blob: 420a128c00e61fffa1c1bc7d58cac6e894f9358e [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;
Ole Troan6855f6c2016-04-09 03:16:30 +020035FILE *pythonfp;
Ed Warnickecb9cada2015-12-08 15:45:58 -070036time_t starttime;
37char *vlib_app_name;
38char *input_filename;
39node_vft_t *the_vft[NODE_N_TYPES];
40static int indent;
41static int dont_output_version;
42int dump_tree;
43static char *fixed_name;
44static char tmpbuf [MAXNAME];
45static char *current_def_name;
46static char *current_union_name;
47static char *current_type_fmt;
48static char *current_type_cast;
49static char current_id;
50static char current_is_complex;
51static char *current_endianfun;
52static char *current_type_name;
Ed Warnickecb9cada2015-12-08 15:45:58 -070053
54void indent_me(FILE *ofp)
55{
56 int i;
57
58 for (i = 0; i < indent; i++)
59 putc(' ', ofp);
60}
61
62char *uppercase (char *s)
63{
64 char *cp;
65
66 cp = tmpbuf;
67
68 while (*s && (cp < tmpbuf + (sizeof(tmpbuf)-1))) {
69 if (*s >= 'a' && *s <= 'z')
70 *cp++ = *s++ - ('a' - 'A');
71 else
72 *cp++ = *s++;
73 }
74 *cp = 0;
75 return(tmpbuf);
76}
77
78char *lowercase (char *s)
79{
80 char *cp;
81
82 cp = tmpbuf;
83
84 while (*s && (cp < tmpbuf + (sizeof(tmpbuf)-1))) {
85 if (*s >= 'A' && *s <= 'Z')
86 *cp++ = *s++ + ('a' - 'A');
87 else
88 *cp++ = *s++;
89 }
90 *cp = 0;
91 return(tmpbuf);
92}
93
Ed Warnickecb9cada2015-12-08 15:45:58 -070094void primtype_recursive_print(node_t *this, i8 *fmt)
95{
96 fputs((char *)fmt, stdout);
97
98 if (this->deeper) {
99 node_vft_t *vftp = the_vft[this->deeper->type];
100 vftp->print(this->deeper);
101 }
102}
103
104void primtype_recursive_generate(node_t *this, enum passid which, FILE *ofp,
105 i8 *type_name, i8 *type_fmt, i8 *type_cast)
106{
107 node_vft_t *vftp;
108
109 current_type_name = (char *)type_name;
110 current_type_cast = (char *)type_cast;
111
112 switch(which) {
113 case TYPEDEF_PASS:
114 fputs((char *)type_name, ofp);
115 fputs(" ", ofp);
116 break;
117
118 case PRINTFUN_PASS:
119 current_type_fmt = (char *)type_fmt;
120 break;
121
122 case ENDIANFUN_PASS:
123 vftp = the_vft[this->type];
124 current_endianfun = vftp->endian_converter;
125 break;
126
Ole Troan6855f6c2016-04-09 03:16:30 +0200127 case PYTHON_PASS:
128 fputs("('", pythonfp);
129 fputs((char *)type_name, pythonfp);
130 fputs("', ", pythonfp);
131 break;
132
Ed Warnickecb9cada2015-12-08 15:45:58 -0700133 default:
134 fprintf(stderr, "primtype_recursive_generate: unimp pass %d\n", which);
135 break;
136 }
137
138 if (this->deeper) {
139 vftp = the_vft[this->deeper->type];
140 vftp->generate(this->deeper, which, ofp);
141 }
142}
143
Ed Warnickecb9cada2015-12-08 15:45:58 -0700144void node_illegal_print (node_t *this)
145{
146 fprintf(stderr, "node_illegal_print called\n");
147 exit(0);
148}
149
150void node_illegal_generate (node_t *this, enum passid notused, FILE *ofp)
151{
152 fprintf(stderr, "node_illegal_generate called\n");
153 exit(0);
154}
155
Ed Warnickecb9cada2015-12-08 15:45:58 -0700156node_vft_t node_illegal_vft = {
157 node_illegal_print,
158 node_illegal_generate,
Marek Gradzki948b95a2016-07-20 14:53:48 +0200159 "illegal"
Ed Warnickecb9cada2015-12-08 15:45:58 -0700160};
161
162void node_u8_print (node_t *this)
163{
164 primtype_recursive_print(this, "u8 ");
165}
166
167void node_u8_generate (node_t *this, enum passid which, FILE *ofp)
168{
169 primtype_recursive_generate(this, which, ofp, "u8", "%u", "(unsigned)");
170}
171
Ed Warnickecb9cada2015-12-08 15:45:58 -0700172node_vft_t node_u8_vft = {
173 node_u8_print,
174 node_u8_generate,
Chris Luke1642e392016-07-22 09:40:19 -0400175 NULL
Ed Warnickecb9cada2015-12-08 15:45:58 -0700176};
177
178void node_u16_print (node_t *this)
179{
180 primtype_recursive_print(this, "u16 ");
181}
182
183void node_u16_generate (node_t *this, enum passid which, FILE *ofp)
184{
185 primtype_recursive_generate(this, which, ofp, "u16", "%u", "(unsigned)");
186}
187
Ed Warnickecb9cada2015-12-08 15:45:58 -0700188node_vft_t node_u16_vft = {
189 node_u16_print,
190 node_u16_generate,
Marek Gradzki948b95a2016-07-20 14:53:48 +0200191 "clib_net_to_host_u16"
Ed Warnickecb9cada2015-12-08 15:45:58 -0700192};
193
194void node_u32_print (node_t *this)
195{
196 primtype_recursive_print(this, "u32 ");
197}
198
199void node_u32_generate (node_t *this, enum passid which, FILE *ofp)
200{
201 primtype_recursive_generate(this, which, ofp, "u32", "%u", "(unsigned)");
202}
203
Ed Warnickecb9cada2015-12-08 15:45:58 -0700204node_vft_t node_u32_vft = {
205 node_u32_print,
206 node_u32_generate,
207 "clib_net_to_host_u32",
Ed Warnickecb9cada2015-12-08 15:45:58 -0700208};
209
210void node_u64_print (node_t *this)
211{
212 primtype_recursive_print(this, "u64 ");
213}
214
215void node_u64_generate (node_t *this, enum passid which, FILE *ofp)
216{
217 primtype_recursive_generate(this, which, ofp, "u64", "%llu",
218 "(long long)");
219}
220
Ed Warnickecb9cada2015-12-08 15:45:58 -0700221node_vft_t node_u64_vft = {
222 node_u64_print,
223 node_u64_generate,
Marek Gradzki948b95a2016-07-20 14:53:48 +0200224 "clib_net_to_host_u64"
Ed Warnickecb9cada2015-12-08 15:45:58 -0700225};
226
227void node_i8_print (node_t *this)
228{
229 primtype_recursive_print(this, "i8 ");
230}
231
232void node_i8_generate (node_t *this, enum passid which, FILE *ofp)
233{
234 primtype_recursive_generate(this, which, ofp, "i8", "%d", "(int)");
235}
236
237node_vft_t node_i8_vft = {
238 node_i8_print,
239 node_i8_generate,
Marek Gradzki948b95a2016-07-20 14:53:48 +0200240 ""
Ed Warnickecb9cada2015-12-08 15:45:58 -0700241};
242
243void node_i16_print (node_t *this)
244{
245 primtype_recursive_print(this, "i16 ");
246}
247
248void node_i16_generate (node_t *this, enum passid which, FILE *ofp)
249{
250 primtype_recursive_generate(this, which, ofp, "i16", "%d", "(int)");
251}
252
253node_vft_t node_i16_vft = {
254 node_i16_print,
255 node_i16_generate,
Marek Gradzki948b95a2016-07-20 14:53:48 +0200256 "clib_net_to_host_u16"
Ed Warnickecb9cada2015-12-08 15:45:58 -0700257};
258
259void node_i32_print (node_t *this)
260{
261 primtype_recursive_print(this, "i32 ");
262}
263
264void node_i32_generate (node_t *this, enum passid which, FILE *ofp)
265{
266 primtype_recursive_generate(this, which, ofp, "i32", "%ld", "(long)");
267}
268
269node_vft_t node_i32_vft = {
270 node_i32_print,
271 node_i32_generate,
Marek Gradzki948b95a2016-07-20 14:53:48 +0200272 "clib_net_to_host_u32"
Ed Warnickecb9cada2015-12-08 15:45:58 -0700273};
274
275void node_i64_print (node_t *this)
276{
277 primtype_recursive_print(this, "i64 ");
278}
279
280void node_i64_generate (node_t *this, enum passid which, FILE *ofp)
281{
282 primtype_recursive_generate(this, which, ofp, "i64", "%lld",
283 "(long long)");
284}
285
286node_vft_t node_i64_vft = {
287 node_i64_print,
288 node_i64_generate,
Marek Gradzki948b95a2016-07-20 14:53:48 +0200289 "clib_net_to_host_u64"
Ed Warnickecb9cada2015-12-08 15:45:58 -0700290};
291
292void node_f64_print (node_t *this)
293{
294 primtype_recursive_print(this, "f64 ");
295}
296
297void node_f64_generate (node_t *this, enum passid which, FILE *ofp)
298{
299 primtype_recursive_generate(this, which, ofp, "f64", "%.2f",
300 "(double)");
301}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700302
303node_vft_t node_f64_vft = {
304 node_f64_print,
305 node_f64_generate,
306 " ", /* FP numbers are sent in host byte order */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700307};
308
309
310void node_packed_print (node_t *this)
311{
312 primtype_recursive_print (this, "packed ");
313}
314
315void node_packed_generate (node_t *this, enum passid which, FILE *ofp)
316{
317 primtype_recursive_generate(this, which, ofp, "PACKED", "", "");
318}
319
320node_vft_t node_packed_vft = {
321 node_packed_print,
322 node_packed_generate,
323 0,
324};
325
326void node_define_print (node_t *this)
327{
328 fprintf(stdout, "define %s {\n", CDATA0);
329 if (this->deeper) {
330 node_vft_t *vftp = the_vft[this->deeper->type];
331 fprintf(stdout, " ");
332 vftp->print(this->deeper);
333 }
334 fprintf(stdout, "};\n");
335}
336
337void node_define_generate (node_t *this, enum passid which, FILE *fp)
338{
339 node_t *child, *save_child;
340
341 switch(which) {
342 case TYPEDEF_PASS:
343 fprintf(fp, "typedef VL_API_PACKED(struct _vl_api_%s {\n", CDATA0);
344 child = this->deeper;
345 indent += 4;
346 while (child) {
347 node_vft_t *vftp = the_vft[child->type];
348 indent_me(fp);
349 vftp->generate(child, which, fp);
350 child = child->peer;
351 }
352 indent -= 4;
353 fprintf(fp, "}) vl_api_%s_t;\n\n", CDATA0);
354 break;
355
356 case ENDIANFUN_PASS:
357 case PRINTFUN_PASS:
358 child = this->deeper;
359 while (child) {
360 node_vft_t *vftp = the_vft[child->type];
361 vftp->generate(child, which, fp);
362 child = child->peer;
363 }
364 break;
365
Ole Troan6855f6c2016-04-09 03:16:30 +0200366 case PYTHON_PASS:
367 fprintf(fp, "('%s',\n", CDATA0);
368 child = this->deeper;
369 indent += 4;
370 while (child) {
371 node_vft_t *vftp = the_vft[child->type];
372 indent_me(fp);
373 vftp->generate(child, which, fp);
374 child = child->peer;
375 }
376 indent -= 4;
377 fprintf(fp, "),\n\n");
378 break;
379
Ed Warnickecb9cada2015-12-08 15:45:58 -0700380 default:
381 fprintf(stderr, "node_define_generate: unimp pass %d\n", which);
382 break;
383 }
384}
385
386node_vft_t node_define_vft = {
387 node_define_print,
388 node_define_generate,
389 0,
390};
391
392void node_union_print (node_t *this)
393{
394 primtype_recursive_print (this, "union ");
395}
396
397void node_union_generate (node_t *this, enum passid which, FILE *fp)
398{
399 node_t *child;
400 node_t *uelem;
401 int case_id=1;
402
403 switch(which) {
404 case TYPEDEF_PASS:
405 fprintf(fp, "u8 _%s_which;\n", CDATA0);
406 indent_me(fp);
407 fprintf(fp, "union _%s {\n", CDATA0);
408 child = this->deeper;
409 indent += 4;
410
411 while (child) {
412 node_vft_t *vftp = the_vft[child->type];
413 indent_me(fp);
414 vftp->generate(child, which, fp);
415 child = child->peer;
416 }
417 indent -= 4;
418 indent_me(fp);
419 fprintf(fp, "} %s;\n", CDATA0);
420 break;
421
422 case PRINTFUN_PASS:
423 case ENDIANFUN_PASS:
424 uelem = this->deeper;
425
426 indent_me(fp);
427 fprintf(fp, "switch(a->_%s_which) {\n",
428 CDATA0);
429 indent += 4;
430 current_union_name = CDATA0;
431
432 /* Walk the list of objects in this union */
433 while (uelem) {
434 node_vft_t *vftp = the_vft[uelem->type];
435 indent -= 4;
436 indent_me(fp);
437 fprintf(fp, "case %d:\n", case_id);
438 case_id++;
439 indent += 4;
440 /* Drill down on each element */
441 vftp->generate(uelem, which, fp);
442 indent_me(fp);
443 fprintf(fp, "break;\n");
444 uelem = uelem->peer;
445 }
446 current_union_name = 0;
447 indent -= 4;
448 indent_me(fp);
449 fprintf(fp, "default:\n");
450 indent += 4;
451 indent_me(fp);
452 if (which == PRINTFUN_PASS) {
453 fprintf(fp,
454 "vl_print(handle, \"WARNING: _%s_which not set.\\n\");\n",
455 CDATA0);
456 }
457 indent_me(fp);
458 fprintf(fp, "break;\n");
459 indent -= 4;
460 indent_me(fp);
461 fprintf(fp, "}\n");
462 break;
463
464 default:
465 fprintf(stderr, "node_union_generate: unimp pass %d\n", which);
466 break;
467 }
468}
469
470
471node_vft_t node_union_vft = {
472 node_union_print,
473 node_union_generate,
474 0,
475};
476
477void node_scalar_print (node_t *this)
478{
479 fprintf(stdout, "%s", CDATA0);
480 primtype_recursive_print (this, "");
481}
482
483void node_scalar_generate (node_t *this, enum passid which, FILE *fp)
484{
485 char *union_prefix = "";
486
487 if (current_union_name) {
488 sprintf(tmpbuf, "%s.", current_union_name);
489 union_prefix = tmpbuf;
490 }
491
492 switch(which) {
493 case TYPEDEF_PASS:
494 fprintf(fp, "%s;\n", CDATA0);
495 break;
496
497 case PRINTFUN_PASS:
498 indent_me(fp);
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);
502 } else {
503 if (!strcmp(current_type_fmt, "uword")) {
504 fprintf(fp,
505 "vl_print(handle, \"%s%s: \" _uword_fmt \"\\n\", %s a->%s%s);\n",
506 union_prefix, CDATA0, "(_uword_cast)",
507 union_prefix, CDATA0);
508 } else {
509 fprintf(fp,
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);
514 }
515 }
516 break;
517
518 case ENDIANFUN_PASS:
519 indent_me(fp);
520 if (current_is_complex) {
521 fprintf(fp, "vl_api%s_t_endian(a->%s%s);\n",
522 current_type_name, union_prefix, CDATA0);
523 } else {
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);
529 } else {
Chris Luke1642e392016-07-22 09:40:19 -0400530 fprintf(fp, "/* a->%s%s = a->%s%s (no-op) */\n",
Ed Warnickecb9cada2015-12-08 15:45:58 -0700531 union_prefix, CDATA0,
532 union_prefix, CDATA0);
533 }
534 }
535 break;
Ole Troan6855f6c2016-04-09 03:16:30 +0200536 case PYTHON_PASS:
537 fprintf(fp, "'%s'),\n", CDATA0);
538 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700539
540 default:
541 fprintf(stderr, "node_scalar_generate: unimp pass %d\n", which);
542 }
543 if (this->deeper) {
544 fprintf(stderr, "broken recursion in node_scalar_generate\n");
545 }
546}
547
548
549node_vft_t node_scalar_vft = {
550 node_scalar_print,
551 node_scalar_generate,
552 0,
553};
554
555void node_vector_print (node_t *this)
556{
557 primtype_recursive_print (this, "vector ");
558}
559
560void node_vector_generate (node_t *this, enum passid which, FILE *fp)
561{
562 char *union_prefix = "";
563
564 if (current_union_name) {
565 sprintf(tmpbuf, "%s.", current_union_name);
566 union_prefix = tmpbuf;
567 }
568
569 switch(which) {
570 case TYPEDEF_PASS:
571 fprintf(fp, "%s[%d];\n", CDATA0, IDATA1);
572 break;
573
574 case PRINTFUN_PASS:
575 /* Don't bother about "u8 data [0];" et al. */
576 if (IDATA1 == 0)
577 break;
578
579 indent_me(fp);
580 fprintf(fp, "{\n");
581 indent += 4;
582 indent_me(fp);
583 fprintf(fp, "int _i;\n");
584 indent_me(fp);
585 fprintf(fp, "for (_i = 0; _i < %d; _i++) {\n",
586 IDATA1);
587 indent += 4;
588 indent_me(fp);
589 if (current_is_complex) {
590 fprintf(fp, "vl_print(handle, \"%s%s[%%d]: ",
591 union_prefix, CDATA0);
592 fprintf(fp,
593 "vl_print_%s (handle, a->%s%s[_i]);\n",
594 CDATA0, union_prefix, CDATA0);
595 } else {
596 fprintf(fp,
597 "vl_print(handle, \"%s%s[%%d]: %s\\n\", _i, a->%s%s[_i]);\n",
598 union_prefix, CDATA0,
599 current_type_fmt,
600 union_prefix, CDATA0);
601 }
602 indent -= 4;
603 indent_me(fp);
604 fprintf(fp, "}\n");
605 indent -= 4;
606 indent_me(fp);
607 fprintf(fp, "}\n");
608 break;
609
610 case ENDIANFUN_PASS:
611 /* Don't bother about "u8 data [0];" et al. */
612 if (IDATA1 == 0)
613 break;
Chris Luke1642e392016-07-22 09:40:19 -0400614 /* 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.
616 */
617 if (!current_is_complex && current_endianfun == NULL) {
618 indent_me(fp);
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);
622 break;
623 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700624
625 indent_me(fp);
626 fprintf(fp, "{\n");
627 indent += 4;
628 indent_me(fp);
629 fprintf(fp, "int _i;\n");
630 indent_me(fp);
631 fprintf(fp, "for (_i = 0; _i < %d; _i++) {\n",
632 IDATA1);
633 indent += 4;
634 indent_me(fp);
635 if (current_is_complex) {
636 fprintf(fp,
637 "vl_api_%s_t_endian (a->%s%s[_i]);\n",
638 current_type_name, union_prefix, CDATA0);
639 } else {
640 fprintf(fp,
641 "a->%s%s[_i] = %s(a->%s%s[_i]);\n",
642 union_prefix, CDATA0,
643 current_endianfun,
644 union_prefix, CDATA0);
645 }
646 indent -= 4;
647 indent_me(fp);
648 fprintf(fp, "}\n");
649 indent -= 4;
650 indent_me(fp);
651 fprintf(fp, "}\n");
652 break;
Ole Troan6855f6c2016-04-09 03:16:30 +0200653 case PYTHON_PASS:
Marek Gradzkifa42e252016-06-15 16:38:33 +0200654 if (CDATA2 != 0) { // variable length vector
655 fprintf(fp, "'%s', '%d', '%s'),\n", CDATA0, IDATA1, CDATA2);
656 } else {
657 fprintf(fp, "'%s', '%d'),\n", CDATA0, IDATA1);
658 }
Ole Troan6855f6c2016-04-09 03:16:30 +0200659 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700660
661 default:
662 fprintf(stderr, "node_vector_generate: unimp pass %d\n", which);
663 }
664 if (this->deeper) {
665 fprintf(stderr, "broken recursion in node_vector_generate\n");
666 }
667}
668
669node_vft_t node_vector_vft = {
670 node_vector_print,
671 node_vector_generate,
672 0,
673};
674
675void node_complex_print (node_t *this)
676{
677 primtype_recursive_print (this, "complex ");
678}
679
680void node_complex_generate (node_t *this, enum passid which, FILE *fp)
681{
682 node_t *deeper;
683 node_vft_t *vftp;
684 char *member_name = "broken!";
685 char *union_prefix = "";
686
687 if (current_union_name) {
688 sprintf(tmpbuf, "%s.", current_union_name);
689 union_prefix = tmpbuf;
690 }
691
692 current_is_complex++;
693
694 switch(which) {
695 case TYPEDEF_PASS:
696 fprintf(fp, "%s ", CDATA0);
697 deeper = this->deeper;
698 if (deeper) {
699 vftp = the_vft[deeper->type];
700 vftp->generate(deeper, which, fp);
701 }
702 break;
703
704 case PRINTFUN_PASS:
705 deeper = this->deeper;
706 while (deeper) {
707 if (deeper->type == NODE_SCALAR ||
708 deeper->type == NODE_VECTOR) {
709 member_name = deeper->data[0];
710 break;
711 }
712 deeper = deeper->deeper;
713 }
714 indent_me(fp);
715 fprintf(fp, "vl_print(handle, \"%s%s ----- \\n\");\n",
716 union_prefix, member_name);
717 indent_me(fp);
718 fprintf(fp, "%s_print(&a->%s%s, handle);\n",
719 CDATA0, union_prefix, member_name);
720 indent_me(fp);
721 fprintf(fp, "vl_print(handle, \"%s%s ----- END \\n\");\n",
722 union_prefix, member_name);
723 break;
724
725 case ENDIANFUN_PASS:
726 deeper = this->deeper;
727 while (deeper) {
728 if (deeper->type == NODE_SCALAR ||
729 deeper->type == NODE_VECTOR) {
730 member_name = deeper->data[0];
731 break;
732 }
733 deeper = deeper->deeper;
734 }
735
736 indent_me(fp);
737 fprintf(fp, "%s_endian(&a->%s%s);\n",
738 CDATA0, union_prefix, member_name);
739 break;
Ole Troan6855f6c2016-04-09 03:16:30 +0200740 case PYTHON_PASS:
741 fprintf(fp, "('%s',", CDATA0);
742 deeper = this->deeper;
743 if (deeper) {
744 vftp = the_vft[deeper->type];
745 vftp->generate(deeper, which, fp);
746 }
747 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700748
749 default:
750 fprintf(stderr, "node_complex_generate unimp pass %d...\n", which);
751 break;
752 }
753 current_is_complex--;
754}
755
756node_vft_t node_complex_vft = {
757 node_complex_print,
758 node_complex_generate,
759 0,
760};
761
762void node_noversion_print (node_t *this)
763{
764 primtype_recursive_print (this, "noversion ");
765}
766
767void node_noversion_generate (node_t *this, enum passid which, FILE *ofp)
768{
769 fprintf(stderr, "node_noversion_generate called...\n");
770}
771
772node_vft_t node_noversion_vft = {
773 node_noversion_print,
774 node_noversion_generate,
775 0,
776};
777
778void node_uword_print (node_t *this)
779{
780 primtype_recursive_print(this, "uword ");
781}
782
783void node_uword_generate (node_t *this, enum passid which, FILE *ofp)
784{
785 primtype_recursive_generate(this, which, ofp, "uword", "uword", "");
786}
787
788node_vft_t node_uword_vft = {
789 node_uword_print,
790 node_uword_generate,
791 "clib_net_to_host_uword",
792};
793
794node_vft_t *the_vft[NODE_N_TYPES] = {
795 &node_illegal_vft,
796 &node_u8_vft,
797 &node_u16_vft,
798 &node_u32_vft,
799 &node_u64_vft,
800 &node_i8_vft,
801 &node_i16_vft,
802 &node_i32_vft,
803 &node_i64_vft,
804 &node_f64_vft,
805 &node_packed_vft,
806 &node_define_vft,
807 &node_union_vft,
808 &node_scalar_vft,
809 &node_vector_vft,
810 &node_complex_vft,
811 &node_noversion_vft,
812 &node_uword_vft,
813};
814
815void *make_node (enum node_subclass type)
816{
817 node_t *rv;
818
819 rv = (node_t *) malloc (sizeof (*rv));
820 if (rv == 0) {
821 fprintf (stderr, "fatal: make_node out of memory\n");
822 exit (1);
823 }
824 bzero (rv, sizeof (*rv));
825 rv->type = type;
826 return ((void *) rv);
827}
828
829YYSTYPE deeper (YYSTYPE arg1, YYSTYPE arg2)
830{
831 node_t *np1 = (node_t *) arg1;
832 node_t *np2 = (node_t *) arg2;
833 node_t *hook_point;
834
835 hook_point = np1;
836
837 while (hook_point->deeper)
838 hook_point = hook_point->deeper;
839
840 hook_point->deeper = np2;
841 return (arg1);
842}
843
844YYSTYPE addpeer (YYSTYPE arg1, YYSTYPE arg2)
845{
846 node_t *np1 = (node_t *) arg1;
847 node_t *np2 = (node_t *) arg2;
848 node_t *hook_point;
849
850 hook_point = np1;
851
852 while (hook_point->peer)
853 hook_point = hook_point->peer;
854
855 hook_point->peer = np2;
856 return (arg1);
857}
858
859/*
860 * add_slist (stmt_list, stmt)
861 */
862
863YYSTYPE add_slist (YYSTYPE a1, YYSTYPE a2)
864{
865 if (a1 && a2)
866 return (addpeer(a1, a2));
867 else if(a1)
868 return(a1);
869 else
870 return(a2);
871}
872
873/*
874 * add_define (char *name, defn_list);
875 */
876YYSTYPE add_define (YYSTYPE a1, YYSTYPE a2)
877{
878 node_t *np;
879
880 np = make_node(NODE_DEFINE);
881 np->data[0] = a1;
882 deeper((YYSTYPE)np, a2);
883 return ((YYSTYPE) np);
884}
885
886/*
887 * add_defbody (defn_list, new_defn)
888 */
889YYSTYPE add_defbody (YYSTYPE a1, YYSTYPE a2)
890{
891 return (addpeer(a1, a2));
892}
893
894/*
895 * add_primtype ([packed], primitive type, instance)
896 */
897
898YYSTYPE add_primtype (YYSTYPE a1, YYSTYPE a2, YYSTYPE a3)
899{
900 node_t *np1;
901
902 np1 = (node_t *)a1;
903
904 /* Hook instance to type node */
905 deeper (a1, a2);
906 if (a3) {
907 deeper(a1, a3);
908 }
909 return (a1);
910}
911
912/*
913 * add_complex(char *type_name, instance)
914 */
915
916YYSTYPE add_complex (YYSTYPE a1, YYSTYPE a2)
917{
918 node_t *np;
919
920 np = make_node(NODE_COMPLEX);
921 np->data[0] = (void *) a1;
922
923 deeper((YYSTYPE)np, a2);
924 return ((YYSTYPE) np);
925}
926
927/*
928 * add_union(char *type_name, definition)
929 */
930
931YYSTYPE add_union (YYSTYPE a1, YYSTYPE a2)
932{
933 node_t *np;
934
935 np = make_node(NODE_UNION);
936 np->data[0] = (void *) a1;
937
938 deeper((YYSTYPE)np, a2);
939 return ((YYSTYPE) np);
940}
941
942
943/*
944 * add_vector_vbl (node_t *variable, YYSTYPE size)
945 */
946
947YYSTYPE add_vector_vbl (YYSTYPE a1, YYSTYPE a2)
948{
949 node_t *np;
950
951 np = make_node(NODE_VECTOR);
952 np->data[0] = (void *) a1;
953 np->data[1] = (void *) a2;
954 return ((YYSTYPE) np);
955}
956
957/*
Marek Gradzkifa42e252016-06-15 16:38:33 +0200958 * add_vector_vbl (char *vector_name, char *vector_length_var)
959 */
960
961YYSTYPE add_variable_length_vector_vbl (YYSTYPE vector_name, YYSTYPE vector_length_var)
962{
963 node_t *np;
964
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);
970}
971
972/*
Ed Warnickecb9cada2015-12-08 15:45:58 -0700973 * add_scalar_vbl (char *name)
974 */
975YYSTYPE add_scalar_vbl (YYSTYPE a1)
976{
977 node_t *np;
978
979 np = make_node(NODE_SCALAR);
980 np->data[0] = (void *) a1;
981 return ((YYSTYPE) np);
982}
983
984/*
985 * set_flags (int flags, msg(=0?))
986 */
987YYSTYPE set_flags(YYSTYPE a1, YYSTYPE a2)
988{
989 node_t *np;
990 int flags;
991
992 np = (node_t *)a2;
993 if (!np)
994 return(0);
995
996 flags = (int)(uword) a1;
997
998 np->flags |= flags;
999 return (a2);
1000}
1001/*
1002 * suppress_version
1003 */
1004YYSTYPE suppress_version (void)
1005{
1006 dont_output_version = 1;
1007 return (0);
1008}
1009
1010void dump(node_t *np)
1011{
1012 node_vft_t *vftp;
1013
1014 while (np) {
1015 vftp = the_vft[np->type];
1016 vftp->print(np);
1017 np = np->peer;
1018 }
1019}
1020
1021char *fixup_input_filename(void)
1022{
1023 char *cp;
1024
1025 cp = (char *)input_filename;
1026
1027 while (*cp)
1028 cp++;
1029
1030 cp--;
1031
1032 while (cp > input_filename && *cp != '/')
1033 cp--;
1034 if (*cp == '/')
1035 cp++;
1036
Dave Barachf9c231e2016-08-05 10:10:18 -04001037 strncpy (tmpbuf, cp, sizeof(tmpbuf)-1);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001038
1039 cp = tmpbuf;
1040
1041 while (*cp)
1042 cp++;
1043
1044 cp--;
1045
1046 while (cp > tmpbuf && *cp != '.')
1047 cp--;
1048
1049 if (*cp == '.')
1050 *cp = 0;
1051
1052 return (sxerox(tmpbuf));
1053}
1054
1055void generate_top_boilerplate(FILE *fp)
1056
1057{
1058 char *datestring = ctime(&starttime);
1059 fixed_name = fixup_input_filename();
1060
1061 datestring[24] = 0;
1062
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");
1068
1069 /* Moron Acme trigger workaround */
1070 fprintf (fp, " * %syright (c) %s by Cisco Systems, Inc.\n", "Cop",
1071 &datestring[20]);
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");
1082}
1083
1084void generate_bottom_boilerplate(FILE *fp)
1085
1086{
1087 fprintf (fp, "\n#ifdef vl_api_version\n");
1088
1089 if (dont_output_version) {
1090 fprintf (fp, "/* WARNING: API FILE VERSION CHECK DISABLED */\n");
1091 input_crc = 0;
1092 }
1093
1094 fprintf (fp, "vl_api_version(%s, 0x%08x)\n\n",
1095 fixed_name, (unsigned int)input_crc);
1096 fprintf (fp, "#endif\n\n");
1097}
1098
1099void generate_msg_ids(YYSTYPE a1, FILE *fp)
1100{
1101 node_t *np = (node_t *)a1;
1102
1103 fprintf (fp, "\n/****** Message ID / handler enum ******/\n\n");
1104 fprintf (fp, "#ifdef vl_msg_id\n");
1105
1106 while (np) {
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]);
1111 } else {
1112 fprintf (fp, "/* typeonly: %s */\n", (i8 *)np->data[0]);
1113 }
1114 }
1115 np = np->peer;
1116 }
1117 fprintf (fp, "#endif\n");
1118
1119}
1120
1121void generate_msg_names(YYSTYPE a1, FILE *fp)
1122{
1123 node_t *np = (node_t *)a1;
1124
1125 fprintf (fp, "\n/****** Message names ******/\n\n");
1126
1127 fprintf (fp, "#ifdef vl_msg_name\n");
1128
1129 while (np) {
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",
1133 (i8 *) np->data[0],
1134 (np->flags & NODE_FLAG_DONT_TRACE ? 0 : 1));
1135 } else {
1136 fprintf (fp, "/* typeonly: %s */\n", (i8 *)np->data[0]);
1137 }
1138 }
1139 np = np->peer;
1140 }
1141 fprintf (fp, "#endif\n\n");
1142}
1143
1144void generate_typedefs(YYSTYPE a1, FILE *fp)
1145{
1146 node_t *np = (node_t *)a1;
1147 node_vft_t *vftp;
1148
1149 fprintf(fp, "\n/****** Typedefs *****/\n\n");
1150 fprintf(fp, "#ifdef vl_typedefs\n\n");
1151
1152 /* Walk the top-level node-list */
1153 while (np) {
1154 if (np->type == NODE_DEFINE) {
1155 /* Yeah, this is pedantic */
1156 vftp = the_vft[np->type];
1157 vftp->generate(np, TYPEDEF_PASS, fp);
1158 }
1159 np = np->peer;
1160 }
1161 fprintf(fp, "#endif /* vl_typedefs */\n\n");
1162}
1163
1164void union_walk_one_defn(node_t *np, FILE *fp)
1165{
1166 node_t *vblp;
1167 node_t *uelem;
1168
1169 /* Walk the list of typed objects in this msg def */
1170 while (np) {
1171 if (np->type == NODE_UNION) {
1172 current_union_name = np->data[0];
1173 uelem = np->deeper;
1174
1175 /* Walk the list of objects in this union */
1176 while (uelem) {
1177 vblp = uelem->deeper;
1178 /* Drill down on each element, find the variable name */
1179 while(vblp) {
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]),
1187 current_id);
1188 current_id++;
1189 break;
1190 }
1191 vblp = vblp->deeper;
1192 }
1193 uelem = uelem->peer;
1194 }
1195 current_union_name = 0;
1196 current_id = 1;
1197 }
1198 np = np->peer;
1199 }
1200}
1201
1202void generate_uniondefs(YYSTYPE a1, FILE *fp)
1203{
1204 node_t *np = (node_t *)a1;
1205
1206 fprintf(fp, "/****** Discriminated Union Definitions *****/\n\n");
1207 fprintf(fp, "#ifdef vl_union_id\n\n");
1208
1209 /* Walk the top-level node-list */
1210 while (np) {
1211 if (np->type == NODE_DEFINE) {
1212 current_id = 1;
1213 current_def_name = np->data[0];
1214 union_walk_one_defn(np->deeper, fp);
1215 }
1216 np = np->peer;
1217 }
1218 fprintf(fp, "\n#endif /* vl_union_id */\n\n");
1219}
1220
1221void generate_printfun(YYSTYPE a1, FILE *fp)
1222{
1223 node_t *np = (node_t *)a1;
1224 node_vft_t *vftp;
1225
1226 fprintf(fp, "/****** Print functions *****/\n\n");
1227 fprintf(fp, "#ifdef vl_printfun\n\n");
1228
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");
1236
1237 /* Walk the top-level node-list */
1238 while (np) {
1239 if (np->type == NODE_DEFINE) {
1240 if (!(np->flags & NODE_FLAG_MANUAL_PRINT)) {
1241 fprintf(fp,
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 */
1246 fprintf(fp,
1247 " vl_print(handle, \"vl_api_%s_t:\\n\");\n",
1248 (i8 *)np->data[0]);
1249
1250 indent += 4;
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");
1256 indent -= 4;
1257 } else {
1258 fprintf(fp, "/***** manual: vl_api_%s_t_print *****/\n\n",
1259 (i8 *) np->data[0]);
1260 }
1261 }
1262 np = np->peer;
1263 }
1264 fprintf(fp, "#endif /* vl_printfun */\n\n");
1265}
1266
1267void generate_endianfun(YYSTYPE a1, FILE *fp)
1268{
1269 node_t *np = (node_t *)a1;
1270 node_vft_t *vftp;
1271
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");
1280
1281 /* Walk the top-level node-list */
1282 while (np) {
1283 if (np->type == NODE_DEFINE) {
1284 if (!(np->flags & NODE_FLAG_MANUAL_ENDIAN)) {
1285 fprintf(fp,
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]);
1288 indent += 4;
1289 /* Yeah, this is pedantic */
1290 vftp = the_vft[np->type];
1291 vftp->generate(np, ENDIANFUN_PASS, fp);
1292 fprintf(fp, "}\n\n");
1293 indent -= 4;
1294 } else {
1295 fprintf(fp, "/***** manual: vl_api_%s_t_endian *****/\n\n",
1296 (i8 *) np->data[0]);
1297 }
1298 }
1299 np = np->peer;
1300 }
1301 fprintf(fp, "#endif /* vl_endianfun */\n\n");
1302}
1303
1304void add_msg_ids(YYSTYPE a1)
1305{
1306 node_t *np = (node_t *)a1;
1307 node_t *new_u16;
1308 node_t *new_vbl;
1309
1310 /* Walk the top-level node-list */
1311 while (np) {
1312 if (np->type == NODE_DEFINE) {
1313 if (!(np->flags & NODE_FLAG_TYPEONLY)) {
Ole Troan6855f6c2016-04-09 03:16:30 +02001314 /* add the parse tree for "u16 _vl_msg_id" */
Ed Warnickecb9cada2015-12-08 15:45:58 -07001315 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;
Ole Troan6855f6c2016-04-09 03:16:30 +02001321 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001322 }
1323 np = np->peer;
1324 }
1325}
1326
Ole Troan6855f6c2016-04-09 03:16:30 +02001327void generate_python (YYSTYPE a1, FILE *fp)
1328{
1329 node_t *np = (node_t *)a1;
1330 node_vft_t *vftp;
1331 fprintf (fp, "vppapidef = [\n");
1332 /* Walk the top-level node-list */
1333 while (np) {
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);
1338 }
1339 np = np->peer;
1340 }
1341 fprintf (fp, "\n]\n");
Ole Troan5f9dcff2016-08-01 04:59:13 +02001342
1343 /*
1344 * API CRC signature
1345 */
1346 fprintf (fp, "vl_api_version = 0x%08x\n\n", (unsigned int)input_crc);
Ole Troan6855f6c2016-04-09 03:16:30 +02001347}
1348
Ed Warnickecb9cada2015-12-08 15:45:58 -07001349void generate(YYSTYPE a1)
1350{
1351 if (dump_tree) {
1352 dump((node_t *)a1);
1353 }
1354
1355 add_msg_ids(a1);
1356
1357 if (ofp) {
1358 generate_top_boilerplate(ofp);
1359
1360 generate_msg_ids(a1, ofp);
1361 generate_msg_names(a1, ofp);
1362 generate_typedefs(a1, ofp);
1363 generate_uniondefs(a1, ofp);
1364 generate_printfun(a1, ofp);
1365 generate_endianfun(a1, ofp);
1366
1367 generate_bottom_boilerplate(ofp);
1368 }
Ole Troan6855f6c2016-04-09 03:16:30 +02001369 if (pythonfp) {
1370 generate_python(a1, pythonfp);
1371 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001372}