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