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