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 "ndrgen.h"
28#include "y.tab.h"
29
30
31static void print_declaration(ndr_node_t *);
32static void print_advice_list(ndr_node_t *);
33static void print_node_list(ndr_node_t *);
34
35
36void
37tdata_dump(void)
38{
39	print_node_list(construct_list);
40}
41
42void
43print_node(ndr_node_t *np)
44{
45	char		*nm;
46
47	if (!np) {
48		(void) printf("<null>");
49		return;
50	}
51
52	switch (np->label) {
53	case ALIGN_KW:		nm = "align";		break;
54	case STRUCT_KW:		nm = "struct";		break;
55	case UNION_KW:		nm = "union";		break;
56	case TYPEDEF_KW:	nm = "typedef";		break;
57	case INTERFACE_KW:	nm = "interface";	break;
58	case IN_KW:		nm = "in";		break;
59	case OUT_KW:		nm = "out";		break;
60	case SIZE_IS_KW:	nm = "size_is";		break;
61	case LENGTH_IS_KW:	nm = "length_is";	break;
62	case STRING_KW:		nm = "string";		break;
63	case TRANSMIT_AS_KW:	nm = "transmit_as";	break;
64	case OPERATION_KW:	nm = "operation";	break;
65	case UUID_KW:		nm = "uuid";		break;
66	case _NO_REORDER_KW:	nm = "_no_reorder";	break;
67	case EXTERN_KW:		nm = "extern";		break;
68	case ARG_IS_KW:		nm = "arg_is";		break;
69	case CASE_KW:		nm = "case";		break;
70	case DEFAULT_KW:	nm = "default";		break;
71	case BASIC_TYPE:	nm = "<btype>";		break;
72	case TYPENAME:		nm = "<tname>";		break;
73	case IDENTIFIER:	nm = "<ident>";		break;
74	case INTEGER:		nm = "<intg>";		break;
75	case STRING:		nm = "<string>";	break;
76	case STAR:		nm = "<*>";		break;
77	case LB:		nm = "<[>";		break;
78	case LP:		nm = "<(>";		break;
79	case L_MEMBER:		nm = "<member>";	break;
80	default:
81		(void) printf("<<lab=%d>>", np->label);
82		return;
83	}
84
85	switch (np->label) {
86	case STRUCT_KW:
87	case UNION_KW:
88	case TYPEDEF_KW:
89		(void) printf("\n");
90		if (np->n_c_advice) {
91			print_advice_list(np->n_c_advice);
92			(void) printf("\n");
93		}
94		(void) printf("%s ", nm);
95		print_node(np->n_c_typename);
96		(void) printf(" {\n");
97		print_node_list(np->n_c_members);
98		(void) printf("};\n");
99		break;
100
101	case IN_KW:
102	case OUT_KW:
103	case STRING_KW:
104	case DEFAULT_KW:
105	case _NO_REORDER_KW:
106	case EXTERN_KW:
107		(void) printf("%s", nm);
108		break;
109
110	case ALIGN_KW:
111		/*
112		 * Don't output anything for default alignment.
113		 */
114		if ((np->n_a_arg == NULL) || (np->n_a_arg->n_int == 0))
115			break;
116		(void) printf("%s(", nm);
117		print_node(np->n_a_arg);
118		(void) printf(")");
119		break;
120
121	case SIZE_IS_KW:
122	case LENGTH_IS_KW:
123		(void) printf("%s(", nm);
124		print_field_attr(np);
125		(void) printf(")");
126		break;
127
128	case INTERFACE_KW:
129	case TRANSMIT_AS_KW:
130	case ARG_IS_KW:
131	case CASE_KW:
132	case OPERATION_KW:
133	case UUID_KW:
134		(void) printf("%s(", nm);
135		print_node(np->n_a_arg);
136		(void) printf(")");
137		break;
138
139	case BASIC_TYPE:
140	case TYPENAME:
141	case IDENTIFIER:
142		(void) printf("%s", np->n_sym->name);
143		break;
144
145	case INTEGER:
146		(void) printf("%ld", np->n_int);
147		break;
148
149	case STRING:
150		(void) printf("\"%s\"", np->n_str);
151		break;
152
153	case STAR:
154		(void) printf("*");
155		print_node(np->n_d_descend);
156		break;
157
158	case LB:
159		print_node(np->n_d_descend);
160		(void) printf("[");
161		if (np->n_d_dim)
162			print_node(np->n_d_dim);
163		(void) printf("]");
164		break;
165
166	case LP:
167		(void) printf("(");
168		print_node(np->n_d_descend);
169		(void) printf(")");
170		break;
171
172	case L_MEMBER:
173		if (np->n_m_advice) {
174			(void) printf("    ");
175			print_advice_list(np->n_m_advice);
176			(void) printf("\n");
177		}
178		(void) printf("\t");
179		print_declaration(np);
180		(void) printf(";\n");
181		break;
182
183	default:
184		return;
185	}
186}
187
188/*
189 * Field attributes are used to specify the size of an array, or the portion
190 * of the array, that contains valid data, which is done by associating
191 * another parameter with the array that contains the sizing information.
192 *
193 * Supports formats such as size_is(x) or size_is(x / 2).  The supported
194 * operators are:
195 *
196 * 	* / % + - & | ^
197 */
198void
199print_field_attr(ndr_node_t *np)
200{
201	static char	*valid = "*/%+-&|^";
202	ndr_node_t	*arg;
203	char		*name;
204	char		*operator;
205	long		value;
206
207	arg = np->n_a_arg;
208	if (arg->label != IDENTIFIER)
209		fatal_error("invalid label %d", arg->label);
210	if ((name = arg->n_sym->name) == NULL)
211		fatal_error("missing symbol name");
212
213	arg = np->n_a_arg1;
214	operator = NULL;
215	if (arg->label == IDENTIFIER) {
216		operator = arg->n_sym->name;
217
218		if (operator != NULL) {
219			/*
220			 * The lexer sets the name and operator to
221			 * the same value if there is no operator.
222			 */
223			if (strcmp(name, operator) == 0)
224				operator = NULL;
225			else if (strchr(valid, *operator) == NULL)
226				compile_error("invalid operator: %s", operator);
227		}
228	}
229
230	arg = np->n_a_arg2;
231	if (arg->label == INTEGER) {
232		value = arg->n_int;
233
234		if ((value == 0) && strcmp(operator, "/") == 0)
235			compile_error("divide by zero");
236	}
237
238	if (operator)
239		(void) printf("%s %s %ldUL", name, operator, value);
240	else
241		(void) printf("%s", name);
242}
243
244static void
245print_declaration(ndr_node_t *np)
246{
247	ndr_node_t	*dnp = np->n_m_decl;
248	char		buf[NDLBUFSZ];
249	char		*p = buf;
250
251	if (np->n_m_type &&
252	    (np->n_m_type->label == IDENTIFIER ||
253	    np->n_m_type->label == TYPENAME)) {
254		(void) snprintf(buf, NDLBUFSZ, "%s", np->n_m_type->n_sym->name);
255
256		while (*p)
257			p++;
258
259		if (dnp && dnp->label == STAR) {
260			*p++ = ' ';
261			while (dnp && dnp->label == STAR) {
262				*p++ = '*';
263				dnp = dnp->n_d_descend;
264			}
265		}
266		*p = 0;
267		(void) printf("%-23s ", buf);
268	} else {
269		print_node(np->n_m_type);
270		(void) printf(" ");
271	}
272
273	print_node(dnp);
274}
275
276static void
277print_advice_list(ndr_node_t *np)
278{
279	if (!np)
280		return;
281
282	(void) printf("[");
283	for (; np; np = np->n_next) {
284		print_node(np);
285		if (np->n_next)
286			(void) printf(" ");
287	}
288	(void) printf("]");
289}
290
291static void
292print_node_list(ndr_node_t *np)
293{
294	for (; np; np = np->n_next) {
295		print_node(np);
296	}
297}
298