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