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