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