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