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