2 *------------------------------------------------------------------
3 * node.c - the api generator's semantic back-end
5 * Copyright (c) 2004-2009 Cisco and/or its affiliates.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at:
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *------------------------------------------------------------------
26 #include <vppinfra/vec.h>
27 #include <vppinfra/hash.h>
32 #define YYSTYPE void *
39 node_vft_t *the_vft[NODE_N_TYPES];
41 static int dont_output_version;
43 static char *fixed_name;
44 static char tmpbuf [MAXNAME];
45 static char *current_def_name;
46 static char *current_union_name;
47 static char *current_type_fmt;
48 static char *current_type_cast;
49 static char current_id;
50 static char current_is_complex;
51 static char *current_endianfun;
52 static char *current_type_name;
54 void indent_me(FILE *ofp)
58 for (i = 0; i < indent; i++)
62 char *uppercase (char *s)
68 while (*s && (cp < tmpbuf + (sizeof(tmpbuf)-1))) {
69 if (*s >= 'a' && *s <= 'z')
70 *cp++ = *s++ - ('a' - 'A');
78 char *lowercase (char *s)
84 while (*s && (cp < tmpbuf + (sizeof(tmpbuf)-1))) {
85 if (*s >= 'A' && *s <= 'Z')
86 *cp++ = *s++ + ('a' - 'A');
94 void primtype_recursive_print(node_t *this, i8 *fmt)
96 fputs((char *)fmt, stdout);
99 node_vft_t *vftp = the_vft[this->deeper->type];
100 vftp->print(this->deeper);
104 void primtype_recursive_generate(node_t *this, enum passid which, FILE *ofp,
105 i8 *type_name, i8 *type_fmt, i8 *type_cast)
109 current_type_name = (char *)type_name;
110 current_type_cast = (char *)type_cast;
114 fputs((char *)type_name, ofp);
119 current_type_fmt = (char *)type_fmt;
123 vftp = the_vft[this->type];
124 current_endianfun = vftp->endian_converter;
128 fputs("('", pythonfp);
129 fputs((char *)type_name, pythonfp);
130 fputs("', ", pythonfp);
134 fprintf(stderr, "primtype_recursive_generate: unimp pass %d\n", which);
139 vftp = the_vft[this->deeper->type];
140 vftp->generate(this->deeper, which, ofp);
144 void node_illegal_print (node_t *this)
146 fprintf(stderr, "node_illegal_print called\n");
150 void node_illegal_generate (node_t *this, enum passid notused, FILE *ofp)
152 fprintf(stderr, "node_illegal_generate called\n");
156 node_vft_t node_illegal_vft = {
158 node_illegal_generate,
162 void node_u8_print (node_t *this)
164 primtype_recursive_print(this, "u8 ");
167 void node_u8_generate (node_t *this, enum passid which, FILE *ofp)
169 primtype_recursive_generate(this, which, ofp, "u8", "%u", "(unsigned)");
172 node_vft_t node_u8_vft = {
178 void node_u16_print (node_t *this)
180 primtype_recursive_print(this, "u16 ");
183 void node_u16_generate (node_t *this, enum passid which, FILE *ofp)
185 primtype_recursive_generate(this, which, ofp, "u16", "%u", "(unsigned)");
188 node_vft_t node_u16_vft = {
191 "clib_net_to_host_u16"
194 void node_u32_print (node_t *this)
196 primtype_recursive_print(this, "u32 ");
199 void node_u32_generate (node_t *this, enum passid which, FILE *ofp)
201 primtype_recursive_generate(this, which, ofp, "u32", "%u", "(unsigned)");
204 node_vft_t node_u32_vft = {
207 "clib_net_to_host_u32",
210 void node_u64_print (node_t *this)
212 primtype_recursive_print(this, "u64 ");
215 void node_u64_generate (node_t *this, enum passid which, FILE *ofp)
217 primtype_recursive_generate(this, which, ofp, "u64", "%llu",
221 node_vft_t node_u64_vft = {
224 "clib_net_to_host_u64"
227 void node_i8_print (node_t *this)
229 primtype_recursive_print(this, "i8 ");
232 void node_i8_generate (node_t *this, enum passid which, FILE *ofp)
234 primtype_recursive_generate(this, which, ofp, "i8", "%d", "(int)");
237 node_vft_t node_i8_vft = {
243 void node_i16_print (node_t *this)
245 primtype_recursive_print(this, "i16 ");
248 void node_i16_generate (node_t *this, enum passid which, FILE *ofp)
250 primtype_recursive_generate(this, which, ofp, "i16", "%d", "(int)");
253 node_vft_t node_i16_vft = {
256 "clib_net_to_host_u16"
259 void node_i32_print (node_t *this)
261 primtype_recursive_print(this, "i32 ");
264 void node_i32_generate (node_t *this, enum passid which, FILE *ofp)
266 primtype_recursive_generate(this, which, ofp, "i32", "%ld", "(long)");
269 node_vft_t node_i32_vft = {
272 "clib_net_to_host_u32"
275 void node_i64_print (node_t *this)
277 primtype_recursive_print(this, "i64 ");
280 void node_i64_generate (node_t *this, enum passid which, FILE *ofp)
282 primtype_recursive_generate(this, which, ofp, "i64", "%lld",
286 node_vft_t node_i64_vft = {
289 "clib_net_to_host_u64"
292 void node_f64_print (node_t *this)
294 primtype_recursive_print(this, "f64 ");
297 void node_f64_generate (node_t *this, enum passid which, FILE *ofp)
299 primtype_recursive_generate(this, which, ofp, "f64", "%.2f",
303 node_vft_t node_f64_vft = {
306 " ", /* FP numbers are sent in host byte order */
310 void node_packed_print (node_t *this)
312 primtype_recursive_print (this, "packed ");
315 void node_packed_generate (node_t *this, enum passid which, FILE *ofp)
317 primtype_recursive_generate(this, which, ofp, "PACKED", "", "");
320 node_vft_t node_packed_vft = {
322 node_packed_generate,
326 void node_define_print (node_t *this)
328 fprintf(stdout, "define %s {\n", CDATA0);
330 node_vft_t *vftp = the_vft[this->deeper->type];
331 fprintf(stdout, " ");
332 vftp->print(this->deeper);
334 fprintf(stdout, "};\n");
337 void node_define_generate (node_t *this, enum passid which, FILE *fp)
339 node_t *child, *save_child;
343 fprintf(fp, "typedef VL_API_PACKED(struct _vl_api_%s {\n", CDATA0);
344 child = this->deeper;
347 node_vft_t *vftp = the_vft[child->type];
349 vftp->generate(child, which, fp);
353 fprintf(fp, "}) vl_api_%s_t;\n\n", CDATA0);
358 child = this->deeper;
360 node_vft_t *vftp = the_vft[child->type];
361 vftp->generate(child, which, fp);
367 fprintf(fp, "('%s',\n", CDATA0);
368 child = this->deeper;
371 node_vft_t *vftp = the_vft[child->type];
373 vftp->generate(child, which, fp);
377 fprintf(fp, "),\n\n");
381 fprintf(stderr, "node_define_generate: unimp pass %d\n", which);
386 node_vft_t node_define_vft = {
388 node_define_generate,
392 void node_union_print (node_t *this)
394 primtype_recursive_print (this, "union ");
397 void node_union_generate (node_t *this, enum passid which, FILE *fp)
405 fprintf(fp, "u8 _%s_which;\n", CDATA0);
407 fprintf(fp, "union _%s {\n", CDATA0);
408 child = this->deeper;
412 node_vft_t *vftp = the_vft[child->type];
414 vftp->generate(child, which, fp);
419 fprintf(fp, "} %s;\n", CDATA0);
424 uelem = this->deeper;
427 fprintf(fp, "switch(a->_%s_which) {\n",
430 current_union_name = CDATA0;
432 /* Walk the list of objects in this union */
434 node_vft_t *vftp = the_vft[uelem->type];
437 fprintf(fp, "case %d:\n", case_id);
440 /* Drill down on each element */
441 vftp->generate(uelem, which, fp);
443 fprintf(fp, "break;\n");
446 current_union_name = 0;
449 fprintf(fp, "default:\n");
452 if (which == PRINTFUN_PASS) {
454 "vl_print(handle, \"WARNING: _%s_which not set.\\n\");\n",
458 fprintf(fp, "break;\n");
465 fprintf(stderr, "node_union_generate: unimp pass %d\n", which);
471 node_vft_t node_union_vft = {
477 void node_scalar_print (node_t *this)
479 fprintf(stdout, "%s", CDATA0);
480 primtype_recursive_print (this, "");
483 void node_scalar_generate (node_t *this, enum passid which, FILE *fp)
485 char *union_prefix = "";
487 if (current_union_name) {
488 sprintf(tmpbuf, "%s.", current_union_name);
489 union_prefix = tmpbuf;
494 fprintf(fp, "%s;\n", CDATA0);
499 if (current_is_complex) {
500 fprintf(fp, "vl_api_%s_t_print(a->%s%s, handle);\n",
501 current_type_name, union_prefix, CDATA0);
503 if (!strcmp(current_type_fmt, "uword")) {
505 "vl_print(handle, \"%s%s: \" _uword_fmt \"\\n\", %s a->%s%s);\n",
506 union_prefix, CDATA0, "(_uword_cast)",
507 union_prefix, CDATA0);
510 "vl_print(handle, \"%s%s: %s\\n\", %s a->%s%s);\n",
511 union_prefix, CDATA0,
512 current_type_fmt, current_type_cast,
513 union_prefix, CDATA0);
520 if (current_is_complex) {
521 fprintf(fp, "vl_api%s_t_endian(a->%s%s);\n",
522 current_type_name, union_prefix, CDATA0);
524 /* Current_endianfun == NULL means e.g. it's a u8... */
525 if (current_endianfun) {
526 fprintf(fp, "a->%s%s = %s(a->%s%s);\n", union_prefix,
527 CDATA0, current_endianfun,
528 union_prefix, CDATA0);
530 fprintf(fp, "/* a->%s%s = a->%s%s (no-op) */\n",
531 union_prefix, CDATA0,
532 union_prefix, CDATA0);
537 fprintf(fp, "'%s'),\n", CDATA0);
541 fprintf(stderr, "node_scalar_generate: unimp pass %d\n", which);
544 fprintf(stderr, "broken recursion in node_scalar_generate\n");
549 node_vft_t node_scalar_vft = {
551 node_scalar_generate,
555 void node_vector_print (node_t *this)
557 primtype_recursive_print (this, "vector ");
560 void node_vector_generate (node_t *this, enum passid which, FILE *fp)
562 char *union_prefix = "";
564 if (current_union_name) {
565 sprintf(tmpbuf, "%s.", current_union_name);
566 union_prefix = tmpbuf;
571 fprintf(fp, "%s[%d];\n", CDATA0, IDATA1);
575 /* Don't bother about "u8 data [0];" et al. */
583 fprintf(fp, "int _i;\n");
585 fprintf(fp, "for (_i = 0; _i < %d; _i++) {\n",
589 if (current_is_complex) {
590 fprintf(fp, "vl_print(handle, \"%s%s[%%d]: ",
591 union_prefix, CDATA0);
593 "vl_print_%s (handle, a->%s%s[_i]);\n",
594 CDATA0, union_prefix, CDATA0);
597 "vl_print(handle, \"%s%s[%%d]: %s\\n\", _i, a->%s%s[_i]);\n",
598 union_prefix, CDATA0,
600 union_prefix, CDATA0);
611 /* Don't bother about "u8 data [0];" et al. */
614 /* If this is a simple endian swap, but the endian swap method is a no-op,
615 * then indicate this is a no-op in a comment.
617 if (!current_is_complex && current_endianfun == NULL) {
619 fprintf(fp, "/* a->%s%s[0..%d] = a->%s%s[0..%d] (no-op) */\n",
620 union_prefix, CDATA0, IDATA1 - 1,
621 union_prefix, CDATA0, IDATA1 - 1);
629 fprintf(fp, "int _i;\n");
631 fprintf(fp, "for (_i = 0; _i < %d; _i++) {\n",
635 if (current_is_complex) {
637 "vl_api_%s_t_endian (a->%s%s[_i]);\n",
638 current_type_name, union_prefix, CDATA0);
641 "a->%s%s[_i] = %s(a->%s%s[_i]);\n",
642 union_prefix, CDATA0,
644 union_prefix, CDATA0);
654 if (CDATA2 != 0) { // variable length vector
655 fprintf(fp, "'%s', '%d', '%s'),\n", CDATA0, IDATA1, CDATA2);
657 fprintf(fp, "'%s', '%d'),\n", CDATA0, IDATA1);
662 fprintf(stderr, "node_vector_generate: unimp pass %d\n", which);
665 fprintf(stderr, "broken recursion in node_vector_generate\n");
669 node_vft_t node_vector_vft = {
671 node_vector_generate,
675 void node_complex_print (node_t *this)
677 primtype_recursive_print (this, "complex ");
680 void node_complex_generate (node_t *this, enum passid which, FILE *fp)
684 char *member_name = "broken!";
685 char *union_prefix = "";
687 if (current_union_name) {
688 sprintf(tmpbuf, "%s.", current_union_name);
689 union_prefix = tmpbuf;
692 current_is_complex++;
696 fprintf(fp, "%s ", CDATA0);
697 deeper = this->deeper;
699 vftp = the_vft[deeper->type];
700 vftp->generate(deeper, which, fp);
705 deeper = this->deeper;
707 if (deeper->type == NODE_SCALAR ||
708 deeper->type == NODE_VECTOR) {
709 member_name = deeper->data[0];
712 deeper = deeper->deeper;
715 fprintf(fp, "vl_print(handle, \"%s%s ----- \\n\");\n",
716 union_prefix, member_name);
718 fprintf(fp, "%s_print(&a->%s%s, handle);\n",
719 CDATA0, union_prefix, member_name);
721 fprintf(fp, "vl_print(handle, \"%s%s ----- END \\n\");\n",
722 union_prefix, member_name);
726 deeper = this->deeper;
728 if (deeper->type == NODE_SCALAR ||
729 deeper->type == NODE_VECTOR) {
730 member_name = deeper->data[0];
733 deeper = deeper->deeper;
737 fprintf(fp, "%s_endian(&a->%s%s);\n",
738 CDATA0, union_prefix, member_name);
741 fprintf(fp, "('%s',", CDATA0);
742 deeper = this->deeper;
744 vftp = the_vft[deeper->type];
745 vftp->generate(deeper, which, fp);
750 fprintf(stderr, "node_complex_generate unimp pass %d...\n", which);
753 current_is_complex--;
756 node_vft_t node_complex_vft = {
758 node_complex_generate,
762 void node_noversion_print (node_t *this)
764 primtype_recursive_print (this, "noversion ");
767 void node_noversion_generate (node_t *this, enum passid which, FILE *ofp)
769 fprintf(stderr, "node_noversion_generate called...\n");
772 node_vft_t node_noversion_vft = {
773 node_noversion_print,
774 node_noversion_generate,
778 void node_uword_print (node_t *this)
780 primtype_recursive_print(this, "uword ");
783 void node_uword_generate (node_t *this, enum passid which, FILE *ofp)
785 primtype_recursive_generate(this, which, ofp, "uword", "uword", "");
788 node_vft_t node_uword_vft = {
791 "clib_net_to_host_uword",
794 node_vft_t *the_vft[NODE_N_TYPES] = {
815 void *make_node (enum node_subclass type)
819 rv = (node_t *) malloc (sizeof (*rv));
821 fprintf (stderr, "fatal: make_node out of memory\n");
824 bzero (rv, sizeof (*rv));
826 return ((void *) rv);
829 YYSTYPE deeper (YYSTYPE arg1, YYSTYPE arg2)
831 node_t *np1 = (node_t *) arg1;
832 node_t *np2 = (node_t *) arg2;
837 while (hook_point->deeper)
838 hook_point = hook_point->deeper;
840 hook_point->deeper = np2;
844 YYSTYPE addpeer (YYSTYPE arg1, YYSTYPE arg2)
846 node_t *np1 = (node_t *) arg1;
847 node_t *np2 = (node_t *) arg2;
852 while (hook_point->peer)
853 hook_point = hook_point->peer;
855 hook_point->peer = np2;
860 * add_slist (stmt_list, stmt)
863 YYSTYPE add_slist (YYSTYPE a1, YYSTYPE a2)
866 return (addpeer(a1, a2));
874 * add_define (char *name, defn_list);
876 YYSTYPE add_define (YYSTYPE a1, YYSTYPE a2)
880 np = make_node(NODE_DEFINE);
882 deeper((YYSTYPE)np, a2);
883 return ((YYSTYPE) np);
887 * add_defbody (defn_list, new_defn)
889 YYSTYPE add_defbody (YYSTYPE a1, YYSTYPE a2)
891 return (addpeer(a1, a2));
895 * add_primtype ([packed], primitive type, instance)
898 YYSTYPE add_primtype (YYSTYPE a1, YYSTYPE a2, YYSTYPE a3)
904 /* Hook instance to type node */
913 * add_complex(char *type_name, instance)
916 YYSTYPE add_complex (YYSTYPE a1, YYSTYPE a2)
920 np = make_node(NODE_COMPLEX);
921 np->data[0] = (void *) a1;
923 deeper((YYSTYPE)np, a2);
924 return ((YYSTYPE) np);
928 * add_union(char *type_name, definition)
931 YYSTYPE add_union (YYSTYPE a1, YYSTYPE a2)
935 np = make_node(NODE_UNION);
936 np->data[0] = (void *) a1;
938 deeper((YYSTYPE)np, a2);
939 return ((YYSTYPE) np);
944 * add_vector_vbl (node_t *variable, YYSTYPE size)
947 YYSTYPE add_vector_vbl (YYSTYPE a1, YYSTYPE a2)
951 np = make_node(NODE_VECTOR);
952 np->data[0] = (void *) a1;
953 np->data[1] = (void *) a2;
954 return ((YYSTYPE) np);
958 * add_vector_vbl (char *vector_name, char *vector_length_var)
961 YYSTYPE add_variable_length_vector_vbl (YYSTYPE vector_name, YYSTYPE vector_length_var)
965 np = make_node(NODE_VECTOR);
966 np->data[0] = (void *) vector_name;
967 np->data[1] = (void *) 0; // vector size used for vpe.api.h generation (array of length zero)
968 np->data[2] = (void *) vector_length_var; // name of the variable that stores vector length
969 return ((YYSTYPE) np);
973 * add_scalar_vbl (char *name)
975 YYSTYPE add_scalar_vbl (YYSTYPE a1)
979 np = make_node(NODE_SCALAR);
980 np->data[0] = (void *) a1;
981 return ((YYSTYPE) np);
985 * set_flags (int flags, msg(=0?))
987 YYSTYPE set_flags(YYSTYPE a1, YYSTYPE a2)
996 flags = (int)(uword) a1;
1004 YYSTYPE suppress_version (void)
1006 dont_output_version = 1;
1010 void dump(node_t *np)
1015 vftp = the_vft[np->type];
1021 char *fixup_input_filename(void)
1025 cp = (char *)input_filename;
1032 while (cp > input_filename && *cp != '/')
1037 strncpy (tmpbuf, cp, sizeof(tmpbuf)-1);
1046 while (cp > tmpbuf && *cp != '.')
1052 return (sxerox(tmpbuf));
1055 void generate_top_boilerplate(FILE *fp)
1058 char *datestring = ctime(&starttime);
1059 fixed_name = fixup_input_filename();
1063 fprintf (fp, "/*\n");
1064 fprintf (fp, " * VLIB API definitions %s\n", datestring);
1065 fprintf (fp, " * Input file: %s\n", input_filename);
1066 fprintf (fp, " * Automatically generated: please edit the input file ");
1067 fprintf (fp, "NOT this file!\n");
1069 /* Moron Acme trigger workaround */
1070 fprintf (fp, " * %syright (c) %s by Cisco Systems, Inc.\n", "Cop",
1072 fprintf (fp, " */\n\n");
1073 fprintf (fp, "#if defined(vl_msg_id)||defined(vl_union_id)||");
1074 fprintf (fp, "defined(vl_printfun) \\\n ||defined(vl_endianfun)||");
1075 fprintf (fp, " defined(vl_api_version)||defined(vl_typedefs) \\\n");
1076 fprintf (fp, " ||defined(vl_msg_name)\n");
1077 fprintf (fp, "/* ok, something was selected */\n");
1078 fprintf (fp, "#else\n");
1079 fprintf (fp, "#warning no content included from %s\n", input_filename);
1080 fprintf (fp, "#endif\n\n");
1081 fprintf (fp, "#define VL_API_PACKED(x) x __attribute__ ((packed))\n\n");
1084 void generate_bottom_boilerplate(FILE *fp)
1087 fprintf (fp, "\n#ifdef vl_api_version\n");
1089 if (dont_output_version) {
1090 fprintf (fp, "/* WARNING: API FILE VERSION CHECK DISABLED */\n");
1094 fprintf (fp, "vl_api_version(%s, 0x%08x)\n\n",
1095 fixed_name, (unsigned int)input_crc);
1096 fprintf (fp, "#endif\n\n");
1099 void generate_msg_ids(YYSTYPE a1, FILE *fp)
1101 node_t *np = (node_t *)a1;
1103 fprintf (fp, "\n/****** Message ID / handler enum ******/\n\n");
1104 fprintf (fp, "#ifdef vl_msg_id\n");
1107 if (np->type == NODE_DEFINE) {
1108 if (!(np->flags & NODE_FLAG_TYPEONLY)) {
1109 fprintf (fp, "vl_msg_id(VL_API_%s, vl_api_%s_t_handler)\n",
1110 uppercase(np->data[0]), (i8 *)np->data[0]);
1112 fprintf (fp, "/* typeonly: %s */\n", (i8 *)np->data[0]);
1117 fprintf (fp, "#endif\n");
1121 void generate_msg_names(YYSTYPE a1, FILE *fp)
1123 node_t *np = (node_t *)a1;
1125 fprintf (fp, "\n/****** Message names ******/\n\n");
1127 fprintf (fp, "#ifdef vl_msg_name\n");
1130 if (np->type == NODE_DEFINE) {
1131 if (!(np->flags & NODE_FLAG_TYPEONLY)) {
1132 fprintf (fp, "vl_msg_name(vl_api_%s_t, %d)\n",
1134 (np->flags & NODE_FLAG_DONT_TRACE ? 0 : 1));
1136 fprintf (fp, "/* typeonly: %s */\n", (i8 *)np->data[0]);
1141 fprintf (fp, "#endif\n\n");
1144 void generate_typedefs(YYSTYPE a1, FILE *fp)
1146 node_t *np = (node_t *)a1;
1149 fprintf(fp, "\n/****** Typedefs *****/\n\n");
1150 fprintf(fp, "#ifdef vl_typedefs\n\n");
1152 /* Walk the top-level node-list */
1154 if (np->type == NODE_DEFINE) {
1155 /* Yeah, this is pedantic */
1156 vftp = the_vft[np->type];
1157 vftp->generate(np, TYPEDEF_PASS, fp);
1161 fprintf(fp, "#endif /* vl_typedefs */\n\n");
1164 void union_walk_one_defn(node_t *np, FILE *fp)
1169 /* Walk the list of typed objects in this msg def */
1171 if (np->type == NODE_UNION) {
1172 current_union_name = np->data[0];
1175 /* Walk the list of objects in this union */
1177 vblp = uelem->deeper;
1178 /* Drill down on each element, find the variable name */
1180 if (vblp->type == NODE_SCALAR ||
1181 vblp->type == NODE_VECTOR ||
1182 vblp->type == NODE_COMPLEX) {
1183 fprintf(ofp, "#define %s_",
1184 uppercase(current_def_name));
1185 fprintf(ofp, "%s_", uppercase(current_union_name));
1186 fprintf(ofp, "%s %d\n",uppercase(vblp->data[0]),
1191 vblp = vblp->deeper;
1193 uelem = uelem->peer;
1195 current_union_name = 0;
1202 void generate_uniondefs(YYSTYPE a1, FILE *fp)
1204 node_t *np = (node_t *)a1;
1206 fprintf(fp, "/****** Discriminated Union Definitions *****/\n\n");
1207 fprintf(fp, "#ifdef vl_union_id\n\n");
1209 /* Walk the top-level node-list */
1211 if (np->type == NODE_DEFINE) {
1213 current_def_name = np->data[0];
1214 union_walk_one_defn(np->deeper, fp);
1218 fprintf(fp, "\n#endif /* vl_union_id */\n\n");
1221 void generate_printfun(YYSTYPE a1, FILE *fp)
1223 node_t *np = (node_t *)a1;
1226 fprintf(fp, "/****** Print functions *****/\n\n");
1227 fprintf(fp, "#ifdef vl_printfun\n\n");
1229 fprintf(fp, "#ifdef LP64\n");
1230 fputs ("#define _uword_fmt \"%lld\"\n", fp);
1231 fputs ("#define _uword_cast (long long)\n", fp);
1232 fprintf(fp, "#else\n");
1233 fputs("#define _uword_fmt \"%ld\"\n", fp);
1234 fputs ("#define _uword_cast long\n", fp);
1235 fprintf(fp, "#endif\n\n");
1237 /* Walk the top-level node-list */
1239 if (np->type == NODE_DEFINE) {
1240 if (!(np->flags & NODE_FLAG_MANUAL_PRINT)) {
1242 "static inline void *vl_api_%s_t_print (vl_api_%s_t *a,",
1243 (i8 *)np->data[0], (i8 *) np->data[0]);
1244 fprintf(fp, "void *handle)\n{\n");
1245 /* output the message name */
1247 " vl_print(handle, \"vl_api_%s_t:\\n\");\n",
1251 /* Yeah, this is pedantic */
1252 vftp = the_vft[np->type];
1253 vftp->generate(np, PRINTFUN_PASS, fp);
1254 fprintf(fp, " return handle;\n");
1255 fprintf(fp, "}\n\n");
1258 fprintf(fp, "/***** manual: vl_api_%s_t_print *****/\n\n",
1259 (i8 *) np->data[0]);
1264 fprintf(fp, "#endif /* vl_printfun */\n\n");
1267 void generate_endianfun(YYSTYPE a1, FILE *fp)
1269 node_t *np = (node_t *)a1;
1272 fprintf(fp, "\n/****** Endian swap functions *****/\n\n");
1273 fprintf(fp, "#ifdef vl_endianfun\n\n");
1274 fprintf(fp, "#undef clib_net_to_host_uword\n");
1275 fprintf(fp, "#ifdef LP64\n");
1276 fprintf(fp, "#define clib_net_to_host_uword clib_net_to_host_u64\n");
1277 fprintf(fp, "#else\n");
1278 fprintf(fp, "#define clib_net_to_host_uword clib_net_to_host_u32\n");
1279 fprintf(fp, "#endif\n\n");
1281 /* Walk the top-level node-list */
1283 if (np->type == NODE_DEFINE) {
1284 if (!(np->flags & NODE_FLAG_MANUAL_ENDIAN)) {
1286 "static inline void vl_api_%s_t_endian (vl_api_%s_t *a)\n{\n",
1287 (i8 *) np->data[0], (i8 *) np->data[0]);
1289 /* Yeah, this is pedantic */
1290 vftp = the_vft[np->type];
1291 vftp->generate(np, ENDIANFUN_PASS, fp);
1292 fprintf(fp, "}\n\n");
1295 fprintf(fp, "/***** manual: vl_api_%s_t_endian *****/\n\n",
1296 (i8 *) np->data[0]);
1301 fprintf(fp, "#endif /* vl_endianfun */\n\n");
1304 void add_msg_ids(YYSTYPE a1)
1306 node_t *np = (node_t *)a1;
1310 /* Walk the top-level node-list */
1312 if (np->type == NODE_DEFINE) {
1313 if (!(np->flags & NODE_FLAG_TYPEONLY)) {
1314 /* add the parse tree for "u16 _vl_msg_id" */
1315 new_u16 = make_node(NODE_U16);
1316 new_u16->peer = np->deeper;
1317 np->deeper = new_u16;
1318 new_vbl = make_node(NODE_SCALAR);
1319 new_vbl->data[0] = sxerox("_vl_msg_id");
1320 new_u16->deeper = new_vbl;
1327 void generate_python_msg_definitions(YYSTYPE a1, FILE *fp)
1329 node_t *np = (node_t *)a1;
1331 fprintf (fp, "messages = [\n");
1332 /* Walk the top-level node-list */
1334 if (np->type == NODE_DEFINE && !(np->flags & NODE_FLAG_TYPEONLY)) {
1335 /* Yeah, this is pedantic */
1336 vftp = the_vft[np->type];
1337 vftp->generate(np, PYTHON_PASS, fp);
1341 fprintf (fp, "\n]\n");
1344 void generate_python_typeonly_definitions(YYSTYPE a1, FILE *fp)
1346 node_t *np = (node_t *)a1;
1348 fprintf (fp, "types = [\n");
1349 /* Walk the top-level node-list */
1351 if (np->type == NODE_DEFINE && (np->flags & NODE_FLAG_TYPEONLY)) {
1352 vftp = the_vft[np->type];
1353 vftp->generate(np, PYTHON_PASS, fp);
1357 fprintf (fp, "\n]\n");
1360 void generate_python(YYSTYPE a1, FILE *fp)
1362 generate_python_typeonly_definitions(a1, fp);
1363 generate_python_msg_definitions(a1, fp);
1368 fprintf (fp, "vl_api_version = 0x%08x\n\n", (unsigned int)input_crc);
1371 void generate(YYSTYPE a1)
1380 generate_top_boilerplate(ofp);
1382 generate_msg_ids(a1, ofp);
1383 generate_msg_names(a1, ofp);
1384 generate_typedefs(a1, ofp);
1385 generate_uniondefs(a1, ofp);
1386 generate_printfun(a1, ofp);
1387 generate_endianfun(a1, ofp);
1389 generate_bottom_boilerplate(ofp);
1392 generate_python(a1, pythonfp);