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.
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.
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]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
29 * University Copyright- Copyright (c) 1982, 1986, 1988
30 * The Regents of the University of California
33 * University Acknowledgment- Portions of this document are derived from
34 * software developed by the University of California, Berkeley, and its
39 * rpc_cout.c, XDR routine outputter for the RPC protocol compiler
45 #include "rpc_parse.h"
48 extern void crash(void);
50 static void print_header(definition
*);
51 static void print_trailer(void);
52 static void emit_enum(definition
*);
53 static void emit_program(definition
*);
54 static void emit_union(definition
*);
55 static void emit_struct(definition
*);
56 static void emit_typedef(definition
*);
57 static void print_stat(int, declaration
*);
58 static void emit_inline(int, declaration
*, int);
59 static void emit_inline64(int, declaration
*, int);
60 static void emit_single_in_line(int, declaration
*, int, relation
);
61 static void emit_single_in_line64(int, declaration
*, int, relation
);
62 static char *upcase(char *);
65 * Emit the C-routine for the given definition
70 if (def
->def_kind
== DEF_CONST
)
72 if (def
->def_kind
== DEF_PROGRAM
) {
76 if (def
->def_kind
== DEF_TYPEDEF
) {
78 * now we need to handle declarations like
79 * struct typedef foo foo;
80 * since we dont want this to be expanded into 2 calls
84 if (strcmp(def
->def
.ty
.old_type
, def
->def_name
) == 0)
88 switch (def
->def_kind
) {
106 findtype(definition
*def
, char *type
)
109 if (def
->def_kind
== DEF_PROGRAM
|| def
->def_kind
== DEF_CONST
)
111 return (streq(def
->def_name
, type
));
115 undefined(char *type
)
119 def
= (definition
*)FINDVAL(defined
, type
, findtype
);
120 return (def
== NULL
);
125 print_generic_header(char *procname
, int pointerp
)
128 f_print(fout
, "bool_t\n");
130 f_print(fout
, "xdr_%s(", procname
);
131 f_print(fout
, "XDR *xdrs, ");
132 f_print(fout
, "%s ", procname
);
135 f_print(fout
, "objp)\n{\n\n");
137 f_print(fout
, "xdr_%s(xdrs, objp)\n", procname
);
138 f_print(fout
, "\tXDR *xdrs;\n");
139 f_print(fout
, "\t%s ", procname
);
142 f_print(fout
, "objp;\n{\n\n");
147 print_header(definition
*def
)
149 print_generic_header(def
->def_name
,
150 def
->def_kind
!= DEF_TYPEDEF
||
151 !isvectordef(def
->def
.ty
.old_type
, def
->def
.ty
.rel
));
152 /* Now add Inline support */
156 /* May cause lint to complain. but ... */
157 f_print(fout
, "\trpc_inline_t *buf;\n\n");
161 print_prog_header(proc_list
*plist
)
163 print_generic_header(plist
->args
.argname
, 1);
169 f_print(fout
, "\treturn (TRUE);\n");
170 f_print(fout
, "}\n");
175 print_ifopen(int indent
, char *name
)
177 tabify(fout
, indent
);
178 if (streq(name
, "rpcprog_t") ||
179 streq(name
, "rpcvers_t") ||
180 streq(name
, "rpcproc_t") ||
181 streq(name
, "rpcprot_t") ||
182 streq(name
, "rpcport_t"))
183 (void) strtok(name
, "_");
184 f_print(fout
, "if (!xdr_%s(xdrs", name
);
188 print_ifarg(char *arg
)
190 f_print(fout
, ", %s", arg
);
194 print_ifsizeof(int indent
, char *prefix
, char *type
)
197 f_print(fout
, ",\n");
198 tabify(fout
, indent
);
202 if (streq(type
, "bool")) {
203 f_print(fout
, "sizeof (bool_t), (xdrproc_t)xdr_bool");
205 f_print(fout
, "sizeof (");
206 if (undefined(type
) && prefix
) {
207 f_print(fout
, "%s ", prefix
);
209 f_print(fout
, "%s), (xdrproc_t)xdr_%s", type
, type
);
214 print_ifclose(int indent
)
216 f_print(fout
, "))\n");
217 tabify(fout
, indent
);
218 f_print(fout
, "\treturn (FALSE);\n");
222 print_ifstat(int indent
, char *prefix
, char *type
, relation rel
,
223 char *amax
, char *objname
, char *name
)
229 print_ifopen(indent
, "pointer");
230 print_ifarg("(char **)");
231 f_print(fout
, "%s", objname
);
232 print_ifsizeof(0, prefix
, type
);
235 if (streq(type
, "string"))
237 else if (streq(type
, "opaque"))
240 print_ifopen(indent
, alt
);
241 print_ifarg(objname
);
243 print_ifopen(indent
, "vector");
244 print_ifarg("(char *)");
245 f_print(fout
, "%s", objname
);
249 print_ifsizeof(indent
+ 1, prefix
, type
);
252 if (streq(type
, "string"))
254 else if (streq(type
, "opaque"))
256 if (streq(type
, "string")) {
257 print_ifopen(indent
, alt
);
258 print_ifarg(objname
);
261 print_ifopen(indent
, alt
);
263 print_ifopen(indent
, "array");
264 print_ifarg("(char **)");
266 f_print(fout
, "%s.%s_val, (u_int *) %s.%s_len",
267 objname
, name
, objname
, name
);
270 "&%s->%s_val, (u_int *) &%s->%s_len",
271 objname
, name
, objname
, name
);
275 print_ifsizeof(indent
+ 1, prefix
, type
);
278 print_ifopen(indent
, type
);
279 print_ifarg(objname
);
282 print_ifclose(indent
);
287 emit_enum(definition
*def
)
289 print_ifopen(1, "enum");
290 print_ifarg("(enum_t *)objp");
295 emit_program(definition
*def
)
301 for (vlist
= def
->def
.pr
.versions
; vlist
!= NULL
; vlist
= vlist
->next
)
302 for (plist
= vlist
->procs
; plist
!= NULL
; plist
= plist
->next
) {
303 if (!newstyle
|| plist
->arg_num
< 2)
304 continue; /* old style, or single argument */
305 print_prog_header(plist
);
306 for (dl
= plist
->args
.decls
; dl
!= NULL
;
308 print_stat(1, &dl
->decl
);
315 emit_union(definition
*def
)
322 print_stat(1, &def
->def
.un
.enum_decl
);
323 f_print(fout
, "\tswitch (objp->%s) {\n", def
->def
.un
.enum_decl
.name
);
324 for (cl
= def
->def
.un
.cases
; cl
!= NULL
; cl
= cl
->next
) {
326 f_print(fout
, "\tcase %s:\n", cl
->case_name
);
327 if (cl
->contflag
== 1) /* a continued case statement */
330 if (!streq(cs
->type
, "void")) {
331 size_t len
= strlen(def
->def_name
) +
332 strlen("&objp->%s_u.%s") +
333 strlen(cs
->name
) + 1;
334 object
= malloc(len
);
335 if (isvectordef(cs
->type
, cs
->rel
))
336 (void) snprintf(object
, len
, "objp->%s_u.%s",
337 def
->def_name
, cs
->name
);
339 (void) snprintf(object
, len
, "&objp->%s_u.%s",
340 def
->def_name
, cs
->name
);
341 print_ifstat(2, cs
->prefix
, cs
->type
, cs
->rel
,
342 cs
->array_max
, object
, cs
->name
);
345 f_print(fout
, "\t\tbreak;\n");
347 dflt
= def
->def
.un
.default_decl
;
349 if (!streq(dflt
->type
, "void")) {
350 size_t len
= strlen(def
->def_name
) +
351 strlen("&objp->%s_u.%s") +
352 strlen(dflt
->name
) + 1;
353 f_print(fout
, "\tdefault:\n");
354 object
= malloc(len
);
355 if (isvectordef(dflt
->type
, dflt
->rel
))
356 (void) snprintf(object
, len
, "objp->%s_u.%s",
357 def
->def_name
, dflt
->name
);
359 (void) snprintf(object
, len
, "&objp->%s_u.%s",
360 def
->def_name
, dflt
->name
);
362 print_ifstat(2, dflt
->prefix
, dflt
->type
, dflt
->rel
,
363 dflt
->array_max
, object
, dflt
->name
);
365 f_print(fout
, "\t\tbreak;\n");
368 f_print(fout
, "\tdefault:\n");
369 f_print(fout
, "\t\treturn (FALSE);\n");
372 f_print(fout
, "\t}\n");
376 expand_inline(int indent
, const char *sizestr
,
377 int size
, int flag
, decl_list
*dl
, decl_list
*cur
)
382 * were already looking at a xdr_inlineable structure
384 tabify(fout
, indent
+ 1);
387 "buf = XDR_INLINE(xdrs, %d * BYTES_PER_XDR_UNIT);",
391 "buf = XDR_INLINE(xdrs, (%s) * BYTES_PER_XDR_UNIT);",
395 "buf = XDR_INLINE(xdrs, (%d + (%s)) "
396 "* BYTES_PER_XDR_UNIT);", size
, sizestr
);
399 tabify(fout
, indent
+ 1);
400 f_print(fout
, "if (buf == NULL) {\n");
404 print_stat(indent
+ 2,
409 tabify(fout
, indent
+1);
410 f_print(fout
, "} else {\n");
412 f_print(fout
, "#if defined(_LP64) || defined(_KERNEL)\n");
415 emit_inline64(indent
+ 2, &cur
->decl
, flag
);
418 f_print(fout
, "#else\n");
421 emit_inline(indent
+ 2, &cur
->decl
, flag
);
424 f_print(fout
, "#endif\n");
426 tabify(fout
, indent
+ 1);
427 f_print(fout
, "}\n");
431 * An inline type is a base type (interger type) or a vector of base types.
434 inline_type(declaration
*dc
, int *size
)
440 if (dc
->prefix
== NULL
&&
441 (dc
->rel
== REL_ALIAS
|| dc
->rel
== REL_VECTOR
)) {
442 ptr
= find_type(dc
->type
);
453 arraysize(char *sz
, declaration
*dc
, int elsize
)
464 * Calculate the size of a string to hold the size of all arrays
467 * We have the string representation of the total size that has already
468 * been seen. (Null if this is the first array).
469 * We have the string representation of array max from the declaration,
470 * optionally the plus string, " + ", if this is not the first array,
471 * and the number of digits for the element size for this declaration.
478 /* Calculate the number of digits to hold the element size */
479 for (digits
= 1; elsz
>= 10; digits
++)
483 * If elsize != 1 the allocate 3 extra bytes for the times
484 * string, " * ", the "()" below, and the digits. One extra
485 * for the trailing NULL
487 len
= strlen(dc
->array_max
) + (elsize
== 1 ? 0 : digits
+ 5) + 1;
488 tlen
= slen
+ len
+ strlen(plus
);
489 tmp
= realloc(sz
, tlen
);
491 f_print(stderr
, "Fatal error : no memory\n");
496 (void) snprintf(tmp
+ slen
, tlen
- slen
, "%s%s",
497 plus
, dc
->array_max
);
499 (void) snprintf(tmp
+ slen
, tlen
- slen
, "%s(%s) * %d",
500 plus
, dc
->array_max
, elsize
);
506 inline_struct(decl_list
*dl
, decl_list
*last
, int flag
, int indent
)
515 for (; dl
!= last
; dl
= dl
->next
) {
516 if (inline_type(&dl
->decl
, &size
)) {
520 if (dl
->decl
.rel
== REL_ALIAS
)
523 /* this code is required to handle arrays */
524 sizestr
= arraysize(sizestr
, &dl
->decl
, size
);
528 if (sizestr
== NULL
&& tsize
< inlinelen
) {
530 * don't expand into inline code
531 * if tsize < inlinelen
534 print_stat(indent
+ 1,
539 expand_inline(indent
, sizestr
,
540 tsize
, flag
, dl
, cur
);
545 print_stat(indent
+ 1, &dl
->decl
);
551 if (sizestr
== NULL
&& tsize
< inlinelen
) {
552 /* don't expand into inline code if tsize < inlinelen */
554 print_stat(indent
+ 1, &cur
->decl
);
558 expand_inline(indent
, sizestr
, tsize
, flag
, dl
, cur
);
563 * Check if we can inline this structure. While we are at it check if the
564 * declaration list has any vectors defined of "basic" types.
567 check_inline(decl_list
*dl
, int inlinelen
, int *have_vector
)
577 for (; dl
!= NULL
; dl
= dl
->next
) {
578 if (!inline_type(&dl
->decl
, &size
)) {
582 if (dl
->decl
.rel
== REL_VECTOR
) {
587 if (tsize
>= inlinelen
)
596 emit_struct_tail_recursion(definition
*defp
, int can_inline
)
599 struct_def
*sp
= &defp
->def
.st
;
603 f_print(fout
, "\t%s *tmp_%s;\n",
604 defp
->def_name
, defp
->def_name
);
606 f_print(fout
, "\tbool_t more_data = TRUE;\n");
607 f_print(fout
, "\tbool_t first_objp = TRUE;\n\n");
609 f_print(fout
, "\n\tif (xdrs->x_op == XDR_DECODE) {\n");
610 f_print(fout
, "\n\t\twhile (more_data) {\n");
611 f_print(fout
, "\n\t\t\tvoid bzero();\n\n");
614 inline_struct(sp
->decls
, sp
->tail
, GET
, indent
);
616 for (dl
= sp
->decls
; dl
!= NULL
&& dl
!= sp
->tail
;
618 print_stat(indent
, &dl
->decl
);
620 f_print(fout
, "\t\t\tif (!xdr_bool(xdrs, "
621 "&more_data))\n\t\t\t\treturn (FALSE);\n");
623 f_print(fout
, "\n\t\t\tif (!more_data) {\n");
624 f_print(fout
, "\t\t\t\tobjp->%s = NULL;\n", sp
->tail
->decl
.name
);
625 f_print(fout
, "\t\t\t\tbreak;\n");
626 f_print(fout
, "\t\t\t}\n\n");
627 f_print(fout
, "\t\t\tif (objp->%s == NULL) {\n", sp
->tail
->decl
.name
);
628 f_print(fout
, "\t\t\t\tobjp->%s = "
629 "(%s *)\n\t\t\t\t\tmem_alloc(sizeof (%s));\n",
630 sp
->tail
->decl
.name
, defp
->def_name
, defp
->def_name
);
632 f_print(fout
, "\t\t\t\tif (objp->%s == NULL)\n"
633 "\t\t\t\t\treturn (FALSE);\n", sp
->tail
->decl
.name
);
634 f_print(fout
, "\t\t\t\tbzero(objp->%s, sizeof (%s));\n",
635 sp
->tail
->decl
.name
, defp
->def_name
);
636 f_print(fout
, "\t\t\t}\n");
637 f_print(fout
, "\t\t\tobjp = objp->%s;\n", sp
->tail
->decl
.name
);
638 f_print(fout
, "\t\t}\n");
640 f_print(fout
, "\n\t} else if (xdrs->x_op == XDR_ENCODE) {\n");
641 f_print(fout
, "\n\t\twhile (more_data) {\n");
644 inline_struct(sp
->decls
, sp
->tail
, PUT
, indent
);
646 for (dl
= sp
->decls
; dl
!= NULL
&& dl
!= sp
->tail
;
648 print_stat(indent
, &dl
->decl
);
650 f_print(fout
, "\t\t\tobjp = objp->%s;\n", sp
->tail
->decl
.name
);
651 f_print(fout
, "\t\t\tif (objp == NULL)\n");
652 f_print(fout
, "\t\t\t\tmore_data = FALSE;\n");
654 f_print(fout
, "\t\t\tif (!xdr_bool(xdrs, &more_data))\n"
655 "\t\t\t\treturn (FALSE);\n");
657 f_print(fout
, "\t\t}\n");
659 f_print(fout
, "\n\t} else {\n");
660 f_print(fout
, "\n\t\twhile (more_data) {\n");
662 for (dl
= sp
->decls
; dl
!= NULL
&& dl
!= sp
->tail
; dl
= dl
->next
)
663 print_stat(indent
, &dl
->decl
);
665 f_print(fout
, "\t\t\ttmp_%s = objp;\n", defp
->def_name
);
666 f_print(fout
, "\t\t\tobjp = objp->%s;\n", sp
->tail
->decl
.name
);
668 f_print(fout
, "\t\t\tif (objp == NULL)\n");
669 f_print(fout
, "\t\t\t\tmore_data = FALSE;\n");
671 f_print(fout
, "\t\t\tif (!first_objp)\n");
673 f_print(fout
, "\t\t\t\tmem_free(tmp_%s, sizeof (%s));\n",
674 defp
->def_name
, defp
->def_name
);
676 f_print(fout
, "\t\t\telse\n\t\t\t\tfirst_objp = FALSE;\n\t\t}\n");
678 f_print(fout
, "\n\t}\n");
682 emit_struct(definition
*def
)
684 decl_list
*dl
= def
->def
.st
.decls
;
685 int can_inline
, have_vector
;
688 can_inline
= check_inline(dl
, inlinelen
, &have_vector
);
690 f_print(fout
, "\tint i;\n");
693 if (rflag
&& def
->def
.st
.self_pointer
) {
694 /* Handle tail recursion elimination */
695 emit_struct_tail_recursion(def
, can_inline
);
701 f_print(fout
, "\n\tif (xdrs->x_op == XDR_ENCODE) {\n");
702 inline_struct(dl
, NULL
, PUT
, 1);
704 f_print(fout
, "\t\treturn (TRUE);\n\t}"
705 " else if (xdrs->x_op == XDR_DECODE) {\n");
707 inline_struct(dl
, NULL
, GET
, 1);
708 f_print(fout
, "\t\treturn (TRUE);\n\t}\n\n");
711 /* now take care of XDR_FREE inline case or the non-inline cases */
713 for (dl
= def
->def
.st
.decls
; dl
!= NULL
; dl
= dl
->next
)
714 print_stat(1, &dl
->decl
);
719 emit_typedef(definition
*def
)
721 char *prefix
= def
->def
.ty
.old_prefix
;
722 char *type
= def
->def
.ty
.old_type
;
723 char *amax
= def
->def
.ty
.array_max
;
724 relation rel
= def
->def
.ty
.rel
;
726 print_ifstat(1, prefix
, type
, rel
, amax
, "objp", def
->def_name
);
730 print_stat(int indent
, declaration
*dec
)
732 char *prefix
= dec
->prefix
;
733 char *type
= dec
->type
;
734 char *amax
= dec
->array_max
;
735 relation rel
= dec
->rel
;
738 if (isvectordef(type
, rel
))
739 (void) snprintf(name
, sizeof (name
), "objp->%s", dec
->name
);
741 (void) snprintf(name
, sizeof (name
), "&objp->%s", dec
->name
);
742 print_ifstat(indent
, prefix
, type
, rel
, amax
, name
, dec
->name
);
747 emit_inline(int indent
, declaration
*decl
, int flag
)
751 emit_single_in_line(indent
, decl
, flag
, REL_ALIAS
);
754 tabify(fout
, indent
);
755 f_print(fout
, "{\n");
756 tabify(fout
, indent
+ 1);
757 f_print(fout
, "%s *genp;\n\n", decl
->type
);
758 tabify(fout
, indent
+ 1);
760 "for (i = 0, genp = objp->%s;\n", decl
->name
);
761 tabify(fout
, indent
+ 2);
762 f_print(fout
, "i < %s; i++) {\n", decl
->array_max
);
763 emit_single_in_line(indent
+ 2, decl
, flag
, REL_VECTOR
);
764 tabify(fout
, indent
+ 1);
765 f_print(fout
, "}\n");
766 tabify(fout
, indent
);
767 f_print(fout
, "}\n");
772 emit_inline64(int indent
, declaration
*decl
, int flag
)
776 emit_single_in_line64(indent
, decl
, flag
, REL_ALIAS
);
779 tabify(fout
, indent
);
780 f_print(fout
, "{\n");
781 tabify(fout
, indent
+ 1);
782 f_print(fout
, "%s *genp;\n\n", decl
->type
);
783 tabify(fout
, indent
+ 1);
785 "for (i = 0, genp = objp->%s;\n", decl
->name
);
786 tabify(fout
, indent
+ 2);
787 f_print(fout
, "i < %s; i++) {\n", decl
->array_max
);
788 emit_single_in_line64(indent
+ 2, decl
, flag
, REL_VECTOR
);
789 tabify(fout
, indent
+ 1);
790 f_print(fout
, "}\n");
791 tabify(fout
, indent
);
792 f_print(fout
, "}\n");
797 emit_single_in_line(int indent
, declaration
*decl
, int flag
, relation rel
)
802 tabify(fout
, indent
);
804 f_print(fout
, "IXDR_PUT_");
806 if (rel
== REL_ALIAS
)
807 f_print(fout
, "objp->%s = IXDR_GET_", decl
->name
);
809 f_print(fout
, "*genp++ = IXDR_GET_");
811 upp_case
= upcase(decl
->type
);
814 if (strcmp(upp_case
, "INT") == 0) {
819 if ((strcmp(upp_case
, "U_INT") == 0) ||
820 (strcmp(upp_case
, "RPCPROG") == 0) ||
821 (strcmp(upp_case
, "RPCVERS") == 0) ||
822 (strcmp(upp_case
, "RPCPROC") == 0) ||
823 (strcmp(upp_case
, "RPCPROT") == 0) ||
824 (strcmp(upp_case
, "RPCPORT") == 0)) {
831 if (rel
== REL_ALIAS
)
833 "%s(buf, objp->%s);\n", upp_case
, decl
->name
);
835 f_print(fout
, "%s(buf, *genp++);\n", upp_case
);
838 f_print(fout
, "%s(buf);\n", upp_case
);
844 emit_single_in_line64(int indent
, declaration
*decl
, int flag
, relation rel
)
849 tabify(fout
, indent
);
851 f_print(fout
, "IXDR_PUT_");
853 if (rel
== REL_ALIAS
)
854 f_print(fout
, "objp->%s = IXDR_GET_", decl
->name
);
856 f_print(fout
, "*genp++ = IXDR_GET_");
858 upp_case
= upcase(decl
->type
);
861 if ((strcmp(upp_case
, "INT") == 0)||(strcmp(upp_case
, "LONG") == 0)) {
866 if ((strcmp(upp_case
, "U_INT") == 0) ||
867 (strcmp(upp_case
, "U_LONG") == 0) ||
868 (strcmp(upp_case
, "RPCPROG") == 0) ||
869 (strcmp(upp_case
, "RPCVERS") == 0) ||
870 (strcmp(upp_case
, "RPCPROC") == 0) ||
871 (strcmp(upp_case
, "RPCPROT") == 0) ||
872 (strcmp(upp_case
, "RPCPORT") == 0)) {
875 upp_case
= "U_INT32";
879 if (rel
== REL_ALIAS
)
881 "%s(buf, objp->%s);\n", upp_case
, decl
->name
);
883 f_print(fout
, "%s(buf, *genp++);\n", upp_case
);
886 f_print(fout
, "%s(buf);\n", upp_case
);
896 ptr
= malloc(strlen(str
)+1);
898 f_print(stderr
, "malloc failed\n");
904 *ptr
++ = toupper(*str
++);