VPPAPIGEN: vppapigen replacement in Python PLY. 81/8781/23
authorOle Troan <ot@cisco.com>
Thu, 12 Oct 2017 11:06:35 +0000 (13:06 +0200)
committerNeale Ranns <nranns@cisco.com>
Tue, 23 Jan 2018 13:03:53 +0000 (13:03 +0000)
This is a version of the VPP API generator in Python PLY. It supports
the existing language, and has a plugin architecture for generators.
Currently C and JSON are supported.

Changes:
 - vl_api_version to option version = "major.minor.patch"
 - enum support
 - Added error checking and reporting
 - import support (removed the C pre-processor)
 - services (tying request/reply together)

Version:
 option version = "1.0.0";

Enum:
 enum colours {
   RED,
   BLUE = 50,
 };
 define foo {
  vl_api_colours_t colours;
 };

Services:
 service {
  rpc foo returns foo_reply;
  rpc foo_dump returns stream foo_details;
  rpc want_stats returns want_stats_reply
      events ip4_counters, ip6_counters;
 };

Future planned features:
 - unions
 - bool, text
 - array support (including length)
 - proto3 output plugin
 - Refactor C/C++ generator as a plugin
 - Refactor Java generator as a plugin

Change-Id: Ifa289966c790e1b1a8e2938a91e69331e3a58bdf
Signed-off-by: Ole Troan <ot@cisco.com>
82 files changed:
Makefile
build-data/platforms.mk
build-root/Makefile
extras/rpm/vpp.spec
src/configure.ac
src/examples/sample-plugin/Makefile.am
src/examples/sample-plugin/sample/sample.api
src/plugins/acl/acl.api
src/plugins/dpdk/api/dpdk.api
src/plugins/flowprobe/flowprobe.api
src/plugins/gtpu/gtpu.api
src/plugins/ioam/export-vxlan-gpe/vxlan_gpe_ioam_export.api
src/plugins/ioam/export/ioam_export.api
src/plugins/ioam/ip6/ioam_cache.api
src/plugins/ioam/lib-pot/pot.api
src/plugins/ioam/lib-trace/trace.api
src/plugins/ioam/lib-vxlan-gpe/ioam_vxlan_gpe.api
src/plugins/ioam/udp-ping/udp_ping.api
src/plugins/kubeproxy/kp.api
src/plugins/l2e/l2e.api
src/plugins/lb/lb.api
src/plugins/memif/memif.api
src/plugins/nat/nat.api
src/plugins/pppoe/pppoe.api
src/plugins/stn/stn.api
src/suffix-rules.mk
src/tools/vppapigen/C.py [new file with mode: 0644]
src/tools/vppapigen/JSON.py [new file with mode: 0644]
src/tools/vppapigen/gram.y [deleted file]
src/tools/vppapigen/lex.c [deleted file]
src/tools/vppapigen/lex.h [deleted file]
src/tools/vppapigen/node.c [deleted file]
src/tools/vppapigen/node.h [deleted file]
src/tools/vppapigen/test_vppapigen.py [new file with mode: 0755]
src/tools/vppapigen/vppapigen [new symlink]
src/tools/vppapigen/vppapigen.py [new file with mode: 0755]
src/vlibmemory/memclnt.api
src/vnet/bfd/bfd.api
src/vnet/bier/bier.api
src/vnet/classify/classify.api
src/vnet/cop/cop.api
src/vnet/devices/af_packet/af_packet.api
src/vnet/devices/netmap/netmap.api
src/vnet/devices/tap/tapv2.api
src/vnet/devices/virtio/vhost_user.api
src/vnet/dhcp/dhcp.api
src/vnet/dns/dns.api
src/vnet/ethernet/p2p_ethernet.api
src/vnet/feature/feature.api
src/vnet/fib/fib_types.api [new file with mode: 0644]
src/vnet/flow/flow.api
src/vnet/geneve/geneve.api
src/vnet/gre/gre.api
src/vnet/interface.api
src/vnet/ip/ip.api
src/vnet/ip/punt.api
src/vnet/ipsec-gre/ipsec_gre.api
src/vnet/ipsec/ipsec.api
src/vnet/l2/l2.api
src/vnet/l2tp/l2tp.api
src/vnet/lisp-cp/lisp.api
src/vnet/lisp-cp/one.api
src/vnet/lisp-gpe/lisp_gpe.api
src/vnet/lldp/lldp.api
src/vnet/map/map.api
src/vnet/mpls/mpls.api
src/vnet/pg/pg.api
src/vnet/policer/policer.api
src/vnet/session/session.api
src/vnet/span/span.api
src/vnet/srmpls/sr_mpls.api
src/vnet/srv6/sr.api
src/vnet/tcp/tcp.api
src/vnet/udp/udp.api
src/vnet/unix/tap.api
src/vnet/vxlan-gpe/vxlan_gpe.api
src/vnet/vxlan/vxlan.api
src/vpp-api/java/Makefile.am
src/vpp/api/vpe.api
src/vpp/oam/oam.api
src/vpp/stats/stats.api
src/vppapigen.am

index ec3e92d..06c291b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -58,12 +58,12 @@ endif
 
 # +libganglia1-dev if building the gmond plugin
 
-DEB_DEPENDS  = curl build-essential autoconf automake bison ccache
+DEB_DEPENDS  = curl build-essential autoconf automake ccache
 DEB_DEPENDS += debhelper dkms git libtool libapr1-dev dh-systemd
 DEB_DEPENDS += libconfuse-dev git-review exuberant-ctags cscope pkg-config
 DEB_DEPENDS += lcov chrpath autoconf indent clang-format libnuma-dev
 DEB_DEPENDS += python-all python-dev python-virtualenv python-pip libffi6 check
-DEB_DEPENDS += libboost-all-dev libffi-dev
+DEB_DEPENDS += libboost-all-dev libffi-dev python-ply
 ifeq ($(OS_VERSION_ID),14.04)
        DEB_DEPENDS += openjdk-8-jdk-headless
        DEB_DEPENDS += libssl-dev
@@ -108,8 +108,8 @@ endif
 RPM_DEPENDS += chrpath libffi-devel rpm-build
 
 SUSE_NAME= $(shell grep '^NAME=' /etc/os-release | cut -f2- -d= | sed -e 's/\"//g' | cut -d' ' -f2)
-RPM_SUSE_BUILDTOOLS_DEPS = autoconf automake bison ccache check-devel chrpath
-RPM_SUSE_BUILDTOOLS_DEPS += clang indent libtool make
+RPM_SUSE_BUILDTOOLS_DEPS = autoconf automake ccache check-devel chrpath
+RPM_SUSE_BUILDTOOLS_DEPS += clang indent libtool make python-ply
 
 RPM_SUSE_DEVEL_DEPS = glibc-devel-static java-1_8_0-openjdk-devel libnuma-devel
 RPM_SUSE_DEVEL_DEPS += libopenssl-devel openssl-devel
index 196a674..45bd3a1 100644 (file)
@@ -78,6 +78,10 @@ install-deb: $(patsubst %,%-find-source,$(ROOT_PACKAGES))
        : dev package needs a couple of additions ;                     \
        echo ../$(INSTALL_PREFIX)$(ARCH)/vpp/bin/vppapigen /usr/bin     \
           >> deb/debian/vpp-dev.install ;                              \
+       echo ../$(INSTALL_PREFIX)$(ARCH)/vpp/share/vpp/C.py /usr/share/vpp  \
+          >> deb/debian/vpp-dev.install ;                              \
+       echo ../$(INSTALL_PREFIX)$(ARCH)/vpp/share/vpp/JSON.py /usr/share/vpp \
+          >> deb/debian/vpp-dev.install ;                              \
        echo ../../src/vpp-api/java/jvpp/gen/jvpp_gen.py /usr/bin       \
           >> deb/debian/vpp-dev.install ;                              \
        for i in $$(ls ../src/vpp-api/java/jvpp/gen/jvppgen/*.py); do   \
index af35be4..8154ecd 100644 (file)
@@ -367,7 +367,7 @@ CROSS_TOOLS_$(IS_LINUX) += glibc gcc
 NATIVE_TOOLS = findutils make
 
 # basic tools needed for build system
-NATIVE_TOOLS += git automake autoconf libtool texinfo bison flex tar
+NATIVE_TOOLS += git automake autoconf libtool texinfo tar
 
 # needed to compile gcc
 NATIVE_TOOLS += mpfr gmp mpc
index 8487f06..532b9a2 100644 (file)
@@ -337,6 +337,7 @@ fi
 %{_includedir}/*
 %{python2_sitelib}/jvppgen/*
 /usr/share/doc/vpp/examples/sample-plugin
+/usr/share/vpp
 
 %files plugins
 %defattr(-,bin,bin)
index d28b6c1..949901c 100644 (file)
@@ -304,19 +304,10 @@ AM_COND_IF([ENABLE_MARVELL_PLUGIN],
     ])
 ])
 
-# If cross-compiling, we need external vppapigen and we cannot continue without it
-# For native builds, we just set dependency on vpppaigen binary in top_builddir
-AM_COND_IF([CROSSCOMPILE],
-[
-  AC_PATH_PROG([VPPAPIGEN], [vppapigen], [no])
-  if test "$VPPAPIGEN" = "no"; then
-    AC_MSG_ERROR([Externaly built vppapigen is needed when cross-compiling...])
-  fi
-],[
-  VPPAPIGEN=\$\(top_builddir\)/vppapigen
-])
-AC_SUBST([VPPAPIGEN])
-
+AC_PATH_PROG([VPPAPIGEN], [vppapigen], [no])
+if test "$VPPAPIGEN" = "no"; then
+   VPPAPIGEN=\$\(top_srcdir\)/tools/vppapigen/vppapigen
+fi
 
 ###############################################################################
 # JAVA
index a3a9a8d..5c279c4 100644 (file)
@@ -32,14 +32,12 @@ include sample.am
 
 %.api.h: %.api
        mkdir -p `dirname $@` ; \
-       $(CC) $(CPPFLAGS) -E -P -C -x c $^ \
-       | vppapigen --input - --output $@ --show-name $@
+       vppapigen --input $^ --output $@
 
 %.api.json: %.api
        @echo "  JSON APIGEN  " $@ ;                            \
        mkdir -p `dirname $@` ;                                 \
-       $(CC) $(CPPFLAGS) -E -P -C -x c $^                      \
-       | vppapigen --input - --json $@
+       vppapigen --input $^ JSON --output $@
 
 apidir = $(prefix)/api/plugins
 apiincludedir = ${includedir}/vpp_plugins
index f3604b6..ffee7b1 100644 (file)
@@ -16,7 +16,7 @@
 
 /* Define a simple binary API to control the feature */
 
-vl_api_version 0.1.0
+option version = "0.1.0";
 
 autoreply define sample_macswap_enable_disable {
     /* Client identifier, set from api_main.my_client_index */
index 19f007a..e3166d6 100644 (file)
@@ -19,7 +19,7 @@
     used to control the ACL plugin
 */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /** \brief Get the plugin version
     @param client_index - opaque cookie to identify the sender
index 5ded450..2c20ef4 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /** \brief DPDK interface HQoS pipe profile set request
     @param client_index - opaque cookie to identify the sender
index 5bfe451..5bbe011 100644 (file)
@@ -5,7 +5,7 @@
     used to control the flowprobe plugin
 */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /** \brief Enable / disable per-packet IPFIX recording on an interface
     @param client_index - opaque cookie to identify the sender
index fea4791..f8333ff 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /** \brief Set or delete an GTPU tunnel
     @param client_index - opaque cookie to identify the sender
index 3637ae8..f6a63df 100644 (file)
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /* Define a simple binary API to control the feature */
 
index 47a8cc0..c127bd2 100644 (file)
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /* Define a simple binary API to control the feature */
 
index c953b67..71a048b 100644 (file)
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /*  API to control ioam caching */
 
index d1bfe44..f133748 100644 (file)
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /** \brief Proof of Transit(POT): Set POT profile
     @param id - id of the profile 
index 59d664a..52dc648 100644 (file)
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /** \brief iOAM6 Trace - Set the iOAM6 trace profile
     @param trace_type - Type of trace requested
index dfaecff..0cbdf6d 100644 (file)
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /** \brief iOAM Over VxLAN-GPE - Set iOAM transport for VxLAN-GPE
     @param client_index - opaque cookie to identify the sender
index b5b5f23..72e578c 100644 (file)
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-vl_api_version 2.0.0
+option version = "2.0.0";
 
 /** \brief UDP-Probe Add/Delete request 
     @param src_ip_address - Source ipv4/v6 address for the udp-ping flow
index e8063c1..1eedd9e 100644 (file)
@@ -12,8 +12,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-vl_api_version 1.0.0
+
+option version = "1.0.0";
 
 /** \brief Configure Kube-proxy global parameters
     @param client_index - opaque cookie to identify the sender
index e4e3438..dd2eb16 100644 (file)
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /** \brief L2 emulation at L3
     @param client_index - opaque cookie to identify the sender
index 7f48666..f5036ed 100644 (file)
@@ -1,4 +1,4 @@
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /** \brief Configure Load-Balancer global parameters
     @param client_index - opaque cookie to identify the sender
index 08d056f..cd09b92 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /** \brief Create memory interface
     @param client_index - opaque cookie to identify the sender
index 1de70ed..02c1627 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-vl_api_version 2.3.0
+option version = "2.3.0";
 
 /**
  * @file nat.api
index 78982f3..b687d51 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /** \brief Set or delete an PPPOE session
     @param client_index - opaque cookie to identify the sender
index 07d214d..97731b3 100644 (file)
@@ -19,6 +19,7 @@
  *
  */
 
+option version = "1.0.0";
 
 /** \brief Add/del STN rules
     @param client_index - opaque cookie to identify the sender
index 9115c55..495d828 100644 (file)
 # Please do not set "SUFFIXES = .api.h .api" here
 
 %.api.h: %.api @VPPAPIGEN@
-       @echo "  APIGEN  " $@ ;                                 \
-       mkdir -p `dirname $@` ;                                 \
-       $(CC) $(CPPFLAGS) -E -P -C -x c $<                      \
-       | @VPPAPIGEN@ --input - --output $@ --show-name $@ > /dev/null
+       @echo "  APIGEN  " $@ ;                                              \
+       mkdir -p `dirname $@` ;                                              \
+       @VPPAPIGEN@ --includedir $(top_srcdir) --input $< --output $@
 
-%.api.json: %.api @VPPAPIGEN@
-       @echo "  JSON API" $@ ;                                 \
-       mkdir -p `dirname $@` ;                                 \
-       $(CC) $(CPPFLAGS) -E -P -C -x c $<                      \
-       | @VPPAPIGEN@ --input - --json $@ > /dev/null
+%.api.json: %.api
+       @echo "  JSON API" $@ ;                                              \
+       mkdir -p `dirname $@` ;                                              \
+       @VPPAPIGEN@ --includedir $(top_srcdir) --input $< JSON --output $@
diff --git a/src/tools/vppapigen/C.py b/src/tools/vppapigen/C.py
new file mode 100644 (file)
index 0000000..2a89306
--- /dev/null
@@ -0,0 +1,279 @@
+# C generation
+import datetime
+import os
+
+datestring = datetime.datetime.now()
+input_filename = 'inputfil'
+top_boilerplate = '''\
+/*
+ * VLIB API definitions {datestring}
+ * Input file: {input_filename}
+ * Automatically generated: please edit the input file NOT this file!
+ */
+
+#if defined(vl_msg_id)||defined(vl_union_id) \\
+    || defined(vl_printfun) ||defined(vl_endianfun) \\
+    || defined(vl_api_version)||defined(vl_typedefs) \\
+    || defined(vl_msg_name)||defined(vl_msg_name_crc_list) \\
+    || defined(vl_api_version_tuple)
+/* ok, something was selected */
+#else
+#warning no content included from {input_filename}
+#endif
+
+#define VL_API_PACKED(x) x __attribute__ ((packed))
+'''
+
+bottom_boilerplate = '''\
+/****** API CRC (whole file) *****/
+
+#ifdef vl_api_version
+vl_api_version({input_filename}, {file_crc:#08x})
+
+#endif
+'''
+
+
+def msg_ids(s):
+    output = '''\
+
+/****** Message ID / handler enum ******/
+
+#ifdef vl_msg_id
+'''
+
+    for t in s['defines']:
+        output += "vl_msg_id(VL_API_%s, vl_api_%s_t_handler)\n" % \
+                  (t.name.upper(), t.name)
+    output += "#endif"
+
+    return output
+
+
+def msg_names(s):
+    output = '''\
+
+/****** Message names ******/
+
+#ifdef vl_msg_name
+'''
+
+    for t in s['defines']:
+        dont_trace = 0 if t.dont_trace else 1
+        output += "vl_msg_name(vl_api_%s_t, %d)\n" % (t.name, dont_trace)
+    output += "#endif"
+
+    return output
+
+
+def msg_name_crc_list(s, suffix):
+    output = '''\
+
+/****** Message name, crc list ******/
+
+#ifdef vl_msg_name_crc_list
+'''
+    output += "#define foreach_vl_msg_name_crc_%s " % suffix
+
+    for t in s['defines']:
+        output += "\\\n_(VL_API_%s, %s, %08x) " % \
+                   (t.name.upper(), t.name, t.crc)
+    output += "\n#endif"
+
+    return output
+
+
+def duplicate_wrapper_head(name):
+    s = "#ifndef defined_%s\n" % name
+    s += "#define defined_%s\n" % name
+    return s
+
+
+def duplicate_wrapper_tail():
+    return '#endif\n\n'
+
+
+def typedefs(s, filename):
+    name = filename.replace('.', '_')
+    output = '''\
+
+
+/****** Typedefs ******/
+
+#ifdef vl_typedefs
+#ifndef included_{module}
+#define included_{module}
+'''
+    output = output.format(module=name)
+    for e in s['enums']:
+        output += duplicate_wrapper_head(e.name)
+        output += "typedef enum {\n"
+        for b in e.block:
+            output += "    %s = %s,\n" % (b[0], b[1])
+        output += '} vl_api_%s_t;\n' % e.name
+        output += duplicate_wrapper_tail()
+
+    for t in s['typedefs'] + s['defines']:
+        output += duplicate_wrapper_head(t.name)
+        output += "typedef VL_API_PACKED(struct _vl_api_%s {\n" % t.name
+        for b in t.block:
+            if b.type == 'Field':
+                output += "    %s %s;\n" % (b.fieldtype, b.fieldname)
+            elif b.type == 'Array':
+                if b.lengthfield:
+                    output += "    %s %s[0];\n" % (b.fieldtype, b.fieldname)
+                else:
+                    output += "    %s %s[%s];\n" % (b.fieldtype, b.fieldname,
+                                                    b.length)
+            else:
+                raise ValueError("Error in processing array type %s" % b)
+
+        output += '}) vl_api_%s_t;\n' % t.name
+        output += duplicate_wrapper_tail()
+
+    output += "\n#endif"
+    output += "\n#endif\n\n"
+
+    return output
+
+
+format_strings = {'u8': '%u',
+                  'i8': '%d',
+                  'u16': '%u',
+                  'i16': '%d',
+                  'u32': '%u',
+                  'i32': '%ld',
+                  'u64': '%llu',
+                  'i64': '%llu',
+                  'f64': '%.2f', }
+
+
+def printfun(s):
+    output = '''\
+/****** Print functions *****/
+#ifdef vl_printfun
+
+#ifdef LP64
+#define _uword_fmt \"%lld\"
+#define _uword_cast (long long)
+#else
+#define _uword_fmt \"%ld\"
+#define _uword_cast long
+#endif
+
+'''
+    for t in s['typedefs'] + s['defines']:
+        if t.manual_print:
+            output += "/***** manual: vl_api_%s_t_print  *****/\n\n" % t.name
+            continue
+        output += duplicate_wrapper_head(t.name + '_t_print')
+        output += "static inline void *vl_api_%s_t_print (vl_api_%s_t *a," % \
+                  (t.name, t.name)
+        output += "void *handle)\n{\n"
+        output += "    vl_print(handle, \"vl_api_%s_t:\\n\");\n" % t.name
+
+        for o in t.block:
+            if o.type != 'Field':
+                continue
+            if o.fieldtype in format_strings:
+                output += "    vl_print(handle, \"%s: %s\\n\", a->%s);\n" % \
+                          (o.fieldname, format_strings[o.fieldtype],
+                           o.fieldname)
+
+        output += '    return handle;\n'
+        output += '}\n\n'
+        output += duplicate_wrapper_tail()
+
+    output += "\n#endif /* vl_printfun */\n"
+
+    return output
+
+
+endian_strings = {
+    'u16': 'clib_net_to_host_u16',
+    'u32': 'clib_net_to_host_u32',
+    'u64': 'clib_net_to_host_u64',
+    'i16': 'clib_net_to_host_u16',
+    'i32': 'clib_net_to_host_u32',
+    'i64': 'clib_net_to_host_u64',
+}
+
+
+def endianfun(s):
+    output = '''\
+
+/****** Endian swap functions *****/\n\
+#ifdef vl_endianfun
+
+#undef clib_net_to_host_uword
+#ifdef LP64
+#define clib_net_to_host_uword clib_net_to_host_u64
+#else
+#define clib_net_to_host_uword clib_net_to_host_u32
+#endif
+
+'''
+
+    for t in s['typedefs'] + s['defines']:
+        if t.manual_endian:
+            output += "/***** manual: vl_api_%s_t_endian  *****/\n\n" % t.name
+            continue
+        output += duplicate_wrapper_head(t.name + '_t_endian')
+        output += "static inline void vl_api_%s_t_endian (vl_api_%s_t *a)" % \
+                  (t.name, t.name)
+        output += "\n{\n"
+
+        for o in t.block:
+            if o.type != 'Field':
+                continue
+            if o.fieldtype in endian_strings:
+                output += "    a->%s = %s(a->%s);\n" % \
+                        (o.fieldname, endian_strings[o.fieldtype], o.fieldname)
+            else:
+                output += "    /* a->%s = a->%s (no-op) */\n" % \
+                                          (o.fieldname, o.fieldname)
+
+        output += '}\n\n'
+        output += duplicate_wrapper_tail()
+    output += "\n#endif /* vl_endianfun */\n\n"
+
+    return output
+
+
+def version_tuple(s, module):
+    output = '''\
+/****** Version tuple *****/
+
+#ifdef vl_api_version_tuple
+
+'''
+    if 'version' in s['options']:
+        v = s['options']['version']
+        (major, minor, patch) = v.split('.')
+        output += "vl_api_version_tuple(%s, %s, %s, %s)\n" % \
+                  (module, major, minor, patch)
+
+    output += "\n#endif /* vl_api_version_tuple */\n\n"
+
+    return output
+
+
+#
+# Plugin entry point
+#
+def run(input_filename, s, file_crc):
+    basename = os.path.basename(input_filename)
+    filename, file_extension = os.path.splitext(basename)
+    output = top_boilerplate.format(datestring=datestring,
+                                    input_filename=basename)
+    output += msg_ids(s)
+    output += msg_names(s)
+    output += msg_name_crc_list(s, filename)
+    output += typedefs(s, filename + file_extension)
+    output += printfun(s)
+    output += endianfun(s)
+    output += version_tuple(s, basename)
+    output += bottom_boilerplate.format(input_filename=basename,
+                                        file_crc=file_crc)
+
+    return output
diff --git a/src/tools/vppapigen/JSON.py b/src/tools/vppapigen/JSON.py
new file mode 100644 (file)
index 0000000..d1f47eb
--- /dev/null
@@ -0,0 +1,66 @@
+# JSON generation
+import json
+
+
+def walk_enums(s):
+    r = []
+    for e in s:
+        d = []
+        d.append(e.name)
+        for b in e.block:
+            d.append(b)
+        d.append({'enumtype': e.enumtype})
+        r.append(d)
+    return r
+
+
+def walk_services(s):
+    r = []
+    for e in s:
+        d = {'reply': e.reply}
+        if e.stream:
+            d['stream'] = True
+        if e.events:
+            d['events'] = e.events
+        r.append({e.caller: d})
+    return r
+
+
+def walk_defs(s):
+    r = []
+    for t in s:
+        d = []
+        d.append(t.name)
+        for b in t.block:
+            f = []
+            if b.type == 'Field':
+                f = [b.fieldtype, b.fieldname]
+            elif b.type == 'Array':
+                if b.lengthfield:
+                    f = [b.fieldtype, b.fieldname, b.length, b.lengthfield]
+                else:
+                    f = [b.fieldtype, b.fieldname, b.length]
+            else:
+                raise ValueError("Error in processing array type %s" % b)
+            d.append(f)
+        if t.crc:
+            c = {}
+            c['crc'] = "{0:#0{1}x}".format(t.crc, 10)
+            d.append(c)
+
+        r.append(d)
+    return r
+
+
+#
+# Plugin entry point
+#
+def run(filename, s, file_crc):
+    j = {}
+
+    j['types'] = walk_defs(s['typedefs'])
+    j['messages'] = walk_defs(s['defines'])
+    j['enums'] = walk_enums(s['enums'])
+    j['services'] = walk_services(s['services'])
+    j['vl_api_version'] = hex(file_crc)
+    return json.dumps(j, indent=4, separators=(',', ': '))
diff --git a/src/tools/vppapigen/gram.y b/src/tools/vppapigen/gram.y
deleted file mode 100644 (file)
index 5c5d46f..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-%{
-/*
- * gram.y - message definition language
- *
- * Copyright (c) 2009 Cisco and/or its affiliates.
- * 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.
- */
-
-extern void yyerror (char *s);
-extern int yylex (void);
-    
-#define YYSTYPE void *
-    
-void generate (YYSTYPE);
- YYSTYPE add_slist(YYSTYPE, YYSTYPE);
- YYSTYPE add_define(YYSTYPE, YYSTYPE);
- YYSTYPE suppress_version(void);
- YYSTYPE add_defbody(YYSTYPE, YYSTYPE);
- YYSTYPE add_primtype(YYSTYPE, YYSTYPE, YYSTYPE);
- YYSTYPE add_complex(YYSTYPE, YYSTYPE);
- YYSTYPE add_union(YYSTYPE, YYSTYPE);
- YYSTYPE add_scalar_vbl(YYSTYPE);
- YYSTYPE add_vector_vbl(YYSTYPE, YYSTYPE);
- YYSTYPE add_variable_length_vector_vbl(YYSTYPE, YYSTYPE);
- YYSTYPE set_flags(YYSTYPE, YYSTYPE);
- YYSTYPE add_version(YYSTYPE, YYSTYPE, YYSTYPE);
-%}
-
-%token NAME RPAR LPAR SEMI LBRACK RBRACK NUMBER PRIMTYPE BARF
-%token TPACKED DEFINE LCURLY RCURLY STRING UNION
-%token HELPER_STRING COMMA DOT VL_API_VERSION
-%token NOVERSION MANUAL_PRINT MANUAL_ENDIAN TYPEONLY DONT_TRACE AUTOREPLY
-
-%%
-
-pgm:     slist                 {generate ($1);}
-          ;
-
-slist:   slist stmt            {$$ = add_slist ($1, $2);}
-        | stmt                  {$$ = $1;}
-          ;
-
-stmt:     flist defn            {$$ = set_flags($1, $2);}
-        | defn                  {$$ = $1;}
-        | api_version           {$$ = $1;}
-          ;
-
-flist:    flist flag            {$$ = (YYSTYPE)(unsigned long)
-                                     ((unsigned long) $1 
-                                    | (unsigned long) $2);}
-        | flag                  {$$ = $1;}
-          ;
-
-flag:   
-          MANUAL_PRINT          {$$ = $1;}
-        | MANUAL_ENDIAN         {$$ = $1;}
-        | DONT_TRACE            {$$ = $1;}
-        | TYPEONLY              {$$ = $1;}
-        | AUTOREPLY             {$$ = $1;}
-          ;
-
-defn:     DEFINE NAME LCURLY defbody RCURLY SEMI 
-                                {$$ = add_define($2, $4);}
-
-        | NOVERSION SEMI
-                                {$$ = suppress_version();}
-          ;
-
-defbody:  defbody onedef        {$$ = add_defbody($1, $2);}
-        | onedef                {$$ = $1;}
-          ;
-
-onedef:   PRIMTYPE vbl SEMI      {$$ = add_primtype($1, $2, 0);}
-        | TPACKED PRIMTYPE vbl SEMI {$$ = add_primtype($1, $2, $3);}
-        | NAME vbl SEMI          {$$ = add_complex($1, $2);}
-        | UNION NAME LCURLY defbody RCURLY SEMI 
-                                 {$$ = add_union($2, $4);}
-          ;
-
-vbl:      NAME                      {$$ = add_scalar_vbl($1);}
-        | NAME LBRACK NUMBER RBRACK {$$ = add_vector_vbl($1, $3);}
-        | NAME LBRACK NAME RBRACK {$$ = add_variable_length_vector_vbl($1, $3);}
-          ;
-
-api_version:  VL_API_VERSION NUMBER DOT NUMBER DOT NUMBER 
-                                    {$$ = add_version ($2, $4, $6);}
diff --git a/src/tools/vppapigen/lex.c b/src/tools/vppapigen/lex.c
deleted file mode 100644 (file)
index d9f82c2..0000000
+++ /dev/null
@@ -1,1129 +0,0 @@
-/* 
- *------------------------------------------------------------------
- * lex.c - API generator lexical analyzer
- *
- * Copyright (c) 1996-2009 Cisco and/or its affiliates.
- * 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.
- *------------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <ctype.h>
-#include <time.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdlib.h>
-
-#include "lex.h"
-#include "node.h"
-#include "tools/vppapigen/gram.h"
-#include <vppinfra/clib.h>
-#include <vppinfra/fifo.h>
-#include <vppinfra/format.h>
-
-FILE *ifp, *ofp, *pythonfp, *jsonfp;
-char *vlib_app_name = "vpp";
-int dump_tree;
-time_t starttime;
-char *input_filename;
-char *current_filename;
-int current_filename_allocated;
-unsigned long input_crc;
-unsigned long message_crc;
-int yydebug;
-char *push_input_fifo;
-char saved_ungetc_char;
-char have_ungetc_char;
-
-/*
- * lexer variable definitions 
- */
-
-static const char *version = "0.1";
-static int the_lexer_linenumber = 1;
-static enum lex_state the_lexer_state = START_STATE;
-
-/*
- * private prototypes
- */
-static void usage (char *);
-static int name_check (const char *, YYSTYPE *);
-static int name_compare (const char *, const char *);
-extern int yydebug;
-extern YYSTYPE yylval;
-
-unsigned int crc32c_table[256] = { 
-  0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,  
-  0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,  
-  0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,  
-  0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,  
-  0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,  
-  0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,  
-  0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,  
-  0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,  
-  0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,  
-  0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,  
-  0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,  
-  0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,  
-  0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,  
-  0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,  
-  0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,  
-  0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,  
-  0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,  
-  0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,  
-  0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,  
-  0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,  
-  0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,  
-  0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,  
-  0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,  
-  0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,  
-  0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,  
-  0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,  
-  0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,  
-  0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,  
-  0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,  
-  0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,  
-  0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,  
-  0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,  
-  0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,  
-  0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,  
-  0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,  
-  0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,  
-  0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,  
-  0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,  
-  0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,  
-  0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,  
-  0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,  
-  0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,  
-  0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,  
-  0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,  
-  0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,  
-  0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,  
-  0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,  
-  0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,  
-  0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,  
-  0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,  
-  0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,  
-  0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,  
-  0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,  
-  0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,  
-  0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,  
-  0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,  
-  0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,  
-  0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,  
-  0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,  
-  0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,  
-  0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,  
-  0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,  
-  0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,  
-  0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351  
-}; 
-
-static inline unsigned long CRC8 (unsigned long crc,
-                                  unsigned char d)
-{
-    return ((crc >> 8) ^ crc32c_table[(crc ^ d) & 0xFF]);
-}
-static inline unsigned long CRC16 (unsigned long crc,
-                                   unsigned short d)
-{
-    crc = CRC8 (crc, d & 0xff);
-    d = d >> 8;
-    crc = CRC8 (crc, d & 0xff);
-    return crc;
-}
-
-
-static unsigned long
-crc_eliding_c_comments (const char *buf, unsigned long crc)
-{
-    const char *p;
-    enum { cOTHER,              /*  */
-           cSTRING,             /* "...    */
-           cSBACKSLASH,         /* "...\   */
-           cCHAR,               /* '...    */
-           cCBACKSLASH,         /* '...\   */
-           cSLASH,              /* /       */
-           cSLASH_SLASH,        /* //...   */
-           cSLASH_STAR,         /* / *...  */
-           cSTAR                /* / *...* */
-    } ss = cOTHER;
-
-    for (p = buf; ;) {
-        unsigned char c = *p++;
-
-        switch (c) {
-        case 0:
-            switch (ss) {
-            case cOTHER:
-                return (crc);
-            case cSTRING: case cSBACKSLASH:
-            case cCHAR: case cCBACKSLASH:
-            case cSLASH: case cSLASH_SLASH: case cSLASH_STAR: case cSTAR:
-                fprintf (stderr, "Inopportune EOF: %s\n", buf);
-                exit (1);
-            }
-            break;
-        case '\"':
-            switch (ss) {
-            case cOTHER: ss = cSTRING; break; /* start string */
-            case cSTRING: ss = cOTHER; break; /* end string */
-            case cSBACKSLASH: ss = cSTRING; break;
-            case cCHAR: break;
-            case cCBACKSLASH: ss = cCHAR; break;
-            case cSLASH: crc = CRC8 (crc, '/'); ss = cOTHER; break;
-            case cSLASH_SLASH: continue; /* in comment */
-            case cSLASH_STAR: continue; /* in comment */
-            case cSTAR: ss = cSLASH_STAR; continue; /* in comment */
-            }
-            break;
-        case '\\':
-            switch (ss) {
-            case cOTHER: break;
-            case cSTRING: ss = cSBACKSLASH; break;
-            case cSBACKSLASH: ss = cSTRING; break;
-            case cCHAR: ss = cCBACKSLASH; break;
-            case cCBACKSLASH: ss = cCHAR; break;
-            case cSLASH: crc = CRC8 (crc, '/'); ; ss = cOTHER; break;
-            case cSLASH_SLASH: continue; /* in comment */
-            case cSLASH_STAR: continue; /* in comment */
-            case cSTAR: ss = cSLASH_STAR; continue; /* in comment */
-            }
-            break;
-        case '/':
-            switch (ss) {
-            case cOTHER: ss = cSLASH; continue; /* potential comment */
-            case cSTRING: break;
-            case cSBACKSLASH: ss = cSTRING; break;
-            case cCHAR: break;
-            case cCBACKSLASH: ss = cCHAR; break;
-            case cSLASH: ss = cSLASH_SLASH; continue; /* start comment */
-            case cSLASH_SLASH: continue; /* in comment */
-            case cSLASH_STAR: continue; /* in comment */
-            case cSTAR: ss = cOTHER; continue; /* end of comment */
-            }
-            break;
-        case '*':
-            switch (ss) {
-            case cOTHER: break;
-            case cSTRING: break;
-            case cSBACKSLASH: ss = cSTRING; break;
-            case cCHAR: break;
-            case cCBACKSLASH: ss = cCHAR; break;
-            case cSLASH: ss = cSLASH_STAR; continue; /* start comment */
-            case cSLASH_SLASH: continue; /* in comment */
-            case cSLASH_STAR: ss = cSTAR; continue; /* potential end */
-            case cSTAR: continue; /* still potential end of comment */
-            }
-            break;
-        case '\n': case '\r': case ' ': case '\t': case '\014':
-            switch (ss) {
-            case cOTHER: continue; /* ignore all whitespace */
-            case cSTRING: break;
-            case cSBACKSLASH: ss = cSTRING; break;
-            case cCHAR: break;
-            case cCBACKSLASH: ss = cCHAR; break;
-            case cSLASH: c = '/'; ss = cOTHER; break;
-            case cSLASH_SLASH:
-                if (c == '\n' || c == '\r') ss = cOTHER; /* end comment */
-                continue;
-            case cSLASH_STAR: continue; /* in comment */
-            case cSTAR: ss = cSLASH_STAR; continue; /* in comment */
-            }
-        default:
-            switch (ss) {
-            case cOTHER: break;
-            case cSTRING: break;
-            case cSBACKSLASH: ss = cSTRING; break;
-            case cCHAR: break;
-            case cCBACKSLASH: ss = cCHAR; break;
-            case cSLASH: crc = CRC8 (crc, '/'); ss = cOTHER; break;
-            case cSLASH_SLASH: continue; /* in comment */
-            case cSLASH_STAR: continue; /* in comment */
-            case cSTAR: ss = cSLASH_STAR; continue; /* in comment */
-            }
-        }
-        crc = CRC8 (crc, c);
-    }
-}
-
-/*
- * main 
- */
-int main (int argc, char **argv)
-{
-    int curarg = 1;
-    char *ofile=0;
-    char *pythonfile=0;
-    char *jsonfile=0;
-    char *show_name=0;
-
-    while (curarg < argc) {
-        if (!strncmp (argv [curarg], "--verbose", 3)) {
-            fprintf (stderr, "%s version %s\n", argv [0], version);
-            curarg++;
-            continue;
-        }
-        
-        if (!strncmp (argv [curarg], "--yydebug", 3)) {
-            yydebug = 1;
-            curarg++;
-            continue;
-        }
-        
-        if (!strncmp (argv [curarg], "--dump", 3)) {
-            dump_tree = 1;
-            curarg++;
-            continue;
-        }
-        
-        if (!strncmp (argv[curarg], "--show-name", 3)) {
-            curarg++;
-            if (curarg < argc) {
-                show_name = argv[curarg];
-                curarg++;
-                continue;
-            } else {
-                fprintf(stderr, "Missing filename after --show-name \n");
-                exit(1);
-            }
-        }
-
-        if (!strncmp (argv [curarg], "--input", 3)) {
-            curarg++;
-            if (curarg < argc) {
-                input_filename = argv[curarg];
-                if (!strcmp (argv [curarg], "-"))
-                    ifp = stdin;
-                else
-                    ifp = fopen (argv [curarg], "r");
-                if (ifp == NULL) {
-                    fprintf (stderr, "Couldn't open input file %s\n", 
-                             argv[curarg]);
-                    exit (1);
-                }
-                curarg++;
-            } else {
-                fprintf(stderr, "Missing filename after --input\n");
-                exit(1);
-            }
-            continue;
-        }
-        if (!strncmp (argv [curarg], "--output", 3)) {
-            curarg++;
-            if (curarg < argc) {
-                ofp = fopen (argv[curarg], "w");
-                if (ofp == NULL) {
-                    fprintf (stderr, "Couldn't open output file %s\n", 
-                         argv[curarg]);
-                    exit (1);
-                }
-                ofile = argv[curarg];
-                curarg++;
-            } else {
-                fprintf(stderr, "Missing filename after --output\n");
-                exit(1);
-            }
-            continue;
-        }
-        if (!strncmp (argv [curarg], "--python", 8)) {
-            curarg++;
-            if (curarg < argc) {
-               if (!strcmp(argv[curarg], "-")) {
-                   pythonfp = stdout;
-               } else {
-                   pythonfp = fopen(argv[curarg], "w");
-                   pythonfile = argv[curarg];
-               }
-                if (pythonfp == NULL) {
-                    fprintf (stderr, "Couldn't open python output file %s\n",
-                         argv[curarg]);
-                    exit (1);
-                }
-                curarg++;
-            } else {
-                fprintf(stderr, "Missing filename after --python\n");
-                exit(1);
-            }
-            continue;
-        }
-        if (!strncmp (argv [curarg], "--json", 6)) {
-            curarg++;
-            if (curarg < argc) {
-               if (!strcmp(argv[curarg], "-")) {
-                   jsonfp = stdout;
-               } else {
-                   jsonfp = fopen(argv[curarg], "w");
-                   jsonfile = argv[curarg];
-               }
-                if (jsonfp == NULL) {
-                    fprintf (stderr, "Couldn't open JSON output file %s\n",
-                         argv[curarg]);
-                    exit (1);
-                }
-                curarg++;
-            } else {
-                fprintf(stderr, "Missing filename after --json\n");
-                exit(1);
-            }
-            continue;
-        }
-        if (!strncmp (argv [curarg], "--app", 4)) {
-            curarg++;
-            if (curarg < argc) {
-                vlib_app_name = argv[curarg];
-                curarg++;
-            } else {
-                fprintf(stderr, "Missing app name after --app\n");
-                exit(1);
-            }
-            continue;
-        }
-
-        usage(argv[0]);
-        exit (1);
-    }
-    if (ofp == NULL) {
-        ofile = 0;
-    }
-    if (pythonfp == NULL) {
-        pythonfile = 0;
-    }
-    if (jsonfp == NULL) {
-        jsonfile = 0;
-    }
-    if (ifp == NULL) {
-        fprintf(stderr, "No input file specified...\n");
-        exit(1);
-    }
-    if (show_name) {
-        input_filename = show_name;
-    }
-
-    starttime = time (0);
-
-    if (yyparse() == 0) {
-        fclose (ifp);
-        curarg -= 2;
-        if (ofile) {
-            printf ("Output written to %s\n", ofile);
-            fclose (ofp);
-        }
-        if (pythonfile) {
-            printf ("Python bindings written to %s\n", pythonfile);
-            fclose (pythonfp);
-        }
-        if (jsonfile) {
-            printf ("JSON bindings written to %s\n", jsonfile);
-            fclose (jsonfp);
-        }
-    }
-    else {
-        fclose (ifp);
-        if (ofp)
-            fclose (ofp);
-        if (ofile) {
-            printf ("Removing %s\n", ofile);
-            unlink (ofile);
-        }
-        if (pythonfile) {
-            printf ("Removing %s\n", pythonfile);
-            unlink (pythonfile);
-        }
-        if (jsonfile) {
-            printf ("Removing %s\n", jsonfile);
-            unlink (jsonfile);
-        }
-        exit (1);
-    }
-    exit (0);
-}
-
-/*
- * usage
- */
-static void usage (char *progname)
-{
-    fprintf (stderr, 
-             "usage: %s --input <filename> [--output <filename>] "
-            "[--json <filename>] [--python <filename>]\n%s",
-             progname,
-             "          [--yydebug] [--dump-tree]\n");
-    exit (1);
-}
-
-/*
- * yyerror 
- */
-void yyerror (char *s)
-{
-    fprintf (stderr, "%s:%d %s\n", current_filename, the_lexer_linenumber, s);
-}
-
-static char namebuf [MAXNAME];
-
-static inline char
-getc_char (FILE *ifp)
-{
-    char rv;
-
-    if (have_ungetc_char) {
-        have_ungetc_char = 0;
-        return saved_ungetc_char;
-    }
-        
-    if (clib_fifo_elts (push_input_fifo)) {
-        clib_fifo_sub1(push_input_fifo, rv);
-        return (rv & 0x7f);
-    }
-    return ((char)(getc(ifp) & 0x7f));
-}
-
-u32 fe (char *fifo)
-{
-    return clib_fifo_elts (fifo);
-}
-
-static inline void
-ungetc_char (char c, FILE *ifp)
-{
-    saved_ungetc_char = c;
-    have_ungetc_char = 1;
-}
-
-void autoreply (void *np_arg)
-{
-    static u8 *s;
-    node_t *np = (node_t *)np_arg;
-    int i;
-
-    vec_reset_length (s);
-
-    s = format (0, " define %s_reply\n", (char *)(np->data[0]));
-    s = format (s, "{\n");
-    s = format (s, "    u32 context;\n");
-    s = format (s, "    i32 retval;\n");
-    s = format (s, "};\n");
-
-    for (i = 0; i < vec_len (s); i++)
-        clib_fifo_add1 (push_input_fifo, s[i]);
-}
-
-/*
- * yylex (well, yylex_1: The real yylex below does crc-hackery)
- */
-static int yylex_1 (void)
-{
-    int nameidx=0;
-    char c;
-    enum { LP_INITIAL_WHITESPACE, LP_LINE_NUMBER,
-          LP_PRE_FILENAME_WHITESPACE, LP_FILENAME,
-          LP_POST_FILENAME,
-          LP_OTHER
-    } lp_substate = LP_INITIAL_WHITESPACE;
-
- again:
-    switch (the_lexer_state) {
-        /*
-         * START state -- looking for something interesting 
-         */
-    case START_STATE:
-        c = getc_char (ifp);
-        if (feof (ifp))
-            return (EOF);
-
-        switch (c) {
-        case '\n':
-            the_lexer_linenumber++;
-            goto again;
-
-        case '#':
-            the_lexer_state = LINE_PRAGMA_STATE;
-            lp_substate = LP_INITIAL_WHITESPACE;
-            goto again;
-
-            /* FALLTHROUGH */
-        case '\t':
-        case ' ':
-            goto again;
-            
-        case '(':
-            return (LPAR);
-
-        case ')':
-            return (RPAR);
-
-        case ';':
-            return (SEMI);
-
-        case '[':
-            return (LBRACK);
-            
-        case ']':
-            return (RBRACK);
-
-        case '{':
-            return (LCURLY);
-            
-        case '}':
-            return (RCURLY);
-
-        case ',':
-            return (COMMA);
-
-        case '.':
-            return (DOT);
-
-        case '"':
-            nameidx = 0;
-            the_lexer_state = STRING_STATE;
-            goto again;
-
-        case '@':
-            nameidx = 0;
-            the_lexer_state = HELPER_STATE;
-            goto again;
-
-        case '/':
-            c = getc_char (ifp);
-            if (feof (ifp))
-                return (EOF);
-
-            if (c == '/') {
-                the_lexer_state = CPP_COMMENT_STATE;
-                goto again;
-            } else if (c == '*') {
-                the_lexer_state = C_COMMENT_STATE;
-                goto again;
-            } else {
-                fprintf (stderr, "unknown token /%c at line %d\n",
-                         c, the_lexer_linenumber);
-                return (BARF);
-            }
-
-        case '\\':
-            c = getc_char (ifp);
-            if (feof (ifp))
-                return (EOF);
-            
-            /* Note fallthrough... */
-
-        default:
-            if (isalpha (c) || c == '_') {
-                namebuf [0] = c;
-                nameidx = 1;
-                the_lexer_state = NAME_STATE;
-                goto again;
-            } else if (isdigit(c)) {
-                namebuf [0] = c;
-                nameidx = 1;
-                the_lexer_state = NUMBER_STATE;
-                goto again;
-            }
-
-            fprintf (stderr, "unknown token %c at line %d\n",
-                     c, the_lexer_linenumber);
-            return (BARF);
-        }
-
-        /*
-         * NAME state -- eat the rest of a name 
-         */
-    case NAME_STATE:
-        c = getc_char (ifp);
-        if (feof (ifp))
-            return (EOF);
-        
-        if (!isalnum (c) && c != '_') {
-            ungetc_char (c, ifp);
-            namebuf [nameidx] = 0;
-            the_lexer_state = START_STATE;
-            return (name_check (namebuf, &yylval));
-        }                
-        if (nameidx >= (MAXNAME-1)) {
-            fprintf(stderr, "lex input buffer overflow...\n");
-            exit(1);
-        }
-        namebuf [nameidx++] = c;
-        goto again;
-        
-        /*
-         * NUMBER state -- eat the rest of a number
-         */
-    case NUMBER_STATE:
-        c = getc_char (ifp);
-        if (feof (ifp))
-            return (EOF);
-        
-        if (!isdigit (c)) {
-            ungetc_char (c, ifp);
-            namebuf [nameidx] = 0;
-            the_lexer_state = START_STATE;
-            yylval = (void *) atol(namebuf);
-            return (NUMBER);
-        }                
-        if (nameidx >= (MAXNAME-1)) {
-            fprintf(stderr, "lex input buffer overflow...\n");
-            exit(1);
-        }
-        namebuf [nameidx++] = c;
-        goto again;
-
-        /*
-         * C_COMMENT state -- eat a peach
-         */
-    case C_COMMENT_STATE:
-        c = getc_char (ifp);
-        if (feof (ifp))
-            return (EOF);
-        if (c == '*') {
-            c = getc_char (ifp);
-            if (feof (ifp))
-                return (EOF);
-            if (c == '/') {
-                the_lexer_state = START_STATE;
-                goto again;
-            }
-        }
-        if (c == '\n')
-            the_lexer_linenumber++;
-        goto again;
-            
-        /*
-         * CPP_COMMENT state -- eat a plum 
-         */
-
-    case CPP_COMMENT_STATE:
-        c = getc_char (ifp);
-        if (feof (ifp))
-            return (EOF);
-        if (c == '\n') {
-            the_lexer_linenumber++;
-            the_lexer_state = START_STATE;
-            goto again;
-        }
-        goto again;
-
-    case STRING_STATE:
-        c = getc_char (ifp);
-        if (feof (ifp))
-            return (EOF);
-        switch (c) {
-        case '\\':
-            c = getc_char (ifp);
-            if (feof (ifp))
-                return (EOF);
-            namebuf[nameidx++] = c;
-            goto again;
-
-        case '"':
-            namebuf[nameidx] = 0;
-            yylval = (YYSTYPE) sxerox (namebuf);
-            the_lexer_state = START_STATE;
-            return (STRING);
-
-        default:
-            if (c == '\n')
-                the_lexer_linenumber++;
-
-            if (nameidx >= (MAXNAME-1)) {
-                fprintf(stderr, "lex input buffer overflow...\n");
-                exit(1);
-            }
-            namebuf[nameidx++] = c;
-            goto again;
-        }
-        break;
-
-    case HELPER_STATE:
-        c = getc_char (ifp);
-        if (feof (ifp))
-            return (EOF);
-        switch (c) {
-        case '\\':
-            c = getc_char (ifp);
-            if (feof (ifp))
-                return (EOF);
-            namebuf[nameidx] = c;
-            goto again;
-
-        case '@':
-            namebuf[nameidx] = 0;
-            yylval = (YYSTYPE) sxerox (namebuf);
-            the_lexer_state = START_STATE;
-            return (HELPER_STRING);
-
-        default:
-            if (c == '\n')
-                the_lexer_linenumber++;
-
-            /*
-             * CPP makes it approximately impossible to 
-             * type "#define FOO 123", so we provide a 
-             * lexical trick to achieve that result 
-             */
-
-            if (c == '$')
-                c = '#';
-
-            if (nameidx >= (MAXNAME-1)) {
-                fprintf(stderr, "lex input buffer overflow...\n");
-                exit(1);
-            }
-            namebuf[nameidx++] = c;
-            goto again;
-        }
-        break;
-
-    case LINE_PRAGMA_STATE:
-       /* We're only interested in lines of the form # 259 "foo.c" 17 */
-
-        switch (lp_substate) {
-
-        case LP_INITIAL_WHITESPACE: /* no number seen yet */
-            c = getc_char(ifp);
-            if (feof(ifp))
-                return(EOF);
-            if (c >= '0' && c <= '9') {
-                namebuf[nameidx++] = c;
-                lp_substate = LP_LINE_NUMBER;
-            } else if (c == '\n') {
-               goto lp_end_of_line;
-           } else if (c != ' ' && c != '\t') {
-               /* Nothing */
-           } else {
-               lp_substate = LP_OTHER;
-           }
-           goto again;
-
-        case LP_LINE_NUMBER:   /* eating linenumber */
-            c = getc_char(ifp);
-            if (feof(ifp))
-                return(EOF);
-            if (c >= '0' && c <= '9') {
-                namebuf[nameidx++] = c;
-           } else if (c == ' ' || c == '\t') {
-                namebuf[nameidx++] = 0;
-                the_lexer_linenumber = atol(namebuf);
-                lp_substate = LP_PRE_FILENAME_WHITESPACE;
-            } else if (c == '\n') {
-               goto lp_end_of_line;
-            } else {
-               lp_substate = LP_OTHER;
-           }
-            goto again;
-
-        case LP_PRE_FILENAME_WHITESPACE: /* awaiting filename */
-            c = getc_char(ifp);
-            if (feof(ifp))
-                return(EOF);
-            
-            if (c == '"') {
-                lp_substate = LP_FILENAME;
-                nameidx = 0;
-            } else if (c == ' ' || c == '\t') {
-               /* nothing */
-           } else if (c == '\n') {
-               goto lp_end_of_line;
-           } else {
-               lp_substate = LP_OTHER;
-           }
-            goto again;
-
-        case LP_FILENAME:      /* eating filename */
-            c = getc_char(ifp);
-            if (feof(ifp))
-                return(EOF);
-
-            if (c == '"') {
-                lp_substate = LP_POST_FILENAME;
-                namebuf[nameidx] = 0;
-            } else if (c == '\n') {
-               goto lp_end_of_line; /* syntax error... */
-           } else {
-                namebuf[nameidx++] = c;
-            }
-            goto again;
-
-        case LP_POST_FILENAME: /* ignoring rest of line */
-        case LP_OTHER:
-            c = getc_char(ifp);
-            if (feof(ifp))
-                return(EOF);
-
-            if (c == '\n') {
-               if (lp_substate == LP_POST_FILENAME) {
-                   if (current_filename_allocated) {
-                       current_filename_allocated = 0;
-                       free(current_filename);
-                   }
-
-                   if (!strcmp(namebuf, "<stdin>")) {
-                       current_filename = input_filename;
-                   } else {
-                       current_filename = sxerox(namebuf);
-                       current_filename_allocated = 1;
-                   }
-               }
-           lp_end_of_line:
-                the_lexer_state = START_STATE;
-                nameidx = 0;
-            }
-            goto again;
-        }
-        break;
-    }
-    fprintf (stderr, "LEXER BUG!\n");
-    exit (1);
-    /* NOTREACHED */
-    return (0);
-}
-
-/*
- * Parse a token and side-effect input_crc
- * in a whitespace- and comment-insensitive fashion.
- */
-int yylex (void)
-{
-    /*
-     * Accumulate a crc32-based signature while processing the
-     * input file.  The goal is to come up with a magic number
-     * which changes precisely when the original input file changes
-     * but which ignores whitespace changes.
-     */
-    unsigned long crc = input_crc;
-    int node_type = yylex_1 ();
-    unsigned long crc2 = message_crc;
-    int use_helper_string = 0;
-    unsigned short code;
-
-    switch (node_type) {
-    case PRIMTYPE:
-    case NAME:
-    case NUMBER:
-    case STRING:
-    case HELPER_STRING: 
-        use_helper_string = 1;
-        break;
-
-     /* Other node types have no "substate" */
-     /* This code is written in this curious fashion because we
-      * want the generated CRC to be independent of the particular
-      * values a particular version of lex/bison assigned to various states.
-      */
-
-    case RPAR:               code = 258; break;
-    case LPAR:               code = 259; break;
-    case SEMI:               code = 260; break;
-    case LBRACK:             code = 261; break;
-    case RBRACK:             code = 262; break;
-    case BARF:               code = 265; break;
-    case TPACKED:            code = 266; break;
-    case DEFINE:             code = 267; break;
-    case LCURLY:             code = 268; break;
-    case RCURLY:             code = 269; break;
-    case UNION:              code = 271; break;
-    case COMMA:              code = 273; break;
-    case NOVERSION:          code = 274; break;
-    case MANUAL_PRINT:       code = 275; break;
-    case MANUAL_ENDIAN:      code = 276; break;
-    case TYPEONLY:           code = 278; break;
-    case DONT_TRACE:         code = 279; break;
-    case AUTOREPLY:          code = 280; break;
-    case DOT:                code = 281; break;
-    case VL_API_VERSION:     code = 282; break;
-        
-    case EOF: code = ~0; break; /* hysterical compatibility */
-
-    default:
-        fprintf(stderr, "yylex: node_type %d missing state CRC cookie\n",
-                node_type);
-        exit(1);
-    }
-
-    if (use_helper_string)
-    {
-        /* We know these types accumulated token text into namebuf */
-        /* HELPER_STRING may still contain C comments.  Argh. */
-        crc = crc_eliding_c_comments (namebuf, crc);
-        crc2 = crc_eliding_c_comments (namebuf, crc2);
-    } else
-    {
-        crc = CRC16 (crc, code);
-        crc2 = CRC16 (crc2, code);
-    }
-
-    input_crc = crc;
-    message_crc = crc2;
-    return (node_type);
-}
-
-/*
- * name_check -- see if the name we just ate
- * matches a known keyword.  If so, set yylval
- * to a new instance of <subclass of node>, and return PARSER_MACRO
- *
- * Otherwise, set yylval to sxerox (s) and return NAME
- */
-
-static struct keytab {
-    char *name;
-    enum node_subclass subclass_id;
-} keytab [] = 
-/* Keep the table sorted, binary search used below! */
-{
-    {"autoreply",       NODE_AUTOREPLY},
-    {"define",          NODE_DEFINE},  
-    {"dont_trace",      NODE_DONT_TRACE},
-    {"f64",             NODE_F64},
-    {"i16",             NODE_I16},
-    {"i32",             NODE_I32},
-    {"i64",             NODE_I64},
-    {"i8",              NODE_I8},
-    {"manual_endian",   NODE_MANUAL_ENDIAN},
-    {"manual_print",    NODE_MANUAL_PRINT},
-    {"noversion",       NODE_NOVERSION},
-    {"packed",          NODE_PACKED},
-    {"typeonly",        NODE_TYPEONLY},
-    {"u16",            NODE_U16},
-    {"u32",            NODE_U32},
-    {"u64",             NODE_U64},
-    {"u8",             NODE_U8},
-    {"union",           NODE_UNION},
-    {"uword",           NODE_UWORD},
-    {"vl_api_version",         NODE_VERSION},
-};
-static int name_check (const char *s, YYSTYPE *token_value)
-{
-    enum node_subclass subclass_id;
-    int top, bot, mid;
-    int result;
-
-    for (top = 0, bot = (sizeof(keytab) / sizeof(struct keytab))-1; 
-         bot >= top; ) {
-        mid = (top + bot) / 2;
-        result = name_compare (s, keytab[mid].name);
-        if (result < 0)
-            bot = mid - 1;
-        else if (result > 0)
-            top = mid + 1;
-        else {
-            subclass_id = keytab[mid].subclass_id;
-
-            switch (subclass_id) {
-            case NODE_U8:
-            case NODE_U16:
-            case NODE_U32:
-            case NODE_U64:
-            case NODE_I8:
-            case NODE_I16:
-            case NODE_I32:
-            case NODE_I64:
-            case NODE_F64:
-            case NODE_UWORD:
-                *token_value = make_node(subclass_id);
-                return (PRIMTYPE);
-
-            case NODE_PACKED:
-                *token_value = make_node(subclass_id);
-                return (TPACKED);
-
-            case NODE_DEFINE:
-                message_crc = 0;
-                *token_value = make_node(subclass_id);
-                return(DEFINE);
-
-            case NODE_MANUAL_PRINT:
-                *token_value = (YYSTYPE) NODE_FLAG_MANUAL_PRINT;
-                return (MANUAL_PRINT);
-
-            case NODE_MANUAL_ENDIAN:
-                *token_value = (YYSTYPE) NODE_FLAG_MANUAL_ENDIAN;
-                return (MANUAL_ENDIAN);
-
-            case NODE_TYPEONLY:
-                *token_value = (YYSTYPE) NODE_FLAG_TYPEONLY;
-                return(TYPEONLY);
-
-            case NODE_DONT_TRACE:
-                *token_value = (YYSTYPE) NODE_FLAG_DONT_TRACE;
-                return(DONT_TRACE);
-
-            case NODE_AUTOREPLY:
-                *token_value = (YYSTYPE) NODE_FLAG_AUTOREPLY;
-                return(AUTOREPLY);
-
-            case NODE_NOVERSION:
-                return(NOVERSION);
-
-            case NODE_VERSION:
-                return(VL_API_VERSION);
-
-            case NODE_UNION:
-                return(UNION);
-
-            default:
-                fprintf (stderr, "fatal: keytab botch!\n");
-                exit (1);
-            }
-        }
-    }
-    *token_value = (YYSTYPE) sxerox (s);
-    return (NAME);
-}
-
-/*
- * sxerox
- */
-
-char *sxerox (const char *s)
-{
-    int len = strlen (s);
-    char *rv;
-
-    rv = (char *) malloc (len+1);
-    if (rv == 0) {
-        fprintf(stderr, "Out of memory...");
-        exit (1);
-    }
-        
-    strcpy (rv, s);
-    return (rv);
-}
-
-/*
- * name_compare
- */
-
-int name_compare (const char *s1, const char *s2)
-{
-    char c1, c2;
-
-    while (*s1 && *s2) {
-        c1 = *s1++;
-        c2 = *s2++;
-
-        c1 = tolower (c1);
-        c2 = tolower (c2);
-        if (c1 < c2)
-            return (-1);
-        else if (c1 > c2)
-            return (1);
-    }
-    if (*s1 < *s2)
-        return (-1);
-    else if (*s1 > *s2)
-        return (1);
-    return (0);
-}
diff --git a/src/tools/vppapigen/lex.h b/src/tools/vppapigen/lex.h
deleted file mode 100644 (file)
index 275cf68..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- *------------------------------------------------------------------
- * lex.h - definitions for the api generator's lexical
- * analyzer.
- *
- * Copyright (c) 1996-2009 Cisco and/or its affiliates.
- * 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.
- *------------------------------------------------------------------
- */
-
-#ifndef _LEX_H_
-#define _LEX_H_ 1
-
-extern int yylex (void);
-extern void yyerror (char *);
-extern int yyparse (void);
-extern void autoreply (void *);
-
-#ifndef YYSTYPE
-#define YYSTYPE void *
-#endif
-
-#include "tools/vppapigen/gram.h"
-
-enum lex_state {
-    START_STATE = 1,
-    NAME_STATE,
-    NUMBER_STATE,
-    C_COMMENT_STATE,
-    CPP_COMMENT_STATE,
-    STRING_STATE,
-    HELPER_STATE,
-    LINE_PRAGMA_STATE,
-};
-
-#define MAXNAME 64000
-
-extern unsigned long input_crc;
-extern unsigned long message_crc;
-
-#endif /* _LEX_H_ */
diff --git a/src/tools/vppapigen/node.c b/src/tools/vppapigen/node.c
deleted file mode 100644 (file)
index 37ba493..0000000
+++ /dev/null
@@ -1,1602 +0,0 @@
-/* 
- *------------------------------------------------------------------
- * node.c - the api generator's semantic back-end
- *
- * Copyright (c) 2004-2009 Cisco and/or its affiliates.
- * 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.
- *------------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdbool.h>
-#include <ctype.h>
-#include <time.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <vppinfra/vec.h>
-#include <vppinfra/hash.h>
-
-#include "lex.h"
-#include "node.h"
-
-#define YYSTYPE void *
-
-FILE *ofp;
-FILE *pythonfp;
-FILE *jsonfp;
-time_t starttime;
-char *vlib_app_name;
-char *input_filename;
-node_vft_t *the_vft[NODE_N_TYPES];
-static u32 indent;
-static int dont_output_version;
-int dump_tree;
-static char *fixed_name;
-static char tmpbuf [MAXNAME];
-static char *current_def_name;
-static char *current_union_name;
-static char *current_type_fmt;
-static char *current_type_cast;
-static char current_id;
-static char current_is_complex;
-static char *current_endianfun;
-static char *current_type_name;
-
-void indent_me(FILE *ofp)
-{
-    int i;
-
-    for (i = 0; i < indent; i++)
-        putc(' ', ofp);
-}
-
-char *uppercase (char *s)
-{
-    char *cp;
-
-    cp = tmpbuf;
-
-    while (*s && (cp < tmpbuf + (sizeof(tmpbuf)-1))) {
-        if (*s >= 'a' && *s <= 'z')
-            *cp++ = *s++ - ('a' - 'A');
-        else
-            *cp++ = *s++;
-    }
-    *cp = 0;
-    return(tmpbuf);
-}
-
-char *lowercase (char *s)
-{
-    char *cp;
-
-    cp = tmpbuf;
-
-    while (*s && (cp < tmpbuf + (sizeof(tmpbuf)-1))) {
-        if (*s >= 'A' && *s <= 'Z')
-            *cp++ = *s++ + ('a' - 'A');
-        else
-            *cp++ = *s++;
-    }
-    *cp = 0;
-    return(tmpbuf);
-}
-
-void primtype_recursive_print(node_t *this, i8 *fmt)
-{
-    fputs((char *)fmt, stdout);
-
-    if (this->deeper) {
-        node_vft_t *vftp = the_vft[this->deeper->type];
-        vftp->print(this->deeper);
-    }
-}
-
-void primtype_recursive_generate(node_t *this, enum passid which, FILE *ofp,
-                                 i8 *type_name, i8 *type_fmt, i8 *type_cast)
-{
-    node_vft_t *vftp;
-
-    current_type_name = (char *)type_name;
-    current_type_cast = (char *)type_cast;
-
-    switch(which) {
-    case TYPEDEF_PASS:
-        fputs((char *)type_name, ofp);
-        fputs(" ", ofp);
-        break;
-
-    case PRINTFUN_PASS:
-        current_type_fmt = (char *)type_fmt;
-        break;
-
-    case ENDIANFUN_PASS:
-        vftp = the_vft[this->type];
-        current_endianfun = vftp->endian_converter;
-        break;
-
-    case PYTHON_PASS:
-        fputs("('", pythonfp);
-        fputs((char *)type_name, pythonfp);
-        fputs("', ", pythonfp);
-        break;
-
-    case JSON_PASS:
-        fputs("[\"", jsonfp);
-        fputs((char *)type_name, jsonfp);
-        fputs("\", ", jsonfp);
-        break;
-
-    default:
-        fprintf(stderr, "primtype_recursive_generate: unimp pass %d\n", which);
-        break;
-    }
-
-    if (this->deeper) {
-        vftp = the_vft[this->deeper->type];
-        vftp->generate(this->deeper, which, ofp);
-    }
-}
-
-void node_illegal_print (node_t *this)
-{
-    fprintf(stderr, "node_illegal_print called\n");
-    exit(0);
-}
-
-void node_illegal_generate (node_t *this, enum passid notused, FILE *ofp)
-{
-    fprintf(stderr, "node_illegal_generate called\n");
-    exit(0);
-}
-
-node_vft_t node_illegal_vft = {
-    node_illegal_print,
-    node_illegal_generate,
-    "illegal"
-};
-
-void node_u8_print (node_t *this)
-{
-    primtype_recursive_print(this, "u8 ");
-}
-
-void node_u8_generate (node_t *this, enum passid which, FILE *ofp)
-{
-    primtype_recursive_generate(this, which, ofp, "u8", "%u", "(unsigned)");
-}
-
-node_vft_t node_u8_vft = {
-    node_u8_print,
-    node_u8_generate,
-    NULL
-};
-
-void node_u16_print (node_t *this)
-{
-    primtype_recursive_print(this, "u16 ");
-}
-
-void node_u16_generate (node_t *this, enum passid which, FILE *ofp)
-{
-    primtype_recursive_generate(this, which, ofp, "u16", "%u", "(unsigned)");
-}
-
-node_vft_t node_u16_vft = {
-    node_u16_print,
-    node_u16_generate,
-    "clib_net_to_host_u16"
-};
-
-void node_u32_print (node_t *this)
-{
-    primtype_recursive_print(this, "u32 ");
-}
-
-void node_u32_generate (node_t *this, enum passid which, FILE *ofp)
-{
-    primtype_recursive_generate(this, which, ofp, "u32", "%u", "(unsigned)");
-}
-
-node_vft_t node_u32_vft = {
-    node_u32_print,
-    node_u32_generate,
-    "clib_net_to_host_u32",
-};
-
-void node_u64_print (node_t *this)
-{
-    primtype_recursive_print(this, "u64 ");
-}
-
-void node_u64_generate (node_t *this, enum passid which, FILE *ofp)
-{
-    primtype_recursive_generate(this, which, ofp, "u64", "%llu", 
-                                "(long long)");
-}
-
-node_vft_t node_u64_vft = {
-    node_u64_print,
-    node_u64_generate,
-    "clib_net_to_host_u64"
-};
-
-void node_i8_print (node_t *this)
-{
-    primtype_recursive_print(this, "i8 ");
-}
-
-void node_i8_generate (node_t *this, enum passid which, FILE *ofp)
-{
-    primtype_recursive_generate(this, which, ofp, "i8", "%d", "(int)");
-}
-
-node_vft_t node_i8_vft = {
-    node_i8_print,
-    node_i8_generate,
-    ""
-};
-
-void node_i16_print (node_t *this)
-{
-    primtype_recursive_print(this, "i16 ");
-}
-
-void node_i16_generate (node_t *this, enum passid which, FILE *ofp)
-{
-    primtype_recursive_generate(this, which, ofp, "i16", "%d", "(int)");
-}
-
-node_vft_t node_i16_vft = {
-    node_i16_print,
-    node_i16_generate,
-    "clib_net_to_host_u16"
-};
-
-void node_i32_print (node_t *this)
-{
-    primtype_recursive_print(this, "i32 ");
-}
-
-void node_i32_generate (node_t *this, enum passid which, FILE *ofp)
-{
-    primtype_recursive_generate(this, which, ofp, "i32", "%ld", "(long)");
-}
-
-node_vft_t node_i32_vft = {
-    node_i32_print,
-    node_i32_generate,
-    "clib_net_to_host_u32"
-};
-
-void node_i64_print (node_t *this)
-{
-    primtype_recursive_print(this, "i64 ");
-}
-
-void node_i64_generate (node_t *this, enum passid which, FILE *ofp)
-{
-    primtype_recursive_generate(this, which, ofp, "i64", "%lld", 
-                                "(long long)");
-}
-
-node_vft_t node_i64_vft = {
-    node_i64_print,
-    node_i64_generate,
-    "clib_net_to_host_u64"
-};
-
-void node_f64_print (node_t *this)
-{
-    primtype_recursive_print(this, "f64 ");
-}
-
-void node_f64_generate (node_t *this, enum passid which, FILE *ofp)
-{
-    primtype_recursive_generate(this, which, ofp, "f64", "%.2f", 
-                                "(double)");
-}
-
-node_vft_t node_f64_vft = {
-    node_f64_print,
-    node_f64_generate,
-    " ",                        /* FP numbers are sent in host byte order */
-};
-
-
-void node_packed_print (node_t *this)
-{
-    primtype_recursive_print (this, "packed ");
-}
-
-void node_packed_generate (node_t *this, enum passid which, FILE *ofp)
-{
-    primtype_recursive_generate(this, which, ofp, "PACKED", "", "");
-}
-
-node_vft_t node_packed_vft = {
-    node_packed_print,
-    node_packed_generate,
-    0,
-};
-
-void node_define_print (node_t *this)
-{
-    fprintf(stdout, "define %s {\n", CDATA0);
-    if (this->deeper) {
-        node_vft_t *vftp = the_vft[this->deeper->type];
-        fprintf(stdout, "    ");
-        vftp->print(this->deeper);
-    }
-    fprintf(stdout, "};\n");
-}
-
-void node_define_generate (node_t *this, enum passid which, FILE *fp)
-{
-    node_t *child;
-
-    switch(which) {
-    case TYPEDEF_PASS:
-        fprintf(fp, "typedef VL_API_PACKED(struct _vl_api_%s {\n", CDATA0);
-        child = this->deeper;
-        indent += 4;
-        while (child) {
-            node_vft_t *vftp = the_vft[child->type];
-            indent_me(fp);
-            vftp->generate(child, which, fp);
-            child = child->peer;
-        }
-        indent -= 4;
-        fprintf(fp, "}) vl_api_%s_t;\n\n", CDATA0);
-        break;
-
-    case ENDIANFUN_PASS:
-    case PRINTFUN_PASS:
-        child = this->deeper;
-        while (child) {
-            node_vft_t *vftp = the_vft[child->type];
-            vftp->generate(child, which, fp);
-            child = child->peer;
-        }
-        break;
-
-    case PYTHON_PASS:
-      fprintf(fp, "('%s',\n", CDATA0);
-        child = this->deeper;
-        indent += 4;
-        while (child) {
-            node_vft_t *vftp = the_vft[child->type];
-            indent_me(fp);
-            vftp->generate(child, which, fp);
-            child = child->peer;
-        }
-        indent -= 4;
-        fprintf(fp, "),\n\n");
-        break;
-
-    case JSON_PASS:
-        fprintf(fp, "[\"%s\",\n", CDATA0);
-        child = this->deeper;
-        indent += 4;
-        while (child) {
-            node_vft_t *vftp = the_vft[child->type];
-            indent_me(fp);
-            vftp->generate(child, which, fp);
-            child = child->peer;
-           fprintf(fp, ",\n");
-        }
-       indent_me(fp);
-       fprintf (fp, "{\"crc\" : \"0x%08x\"}\n", (u32)(uword)CDATA3);
-        indent -= 4;
-       indent_me(fp);
-        fprintf(fp, "]");
-        break;
-
-    default:
-        fprintf(stderr, "node_define_generate: unimp pass %d\n", which);
-        break;
-    }
-}
-
-node_vft_t node_define_vft = {
-    node_define_print,
-    node_define_generate,
-    0,
-};
-
-void node_union_print (node_t *this)
-{
-    primtype_recursive_print (this, "union ");
-}
-
-void node_union_generate (node_t *this, enum passid which, FILE *fp)
-{
-    node_t *child;
-    node_t *uelem;
-    int case_id=1;
-
-    switch(which) {
-    case TYPEDEF_PASS:
-        fprintf(fp, "u8 _%s_which;\n", CDATA0);
-        indent_me(fp);
-        fprintf(fp, "union _%s {\n", CDATA0);
-        child = this->deeper;
-        indent += 4;
-    
-        while (child) {
-            node_vft_t *vftp = the_vft[child->type];
-            indent_me(fp);
-            vftp->generate(child, which, fp);
-            child = child->peer;
-        }
-        indent -= 4;
-        indent_me(fp);
-        fprintf(fp, "} %s;\n", CDATA0);
-        break;
-
-    case PRINTFUN_PASS:
-    case ENDIANFUN_PASS:
-        uelem = this->deeper;
-        
-        indent_me(fp);
-        fprintf(fp, "switch(a->_%s_which) {\n",
-                CDATA0);
-        indent += 4;
-        current_union_name = CDATA0;
-
-        /* Walk the list of objects in this union */
-        while (uelem) {
-            node_vft_t *vftp = the_vft[uelem->type];
-            indent -= 4;
-            indent_me(fp);
-            fprintf(fp, "case %d:\n", case_id);
-            case_id++;
-            indent += 4;
-            /* Drill down on each element */
-            vftp->generate(uelem, which, fp);
-            indent_me(fp);
-            fprintf(fp, "break;\n");
-            uelem = uelem->peer;
-        }
-        current_union_name = 0;
-        indent -= 4;
-        indent_me(fp);
-        fprintf(fp, "default:\n");
-        indent += 4;
-        indent_me(fp);                 
-        if (which == PRINTFUN_PASS) {
-            fprintf(fp, 
-                    "vl_print(handle, \"WARNING: _%s_which not set.\\n\");\n",
-                    CDATA0);
-        }
-        indent_me(fp);
-        fprintf(fp, "break;\n");
-        indent -= 4;
-        indent_me(fp);
-        fprintf(fp, "}\n");
-        break;
-
-    default:
-        fprintf(stderr, "node_union_generate: unimp pass %d\n", which);
-        break;
-    }
-}
-
-
-node_vft_t node_union_vft = {
-    node_union_print,
-    node_union_generate,
-    0,
-};
-
-void node_scalar_print (node_t *this)
-{
-    fprintf(stdout, "%s", CDATA0);
-    primtype_recursive_print (this, "");
-}
-
-void node_scalar_generate (node_t *this, enum passid which, FILE *fp)
-{
-    char *union_prefix = "";
-
-    if (current_union_name) {
-        sprintf(tmpbuf, "%s.", current_union_name);
-        union_prefix = tmpbuf;
-    }
-
-    switch(which) {
-    case TYPEDEF_PASS:
-        fprintf(fp, "%s;\n", CDATA0);
-        break;
-
-    case PRINTFUN_PASS:
-        indent_me(fp);
-        if (current_is_complex) {
-            fprintf(fp, "vl_api_%s_t_print(a->%s%s, handle);\n", 
-                    current_type_name, union_prefix, CDATA0);
-        } else {
-            if (!strcmp(current_type_fmt, "uword")) {
-                fprintf(fp, 
-           "vl_print(handle, \"%s%s: \" _uword_fmt \"\\n\", %s a->%s%s);\n", 
-                        union_prefix, CDATA0, "(_uword_cast)",
-                        union_prefix, CDATA0);
-            } else {
-                fprintf(fp, 
-                        "vl_print(handle, \"%s%s: %s\\n\", %s a->%s%s);\n", 
-                        union_prefix, CDATA0, 
-                        current_type_fmt, current_type_cast,
-                        union_prefix, CDATA0);
-            }
-        }
-        break;
-
-    case ENDIANFUN_PASS:
-        indent_me(fp);
-        if (current_is_complex) {
-            fprintf(fp, "vl_api%s_t_endian(a->%s%s);\n", 
-                    current_type_name, union_prefix, CDATA0);
-        } else {
-            /* Current_endianfun == NULL means e.g. it's a u8... */
-            if (current_endianfun) {
-                fprintf(fp, "a->%s%s = %s(a->%s%s);\n", union_prefix,
-                        CDATA0, current_endianfun, 
-                        union_prefix, CDATA0);
-            } else {
-                fprintf(fp, "/* a->%s%s = a->%s%s (no-op) */\n",
-                        union_prefix, CDATA0, 
-                        union_prefix, CDATA0);
-            }
-        }
-        break;
-    case PYTHON_PASS:
-        fprintf(fp, "'%s'),\n", CDATA0);
-        break;
-
-    case JSON_PASS:
-        fprintf(fp, "\"%s\"]", CDATA0);
-        break;
-
-    default:
-        fprintf(stderr, "node_scalar_generate: unimp pass %d\n", which);
-    }
-    if (this->deeper) {
-        fprintf(stderr, "broken recursion in node_scalar_generate\n");
-    }
-}
-
-
-node_vft_t node_scalar_vft = {
-    node_scalar_print,
-    node_scalar_generate,
-    0,
-};
-
-void node_vector_print (node_t *this)
-{
-    primtype_recursive_print (this, "vector ");
-}
-
-void node_vector_generate (node_t *this, enum passid which, FILE *fp)
-{
-    char *union_prefix = "";
-
-    if (current_union_name) {
-        sprintf(tmpbuf, "%s.", current_union_name);
-        union_prefix = tmpbuf;
-    }
-
-    switch(which) {
-    case TYPEDEF_PASS:
-        fprintf(fp, "%s[%d];\n", CDATA0, IDATA1);
-        break;
-
-    case PRINTFUN_PASS:
-        /* Don't bother about "u8 data [0];" et al. */
-        if (IDATA1 == 0)
-            break;
-
-        indent_me(fp);
-        fprintf(fp, "{\n");
-        indent += 4;
-        indent_me(fp);
-        fprintf(fp, "int _i;\n");
-        indent_me(fp);
-        fprintf(fp, "for (_i = 0; _i < %d; _i++) {\n", 
-                IDATA1);
-        indent += 4;
-        indent_me(fp);
-        if (current_is_complex) {
-            fprintf(fp, "vl_print(handle, \"%s%s[%%d]: ",
-                    union_prefix, CDATA0);
-            fprintf(fp, 
-                    "vl_print_%s (handle, a->%s%s[_i]);\n", 
-                    CDATA0, union_prefix, CDATA0);
-        } else {
-            fprintf(fp, 
-         "vl_print(handle, \"%s%s[%%d]: %s\\n\", _i, a->%s%s[_i]);\n",
-                    union_prefix, CDATA0, 
-                    current_type_fmt, 
-                    union_prefix, CDATA0);
-        }
-        indent -= 4;
-        indent_me(fp);
-        fprintf(fp, "}\n");
-        indent -= 4;
-        indent_me(fp);
-        fprintf(fp, "}\n");
-        break;
-
-    case ENDIANFUN_PASS:
-        /* Don't bother about "u8 data [0];" et al. */
-        if (IDATA1 == 0)
-            break;
-        /* If this is a simple endian swap, but the endian swap method is a no-op,
-         * then indicate this is a no-op in a comment.
-         */
-       if (!current_is_complex && current_endianfun == NULL) {
-            indent_me(fp);
-            fprintf(fp, "/* a->%s%s[0..%d] = a->%s%s[0..%d] (no-op) */\n",
-                    union_prefix, CDATA0, IDATA1 - 1,
-                    union_prefix, CDATA0, IDATA1 - 1);
-            break;
-        }
-
-        indent_me(fp);
-        fprintf(fp, "{\n");
-        indent += 4;
-        indent_me(fp);
-        fprintf(fp, "int _i;\n");
-        indent_me(fp);
-        fprintf(fp, "for (_i = 0; _i < %d; _i++) {\n", 
-                IDATA1);
-        indent += 4;
-        indent_me(fp);
-        if (current_is_complex) {
-            fprintf(fp, 
-                    "vl_api_%s_t_endian (a->%s%s[_i]);\n", 
-                    current_type_name, union_prefix, CDATA0);
-        } else {
-            fprintf(fp, 
-                    "a->%s%s[_i] = %s(a->%s%s[_i]);\n", 
-                    union_prefix, CDATA0, 
-                    current_endianfun, 
-                    union_prefix, CDATA0);
-        }
-        indent -= 4;
-        indent_me(fp);
-        fprintf(fp, "}\n");
-        indent -= 4;
-        indent_me(fp);
-        fprintf(fp, "}\n");
-        break;
-    case PYTHON_PASS:
-        if (CDATA2 != 0) { // variable length vector
-            fprintf(fp, "'%s', '%d', '%s'),\n", CDATA0, IDATA1, CDATA2);
-        } else {
-            fprintf(fp, "'%s', '%d'),\n", CDATA0, IDATA1);
-        }
-        break;
-
-    case JSON_PASS:
-      if (CDATA2 != 0) { /* variable length vector */
-            fprintf(fp, "\"%s\", %d, \"%s\"]", CDATA0, IDATA1, CDATA2);
-        } else {
-            fprintf(fp, "\"%s\", %d]", CDATA0, IDATA1);
-        }
-        break;
-
-    default:
-        fprintf(stderr, "node_vector_generate: unimp pass %d\n", which);
-    }
-    if (this->deeper) {
-        fprintf(stderr, "broken recursion in node_vector_generate\n");
-    }
-}
-
-node_vft_t node_vector_vft = {
-    node_vector_print,
-    node_vector_generate,
-    0,
-};
-
-void node_complex_print (node_t *this)
-{
-    primtype_recursive_print (this, "complex ");
-}
-
-void node_complex_generate (node_t *this, enum passid which, FILE *fp)
-{
-    node_t *deeper;
-    node_vft_t *vftp;
-    char *member_name = "broken!";
-    char *union_prefix = "";
-
-    if (current_union_name) {
-        sprintf(tmpbuf, "%s.", current_union_name);
-        union_prefix = tmpbuf;
-    }
-
-    current_is_complex++;
-    
-    switch(which) {
-    case TYPEDEF_PASS:
-        fprintf(fp, "%s ", CDATA0);
-        deeper = this->deeper;
-        if (deeper) {
-            vftp = the_vft[deeper->type];
-            vftp->generate(deeper, which, fp);
-        }
-        break;
-
-    case PRINTFUN_PASS:
-        deeper = this->deeper;
-        while (deeper) {
-            if (deeper->type == NODE_SCALAR ||
-                deeper->type == NODE_VECTOR) {
-                member_name = deeper->data[0];
-                break;
-            }
-            deeper = deeper->deeper;
-        }
-        indent_me(fp);
-        fprintf(fp, "vl_print(handle, \"%s%s ----- \\n\");\n", 
-                union_prefix, member_name);
-        indent_me(fp);
-
-        if (deeper && deeper->type == NODE_VECTOR)
-            fprintf(fp, "%s_print(a->%s%s, handle);\n", 
-                    CDATA0, union_prefix, member_name);
-        else
-            fprintf(fp, "%s_print(&a->%s%s, handle);\n", 
-                    CDATA0, union_prefix, member_name);
-
-        indent_me(fp);
-        fprintf(fp, "vl_print(handle, \"%s%s ----- END \\n\");\n", 
-                union_prefix, member_name);
-        break;
-
-    case ENDIANFUN_PASS:
-        deeper = this->deeper;
-        while (deeper) {
-            if (deeper->type == NODE_SCALAR ||
-                deeper->type == NODE_VECTOR) {
-                member_name = deeper->data[0];
-                break;
-            }
-            deeper = deeper->deeper;
-        }
-
-        indent_me(fp);
-        if (deeper && deeper->type == NODE_VECTOR)
-            fprintf(fp, "%s_endian(a->%s%s);\n", 
-                    CDATA0, union_prefix, member_name);
-        else
-            fprintf(fp, "%s_endian(&a->%s%s);\n", 
-                    CDATA0, union_prefix, member_name);
-        break;
-    case PYTHON_PASS:
-        fprintf(fp, "('%s',", CDATA0);
-        deeper = this->deeper;
-        if (deeper) {
-            vftp = the_vft[deeper->type];
-            vftp->generate(deeper, which, fp);
-        }
-        break;
-
-    case JSON_PASS:
-        fprintf(fp, "[\"%s\", ", CDATA0);
-        deeper = this->deeper;
-        if (deeper) {
-            vftp = the_vft[deeper->type];
-            vftp->generate(deeper, which, fp);
-        }
-        break;
-
-    default:
-        fprintf(stderr, "node_complex_generate unimp pass %d...\n", which);
-        break;
-    }
-    current_is_complex--;
-}
-
-node_vft_t node_complex_vft = {
-    node_complex_print,
-    node_complex_generate,
-    0,
-};
-
-void node_noversion_print (node_t *this)
-{
-    primtype_recursive_print (this, "noversion ");
-}
-
-void node_noversion_generate (node_t *this, enum passid which, FILE *ofp)
-{
-    fprintf(stderr, "node_noversion_generate called...\n");
-}
-
-node_vft_t node_noversion_vft = {
-    node_noversion_print,
-    node_noversion_generate,
-    0,
-};
-
-void node_version_print (node_t *this)
-{
-    primtype_recursive_print (this, "version ");
-}
-
-void node_version_generate (node_t *this, enum passid which, FILE *ofp)
-{
-    fprintf(stderr, "node_version_generate called...\n");
-}
-
-node_vft_t node_version_vft = {
-    node_version_print,
-    node_version_generate,
-    0,
-};
-
-void node_uword_print (node_t *this)
-{
-    primtype_recursive_print(this, "uword ");
-}
-
-void node_uword_generate (node_t *this, enum passid which, FILE *ofp)
-{
-    primtype_recursive_generate(this, which, ofp, "uword", "uword", "");
-}
-
-node_vft_t node_uword_vft = {
-    node_uword_print,
-    node_uword_generate,
-    "clib_net_to_host_uword",
-};
-
-node_vft_t *the_vft[NODE_N_TYPES] = {
-    &node_illegal_vft,
-    &node_u8_vft,
-    &node_u16_vft,
-    &node_u32_vft,
-    &node_u64_vft,
-    &node_i8_vft,
-    &node_i16_vft,
-    &node_i32_vft,
-    &node_i64_vft,
-    &node_f64_vft,
-    &node_packed_vft,
-    &node_define_vft,
-    &node_union_vft,
-    &node_scalar_vft,
-    &node_vector_vft,
-    &node_complex_vft,
-    &node_noversion_vft,
-    &node_version_vft,
-    &node_uword_vft,
-};
-
-void *make_node (enum node_subclass type)
-{
-    node_t *rv;
-
-    rv = (node_t *) malloc (sizeof (*rv));
-    if (rv == 0) {
-        fprintf (stderr, "fatal: make_node out of memory\n");
-        exit (1);
-    }
-    bzero (rv, sizeof (*rv));
-    rv->type = type;
-    return ((void *) rv);
-}
-
-YYSTYPE deeper (YYSTYPE arg1, YYSTYPE arg2)
-{
-    node_t *np1 = (node_t *) arg1;
-    node_t *np2 = (node_t *) arg2;
-    node_t *hook_point;
-    
-    hook_point = np1;
-
-    while (hook_point->deeper)
-        hook_point = hook_point->deeper;
-
-    hook_point->deeper = np2;
-    return (arg1);
-}
-
-YYSTYPE addpeer (YYSTYPE arg1, YYSTYPE arg2)
-{
-    node_t *np1 = (node_t *) arg1;
-    node_t *np2 = (node_t *) arg2;
-    node_t *hook_point;
-    
-    hook_point = np1;
-
-    while (hook_point->peer)
-        hook_point = hook_point->peer;
-
-    hook_point->peer = np2;
-    return (arg1);
-}
-
-/*
- * add_slist (stmt_list, stmt)
- */
-
-YYSTYPE add_slist (YYSTYPE a1, YYSTYPE a2)
-{
-    if (a1 && a2)
-        return (addpeer(a1, a2));
-    else if(a1)
-        return(a1);
-    else 
-        return(a2);
-}
-
-/*
- * add_define (char *name, defn_list);
- */
-YYSTYPE add_define (YYSTYPE a1, YYSTYPE a2)
-{
-    node_t *np;
-
-    np = make_node(NODE_DEFINE);
-    np->data[0] = a1;
-    np->data[3] = (void *) message_crc;
-    deeper((YYSTYPE)np, a2);
-    return ((YYSTYPE) np);
-}
-
-/*
- * add_defbody (defn_list, new_defn)
- */
-YYSTYPE add_defbody (YYSTYPE a1, YYSTYPE a2)
-{
-    return (addpeer(a1, a2));
-}
-
-/*
- * add_primtype ([packed], primitive type, instance)
- */ 
-
-YYSTYPE add_primtype (YYSTYPE a1, YYSTYPE a2, YYSTYPE a3)
-{
-    /* Hook instance to type node */
-    deeper (a1, a2);
-    if (a3) {
-        deeper(a1, a3);
-    }
-    return (a1);
-}
-
-/*
- * add_complex(char *type_name, instance)
- */
-
-YYSTYPE add_complex (YYSTYPE a1, YYSTYPE a2)
-{
-    node_t *np;
-
-    np = make_node(NODE_COMPLEX);
-    np->data[0] = (void *) a1;
-
-    deeper((YYSTYPE)np, a2);
-    return ((YYSTYPE) np);
-}
-
-/*
- * add_union(char *type_name, definition)
- */
-
-YYSTYPE add_union (YYSTYPE a1, YYSTYPE a2)
-{
-    node_t *np;
-
-    np = make_node(NODE_UNION);
-    np->data[0] = (void *) a1;
-
-    deeper((YYSTYPE)np, a2);
-    return ((YYSTYPE) np);
-}
-
-
-/*
- * add_vector_vbl (node_t *variable, YYSTYPE size)
- */
-
-YYSTYPE add_vector_vbl (YYSTYPE a1, YYSTYPE a2)
-{
-    node_t *np;
-
-    np = make_node(NODE_VECTOR);
-    np->data[0] = (void *) a1;
-    np->data[1] = (void *) a2;
-    return ((YYSTYPE) np);
-}
-
-/*
- * add_vector_vbl (char *vector_name, char *vector_length_var)
- */
-
-YYSTYPE add_variable_length_vector_vbl (YYSTYPE vector_name, YYSTYPE vector_length_var)
-{
-    node_t *np;
-
-    np = make_node(NODE_VECTOR);
-    np->data[0] = (void *) vector_name;
-    np->data[1] = (void *) 0; // vector size used for vpe.api.h generation (array of length zero)
-    np->data[2] = (void *) vector_length_var; // name of the variable that stores vector length
-    return ((YYSTYPE) np);
-}
-
-/*
- * add_scalar_vbl (char *name)
- */
-YYSTYPE add_scalar_vbl (YYSTYPE a1)
-{
-    node_t *np;
-
-    np = make_node(NODE_SCALAR);
-    np->data[0] = (void *) a1;
-    return ((YYSTYPE) np);
-}
-
-/*
- * set_flags (int flags, msg(=0?))
- */ 
-YYSTYPE set_flags(YYSTYPE a1, YYSTYPE a2)
-{
-    node_t *np;
-    int flags;
-
-    np = (node_t *)a2;
-    if (!np)
-        return(0);
-
-    flags = (int)(uword) a1;
-
-    np->flags |= flags;
-
-    /* Generate a foo_reply_t right here */
-    if (flags & NODE_FLAG_AUTOREPLY) 
-        autoreply(np);
-
-    return (a2);
-}
-/*
- * suppress_version
- */
-YYSTYPE suppress_version (void)
-{
-    dont_output_version = 1;
-    return (0);
-}
-
-void dump(node_t *np)
-{
-    node_vft_t *vftp;
-
-    while (np) {
-        vftp = the_vft[np->type];
-        vftp->print(np);
-        np = np->peer;
-    }
-}
-
-char *fixup_input_filename(void)
-{
-    char *cp;
-
-    cp = (char *)input_filename;
-
-    while (*cp)
-        cp++;
-
-    cp--;
-
-    while (cp > input_filename && *cp != '/')
-        cp--;
-    if (*cp == '/')
-        cp++;
-
-    strncpy (tmpbuf, cp, sizeof(tmpbuf)-1);
-
-    cp = tmpbuf;
-
-    while (*cp)
-        cp++;
-
-    cp--;
-
-    while (cp > tmpbuf && *cp != '.')
-        cp--;
-    
-    if (*cp == '.')
-        *cp = 0;
-
-    return (sxerox(tmpbuf));
-}
-
-void generate_top_boilerplate(FILE *fp)
-
-{
-    time_t curtime;
-    char *datestring;
-    char *source_date_epoch;
-    if ((source_date_epoch = getenv("SOURCE_DATE_EPOCH")) == NULL || (curtime = (time_t)strtol(source_date_epoch, NULL, 10)) <= 0)
-        curtime = starttime;
-    datestring = asctime(gmtime(&curtime));
-    fixed_name = fixup_input_filename();
-
-    datestring[24] = 0;
-
-    fprintf (fp, "/*\n");
-    fprintf (fp, " * VLIB API definitions %s\n", datestring);
-    fprintf (fp, " * Input file: %s\n", input_filename);
-    fprintf (fp, " * Automatically generated: please edit the input file ");
-    fprintf (fp, "NOT this file!\n");
-    fprintf (fp, " */\n\n");
-    fprintf (fp, "#if defined(vl_msg_id)||defined(vl_union_id)||");
-    fprintf (fp, "defined(vl_printfun) \\\n ||defined(vl_endianfun)||");
-    fprintf (fp, " defined(vl_api_version)||defined(vl_typedefs) \\\n");
-    fprintf (fp, " ||defined(vl_msg_name)||defined(vl_msg_name_crc_list) \\\n");
-    fprintf (fp, " ||defined(vl_api_version_tuple)\n");
-    fprintf (fp, "/* ok, something was selected */\n");
-    fprintf (fp, "#else\n");
-    fprintf (fp, "#warning no content included from %s\n", input_filename);
-    fprintf (fp, "#endif\n\n");
-    fprintf (fp, "#define VL_API_PACKED(x) x __attribute__ ((packed))\n\n");
-}
-
-void generate_bottom_boilerplate(FILE *fp)
-
-{
-    fprintf(fp, "/****** API CRC (whole file) *****/\n\n");
-    fprintf (fp, "#ifdef vl_api_version\n");
-
-    if (dont_output_version) {
-        fprintf (fp, "/* WARNING: API FILE VERSION CHECK DISABLED */\n");
-        input_crc = 0;
-    }
-
-    fprintf (fp, "vl_api_version(%s, 0x%08x)\n\n", 
-             fixed_name, (unsigned int)input_crc);
-
-    fprintf (fp, "#endif\n\n");
-}
-
-void generate_msg_ids(YYSTYPE a1, FILE *fp)
-{
-    node_t *np = (node_t *)a1;
-
-    fprintf (fp, "\n/****** Message ID / handler enum ******/\n\n");
-    fprintf (fp, "#ifdef vl_msg_id\n");
-
-    while (np) {
-        if (np->type == NODE_DEFINE) {
-            if (!(np->flags & NODE_FLAG_TYPEONLY)) {
-                fprintf (fp, "vl_msg_id(VL_API_%s, vl_api_%s_t_handler)\n", 
-                         uppercase(np->data[0]), (i8 *)np->data[0]);
-            } else {
-                fprintf (fp, "/* typeonly: %s */\n", (i8 *)np->data[0]);
-            }
-        }
-        np = np->peer;
-    }
-    fprintf (fp, "#endif\n");
-
-}
-
-void generate_msg_names(YYSTYPE a1, FILE *fp)
-{
-    node_t *np = (node_t *)a1;
-
-    fprintf (fp, "\n/****** Message names ******/\n\n");
-
-    fprintf (fp, "#ifdef vl_msg_name\n");
-
-    while (np) {
-        if (np->type == NODE_DEFINE) {
-            if (!(np->flags & NODE_FLAG_TYPEONLY)) {
-                fprintf (fp, "vl_msg_name(vl_api_%s_t, %d)\n",
-                         (i8 *) np->data[0], 
-                         (np->flags & NODE_FLAG_DONT_TRACE ? 0 : 1));
-            } else {
-                fprintf (fp, "/* typeonly: %s */\n", (i8 *)np->data[0]);
-            }
-        }
-        np = np->peer;
-    }
-    fprintf (fp, "#endif\n\n");
-}
-
-void generate_msg_name_crc_list (YYSTYPE a1, FILE *fp)
-{
-    node_t *np = (node_t *)a1;
-    char *unique_suffix, *cp;
-
-    unique_suffix = sxerox(fixed_name);
-
-    cp = unique_suffix;
-    while (*cp && (*cp != '.'))
-        cp++;
-    if (*cp == '.')
-        *cp = 0;
-
-    fprintf (fp, "\n/****** Message name, crc list ******/\n\n");
-
-    fprintf (fp, "#ifdef vl_msg_name_crc_list\n");
-    fprintf (fp, "#define foreach_vl_msg_name_crc_%s ", unique_suffix);
-
-    while (np) {
-        if (np->type == NODE_DEFINE) {
-            if (!(np->flags & NODE_FLAG_TYPEONLY)) {
-                fprintf (fp, "\\\n_(VL_API_%s, %s, %08x) ",
-                         uppercase (np->data[0]), (i8 *) np->data[0],
-                         (u32)(uword)np->data[3]);
-            }
-        }
-        np = np->peer;
-    }
-    fprintf (fp, "\n#endif\n\n");
-    free (unique_suffix);
-}
-
-void generate_typedefs(YYSTYPE a1, FILE *fp)
-{
-    node_t *np = (node_t *)a1;
-    node_vft_t *vftp;
-
-    fprintf(fp, "\n/****** Typedefs *****/\n\n");
-    fprintf(fp, "#ifdef vl_typedefs\n\n");
-
-    /* Walk the top-level node-list */
-    while (np) {
-        if (np->type == NODE_DEFINE) {
-            /* Yeah, this is pedantic */
-            vftp = the_vft[np->type];
-            vftp->generate(np, TYPEDEF_PASS, fp);
-        }
-        np = np->peer;
-    }
-    fprintf(fp, "#endif /* vl_typedefs */\n\n");
-}
-
-void union_walk_one_defn(node_t *np, FILE *fp)
-{
-    node_t *vblp;
-    node_t *uelem;
-
-    /* Walk the list of typed objects in this msg def */
-    while (np) {
-        if (np->type == NODE_UNION) {
-            current_union_name = np->data[0];
-            uelem = np->deeper;
-
-            /* Walk the list of objects in this union */
-            while (uelem) {
-                vblp = uelem->deeper;
-                /* Drill down on each element, find the variable name */
-                while(vblp) {
-                    if (vblp->type == NODE_SCALAR ||
-                        vblp->type == NODE_VECTOR ||
-                        vblp->type == NODE_COMPLEX) {
-                        fprintf(ofp, "#define %s_", 
-                                uppercase(current_def_name));
-                        fprintf(ofp, "%s_", uppercase(current_union_name));
-                        fprintf(ofp, "%s %d\n",uppercase(vblp->data[0]),
-                                current_id);
-                        current_id++;
-                        break;
-                    }
-                    vblp = vblp->deeper;
-                }
-                uelem = uelem->peer;
-            }
-            current_union_name = 0;
-            current_id = 1;
-        }
-        np = np->peer;
-    }
-}
-
-void generate_uniondefs(YYSTYPE a1, FILE *fp)
-{
-    node_t *np = (node_t *)a1;
-
-    fprintf(fp, "/****** Discriminated Union Definitions *****/\n\n");
-    fprintf(fp, "#ifdef vl_union_id\n\n");
-
-    /* Walk the top-level node-list */
-    while (np) {
-        if (np->type == NODE_DEFINE) {
-            current_id = 1;
-            current_def_name = np->data[0];
-            union_walk_one_defn(np->deeper, fp);
-        }
-        np = np->peer;
-    }
-    fprintf(fp, "\n#endif /* vl_union_id */\n\n");
-}
-
-void generate_printfun(YYSTYPE a1, FILE *fp)
-{
-    node_t *np = (node_t *)a1;
-    node_vft_t *vftp;
-
-    fprintf(fp, "/****** Print functions *****/\n\n");
-    fprintf(fp, "#ifdef vl_printfun\n\n");
-
-    fprintf(fp, "#ifdef LP64\n");
-    fputs ("#define _uword_fmt \"%lld\"\n", fp);
-    fputs ("#define _uword_cast (long long)\n", fp);
-    fprintf(fp, "#else\n");
-    fputs("#define _uword_fmt \"%ld\"\n", fp);
-    fputs ("#define _uword_cast long\n", fp);
-    fprintf(fp, "#endif\n\n");
-
-    /* Walk the top-level node-list */
-    while (np) {
-        if (np->type == NODE_DEFINE) {
-            if (!(np->flags & NODE_FLAG_MANUAL_PRINT)) {
-                fprintf(fp, 
-       "static inline void *vl_api_%s_t_print (vl_api_%s_t *a,",
-                        (i8 *)np->data[0], (i8 *) np->data[0]);
-                fprintf(fp, "void *handle)\n{\n");
-                /* output the message name */
-                fprintf(fp, 
-                    "    vl_print(handle, \"vl_api_%s_t:\\n\");\n",
-                        (i8 *)np->data[0]);
-
-                indent += 4;
-                /* Yeah, this is pedantic */
-                vftp = the_vft[np->type];
-                vftp->generate(np, PRINTFUN_PASS, fp);
-                fprintf(fp, "    return handle;\n");
-                fprintf(fp, "}\n\n");
-                indent -= 4;
-            } else {
-                fprintf(fp, "/***** manual: vl_api_%s_t_print  *****/\n\n",
-                        (i8 *) np->data[0]);
-            }
-        }
-        np = np->peer;
-    }
-    fprintf(fp, "#endif /* vl_printfun */\n\n");
-}
-
-void generate_endianfun(YYSTYPE a1, FILE *fp)
-{
-    node_t *np = (node_t *)a1;
-    node_vft_t *vftp;
-
-    fprintf(fp, "\n/****** Endian swap functions *****/\n\n");
-    fprintf(fp, "#ifdef vl_endianfun\n\n");
-    fprintf(fp, "#undef clib_net_to_host_uword\n");
-    fprintf(fp, "#ifdef LP64\n");
-    fprintf(fp, "#define clib_net_to_host_uword clib_net_to_host_u64\n");
-    fprintf(fp, "#else\n");
-    fprintf(fp, "#define clib_net_to_host_uword clib_net_to_host_u32\n");
-    fprintf(fp, "#endif\n\n");
-
-    /* Walk the top-level node-list */
-    while (np) {
-        if (np->type == NODE_DEFINE) {
-            if (!(np->flags & NODE_FLAG_MANUAL_ENDIAN)) {
-                fprintf(fp, 
-               "static inline void vl_api_%s_t_endian (vl_api_%s_t *a)\n{\n",
-                        (i8 *) np->data[0], (i8 *) np->data[0]);
-                indent += 4;
-                /* Yeah, this is pedantic */
-                vftp = the_vft[np->type];
-                vftp->generate(np, ENDIANFUN_PASS, fp);
-                fprintf(fp, "}\n\n");
-                indent -= 4;
-            } else {
-                fprintf(fp, "/***** manual: vl_api_%s_t_endian  *****/\n\n",
-                        (i8 *) np->data[0]);
-            }
-        }
-        np = np->peer;
-    }
-    fprintf(fp, "#endif /* vl_endianfun */\n\n");
-}
-
-void add_msg_ids(YYSTYPE a1)
-{
-    node_t *np = (node_t *)a1;
-    node_t *new_u16;
-    node_t *new_vbl;
-
-    /* Walk the top-level node-list */
-    while (np) {
-        if (np->type == NODE_DEFINE) {
-            if (!(np->flags & NODE_FLAG_TYPEONLY)) {
-               /* add the parse tree for "u16 _vl_msg_id" */
-                new_u16 = make_node(NODE_U16);
-                new_u16->peer = np->deeper;
-                np->deeper = new_u16;
-                new_vbl = make_node(NODE_SCALAR);
-                new_vbl->data[0] = sxerox("_vl_msg_id");
-                new_u16->deeper = new_vbl;
-           }
-        }
-        np = np->peer;
-    }
-}
-
-/*
- * add_scalar_vbl (char *name)
- */
-YYSTYPE add_version (YYSTYPE a1, YYSTYPE a2, YYSTYPE a3)
-{
-    node_t *np;
-
-    np = make_node(NODE_VERSION);
-    np->data[0] = (void *) a1;
-    np->data[1] = (void *) a2;
-    np->data[2] = (void *) a3;
-    return ((YYSTYPE) np);
-}
-
-void generate_python_msg_definitions(YYSTYPE a1, FILE *fp)
-{
-    node_t *np = (node_t *)a1;
-    node_vft_t *vftp;
-    fprintf (fp, "messages = [\n");
-    /* Walk the top-level node-list */
-    while (np) {
-      if (np->type == NODE_DEFINE && !(np->flags & NODE_FLAG_TYPEONLY)) {
-        /* Yeah, this is pedantic */
-        vftp = the_vft[np->type];
-        vftp->generate(np, PYTHON_PASS, fp);
-      }
-      np = np->peer;
-    }
-    fprintf (fp, "\n]\n");
-}
-
-static bool
-is_typeonly_check(node_t *np, bool typeonly)
-{
-  bool is_typeonly = (np->flags & NODE_FLAG_TYPEONLY);
-  return (is_typeonly == typeonly);
-}
-
-static void
-generate_json_definitions(YYSTYPE a1, FILE *fp, bool typeonly)
-{
-    node_t *np = (node_t *)a1;
-    node_vft_t *vftp;
-    indent_me(fp);
-    if (typeonly)
-      fprintf (fp, "\"types\" : [\n");
-    else
-      fprintf (fp, "\"messages\" : [\n");
-
-    /* Walk the top-level node-list */
-    bool comma = false;
-    indent += 4;
-    while (np) {
-      if (np->type == NODE_DEFINE && is_typeonly_check(np, typeonly)) {
-        /* Yeah, this is pedantic */
-        vftp = the_vft[np->type];
-       indent_me(fp);
-        vftp->generate(np, JSON_PASS, fp);
-       comma = true;
-      }
-      np = np->peer;
-      if (comma && np &&
-         np->type == NODE_DEFINE && is_typeonly_check(np, typeonly))
-       fprintf (fp, ",\n");
-
-    }
-    indent -= 4;
-    fprintf (fp, "\n");
-    indent_me(fp);
-    fprintf(fp, "]");
-}
-
-void generate_python_typeonly_definitions(YYSTYPE a1, FILE *fp)
-{
-    node_t *np = (node_t *)a1;
-    node_vft_t *vftp;
-    fprintf (fp, "types = [\n");
-    /* Walk the top-level node-list */
-    while (np) {
-      if (np->type == NODE_DEFINE && (np->flags & NODE_FLAG_TYPEONLY)) {
-        vftp = the_vft[np->type];
-        vftp->generate(np, PYTHON_PASS, fp);
-      }
-      np = np->peer;
-    }
-    fprintf (fp, "\n]\n");
-}
-
-void generate_python(YYSTYPE a1, FILE *fp)
-{
-    generate_python_typeonly_definitions(a1, fp);
-    generate_python_msg_definitions(a1, fp);
-
-    /*
-     * API CRC signature
-     */
-    fprintf (fp, "vl_api_version = 0x%08x\n\n", (unsigned int)input_crc);
-}
-
-void generate_json(YYSTYPE a1, FILE *fp)
-{
-    fprintf (fp, "{\n");
-    indent += 4;
-    generate_json_definitions(a1, fp, true);
-    fprintf (fp, ",\n");
-    generate_json_definitions(a1, fp, false);
-
-    /*
-     * API CRC signature
-     */
-    fprintf (fp, ",\n\"vl_api_version\" :\"0x%08x\"\n",
-            (unsigned int)input_crc);
-    fprintf (fp, "}\n");
-}
-
-void generate_version_tuple(YYSTYPE a1, FILE *fp)
-{
-    node_t *this = (node_t *)a1;
-
-    fprintf(fp, "/****** Version tuple *****/\n\n");
-
-    fprintf(fp, "#ifdef vl_api_version_tuple\n\n");
-
-    /* Walk the top-level node-list */
-    while (this) {
-        if (this->type == NODE_VERSION) {
-            fprintf (fp, "vl_api_version_tuple(%s, %d, %d, %d)\n",
-                     fixed_name, IDATA0, IDATA1, IDATA2);
-        }
-        this = this->peer;
-    }
-
-    fprintf(fp, "\n#endif /* vl_api_version_tuple */\n\n");
-}
-
-void generate(YYSTYPE a1)
-{
-    if (dump_tree) {
-        dump((node_t *)a1);
-    }
-
-    add_msg_ids(a1);
-
-    if (ofp) {
-        generate_top_boilerplate(ofp);
-
-        generate_msg_ids(a1, ofp);
-        generate_msg_names(a1, ofp);
-        generate_msg_name_crc_list(a1, ofp);
-        generate_typedefs(a1, ofp);
-        generate_uniondefs(a1, ofp);
-        generate_printfun(a1, ofp);
-        generate_endianfun(a1, ofp);
-        generate_version_tuple(a1, ofp);
-        
-        generate_bottom_boilerplate(ofp);
-    }
-    if (pythonfp) {
-      generate_python(a1, pythonfp);
-    }
-    if (jsonfp) {
-      generate_json(a1, jsonfp);
-    }
-}
diff --git a/src/tools/vppapigen/node.h b/src/tools/vppapigen/node.h
deleted file mode 100644 (file)
index 58570d8..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- *------------------------------------------------------------------
- * node.h - definitions for an API generator
- *
- * Copyright (c) 2004-2009 Cisco and/or its affiliates.
- * 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.
- *------------------------------------------------------------------
- */
-
-#ifndef _node_h_
-#define _node_h_
-
-/*
- * Global prototypes
- */
-
-char *sxerox (const char *s);
-
-enum node_subclass {  /* WARNING: indices must match the vft... */
-    NODE_ILLEGAL=0,
-    NODE_U8,
-    NODE_U16,
-    NODE_U32,
-    NODE_U64,
-    NODE_I8,
-    NODE_I16,
-    NODE_I32,
-    NODE_I64,
-    NODE_F64,
-    NODE_PACKED,
-    NODE_DEFINE,
-    NODE_UNION,
-    NODE_SCALAR,
-    NODE_VECTOR,
-    NODE_COMPLEX,
-    NODE_NOVERSION,
-    NODE_VERSION,
-    NODE_UWORD,
-    NODE_N_TYPES,  /* number of node types with VFT's */
-
-    /* pseudo-node(s) used in the lexer keyword table, but
-       NOT in need of a VFT... */
-    NODE_TYPEONLY,
-    NODE_MANUAL_PRINT,
-    NODE_MANUAL_ENDIAN,
-    NODE_DONT_TRACE,
-    NODE_AUTOREPLY,
-};
-
-enum passid {
-    TYPEDEF_PASS=1,
-    UNION_DEF_PASS,
-    ENDIANFUN_PASS,
-    PRINTFUN_PASS,
-    PYTHON_PASS,
-    JSON_PASS,
-};
-
-extern void *make_node (enum node_subclass type);
-
-typedef struct node_ {
-    enum node_subclass type;
-    struct node_ *peer;
-    struct node_ *deeper;
-    int flags;
-    void *data[4];
-} node_t;
-
-/* To shut up gcc-4.2.x warnings */
-#define CDATA0 ((char *)(this->data[0]))
-#define CDATA1 ((char *)(this->data[0]))
-#define CDATA2 ((char *)(this->data[2]))
-#define CDATA3 ((char *)(this->data[3]))
-
-#define IDATA0 ((int)(uword)(this->data[0]))
-#define IDATA1 ((int)(uword)(this->data[1]))
-#define IDATA2 ((int)(uword)(this->data[2]))
-#define IDATA3 ((int)(uword)(this->data[3]))
-
-#define NODE_FLAG_MANUAL_PRINT (1<<0)
-#define NODE_FLAG_MANUAL_ENDIAN (1<<1)
-#define NODE_FLAG_TYPEONLY (1<<3)
-#define NODE_FLAG_DONT_TRACE (1<<4)
-#define NODE_FLAG_AUTOREPLY (1<<5)
-
-typedef struct node_vft_ {
-    void (*print)(struct node_ *);
-    void (*generate)(struct node_ *, enum passid id, FILE *ofp);
-    char *endian_converter;
-} node_vft_t;    
-
-#endif /* _node_h */
diff --git a/src/tools/vppapigen/test_vppapigen.py b/src/tools/vppapigen/test_vppapigen.py
new file mode 100755 (executable)
index 0000000..09187f4
--- /dev/null
@@ -0,0 +1,80 @@
+#!/usr/bin/env python
+
+import unittest
+from vppapigen import VPPAPI, Option, ParseError
+
+# TODO
+# - test parsing of options, typedefs, enums, defines, CRC
+# - test JSON, C output
+
+
+class TestVersion(unittest.TestCase):
+    @classmethod
+    def setUpClass(cls):
+        cls.parser = VPPAPI()
+
+    def test_version(self):
+        version_string = 'option version = "1.0.0";'
+        r = self.parser.parse_string(version_string)
+        self.assertTrue(isinstance(r[0], Option))
+
+
+class TestTypedef(unittest.TestCase):
+    @classmethod
+    def setUpClass(cls):
+        cls.parser = VPPAPI()
+
+    def test_duplicatetype(self):
+        test_string = '''
+        typeonly define foo1 { u8 dummy; };
+        typeonly define foo1 { u8 dummy; };
+        '''
+        self.assertRaises(KeyError, self.parser.parse_string, test_string)
+
+
+class TestDefine(unittest.TestCase):
+    @classmethod
+    def setUpClass(cls):
+        cls.parser = VPPAPI()
+
+    def test_unknowntype(self):
+        test_string = 'define foo { foobar foo;};'
+        self.assertRaises(ParseError, self.parser.parse_string, test_string)
+        test_string = 'define { u8 foo;};'
+        self.assertRaises(ParseError, self.parser.parse_string, test_string)
+
+    def test_flags(self):
+        test_string = '''
+          manual_print dont_trace manual_endian define foo { u8 foo; };
+        '''
+        r = self.parser.parse_string(test_string)
+        self.assertIsNotNone(r)
+        s = self.parser.process(r)
+        self.assertIsNotNone(s)
+        for d in s['defines']:
+            self.assertTrue(d.dont_trace)
+            self.assertTrue(d.manual_endian)
+            self.assertTrue(d.manual_print)
+            self.assertFalse(d.autoreply)
+
+        test_string = '''
+          nonexisting_flag define foo { u8 foo; };
+        '''
+        self.assertRaises(ParseError, self.parser.parse_string, test_string)
+
+
+class TestService(unittest.TestCase):
+    @classmethod
+    def setUpClass(cls):
+        cls.parser = VPPAPI()
+
+    def test_service(self):
+        test_string = '''
+         service foo { rpc foo (show_version) returns (show_version) };
+        '''
+        r = self.parser.parse_string(test_string)
+        print('R', r)
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/src/tools/vppapigen/vppapigen b/src/tools/vppapigen/vppapigen
new file mode 120000 (symlink)
index 0000000..97b143f
--- /dev/null
@@ -0,0 +1 @@
+vppapigen.py
\ No newline at end of file
diff --git a/src/tools/vppapigen/vppapigen.py b/src/tools/vppapigen/vppapigen.py
new file mode 100755 (executable)
index 0000000..81f26fe
--- /dev/null
@@ -0,0 +1,745 @@
+#!/usr/bin/env python
+
+from __future__ import print_function
+import ply.lex as lex
+import ply.yacc as yacc
+import sys
+import argparse
+import logging
+import binascii
+import os
+
+#
+# VPP API language
+#
+
+# Global dictionary of new types (including enums)
+global_types = {}
+
+
+def global_type_add(name):
+    '''Add new type to the dictionary of types '''
+    type_name = 'vl_api_' + name + '_t'
+    if type_name in global_types:
+        raise KeyError('Type is already defined: {}'.format(name))
+    global_types[type_name] = True
+
+
+# All your trace are belong to us!
+def exception_handler(exception_type, exception, traceback):
+    print ("%s: %s" % (exception_type.__name__, exception))
+
+
+#
+# Lexer
+#
+class VPPAPILexer(object):
+    def __init__(self, filename):
+        self.filename = filename
+
+    reserved = {
+        'service': 'SERVICE',
+        'rpc': 'RPC',
+        'returns': 'RETURNS',
+        'stream': 'STREAM',
+        'events': 'EVENTS',
+        'define': 'DEFINE',
+        'typedef': 'TYPEDEF',
+        'enum': 'ENUM',
+        'typeonly': 'TYPEONLY',
+        'manual_print': 'MANUAL_PRINT',
+        'manual_endian': 'MANUAL_ENDIAN',
+        'dont_trace': 'DONT_TRACE',
+        'autoreply': 'AUTOREPLY',
+        'option': 'OPTION',
+        'u8': 'U8',
+        'u16': 'U16',
+        'u32': 'U32',
+        'u64': 'U64',
+        'i8': 'I8',
+        'i16': 'I16',
+        'i32': 'I32',
+        'i64': 'I64',
+        'f64': 'F64',
+        'bool': 'BOOL',
+        'string': 'STRING',
+        'import': 'IMPORT',
+        'true': 'TRUE',
+        'false': 'FALSE',
+    }
+
+    tokens = ['STRING_LITERAL',
+              'ID', 'NUM'] + list(reserved.values())
+
+    t_ignore_LINE_COMMENT = '//.*'
+
+    def t_NUM(self, t):
+        r'0[xX][0-9a-fA-F]+|\d+'
+        base = 16 if t.value.startswith('0x') else 10
+        t.value = int(t.value, base)
+        return t
+
+    def t_ID(self, t):
+        r'[a-zA-Z_][a-zA-Z_0-9]*'
+        # Check for reserved words
+        t.type = VPPAPILexer.reserved.get(t.value, 'ID')
+        return t
+
+    # C string
+    def t_STRING_LITERAL(self, t):
+        r'\"([^\\\n]|(\\.))*?\"'
+        t.value = str(t.value).replace("\"", "")
+        return t
+
+    # C or C++ comment (ignore)
+    def t_comment(self, t):
+        r'(/\*(.|\n)*?\*/)|(//.*)'
+        t.lexer.lineno += t.value.count('\n')
+
+    # Error handling rule
+    def t_error(self, t):
+        raise ParseError("Illegal character '{}' ({})"
+                         "in {}: line {}".format(t.value[0],
+                                                 hex(ord(t.value[0])),
+                                                 self.filename,
+                                                 t.lexer.lineno))
+        t.lexer.skip(1)
+
+    # Define a rule so we can track line numbers
+    def t_newline(self, t):
+        r'\n+'
+        t.lexer.lineno += len(t.value)
+
+    literals = ":{}[];=.,"
+
+    # A string containing ignored characters (spaces and tabs)
+    t_ignore = ' \t'
+
+
+class Iterator(type):
+    def __iter__(self):
+        return self.iter()
+
+
+class Service():
+    def __init__(self, caller, reply, events=[], stream=False):
+        self.caller = caller
+        self.reply = reply
+        self.stream = stream
+        self.events = events
+
+
+class Typedef():
+    def __init__(self, name, flags, block):
+        self.name = name
+        self.flags = flags
+        self.block = block
+        self.crc = binascii.crc32(str(block)) & 0xffffffff
+        global_type_add(name)
+
+    def __repr__(self):
+        return self.name + str(self.flags) + str(self.block)
+
+
+class Define():
+    def __init__(self, name, flags, block):
+        self.name = name
+        self.flags = flags
+        self.block = block
+        self.crc = binascii.crc32(str(block)) & 0xffffffff
+        self.typeonly = False
+        self.dont_trace = False
+        self.manual_print = False
+        self.manual_endian = False
+        self.autoreply = False
+        self.singular = False
+        for f in flags:
+            if f == 'typeonly':
+                self.typeonly = True
+                global_type_add(name)
+            elif f == 'dont_trace':
+                self.dont_trace = True
+            elif f == 'manual_print':
+                self.manual_print = True
+            elif f == 'manual_endian':
+                self.manual_endian = True
+            elif f == 'autoreply':
+                self.autoreply = True
+
+        for b in block:
+            if isinstance(b, Option):
+                if b[1] == 'singular' and b[2] == 'true':
+                    self.singular = True
+                block.remove(b)
+
+    def __repr__(self):
+        return self.name + str(self.flags) + str(self.block)
+
+
+class Enum():
+    def __init__(self, name, block, enumtype='u32'):
+        self.name = name
+        self.enumtype = enumtype
+        count = 0
+        for i, b in enumerate(block):
+            if type(b) is list:
+                count = b[1]
+            else:
+                count += 1
+                block[i] = [b, count]
+
+        self.block = block
+        self.crc = binascii.crc32(str(block)) & 0xffffffff
+        global_type_add(name)
+
+    def __repr__(self):
+        return self.name + str(self.block)
+
+
+class Import():
+    def __init__(self, filename):
+        self.filename = filename
+
+        # Deal with imports
+        parser = VPPAPI(filename=filename)
+        dirlist = dirlist_get()
+        f = filename
+        for dir in dirlist:
+            f = os.path.join(dir, filename)
+            if os.path.exists(f):
+                break
+        with open(f) as fd:
+            self.result = parser.parse_file(fd, None)
+
+    def __repr__(self):
+        return self.filename
+
+
+class Option():
+    def __init__(self, option):
+        self.option = option
+        self.crc = binascii.crc32(str(option)) & 0xffffffff
+
+    def __repr__(self):
+        return str(self.option)
+
+    def __getitem__(self, index):
+        return self.option[index]
+
+
+class Array():
+    def __init__(self, fieldtype, name, length):
+        self.type = 'Array'
+        self.fieldtype = fieldtype
+        self.fieldname = name
+        if type(length) is str:
+            self.lengthfield = length
+            self.length = 0
+        else:
+            self.length = length
+            self.lengthfield = None
+
+    def __repr__(self):
+        return str([self.fieldtype, self.fieldname, self.length,
+                    self.lengthfield])
+
+
+class Field():
+    def __init__(self, fieldtype, name):
+        self.type = 'Field'
+        self.fieldtype = fieldtype
+        self.fieldname = name
+
+    def __repr__(self):
+        return str([self.fieldtype, self.fieldname])
+
+
+class Coord(object):
+    """ Coordinates of a syntactic element. Consists of:
+            - File name
+            - Line number
+            - (optional) column number, for the Lexer
+    """
+    __slots__ = ('file', 'line', 'column', '__weakref__')
+
+    def __init__(self, file, line, column=None):
+        self.file = file
+        self.line = line
+        self.column = column
+
+    def __str__(self):
+        str = "%s:%s" % (self.file, self.line)
+        if self.column:
+            str += ":%s" % self.column
+        return str
+
+
+class ParseError(Exception):
+    pass
+
+
+#
+# Grammar rules
+#
+class VPPAPIParser(object):
+    tokens = VPPAPILexer.tokens
+
+    def __init__(self, filename, logger):
+        self.filename = filename
+        self.logger = logger
+        self.fields = []
+
+    def _parse_error(self, msg, coord):
+        raise ParseError("%s: %s" % (coord, msg))
+
+    def _parse_warning(self, msg, coord):
+        if self.logger:
+            self.logger.warning("%s: %s" % (coord, msg))
+
+    def _coord(self, lineno, column=None):
+        return Coord(
+                file=self.filename,
+                line=lineno, column=column)
+
+    def _token_coord(self, p, token_idx):
+        """ Returns the coordinates for the YaccProduction object 'p' indexed
+            with 'token_idx'. The coordinate includes the 'lineno' and
+            'column'. Both follow the lex semantic, starting from 1.
+        """
+        last_cr = p.lexer.lexdata.rfind('\n', 0, p.lexpos(token_idx))
+        if last_cr < 0:
+            last_cr = -1
+        column = (p.lexpos(token_idx) - (last_cr))
+        return self._coord(p.lineno(token_idx), column)
+
+    def p_slist(self, p):
+        '''slist : stmt
+                 | slist stmt'''
+        if len(p) == 2:
+            p[0] = [p[1]]
+        else:
+            p[0] = p[1] + [p[2]]
+
+    def p_stmt(self, p):
+        '''stmt : define
+                | typedef
+                | option
+                | import
+                | enum
+                | service'''
+        p[0] = p[1]
+
+    def p_import(self, p):
+        '''import : IMPORT STRING_LITERAL ';' '''
+        p[0] = Import(p[2])
+
+    def p_service(self, p):
+        '''service : SERVICE '{' service_statements '}' ';' '''
+        p[0] = p[3]
+
+    def p_service_statements(self, p):
+        '''service_statements : service_statement
+                        | service_statements service_statement'''
+        if len(p) == 2:
+            p[0] = [p[1]]
+        else:
+            p[0] = p[1] + [p[2]]
+
+    def p_service_statement(self, p):
+        '''service_statement : RPC ID RETURNS ID ';'
+                             | RPC ID RETURNS STREAM ID ';'
+                             | RPC ID RETURNS ID EVENTS event_list ';' '''
+        if len(p) == 8:
+            p[0] = Service(p[2], p[4], p[6])
+        elif len(p) == 7:
+            p[0] = Service(p[2], p[5], stream=True)
+        else:
+            p[0] = Service(p[2], p[4])
+
+    def p_event_list(self, p):
+        '''event_list : events
+                      | event_list events '''
+        if len(p) == 2:
+            p[0] = [p[1]]
+        else:
+            p[0] = p[1] + [p[2]]
+
+    def p_event(self, p):
+        '''events : ID
+                  | ID ',' '''
+        p[0] = p[1]
+
+    def p_enum(self, p):
+        '''enum : ENUM ID '{' enum_statements '}' ';' '''
+        p[0] = Enum(p[2], p[4])
+
+    def p_enum_type(self, p):
+        ''' enum : ENUM ID ':' enum_size '{' enum_statements '}' ';' '''
+        if len(p) == 9:
+            p[0] = Enum(p[2], p[6], enumtype=p[4])
+        else:
+            p[0] = Enum(p[2], p[4])
+
+    def p_enum_size(self, p):
+        ''' enum_size : U8
+                      | U16
+                      | U32 '''
+        p[0] = p[1]
+
+    def p_define(self, p):
+        '''define : DEFINE ID '{' block_statements_opt '}' ';' '''
+        self.fields = []
+        p[0] = Define(p[2], [], p[4])
+
+    def p_define_flist(self, p):
+        '''define : flist DEFINE ID '{' block_statements_opt '}' ';' '''
+        p[0] = Define(p[3], p[1], p[5])
+
+    def p_flist(self, p):
+        '''flist : flag
+                 | flist flag'''
+        if len(p) == 2:
+            p[0] = [p[1]]
+        else:
+            p[0] = p[1] + [p[2]]
+
+    def p_flag(self, p):
+        '''flag : MANUAL_PRINT
+                | MANUAL_ENDIAN
+                | DONT_TRACE
+                | TYPEONLY
+                | AUTOREPLY'''
+        if len(p) == 1:
+            return
+        p[0] = p[1]
+
+    def p_typedef(self, p):
+        '''typedef : TYPEDEF ID '{' block_statements_opt '}' ';' '''
+        p[0] = Typedef(p[2], [], p[4])
+
+    def p_block_statements_opt(self, p):
+        '''block_statements_opt : block_statements'''
+        p[0] = p[1]
+
+    def p_block_statements(self, p):
+        '''block_statements : block_statement
+                            | block_statements block_statement'''
+        if len(p) == 2:
+            p[0] = [p[1]]
+        else:
+            p[0] = p[1] + [p[2]]
+
+    def p_block_statement(self, p):
+        '''block_statement : declaration
+                           | option '''
+        p[0] = p[1]
+
+    def p_enum_statements(self, p):
+        '''enum_statements : enum_statement
+                            | enum_statements enum_statement'''
+        if len(p) == 2:
+            p[0] = [p[1]]
+        else:
+            p[0] = p[1] + [p[2]]
+
+    def p_enum_statement(self, p):
+        '''enum_statement : ID '=' NUM ','
+                          | ID ',' '''
+        if len(p) == 5:
+            p[0] = [p[1], p[3]]
+        else:
+            p[0] = p[1]
+
+    def p_declaration(self, p):
+        '''declaration : type_specifier ID ';' '''
+        if len(p) != 4:
+            self._parse_error('ERROR')
+        self.fields.append(p[2])
+        p[0] = Field(p[1], p[2])
+
+    def p_declaration_array(self, p):
+        '''declaration : type_specifier ID '[' NUM ']' ';'
+                       | type_specifier ID '[' ID ']' ';' '''
+        if len(p) != 7:
+            return self._parse_error(
+                'array: %s' % p.value,
+                self._coord(lineno=p.lineno))
+
+        # Make this error later
+        if type(p[4]) is int and p[4] == 0:
+            # XXX: Line number is wrong
+            self._parse_warning('Old Style VLA: {} {}[{}];'
+                                .format(p[1], p[2], p[4]),
+                                self._token_coord(p, 1))
+
+        if type(p[4]) is str and p[4] not in self.fields:
+            # Verify that length field exists
+            self._parse_error('Missing length field: {} {}[{}];'
+                              .format(p[1], p[2], p[4]),
+                              self._token_coord(p, 1))
+        p[0] = Array(p[1], p[2], p[4])
+
+    def p_option(self, p):
+        '''option : OPTION ID '=' assignee ';' '''
+        p[0] = Option([p[1], p[2], p[4]])
+
+    def p_assignee(self, p):
+        '''assignee : NUM
+                    | TRUE
+                    | FALSE
+                    | STRING_LITERAL '''
+        p[0] = p[1]
+
+    def p_type_specifier(self, p):
+        '''type_specifier : U8
+                          | U16
+                          | U32
+                          | U64
+                          | I8
+                          | I16
+                          | I32
+                          | I64
+                          | F64
+                          | BOOL
+                          | STRING'''
+        p[0] = p[1]
+
+    # Do a second pass later to verify that user defined types are defined
+    def p_typedef_specifier(self, p):
+        '''type_specifier : ID '''
+        if p[1] not in global_types:
+            self._parse_error('Undefined type: {}'.format(p[1]),
+                              self._token_coord(p, 1))
+        p[0] = p[1]
+
+    # Error rule for syntax errors
+    def p_error(self, p):
+        if p:
+            self._parse_error(
+                'before: %s' % p.value,
+                self._coord(lineno=p.lineno))
+        else:
+            self._parse_error('At end of input', self.filename)
+
+
+class VPPAPI(object):
+
+    def __init__(self, debug=False, filename='', logger=None):
+        self.lexer = lex.lex(module=VPPAPILexer(filename), debug=debug)
+        self.parser = yacc.yacc(module=VPPAPIParser(filename, logger),
+                                tabmodule='vppapigentab', debug=debug)
+        self.logger = logger
+
+    def parse_string(self, code, debug=0, lineno=1):
+        self.lexer.lineno = lineno
+        return self.parser.parse(code, lexer=self.lexer, debug=debug)
+
+    def parse_file(self, fd, debug=0):
+        data = fd.read()
+        return self.parse_string(data, debug=debug)
+
+    def autoreply_block(self, name):
+        block = [Field('u32', 'context'),
+                 Field('i32', 'retval')]
+        return Define(name + '_reply', [], block)
+
+    def process(self, objs):
+        s = {}
+        s['defines'] = []
+        s['typedefs'] = []
+        s['imports'] = []
+        s['options'] = {}
+        s['enums'] = []
+        s['services'] = []
+
+        for o in objs:
+            if isinstance(o, Define):
+                if o.typeonly:
+                    s['typedefs'].append(o)
+                else:
+                    s['defines'].append(o)
+                    if o.autoreply:
+                        s['defines'].append(self.autoreply_block(o.name))
+            elif isinstance(o, Option):
+                s['options'][o[1]] = o[2]
+            elif isinstance(o, Enum):
+                s['enums'].append(o)
+            elif isinstance(o, Typedef):
+                s['typedefs'].append(o)
+            elif type(o) is list:
+                for o2 in o:
+                    if isinstance(o2, Service):
+                        s['services'].append(o2)
+
+        # Create services implicitly
+        msgs = {d.name: d for d in s['defines']}
+        svcs = {s.caller: s for s in s['services']}
+
+        for service in svcs:
+            if service not in msgs:
+                raise ValueError('Service definition refers to unknown message'
+                                 ' definition: {}'.format(service))
+            if svcs[service].reply not in msgs:
+                raise ValueError('Service definition refers to unknown message'
+                                 ' definition in reply: {}'
+                                 .format(svcs[service].reply))
+            for event in svcs[service].events:
+                if event not in msgs:
+                    raise ValueError('Service definition refers to unknown '
+                                     'event: {} in message: {}'
+                                     .format(event, service))
+
+        for d in msgs:
+            if msgs[d].singular is True:
+                continue
+            if d.endswith('_counters'):
+                continue
+            if d.endswith('_reply'):
+                if d[:-6] in svcs:
+                    continue
+                if d[:-6] not in msgs:
+                    self.logger.warning('{} missing calling message'
+                                        .format(d))
+                continue
+            if d.endswith('_dump'):
+                if d in svcs:
+                    continue
+                if d[:-5]+'_details' in msgs:
+                    s['services'].append(Service(d, d[:-5]+'_details',
+                                                 stream=True))
+                else:
+                    self.logger.error('{} missing details message'
+                                      .format(d))
+                continue
+
+            if d.endswith('_details'):
+                if d[:-8]+'_dump' not in msgs:
+                    self.logger.error('{} missing dump message'
+                                      .format(d))
+                continue
+
+            if d in svcs:
+                continue
+            if d+'_reply' in msgs:
+                s['services'].append(Service(d, d+'_reply'))
+            else:
+                self.logger.warning('{} missing reply message ({})'
+                                    .format(d, d+'_reply'))
+                s['services'].append(Service(d, None))
+
+        return s
+
+    def process_imports(self, objs):
+        for o in objs:
+            if isinstance(o, Import):
+                return objs + self.process_imports(o.result)
+        return objs
+
+
+# Add message ids to each message.
+def add_msg_id(s):
+    for o in s:
+        o.block.insert(0, Field('u16', '_vl_msg_id'))
+    return s
+
+
+def getcrc(s):
+    return binascii.crc32(str(s)) & 0xffffffff
+
+
+dirlist = []
+
+
+def dirlist_add(dirs):
+    global dirlist
+    if dirs:
+        dirlist = dirlist + dirs
+
+
+def dirlist_get():
+    return dirlist
+
+
+#
+# Main
+#
+def main():
+    logging.basicConfig()
+    log = logging.getLogger('vppapigen')
+
+    cliparser = argparse.ArgumentParser(description='VPP API generator')
+    cliparser.add_argument('--pluginpath', default=""),
+    cliparser.add_argument('--includedir', action='append'),
+    cliparser.add_argument('--input', type=argparse.FileType('r'),
+                           default=sys.stdin)
+    cliparser.add_argument('--output', nargs='?', type=argparse.FileType('w'),
+                           default=sys.stdout)
+
+    cliparser.add_argument('output_module', nargs='?', default='C')
+    cliparser.add_argument('--debug', action='store_true')
+    cliparser.add_argument('--show-name', nargs=1)
+    args = cliparser.parse_args()
+
+    dirlist_add(args.includedir)
+    if not args.debug:
+        sys.excepthook = exception_handler
+
+    # Filename
+    if args.show_name:
+        filename = args.show_name[0]
+    elif args.input != sys.stdin:
+        filename = args.input.name
+    else:
+        filename = ''
+
+    parser = VPPAPI(debug=args.debug, filename=filename, logger=log)
+    result = parser.parse_file(args.input, log)
+
+    # Build a list of objects. Hash of lists.
+    result = parser.process_imports(result)
+    s = parser.process(result)
+
+    # Add msg_id field
+    s['defines'] = add_msg_id(s['defines'])
+
+    file_crc = getcrc(s)
+
+    #
+    # Debug
+    if args.debug:
+        import pprint
+        pp = pprint.PrettyPrinter(indent=4)
+        for t in s['defines']:
+            pp.pprint([t.name, t.flags, t.block])
+        for t in s['typedefs']:
+            pp.pprint([t.name, t.flags, t.block])
+
+    #
+    # Generate representation
+    #
+    import imp
+
+    # Default path
+    if not args.pluginpath:
+        pluginpath = os.path.dirname(os.path.realpath(__file__)) + \
+                                     '/../share/vpp/'
+    else:
+        pluginpath = args.pluginpath + '/'
+    module_path = pluginpath + args.output_module + '.py'
+
+    try:
+        plugin = imp.load_source(args.output_module, module_path)
+    except Exception, err:
+        raise Exception('Error importing output plugin: {}, {}'
+                        .format(module_path, err))
+
+    result = plugin.run(filename, s, file_crc)
+    if result:
+        print (result, file=args.output)
+    else:
+        raise Exception('Running plugin failed: {} {}'
+                        .format(filename, result))
+
+
+if __name__ == '__main__':
+    main()
index 20a73f2..fb08f51 100644 (file)
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /*
  * Create a client registration 
index 1c5c578..912c695 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /** \brief Set BFD echo source
     @param client_index - opaque cookie to identify the sender
index c7e9a98..380d297 100644 (file)
@@ -18,7 +18,8 @@
     This file defines vpp BIER control-plane API messages which are generally
     called through a shared memory interface.
 */
-vl_api_version 1.0.0
+option version = "1.0.0";
+import "vnet/fib/fib_types.api";
 
 /** \brief BIER Table Indentifier
     @param bt_set - The BIER set
@@ -63,37 +64,6 @@ define bier_table_details
   vl_api_bier_table_id_t bt_tbl_id;
 };
 
-/** \brief FIB path
-    @param sw_if_index - index of the interface
-    @param weight - The weight, for UCMP
-    @param preference - The preference of the path. lowest preference is prefered
-    @param is_local - local if non-zero, else remote
-    @param is_drop - Drop the packet
-    @param is_udp_encap - The path describes a UDP-o-IP encapsulation.
-    @param afi - the afi of the next hop, IP46_TYPE_IP4=1, IP46_TYPE_IP6=2
-    @param next_hop[16] - the next hop address
-    @param next_hop_id - Used when the path resolves via an object that has a unique
-                         identifier. e.g. the UDP encap object
-
-    WARNING: this type is replicated, pending cleanup completion
-*/
-typeonly define fib_path3
-{
-  u32 sw_if_index;
-  u32 table_id;
-  u8 weight;
-  u8 preference;
-  u8 is_local;
-  u8 is_drop;
-  u8 is_udp_encap;
-  u8 afi;
-  u8 next_hop[16];
-  u32 next_hop_id;
-  u32 rpf_id;
-  u8 n_labels;
-  u32 label_stack[16];
-};
-
 /** \brief BIER Route Add / del route
     @param client_index - opaque cookie to identify the sender
     @param context - sender context, to match reply w/ request
index 532638c..c22d610 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /** \brief Add/Delete classification table request
     @param client_index - opaque cookie to identify the sender
index a11b451..bcdd562 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
  /** \brief cop: enable/disable junk filtration features on an interface
     @param client_index - opaque cookie to identify the sender
index a1b30d5..d7637da 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /** \brief Create host-interface
     @param client_index - opaque cookie to identify the sender
index d2de033..a14753c 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /** \brief Create netmap
     @param client_index - opaque cookie to identify the sender
index 0d86edf..21c3ffb 100644 (file)
@@ -19,7 +19,7 @@
     the Linux kernel TAP device driver
 */
 
-vl_api_version 1.1.0
+option version = "1.1.0";
 
 /** \brief Initialize a new tap interface with the given paramters
     @param client_index - opaque cookie to identify the sender
index 6f21cb6..ccaa87c 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /** \brief vhost-user interface create request
     @param client_index - opaque cookie to identify the sender
index 19650f5..528915a 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.1
+option version = "1.0.1";
 
 /** \brief DHCP Proxy config add / del request
     @param client_index - opaque cookie to identify the sender
index f188b05..4045b81 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
  
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /** \brief enable/disable name resolution
 
index ead7cab..c75ed40 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 define p2p_ethernet_add
 {
@@ -49,4 +49,4 @@ define p2p_ethernet_del_reply
  * Local Variables:
  * eval: (c-set-style "gnu")
  * End:
- */
\ No newline at end of file
+ */
index c371054..96ee724 100644 (file)
@@ -19,7 +19,7 @@
     called through a shared memory interface. 
 */
 
-vl_api_version 1.0.1
+option version = "1.0.1";
 
 /** \brief Feature path enable/disable request
     @param client_index - opaque cookie to identify the sender
diff --git a/src/vnet/fib/fib_types.api b/src/vnet/fib/fib_types.api
new file mode 100644 (file)
index 0000000..61a0898
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ * 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.
+ */
+
+/** \brief FIB path
+    @param sw_if_index - index of the interface
+    @param weight - The weight, for UCMP
+    @param preference - The preference of the path. lowest preference
+    is prefered
+    @param is_local - local if non-zero, else remote
+    @param is_drop - Drop the packet
+    @param is_udp_encap - The path describes a UDP-o-IP encapsulation.
+    @param afi - the afi of the next hop, IP46_TYPE_IP4=1, IP46_TYPE_IP6=2
+    @param next_hop[16] - the next hop address
+    @param next_hop_id - Used when the path resolves via an object
+                         that has a unique identifier. e.g. the UDP
+                         encap object
+*/
+typeonly define fib_path3
+{
+  u32 sw_if_index;
+  u32 table_id;
+  u8 weight;
+  u8 preference;
+  u8 is_local;
+  u8 is_drop;
+  u8 is_udp_encap;
+  u8 afi;
+  u8 next_hop[16];
+  u32 next_hop_id;
+  u32 rpf_id;
+  u8 n_labels;
+  u32 label_stack[16];
+};
index 6c49428..9bd3790 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /** \brief Configure IPFIX exporter process request
     @param client_index - opaque cookie to identify the sender
index 9be4bb3..b48989c 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 define geneve_add_del_tunnel
 {
index 1091835..b410ac9 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 define gre_add_del_tunnel
 {
index fbbb940..a8733d1 100644 (file)
@@ -1,4 +1,4 @@
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /** \brief Set flags on the interface
     @param client_index - opaque cookie to identify the sender
index 54047b6..0da0a61 100644 (file)
@@ -19,7 +19,7 @@
     called through a shared memory interface. 
 */
 
-vl_api_version 1.0.1
+option version = "1.0.1";
 
 /** \brief Add / del table request
            A table can be added multiple times, but need be deleted only once.
index a67b592..4477e5c 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /** \brief Punt traffic to the host
     @param client_index - opaque cookie to identify the sender
index ad6ec4e..770746d 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /** \brief Add / del ipsec gre tunnel request
     @param client_index - opaque cookie to identify the sender
@@ -78,4 +78,4 @@ define ipsec_gre_tunnel_details {
  * eval: (c-set-style "gnu")
  * End:
  */
\ No newline at end of file
index 1b2e4bd..bf2bc60 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /** \brief IPsec: Add/delete Security Policy Database
     @param client_index - opaque cookie to identify the sender
index 0ef7113..5102783 100644 (file)
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-vl_api_version 2.0.0
+option version = "2.0.0";
 
 /** \brief Reply to l2_xconnect_dump 
     @param context - sender context which was passed in the request
index 1ccf71b..f679b75 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /** \brief l2tpv3 tunnel interface create request
     @param client_index - opaque cookie to identify the sender
index 7ec17d9..0e47585 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 typeonly manual_print manual_endian define local_locator
 {
index 6cb2ef3..32ac702 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 typeonly manual_print manual_endian define one_local_locator
 {
index 626038f..09c1e84 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /** \brief GPE locator structure
     @param is_ip4 - whether addr is IPv4 or v6
index acc5f71..2ad80d8 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /** \brief configure global parameter for LLDP
     @param client_index - opaque cookie to identify the sender
index a63703a..a066b68 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.1.0
+option version = "1.1.0";
 
 /** \brief Add MAP domains
     @param client_index - opaque cookie to identify the sender
index 6ed462c..572ac91 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.1
+option version = "1.0.1";
 
 /** \brief Bind/Unbind an MPLS local label to an IP prefix. i.e. create
            a per-prefix label entry.
index 46c9645..8f986cb 100644 (file)
@@ -18,7 +18,7 @@
     This file defines packet-generator interface APIs.
 */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /** \brief PacketGenerator create interface request
     @param client_index - opaque cookie to identify the sender
index 13024dd..8ca0ffb 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /** \brief Add/del policer
     @param client_index - opaque cookie to identify the sender
index 735b826..1c3e84b 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /** \brief client->vpp, attach application to session layer
     @param client_index - opaque cookie to identify the sender
index a0f2915..8cbac7b 100644 (file)
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
  /** \brief Enable/Disable span to mirror traffic from one interface to another
     @param client_index - opaque cookie to identify the sender
index e11dbb7..2c98141 100644 (file)
@@ -13,7 +13,8 @@
  * under the License.
  */
 
-vl_api_version 1.0 .0
+option version = "1.0.0";
+
 /** \brief MPLS SR policy add
     @param client_index - opaque cookie to identify the sender
     @param context - sender context, to match reply w/ request
@@ -22,7 +23,7 @@ vl_api_version 1.0 .0
     @param type is the type of the SR policy. (0.Default // 1.Spray)
     @param segments vector of labels (20bit) composing the segment list
 */
-  autoreply define sr_mpls_policy_add
+autoreply define sr_mpls_policy_add
 {
   u32 client_index;
   u32 context;
index f2f6e78..bc22d61 100644 (file)
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.1
+option version = "1.0.1";
 
 /** \brief IPv6 SR LocalSID add/del request
     @param client_index - opaque cookie to identify the sender
index 093a5a8..05f9aeb 100644 (file)
@@ -12,6 +12,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
+option version = "1.0.0";
  
 /** \brief Configure TCP source addresses, for active-open TCP sessions
 
index 25ee964..9f5e2ec 100644 (file)
@@ -19,7 +19,7 @@
     called through a shared memory interface. 
 */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /** \brief Add / del table request
            A table can be added multiple times, but need be deleted only once.
index 6b1b2b4..861d479 100644 (file)
@@ -19,7 +19,7 @@
     the Linux kernel TAP device driver
 */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /** \brief Initialize a new tap interface with the given paramters 
     @param client_index - opaque cookie to identify the sender
index 6391148..89d3707 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 define vxlan_gpe_add_del_tunnel
 {
@@ -78,4 +78,4 @@ autoreply define sw_interface_set_vxlan_gpe_bypass
  * Local Variables:
  * eval: (c-set-style "gnu")
  * End:
- */
\ No newline at end of file
+ */
index 64850f0..d8ace33 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 define vxlan_add_del_tunnel
 {
index 0c450d6..09f2ee5 100644 (file)
@@ -80,7 +80,7 @@ define japigen
        @echo "  JAPIGEN  $@"
        @rm -rf jvpp-$(1)/target
        @ @srcdir@/jvpp/gen/jvpp_gen.py --plugin_name $(1) --root_dir jvpp-$(1) \
-         -i $(jvpp_$(1)_json_files) > /dev/null
+         -i $(jvpp_$(1)_json_files)
        @find jvpp-$(1)/target -name \*.java > jvpp-$(1).generated.files
        @find @srcdir@/jvpp-$(1) -name \*.java > jvpp-$(1).static.files
        @$(JAVAC) -classpath jvpp-registry/target \
index 0cb006a..22b7f3e 100644 (file)
@@ -19,7 +19,7 @@
     called through a shared memory interface. 
 */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /* 
  * Note: API placement cleanup in progress
index 47b5b3e..d03902e 100644 (file)
@@ -19,7 +19,7 @@
     called through a shared memory interface. 
 */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /** \brief OAM event structure
     @param dst_address[] - 
index 237415a..b429faa 100644 (file)
@@ -18,7 +18,7 @@
     This file defines the stats API 
 */
 
-vl_api_version 1.0.0
+option version = "1.0.0";
 
 /** \brief Want Stats, enable/disable ALL stats updates
     @param client_index - opaque cookie to identify the sender
index fe9ff03..485205b 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-bin_PROGRAMS += vppapigen
+dist_bin_SCRIPTS += tools/vppapigen/vppapigen
 
-tools/vppapigen/gram.h: tools/vppapigen/gram.y
-       @$(YACC) -d @srcdir@/tools/vppapigen/gram.y
-       @mv y.tab.h tools/vppapigen/gram.h
-       @rm y.tab.c
-
-tools/vppapigen/lex.o: tools/vppapigen/gram.h
-tools/vppapigen/node.o: tools/vppapigen/gram.h
-
-vppapigen_SOURCES = tools/vppapigen/gram.y tools/vppapigen/lex.c tools/vppapigen/node.c
-vppapigen_LDADD = libvppinfra.la
-vppapigen_LDFLAGS = -static
-
-CLEANFILES += tools/vppapigen/gram.c tools/vppapigen/gram.h
+dist_pkgdata_SCRIPTS = tools/vppapigen/C.py \
+                       tools/vppapigen/JSON.py
 # vi:syntax=automake