2ac8b4f0e3daf3722309c08888250f4d12911060
[openafs.git] / src / rxgen / rpc_main.c
1 /* @(#)rpc_main.c       1.4 87/11/30 3.9 RPCSRC */
2 /*
3  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
4  * unrestricted use provided that this legend is included on all tape
5  * media and as a part of the software program in whole or part.  Users
6  * may copy or modify Sun RPC without charge, but are not authorized
7  * to license or distribute it to anyone else except as part of a product or
8  * program developed by the user.
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  * rpc_main.c, Top level of the RPC protocol compiler. 
33  * Copyright (C) 1987, Sun Microsystems, Inc. 
34  */
35
36 #include <afsconfig.h>
37 #include <afs/param.h>
38
39 RCSID
40     ("$Header$");
41
42 #include <limits.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <ctype.h>
46 #ifdef HAVE_STRING_H
47 #include <string.h>
48 #else
49 #ifdef HAVE_STRINGS_H
50 #include <strings.h>
51 #endif
52 #endif
53 #ifdef HAVE_SIGNAL_H
54 #include <signal.h>
55 #endif
56 #ifdef HAVE_SYS_FILE_H
57 #include <sys/file.h>
58 #endif
59 #ifdef HAVE_UNISTD_H
60 #include <unistd.h>
61 #endif
62 #include "rpc_scan.h"
63 #include "rpc_parse.h"
64 #include "rpc_util.h"
65
66 #define EXTEND  1               /* alias for TRUE */
67
68 struct commandline {
69     int cflag;
70     int hflag;
71     int lflag;
72     int sflag;
73     int mflag;
74     int Cflag;
75     int Sflag;
76     int rflag;
77     int kflag;
78     int pflag;
79     int dflag;
80     int xflag;
81     int yflag;
82     int uflag;
83     char *infile;
84     char *outfile;
85 };
86
87 #define MAXCPPARGS      256     /* maximum number of arguments to cpp */
88 #define MAXCMDLINE      1024    /* MAX chars on a single  cmd line */
89
90 char *prefix = "";
91 static char *IncludeDir[MAXCPPARGS];
92 int nincludes = 0;
93 char *OutFileFlag = "";
94 char OutFile[256];
95 char Sflag = 0, Cflag = 0, hflag = 0, cflag = 0, kflag = 0, uflag = 0;
96 char zflag = 0;                 /* If set, abort server stub if rpc call returns non-zero */
97 char xflag = 0;                 /* if set, add stats code to stubs */
98 char yflag = 0;                 /* if set, only emit function name arrays to xdr file */
99 int debug = 0;
100 static char *cmdname;
101 #ifdef  __PROG_CPP__
102 static char CPP[] = __PROG_CPP__;
103 #else
104 static char CPP[] = "/lib/cpp";
105 #endif
106 static char CPPFLAGS[] = "-C";
107
108 #ifdef  AFS_ALPHA_ENV
109 /*
110  * Running "cpp" directly on DEC OSF/1 does not define anything; the "cc"
111  * driver is responsible.  To compensate (and allow for other definitions
112  * which should always be passed to "cpp"), place definitions which whould
113  * always be passed to "rxgen" in this table.
114  */
115 static char *XTRA_CPPFLAGS[] = {
116 #ifdef  __alpha
117     "-D__alpha",
118 #endif /* __alpha */
119 #ifdef  OSF
120     "-DOSF",
121 #endif /* OSF */
122     NULL
123 };
124 #endif
125
126 #include "AFS_component_version_number.c"
127
128 /* static prototypes */
129 static char *extendfile(char *file, char *ext);
130 static void open_output(char *infile, char *outfile);
131 static void open_input(char *infile, char *define);
132 static void c_output(char *infile, char *define, int extend, char *outfile,
133                      int append);
134 static void h_output(char *infile, char *define, int extend, char *outfile,
135                      int append);
136 static void s_output(int argc, char *argv[], char *infile, char *define,
137                      int extend, char *outfile, int nomain);
138 static void l_output(char *infile, char *define, int extend, char *outfile);
139 static void do_registers(int argc, char *argv[]);
140 static int parseargs(int argc, char *argv[], struct commandline *cmd);
141 static void C_output(char *infile, char *define, int extend, char *outfile,
142                      int append);
143 static void S_output(char *infile, char *define, int extend, char *outfile,
144                      int append);
145 static char *uppercase(char *str);
146
147 int
148 main(int argc, char *argv[])
149 {
150     struct commandline cmd;
151 #ifdef AFS_NT40_ENV
152     char *ep;
153
154     /* initialize CPP with the correct pre-processor on NT */
155     ep = getenv("RXGEN_CPPCMD");
156     if (ep)
157         strcpy(CPP, ep);
158     else
159         strcpy(CPP, "cl /EP /C /nologo");
160 #endif
161 #ifdef  AFS_AIX32_ENV
162     /*
163      * The following signal action for AIX is necessary so that in case of a 
164      * crash (i.e. core is generated) we can include the user's data section 
165      * in the core dump. Unfortunately, by default, only a partial core is
166      * generated which, in many cases, isn't too useful.
167      */
168     struct sigaction nsa;
169
170     sigemptyset(&nsa.sa_mask);
171     nsa.sa_handler = SIG_DFL;
172     nsa.sa_flags = SA_FULLDUMP;
173     sigaction(SIGSEGV, &nsa, NULL);
174 #endif
175     reinitialize();
176     if (!parseargs(argc, argv, &cmd)) {
177         f_print(stderr, "usage: %s infile\n", cmdname);
178         f_print(stderr,
179                 "       %s [-c | -h | -l | -m | -C | -S | -r | -k | -R | -p | -d | -z | -u] [-Pprefix] [-Idir] [-o outfile] [infile]\n",
180                 cmdname);
181         f_print(stderr, "       %s [-s udp|tcp]* [-o outfile] [infile]\n",
182                 cmdname);
183         exit(1);
184     }
185     OutFileFlag = cmd.outfile;
186     if (OutFileFlag)
187         strcpy(OutFile, cmd.outfile);
188     if (cmd.cflag) {
189         OutFileFlag = NULL;
190         c_output(cmd.infile, "-DRPC_XDR", !EXTEND, cmd.outfile, 0);
191     } else if (cmd.hflag) {
192         h_output(cmd.infile, "-DRPC_HDR", !EXTEND, cmd.outfile, 0);
193     } else if (cmd.lflag) {
194         l_output(cmd.infile, "-DRPC_CLNT", !EXTEND, cmd.outfile);
195     } else if (cmd.sflag || cmd.mflag) {
196         s_output(argc, argv, cmd.infile, "-DRPC_SVC", !EXTEND, cmd.outfile,
197                  cmd.mflag);
198     } else if (cmd.Cflag) {
199         OutFileFlag = NULL;
200         C_output(cmd.infile, "-DRPC_CLIENT", !EXTEND, cmd.outfile, 1);
201     } else if (cmd.Sflag) {
202         OutFileFlag = NULL;
203         S_output(cmd.infile, "-DRPC_SERVER", !EXTEND, cmd.outfile, 1);
204     } else {
205         if (OutFileFlag && (strrchr(OutFile, '.') == NULL))
206             strcat(OutFile, ".");
207         if (cmd.rflag) {
208             C_output((OutFileFlag ? OutFile : cmd.infile), "-DRPC_CLIENT",
209                      EXTEND, ".cs.c", 1);
210             reinitialize();
211             S_output((OutFileFlag ? OutFile : cmd.infile), "-DRPC_SERVER",
212                      EXTEND, ".ss.c", 1);
213             reinitialize();
214         } else {
215             reinitialize();
216             c_output((OutFileFlag ? OutFile : cmd.infile), "-DRPC_XDR",
217                      EXTEND, ".xdr.c", 0);
218             reinitialize();
219             h_output((OutFileFlag ? OutFile : cmd.infile), "-DRPC_HDR",
220                      EXTEND, ".h", 0);
221             reinitialize();
222             C_output((OutFileFlag ? OutFile : cmd.infile), "-DRPC_CLIENT",
223                      EXTEND, ".cs.c", 1);
224             reinitialize();
225             S_output((OutFileFlag ? OutFile : cmd.infile), "-DRPC_SERVER",
226                      EXTEND, ".ss.c", 1);
227             reinitialize();
228         }
229     }
230     exit(0);
231 }
232
233 /*
234  * add extension to filename 
235  */
236 static char *
237 extendfile(char *file, char *ext)
238 {
239     char *res;
240     char *p;
241     char *sname;
242
243     res = alloc(strlen(file) + strlen(ext) + 1);
244     if (res == NULL) {
245         abort();
246     }
247     p = (char *)strrchr(file, '.');
248     if (p == NULL) {
249         p = file + strlen(file);
250     }
251     sname = (char *)strrchr(file, '/');
252     if (sname == NULL)
253         sname = file;
254     else
255         sname++;
256     strcpy(res, sname);
257     strcpy(res + (p - sname), ext);
258     return (res);
259 }
260
261 /*
262  * Open output file with given extension 
263  */
264 static void
265 open_output(char *infile, char *outfile)
266 {
267     if (outfile == NULL) {
268         fout = stdout;
269         return;
270     }
271     if (infile != NULL && streq(outfile, infile)) {
272         f_print(stderr, "%s: output would overwrite %s\n", cmdname, infile);
273         crash();
274     }
275     fout = fopen(outfile, "w");
276     if (fout == NULL) {
277         f_print(stderr, "%s: unable to open ", cmdname);
278         perror(outfile);
279         crash();
280     }
281     record_open(outfile);
282 }
283
284 /*
285  * Open input file with given define for C-preprocessor 
286  */
287 static void
288 open_input(char *infile, char *define)
289 {
290     char cpp_cmdline[MAXCMDLINE];
291
292     int i;
293     if (debug == 0) {
294         infilename = (infile == NULL) ? "<stdin>" : infile;
295         strcpy(cpp_cmdline, CPP);
296         strcat(cpp_cmdline, " ");
297         strcat(cpp_cmdline, CPPFLAGS);
298         strcat(cpp_cmdline, " ");
299         strcat(cpp_cmdline, define);
300
301 #ifdef  AFS_ALPHA_ENV
302         for (i = 0;
303              i < (sizeof(XTRA_CPPFLAGS) / sizeof(XTRA_CPPFLAGS[0])) - 1;
304              i++) {
305             strcat(cpp_cmdline, " ");
306             strcat(cpp_cmdline, XTRA_CPPFLAGS[i]);
307         }
308 #endif
309         for (i = 0; i < nincludes; i++) {
310             strcat(cpp_cmdline, " ");
311             strcat(cpp_cmdline, IncludeDir[i]);
312         }
313
314         strcat(cpp_cmdline, " ");
315         strcat(cpp_cmdline, infile);
316
317         fin = popen(cpp_cmdline, "r");
318         if (fin == NULL)
319             perror("popen");
320
321     } else {
322         if (infile == NULL) {
323             fin = stdin;
324             return;
325         }
326         fin = fopen(infile, "r");
327     }
328     if (fin == NULL) {
329         f_print(stderr, "%s: ", cmdname);
330         perror(infilename);
331         crash();
332     }
333 }
334
335 /*
336  * Compile into an XDR routine output file
337  */
338 static void
339 c_output(char *infile, char *define, int extend, char *outfile, int append)
340 {
341     definition *def;
342     char *include;
343     char *outfilename;
344     long tell;
345     char fullname[1024];
346     char *currfile = (OutFileFlag ? OutFile : infile);
347     int i, j;
348
349     open_input(infile, define);
350     cflag = 1;
351     memset(fullname, 0, sizeof(fullname));
352     if (append) {
353         strcpy(fullname, prefix);
354         strcat(fullname, infile);
355     } else
356         strcpy(fullname, infile);
357     outfilename = extend ? extendfile(fullname, outfile) : outfile;
358     open_output(infile, outfilename);
359     f_print(fout, "/* Machine generated file -- Do NOT edit */\n\n");
360     if (xflag) {
361         if (kflag) {
362             f_print(fout, "#include \"afs/param.h\"\n");
363         } else {
364             f_print(fout, "#include <afs/param.h>\n");
365         }
366         f_print(fout, "#ifdef AFS_NT40_ENV\n");
367         f_print(fout, "#define AFS_RXGEN_EXPORT __declspec(dllexport)\n");
368         f_print(fout, "#endif /* AFS_NT40_ENV */\n");
369     }
370     if (currfile && (include = extendfile(currfile, ".h"))) {
371         if (kflag) {
372             f_print(fout, "#include \"%s\"\n\n", include);
373         } else
374             f_print(fout, "#include \"%s\"\n\n", include);
375         free(include);
376     } else {
377         /* In case we can't include the interface's own header file... */
378         if (kflag) {
379             f_print(fout, "#include \"h/types.h\"\n");
380             f_print(fout, "#include \"h/socket.h\"\n");
381             f_print(fout, "#include \"h/file.h\"\n");
382             f_print(fout, "#include \"h/stat.h\"\n");
383             f_print(fout, "#include \"netinet/in.h\"\n");
384             f_print(fout, "#include \"h/time.h\"\n");
385             f_print(fout, "#include \"rx/xdr.h\"\n");
386             f_print(fout, "#include \"rxgen_consts.h\"\n");
387         } else {
388             f_print(fout, "#include <rx/xdr.h>\n");
389         }
390     }
391
392     tell = ftell(fout);
393     while ((def = get_definition())) {
394         if (!yflag) {
395             if ((!IsRxgenDefinition(def)) && def->def_kind != DEF_CUSTOMIZED)
396                 emit(def);
397         }
398     }
399
400     /*
401      * Print out array containing list of all functions in the interface
402      * in order
403      */
404
405     if (xflag) {
406         for (j = 0; j <= PackageIndex; j++) {
407             f_print(fout, "AFS_RXGEN_EXPORT\n");
408             f_print(fout, "const char *%sfunction_names[] = {\n",
409                     PackagePrefix[j]);
410
411             for (i = 0; i < no_of_stat_funcs_header[j]; i++) {
412                 if (i == 0) {
413                     f_print(fout, "\t\"%s\"", function_list[j][i]);
414                 } else {
415                     f_print(fout, ",\n\t\"%s\"", function_list[j][i]);
416                 }
417             }
418
419             f_print(fout, "\n};\n");
420         }
421     }
422
423     if (extend && tell == ftell(fout)) {
424         (void)unlink(outfilename);
425     }
426     cflag = 0;
427 }
428
429 /*
430  * Compile into an XDR header file
431  */
432 static void
433 h_output(char *infile, char *define, int extend, char *outfile, int append)
434 {
435     definition *def;
436     char *outfilename;
437     long tell;
438     char fullname[1024], *p;
439
440     open_input(infile, define);
441     hflag = 1;
442     memset(fullname, 0, sizeof(fullname));
443     if (append) {
444         strcpy(fullname, prefix);
445         strcat(fullname, infile);
446     } else
447         strcpy(fullname, infile);
448     outfilename = extend ? extendfile(fullname, outfile) : outfile;
449     open_output(infile, outfilename);
450     strcpy(fullname, outfilename);
451     if ((p = strchr(fullname, '.')))
452         *p = '\0';
453     f_print(fout, "/* Machine generated file -- Do NOT edit */\n\n");
454     f_print(fout, "#ifndef      _RXGEN_%s_\n", uppercase(fullname));
455     f_print(fout, "#define      _RXGEN_%s_\n\n", uppercase(fullname));
456     f_print(fout, "#ifdef       KERNEL\n");
457     f_print(fout,
458             "/* The following 'ifndefs' are not a good solution to the vendor's omission of surrounding all system includes with 'ifndef's since it requires that this file is included after the system includes...*/\n");
459     f_print(fout, "#include <afsconfig.h>\n");
460     f_print(fout, "#include \"afs/param.h\"\n");
461     f_print(fout, "#ifdef       UKERNEL\n");
462     f_print(fout, "#include \"afs/sysincludes.h\"\n");
463     f_print(fout, "#include \"rx/xdr.h\"\n");
464     f_print(fout, "#include \"rx/rx.h\"\n");
465     if (xflag) {
466         f_print(fout, "#include \"rx/rx_globals.h\"\n");
467     }
468     if (uflag)
469         f_print(fout, "#include <ubik.h>\n");
470     f_print(fout, "#else        /* UKERNEL */\n");
471     f_print(fout, "#include \"h/types.h\"\n");
472     f_print(fout, "#ifndef      SOCK_DGRAM  /* XXXXX */\n");
473     f_print(fout, "#include \"h/socket.h\"\n");
474     f_print(fout, "#endif\n");
475     f_print(fout, "struct ubik_client;\n");
476     f_print(fout, "#ifndef      DTYPE_SOCKET  /* XXXXX */\n");
477     f_print(fout, "#ifndef AFS_LINUX22_ENV\n");
478     f_print(fout, "#include \"h/file.h\"\n");
479     f_print(fout, "#endif\n");
480     f_print(fout, "#endif\n");
481     f_print(fout, "#ifndef      S_IFMT  /* XXXXX */\n");
482     f_print(fout, "#include \"h/stat.h\"\n");
483     f_print(fout, "#endif\n");
484     f_print(fout, "#if defined (AFS_OBSD_ENV) && !defined (MLEN)\n");
485     f_print(fout, "#include \"sys/mbuf.h\"\n");
486     f_print(fout, "#endif\n");
487     f_print(fout, "#ifndef      IPPROTO_UDP /* XXXXX */\n");
488     f_print(fout, "#include \"netinet/in.h\"\n");
489     f_print(fout, "#endif\n");
490     f_print(fout, "#ifndef      DST_USA  /* XXXXX */\n");
491     f_print(fout, "#include \"h/time.h\"\n");
492     f_print(fout, "#endif\n");
493     f_print(fout, "#ifndef AFS_LINUX22_ENV\n");
494     f_print(fout, "#include \"rpc/types.h\"\n");
495     f_print(fout, "#endif /* AFS_LINUX22_ENV */\n");
496     f_print(fout, "#ifndef      XDR_GETLONG /* XXXXX */\n");
497     f_print(fout, "#ifdef AFS_LINUX22_ENV\n");
498     f_print(fout, "#ifndef quad_t\n");
499     f_print(fout, "#define quad_t __quad_t\n");
500     f_print(fout, "#define u_quad_t __u_quad_t\n");
501     f_print(fout, "#endif\n");
502     f_print(fout, "#endif\n");
503     f_print(fout, "#include \"rx/xdr.h\"\n");
504     f_print(fout, "#endif /* XDR_GETLONG */\n");
505     f_print(fout, "#endif   /* UKERNEL */\n");
506     f_print(fout, "#include \"rxgen_consts.h\"\n");
507     f_print(fout, "#include \"afs_osi.h\"\n");
508     f_print(fout, "#include \"rx/rx.h\"\n");
509     if (xflag) {
510         f_print(fout, "#include \"rx/rx_globals.h\"\n");
511     }
512     f_print(fout, "#else        /* KERNEL */\n");
513     f_print(fout, "#include <afs/param.h>\n");
514     f_print(fout, "#include <afs/stds.h>\n");
515     f_print(fout, "#include <sys/types.h>\n");
516     f_print(fout, "#include <rx/xdr.h>\n");
517     f_print(fout, "#include <rx/rx.h>\n");
518     if (xflag) {
519         f_print(fout, "#include <rx/rx_globals.h>\n");
520     }
521     f_print(fout, "#include <afs/rxgen_consts.h>\n");
522     if (uflag)
523         f_print(fout, "#include <ubik.h>\n");
524     f_print(fout, "#endif       /* KERNEL */\n\n");
525     f_print(fout, "#ifdef AFS_NT40_ENV\n");
526     f_print(fout, "#ifndef AFS_RXGEN_EXPORT\n");
527     f_print(fout, "#define AFS_RXGEN_EXPORT __declspec(dllimport)\n");
528     f_print(fout, "#endif /* AFS_RXGEN_EXPORT */\n");
529     f_print(fout, "#else /* AFS_NT40_ENV */\n");
530     f_print(fout, "#define AFS_RXGEN_EXPORT\n");
531     f_print(fout, "#endif /* AFS_NT40_ENV */\n\n");
532     tell = ftell(fout);
533     while ((def = get_definition())) {
534         print_datadef(def);
535     }
536     h_opcode_stats();
537     hflag = 0;
538     f_print(fout, "#endif       /* _RXGEN_%s_ */\n", uppercase(fullname));
539     if (extend && tell == ftell(fout)) {
540         (void)unlink(outfilename);
541     }
542 }
543
544 /*
545  * Compile into an RPC service
546  */
547 static void
548 s_output(int argc, char *argv[], char *infile, char *define, int extend,
549          char *outfile, int nomain)
550 {
551     char *include;
552     definition *def;
553     int foundprogram;
554     char *outfilename;
555
556     open_input(infile, define);
557     outfilename = extend ? extendfile(infile, outfile) : outfile;
558     open_output(infile, outfilename);
559     f_print(fout, "#include <stdio.h>\n");
560     f_print(fout, "#include <rpc/rpc.h>\n");
561     if (infile && (include = extendfile(infile, ".h"))) {
562         f_print(fout, "#include \"%s\"\n", include);
563         free(include);
564     }
565     foundprogram = 0;
566     while ((def = get_definition())) {
567         foundprogram |= (def->def_kind == DEF_PROGRAM);
568     }
569     if (extend && !foundprogram) {
570         (void)unlink(outfilename);
571         return;
572     }
573     if (nomain) {
574         write_programs((char *)NULL);
575     } else {
576         write_most();
577         do_registers(argc, argv);
578         write_rest();
579         write_programs("static");
580     }
581 }
582
583 static void
584 l_output(char *infile, char *define, int extend, char *outfile)
585 {
586     char *include;
587     definition *def;
588     int foundprogram;
589     char *outfilename;
590
591     open_input(infile, define);
592     outfilename = extend ? extendfile(infile, outfile) : outfile;
593     open_output(infile, outfilename);
594     f_print(fout, "#include <rpc/rpc.h>\n");
595     f_print(fout, "#include <sys/time.h>\n");
596     if (infile && (include = extendfile(infile, ".h"))) {
597         f_print(fout, "#include \"%s\"\n", include);
598         free(include);
599     }
600     foundprogram = 0;
601     while ((def = get_definition())) {
602         foundprogram |= (def->def_kind == DEF_PROGRAM);
603     }
604     if (extend && !foundprogram) {
605         (void)unlink(outfilename);
606         return;
607     }
608     write_stubs();
609 }
610
611 /*
612  * Perform registrations for service output 
613  */
614 static void
615 do_registers(int argc, char *argv[])
616 {
617     int i;
618
619     for (i = 1; i < argc; i++) {
620         if (streq(argv[i], "-s")) {
621             write_register(argv[i + 1]);
622             i++;
623         }
624     }
625 }
626
627
628 static void
629 C_output(char *infile, char *define, int extend, char *outfile, int append)
630 {
631     char *include;
632     char *outfilename;
633     char fullname[1024];
634     long tell;
635     char *currfile = (OutFileFlag ? OutFile : infile);
636
637     Cflag = 1;
638     open_input(infile, define);
639     memset(fullname, 0, sizeof(fullname));
640     if (append) {
641         strcpy(fullname, prefix);
642         strcat(fullname, infile);
643     } else
644         strcpy(fullname, infile);
645     outfilename = extend ? extendfile(fullname, outfile) : outfile;
646     open_output(infile, outfilename);
647     f_print(fout, "/* Machine generated file -- Do NOT edit */\n\n");
648     if (currfile && (include = extendfile(currfile, ".h"))) {
649         if (kflag) {
650             f_print(fout, "#include \"%s\"\n\n", include);
651         } else {
652             f_print(fout, "#include \"%s\"\n\n", include);
653         }
654         free(include);
655     } else {
656         if (kflag) {
657             f_print(fout, "#include \"h/types.h\"\n");
658             f_print(fout, "#include \"h/socket.h\"\n");
659             f_print(fout, "#include \"h/file.h\"\n");
660             f_print(fout, "#include \"h/stat.h\"\n");
661             f_print(fout, "#include \"netinet/in.h\"\n");
662             f_print(fout, "#include \"h/time.h\"\n");
663             f_print(fout, "#include \"rpc/types.h\"\n");
664             f_print(fout, "#include \"rx/xdr.h\"\n");
665             f_print(fout, "#include \"rxgen_consts.h\"\n");
666             f_print(fout, "#include \"afs/afs_osi.h\"\n");
667             f_print(fout, "#include \"rx/rx.h\"\n");
668             if (xflag) {
669                 f_print(fout, "#include \"rx/rx_globals.h\"\n");
670             }
671         } else {
672             f_print(fout, "#include <sys/types.h>\n");
673             f_print(fout, "#include <rx/xdr.h>\n");
674             f_print(fout, "#include <rx/rx.h>\n");
675             if (xflag) {
676                 f_print(fout, "#include <rx/rx_globals.h>\n");
677             }
678             f_print(fout, "#include <afs/rxgen_consts.h>\n");
679         }
680     }
681
682     tell = ftell(fout);
683     while (get_definition())
684         continue;
685     if (extend && tell == ftell(fout)) {
686         (void)unlink(outfilename);
687     }
688
689     Cflag = 0;
690 }
691
692 static void
693 S_output(char *infile, char *define, int extend, char *outfile, int append)
694 {
695     char *include;
696     char *outfilename;
697     char fullname[1024];
698     definition *def;
699     long tell;
700     char *currfile = (OutFileFlag ? OutFile : infile);
701
702     Sflag = 1;
703     open_input(infile, define);
704     memset(fullname, 0, sizeof(fullname));
705     if (append) {
706         strcpy(fullname, prefix);
707         strcat(fullname, infile);
708     } else
709         strcpy(fullname, infile);
710     outfilename = extend ? extendfile(fullname, outfile) : outfile;
711     open_output(infile, outfilename);
712     f_print(fout, "/* Machine generated file -- Do NOT edit */\n\n");
713     if (currfile && (include = extendfile(currfile, ".h"))) {
714         if (kflag) {
715             f_print(fout, "#include \"%s\"\n", include);
716         } else {
717             f_print(fout, "#include \"%s\"\n\n", include);
718         }
719         free(include);
720     } else {
721         if (kflag) {
722             f_print(fout, "#include \"h/types.h\"\n");
723             f_print(fout, "#include \"h/socket.h\"\n");
724             f_print(fout, "#include \"h/file.h\"\n");
725             f_print(fout, "#include \"h/stat.h\"\n");
726             f_print(fout, "#include \"netinet/in.h\"\n");
727             f_print(fout, "#include \"h/time.h\"\n");
728             f_print(fout, "#include \"rpc/types.h\"\n");
729             f_print(fout, "#include \"rx/xdr.h\"\n");
730             f_print(fout, "#include \"rxgen_consts.h\"\n");
731             f_print(fout, "#include \"afs/afs_osi.h\"\n");
732             f_print(fout, "#include \"rx/rx.h\"\n");
733             if (xflag) {
734                 f_print(fout, "#include \"rx/rx_globals.h\"\n");
735             }
736         } else {
737             f_print(fout, "#include <sys/types.h>\n");
738             f_print(fout, "#include <rx/xdr.h>\n");
739             f_print(fout, "#include <rx/rx.h>\n");
740             if (xflag) {
741                 f_print(fout, "#include <rx/rx_globals.h>\n");
742             }
743             f_print(fout, "#include <afs/rxgen_consts.h>\n");
744         }
745     }
746
747     tell = ftell(fout);
748     fflush(fout);
749     while ((def = get_definition())) {
750         fflush(fout);
751         print_datadef(def);
752     }
753
754     er_Proc_CodeGeneration();
755
756     if (extend && tell == ftell(fout)) {
757         (void)unlink(outfilename);
758     }
759     Sflag = 0;
760 }
761
762 static char *
763 uppercase(char *str)
764 {
765     static char max_size[100];
766     char *pnt;
767     int len = (int)strlen(str);
768
769     for (pnt = max_size; len > 0; len--, str++) {
770         *pnt++ = (islower(*str) ? toupper(*str) : *str);
771     }
772     *pnt = '\0';
773     return max_size;
774 }
775
776 /*
777  * Parse command line arguments 
778  */
779 static int
780 parseargs(int argc, char *argv[], struct commandline *cmd)
781 {
782     int i;
783     int j;
784     char c;
785     char flag[(1 << (8 * sizeof(char)))];
786     int nflags;
787
788     cmdname = argv[0];
789     cmd->infile = cmd->outfile = NULL;
790     if (argc < 2) {
791         return (0);
792     }
793     memset(flag, 0, sizeof(flag));
794     cmd->outfile = NULL;
795     for (i = 1; i < argc; i++) {
796         if (argv[i][0] != '-') {
797             if (cmd->infile) {
798                 return (0);
799             }
800             cmd->infile = argv[i];
801         } else {
802             for (j = 1; argv[i][j] != 0; j++) {
803                 c = argv[i][j];
804                 switch (c) {
805                 case 'c':
806                 case 'h':
807                 case 'l':
808                 case 'm':
809                 case 'C':
810                 case 'S':
811                 case 'r':
812                 case 'R':
813                 case 'k':
814                 case 'p':
815                 case 'd':
816                 case 'u':
817                 case 'x':
818                 case 'y':
819                 case 'z':
820                     if (flag[(int)c]) {
821                         return (0);
822                     }
823                     flag[(int)c] = 1;
824                     break;
825                 case 'o':
826                 case 's':
827                     if (argv[i][j - 1] != '-' || argv[i][j + 1] != 0) {
828                         return (0);
829                     }
830                     flag[(int)c] = 1;
831                     if (++i == argc) {
832                         return (0);
833                     }
834                     if (c == 's') {
835                         if (!streq(argv[i], "udp") && !streq(argv[i], "tcp")) {
836                             return (0);
837                         }
838                     } else if (c == 'o') {
839                         if (cmd->outfile) {
840                             return (0);
841                         }
842                         cmd->outfile = argv[i];
843                     }
844                     goto nextarg;
845                 case 'P':
846                     if (argv[i][j - 1] != '-')
847                         return (0);
848                     prefix = &argv[i][j + 1];
849                     goto nextarg;
850                 case 'I':
851                     if (argv[i][j - 1] != '-')
852                         return (0);
853                     IncludeDir[nincludes++] = &argv[i][j - 1];
854                     goto nextarg;
855                 default:
856                     return (0);
857                 }
858             }
859           nextarg:
860             ;
861         }
862     }
863     cmd->cflag = cflag = flag['c'];
864     cmd->hflag = hflag = flag['h'];
865     cmd->sflag = flag['s'];
866     cmd->lflag = flag['l'];
867     cmd->mflag = flag['m'];
868     cmd->xflag = xflag = flag['x'];
869     cmd->yflag = yflag = flag['y'];
870     cmd->Cflag = Cflag = flag['C'];
871     cmd->Sflag = Sflag = flag['S'];
872     cmd->rflag = flag['r'];
873     cmd->uflag = uflag = flag['u'];
874     cmd->kflag = kflag = flag['k'];
875     cmd->pflag = flag['p'];
876     cmd->dflag = debug = flag['d'];
877     zflag = flag['z'];
878     if (cmd->pflag)
879         combinepackages = 1;
880     nflags =
881         cmd->cflag + cmd->hflag + cmd->sflag + cmd->lflag + cmd->mflag +
882         cmd->Cflag + cmd->Sflag + cmd->rflag;
883     if (nflags == 0) {
884         if (cmd->outfile != NULL || cmd->infile == NULL) {
885             return (0);
886         }
887     } else if (nflags > 1) {
888         return (0);
889     }
890     return (1);
891 }