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