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