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