Make RXGEN_CPPCMD work on unix
[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
73 char *prefix = "";
74 static char *IncludeDir[MAXCPPARGS];
75 int nincludes = 0;
76 char *OutFileFlag = "";
77 char OutFile[256];
78 char Sflag = 0, Cflag = 0, hflag = 0, cflag = 0, kflag = 0, uflag = 0;
79 char ansic_flag = 0;            /* If set, build ANSI C style prototypes */
80 char brief_flag = 0;            /* If set, shorten names */
81 char zflag = 0;                 /* If set, abort server stub if rpc call returns non-zero */
82 char xflag = 0;                 /* if set, add stats code to stubs */
83 char yflag = 0;                 /* if set, only emit function name arrays to xdr file */
84 int debug = 0;
85 static int pclose_fin = 0;
86 static char *cmdname;
87 #ifdef PATH_CPP
88 static char *CPP = PATH_CPP;
89 #else
90 #ifdef AFS_NT40_ENV
91 static char *CPP = "cl /EP /C /nologo";
92 #else
93 static char *CPP = "/lib/cpp";
94 #endif
95 #endif
96
97 /*
98  * Running "cpp" directly on DEC OSF/1 does not define anything; the "cc"
99  * driver is responsible.  To compensate (and allow for other definitions
100  * which should always be passed to "cpp"), place definitions which whould
101  * always be passed to "rxgen" in this string.
102  */
103 static char *CPPFLAGS = "-C"
104 #ifdef  AFS_ALPHA_ENV
105 #ifdef  __alpha
106     " -D__alpha"
107 #endif /* __alpha */
108 #ifdef  OSF
109     " -DOSF"
110 #endif /* OSF */
111 #endif
112 ;
113
114 #include "AFS_component_version_number.c"
115
116 /* static prototypes */
117 static char *extendfile(char *file, char *ext);
118 static void open_output(char *infile, char *outfile);
119 static void open_input(char *infile, char *define);
120 static void c_output(char *infile, char *define, int extend, char *outfile,
121                      int append);
122 static void h_output(char *infile, char *define, int extend, char *outfile,
123                      int append);
124 static void s_output(int argc, char *argv[], char *infile, char *define,
125                      int extend, char *outfile, int nomain);
126 static void l_output(char *infile, char *define, int extend, char *outfile);
127 static void do_registers(int argc, char *argv[]);
128 static int parseargs(int argc, char *argv[], struct commandline *cmd);
129 static void C_output(char *infile, char *define, int extend, char *outfile,
130                      int append);
131 static void S_output(char *infile, char *define, int extend, char *outfile,
132                      int append);
133 static char *uppercase(char *str);
134
135 int
136 main(int argc, char *argv[])
137 {
138     struct commandline cmd;
139     char *ep;
140
141     ep = getenv("RXGEN_CPPCMD");
142     if (ep)
143         CPP = ep;
144 #ifdef  AFS_AIX32_ENV
145     /*
146      * The following signal action for AIX is necessary so that in case of a
147      * crash (i.e. core is generated) we can include the user's data section
148      * in the core dump. Unfortunately, by default, only a partial core is
149      * generated which, in many cases, isn't too useful.
150      */
151     struct sigaction nsa;
152
153     sigemptyset(&nsa.sa_mask);
154     nsa.sa_handler = SIG_DFL;
155     nsa.sa_flags = SA_FULLDUMP;
156     sigaction(SIGSEGV, &nsa, NULL);
157 #endif
158     reinitialize();
159     if (!parseargs(argc, argv, &cmd)) {
160         f_print(stderr, "usage: %s infile\n", cmdname);
161         f_print(stderr,
162                 "       %s [-c | -h | -l | -m | -C | -S | -r | -b | -k | -R | -p | -d | -z | -u] [-Pprefix] [-Idir] [-o outfile] [infile]\n",
163                 cmdname);
164         f_print(stderr, "       %s [-s udp|tcp]* [-o outfile] [infile]\n",
165                 cmdname);
166         exit(1);
167     }
168     OutFileFlag = cmd.outfile;
169     if (OutFileFlag)
170         strcpy(OutFile, cmd.outfile);
171     if (cmd.cflag) {
172         OutFileFlag = NULL;
173         c_output(cmd.infile, "-DRPC_XDR", !EXTEND, cmd.outfile, 0);
174     } else if (cmd.hflag) {
175         h_output(cmd.infile, "-DRPC_HDR", !EXTEND, cmd.outfile, 0);
176     } else if (cmd.lflag) {
177         l_output(cmd.infile, "-DRPC_CLNT", !EXTEND, cmd.outfile);
178     } else if (cmd.sflag || cmd.mflag) {
179         s_output(argc, argv, cmd.infile, "-DRPC_SVC", !EXTEND, cmd.outfile,
180                  cmd.mflag);
181     } else if (cmd.Cflag) {
182         OutFileFlag = NULL;
183         C_output(cmd.infile, "-DRPC_CLIENT", !EXTEND, cmd.outfile, 1);
184     } else if (cmd.Sflag) {
185         OutFileFlag = NULL;
186         S_output(cmd.infile, "-DRPC_SERVER", !EXTEND, cmd.outfile, 1);
187     } else {
188         if (OutFileFlag && (strrchr(OutFile, '.') == NULL))
189             strcat(OutFile, ".");
190         if (cmd.rflag) {
191             C_output((OutFileFlag ? OutFile : cmd.infile), "-DRPC_CLIENT",
192                      EXTEND, ".cs.c", 1);
193             reinitialize();
194             S_output((OutFileFlag ? OutFile : cmd.infile), "-DRPC_SERVER",
195                      EXTEND, ".ss.c", 1);
196             reinitialize();
197         } else {
198             reinitialize();
199             c_output((OutFileFlag ? OutFile : cmd.infile), "-DRPC_XDR",
200                      EXTEND, ".xdr.c", 0);
201             reinitialize();
202             h_output((OutFileFlag ? OutFile : cmd.infile), "-DRPC_HDR",
203                      EXTEND, ".h", 0);
204             reinitialize();
205             C_output((OutFileFlag ? OutFile : cmd.infile), "-DRPC_CLIENT",
206                      EXTEND, ".cs.c", 1);
207             reinitialize();
208             S_output((OutFileFlag ? OutFile : cmd.infile), "-DRPC_SERVER",
209                      EXTEND, ".ss.c", 1);
210             reinitialize();
211         }
212     }
213     if (fin && pclose_fin) {
214         /* the cpp command we called returned a non-zero exit status */
215         if (pclose(fin)) {
216             crash();
217         }
218     }
219     exit(0);
220 }
221
222 /*
223  * add extension to filename
224  */
225 static char *
226 extendfile(char *file, char *ext)
227 {
228     char *res;
229     char *p;
230     char *sname;
231
232     res = alloc(strlen(file) + strlen(ext) + 1);
233     if (res == NULL) {
234         abort();
235     }
236     p = (char *)strrchr(file, '.');
237     if (p == NULL) {
238         p = file + strlen(file);
239     }
240     sname = (char *)strrchr(file, '/');
241     if (sname == NULL)
242         sname = file;
243     else
244         sname++;
245     strcpy(res, sname);
246     strcpy(res + (p - sname), ext);
247     return (res);
248 }
249
250 /*
251  * Open output file with given extension
252  */
253 static void
254 open_output(char *infile, char *outfile)
255 {
256     if (outfile == NULL) {
257         fout = stdout;
258         return;
259     }
260     if (infile != NULL && streq(outfile, infile)) {
261         f_print(stderr, "%s: output would overwrite %s\n", cmdname, infile);
262         crash();
263     }
264     fout = fopen(outfile, "w");
265     if (fout == NULL) {
266         f_print(stderr, "%s: unable to open ", cmdname);
267         perror(outfile);
268         crash();
269     }
270     record_open(outfile);
271 }
272
273 /*
274  * Open input file with given define for C-preprocessor
275  */
276 static void
277 open_input(char *infile, char *define)
278 {
279     char *cpp_cmdline;
280     int i, l = 0;
281
282     if (debug == 0) {
283         infilename = (infile == NULL) ? "<stdin>" : infile;
284         l = strlen(CPP) + strlen(CPPFLAGS) + strlen(define) + 3;
285         for (i = 0; i < nincludes; i++)
286             l += strlen(IncludeDir[i]) + 1;
287         l += strlen(infile) + 1;
288         cpp_cmdline = malloc(l);
289         if (!cpp_cmdline) {
290           perror("Unable to allocate space for cpp command line");
291           crash();
292         }
293
294         sprintf(cpp_cmdline, "%s %s %s", CPP, CPPFLAGS, define);
295         l = strlen(cpp_cmdline);
296         for (i = 0; i < nincludes; i++) {
297             cpp_cmdline[l++] = ' ';
298             strcpy(cpp_cmdline + l, IncludeDir[i]);
299             l += strlen(IncludeDir[i]);
300         }
301         cpp_cmdline[l++] = ' ';
302         strcpy(cpp_cmdline + l, infile);
303
304         fin = popen(cpp_cmdline, "r");
305         if (fin == NULL)
306             perror("popen");
307         pclose_fin = 1;
308
309     } else {
310         if (infile == NULL) {
311             fin = stdin;
312             return;
313         }
314         fin = fopen(infile, "r");
315     }
316     if (fin == NULL) {
317         f_print(stderr, "%s: ", cmdname);
318         perror(infilename);
319         crash();
320     }
321 }
322
323 /*
324  * Compile into an XDR routine output file
325  */
326 static void
327 c_output(char *infile, char *define, int extend, char *outfile, int append)
328 {
329     definition *def;
330     char *include;
331     char *outfilename;
332     long tell;
333     char fullname[1024];
334     char *currfile = (OutFileFlag ? OutFile : infile);
335     int i, j;
336
337     open_input(infile, define);
338     cflag = 1;
339     memset(fullname, 0, sizeof(fullname));
340     if (append) {
341         strcpy(fullname, prefix);
342         strcat(fullname, infile);
343     } else
344         strcpy(fullname, infile);
345     outfilename = extend ? extendfile(fullname, outfile) : outfile;
346     open_output(infile, outfilename);
347     f_print(fout, "/* Machine generated file -- Do NOT edit */\n\n");
348     if (xflag) {
349         if (kflag) {
350             f_print(fout, "#include \"afsconfig.h\"\n");
351             f_print(fout, "#include \"afs/param.h\"\n");
352         } else {
353             f_print(fout, "#include <afsconfig.h>\n");
354             f_print(fout, "#include <afs/param.h>\n");
355             f_print(fout, "#include <roken.h>\n");
356         }
357         f_print(fout, "#ifdef AFS_NT40_ENV\n");
358         f_print(fout, "#define AFS_RXGEN_EXPORT __declspec(dllexport)\n");
359         f_print(fout, "#endif /* AFS_NT40_ENV */\n");
360     }
361     if (currfile && (include = extendfile(currfile, ".h"))) {
362         if (kflag) {
363             f_print(fout, "#include \"%s\"\n\n", include);
364         } else
365             f_print(fout, "#include \"%s\"\n\n", include);
366         free(include);
367     } else {
368         /* In case we can't include the interface's own header file... */
369         if (kflag) {
370             f_print(fout, "#include \"h/types.h\"\n");
371             f_print(fout, "#include \"h/socket.h\"\n");
372             f_print(fout, "#include \"h/file.h\"\n");
373             f_print(fout, "#include \"h/stat.h\"\n");
374             f_print(fout, "#include \"netinet/in.h\"\n");
375             f_print(fout, "#include \"h/time.h\"\n");
376             f_print(fout, "#include \"rx/xdr.h\"\n");
377             f_print(fout, "#include \"afs/rxgen_consts.h\"\n");
378         } else {
379             f_print(fout, "#include <rx/xdr.h>\n");
380         }
381     }
382
383     tell = ftell(fout);
384     while ((def = get_definition())) {
385         if (!yflag) {
386             if ((!IsRxgenDefinition(def)) && def->def_kind != DEF_CUSTOMIZED)
387                 emit(def);
388         }
389     }
390
391     /*
392      * Print out array containing list of all functions in the interface
393      * in order
394      */
395
396     if (xflag) {
397         for (j = 0; j <= PackageIndex; j++) {
398             f_print(fout, "AFS_RXGEN_EXPORT\n");
399             f_print(fout, "const char *%sfunction_names[] = {\n",
400                     PackagePrefix[j]);
401
402             for (i = 0; i < no_of_stat_funcs_header[j]; i++) {
403                 if (i == 0) {
404                     f_print(fout, "\t\"%s\"", function_list[j][i]);
405                 } else {
406                     f_print(fout, ",\n\t\"%s\"", function_list[j][i]);
407                 }
408             }
409
410
411             f_print(fout, "\n};\n");
412         }
413         er_Proc_CodeGeneration();
414     }
415
416     if (extend && tell == ftell(fout)) {
417         (void)unlink(outfilename);
418     }
419     cflag = 0;
420 }
421
422 /*
423  * Compile into an XDR header file
424  */
425 static void
426 h_output(char *infile, char *define, int extend, char *outfile, int append)
427 {
428     definition *def;
429     char *outfilename;
430     long tell;
431     char fullname[1024], *p;
432
433     open_input(infile, define);
434     hflag = 1;
435     memset(fullname, 0, sizeof(fullname));
436     if (append) {
437         strcpy(fullname, prefix);
438         strcat(fullname, infile);
439     } else
440         strcpy(fullname, infile);
441     outfilename = extend ? extendfile(fullname, outfile) : outfile;
442     open_output(infile, outfilename);
443     strcpy(fullname, outfilename);
444     if ((p = strchr(fullname, '.')))
445         *p = '\0';
446     f_print(fout, "/* Machine generated file -- Do NOT edit */\n\n");
447     f_print(fout, "#ifndef      _RXGEN_%s_\n", uppercase(fullname));
448     f_print(fout, "#define      _RXGEN_%s_\n\n", uppercase(fullname));
449     f_print(fout, "#ifdef       KERNEL\n");
450     f_print(fout,
451             "/* 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");
452     f_print(fout, "#include <afsconfig.h>\n");
453     f_print(fout, "#include \"afs/param.h\"\n");
454     f_print(fout, "#ifdef       UKERNEL\n");
455     f_print(fout, "#include \"afs/sysincludes.h\"\n");
456     f_print(fout, "#include \"rx/xdr.h\"\n");
457     f_print(fout, "#include \"rx/rx.h\"\n");
458     if (xflag) {
459         f_print(fout, "#include \"rx/rx_globals.h\"\n");
460     }
461     if (brief_flag) {
462         f_print(fout, "#include \"rx/rx_opaque.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 \"afs/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     if (brief_flag) {
509         f_print(fout, "#include \"rx/rx_opaque.h\"\n");
510     }
511     f_print(fout, "#else        /* KERNEL */\n");
512     f_print(fout, "#include <afs/param.h>\n");
513     f_print(fout, "#include <afs/stds.h>\n");
514     f_print(fout, "#include <sys/types.h>\n");
515     f_print(fout, "#include <rx/xdr.h>\n");
516     f_print(fout, "#include <rx/rx.h>\n");
517     if (xflag) {
518         f_print(fout, "#include <rx/rx_globals.h>\n");
519     }
520     if (brief_flag) {
521         f_print(fout, "#include <rx/rx_opaque.h>\n");
522     }
523     f_print(fout, "#include <afs/rxgen_consts.h>\n");
524     if (uflag)
525         f_print(fout, "#include <ubik.h>\n");
526     f_print(fout, "#endif       /* KERNEL */\n\n");
527     f_print(fout, "#ifdef AFS_NT40_ENV\n");
528     f_print(fout, "#ifndef AFS_RXGEN_EXPORT\n");
529     f_print(fout, "#define AFS_RXGEN_EXPORT __declspec(dllimport)\n");
530     f_print(fout, "#endif /* AFS_RXGEN_EXPORT */\n");
531     f_print(fout, "#else /* AFS_NT40_ENV */\n");
532     f_print(fout, "#define AFS_RXGEN_EXPORT\n");
533     f_print(fout, "#endif /* AFS_NT40_ENV */\n\n");
534     tell = ftell(fout);
535     while ((def = get_definition())) {
536         print_datadef(def);
537     }
538     h_Proc_CodeGeneration();
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(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 <afsconfig.h>\n");
656             f_print(fout, "#include <afs/param.h>\n");
657             f_print(fout, "#include <roken.h>\n");
658             f_print(fout, "#include <afs/opr.h>\n");
659             f_print(fout, "#ifdef AFS_PTHREAD_ENV\n");
660             f_print(fout, "# include <opr/lock.h>\n");
661             f_print(fout, "#endif\n");
662             f_print(fout, "#include \"%s\"\n\n", include);
663         }
664         free(include);
665     } else {
666         if (kflag) {
667             f_print(fout, "#include \"h/types.h\"\n");
668             f_print(fout, "#include \"h/socket.h\"\n");
669             f_print(fout, "#include \"h/file.h\"\n");
670             f_print(fout, "#include \"h/stat.h\"\n");
671             f_print(fout, "#include \"netinet/in.h\"\n");
672             f_print(fout, "#include \"h/time.h\"\n");
673             f_print(fout, "#include \"rpc/types.h\"\n");
674             f_print(fout, "#include \"rx/xdr.h\"\n");
675             f_print(fout, "#include \"afs/rxgen_consts.h\"\n");
676             f_print(fout, "#include \"afs/afs_osi.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             if (brief_flag) {
682                 f_print(fout, "#include \"rx/rx_opaque.h\"\n");
683             }
684         } else {
685             f_print(fout, "#include <sys/types.h>\n");
686             f_print(fout, "#include <rx/xdr.h>\n");
687             f_print(fout, "#include <rx/rx.h>\n");
688             if (xflag) {
689                 f_print(fout, "#include <rx/rx_globals.h>\n");
690             }
691             if (brief_flag) {
692                 f_print(fout, "#include <rx/rx_opaque.h\"\n");
693             }
694             f_print(fout, "#include <afs/rxgen_consts.h>\n");
695         }
696     }
697
698     tell = ftell(fout);
699     while (get_definition())
700         continue;
701     if (extend && tell == ftell(fout)) {
702         (void)unlink(outfilename);
703     }
704
705     Cflag = 0;
706 }
707
708 static void
709 S_output(char *infile, char *define, int extend, char *outfile, int append)
710 {
711     char *include;
712     char *outfilename;
713     char fullname[1024];
714     definition *def;
715     long tell;
716     char *currfile = (OutFileFlag ? OutFile : infile);
717
718     Sflag = 1;
719     open_input(infile, define);
720     memset(fullname, 0, sizeof(fullname));
721     if (append) {
722         strcpy(fullname, prefix);
723         strcat(fullname, infile);
724     } else
725         strcpy(fullname, infile);
726     outfilename = extend ? extendfile(fullname, outfile) : outfile;
727     open_output(infile, outfilename);
728     f_print(fout, "/* Machine generated file -- Do NOT edit */\n\n");
729     if (currfile && (include = extendfile(currfile, ".h"))) {
730         if (kflag) {
731             f_print(fout, "#include \"%s\"\n", include);
732         } else {
733             f_print(fout, "#include <afsconfig.h>\n");
734             f_print(fout, "#include <afs/param.h>\n");
735             f_print(fout, "#include <roken.h>\n");
736             f_print(fout, "#include \"%s\"\n\n", include);
737         }
738         free(include);
739     } else {
740         if (kflag) {
741             f_print(fout, "#include \"h/types.h\"\n");
742             f_print(fout, "#include \"h/socket.h\"\n");
743             f_print(fout, "#include \"h/file.h\"\n");
744             f_print(fout, "#include \"h/stat.h\"\n");
745             f_print(fout, "#include \"netinet/in.h\"\n");
746             f_print(fout, "#include \"h/time.h\"\n");
747             f_print(fout, "#include \"rpc/types.h\"\n");
748             f_print(fout, "#include \"rx/xdr.h\"\n");
749             f_print(fout, "#include \"afs/rxgen_consts.h\"\n");
750             f_print(fout, "#include \"afs/afs_osi.h\"\n");
751             f_print(fout, "#include \"rx/rx.h\"\n");
752             if (xflag) {
753                 f_print(fout, "#include \"rx/rx_globals.h\"\n");
754             }
755             if (brief_flag) {
756                 f_print(fout, "#include \"rx/rx_opaque.h\"\n");
757             }
758         } else {
759             f_print(fout, "#include <sys/types.h>\n");
760             f_print(fout, "#include <rx/xdr.h>\n");
761             f_print(fout, "#include <rx/rx.h>\n");
762             if (xflag) {
763                 f_print(fout, "#include <rx/rx_globals.h>\n");
764             }
765             if (brief_flag) {
766                 f_print(fout, "#include <rx/rx_opaque.h>\n");
767             }
768             f_print(fout, "#include <afs/rxgen_consts.h>\n");
769         }
770     }
771
772     tell = ftell(fout);
773     fflush(fout);
774     while ((def = get_definition())) {
775         fflush(fout);
776         print_datadef(def);
777     }
778
779     er_Proc_CodeGeneration();
780
781     if (extend && tell == ftell(fout)) {
782         (void)unlink(outfilename);
783     }
784     Sflag = 0;
785 }
786
787 static char *
788 uppercase(char *str)
789 {
790     static char max_size[100];
791     char *pnt;
792     int len = (int)strlen(str);
793
794     for (pnt = max_size; len > 0; len--, str++) {
795         *pnt++ = (islower(*str) ? toupper(*str) : *str);
796     }
797     *pnt = '\0';
798     return max_size;
799 }
800
801 /*
802  * Parse command line arguments
803  */
804 static int
805 parseargs(int argc, char *argv[], struct commandline *cmd)
806 {
807     int i;
808     int j;
809     char c;
810     char flag[(1 << (8 * sizeof(char)))];
811     int nflags;
812
813     cmdname = argv[0];
814     cmd->infile = cmd->outfile = NULL;
815     if (argc < 2) {
816         return (0);
817     }
818     memset(flag, 0, sizeof(flag));
819     cmd->outfile = NULL;
820     for (i = 1; i < argc; i++) {
821         if (argv[i][0] != '-') {
822             if (cmd->infile) {
823                 return (0);
824             }
825             cmd->infile = argv[i];
826         } else {
827             for (j = 1; argv[i][j] != 0; j++) {
828                 c = argv[i][j];
829                 switch (c) {
830                 case 'A':
831                 case 'c':
832                 case 'h':
833                 case 'l':
834                 case 'm':
835                 case 'C':
836                 case 'S':
837                 case 'b':
838                 case 'r':
839                 case 'R':
840                 case 'k':
841                 case 'p':
842                 case 'd':
843                 case 'u':
844                 case 'x':
845                 case 'y':
846                 case 'z':
847                     if (flag[(int)c]) {
848                         return (0);
849                     }
850                     flag[(int)c] = 1;
851                     break;
852                 case 'o':
853                 case 's':
854                     if (argv[i][j - 1] != '-' || argv[i][j + 1] != 0) {
855                         return (0);
856                     }
857                     flag[(int)c] = 1;
858                     if (++i == argc) {
859                         return (0);
860                     }
861                     if (c == 's') {
862                         if (!streq(argv[i], "udp") && !streq(argv[i], "tcp")) {
863                             return (0);
864                         }
865                     } else if (c == 'o') {
866                         if (cmd->outfile) {
867                             return (0);
868                         }
869                         cmd->outfile = argv[i];
870                     }
871                     goto nextarg;
872                 case 'P':
873                     if (argv[i][j - 1] != '-')
874                         return (0);
875                     prefix = &argv[i][j + 1];
876                     goto nextarg;
877                 case 'I':
878                     if (nincludes >= MAXCPPARGS) {
879                         f_print(stderr, "Too many -I arguments\n");
880                         return (0);
881                     }
882                     if (argv[i][j - 1] != '-')
883                         return (0);
884                     IncludeDir[nincludes++] = &argv[i][j - 1];
885                     goto nextarg;
886                 default:
887                     return (0);
888                 }
889             }
890           nextarg:
891             ;
892         }
893     }
894     cmd->ansic_flag = ansic_flag = flag['A'];
895     cmd->brief_flag = brief_flag = flag['b'];
896     cmd->cflag = cflag = flag['c'];
897     cmd->hflag = hflag = flag['h'];
898     cmd->sflag = flag['s'];
899     cmd->lflag = flag['l'];
900     cmd->mflag = flag['m'];
901     cmd->xflag = xflag = flag['x'];
902     cmd->yflag = yflag = flag['y'];
903     cmd->Cflag = Cflag = flag['C'];
904     cmd->Sflag = Sflag = flag['S'];
905     cmd->rflag = flag['r'];
906     cmd->uflag = uflag = flag['u'];
907     cmd->kflag = kflag = flag['k'];
908     cmd->pflag = flag['p'];
909     cmd->dflag = debug = flag['d'];
910     zflag = flag['z'];
911     if (cmd->pflag)
912         combinepackages = 1;
913     nflags =
914         cmd->cflag + cmd->hflag + cmd->sflag + cmd->lflag + cmd->mflag +
915         cmd->Cflag + cmd->Sflag + cmd->rflag;
916     if (nflags == 0) {
917         if (cmd->outfile != NULL || cmd->infile == NULL) {
918             return (0);
919         }
920     } else if (nflags > 1) {
921         return (0);
922     }
923     return (1);
924 }