blob: b82816e2fcfc0220c3432f85516f94c747e5f08e [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
2 *------------------------------------------------------------------
3 * node.c - the api generator's semantic back-end
4 *
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:
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
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 *------------------------------------------------------------------
18 */
19
20#include <stdio.h>
21#include <ctype.h>
22#include <time.h>
23#include <string.h>
24#include <unistd.h>
25#include <stdlib.h>
26#include <vppinfra/vec.h>
27#include <vppinfra/hash.h>
28
29#include "lex.h"
30#include "node.h"
31
32#define YYSTYPE void *
33
34FILE *ofp;
35FILE *javafp;
36FILE *jnifp;
37char *java_class;
38time_t starttime;
39char *vlib_app_name;
40char *input_filename;
41node_vft_t *the_vft[NODE_N_TYPES];
42static int indent;
43static int dont_output_version;
44int dump_tree;
45static char *fixed_name;
46static char tmpbuf [MAXNAME];
47static char *current_def_name;
48static char *current_union_name;
49static char *current_type_fmt;
50static char *current_type_cast;
51static char current_id;
52static char current_is_complex;
53static char *current_endianfun;
54static char *current_type_name;
55static int current_java_parameter_number;
56static int current_java_emitted_parameter;
57static int current_java_parameter_need_comma_space;
58void *current_java_methodfun;
59void *current_java_jnifun;
60
61void indent_me(FILE *ofp)
62{
63 int i;
64
65 for (i = 0; i < indent; i++)
66 putc(' ', ofp);
67}
68
69char *uppercase (char *s)
70{
71 char *cp;
72
73 cp = tmpbuf;
74
75 while (*s && (cp < tmpbuf + (sizeof(tmpbuf)-1))) {
76 if (*s >= 'a' && *s <= 'z')
77 *cp++ = *s++ - ('a' - 'A');
78 else
79 *cp++ = *s++;
80 }
81 *cp = 0;
82 return(tmpbuf);
83}
84
85char *lowercase (char *s)
86{
87 char *cp;
88
89 cp = tmpbuf;
90
91 while (*s && (cp < tmpbuf + (sizeof(tmpbuf)-1))) {
92 if (*s >= 'A' && *s <= 'Z')
93 *cp++ = *s++ + ('a' - 'A');
94 else
95 *cp++ = *s++;
96 }
97 *cp = 0;
98 return(tmpbuf);
99}
100
101/*
102 * javah maps foo_bar to foo_1bar for whatever freakin' reason
103 * So, adjust java names accordingly.
104 */
105char *java_name_mangle (void * name_arg)
106{
107 char * name = name_arg;
108 static u8 * s;
109 int i;
110
111 vec_reset_length (s);
112
113 s = format (s, "%s%c", name, 0);
114
115 for (i = 0; i < vec_len(s); i++)
116 if (s[i] == '_') {
117 vec_delete (s, 1, i);
118 if (s[i] >= 'a' && s[i] <= 'z')
119 s[i] -= ('a' - 'A');
120 }
121 vec_add1 (s, 0);
122
123 return ((char *) s);
124}
125
126void primtype_recursive_print(node_t *this, i8 *fmt)
127{
128 fputs((char *)fmt, stdout);
129
130 if (this->deeper) {
131 node_vft_t *vftp = the_vft[this->deeper->type];
132 vftp->print(this->deeper);
133 }
134}
135
136void primtype_recursive_generate(node_t *this, enum passid which, FILE *ofp,
137 i8 *type_name, i8 *type_fmt, i8 *type_cast)
138{
139 node_vft_t *vftp;
140
141 current_type_name = (char *)type_name;
142 current_type_cast = (char *)type_cast;
143
144 switch(which) {
145 case TYPEDEF_PASS:
146 fputs((char *)type_name, ofp);
147 fputs(" ", ofp);
148 break;
149
150 case PRINTFUN_PASS:
151 current_type_fmt = (char *)type_fmt;
152 break;
153
154 case ENDIANFUN_PASS:
155 vftp = the_vft[this->type];
156 current_endianfun = vftp->endian_converter;
157 break;
158
159 case JAVA_METHOD_PASS:
160 vftp = the_vft[this->type];
161 current_java_methodfun = vftp->java_method_function;
162 break;
163
164 default:
165 fprintf(stderr, "primtype_recursive_generate: unimp pass %d\n", which);
166 break;
167 }
168
169 if (this->deeper) {
170 vftp = the_vft[this->deeper->type];
171 vftp->generate(this->deeper, which, ofp);
172 }
173}
174
175void primtype_java_method (node_t * this, enum passid which, FILE *ofp,
176 char *java_type_name)
177{
178 node_t * deeper;
179
180 deeper = this->deeper;
181
182 /* We'll take care of _msg_id, client_index, and context ourselves */
183 if (current_java_parameter_number++ < 3) {
184 if (!strncmp ((char *)(deeper->data[0]), "client_index", 12))
185 return;
186 else if (!strncmp ((char *)(deeper->data[0]), "context", 7))
187 return;
188 else if (!strncmp ((char *)(deeper->data[0]), "_vl_msg_id", 10))
189 return;
190 }
191
192 if (deeper->type == NODE_SCALAR)
193 fprintf (ofp, "%s %s", java_type_name,
194 java_name_mangle(deeper->data[0]));
195 else
196 fprintf (ofp, "%s [] %s", java_type_name,
197 java_name_mangle(deeper->data[0]));
198
199 current_java_emitted_parameter = 1;
200}
201
202void primtype_java_parameter (node_t * this, enum passid which, FILE *ofp,
203 char *java_type_name)
204{
205 node_t * deeper;
206
207 deeper = this->deeper;
208
209 /* We'll take care of _msg_id, client_index, and context ourselves */
210 if (current_java_parameter_number++ < 3) {
211 if (!strncmp ((char *)(deeper->data[0]), "client_index", 12))
212 return;
213 else if (!strncmp ((char *)(deeper->data[0]), "context", 7))
214 return;
215 else if (!strncmp ((char *)(deeper->data[0]), "_vl_msg_id", 10))
216 return;
217 }
218 if (current_java_parameter_need_comma_space) {
219 current_java_parameter_need_comma_space = 0;
220 fputs (", ", ofp);
221 }
222
223 if (deeper->type == NODE_SCALAR)
224 fprintf (ofp, "%s %s", java_type_name, (char *)(deeper->data[0]));
225 else
226 fprintf (ofp, "%sArray %s", java_type_name, (char *)(deeper->data[0]));
227
228 current_java_emitted_parameter = 1;
229}
230
231void primtype_java_setup (node_t * this, enum passid which, FILE *ofp,
232 char *java_type_name, char *array_element_name)
233{
234 node_t * deeper;
235
236 deeper = this->deeper;
237
238 /* We'll take care of _msg_id, client_index, and context ourselves */
239 if (current_java_parameter_number++ < 3) {
240 if (!strncmp ((char *)(deeper->data[0]), "client_index", 12))
241 return;
242 else if (!strncmp ((char *)(deeper->data[0]), "context", 7))
243 return;
244 else if (!strncmp ((char *)(deeper->data[0]), "_vl_msg_id", 10))
245 return;
246 }
247
248 if (deeper->type == NODE_VECTOR) {
249 indent_me(ofp);
250 fprintf (ofp,
251 "%s * %sP = (*env)->Get%sArrayElements (env, %s, NULL);\n",
252 java_type_name, (char *)(deeper->data[0]),
253 array_element_name, (char *)(deeper->data[0]));
254 }
255
256 current_java_emitted_parameter = 1;
257}
258
259void primtype_java_code (node_t * this, enum passid which, FILE *ofp,
260 char *java_type_name, char * swapper)
261{
262 node_t * deeper;
263 char * s;
264
265 deeper = this->deeper;
266
267 /* We'll take care of _msg_id, client_index, and context ourselves */
268 if (current_java_parameter_number++ < 3) {
269 if (!strncmp ((char *)(deeper->data[0]), "client_index", 12))
270 return;
271 else if (!strncmp ((char *)(deeper->data[0]), "context", 7))
272 return;
273 else if (!strncmp ((char *)(deeper->data[0]), "_vl_msg_id", 10))
274 return;
275 }
276
277 indent_me(ofp);
278
279 s = (char *)(deeper->data[0]);
280
281 if (swapper == 0) {
282 if (deeper->type == NODE_VECTOR)
283 fprintf (ofp, "memcpy (mp->%s, %sP, sizeof (mp->%s));\n",
284 s, s, s);
285 else
286 fprintf (ofp, "mp->%s = %s;\n", s, s);
287 } else {
288 if (deeper->type == NODE_VECTOR) {
289 fprintf(ofp, "{\n");
290 indent += 4;
291 indent_me(ofp);
292 fprintf(ofp, "int _i;\n");
293 indent_me(ofp);
294 fprintf(ofp, "for (_i = 0; _i < %d; _i++) {\n",
295 (int)(u64)(deeper->data[1]));
296 indent += 4;
297 indent_me(ofp);
298 fprintf(ofp, "mp->%s[_i] = %s(%sP[_i]);\n",
299 s, swapper, s);
300 indent -= 4;
301 indent_me(ofp);
302 fprintf(ofp, "}\n");
303 indent -= 4;
304 indent_me(ofp);
305 fprintf(ofp, "}\n");
306 } else {
307 fprintf (ofp, "mp->%s = %s(%s);\n", s, swapper, s);
308 }
309 }
310
311 current_java_emitted_parameter = 1;
312}
313
314void primtype_java_teardown (node_t * this, enum passid which, FILE *ofp,
315 char * array_element_name)
316{
317 node_t * deeper;
318
319 deeper = this->deeper;
320
321 /* We'll take care of _msg_id, client_index, and context ourselves */
322 if (current_java_parameter_number++ < 3) {
323 if (!strncmp ((char *)(deeper->data[0]), "client_index", 12))
324 return;
325 else if (!strncmp ((char *)(deeper->data[0]), "context", 7))
326 return;
327 else if (!strncmp ((char *)(deeper->data[0]), "_vl_msg_id", 10))
328 return;
329 }
330
331 if (deeper->type == NODE_VECTOR) {
332 indent_me(ofp);
333 fprintf (ofp,
334 "(*env)->Release%sArrayElements (env, %s, %sP, 0);\n",
335 array_element_name,
336 (char *)(deeper->data[0]),
337 (char *)(deeper->data[0]));
338 }
339
340 current_java_emitted_parameter = 1;
341}
342
343void node_illegal_print (node_t *this)
344{
345 fprintf(stderr, "node_illegal_print called\n");
346 exit(0);
347}
348
349void node_illegal_generate (node_t *this, enum passid notused, FILE *ofp)
350{
351 fprintf(stderr, "node_illegal_generate called\n");
352 exit(0);
353}
354
355void node_illegal_java_method (node_t *this, enum passid notused, FILE *ofp)
356{
357 fprintf(stderr, "node_illegal_java_method called\n");
358 exit(0);
359}
360
361void node_illegal_java_jni (node_t *this, enum passid notused, FILE *ofp)
362{
363 fprintf(stderr, "node_illegal_java_jni called\n");
364 exit(0);
365}
366
367node_vft_t node_illegal_vft = {
368 node_illegal_print,
369 node_illegal_generate,
370 "illegal",
371 node_illegal_java_method,
372 node_illegal_java_jni,
373};
374
375void node_u8_print (node_t *this)
376{
377 primtype_recursive_print(this, "u8 ");
378}
379
380void node_u8_generate (node_t *this, enum passid which, FILE *ofp)
381{
382 primtype_recursive_generate(this, which, ofp, "u8", "%u", "(unsigned)");
383}
384
385void node_u8_java_method (node_t *this, enum passid which, FILE *ofp)
386{
387 primtype_java_method (this, which, ofp, "byte");
388}
389
390void node_u8_java_parameter (node_t *this, enum passid which, FILE *ofp)
391{
392 primtype_java_parameter (this, which, ofp, "jbyte");
393}
394
395void node_u8_java_setup (node_t *this, enum passid which, FILE *ofp)
396{
397 primtype_java_setup (this, which, ofp, "jbyte", "Byte");
398}
399
400void node_u8_java_code (node_t *this, enum passid which, FILE *ofp)
401{
402 primtype_java_code (this, which, ofp, "jbyte", 0 /* swapper */);
403}
404
405void node_u8_java_teardown (node_t *this, enum passid which, FILE *ofp)
406{
407 primtype_java_teardown (this, which, ofp, "Byte");
408}
409
410node_vft_t node_u8_vft = {
411 node_u8_print,
412 node_u8_generate,
413 "",
414 node_u8_java_method,
415 node_u8_java_parameter,
416 node_u8_java_setup,
417 node_u8_java_code,
418 node_u8_java_teardown,
419};
420
421void node_u16_print (node_t *this)
422{
423 primtype_recursive_print(this, "u16 ");
424}
425
426void node_u16_generate (node_t *this, enum passid which, FILE *ofp)
427{
428 primtype_recursive_generate(this, which, ofp, "u16", "%u", "(unsigned)");
429}
430
431void node_u16_java_method (node_t *this, enum passid which, FILE *ofp)
432{
433 primtype_java_method (this, which, ofp, "short");
434}
435
436void node_u16_java_parameter (node_t *this, enum passid which, FILE *ofp)
437{
438 primtype_java_parameter (this, which, ofp, "jshort");
439}
440
441void node_u16_java_setup (node_t *this, enum passid which, FILE *ofp)
442{
443 primtype_java_setup (this, which, ofp, "jshort", "Short");
444}
445
446void node_u16_java_code (node_t *this, enum passid which, FILE *ofp)
447{
448 primtype_java_code (this, which, ofp, "jshort", "clib_host_to_net_u16");
449}
450
451void node_u16_java_teardown (node_t *this, enum passid which, FILE *ofp)
452{
453 primtype_java_teardown (this, which, ofp, "Short");
454}
455
456node_vft_t node_u16_vft = {
457 node_u16_print,
458 node_u16_generate,
459 "clib_net_to_host_u16",
460 node_u16_java_method,
461 node_u16_java_parameter,
462 node_u16_java_setup,
463 node_u16_java_code,
464 node_u16_java_teardown,
465};
466
467void node_u32_print (node_t *this)
468{
469 primtype_recursive_print(this, "u32 ");
470}
471
472void node_u32_generate (node_t *this, enum passid which, FILE *ofp)
473{
474 primtype_recursive_generate(this, which, ofp, "u32", "%u", "(unsigned)");
475}
476
477void node_u32_java_method (node_t *this, enum passid which, FILE *ofp)
478{
479 primtype_java_method (this, which, ofp, "int");
480}
481
482void node_u32_java_parameter (node_t *this, enum passid which, FILE *ofp)
483{
484 primtype_java_parameter (this, which, ofp, "jint");
485}
486
487void node_u32_java_setup (node_t *this, enum passid which, FILE *ofp)
488{
489 primtype_java_setup (this, which, ofp, "jint", "Int");
490}
491
492void node_u32_java_code (node_t *this, enum passid which, FILE *ofp)
493{
494 primtype_java_code (this, which, ofp, "jint", "clib_host_to_net_u32");
495}
496
497void node_u32_java_teardown (node_t *this, enum passid which, FILE *ofp)
498{
499 primtype_java_teardown (this, which, ofp, "Int");
500}
501
502node_vft_t node_u32_vft = {
503 node_u32_print,
504 node_u32_generate,
505 "clib_net_to_host_u32",
506 node_u32_java_method,
507 node_u32_java_parameter,
508 node_u32_java_setup,
509 node_u32_java_code,
510 node_u32_java_teardown,
511};
512
513void node_u64_print (node_t *this)
514{
515 primtype_recursive_print(this, "u64 ");
516}
517
518void node_u64_generate (node_t *this, enum passid which, FILE *ofp)
519{
520 primtype_recursive_generate(this, which, ofp, "u64", "%llu",
521 "(long long)");
522}
523
524void node_u64_java_method (node_t *this, enum passid which, FILE *ofp)
525{
526 primtype_java_method (this, which, ofp, "long");
527}
528
529void node_u64_java_parameter (node_t *this, enum passid which, FILE *ofp)
530{
531 primtype_java_parameter (this, which, ofp, "jlong");
532}
533
534void node_u64_java_setup (node_t *this, enum passid which, FILE *ofp)
535{
536 primtype_java_setup (this, which, ofp, "jlong", "Long");
537}
538
539void node_u64_java_code (node_t *this, enum passid which, FILE *ofp)
540{
541 primtype_java_code (this, which, ofp, "jlong", "clib_host_to_net_u64");
542}
543
544void node_u64_java_teardown (node_t *this, enum passid which, FILE *ofp)
545{
546 primtype_java_teardown (this, which, ofp, "Long");
547}
548
549node_vft_t node_u64_vft = {
550 node_u64_print,
551 node_u64_generate,
552 "clib_net_to_host_u64",
553 node_u64_java_method,
554 node_u64_java_parameter,
555 node_u64_java_setup,
556 node_u64_java_code,
557 node_u64_java_teardown,
558};
559
560void node_i8_print (node_t *this)
561{
562 primtype_recursive_print(this, "i8 ");
563}
564
565void node_i8_generate (node_t *this, enum passid which, FILE *ofp)
566{
567 primtype_recursive_generate(this, which, ofp, "i8", "%d", "(int)");
568}
569
570node_vft_t node_i8_vft = {
571 node_i8_print,
572 node_i8_generate,
573 "",
574 node_u8_java_method,
575 node_u8_java_parameter,
576 node_u8_java_setup,
577 node_u8_java_code,
578 node_u8_java_teardown,
579};
580
581void node_i16_print (node_t *this)
582{
583 primtype_recursive_print(this, "i16 ");
584}
585
586void node_i16_generate (node_t *this, enum passid which, FILE *ofp)
587{
588 primtype_recursive_generate(this, which, ofp, "i16", "%d", "(int)");
589}
590
591node_vft_t node_i16_vft = {
592 node_i16_print,
593 node_i16_generate,
594 "clib_net_to_host_u16",
595 node_u16_java_method,
596 node_u16_java_parameter,
597 node_u16_java_setup,
598 node_u16_java_code,
599 node_u16_java_teardown,
600};
601
602void node_i32_print (node_t *this)
603{
604 primtype_recursive_print(this, "i32 ");
605}
606
607void node_i32_generate (node_t *this, enum passid which, FILE *ofp)
608{
609 primtype_recursive_generate(this, which, ofp, "i32", "%ld", "(long)");
610}
611
612node_vft_t node_i32_vft = {
613 node_i32_print,
614 node_i32_generate,
615 "clib_net_to_host_u32",
616 node_u32_java_method,
617 node_u32_java_parameter,
618 node_u32_java_setup,
619 node_u32_java_code,
620 node_u32_java_teardown,
621};
622
623void node_i64_print (node_t *this)
624{
625 primtype_recursive_print(this, "i64 ");
626}
627
628void node_i64_generate (node_t *this, enum passid which, FILE *ofp)
629{
630 primtype_recursive_generate(this, which, ofp, "i64", "%lld",
631 "(long long)");
632}
633
634node_vft_t node_i64_vft = {
635 node_i64_print,
636 node_i64_generate,
637 "clib_net_to_host_u64",
638 node_u64_java_method,
639 node_u64_java_parameter,
640 node_u64_java_setup,
641 node_u64_java_code,
642 node_u64_java_teardown,
643};
644
645void node_f64_print (node_t *this)
646{
647 primtype_recursive_print(this, "f64 ");
648}
649
650void node_f64_generate (node_t *this, enum passid which, FILE *ofp)
651{
652 primtype_recursive_generate(this, which, ofp, "f64", "%.2f",
653 "(double)");
654}
655void node_f64_java_method (node_t *this, enum passid which, FILE *ofp)
656{
657 primtype_java_method (this, which, ofp, "double");
658}
659
660void node_f64_java_parameter (node_t *this, enum passid which, FILE *ofp)
661{
662 primtype_java_parameter (this, which, ofp, "jdouble");
663}
664
665void node_f64_java_setup (node_t *this, enum passid which, FILE *ofp)
666{
667 primtype_java_setup (this, which, ofp, "jdouble", "Double");
668}
669
670void node_f64_java_code (node_t *this, enum passid which, FILE *ofp)
671{
672 /*
673 * Current API code doesn't try to endian-swap doubles
674 * FP formats aren't portable yadda yadda yadda
675 */
676 primtype_java_code (this, which, ofp, "jdouble", 0 /* $$$ */);
677}
678
679void node_f64_java_teardown (node_t *this, enum passid which, FILE *ofp)
680{
681 primtype_java_teardown (this, which, ofp, "Double");
682}
683
684node_vft_t node_f64_vft = {
685 node_f64_print,
686 node_f64_generate,
687 " ", /* FP numbers are sent in host byte order */
688 node_f64_java_method,
689 node_f64_java_parameter,
690 node_f64_java_setup,
691 node_f64_java_code,
692 node_f64_java_teardown,
693};
694
695
696void node_packed_print (node_t *this)
697{
698 primtype_recursive_print (this, "packed ");
699}
700
701void node_packed_generate (node_t *this, enum passid which, FILE *ofp)
702{
703 primtype_recursive_generate(this, which, ofp, "PACKED", "", "");
704}
705
706node_vft_t node_packed_vft = {
707 node_packed_print,
708 node_packed_generate,
709 0,
710};
711
712void node_define_print (node_t *this)
713{
714 fprintf(stdout, "define %s {\n", CDATA0);
715 if (this->deeper) {
716 node_vft_t *vftp = the_vft[this->deeper->type];
717 fprintf(stdout, " ");
718 vftp->print(this->deeper);
719 }
720 fprintf(stdout, "};\n");
721}
722
723void node_define_generate (node_t *this, enum passid which, FILE *fp)
724{
725 node_t *child, *save_child;
726
727 switch(which) {
728 case TYPEDEF_PASS:
729 fprintf(fp, "typedef VL_API_PACKED(struct _vl_api_%s {\n", CDATA0);
730 child = this->deeper;
731 indent += 4;
732 while (child) {
733 node_vft_t *vftp = the_vft[child->type];
734 indent_me(fp);
735 vftp->generate(child, which, fp);
736 child = child->peer;
737 }
738 indent -= 4;
739 fprintf(fp, "}) vl_api_%s_t;\n\n", CDATA0);
740 break;
741
742 case ENDIANFUN_PASS:
743 case PRINTFUN_PASS:
744 child = this->deeper;
745 while (child) {
746 node_vft_t *vftp = the_vft[child->type];
747 vftp->generate(child, which, fp);
748 child = child->peer;
749 }
750 break;
751
752 case JAVA_METHOD_PASS:
753 indent += 4;
754 indent_me(fp);
755 fprintf (fp, "public native int %s (",
756 java_name_mangle(CDATA0));
757 child = this->deeper;
758 while (child) {
759 node_vft_t *vftp = the_vft[child->type];
760 current_java_emitted_parameter = 0;
761 vftp->java_method_function(child, which, fp);
762 child = child->peer;
763 if (child && current_java_emitted_parameter)
764 fputs (", ", fp);
765 }
766 fprintf (fp, ");\n");
767 indent -= 4;
768 break;
769
770 case JAVA_JNI_PASS:
771 /* Generate function prototype */
772 fprintf (fp, "JNIEXPORT jint JNICALL Java_org_openvpp_vppjapi_%s_%s\n",
773 java_class, java_name_mangle(CDATA0));
774
775 fprintf (fp, "(JNIEnv * env, jobject obj");
776 current_java_parameter_need_comma_space = 1;
777 child = this->deeper;
778 save_child = child;
779 while (child) {
780 node_vft_t *vftp = the_vft[child->type];
781 current_java_emitted_parameter = 0;
782 vftp->java_jni_parameter(child, which, fp);
783 child = child->peer;
784 if (child && current_java_emitted_parameter)
785 fputs (", ", fp);
786 }
787 fprintf (fp, ")\n{\n");
788 indent += 4;
789
790 /* define the api message pointer */
791 indent_me(fp);
792 fprintf (fp, "vppjni_main_t *jm = &vppjni_main;\n");
793 indent_me(fp);
794 fprintf (fp, "vl_api_%s_t * mp;\n", current_def_name);
795 indent_me(fp);
796 fprintf (fp, "u32 my_context_id;\n");
797 indent_me(fp);
798 fprintf (fp, "int rv;\n");
799
800 indent_me(fp);
801 fprintf (fp, "rv = vppjni_sanity_check (jm);\n");
802 indent_me(fp);
803 fprintf (fp, "if (rv) return rv;\n");
804
805 indent_me(fp);
806 fprintf (fp, "my_context_id = vppjni_get_context_id (jm);\n");
807
808 /* Generate array setups, if any */
809 child = save_child;
810 while (child) {
811 node_vft_t *vftp = the_vft[child->type];
812 current_java_parameter_number = 0;
813 current_java_emitted_parameter = 0;
814 vftp->java_jni_setup(child, which, fp);
815 child = child->peer;
816 }
817
818 /* Setup the API message */
819 indent_me(fp);
820 fprintf (fp, "M(%s, %s);\n", uppercase(current_def_name),
821 current_def_name);
822 indent_me(fp);
823 fprintf (fp, "mp->context = clib_host_to_net_u32 (my_context_id);\n");
824 /* $$$ Set up context hash table or some such... */
825
826 /* Generate code */
827 child = save_child;
828 while (child) {
829 node_vft_t *vftp = the_vft[child->type];
830 current_java_parameter_number = 0;
831 current_java_emitted_parameter = 0;
832 vftp->java_jni_code(child, which, fp);
833 child = child->peer;
834 }
835
836 /* Generate array teardowns */
837 child = save_child;
838 while (child) {
839 node_vft_t *vftp = the_vft[child->type];
840 current_java_parameter_number = 0;
841 current_java_emitted_parameter = 0;
842 vftp->java_jni_teardown(child, which, fp);
843 child = child->peer;
844 }
845
846 /* Send the message, return context_id */
847 indent_me (fp);
848 fprintf (fp, "S;\n");
849 indent_me (fp);
850 fprintf (fp, "return my_context_id;\n");
851
852 indent -= 4;
853 fprintf (fp, "}\n\n");
854 break;
855
856 default:
857 fprintf(stderr, "node_define_generate: unimp pass %d\n", which);
858 break;
859 }
860}
861
862node_vft_t node_define_vft = {
863 node_define_print,
864 node_define_generate,
865 0,
866};
867
868void node_union_print (node_t *this)
869{
870 primtype_recursive_print (this, "union ");
871}
872
873void node_union_generate (node_t *this, enum passid which, FILE *fp)
874{
875 node_t *child;
876 node_t *uelem;
877 int case_id=1;
878
879 switch(which) {
880 case TYPEDEF_PASS:
881 fprintf(fp, "u8 _%s_which;\n", CDATA0);
882 indent_me(fp);
883 fprintf(fp, "union _%s {\n", CDATA0);
884 child = this->deeper;
885 indent += 4;
886
887 while (child) {
888 node_vft_t *vftp = the_vft[child->type];
889 indent_me(fp);
890 vftp->generate(child, which, fp);
891 child = child->peer;
892 }
893 indent -= 4;
894 indent_me(fp);
895 fprintf(fp, "} %s;\n", CDATA0);
896 break;
897
898 case PRINTFUN_PASS:
899 case ENDIANFUN_PASS:
900 uelem = this->deeper;
901
902 indent_me(fp);
903 fprintf(fp, "switch(a->_%s_which) {\n",
904 CDATA0);
905 indent += 4;
906 current_union_name = CDATA0;
907
908 /* Walk the list of objects in this union */
909 while (uelem) {
910 node_vft_t *vftp = the_vft[uelem->type];
911 indent -= 4;
912 indent_me(fp);
913 fprintf(fp, "case %d:\n", case_id);
914 case_id++;
915 indent += 4;
916 /* Drill down on each element */
917 vftp->generate(uelem, which, fp);
918 indent_me(fp);
919 fprintf(fp, "break;\n");
920 uelem = uelem->peer;
921 }
922 current_union_name = 0;
923 indent -= 4;
924 indent_me(fp);
925 fprintf(fp, "default:\n");
926 indent += 4;
927 indent_me(fp);
928 if (which == PRINTFUN_PASS) {
929 fprintf(fp,
930 "vl_print(handle, \"WARNING: _%s_which not set.\\n\");\n",
931 CDATA0);
932 }
933 indent_me(fp);
934 fprintf(fp, "break;\n");
935 indent -= 4;
936 indent_me(fp);
937 fprintf(fp, "}\n");
938 break;
939
940 default:
941 fprintf(stderr, "node_union_generate: unimp pass %d\n", which);
942 break;
943 }
944}
945
946
947node_vft_t node_union_vft = {
948 node_union_print,
949 node_union_generate,
950 0,
951};
952
953void node_scalar_print (node_t *this)
954{
955 fprintf(stdout, "%s", CDATA0);
956 primtype_recursive_print (this, "");
957}
958
959void node_scalar_generate (node_t *this, enum passid which, FILE *fp)
960{
961 char *union_prefix = "";
962
963 if (current_union_name) {
964 sprintf(tmpbuf, "%s.", current_union_name);
965 union_prefix = tmpbuf;
966 }
967
968 switch(which) {
969 case TYPEDEF_PASS:
970 fprintf(fp, "%s;\n", CDATA0);
971 break;
972
973 case PRINTFUN_PASS:
974 indent_me(fp);
975 if (current_is_complex) {
976 fprintf(fp, "vl_api_%s_t_print(a->%s%s, handle);\n",
977 current_type_name, union_prefix, CDATA0);
978 } else {
979 if (!strcmp(current_type_fmt, "uword")) {
980 fprintf(fp,
981 "vl_print(handle, \"%s%s: \" _uword_fmt \"\\n\", %s a->%s%s);\n",
982 union_prefix, CDATA0, "(_uword_cast)",
983 union_prefix, CDATA0);
984 } else {
985 fprintf(fp,
986 "vl_print(handle, \"%s%s: %s\\n\", %s a->%s%s);\n",
987 union_prefix, CDATA0,
988 current_type_fmt, current_type_cast,
989 union_prefix, CDATA0);
990 }
991 }
992 break;
993
994 case ENDIANFUN_PASS:
995 indent_me(fp);
996 if (current_is_complex) {
997 fprintf(fp, "vl_api%s_t_endian(a->%s%s);\n",
998 current_type_name, union_prefix, CDATA0);
999 } else {
1000 /* Current_endianfun == NULL means e.g. it's a u8... */
1001 if (current_endianfun) {
1002 fprintf(fp, "a->%s%s = %s(a->%s%s);\n", union_prefix,
1003 CDATA0, current_endianfun,
1004 union_prefix, CDATA0);
1005 } else {
1006 fprintf(fp, "/* a->%s%s = a->%s%s */\n",
1007 union_prefix, CDATA0,
1008 union_prefix, CDATA0);
1009 }
1010 }
1011 break;
1012
1013 default:
1014 fprintf(stderr, "node_scalar_generate: unimp pass %d\n", which);
1015 }
1016 if (this->deeper) {
1017 fprintf(stderr, "broken recursion in node_scalar_generate\n");
1018 }
1019}
1020
1021
1022node_vft_t node_scalar_vft = {
1023 node_scalar_print,
1024 node_scalar_generate,
1025 0,
1026};
1027
1028void node_vector_print (node_t *this)
1029{
1030 primtype_recursive_print (this, "vector ");
1031}
1032
1033void node_vector_generate (node_t *this, enum passid which, FILE *fp)
1034{
1035 char *union_prefix = "";
1036
1037 if (current_union_name) {
1038 sprintf(tmpbuf, "%s.", current_union_name);
1039 union_prefix = tmpbuf;
1040 }
1041
1042 switch(which) {
1043 case TYPEDEF_PASS:
1044 fprintf(fp, "%s[%d];\n", CDATA0, IDATA1);
1045 break;
1046
1047 case PRINTFUN_PASS:
1048 /* Don't bother about "u8 data [0];" et al. */
1049 if (IDATA1 == 0)
1050 break;
1051
1052 indent_me(fp);
1053 fprintf(fp, "{\n");
1054 indent += 4;
1055 indent_me(fp);
1056 fprintf(fp, "int _i;\n");
1057 indent_me(fp);
1058 fprintf(fp, "for (_i = 0; _i < %d; _i++) {\n",
1059 IDATA1);
1060 indent += 4;
1061 indent_me(fp);
1062 if (current_is_complex) {
1063 fprintf(fp, "vl_print(handle, \"%s%s[%%d]: ",
1064 union_prefix, CDATA0);
1065 fprintf(fp,
1066 "vl_print_%s (handle, a->%s%s[_i]);\n",
1067 CDATA0, union_prefix, CDATA0);
1068 } else {
1069 fprintf(fp,
1070 "vl_print(handle, \"%s%s[%%d]: %s\\n\", _i, a->%s%s[_i]);\n",
1071 union_prefix, CDATA0,
1072 current_type_fmt,
1073 union_prefix, CDATA0);
1074 }
1075 indent -= 4;
1076 indent_me(fp);
1077 fprintf(fp, "}\n");
1078 indent -= 4;
1079 indent_me(fp);
1080 fprintf(fp, "}\n");
1081 break;
1082
1083 case ENDIANFUN_PASS:
1084 /* Don't bother about "u8 data [0];" et al. */
1085 if (IDATA1 == 0)
1086 break;
1087
1088 indent_me(fp);
1089 fprintf(fp, "{\n");
1090 indent += 4;
1091 indent_me(fp);
1092 fprintf(fp, "int _i;\n");
1093 indent_me(fp);
1094 fprintf(fp, "for (_i = 0; _i < %d; _i++) {\n",
1095 IDATA1);
1096 indent += 4;
1097 indent_me(fp);
1098 if (current_is_complex) {
1099 fprintf(fp,
1100 "vl_api_%s_t_endian (a->%s%s[_i]);\n",
1101 current_type_name, union_prefix, CDATA0);
1102 } else {
1103 fprintf(fp,
1104 "a->%s%s[_i] = %s(a->%s%s[_i]);\n",
1105 union_prefix, CDATA0,
1106 current_endianfun,
1107 union_prefix, CDATA0);
1108 }
1109 indent -= 4;
1110 indent_me(fp);
1111 fprintf(fp, "}\n");
1112 indent -= 4;
1113 indent_me(fp);
1114 fprintf(fp, "}\n");
1115 break;
1116
1117 default:
1118 fprintf(stderr, "node_vector_generate: unimp pass %d\n", which);
1119 }
1120 if (this->deeper) {
1121 fprintf(stderr, "broken recursion in node_vector_generate\n");
1122 }
1123}
1124
1125node_vft_t node_vector_vft = {
1126 node_vector_print,
1127 node_vector_generate,
1128 0,
1129};
1130
1131void node_complex_print (node_t *this)
1132{
1133 primtype_recursive_print (this, "complex ");
1134}
1135
1136void node_complex_generate (node_t *this, enum passid which, FILE *fp)
1137{
1138 node_t *deeper;
1139 node_vft_t *vftp;
1140 char *member_name = "broken!";
1141 char *union_prefix = "";
1142
1143 if (current_union_name) {
1144 sprintf(tmpbuf, "%s.", current_union_name);
1145 union_prefix = tmpbuf;
1146 }
1147
1148 current_is_complex++;
1149
1150 switch(which) {
1151 case TYPEDEF_PASS:
1152 fprintf(fp, "%s ", CDATA0);
1153 deeper = this->deeper;
1154 if (deeper) {
1155 vftp = the_vft[deeper->type];
1156 vftp->generate(deeper, which, fp);
1157 }
1158 break;
1159
1160 case PRINTFUN_PASS:
1161 deeper = this->deeper;
1162 while (deeper) {
1163 if (deeper->type == NODE_SCALAR ||
1164 deeper->type == NODE_VECTOR) {
1165 member_name = deeper->data[0];
1166 break;
1167 }
1168 deeper = deeper->deeper;
1169 }
1170 indent_me(fp);
1171 fprintf(fp, "vl_print(handle, \"%s%s ----- \\n\");\n",
1172 union_prefix, member_name);
1173 indent_me(fp);
1174 fprintf(fp, "%s_print(&a->%s%s, handle);\n",
1175 CDATA0, union_prefix, member_name);
1176 indent_me(fp);
1177 fprintf(fp, "vl_print(handle, \"%s%s ----- END \\n\");\n",
1178 union_prefix, member_name);
1179 break;
1180
1181 case ENDIANFUN_PASS:
1182 deeper = this->deeper;
1183 while (deeper) {
1184 if (deeper->type == NODE_SCALAR ||
1185 deeper->type == NODE_VECTOR) {
1186 member_name = deeper->data[0];
1187 break;
1188 }
1189 deeper = deeper->deeper;
1190 }
1191
1192 indent_me(fp);
1193 fprintf(fp, "%s_endian(&a->%s%s);\n",
1194 CDATA0, union_prefix, member_name);
1195 break;
1196
1197 default:
1198 fprintf(stderr, "node_complex_generate unimp pass %d...\n", which);
1199 break;
1200 }
1201 current_is_complex--;
1202}
1203
1204node_vft_t node_complex_vft = {
1205 node_complex_print,
1206 node_complex_generate,
1207 0,
1208};
1209
1210void node_noversion_print (node_t *this)
1211{
1212 primtype_recursive_print (this, "noversion ");
1213}
1214
1215void node_noversion_generate (node_t *this, enum passid which, FILE *ofp)
1216{
1217 fprintf(stderr, "node_noversion_generate called...\n");
1218}
1219
1220node_vft_t node_noversion_vft = {
1221 node_noversion_print,
1222 node_noversion_generate,
1223 0,
1224};
1225
1226void node_uword_print (node_t *this)
1227{
1228 primtype_recursive_print(this, "uword ");
1229}
1230
1231void node_uword_generate (node_t *this, enum passid which, FILE *ofp)
1232{
1233 primtype_recursive_generate(this, which, ofp, "uword", "uword", "");
1234}
1235
1236node_vft_t node_uword_vft = {
1237 node_uword_print,
1238 node_uword_generate,
1239 "clib_net_to_host_uword",
1240};
1241
1242node_vft_t *the_vft[NODE_N_TYPES] = {
1243 &node_illegal_vft,
1244 &node_u8_vft,
1245 &node_u16_vft,
1246 &node_u32_vft,
1247 &node_u64_vft,
1248 &node_i8_vft,
1249 &node_i16_vft,
1250 &node_i32_vft,
1251 &node_i64_vft,
1252 &node_f64_vft,
1253 &node_packed_vft,
1254 &node_define_vft,
1255 &node_union_vft,
1256 &node_scalar_vft,
1257 &node_vector_vft,
1258 &node_complex_vft,
1259 &node_noversion_vft,
1260 &node_uword_vft,
1261};
1262
1263void *make_node (enum node_subclass type)
1264{
1265 node_t *rv;
1266
1267 rv = (node_t *) malloc (sizeof (*rv));
1268 if (rv == 0) {
1269 fprintf (stderr, "fatal: make_node out of memory\n");
1270 exit (1);
1271 }
1272 bzero (rv, sizeof (*rv));
1273 rv->type = type;
1274 return ((void *) rv);
1275}
1276
1277YYSTYPE deeper (YYSTYPE arg1, YYSTYPE arg2)
1278{
1279 node_t *np1 = (node_t *) arg1;
1280 node_t *np2 = (node_t *) arg2;
1281 node_t *hook_point;
1282
1283 hook_point = np1;
1284
1285 while (hook_point->deeper)
1286 hook_point = hook_point->deeper;
1287
1288 hook_point->deeper = np2;
1289 return (arg1);
1290}
1291
1292YYSTYPE addpeer (YYSTYPE arg1, YYSTYPE arg2)
1293{
1294 node_t *np1 = (node_t *) arg1;
1295 node_t *np2 = (node_t *) arg2;
1296 node_t *hook_point;
1297
1298 hook_point = np1;
1299
1300 while (hook_point->peer)
1301 hook_point = hook_point->peer;
1302
1303 hook_point->peer = np2;
1304 return (arg1);
1305}
1306
1307/*
1308 * add_slist (stmt_list, stmt)
1309 */
1310
1311YYSTYPE add_slist (YYSTYPE a1, YYSTYPE a2)
1312{
1313 if (a1 && a2)
1314 return (addpeer(a1, a2));
1315 else if(a1)
1316 return(a1);
1317 else
1318 return(a2);
1319}
1320
1321/*
1322 * add_define (char *name, defn_list);
1323 */
1324YYSTYPE add_define (YYSTYPE a1, YYSTYPE a2)
1325{
1326 node_t *np;
1327
1328 np = make_node(NODE_DEFINE);
1329 np->data[0] = a1;
1330 deeper((YYSTYPE)np, a2);
1331 return ((YYSTYPE) np);
1332}
1333
1334/*
1335 * add_defbody (defn_list, new_defn)
1336 */
1337YYSTYPE add_defbody (YYSTYPE a1, YYSTYPE a2)
1338{
1339 return (addpeer(a1, a2));
1340}
1341
1342/*
1343 * add_primtype ([packed], primitive type, instance)
1344 */
1345
1346YYSTYPE add_primtype (YYSTYPE a1, YYSTYPE a2, YYSTYPE a3)
1347{
1348 node_t *np1;
1349
1350 np1 = (node_t *)a1;
1351
1352 /* Hook instance to type node */
1353 deeper (a1, a2);
1354 if (a3) {
1355 deeper(a1, a3);
1356 }
1357 return (a1);
1358}
1359
1360/*
1361 * add_complex(char *type_name, instance)
1362 */
1363
1364YYSTYPE add_complex (YYSTYPE a1, YYSTYPE a2)
1365{
1366 node_t *np;
1367
1368 np = make_node(NODE_COMPLEX);
1369 np->data[0] = (void *) a1;
1370
1371 deeper((YYSTYPE)np, a2);
1372 return ((YYSTYPE) np);
1373}
1374
1375/*
1376 * add_union(char *type_name, definition)
1377 */
1378
1379YYSTYPE add_union (YYSTYPE a1, YYSTYPE a2)
1380{
1381 node_t *np;
1382
1383 np = make_node(NODE_UNION);
1384 np->data[0] = (void *) a1;
1385
1386 deeper((YYSTYPE)np, a2);
1387 return ((YYSTYPE) np);
1388}
1389
1390
1391/*
1392 * add_vector_vbl (node_t *variable, YYSTYPE size)
1393 */
1394
1395YYSTYPE add_vector_vbl (YYSTYPE a1, YYSTYPE a2)
1396{
1397 node_t *np;
1398
1399 np = make_node(NODE_VECTOR);
1400 np->data[0] = (void *) a1;
1401 np->data[1] = (void *) a2;
1402 return ((YYSTYPE) np);
1403}
1404
1405/*
1406 * add_scalar_vbl (char *name)
1407 */
1408YYSTYPE add_scalar_vbl (YYSTYPE a1)
1409{
1410 node_t *np;
1411
1412 np = make_node(NODE_SCALAR);
1413 np->data[0] = (void *) a1;
1414 return ((YYSTYPE) np);
1415}
1416
1417/*
1418 * set_flags (int flags, msg(=0?))
1419 */
1420YYSTYPE set_flags(YYSTYPE a1, YYSTYPE a2)
1421{
1422 node_t *np;
1423 int flags;
1424
1425 np = (node_t *)a2;
1426 if (!np)
1427 return(0);
1428
1429 flags = (int)(uword) a1;
1430
1431 np->flags |= flags;
1432 return (a2);
1433}
1434/*
1435 * suppress_version
1436 */
1437YYSTYPE suppress_version (void)
1438{
1439 dont_output_version = 1;
1440 return (0);
1441}
1442
1443void dump(node_t *np)
1444{
1445 node_vft_t *vftp;
1446
1447 while (np) {
1448 vftp = the_vft[np->type];
1449 vftp->print(np);
1450 np = np->peer;
1451 }
1452}
1453
1454char *fixup_input_filename(void)
1455{
1456 char *cp;
1457
1458 cp = (char *)input_filename;
1459
1460 while (*cp)
1461 cp++;
1462
1463 cp--;
1464
1465 while (cp > input_filename && *cp != '/')
1466 cp--;
1467 if (*cp == '/')
1468 cp++;
1469
1470 strcpy (tmpbuf, cp);
1471
1472 cp = tmpbuf;
1473
1474 while (*cp)
1475 cp++;
1476
1477 cp--;
1478
1479 while (cp > tmpbuf && *cp != '.')
1480 cp--;
1481
1482 if (*cp == '.')
1483 *cp = 0;
1484
1485 return (sxerox(tmpbuf));
1486}
1487
1488void generate_top_boilerplate(FILE *fp)
1489
1490{
1491 char *datestring = ctime(&starttime);
1492 fixed_name = fixup_input_filename();
1493
1494 datestring[24] = 0;
1495
1496 fprintf (fp, "/*\n");
1497 fprintf (fp, " * VLIB API definitions %s\n", datestring);
1498 fprintf (fp, " * Input file: %s\n", input_filename);
1499 fprintf (fp, " * Automatically generated: please edit the input file ");
1500 fprintf (fp, "NOT this file!\n");
1501
1502 /* Moron Acme trigger workaround */
1503 fprintf (fp, " * %syright (c) %s by Cisco Systems, Inc.\n", "Cop",
1504 &datestring[20]);
1505 fprintf (fp, " */\n\n");
1506 fprintf (fp, "#if defined(vl_msg_id)||defined(vl_union_id)||");
1507 fprintf (fp, "defined(vl_printfun) \\\n ||defined(vl_endianfun)||");
1508 fprintf (fp, " defined(vl_api_version)||defined(vl_typedefs) \\\n");
1509 fprintf (fp, " ||defined(vl_msg_name)\n");
1510 fprintf (fp, "/* ok, something was selected */\n");
1511 fprintf (fp, "#else\n");
1512 fprintf (fp, "#warning no content included from %s\n", input_filename);
1513 fprintf (fp, "#endif\n\n");
1514 fprintf (fp, "#define VL_API_PACKED(x) x __attribute__ ((packed))\n\n");
1515}
1516
1517void generate_bottom_boilerplate(FILE *fp)
1518
1519{
1520 fprintf (fp, "\n#ifdef vl_api_version\n");
1521
1522 if (dont_output_version) {
1523 fprintf (fp, "/* WARNING: API FILE VERSION CHECK DISABLED */\n");
1524 input_crc = 0;
1525 }
1526
1527 fprintf (fp, "vl_api_version(%s, 0x%08x)\n\n",
1528 fixed_name, (unsigned int)input_crc);
1529 fprintf (fp, "#endif\n\n");
1530}
1531
1532void generate_msg_ids(YYSTYPE a1, FILE *fp)
1533{
1534 node_t *np = (node_t *)a1;
1535
1536 fprintf (fp, "\n/****** Message ID / handler enum ******/\n\n");
1537 fprintf (fp, "#ifdef vl_msg_id\n");
1538
1539 while (np) {
1540 if (np->type == NODE_DEFINE) {
1541 if (!(np->flags & NODE_FLAG_TYPEONLY)) {
1542 fprintf (fp, "vl_msg_id(VL_API_%s, vl_api_%s_t_handler)\n",
1543 uppercase(np->data[0]), (i8 *)np->data[0]);
1544 } else {
1545 fprintf (fp, "/* typeonly: %s */\n", (i8 *)np->data[0]);
1546 }
1547 }
1548 np = np->peer;
1549 }
1550 fprintf (fp, "#endif\n");
1551
1552}
1553
1554void generate_msg_names(YYSTYPE a1, FILE *fp)
1555{
1556 node_t *np = (node_t *)a1;
1557
1558 fprintf (fp, "\n/****** Message names ******/\n\n");
1559
1560 fprintf (fp, "#ifdef vl_msg_name\n");
1561
1562 while (np) {
1563 if (np->type == NODE_DEFINE) {
1564 if (!(np->flags & NODE_FLAG_TYPEONLY)) {
1565 fprintf (fp, "vl_msg_name(vl_api_%s_t, %d)\n",
1566 (i8 *) np->data[0],
1567 (np->flags & NODE_FLAG_DONT_TRACE ? 0 : 1));
1568 } else {
1569 fprintf (fp, "/* typeonly: %s */\n", (i8 *)np->data[0]);
1570 }
1571 }
1572 np = np->peer;
1573 }
1574 fprintf (fp, "#endif\n\n");
1575}
1576
1577void generate_typedefs(YYSTYPE a1, FILE *fp)
1578{
1579 node_t *np = (node_t *)a1;
1580 node_vft_t *vftp;
1581
1582 fprintf(fp, "\n/****** Typedefs *****/\n\n");
1583 fprintf(fp, "#ifdef vl_typedefs\n\n");
1584
1585 /* Walk the top-level node-list */
1586 while (np) {
1587 if (np->type == NODE_DEFINE) {
1588 /* Yeah, this is pedantic */
1589 vftp = the_vft[np->type];
1590 vftp->generate(np, TYPEDEF_PASS, fp);
1591 }
1592 np = np->peer;
1593 }
1594 fprintf(fp, "#endif /* vl_typedefs */\n\n");
1595}
1596
1597void union_walk_one_defn(node_t *np, FILE *fp)
1598{
1599 node_t *vblp;
1600 node_t *uelem;
1601
1602 /* Walk the list of typed objects in this msg def */
1603 while (np) {
1604 if (np->type == NODE_UNION) {
1605 current_union_name = np->data[0];
1606 uelem = np->deeper;
1607
1608 /* Walk the list of objects in this union */
1609 while (uelem) {
1610 vblp = uelem->deeper;
1611 /* Drill down on each element, find the variable name */
1612 while(vblp) {
1613 if (vblp->type == NODE_SCALAR ||
1614 vblp->type == NODE_VECTOR ||
1615 vblp->type == NODE_COMPLEX) {
1616 fprintf(ofp, "#define %s_",
1617 uppercase(current_def_name));
1618 fprintf(ofp, "%s_", uppercase(current_union_name));
1619 fprintf(ofp, "%s %d\n",uppercase(vblp->data[0]),
1620 current_id);
1621 current_id++;
1622 break;
1623 }
1624 vblp = vblp->deeper;
1625 }
1626 uelem = uelem->peer;
1627 }
1628 current_union_name = 0;
1629 current_id = 1;
1630 }
1631 np = np->peer;
1632 }
1633}
1634
1635void generate_uniondefs(YYSTYPE a1, FILE *fp)
1636{
1637 node_t *np = (node_t *)a1;
1638
1639 fprintf(fp, "/****** Discriminated Union Definitions *****/\n\n");
1640 fprintf(fp, "#ifdef vl_union_id\n\n");
1641
1642 /* Walk the top-level node-list */
1643 while (np) {
1644 if (np->type == NODE_DEFINE) {
1645 current_id = 1;
1646 current_def_name = np->data[0];
1647 union_walk_one_defn(np->deeper, fp);
1648 }
1649 np = np->peer;
1650 }
1651 fprintf(fp, "\n#endif /* vl_union_id */\n\n");
1652}
1653
1654void generate_printfun(YYSTYPE a1, FILE *fp)
1655{
1656 node_t *np = (node_t *)a1;
1657 node_vft_t *vftp;
1658
1659 fprintf(fp, "/****** Print functions *****/\n\n");
1660 fprintf(fp, "#ifdef vl_printfun\n\n");
1661
1662 fprintf(fp, "#ifdef LP64\n");
1663 fputs ("#define _uword_fmt \"%lld\"\n", fp);
1664 fputs ("#define _uword_cast (long long)\n", fp);
1665 fprintf(fp, "#else\n");
1666 fputs("#define _uword_fmt \"%ld\"\n", fp);
1667 fputs ("#define _uword_cast long\n", fp);
1668 fprintf(fp, "#endif\n\n");
1669
1670 /* Walk the top-level node-list */
1671 while (np) {
1672 if (np->type == NODE_DEFINE) {
1673 if (!(np->flags & NODE_FLAG_MANUAL_PRINT)) {
1674 fprintf(fp,
1675 "static inline void *vl_api_%s_t_print (vl_api_%s_t *a,",
1676 (i8 *)np->data[0], (i8 *) np->data[0]);
1677 fprintf(fp, "void *handle)\n{\n");
1678 /* output the message name */
1679 fprintf(fp,
1680 " vl_print(handle, \"vl_api_%s_t:\\n\");\n",
1681 (i8 *)np->data[0]);
1682
1683 indent += 4;
1684 /* Yeah, this is pedantic */
1685 vftp = the_vft[np->type];
1686 vftp->generate(np, PRINTFUN_PASS, fp);
1687 fprintf(fp, " return handle;\n");
1688 fprintf(fp, "}\n\n");
1689 indent -= 4;
1690 } else {
1691 fprintf(fp, "/***** manual: vl_api_%s_t_print *****/\n\n",
1692 (i8 *) np->data[0]);
1693 }
1694 }
1695 np = np->peer;
1696 }
1697 fprintf(fp, "#endif /* vl_printfun */\n\n");
1698}
1699
1700void generate_endianfun(YYSTYPE a1, FILE *fp)
1701{
1702 node_t *np = (node_t *)a1;
1703 node_vft_t *vftp;
1704
1705 fprintf(fp, "\n/****** Endian swap functions *****/\n\n");
1706 fprintf(fp, "#ifdef vl_endianfun\n\n");
1707 fprintf(fp, "#undef clib_net_to_host_uword\n");
1708 fprintf(fp, "#ifdef LP64\n");
1709 fprintf(fp, "#define clib_net_to_host_uword clib_net_to_host_u64\n");
1710 fprintf(fp, "#else\n");
1711 fprintf(fp, "#define clib_net_to_host_uword clib_net_to_host_u32\n");
1712 fprintf(fp, "#endif\n\n");
1713
1714 /* Walk the top-level node-list */
1715 while (np) {
1716 if (np->type == NODE_DEFINE) {
1717 if (!(np->flags & NODE_FLAG_MANUAL_ENDIAN)) {
1718 fprintf(fp,
1719 "static inline void vl_api_%s_t_endian (vl_api_%s_t *a)\n{\n",
1720 (i8 *) np->data[0], (i8 *) np->data[0]);
1721 indent += 4;
1722 /* Yeah, this is pedantic */
1723 vftp = the_vft[np->type];
1724 vftp->generate(np, ENDIANFUN_PASS, fp);
1725 fprintf(fp, "}\n\n");
1726 indent -= 4;
1727 } else {
1728 fprintf(fp, "/***** manual: vl_api_%s_t_endian *****/\n\n",
1729 (i8 *) np->data[0]);
1730 }
1731 }
1732 np = np->peer;
1733 }
1734 fprintf(fp, "#endif /* vl_endianfun */\n\n");
1735}
1736
1737void add_msg_ids(YYSTYPE a1)
1738{
1739 node_t *np = (node_t *)a1;
1740 node_t *new_u16;
1741 node_t *new_vbl;
1742
1743 /* Walk the top-level node-list */
1744 while (np) {
1745 if (np->type == NODE_DEFINE) {
1746 if (!(np->flags & NODE_FLAG_TYPEONLY)) {
1747 /* add the parse tree for "u16 _vl_msg_id" */
1748 new_u16 = make_node(NODE_U16);
1749 new_u16->peer = np->deeper;
1750 np->deeper = new_u16;
1751 new_vbl = make_node(NODE_SCALAR);
1752 new_vbl->data[0] = sxerox("_vl_msg_id");
1753 new_u16->deeper = new_vbl;
1754 }
1755 }
1756 np = np->peer;
1757 }
1758}
1759
1760void generate_java_top_boilerplate(FILE *fp)
1761
1762{
1763 char *datestring = ctime(&starttime);
1764 fixed_name = fixup_input_filename();
1765
1766 datestring[24] = 0;
1767
1768 fprintf (fp, "/*\n");
1769 fprintf (fp, " * VLIB API java binding %s\n", datestring);
1770 fprintf (fp, " * Input file: %s\n", input_filename);
1771 fprintf (fp, " * Automatically generated: please edit the input file ");
1772 fprintf (fp, "NOT this file!\n");
1773 fprintf (fp, " */\n\n");
1774
1775 fprintf (fp, "package org.openvpp.vppjapi;\n\n");
1776 fprintf (fp, "import org.openvpp.vppjapi.vppConn;\n\n");
1777 fprintf (fp, "public class %s extends vppConn {\n\n",
1778 java_class);
1779}
1780
1781void generate_java_bottom_boilerplate(FILE *fp)
1782{
1783 fprintf (fp, "}\n");
1784}
1785
1786
1787void generate_java_class_definition (YYSTYPE a1, FILE *fp)
1788{
1789 node_t *np = (node_t *)a1;
1790 node_vft_t *vftp;
1791
1792 fprintf(fp, "/****** API methods *****/\n\n");
1793
1794 /* Walk the top-level node-list */
1795 while (np) {
1796 if (np->type == NODE_DEFINE) {
1797 if (!(np->flags & (NODE_FLAG_MANUAL_JAVA | NODE_FLAG_TYPEONLY))) {
1798 /* Suppress messages named "xyz_reply" */
1799 char * cp = (char *) np->data[0];
1800 while (*cp)
1801 cp++;
1802 cp -= 6;
1803 if (strncmp (cp, "_reply", 6)) {
1804 current_java_parameter_number = 0;
1805 vftp = the_vft[np->type];
1806 vftp->generate(np, JAVA_METHOD_PASS, fp);
1807 }
1808 }
1809 }
1810 np = np->peer;
1811 }
1812
1813 fprintf(fp, "\n/****** end of API methods *****/\n");
1814}
1815
1816void generate_jni_reply_handler_list (YYSTYPE a1, FILE *fp)
1817{
1818 node_t *np = (node_t *)a1;
1819 node_vft_t *vftp;
1820
1821 fprintf (fp, "#define foreach_api_reply_handler \\\n");
1822
1823 /* Walk the top-level node-list */
1824 while (np) {
1825 if (np->type == NODE_DEFINE) {
1826 if (!(np->flags & (NODE_FLAG_MANUAL_JAVA | NODE_FLAG_TYPEONLY))) {
1827 /* emit messages named "xyz_reply" */
1828 char * cp = (char *) np->data[0];
1829 while (*cp)
1830 cp++;
1831 cp -= 6;
1832 if (!strncmp (cp, "_reply", 6)) {
1833 fprintf (fp, "_(%s, %s) \\\n",
1834 uppercase(np->data[0]), (char *)(np->data[0]));
1835 }
1836 }
1837 }
1838 np = np->peer;
1839 }
1840
1841 fprintf (fp, "\n\n");
1842}
1843
1844char * m_macro_boilerplate =
1845"#define M(T,t) \\\n"
1846"do { \\\n"
1847" api_result_ready = 0; \\\n"
1848" mp = vl_msg_api_alloc(sizeof(*mp)); \\\n"
1849" memset (mp, 0, sizeof (*mp)); \\\n"
1850" mp->_vl_msg_id = ntohs (VL_API_##T); \\\n"
1851" mp->client_index = api_main.my_client_index; \\\n"
1852"} while(0);\n\n"
1853"#define M2(T,t,n) \\\n"
1854"do { \\\n"
1855" api_result_ready = 0; \\\n"
1856" mp = vl_msg_api_alloc(sizeof(*mp)+(n)); \\\n"
1857" memset (mp, 0, sizeof (*mp)); \\\n"
1858" mp->_vl_msg_id = ntohs (VL_API_##T); \\\n"
1859" mp->client_index = api_main.my_client_index; \\\n"
1860"} while(0);\n\n";
1861
1862char * s_macro_boilerplate =
1863"#define S (vl_msg_api_send_shmem (api_main.shmem_hdr->vl_input_queue, \\\n"
1864"(u8 *)&mp));\n\n";
1865
1866char * w_macro_boilerplate =
1867"#define W \\\n"
1868"do { \\\n"
1869" timeout = clib_time_now (&clib_time) + 1.0; \\\n"
1870" \\\n"
1871" while (clib_time_now (&clib_time) < timeout) { \\\n"
1872" if (api_result_ready == 1) { \\\n"
1873" return ((jint) api_result); \\\n"
1874" } \\\n"
1875" } \\\n"
1876" return -99; \\\n"
1877"} while(0);\n\n";
1878
1879void generate_jni_top_boilerplate(FILE *fp)
1880
1881{
1882 char *datestring = ctime(&starttime);
1883 fixed_name = fixup_input_filename();
1884
1885 datestring[24] = 0;
1886
1887 fprintf (fp, "/*\n");
1888 fprintf (fp, " * VLIB Java native code %s\n", datestring);
1889 fprintf (fp, " * Input file: %s\n", input_filename);
1890 fprintf (fp, " * Automatically generated: please edit the input file ");
1891 fprintf (fp, "NOT this file!\n");
1892 fprintf (fp, " */\n\n");
1893
1894 fprintf (fp, "#include <japi/vppjni.h>\n");
1895
1896 fprintf (fp,
1897 "#define vl_api_version(n,v) static u32 %s_api_version %s = v;\n",
1898 vlib_app_name, "__attribute__((unused))");
1899 fprintf (fp, "#include <api/%s.api.h>\n", vlib_app_name);
1900 fprintf (fp, "#undef vl_api_version\n\n");
1901
1902 fprintf (fp, "#include <japi/org_openvpp_vppjapi_vppConn.h>\n");
1903 fprintf (fp, "#include <japi/org_openvpp_vppjapi_%s.h>\n\n", java_class);
1904
1905 fprintf (fp, "#include <api/%s_msg_enum.h>\n", vlib_app_name);
1906 fprintf (fp, "#define vl_typedefs /* define message structures */\n");
1907 fprintf (fp, "#include <api/%s_all_api_h.h> \n", vlib_app_name);
1908 fprintf (fp, "#undef vl_typedefs\n\n");
1909
1910 fprintf (fp, "#define vl_endianfun \n");
1911 fprintf (fp, "#include <api/%s_all_api_h.h> \n", vlib_app_name);
1912 fprintf (fp, "#undef vl_endianfun\n\n");
1913
1914 fprintf (fp, "#define vl_print(handle, ...)\n");
1915 fprintf (fp, "#define vl_printfun\n");
1916 fprintf (fp, "#include <api/%s_all_api_h.h>\n", vlib_app_name);
1917 fprintf (fp, "#undef vl_printfun\n\n");
1918}
1919
1920void generate_jni_code (YYSTYPE a1, FILE *fp)
1921{
1922 node_t *np = (node_t *)a1;
1923 node_vft_t *vftp;
1924
1925 /* Walk the top-level node-list */
1926 while (np) {
1927 if (np->type == NODE_DEFINE) {
1928 if (!(np->flags & (NODE_FLAG_MANUAL_JAVA | NODE_FLAG_TYPEONLY))) {
1929 /* Suppress messages named "xyz_reply" */
1930 char * cp = (char *) np->data[0];
1931 while (*cp)
1932 cp++;
1933 cp -= 6;
1934 if (strncmp (cp, "_reply", 6)) {
1935 current_def_name = np->data[0];
1936 current_java_parameter_number = 0;
1937 vftp = the_vft[np->type];
1938 vftp->generate(np, JAVA_JNI_PASS, fp);
1939 }
1940 }
1941 }
1942 np = np->peer;
1943 }
1944}
1945
1946char *hookup_boilerplate =
1947"void vl_msg_reply_handler_hookup (void)\n"
1948"{\n"
1949"#define _(N,n) \\\n"
1950" vl_msg_api_set_handlers (VL_API_##N, #n, \\\n"
1951" vl_api_generic_reply_handler, \\\n"
1952" vl_noop_handler, \\\n"
1953" vl_api_##n##_t_endian, \\\n"
1954" vl_api_##n##_t_print, \\\n"
1955" sizeof(vl_api_##n##_t), 1); \n"
1956" foreach_api_reply_handler;\n"
1957"#undef _\n\n"
1958"}\n\n";
1959
1960void generate_jni_bottom_boilerplate(FILE *fp)
1961{
1962 fputs (hookup_boilerplate, fp);
1963}
1964
1965void generate(YYSTYPE a1)
1966{
1967 if (dump_tree) {
1968 dump((node_t *)a1);
1969 }
1970
1971 add_msg_ids(a1);
1972
1973 if (ofp) {
1974 generate_top_boilerplate(ofp);
1975
1976 generate_msg_ids(a1, ofp);
1977 generate_msg_names(a1, ofp);
1978 generate_typedefs(a1, ofp);
1979 generate_uniondefs(a1, ofp);
1980 generate_printfun(a1, ofp);
1981 generate_endianfun(a1, ofp);
1982
1983 generate_bottom_boilerplate(ofp);
1984 }
1985
1986 if (javafp) {
1987 generate_java_top_boilerplate(javafp);
1988 generate_java_class_definition(a1, javafp);
1989 generate_java_bottom_boilerplate(javafp);
1990 }
1991 if (jnifp) {
1992 generate_jni_top_boilerplate(jnifp);
1993 generate_jni_reply_handler_list (a1, jnifp);
1994 generate_jni_code(a1, jnifp);
1995 generate_jni_bottom_boilerplate(jnifp);
1996 }
1997}