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