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