1 /* BLURB gpl
2 
3                            Coda File System
4                               Release 5
5 
6           Copyright (c) 1987-2016 Carnegie Mellon University
7                   Additional copyrights listed below
8 
9 This  code  is  distributed "AS IS" without warranty of any kind under
10 the terms of the GNU General Public Licence Version 2, as shown in the
11 file  LICENSE.  The  technical and financial  contributors to Coda are
12 listed in the file CREDITS.
13 
14                         Additional copyrights
15 
16 #*/
17 
18 /*
19                          IBM COPYRIGHT NOTICE
20 
21                           Copyright (C) 1986
22              International Business Machines Corporation
23                          All Rights Reserved
24 
25 This  file  contains  some  code identical to or derived from the 1986
26 version of the Andrew File System ("AFS"), which is owned by  the  IBM
27 Corporation.   This  code is provided "AS IS" and IBM does not warrant
28 that it is free of infringement of  any  intellectual  rights  of  any
29 third  party.    IBM  disclaims  liability of any kind for any damages
30 whatsoever resulting directly or indirectly from use of this  software
31 or  of  any  derivative work.  Carnegie Mellon University has obtained
32 permission to  modify,  distribute and sublicense this code,  which is
33 based on Version 2  of  AFS  and  does  not  contain  the features and
34 enhancements that are part of  Version 3 of  AFS.  Version 3 of AFS is
35 commercially   available   and  supported  by   Transarc  Corporation,
36 Pittsburgh, PA.
37 
38 */
39 
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <sys/param.h>
44 #include <time.h>
45 #include <unistd.h>
46 #include "rp2.h"
47 
48 int32_t yydebug;
49 
50 static int32_t SetupFiles();
51 static void badargs(void);
52 
53 extern void print_struct_func(RPC2_TYPE *t, FILE *where, FILE *hfile, char *name);
54 extern char *coda_rp2_basename(char * name);
55 extern rp2_bool include2(char *name, char *proc);
56 
57 extern void no_storage();
58 extern void init_lex(), init_table(), yyparse();
59 
60 struct subsystem subsystem;	/* Holds global subsystem information */
61 char *server_prefix, *client_prefix;
62 
63 FILE *file;
64 FILE *cfile = NULL, *sfile = NULL, *hfile = NULL, *mfile = NULL, *pfile = NULL, *libfile = NULL;
65 char *cfile_name, *sfile_name, *hfile_name, *mfile_name, *pfile_name, *libfile_name;;
66 char *file_name;
67 char define_name[MAXPATHLEN]; /* value of __XXX__ */
68 
69 int32_t HeaderOnlyFlag;  /* set to one if only .h file is to be produced */
70 
71 static LANGUAGE clanguage, slanguage, mlanguage;
72 
73 
74 static char *client_includes[] = {
75 	/* NONE */	"Can't happen",
76 	/* C */		"",
77 	/* PASCAL */	"Can't happen",
78 	/* F77 */	"Can't happen"
79 };
80 
81 static char *server_includes[] = {
82 	/* NONE */	"Can't happen",
83 	/* C */		"",
84 	/* PASCAL */	"Can't happen",
85 	/* F77 */	"Can't happen"
86 };
87 
88 static char *h_includes[] = {
89 	/* NONE */	"Can't happen",
90 	/* C */		"#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <rpc2/rpc2.h>\n#include <rpc2/se.h>\n#include <rpc2/errors.h>\n#include <rpc2/pack_helper.h>\n\n#ifdef __cplusplus\n}\n#endif\n",
91 	/* PASCAL */	"Can't happen",
92 	/* F77 */	"Can't happen"
93 };
94 
95 static char *helper_includes[] = {
96 	/* NONE */	"Can't happen",
97 	/* C */		"#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <stdlib.h>\n\n#include <rpc2/pack_helper.h>\n\n#ifdef __cplusplus\n}\n#endif\n",
98 	/* PASCAL */	"Can't happen",
99 	/* F77 */	"Can't happen"
100 };
101 
102 static char *multi_includes[] = {
103 	/* NONE */	"Can't happen",
104 	/* C */		"",
105 	/* PASCAL */	"Can't happen",
106 	/* F77 */	"Can't happen"
107 };
108 
109 rp2_bool testing;
110 rp2_bool strictproto = 1;
111 rp2_bool cplusplus = 0;
112 rp2_bool tcpdump = 0;
113 rp2_bool ansi;
114 rp2_bool neterrors;
115 
116 char **cpatharray;  /* array of strings indicating search paths for
117                   included files (defined by -I flag) */
118 int32_t  cpathcnt; /* no of elements in cpath, initially 0 */
119 
120 time_t versionnumber;	/* used to check version */
121 
122 /* forward decls */
123 static int32_t GetArgs();
124 static int32_t h_hack_begin();
125 static int32_t h_hack_end();
126 static int32_t header();
127 static int32_t do_procs();
128 static int32_t SetupFiles();
129 
130 
main(int argc,char * argv[])131 int main(int argc, char *argv[])
132 {
133     init_lex();
134     init_table();
135     GetArgs(argc, argv);
136     SetupFiles();
137 
138     yyparse();
139     do_procs();
140 
141     if(cfile) {
142       fclose(cfile);
143       cfile = NULL;
144     }
145     if(sfile) {
146       fclose(sfile);
147       sfile = NULL;
148     }
149     if(hfile) {
150       h_hack_end(hfile);
151       fclose(hfile);
152       hfile = NULL;
153     }
154     if(mfile) {
155       fclose(mfile);
156       mfile = NULL;
157     }
158 
159     if (libfile) {
160         fclose(libfile);
161         libfile = NULL;
162     }
163 
164     exit(0);
165 }
166 
GetArgs(argc,argv)167 static int32_t GetArgs(argc, argv)
168     int32_t argc;
169     char *argv[];
170     {
171     register int32_t i;
172 
173     testing = RP2_FALSE;
174     strictproto = RP2_TRUE;   /* generate strict prototypes */
175     cplusplus = RP2_FALSE; /* by default generate .c not .cc files */
176     ansi = RP2_FALSE;     /* generate ## paste tokens rather than double-comment */
177     neterrors = RP2_FALSE; /* exchange errors in OS independent fashion */
178     /* Wire-in client, server and multi languages to be C.
179        Should be settable on command line when other languages are
180        supported */
181     clanguage = C;
182     slanguage = C;
183     mlanguage = C;
184     pfile_name = NULL;
185 
186     if (argc < 2) badargs();
187     for (i = 1; i < argc - 1; i++)
188 	{
189 	if (strcmp(argv[i], "-s") == 0)
190 	    {
191 	    if (++i >= argc) badargs();
192 	    sfile_name = argv[i];
193 	    continue;
194 	    }
195 	if (strcmp(argv[i], "-c") == 0)
196 	    {
197 	    if (++i >= argc) badargs();
198 	    cfile_name = argv[i];
199 	    continue;
200 	    }
201 	if (strcmp(argv[i], "-h") == 0)
202 	    {
203 	    if (++i >= argc) badargs();
204 	    hfile_name = argv[i];
205 	    continue;
206 	    }
207 	if (strcmp(argv[i], "-m") == 0)
208 	    {
209 	    if (++i >= argc) badargs();
210 	    mfile_name = argv[i];
211 	    continue;
212 	    }
213 	if (strcmp(argv[i], "-p") == 0)
214 	    {
215 	    if (++i >= argc) badargs();
216 	    pfile_name = argv[i];
217 	    continue;
218 	    }
219 	if ((strcmp(argv[i], "-t") == 0) || (strcmp(argv[i],"-tcpdump")==0))
220 		{tcpdump = RP2_TRUE; continue;}
221 	if ((strcmp(argv[i], "-e") == 0) || (strcmp(argv[i],"-neterrors")==0))
222 	    {neterrors = RP2_TRUE; continue;}
223 	if (strcmp(argv[i], "-cplusplus") == 0)
224 	    {cplusplus = RP2_TRUE; continue;}
225 	if (strcmp(argv[i], "-I") == 0)
226 	    {
227 	    if (++i >= argc) badargs();
228 	    if (cpathcnt == 0) cpatharray = (char **)malloc(sizeof(char *));
229 	    else cpatharray = (char **)realloc(cpatharray, (cpathcnt+1)*sizeof(char *));
230 	    cpatharray[cpathcnt] = argv[i];
231 	    cpathcnt++;
232 	    continue;
233 	    }
234 	badargs();
235 	}
236     file_name = argv[argc - 1];
237     return(0);
238     }
239 
240 extern char *coda_rp2_basename(), *concat();
241 
SetupFiles()242 static int32_t SetupFiles()
243     {
244     char *base;
245 
246     /* Set up files */
247     if (file_name == NIL) badargs();
248     if (!include2(file_name, "INPUT")) exit(1);
249 
250     /* Get base name of input file */
251     base = coda_rp2_basename(file_name);
252 
253 
254     if (hfile_name == NIL) hfile_name = concat(base, ".h");
255     hfile = fopen(hfile_name, "w");
256     if (hfile == NIL) {perror(hfile_name); exit(-1);}
257     /* Special include hack for .h file */
258     h_hack_begin(hfile, hfile_name);
259     header(hfile, h_includes[(int32_t) clanguage]);
260 
261     if ( cplusplus ) {
262             if (cfile_name == NIL) cfile_name = concat(base, ".client.cc");
263     } else {
264             if (cfile_name == NIL) cfile_name = concat(base, ".client.c");
265     }
266     cfile = fopen(cfile_name, "w");
267     if (cfile == NIL) {perror(cfile_name); exit(-1);}
268     header(cfile, client_includes[(int32_t) clanguage]);
269     fprintf(cfile, "#include \"%s\"\n\n", hfile_name);
270 
271     if ( cplusplus ) {
272             if (sfile_name == NIL) sfile_name = concat(base, ".server.cc");
273     } else {
274             if (sfile_name == NIL) sfile_name = concat(base, ".server.c");
275     }
276     sfile = fopen(sfile_name, "w");
277     if (sfile == NIL) {perror(sfile_name); exit(-1);}
278     header(sfile, server_includes[(int32_t) slanguage]);
279     fprintf(sfile, "#include \"%s\"\n\n", hfile_name);
280 
281     if ( cplusplus ) {
282             if (mfile_name == NIL) mfile_name = concat(base, ".multi.cc");
283     } else {
284             if (mfile_name == NIL) mfile_name = concat(base, ".multi.c");
285     }
286     mfile = fopen(mfile_name, "w");
287     if (mfile == NIL) {perror(mfile_name); exit(-1);}
288     header(mfile, multi_includes[(int32_t) mlanguage]);
289     fprintf(mfile, "#include \"%s\"\n\n", hfile_name);
290 
291     if ( cplusplus ) {
292             if (pfile_name == NIL) pfile_name = concat(base, ".print.cc");
293     } else {
294             if (pfile_name == NIL) pfile_name = concat(base, ".print.c");
295     }
296     pfile = fopen(pfile_name, "w");
297     if (pfile == NIL) {perror(pfile_name); exit(-1);}
298 
299     libfile_name = concat(base, ".helper.c");
300     libfile = fopen(libfile_name, "w");
301     if (libfile == NIL) {perror(libfile_name); exit(-1);}
302     header(libfile, helper_includes[(int32_t) clanguage]);
303     fprintf(libfile, "#include \"%s\"\n\n", hfile_name);
304 
305     free(base);
306 
307     return -1;
308     }
309 
badargs(void)310 static void badargs(void)
311 {
312     printf("Usage: rp2gen [-neterrors,-n] [-I incldir] [-s srvstub] [-c clntstub]\n");
313     printf("              [-h header] [-m multistub] [-p printstub] \n");
314     printf("              [-t tcpdump prettyprint]   file\n");
315     exit(-1);
316 }
317 
uc(char c)318 static char uc(char c)
319 {
320     return (c >= 'a' && c <= 'z') ? c - ('a'-'A') : c;
321 }
322 
h_hack_begin(FILE * where,char * name)323 static int32_t h_hack_begin(FILE *where, char *name)
324 {
325     char *c;
326 
327     c = coda_rp2_basename(name);
328     strcpy(define_name, c);
329     free(c);
330     for (c=define_name; *c!='\0'; c++)
331 	if (*c == '.' || *c == '-')
332 	    *c = '_';
333 	else
334 	    *c = uc(*c);
335     fprintf(where, "#ifndef _%s_\n", define_name);
336     fprintf(where, "#define _%s_\n\n", define_name);
337     return -1;
338 }
339 
h_hack_end(where)340 static int32_t h_hack_end(where)
341     FILE *where;
342     {
343     fprintf(where, "\n#endif /* _%s_ */\n", define_name);
344     return -1;
345     }
346 
header(FILE * f,char * prefix)347 static int32_t header(FILE *f, char *prefix)
348 {
349     fprintf(f, "/* DO NOT EDIT: generated by rp2gen from %s */\n", file_name);
350     fputs(prefix, f);
351     fputc('\n', f);
352     return -1;
353 }
354 
355 /****************************\
356 * 			     *
357 *  Language specific stuff   *
358 * 			     *
359 \****************************/
360 
cant_happen(type,who,where)361 static void cant_happen(type, who, where)
362     ENTRY *type;
363     WHO who;
364     FILE *where;
365 {
366     puts("RP2GEN [can't happen]: no specified language");
367     abort();
368     return;
369 }
370 
371 extern void cinclude(), cdefine(), ctype(), cproc(), copcodes();
372 
373 static void no_support();
374 
375 static struct {
376     char	*name;		/* Name for printing */
377     void	(*include)();	/* Routine for outputting include to file */
378     void	(*define)();	/* Routine for outputting define to file */
379     void	(*type)();	/* Routine for outputting type to file */
380     void	(*proc)();	/* Routine for outputting procedure to file */
381     void	(*op_codes)();	/* Routine for generating op codes in .h file */
382 } lang_struct[] = {
383 
384 	/* NONE */	{ "N/A",	cant_happen,	cant_happen,	cant_happen,	cant_happen,	cant_happen	},
385 	/* C */		{ "C",		cinclude,	cdefine,	ctype,	cproc,		copcodes	},
386 	/* PASCAL */	{ "PASCAL",	no_support,	no_support,	no_support,	no_support,	no_support	},
387 	/* F77 */	{ "FORTRAN 77",	no_support,	no_support,	no_support,	no_support,	no_support	}
388 
389 };
390 
no_support(type,who,where)391 static void no_support(type, who, where)
392     ENTRY *type;
393     WHO who;
394     FILE *where;
395 {
396     printf("RP2GEN: no language support for %s\n",
397 	   lang_struct[(int32_t) clanguage].name);
398     exit(1);
399 }
400 
spit_type(type)401 void spit_type(type)
402     ENTRY *type;
403 {
404     if (clanguage != slanguage || clanguage != mlanguage) {
405 	puts("RP2GEN: warning, SPIT_TYPE does not support multiple languages");
406 	exit(1);
407     }
408     (*lang_struct[(int32_t) clanguage].type)(type, RP2_CLIENT, hfile);		/* Types always go to .h file */
409 
410     print_struct_func(type->type, libfile, hfile, type->name);
411 }
412 
spit_include(filename)413 void spit_include(filename)
414     char *filename;
415 {
416     if (clanguage != slanguage || clanguage != mlanguage) {
417 	puts("RP2GEN: warning, SPIT_INCLUDE does not support multiple languages");
418 	exit(1);
419     }
420     (*lang_struct[(int32_t) clanguage].include)(filename, RP2_CLIENT, hfile);
421 }
422 
spit_define(id,value)423 void spit_define(id, value)
424     char *id, *value;
425 {
426     if (clanguage != slanguage || clanguage != mlanguage) {
427 	puts("RP2GEN: warning, SPIT_DEFINE does not support multiple languages");
428 	exit(1);
429     }
430     (*lang_struct[(int32_t) clanguage].define)(id, value, RP2_CLIENT, hfile);
431 }
432 
do_procs()433 static int32_t do_procs()
434 {
435     extern PROC *get_head();
436     register PROC *head, *proc;
437     register rp2_bool seen_new_connection;
438 
439     versionnumber = time(0);
440 
441     head = get_head();
442 
443     /* Do language-independent checks */
444     seen_new_connection = RP2_FALSE;
445     for (proc=head; proc!=NIL; proc=proc->thread) {
446 	if (proc->new_connection) {
447 	    if (seen_new_connection) {
448 		puts("RP2GEN: too many NEW_CONNECTION procedures specified");
449 		exit(1);
450 	    } else
451 		seen_new_connection = RP2_TRUE;
452 	}
453     }
454 
455     /* Generate op codes in .h file */
456     (*lang_struct[(int32_t) clanguage].op_codes)(head, RP2_CLIENT, hfile);
457     (*lang_struct[(int32_t) clanguage].proc)(head, RP2_HELPER, libfile);
458 
459     /* Generate client file */
460     if (HeaderOnlyFlag)
461 	    {if(cfile) { fclose(cfile); cfile = NULL; } unlink(cfile_name);}
462     else (*lang_struct[(int32_t) clanguage].proc)(head, RP2_CLIENT, cfile);
463 
464     /* Generate server file */
465     if (HeaderOnlyFlag)
466 	    {if(sfile) { fclose(sfile); sfile = NULL; } unlink(sfile_name);}
467     else (*lang_struct[(int32_t) slanguage].proc)(head, RP2_SERVER, sfile);
468 
469     /* Generate multi file */
470     if (HeaderOnlyFlag)
471 	    {if(mfile) { fclose(mfile); mfile = NULL; } unlink(mfile_name);}
472     else (*lang_struct[(int32_t) mlanguage].proc)(head, RP2_MULTI, mfile);
473 
474     if (HeaderOnlyFlag)
475 	    {if(pfile) { fclose(pfile); pfile = NULL; } unlink(pfile_name); }
476     else (*lang_struct[(int32_t) slanguage].proc)(head, RP2_DUMP, pfile);
477 
478     return -1;
479 }
480