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