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 */\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. */
619 fprintf(fp, "int _i;\n");
621 fprintf(fp, "for (_i = 0; _i < %d; _i++) {\n",
625 if (current_is_complex) {
627 "vl_api_%s_t_endian (a->%s%s[_i]);\n",
628 current_type_name, union_prefix, CDATA0);
631 "a->%s%s[_i] = %s(a->%s%s[_i]);\n",
632 union_prefix, CDATA0,
634 union_prefix, CDATA0);
644 if (CDATA2 != 0) { // variable length vector
645 fprintf(fp, "'%s', '%d', '%s'),\n", CDATA0, IDATA1, CDATA2);
647 fprintf(fp, "'%s', '%d'),\n", CDATA0, IDATA1);
652 fprintf(stderr, "node_vector_generate: unimp pass %d\n", which);
655 fprintf(stderr, "broken recursion in node_vector_generate\n");
659 node_vft_t node_vector_vft = {
661 node_vector_generate,
665 void node_complex_print (node_t *this)
667 primtype_recursive_print (this, "complex ");
670 void node_complex_generate (node_t *this, enum passid which, FILE *fp)
674 char *member_name = "broken!";
675 char *union_prefix = "";
677 if (current_union_name) {
678 sprintf(tmpbuf, "%s.", current_union_name);
679 union_prefix = tmpbuf;
682 current_is_complex++;
686 fprintf(fp, "%s ", CDATA0);
687 deeper = this->deeper;
689 vftp = the_vft[deeper->type];
690 vftp->generate(deeper, which, fp);
695 deeper = this->deeper;
697 if (deeper->type == NODE_SCALAR ||
698 deeper->type == NODE_VECTOR) {
699 member_name = deeper->data[0];
702 deeper = deeper->deeper;
705 fprintf(fp, "vl_print(handle, \"%s%s ----- \\n\");\n",
706 union_prefix, member_name);
708 fprintf(fp, "%s_print(&a->%s%s, handle);\n",
709 CDATA0, union_prefix, member_name);
711 fprintf(fp, "vl_print(handle, \"%s%s ----- END \\n\");\n",
712 union_prefix, member_name);
716 deeper = this->deeper;
718 if (deeper->type == NODE_SCALAR ||
719 deeper->type == NODE_VECTOR) {
720 member_name = deeper->data[0];
723 deeper = deeper->deeper;
727 fprintf(fp, "%s_endian(&a->%s%s);\n",
728 CDATA0, union_prefix, member_name);
731 fprintf(fp, "('%s',", CDATA0);
732 deeper = this->deeper;
734 vftp = the_vft[deeper->type];
735 vftp->generate(deeper, which, fp);
740 fprintf(stderr, "node_complex_generate unimp pass %d...\n", which);
743 current_is_complex--;
746 node_vft_t node_complex_vft = {
748 node_complex_generate,
752 void node_noversion_print (node_t *this)
754 primtype_recursive_print (this, "noversion ");
757 void node_noversion_generate (node_t *this, enum passid which, FILE *ofp)
759 fprintf(stderr, "node_noversion_generate called...\n");
762 node_vft_t node_noversion_vft = {
763 node_noversion_print,
764 node_noversion_generate,
768 void node_uword_print (node_t *this)
770 primtype_recursive_print(this, "uword ");
773 void node_uword_generate (node_t *this, enum passid which, FILE *ofp)
775 primtype_recursive_generate(this, which, ofp, "uword", "uword", "");
778 node_vft_t node_uword_vft = {
781 "clib_net_to_host_uword",
784 node_vft_t *the_vft[NODE_N_TYPES] = {
805 void *make_node (enum node_subclass type)
809 rv = (node_t *) malloc (sizeof (*rv));
811 fprintf (stderr, "fatal: make_node out of memory\n");
814 bzero (rv, sizeof (*rv));
816 return ((void *) rv);
819 YYSTYPE deeper (YYSTYPE arg1, YYSTYPE arg2)
821 node_t *np1 = (node_t *) arg1;
822 node_t *np2 = (node_t *) arg2;
827 while (hook_point->deeper)
828 hook_point = hook_point->deeper;
830 hook_point->deeper = np2;
834 YYSTYPE addpeer (YYSTYPE arg1, YYSTYPE arg2)
836 node_t *np1 = (node_t *) arg1;
837 node_t *np2 = (node_t *) arg2;
842 while (hook_point->peer)
843 hook_point = hook_point->peer;
845 hook_point->peer = np2;
850 * add_slist (stmt_list, stmt)
853 YYSTYPE add_slist (YYSTYPE a1, YYSTYPE a2)
856 return (addpeer(a1, a2));
864 * add_define (char *name, defn_list);
866 YYSTYPE add_define (YYSTYPE a1, YYSTYPE a2)
870 np = make_node(NODE_DEFINE);
872 deeper((YYSTYPE)np, a2);
873 return ((YYSTYPE) np);
877 * add_defbody (defn_list, new_defn)
879 YYSTYPE add_defbody (YYSTYPE a1, YYSTYPE a2)
881 return (addpeer(a1, a2));
885 * add_primtype ([packed], primitive type, instance)
888 YYSTYPE add_primtype (YYSTYPE a1, YYSTYPE a2, YYSTYPE a3)
894 /* Hook instance to type node */
903 * add_complex(char *type_name, instance)
906 YYSTYPE add_complex (YYSTYPE a1, YYSTYPE a2)
910 np = make_node(NODE_COMPLEX);
911 np->data[0] = (void *) a1;
913 deeper((YYSTYPE)np, a2);
914 return ((YYSTYPE) np);
918 * add_union(char *type_name, definition)
921 YYSTYPE add_union (YYSTYPE a1, YYSTYPE a2)
925 np = make_node(NODE_UNION);
926 np->data[0] = (void *) a1;
928 deeper((YYSTYPE)np, a2);
929 return ((YYSTYPE) np);
934 * add_vector_vbl (node_t *variable, YYSTYPE size)
937 YYSTYPE add_vector_vbl (YYSTYPE a1, YYSTYPE a2)
941 np = make_node(NODE_VECTOR);
942 np->data[0] = (void *) a1;
943 np->data[1] = (void *) a2;
944 return ((YYSTYPE) np);
948 * add_vector_vbl (char *vector_name, char *vector_length_var)
951 YYSTYPE add_variable_length_vector_vbl (YYSTYPE vector_name, YYSTYPE vector_length_var)
955 np = make_node(NODE_VECTOR);
956 np->data[0] = (void *) vector_name;
957 np->data[1] = (void *) 0; // vector size used for vpe.api.h generation (array of length zero)
958 np->data[2] = (void *) vector_length_var; // name of the variable that stores vector length
959 return ((YYSTYPE) np);
963 * add_scalar_vbl (char *name)
965 YYSTYPE add_scalar_vbl (YYSTYPE a1)
969 np = make_node(NODE_SCALAR);
970 np->data[0] = (void *) a1;
971 return ((YYSTYPE) np);
975 * set_flags (int flags, msg(=0?))
977 YYSTYPE set_flags(YYSTYPE a1, YYSTYPE a2)
986 flags = (int)(uword) a1;
994 YYSTYPE suppress_version (void)
996 dont_output_version = 1;
1000 void dump(node_t *np)
1005 vftp = the_vft[np->type];
1011 char *fixup_input_filename(void)
1015 cp = (char *)input_filename;
1022 while (cp > input_filename && *cp != '/')
1027 strcpy (tmpbuf, cp);
1036 while (cp > tmpbuf && *cp != '.')
1042 return (sxerox(tmpbuf));
1045 void generate_top_boilerplate(FILE *fp)
1048 char *datestring = ctime(&starttime);
1049 fixed_name = fixup_input_filename();
1053 fprintf (fp, "/*\n");
1054 fprintf (fp, " * VLIB API definitions %s\n", datestring);
1055 fprintf (fp, " * Input file: %s\n", input_filename);
1056 fprintf (fp, " * Automatically generated: please edit the input file ");
1057 fprintf (fp, "NOT this file!\n");
1059 /* Moron Acme trigger workaround */
1060 fprintf (fp, " * %syright (c) %s by Cisco Systems, Inc.\n", "Cop",
1062 fprintf (fp, " */\n\n");
1063 fprintf (fp, "#if defined(vl_msg_id)||defined(vl_union_id)||");
1064 fprintf (fp, "defined(vl_printfun) \\\n ||defined(vl_endianfun)||");
1065 fprintf (fp, " defined(vl_api_version)||defined(vl_typedefs) \\\n");
1066 fprintf (fp, " ||defined(vl_msg_name)\n");
1067 fprintf (fp, "/* ok, something was selected */\n");
1068 fprintf (fp, "#else\n");
1069 fprintf (fp, "#warning no content included from %s\n", input_filename);
1070 fprintf (fp, "#endif\n\n");
1071 fprintf (fp, "#define VL_API_PACKED(x) x __attribute__ ((packed))\n\n");
1074 void generate_bottom_boilerplate(FILE *fp)
1077 fprintf (fp, "\n#ifdef vl_api_version\n");
1079 if (dont_output_version) {
1080 fprintf (fp, "/* WARNING: API FILE VERSION CHECK DISABLED */\n");
1084 fprintf (fp, "vl_api_version(%s, 0x%08x)\n\n",
1085 fixed_name, (unsigned int)input_crc);
1086 fprintf (fp, "#endif\n\n");
1089 void generate_msg_ids(YYSTYPE a1, FILE *fp)
1091 node_t *np = (node_t *)a1;
1093 fprintf (fp, "\n/****** Message ID / handler enum ******/\n\n");
1094 fprintf (fp, "#ifdef vl_msg_id\n");
1097 if (np->type == NODE_DEFINE) {
1098 if (!(np->flags & NODE_FLAG_TYPEONLY)) {
1099 fprintf (fp, "vl_msg_id(VL_API_%s, vl_api_%s_t_handler)\n",
1100 uppercase(np->data[0]), (i8 *)np->data[0]);
1102 fprintf (fp, "/* typeonly: %s */\n", (i8 *)np->data[0]);
1107 fprintf (fp, "#endif\n");
1111 void generate_msg_names(YYSTYPE a1, FILE *fp)
1113 node_t *np = (node_t *)a1;
1115 fprintf (fp, "\n/****** Message names ******/\n\n");
1117 fprintf (fp, "#ifdef vl_msg_name\n");
1120 if (np->type == NODE_DEFINE) {
1121 if (!(np->flags & NODE_FLAG_TYPEONLY)) {
1122 fprintf (fp, "vl_msg_name(vl_api_%s_t, %d)\n",
1124 (np->flags & NODE_FLAG_DONT_TRACE ? 0 : 1));
1126 fprintf (fp, "/* typeonly: %s */\n", (i8 *)np->data[0]);
1131 fprintf (fp, "#endif\n\n");
1134 void generate_typedefs(YYSTYPE a1, FILE *fp)
1136 node_t *np = (node_t *)a1;
1139 fprintf(fp, "\n/****** Typedefs *****/\n\n");
1140 fprintf(fp, "#ifdef vl_typedefs\n\n");
1142 /* Walk the top-level node-list */
1144 if (np->type == NODE_DEFINE) {
1145 /* Yeah, this is pedantic */
1146 vftp = the_vft[np->type];
1147 vftp->generate(np, TYPEDEF_PASS, fp);
1151 fprintf(fp, "#endif /* vl_typedefs */\n\n");
1154 void union_walk_one_defn(node_t *np, FILE *fp)
1159 /* Walk the list of typed objects in this msg def */
1161 if (np->type == NODE_UNION) {
1162 current_union_name = np->data[0];
1165 /* Walk the list of objects in this union */
1167 vblp = uelem->deeper;
1168 /* Drill down on each element, find the variable name */
1170 if (vblp->type == NODE_SCALAR ||
1171 vblp->type == NODE_VECTOR ||
1172 vblp->type == NODE_COMPLEX) {
1173 fprintf(ofp, "#define %s_",
1174 uppercase(current_def_name));
1175 fprintf(ofp, "%s_", uppercase(current_union_name));
1176 fprintf(ofp, "%s %d\n",uppercase(vblp->data[0]),
1181 vblp = vblp->deeper;
1183 uelem = uelem->peer;
1185 current_union_name = 0;
1192 void generate_uniondefs(YYSTYPE a1, FILE *fp)
1194 node_t *np = (node_t *)a1;
1196 fprintf(fp, "/****** Discriminated Union Definitions *****/\n\n");
1197 fprintf(fp, "#ifdef vl_union_id\n\n");
1199 /* Walk the top-level node-list */
1201 if (np->type == NODE_DEFINE) {
1203 current_def_name = np->data[0];
1204 union_walk_one_defn(np->deeper, fp);
1208 fprintf(fp, "\n#endif /* vl_union_id */\n\n");
1211 void generate_printfun(YYSTYPE a1, FILE *fp)
1213 node_t *np = (node_t *)a1;
1216 fprintf(fp, "/****** Print functions *****/\n\n");
1217 fprintf(fp, "#ifdef vl_printfun\n\n");
1219 fprintf(fp, "#ifdef LP64\n");
1220 fputs ("#define _uword_fmt \"%lld\"\n", fp);
1221 fputs ("#define _uword_cast (long long)\n", fp);
1222 fprintf(fp, "#else\n");
1223 fputs("#define _uword_fmt \"%ld\"\n", fp);
1224 fputs ("#define _uword_cast long\n", fp);
1225 fprintf(fp, "#endif\n\n");
1227 /* Walk the top-level node-list */
1229 if (np->type == NODE_DEFINE) {
1230 if (!(np->flags & NODE_FLAG_MANUAL_PRINT)) {
1232 "static inline void *vl_api_%s_t_print (vl_api_%s_t *a,",
1233 (i8 *)np->data[0], (i8 *) np->data[0]);
1234 fprintf(fp, "void *handle)\n{\n");
1235 /* output the message name */
1237 " vl_print(handle, \"vl_api_%s_t:\\n\");\n",
1241 /* Yeah, this is pedantic */
1242 vftp = the_vft[np->type];
1243 vftp->generate(np, PRINTFUN_PASS, fp);
1244 fprintf(fp, " return handle;\n");
1245 fprintf(fp, "}\n\n");
1248 fprintf(fp, "/***** manual: vl_api_%s_t_print *****/\n\n",
1249 (i8 *) np->data[0]);
1254 fprintf(fp, "#endif /* vl_printfun */\n\n");
1257 void generate_endianfun(YYSTYPE a1, FILE *fp)
1259 node_t *np = (node_t *)a1;
1262 fprintf(fp, "\n/****** Endian swap functions *****/\n\n");
1263 fprintf(fp, "#ifdef vl_endianfun\n\n");
1264 fprintf(fp, "#undef clib_net_to_host_uword\n");
1265 fprintf(fp, "#ifdef LP64\n");
1266 fprintf(fp, "#define clib_net_to_host_uword clib_net_to_host_u64\n");
1267 fprintf(fp, "#else\n");
1268 fprintf(fp, "#define clib_net_to_host_uword clib_net_to_host_u32\n");
1269 fprintf(fp, "#endif\n\n");
1271 /* Walk the top-level node-list */
1273 if (np->type == NODE_DEFINE) {
1274 if (!(np->flags & NODE_FLAG_MANUAL_ENDIAN)) {
1276 "static inline void vl_api_%s_t_endian (vl_api_%s_t *a)\n{\n",
1277 (i8 *) np->data[0], (i8 *) np->data[0]);
1279 /* Yeah, this is pedantic */
1280 vftp = the_vft[np->type];
1281 vftp->generate(np, ENDIANFUN_PASS, fp);
1282 fprintf(fp, "}\n\n");
1285 fprintf(fp, "/***** manual: vl_api_%s_t_endian *****/\n\n",
1286 (i8 *) np->data[0]);
1291 fprintf(fp, "#endif /* vl_endianfun */\n\n");
1294 void add_msg_ids(YYSTYPE a1)
1296 node_t *np = (node_t *)a1;
1300 /* Walk the top-level node-list */
1302 if (np->type == NODE_DEFINE) {
1303 if (!(np->flags & NODE_FLAG_TYPEONLY)) {
1304 /* add the parse tree for "u16 _vl_msg_id" */
1305 new_u16 = make_node(NODE_U16);
1306 new_u16->peer = np->deeper;
1307 np->deeper = new_u16;
1308 new_vbl = make_node(NODE_SCALAR);
1309 new_vbl->data[0] = sxerox("_vl_msg_id");
1310 new_u16->deeper = new_vbl;
1317 void generate_python (YYSTYPE a1, FILE *fp)
1319 node_t *np = (node_t *)a1;
1321 fprintf (fp, "vppapidef = [\n");
1322 /* Walk the top-level node-list */
1324 if (np->type == NODE_DEFINE && !(np->flags & NODE_FLAG_TYPEONLY)) {
1325 /* Yeah, this is pedantic */
1326 vftp = the_vft[np->type];
1327 vftp->generate(np, PYTHON_PASS, fp);
1331 fprintf (fp, "\n]\n");
1334 void generate(YYSTYPE a1)
1343 generate_top_boilerplate(ofp);
1345 generate_msg_ids(a1, ofp);
1346 generate_msg_names(a1, ofp);
1347 generate_typedefs(a1, ofp);
1348 generate_uniondefs(a1, ofp);
1349 generate_printfun(a1, ofp);
1350 generate_endianfun(a1, ofp);
1352 generate_bottom_boilerplate(ofp);
1355 generate_python(a1, pythonfp);