08b3cb401e5ba901091eec25ca327cc0bdcb0301
[dragonfly.git] / usr.bin / rpcgen / rpc_cout.c
1 /*
2  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
3  * unrestricted use provided that this legend is included on all tape
4  * media and as a part of the software program in whole or part.  Users
5  * may copy or modify Sun RPC without charge, but are not authorized
6  * to license or distribute it to anyone else except as part of a product or
7  * program developed by the user.
8  * 
9  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
10  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
11  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
12  * 
13  * Sun RPC is provided with no support and without any obligation on the
14  * part of Sun Microsystems, Inc. to assist in its use, correction,
15  * modification or enhancement.
16  * 
17  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
18  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
19  * OR ANY PART THEREOF.
20  * 
21  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
22  * or profits or other special, indirect and consequential damages, even if
23  * Sun has been advised of the possibility of such damages.
24  * 
25  * Sun Microsystems, Inc.
26  * 2550 Garcia Avenue
27  * Mountain View, California  94043
28  *
29  * @(#)rpc_cout.c 1.13 89/02/22 (C) 1987 SMI
30  * $FreeBSD: src/usr.bin/rpcgen/rpc_cout.c,v 1.7 1999/08/28 01:05:16 peter Exp $
31  * $DragonFly: src/usr.bin/rpcgen/rpc_cout.c,v 1.2 2003/06/17 04:29:31 dillon Exp $
32  */
33
34 #ident  "@(#)rpc_cout.c 1.14    93/07/05 SMI" 
35
36 /*
37  * rpc_cout.c, XDR routine outputter for the RPC protocol compiler
38  * Copyright (C) 1987, Sun Microsystems, Inc.
39  */
40 #include <err.h>
41 #include <ctype.h>
42 #include <stdio.h>
43 #include <string.h>
44 #include "rpc_parse.h"
45 #include "rpc_util.h"
46
47 static void print_header __P(( definition * ));
48 static void print_trailer __P(( void ));
49 static void print_stat __P(( int , declaration * ));
50 static void emit_enum __P(( definition * ));
51 static void emit_program __P(( definition * ));
52 static void emit_union __P(( definition * ));
53 static void emit_struct __P(( definition * ));
54 static void emit_typedef __P(( definition * ));
55 static void emit_inline __P(( int, declaration *, int ));
56 static void emit_single_in_line __P(( int, declaration *, int, relation ));
57
58 /*
59  * Emit the C-routine for the given definition
60  */
61 void
62 emit(def)
63         definition *def;
64 {
65         if (def->def_kind == DEF_CONST) {
66                 return;
67         }
68         if (def->def_kind == DEF_PROGRAM) {
69                 emit_program(def);
70                 return;
71         }
72         if (def->def_kind == DEF_TYPEDEF) {
73                 /*
74                  * now we need to handle declarations like
75                  * struct typedef foo foo;
76                  * since we dont want this to be expanded into 2 calls to xdr_foo
77                  */
78
79                 if (strcmp(def->def.ty.old_type, def->def_name) == 0)
80                         return;
81         };
82         print_header(def);
83         switch (def->def_kind) {
84         case DEF_UNION:
85                 emit_union(def);
86                 break;
87         case DEF_ENUM:
88                 emit_enum(def);
89                 break;
90         case DEF_STRUCT:
91                 emit_struct(def);
92                 break;
93         case DEF_TYPEDEF:
94                 emit_typedef(def);
95                 break;
96                 /* DEF_CONST and DEF_PROGRAM have already been handled */
97         default: 
98         }
99         print_trailer();
100 }
101
102 static int
103 findtype(def, type)
104         definition *def;
105         char *type;
106 {
107
108         if (def->def_kind == DEF_PROGRAM || def->def_kind == DEF_CONST) {
109                 return (0);
110         } else {
111                 return (streq(def->def_name, type));
112         }
113 }
114
115 static int
116 undefined(type)
117         char *type;
118 {
119         definition *def;
120
121         def = (definition *) FINDVAL(defined, type, findtype);
122         return (def == NULL);
123 }
124
125
126 static void
127 print_generic_header(procname, pointerp)
128     char* procname;
129     int pointerp;
130 {
131         f_print(fout, "\n");
132         f_print(fout, "bool_t\n");
133         if (Cflag) {
134             f_print(fout, "xdr_%s(", procname);
135             f_print(fout, "register XDR *xdrs, ");
136             f_print(fout, "%s ", procname);
137             if (pointerp)
138                     f_print(fout, "*");
139             f_print(fout, "objp)\n{\n\n");
140         } else {
141             f_print(fout, "xdr_%s(xdrs, objp)\n", procname);
142             f_print(fout, "\tregister XDR *xdrs;\n");
143             f_print(fout, "\t%s ", procname);
144             if (pointerp)
145                     f_print(fout, "*");
146             f_print(fout, "objp;\n{\n\n");
147         }
148 }
149
150 static void
151 print_header(def)
152         definition *def;
153 {
154         print_generic_header(def->def_name,
155                             def->def_kind != DEF_TYPEDEF ||
156                             !isvectordef(def->def.ty.old_type,
157                                          def->def.ty.rel));
158         /* Now add Inline support */
159
160         if (inline == 0)
161                 return;
162         /* May cause lint to complain. but  ... */
163         f_print(fout, "\tregister long *buf;\n\n");
164 }
165
166 static void
167 print_prog_header(plist)
168         proc_list *plist;
169 {
170         print_generic_header(plist->args.argname, 1);
171 }
172
173 static void
174 print_trailer()
175 {
176         f_print(fout, "\treturn (TRUE);\n");
177         f_print(fout, "}\n");
178 }
179
180
181 static void
182 print_ifopen(indent, name)
183         int indent;
184         char *name;
185 {
186         tabify(fout, indent);
187         f_print(fout, "if (!xdr_%s(xdrs", name);
188 }
189
190 static void
191 print_ifarg(arg)
192         char *arg;
193 {
194         f_print(fout, ", %s", arg);
195 }
196
197 static void
198 print_ifsizeof(indent, prefix, type)
199         int indent;
200         char *prefix;
201         char *type;
202 {
203         if (indent) {
204                 f_print(fout, ",\n");
205                 tabify(fout, indent);
206         } else  {
207                 f_print(fout, ", ");
208         }
209         if (streq(type, "bool")) {
210                 f_print(fout, "sizeof (bool_t), (xdrproc_t) xdr_bool");
211         } else {
212                 f_print(fout, "sizeof (");
213                 if (undefined(type) && prefix) {
214                         f_print(fout, "%s ", prefix);
215                 }
216                 f_print(fout, "%s), (xdrproc_t) xdr_%s", type, type);
217         }
218 }
219
220 static void
221 print_ifclose(indent)
222         int indent;
223 {
224         f_print(fout, "))\n");
225         tabify(fout, indent);
226         f_print(fout, "\treturn (FALSE);\n");
227 }
228
229 static void
230 print_ifstat(indent, prefix, type, rel, amax, objname, name)
231         int indent;
232         char *prefix;
233         char *type;
234         relation rel;
235         char *amax;
236         char *objname;
237         char *name;
238 {
239         char *alt = NULL;
240
241         switch (rel) {
242         case REL_POINTER:
243                 print_ifopen(indent, "pointer");
244                 print_ifarg("(char **)");
245                 f_print(fout, "%s", objname);
246                 print_ifsizeof(0, prefix, type);
247                 break;
248         case REL_VECTOR:
249                 if (streq(type, "string")) {
250                         alt = "string";
251                 } else if (streq(type, "opaque")) {
252                         alt = "opaque";
253                 }
254                 if (alt) {
255                         print_ifopen(indent, alt);
256                         print_ifarg(objname);
257                 } else {
258                         print_ifopen(indent, "vector");
259                         print_ifarg("(char *)");
260                         f_print(fout, "%s", objname);
261                 }
262                 print_ifarg(amax);
263                 if (!alt) {
264                         print_ifsizeof(indent + 1, prefix, type);
265                 }
266                 break;
267         case REL_ARRAY:
268                 if (streq(type, "string")) {
269                         alt = "string";
270                 } else if (streq(type, "opaque")) {
271                         alt = "bytes";
272                 }
273                 if (streq(type, "string")) {
274                         print_ifopen(indent, alt);
275                         print_ifarg(objname);
276                 } else {
277                         if (alt) {
278                                 print_ifopen(indent, alt);
279                         } else {
280                                 print_ifopen(indent, "array");
281                         }
282                         print_ifarg("(char **)");
283                         if (*objname == '&') {
284                                 f_print(fout, "%s.%s_val, (u_int *) %s.%s_len",
285                                         objname, name, objname, name);
286                         } else {
287                                 f_print(fout,
288                                         "&%s->%s_val, (u_int *) &%s->%s_len",
289                                         objname, name, objname, name);
290                         }
291                 }
292                 print_ifarg(amax);
293                 if (!alt) {
294                         print_ifsizeof(indent + 1, prefix, type);
295                 }
296                 break;
297         case REL_ALIAS:
298                 print_ifopen(indent, type);
299                 print_ifarg(objname);
300                 break;
301         }
302         print_ifclose(indent);
303 }
304
305 /* ARGSUSED */
306 static void
307 emit_enum(def)
308         definition *def;
309 {
310         print_ifopen(1, "enum");
311         print_ifarg("(enum_t *)objp");
312         print_ifclose(1);
313 }
314
315 static void
316 emit_program(def)
317         definition *def;
318 {
319         decl_list *dl;
320         version_list *vlist;
321         proc_list *plist;
322
323         for (vlist = def->def.pr.versions; vlist != NULL; vlist = vlist->next)
324                 for (plist = vlist->procs; plist != NULL; plist = plist->next) {
325                         if (!newstyle || plist->arg_num < 2)
326                                 continue; /* old style, or single argument */
327                         print_prog_header(plist);
328                         for (dl = plist->args.decls; dl != NULL;
329                              dl = dl->next)
330                                 print_stat(1, &dl->decl);
331                         print_trailer();
332                 }
333 }
334
335
336 static void
337 emit_union(def)
338         definition *def;
339 {
340         declaration *dflt;
341         case_list *cl;
342         declaration *cs;
343         char *object;
344         char *vecformat = "objp->%s_u.%s";
345         char *format = "&objp->%s_u.%s";
346
347         print_stat(1, &def->def.un.enum_decl);
348         f_print(fout, "\tswitch (objp->%s) {\n", def->def.un.enum_decl.name);
349         for (cl = def->def.un.cases; cl != NULL; cl = cl->next) {
350
351                 f_print(fout, "\tcase %s:\n", cl->case_name);
352                 if (cl->contflag == 1) /* a continued case statement */
353                         continue;
354                 cs = &cl->case_decl;
355                 if (!streq(cs->type, "void")) {
356                         object = alloc(strlen(def->def_name) + strlen(format) +
357                                        strlen(cs->name) + 1);
358                         if (isvectordef (cs->type, cs->rel)) {
359                                 s_print(object, vecformat, def->def_name,
360                                         cs->name);
361                         } else {
362                                 s_print(object, format, def->def_name,
363                                         cs->name);
364                         }
365                         print_ifstat(2, cs->prefix, cs->type, cs->rel,
366                                      cs->array_max, object, cs->name);
367                         free(object);
368                 }
369                 f_print(fout, "\t\tbreak;\n");
370         }
371         dflt = def->def.un.default_decl;
372         if (dflt != NULL) {
373                 if (!streq(dflt->type, "void")) {
374                         f_print(fout, "\tdefault:\n");
375                         object = alloc(strlen(def->def_name) + strlen(format) +
376 strlen(dflt->name) + 1);
377                         if (isvectordef (dflt->type, dflt->rel)) {
378                                 s_print(object, vecformat, def->def_name,
379                                         dflt->name);
380                         } else {
381                                 s_print(object, format, def->def_name,
382                                         dflt->name);
383                         }
384
385                         print_ifstat(2, dflt->prefix, dflt->type, dflt->rel,
386                                     dflt->array_max, object, dflt->name);
387                         free(object);
388                         f_print(fout, "\t\tbreak;\n");
389                 } else {
390                         f_print(fout, "\tdefault:\n");
391                         f_print(fout, "\t\tbreak;\n");
392                 }
393         } else {
394                 f_print(fout, "\tdefault:\n");
395                 f_print(fout, "\t\treturn (FALSE);\n");
396         }
397
398         f_print(fout, "\t}\n");
399 }
400
401 static void
402 inline_struct(def, flag)
403 definition *def;
404 int flag;
405 {
406         decl_list *dl;
407         int i, size;
408         decl_list *cur, *psav;
409         bas_type *ptr;
410         char *sizestr, *plus;
411         char ptemp[256];
412         int indent = 1;
413
414         if (flag == PUT)
415                 f_print(fout, "\n\tif (xdrs->x_op == XDR_ENCODE) {\n");
416         else
417                 f_print(fout, "\t\treturn (TRUE);\n\t} else if (xdrs->x_op == XDR_DECODE) {\n");
418
419         i = 0;
420         size = 0;
421         sizestr = NULL;
422         for (dl = def->def.st.decls; dl != NULL; dl = dl->next) { /* xxx */
423                 /* now walk down the list and check for basic types */
424                 if ((dl->decl.prefix == NULL) &&
425                     ((ptr = find_type(dl->decl.type)) != NULL) &&
426                     ((dl->decl.rel == REL_ALIAS) ||
427                      (dl->decl.rel == REL_VECTOR))){
428                         if (i == 0)
429                                 cur = dl;
430                         i++;
431
432                         if (dl->decl.rel == REL_ALIAS)
433                                 size += ptr->length;
434                         else {
435                                 /* this code is required to handle arrays */
436                                 if (sizestr == NULL)
437                                         plus = "";
438                                 else
439                                         plus = " + ";
440
441                                 if (ptr->length != 1)
442                                         s_print(ptemp, "%s%s * %d",
443                                                 plus, dl->decl.array_max,
444                                                 ptr->length);
445                                 else
446                                         s_print(ptemp, "%s%s", plus,
447                                                 dl->decl.array_max);
448
449                                 /* now concatenate to sizestr !!!! */
450                                 if (sizestr == NULL)
451                                         sizestr = strdup(ptemp);
452                                 else{
453                                         sizestr = realloc(sizestr,
454                                                           strlen(sizestr)
455                                                           +strlen(ptemp)+1);
456                                         if (sizestr == NULL){
457                                                 warnx("fatal error: no memory");
458                                                 crash();
459                                         };
460                                         sizestr = strcat(sizestr, ptemp);
461                                         /* build up length of array */
462                                 }
463                         }
464                 } else {
465                         if (i > 0) {
466                                 if (sizestr == NULL && size < inline){
467                                         /*
468                                          * don't expand into inline code
469                                          * if size < inline
470                                          */
471                                         while (cur != dl){
472                                                 print_stat(indent + 1, &cur->decl);
473                                                 cur = cur->next;
474                                         }
475                                 } else {
476                                         /* were already looking at a xdr_inlineable structure */
477                                         tabify(fout, indent + 1);
478                                         if (sizestr == NULL)
479                                                 f_print(fout, "buf = XDR_INLINE(xdrs, %d * BYTES_PER_XDR_UNIT);",
480                                                         size);
481                                         else {
482                                                 if (size == 0)
483                                                         f_print(fout,
484                                                                 "buf = XDR_INLINE(xdrs, (%s) * BYTES_PER_XDR_UNIT);",
485                                                                 sizestr);
486                                                 else
487                                                         f_print(fout,
488                                                                 "buf = XDR_INLINE(xdrs, (%d + (%s)) * BYTES_PER_XDR_UNIT);",
489                                                                 size, sizestr);
490
491                                         }
492                                         f_print(fout, "\n");
493                                         tabify(fout, indent + 1);
494                                         f_print(fout,
495                                                 "if (buf == NULL) {\n");
496
497                                         psav = cur;
498                                         while (cur != dl){
499                                                 print_stat(indent + 2, &cur->decl);
500                                                 cur = cur->next;
501                                         }
502
503                                         f_print(fout, "\n\t\t} else {\n");
504
505                                         cur = psav;
506                                         while (cur != dl){
507                                                 emit_inline(indent + 2, &cur->decl, flag);
508                                                 cur = cur->next;
509                                         }
510
511                                         tabify(fout, indent + 1);
512                                         f_print(fout, "}\n");
513                                 }
514                         }
515                         size = 0;
516                         i = 0;
517                         sizestr = NULL;
518                         print_stat(indent + 1, &dl->decl);
519                 }
520         }
521
522         if (i > 0)
523                 if (sizestr == NULL && size < inline){
524                         /* don't expand into inline code if size < inline */
525                         while (cur != dl){
526                                 print_stat(indent + 1, &cur->decl);
527                                 cur = cur->next;
528                         }
529                 } else {
530                         /* were already looking at a xdr_inlineable structure */
531                         if (sizestr == NULL)
532                                 f_print(fout, "\t\tbuf = XDR_INLINE(xdrs, %d * BYTES_PER_XDR_UNIT);",
533                                         size);
534                         else
535                                 if (size == 0)
536                                         f_print(fout,
537                                                 "\t\tbuf = XDR_INLINE(xdrs, (%s) * BYTES_PER_XDR_UNIT);",
538                                                 sizestr);
539                                 else
540                                         f_print(fout,
541                                                 "\t\tbuf = XDR_INLINE(xdrs, (%d + (%s)) * BYTES_PER_XDR_UNIT);",
542                                                 size, sizestr);
543
544                         f_print(fout, "\n\t\tif (buf == NULL) {\n");
545                         psav = cur;
546                         while (cur != NULL){
547                                 print_stat(indent + 2, &cur->decl);
548                                 cur = cur->next;
549                         }
550                         f_print(fout, "\t\t} else {\n");
551
552                         cur = psav;
553                         while (cur != dl){
554                                 emit_inline(indent + 2, &cur->decl, flag);
555                                 cur = cur->next;
556                         }
557                         f_print(fout, "\t\t}\n");
558                 }
559 }
560
561 static void
562 emit_struct(def)
563         definition *def;
564 {
565         decl_list *dl;
566         int j, size, flag;
567         bas_type *ptr;
568         int can_inline;
569
570         if (inline == 0) {
571                 /* No xdr_inlining at all */
572                 for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
573                         print_stat(1, &dl->decl);
574                 return;
575         }
576
577         for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
578                 if (dl->decl.rel == REL_VECTOR){
579                         f_print(fout, "\tint i;\n");
580                         break;
581                 }
582
583         size = 0;
584         can_inline = 0;
585         /*
586          * Make a first pass and see if inling is possible.
587          */
588         for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
589                 if ((dl->decl.prefix == NULL) &&
590                     ((ptr = find_type(dl->decl.type)) != NULL) &&
591                     ((dl->decl.rel == REL_ALIAS)||
592                      (dl->decl.rel == REL_VECTOR))){
593                         if (dl->decl.rel == REL_ALIAS)
594                                 size += ptr->length;
595                         else {
596                                 can_inline = 1;
597                                 break; /* can be inlined */
598                         }
599                 } else {
600                         if (size >= inline){
601                                 can_inline = 1;
602                                 break; /* can be inlined */
603                         }
604                         size = 0;
605                 }
606         if (size >= inline)
607                 can_inline = 1;
608
609         if (can_inline == 0){   /* can not inline, drop back to old mode */
610                 for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
611                         print_stat(1, &dl->decl);
612                 return;
613         }
614
615         flag = PUT;
616         for (j = 0; j < 2; j++){
617                 inline_struct(def, flag);
618                 if (flag == PUT)
619                         flag = GET;
620         }
621
622         f_print(fout, "\t\treturn (TRUE);\n\t}\n\n");
623
624         /* now take care of XDR_FREE case */
625
626         for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
627                 print_stat(1, &dl->decl);
628
629 }
630
631 static void
632 emit_typedef(def)
633         definition *def;
634 {
635         char *prefix = def->def.ty.old_prefix;
636         char *type = def->def.ty.old_type;
637         char *amax = def->def.ty.array_max;
638         relation rel = def->def.ty.rel;
639
640         print_ifstat(1, prefix, type, rel, amax, "objp", def->def_name);
641 }
642
643 static void
644 print_stat(indent, dec)
645         int indent;
646         declaration *dec;
647 {
648         char *prefix = dec->prefix;
649         char *type = dec->type;
650         char *amax = dec->array_max;
651         relation rel = dec->rel;
652         char name[256];
653
654         if (isvectordef(type, rel)) {
655                 s_print(name, "objp->%s", dec->name);
656         } else {
657                 s_print(name, "&objp->%s", dec->name);
658         }
659         print_ifstat(indent, prefix, type, rel, amax, name, dec->name);
660 }
661
662
663 char *upcase ();
664
665 static void
666 emit_inline(indent, decl, flag)
667 int indent;
668 declaration *decl;
669 int flag;
670 {
671         switch (decl->rel) {
672         case  REL_ALIAS :
673                 emit_single_in_line(indent, decl, flag, REL_ALIAS);
674                 break;
675         case REL_VECTOR :
676                 tabify(fout, indent);
677                 f_print(fout, "{\n");
678                 tabify(fout, indent + 1);
679                 f_print(fout, "register %s *genp;\n\n", decl->type);
680                 tabify(fout, indent + 1);
681                 f_print(fout,
682                         "for (i = 0, genp = objp->%s;\n", decl->name);
683                 tabify(fout, indent + 2);
684                 f_print(fout, "i < %s; i++) {\n", decl->array_max);
685                 emit_single_in_line(indent + 2, decl, flag, REL_VECTOR);
686                 tabify(fout, indent + 1);
687                 f_print(fout, "}\n");
688                 tabify(fout, indent);
689                 f_print(fout, "}\n");
690         default:
691         }
692 }
693
694 static void
695 emit_single_in_line(indent, decl, flag, rel)
696 int indent;
697 declaration *decl;
698 int flag;
699 relation rel;
700 {
701         char *upp_case;
702         int freed = 0;
703
704         tabify(fout, indent);
705         if (flag == PUT)
706                 f_print(fout, "IXDR_PUT_");
707         else
708                 if (rel == REL_ALIAS)
709                         f_print(fout, "objp->%s = IXDR_GET_", decl->name);
710                 else
711                         f_print(fout, "*genp++ = IXDR_GET_");
712
713         upp_case = upcase(decl->type);
714
715         /* hack  - XX */
716         if (strcmp(upp_case, "INT") == 0)
717         {
718                 free(upp_case);
719                 freed = 1;
720                 upp_case = "LONG";
721         }
722
723         if (strcmp(upp_case, "U_INT") == 0)
724         {
725                 free(upp_case);
726                 freed = 1;
727                 upp_case = "U_LONG";
728         }
729         if (flag == PUT)
730                 if (rel == REL_ALIAS)
731                         f_print(fout,
732                                 "%s(buf, objp->%s);\n", upp_case, decl->name);
733                 else
734                         f_print(fout, "%s(buf, *genp++);\n", upp_case);
735
736         else
737                 f_print(fout, "%s(buf);\n", upp_case);
738         if (!freed)
739                 free(upp_case);
740 }
741
742 char *upcase(str)
743 char *str;
744 {
745         char *ptr, *hptr;
746
747         ptr =  (char *)malloc(strlen(str)+1);
748         if (ptr == (char *) NULL)
749                 errx(1, "malloc failed");
750
751         hptr = ptr;
752         while (*str != '\0')
753                 *ptr++ = toupper(*str++);
754
755         *ptr = '\0';
756         return (hptr);
757 }