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