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