1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * Copyright 2020 Tintri by DDN, Inc. All rights reserved.
29 */
30
31 #include <string.h>
32 #include "ndrgen.h"
33 #include "y.tab.h"
34
35
36 static void generate_struct(ndr_typeinfo_t *);
37 static void generate_params(ndr_typeinfo_t *);
38 static void generate_union(ndr_typeinfo_t *);
39 static void generate_arg(ndr_node_t *);
40 static void generate_member_macro(char *, char *, ndr_member_t *,
41 ndr_typeinfo_t *);
42 static void generate_member_macro_with_arg(char *, char *, ndr_member_t *,
43 ndr_typeinfo_t *, ndr_node_t *);
44 static void generate_prototypes(ndr_typeinfo_t *, char *);
45 static void generate_member_prototypes(ndr_typeinfo_t *, ndr_member_t *,
46 char *);
47 static void generate_member(ndr_typeinfo_t *, ndr_member_t *);
48 static void generate_aggregate_common_begin(ndr_typeinfo_t *);
49 static void generate_aggregate_common_finish(ndr_typeinfo_t *);
50 static void generate_typeinfo_packing(ndr_typeinfo_t *);
51 static void generate_typeinfo_typeinfo(ndr_typeinfo_t *, int, char *);
52
53
54 void
generate(void)55 generate(void)
56 {
57 ndr_typeinfo_t *ti;
58 char fname_type[NDLBUFSZ];
59
60 (void) printf("\n");
61
62 for (ti = typeinfo_list; ti; ti = ti->next) {
63 if (ti->is_extern || ti->advice.a_extern) {
64 type_extern_suffix(ti, fname_type, NDLBUFSZ);
65 (void) printf(
66 "extern struct ndr_typeinfo ndt_%s;\n",
67 fname_type);
68 continue;
69 }
70
71 switch (ti->type_op) {
72 case STRUCT_KW:
73 if (ti->advice.a_operation)
74 generate_params(ti);
75 else
76 generate_struct(ti);
77 break;
78
79 case UNION_KW:
80 generate_union(ti);
81 break;
82
83 case TYPEDEF_KW:
84 /* silently skip */
85 continue;
86
87 case STRING_KW:
88 case STAR:
89 case LB:
90 case BASIC_TYPE:
91 if (!ti->is_referenced) {
92 type_extern_suffix(ti, fname_type, NDLBUFSZ);
93 (void) printf("extern ndt_%s\n", fname_type);
94 type_null_decl(ti, fname_type, NDLBUFSZ);
95 (void) printf("/* %s */\n", fname_type);
96 }
97 break;
98
99 default:
100 continue;
101 }
102 }
103 }
104
105 static void
generate_struct(ndr_typeinfo_t * ti)106 generate_struct(ndr_typeinfo_t *ti)
107 {
108 int i;
109 ndr_member_t *mem;
110
111 if (ti->advice.a_no_reorder) {
112 /* just use generate_params(), which can safely do this */
113 generate_params(ti);
114 return;
115 }
116
117 generate_aggregate_common_begin(ti);
118
119 (void) printf(" /* do all basic elements first */\n");
120 for (i = 0; i < ti->n_member; i++) {
121 mem = &ti->member[i];
122 if (mem->type->type_op != BASIC_TYPE)
123 continue;
124
125 generate_member(ti, mem);
126 }
127
128 (void) printf("\n");
129 (void) printf(" /* do all constructed elements w/o pointers */\n");
130 for (i = 0; i < ti->n_member; i++) {
131 mem = &ti->member[i];
132 if (mem->type->type_op == BASIC_TYPE)
133 continue;
134
135 if (mem->type->has_pointers)
136 continue;
137
138 generate_member(ti, mem);
139 }
140
141 (void) printf("\n");
142 (void) printf(" /* do members with pointers in order */\n");
143 for (i = 0; i < ti->n_member; i++) {
144 mem = &ti->member[i];
145 if (mem->type->type_op == BASIC_TYPE)
146 continue;
147
148 if (!mem->type->has_pointers)
149 continue;
150
151 generate_member(ti, mem);
152 }
153
154 generate_aggregate_common_finish(ti);
155 }
156
157 static void
generate_params(ndr_typeinfo_t * ti)158 generate_params(ndr_typeinfo_t *ti)
159 {
160 int i;
161 ndr_member_t *mem;
162
163 generate_aggregate_common_begin(ti);
164
165 (void) printf(" /* do all members in order */\n");
166 for (i = 0; i < ti->n_member; i++) {
167 mem = &ti->member[i];
168
169 generate_member(ti, mem);
170 }
171
172 generate_aggregate_common_finish(ti);
173 }
174
175 static void
generate_union(ndr_typeinfo_t * ti)176 generate_union(ndr_typeinfo_t *ti)
177 {
178 int i;
179 ndr_member_t *mem;
180 int have_default = 0;
181 ndr_node_t *np;
182
183 generate_aggregate_common_begin(ti);
184
185 (void) printf(" switch (encl_ref->switch_is) {\n");
186
187 for (i = 0; i < ti->n_member; i++) {
188 mem = &ti->member[i];
189
190 if ((np = mem->advice.a_case) != 0) {
191 (void) printf(" case ");
192 print_node(np->n_a_arg);
193 (void) printf(":\n");
194 } else if ((np = mem->advice.a_default) != 0) {
195 (void) printf(" default:\n");
196 if (have_default++) {
197 compile_error("multiple defaults");
198 }
199 } else {
200 compile_error("syntax error");
201 }
202
203 generate_member(ti, mem);
204 (void) printf(" break;\n\n");
205 }
206
207 if (!have_default) {
208 (void) printf(" default:\n");
209 (void) printf(" NDR_SET_ERROR(encl_ref, "
210 "NDR_ERR_SWITCH_VALUE_INVALID);\n");
211 (void) printf(" return 0;\n");
212 (void) printf(" break;\n");
213 }
214
215 (void) printf(" }\n");
216 (void) printf("\n");
217
218 generate_aggregate_common_finish(ti);
219 }
220
221 static void
generate_arg(ndr_node_t * np)222 generate_arg(ndr_node_t *np)
223 {
224 ndr_node_t *arg = np;
225
226 if (np == NULL) {
227 compile_error("invalid node pointer <null>");
228 return;
229 }
230
231 if (np->label != IDENTIFIER && np->label != INTEGER)
232 arg = np->n_a_arg;
233
234 switch (np->label) {
235 case SIZE_IS_KW:
236 case LENGTH_IS_KW:
237 case SWITCH_IS_KW:
238 (void) printf("val->");
239 print_field_attr(np);
240 break;
241 default:
242 if (arg->label == IDENTIFIER)
243 (void) printf("val->%s", arg->n_sym->name);
244 else
245 print_node(arg);
246 break;
247 }
248 }
249
250 static void
generate_member_macro(char * memkind,char * macro,ndr_member_t * mem,ndr_typeinfo_t * ti)251 generate_member_macro(char *memkind, char *macro, ndr_member_t *mem,
252 ndr_typeinfo_t *ti)
253 {
254 char fname_type[NDLBUFSZ];
255
256 if (!macro)
257 macro = "";
258 if (!ti)
259 ti = mem->type;
260
261 type_extern_suffix(ti, fname_type, NDLBUFSZ);
262
263 if (memkind) {
264 (void) printf(" NDR_%sMEMBER%s (%s, %s);\n",
265 memkind, macro, fname_type, mem->name);
266 } else {
267 (void) printf(" NDR_MEMBER%s (%s, %s, %uUL);\n",
268 macro, fname_type, mem->name, mem->pdu_offset);
269 }
270 }
271
272 static void
generate_member_macro_with_arg(char * memkind,char * macro,ndr_member_t * mem,ndr_typeinfo_t * ti,ndr_node_t * np)273 generate_member_macro_with_arg(char *memkind, char *macro,
274 ndr_member_t *mem, ndr_typeinfo_t *ti, ndr_node_t *np)
275 {
276 char fname_type[NDLBUFSZ];
277
278 if (!macro)
279 macro = "_WITH_ARG";
280 if (!ti)
281 ti = mem->type;
282
283 type_extern_suffix(ti, fname_type, NDLBUFSZ);
284
285 if (memkind) {
286 (void) printf(" NDR_%sMEMBER%s (%s, %s,\n",
287 memkind, macro, fname_type, mem->name);
288 } else {
289 (void) printf(" NDR_MEMBER%s (%s, %s, %uUL,\n",
290 macro, fname_type, mem->name, mem->pdu_offset);
291 }
292
293 (void) printf("\t\t");
294 generate_arg(np);
295 (void) printf(");\n");
296 }
297
298 static void
generate_prototypes(ndr_typeinfo_t * ti,char * fname_type)299 generate_prototypes(ndr_typeinfo_t *ti, char *fname_type)
300 {
301 ndr_member_t *mem;
302 int i;
303
304 if (ti->type_op == STRUCT_KW && ti->advice.a_operation) {
305 for (i = 0; i < ti->n_member; i++) {
306 mem = &ti->member[i];
307
308 generate_member_prototypes(ti, mem, fname_type);
309 }
310 }
311 }
312
313 static void
generate_member_prototypes(ndr_typeinfo_t * ti,ndr_member_t * mem,char * fname_type)314 generate_member_prototypes(ndr_typeinfo_t *ti,
315 ndr_member_t *mem, char *fname_type)
316 {
317 char val_buf[NDLBUFSZ];
318 ndr_typeinfo_t ptr;
319
320 if (mem->type->type_op == UNION_KW) {
321 if (!mem->advice.a_in && mem->advice.a_out) {
322 ptr.type_op = STAR;
323 ptr.type_down = ti;
324 type_name_decl(&ptr, val_buf, NDLBUFSZ, "val");
325
326 (void) printf("\nextern void fixup%s(%s);\n",
327 fname_type, val_buf);
328 }
329 }
330 }
331
332 static void
generate_member(ndr_typeinfo_t * ti,ndr_member_t * mem)333 generate_member(ndr_typeinfo_t *ti, ndr_member_t *mem)
334 {
335 static char *fixup[] = {
336 "/*",
337 " * Cannot use the canned offsets to unmarshall multiple",
338 " * entry discriminated unions. The service must provide",
339 " * this function to patch the offsets at runtime.",
340 " */"
341 };
342
343 char fname_type[NDLBUFSZ];
344 ndr_node_t *np;
345 int is_reference = 0;
346 char *memkind = 0;
347 int cond_pending = 0;
348 int i;
349
350 if (ti->advice.a_operation)
351 memkind = "TOPMOST_";
352 else if (ti->advice.a_interface)
353 memkind = "PARAMS_";
354
355 if (mem->advice.a_in && !mem->advice.a_out) {
356 cond_pending = 1;
357 (void) printf(" if (NDR_DIR_IS_IN) {\n");
358 }
359
360 if (!mem->advice.a_in && mem->advice.a_out) {
361 cond_pending = 1;
362 (void) printf(" if (NDR_DIR_IS_OUT) {\n");
363 }
364
365 type_extern_suffix(ti, fname_type, NDLBUFSZ);
366
367 switch (mem->type->type_op) {
368 case BASIC_TYPE:
369 case STRUCT_KW:
370 generate_member_macro(memkind, 0, mem, 0);
371 break;
372
373 case UNION_KW:
374 np = mem->advice.a_switch_is;
375
376 if (!mem->advice.a_in && mem->advice.a_out) {
377 for (i = 0; i < sizeof (fixup)/sizeof (fixup[0]); ++i)
378 (void) printf("\t%s\n", fixup[i]);
379
380 (void) printf("\tfixup%s(val);\n", fname_type);
381 }
382
383 generate_member_macro_with_arg(memkind,
384 "_WITH_SWITCH_IS", mem, 0, np);
385 break;
386
387 case STAR:
388 if (mem->advice.a_reference)
389 is_reference = 1;
390 else
391 is_reference = 0;
392
393 np = mem->advice.a_size_is;
394 if (np) {
395 generate_member_macro_with_arg(memkind,
396 is_reference ?
397 "_REF_WITH_SIZE_IS" : "_PTR_WITH_SIZE_IS",
398 mem, mem->type->type_down, np);
399 break;
400 }
401
402 np = mem->advice.a_length_is;
403 if (np) {
404 generate_member_macro_with_arg(memkind,
405 is_reference ?
406 "_REF_WITH_LENGTH_IS" : "_PTR_WITH_LENGTH_IS",
407 mem, mem->type->type_down, np);
408 break;
409 }
410
411 generate_member_macro(memkind,
412 is_reference ? "_REF" : "_PTR",
413 mem, mem->type->type_down);
414 break;
415
416 case LB:
417 np = mem->advice.a_size_is;
418 if (np) {
419 generate_member_macro_with_arg(memkind,
420 "_ARR_WITH_SIZE_IS",
421 mem, mem->type->type_down, np);
422 break;
423 }
424
425 np = mem->advice.a_length_is;
426 if (np) {
427 generate_member_macro_with_arg(memkind,
428 "_WITH_LENGTH_IS",
429 mem, mem->type->type_down, np);
430 break;
431 }
432
433 generate_member_macro_with_arg(memkind,
434 "_ARR_WITH_DIMENSION",
435 mem, mem->type->type_down, mem->type->type_dim);
436 break;
437
438 default:
439 generate_member_macro(memkind, "_???", mem, 0);
440 break;
441 }
442
443 if (cond_pending)
444 (void) printf(" }\n");
445 }
446
447 static void
generate_aggregate_common_begin(ndr_typeinfo_t * ti)448 generate_aggregate_common_begin(ndr_typeinfo_t *ti)
449 {
450 char val_buf[NDLBUFSZ];
451 char cast_buf[NDLBUFSZ];
452 char fname_type[NDLBUFSZ];
453 ndr_typeinfo_t ptr;
454
455 type_extern_suffix(ti, fname_type, NDLBUFSZ);
456 generate_typeinfo_typeinfo(ti, 0, fname_type);
457 generate_prototypes(ti, fname_type);
458
459 (void) printf("\n");
460 (void) printf("/*\n * ");
461 show_advice(&ti->advice, 0);
462 (void) printf(" */\n");
463 (void) printf("int\n");
464 (void) printf("ndr_%s (struct ndr_reference *encl_ref)\n",
465 fname_type);
466 (void) printf("{\n");
467
468 ptr.type_op = STAR;
469 ptr.type_down = ti;
470
471 type_name_decl(&ptr, val_buf, NDLBUFSZ, "val");
472 type_null_decl(&ptr, cast_buf, NDLBUFSZ);
473
474 (void) printf(" %s = %s encl_ref->datum;\n", val_buf, cast_buf);
475
476 (void) printf(" struct ndr_reference myref;\n");
477 (void) printf("\n");
478 (void) printf(" (void) bzero(&myref, sizeof (myref));\n");
479 (void) printf(" myref.enclosing = encl_ref;\n");
480 (void) printf(" myref.stream = encl_ref->stream;\n");
481 generate_typeinfo_packing(ti);
482 (void) printf("\n");
483 }
484
485 /* ARGSUSED */
486 static void
generate_aggregate_common_finish(ndr_typeinfo_t * ti)487 generate_aggregate_common_finish(ndr_typeinfo_t *ti)
488 {
489 (void) printf("\n");
490 (void) printf(" return 1;\n");
491 (void) printf("}\n");
492 }
493
494 /*
495 * Structures are normally 4-byte (dword) aligned but the align directive
496 * can be used to pack on a 2-byte (word) boundary. An align value of
497 * zero is taken to mean use default (dword) alignment. Default packing
498 * doesn't need to be flagged.
499 */
500 static void
generate_typeinfo_packing(ndr_typeinfo_t * ti)501 generate_typeinfo_packing(ndr_typeinfo_t *ti)
502 {
503 ndr_node_t *np;
504 unsigned long packing;
505
506 if ((np = ti->advice.a_align) == NULL)
507 return;
508
509 if ((np = np->n_a_arg) == NULL)
510 return;
511
512 packing = np->n_int;
513 if ((packing == 0) || (packing == 4)) {
514 /* default alignment */
515 return;
516 }
517
518 if (packing != 2) {
519 fatal_error("invalid align directive: %lu", packing);
520 /* NOTREACHED */
521 }
522
523 (void) printf(" myref.packed_alignment = %lu;\n", packing);
524 }
525
526 static void
generate_typeinfo_typeinfo(ndr_typeinfo_t * ti,int is_static,char * fname_type)527 generate_typeinfo_typeinfo(ndr_typeinfo_t *ti, int is_static, char *fname_type)
528 {
529 char flags[NDLBUFSZ];
530
531 *flags = 0;
532 if (ti->is_conformant)
533 (void) strlcat(flags, "|NDR_F_CONFORMANT", NDLBUFSZ);
534
535 if (ti->advice.a_fake)
536 (void) strlcat(flags, "|NDR_F_FAKE", NDLBUFSZ);
537
538 if (ti->type_op == STRUCT_KW) {
539 if (ti->advice.a_operation)
540 (void) strlcat(flags, "|NDR_F_OPERATION", NDLBUFSZ);
541 else
542 (void) strlcat(flags, "|NDR_F_STRUCT", NDLBUFSZ);
543 }
544
545 if (ti->type_op == UNION_KW) {
546 if (ti->advice.a_interface)
547 (void) strlcat(flags, "|NDR_F_INTERFACE", NDLBUFSZ);
548 else
549 (void) strlcat(flags, "|NDR_F_UNION", NDLBUFSZ);
550 }
551
552 if (ti->type_op == STRING_KW)
553 (void) strlcat(flags, "|NDR_F_STRING", NDLBUFSZ);
554 if (ti->type_op == LB)
555 (void) strlcat(flags, "|NDR_F_ARRAY", NDLBUFSZ);
556 if (ti->type_op == STAR)
557 (void) strlcat(flags, "|NDR_F_POINTER", NDLBUFSZ);
558
559 if (*flags == 0)
560 (void) strlcpy(flags, "NDR_F_NONE", NDLBUFSZ);
561 else
562 (void) strlcpy(flags, flags+1, NDLBUFSZ);
563
564 (void) printf("\n\n\n");
565 if (is_static)
566 (void) printf("static ");
567
568 (void) printf("int ndr_%s (struct ndr_reference *encl_ref);\n",
569 fname_type);
570 if (is_static)
571 (void) printf("static ");
572
573 (void) printf("struct ndr_typeinfo ndt_%s = {\n", fname_type);
574 (void) printf("\t1, /* NDR version */\n");
575 (void) printf("\t%d, /* alignment */\n", ti->alignment);
576 (void) printf("\t%s, /* flags */\n", flags);
577 (void) printf("\tndr_%s, /* ndr_func */\n", fname_type);
578 (void) printf("\t%d, /* pdu_size_fixed_part */\n",
579 ti->size_fixed_part);
580 (void) printf("\t%d, /* pdu_size_variable_part */\n",
581 ti->size_variable_part);
582
583 (void) printf("\t%d, /* c_size_fixed_part */\n",
584 ti->size_fixed_part);
585 (void) printf("\t%d, /* c_size_variable_part */\n",
586 ti->size_variable_part);
587 (void) printf("};\n\n");
588 }
589