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