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