xref: /illumos-gate/usr/src/tools/ndrgen/ndr_print.c (revision edd580643f2cf1434e252cd7779e83182ea84945)
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 
31 static void print_declaration(ndr_node_t *);
32 static void print_advice_list(ndr_node_t *);
33 static void print_node_list(ndr_node_t *);
34 
35 
36 void
37 tdata_dump(void)
38 {
39 	print_node_list(construct_list);
40 }
41 
42 void
43 print_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  */
198 void
199 print_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 
244 static void
245 print_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 
276 static void
277 print_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 
291 static void
292 print_node_list(ndr_node_t *np)
293 {
294 	for (; np; np = np->n_next) {
295 		print_node(np);
296 	}
297 }
298