1 %{ /* BLURB gpl
2 
3                            Coda File System
4                               Release 5
5 
6           Copyright (c) 1987-1999 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 "rp2.h"
44 
45 extern int yydebug;
46 extern int HeaderOnlyFlag;
47 
48 extern char *copy();
49 extern RPC2_TYPE *rpc2_enum_type(), *rpc2_struct_type();
50 extern ENTRY *make_entry(), *find();
51 extern ENUM *make_enum();
52 extern VAR *make_var();
53 extern PROC *make_proc(), *check_proc();
54 extern void enter();
55 extern char *concat();
56 extern struct subsystem subsystem;
57 extern void no_storage(char *);
58 extern void spit_define(char *, char *);
59 extern void insert(PROC *proc);
60 
61 /* Structure for handling IDENTIFIER lists */
62 
63 #define MAX_IDS	100
64 
65 struct {
66     char	*ids[MAX_IDS];
67     int		counter;
68 } id_list;
69 
make_id_array()70 static char **make_id_array()
71 {
72     register char **array;
73     register int i;
74 
75     array = (char **) calloc(id_list.counter+1, sizeof(char *));
76     if (array == NIL) no_storage("make_id_array");
77     array[id_list.counter] = NIL;
78     for (i=0, id_list.counter--; id_list.counter>=0; i++, id_list.counter--)
79 	array[i] = id_list.ids[id_list.counter];
80     return array;
81 }
82 
83 #define MAX_ENUMS	100
84 
85 struct {
86     ENUM	*enums[MAX_ENUMS];
87     int		counter;
88 } enum_list;
89 
make_enum_array()90 static ENUM **make_enum_array()
91 {
92     register ENUM **array;
93     register int i;
94 
95     array = (ENUM **) calloc(enum_list.counter+1, sizeof(ENUM *));
96     if (array == NIL) no_storage("make_enum_array");
97     array[enum_list.counter] = NIL;
98     for (i=0, enum_list.counter--; enum_list.counter>=0; i++, enum_list.counter--)
99 	array[i] = enum_list.enums[enum_list.counter];
100     return array;
101 }
102 
103 #define MAX_FORMALS	100
104 
105 struct {
106     VAR		*formals[MAX_FORMALS];
107     int		counter;
108 } formal_list;
109 
make_formal_array()110 static VAR **make_formal_array()
111 {
112     register VAR **array;
113     register int i;
114 
115     array = (VAR **) calloc(formal_list.counter+1, sizeof(VAR *));
116     if (array == NIL) no_storage("make_formal_array");
117     array[formal_list.counter] = NIL;
118     for (i=0, formal_list.counter--; formal_list.counter>=0; i++, formal_list.counter--)
119 	array[i] = formal_list.formals[formal_list.counter];
120     return array;
121 }
122 
123 #define MAX_VARS	100
124 
125 struct {
126     VAR		**vars[MAX_VARS];
127     int		counter;
128 } var_list;
129 
length(p)130 static int length(p)
131     char **p;
132 {
133     register int len;
134 
135     for (len=0; *p!=NIL; p++) len++;
136     return len;
137 }
138 
make_var_array()139 static VAR **make_var_array()
140 {
141     register int count, i;
142     register VAR **array;
143 
144     for (i=0, count=0; i<var_list.counter; i++) count += length((char **)var_list.vars[i]);
145     array = (VAR **) calloc(count+1, sizeof(VAR *));
146     if (array == NIL) no_storage("make_var_array");
147     array[count] = NIL;
148 
149     /* Transfer to array */
150     for (i=0, var_list.counter--; var_list.counter>=0; var_list.counter--) {
151 	register VAR **v;
152 	for (v = var_list.vars[var_list.counter]; *v != NIL; v++)
153 	    array[i++] = *v;
154     }
155     return array;
156 }
157 
createsize(name)158 static char *createsize(name)
159     char *name;
160 {
161     return concat(name, "_size_");
162 }
163 
createmaxsize(name)164 static char *createmaxsize(name)
165     char *name;
166 {
167     return concat(name, "_size_max_");
168 }
169 
170 int next_opnum = 1;
171 
172 %}
173 	    /* YACC Declarations Section */
174 %start file
175 
176 %token IDENTIFIER	/* Letter followed by sequence of letters and digits  */
177 %token NUMBER 		/* arb sequence of digits*/
178 %token STRING		/* quoted string */
179 %token SUBSYSTEM
180 %token TIMEOUT DEFINE NEW_CONNECTION
181 %token TYPEDEF RPC2_STRUCT RPC2_ENUM
182 %token CLIENT SERVER PREFIX
183 
184 %token IN
185 %token OUT
186 
187 %union {
188     rp2_bool	u_bool;
189     MODE	u_mode;
190     char	*u_string;
191     char	**u_string_array;
192     RPC2_TYPE	*u_rpc2_type;
193     ENTRY	*u_entry;
194     ENUM	*u_enum;
195     VAR		*u_var;
196     VAR		**u_var_array;
197     VAR		***u_var_array_array;
198     int         u_int;
199 }
200 
201 %type <u_bool> new_connection
202 %type <u_bool> DEFINE TYPEDEF procedure_description
203 
204 %type <u_mode> usage
205 
206 %type <u_string> DefinedNumber String id_number protocol_version
207 %type <u_string> subsystem_name IDENTIFIER NUMBER STRING array_spec
208 %type <u_string> timeout_override
209 %type <u_int>    opcode_number
210 
211 %type <u_string_array> identifier_list
212 
213 %type <u_rpc2_type> rpc2_struct rpc2_enum
214 
215 %type <u_entry> rpc2_type type_name
216 
217 %type <u_enum> enum_val
218 
219 %type <u_var> formal array_spec_var
220 
221 %type <u_var_array> field
222 
223 %type <u_var_array_array> field_list
224 
225 %%
226 	    /* YACC rules section */
227 file			: prefixes header_line default_timeout decl_or_proc_list
228 			;
229 
230 prefixes		: empty
231 			| prefix
232 			| prefix prefix
233 			;
234 
235 prefix			: SERVER PREFIX String ';'
236 					{
237 					    extern char *server_prefix;
238 					    server_prefix = copy($3+1);
239 					    server_prefix[strlen(server_prefix)-1] = '\0';
240 					}
241 			| CLIENT PREFIX String ';'
242 					{
243 					    extern char *client_prefix;
244 					    client_prefix = copy($3+1);
245 					    client_prefix[strlen(client_prefix)-1] = '\0';
246 					}
247 			;
248 
249 header_line		: SUBSYSTEM subsystem_name compatability_stuff ';'
250 					{
251 					    subsystem.subsystem_name = copy($2+1);
252 					    subsystem.subsystem_name[strlen(subsystem.subsystem_name)-1] = '\0';
253 					}
254 			| empty
255 			    {
256 			    printf("NO SUBSYSTEM SPECIFIED: only generating header file\n");
257 			    HeaderOnlyFlag = 1;
258 			    }
259 			;
260 
261 compatability_stuff	: id_number protocol_version
262 					{}
263 			| empty
264 			;
265 
266 subsystem_name		: String
267 					{ $$ = $1; }
268 			;
269 
270 id_number		: DefinedNumber
271 					{ $$ = $1; }
272 			;
273 
274 protocol_version	: DefinedNumber
275 					{ $$ = $1; }
276 			;
277 
278 default_timeout		: TIMEOUT '(' DefinedNumber ')' ';'
279 					{ subsystem.timeout = $3; }
280 			| empty
281 					{ subsystem.timeout = NIL; }
282 			;
283 
284 decl_or_proc_list	: decl_or_proc_list decl_or_proc
285 			| empty
286 			;
287 
288 decl_or_proc		: typedef
289 			| define
290 			| procedure_description
291 					{}
292 			;
293 
294 define			: DEFINE IDENTIFIER NUMBER
295 					{ if ($1) spit_define($2, $3); }
296 			| DEFINE IDENTIFIER String
297 					{ if ($1) spit_define($2, $3); }
298 			;
299 
300 typedef			: TYPEDEF rpc2_type IDENTIFIER array_spec ';'
301 					{
302 					    extern void spit_type();
303 					    $2 -> name = $3;
304 					    $2 -> bound = $4;
305 					    if ($2->bound != NIL && $2->type->tag != RPC2_BYTE_TAG) {
306 						printf("RP2GEN: array type unimplemented: %s\n",
307 						       $3);
308 						exit(1);
309 					    }
310 					    enter($2);
311 					    if ($1) spit_type($2);
312 					}
313 			;
314 
315 rpc2_type		: type_name
316 					{ $$ = make_entry($1->type, $1); }
317 			| rpc2_struct
318 					{ $$ = make_entry($1, NIL); }
319 			| rpc2_enum
320 					{ $$ = make_entry($1, NIL); }
321 			;
322 
323 type_name		: IDENTIFIER
324 					{
325 					    $$ = find($1);
326 					    if ($$ == NIL) {
327 						printf("RP2GEN: can't find type: %s\n", $1);
328 						exit(1);
329 					    }
330 					}
331 			;
332 
333 rpc2_struct		: RPC2_STRUCT '{' field_list '}'
334 					{ $$ = rpc2_struct_type(make_var_array()); }
335 			;
336 
337 field_list		: field field_list
338 					{
339 					    if (var_list.counter >= MAX_VARS) {
340 						printf("RP2GEN: too many fields: %d\n", MAX_VARS);
341 						exit(1);
342 					    }
343 					    var_list.vars[var_list.counter++] = $1;
344 					}
345 			| field
346 					{
347 					    var_list.vars[0] = $1;
348 					    var_list.counter = 1;
349 					}
350 			;
351 
352 field			: type_name identifier_list ';'
353 					{
354 					    register char **id;
355 					    register VAR **p;
356 					    $$ = (VAR **) calloc(length($2)+1, sizeof(VAR *));
357 					    if ($$ == NIL) no_storage("field");
358 					    for (id=$2, p=$$; *id!=NIL; id++, p++)
359 						*p = make_var(*id, NO_MODE, $1);
360 					    *p = NIL;
361 					    free($2);
362 					}
363 			;
364 
365 identifier_list		: identifier_list2
366 					{ $$ = make_id_array(); }
367 			;
368 
369 identifier_list2	: IDENTIFIER ',' identifier_list2
370 					{
371 					    if (id_list.counter >= MAX_IDS) {
372 						printf("RP2GEN: too many identifiers in list: %d\n", MAX_IDS);
373 						exit(1);
374 					    }
375 					    id_list.ids[id_list.counter++] = $1;
376 					}
377 			| IDENTIFIER
378 					{
379 					    id_list.ids[0] = $1;
380 					    id_list.counter = 1;
381 					}
382 			;
383 
384 rpc2_enum		: RPC2_ENUM '{' enum_val_list '}'
385 					{ $$ = rpc2_enum_type(make_enum_array()); }
386 			;
387 
388 enum_val_list		: enum_val ',' enum_val_list
389 					{
390 					    if (enum_list.counter >= MAX_ENUMS) {
391 						printf("RP2GEN: too many enum values: %d\n", MAX_ENUMS);
392 						exit(1);
393 					    }
394 					    enum_list.enums[enum_list.counter++] = $1;
395 					}
396 			| enum_val
397 					{
398 					    enum_list.enums[0] = $1;
399 					    enum_list.counter = 1;
400 					}
401 			;
402 
403 enum_val		: IDENTIFIER '=' NUMBER
404 					{ $$ = make_enum($1, $3); }
405 			;
406 
407 array_spec		: '[' DefinedNumber ']'
408 					{ $$ = $2; }
409 			| empty
410 					{ $$ = NIL; }
411 			;
412 
413 array_spec_var		: '[' ']'
414 					{
415 					    $$ = make_var(NIL, NO_MODE, find("RPC2_Unsigned"));
416 					}
417 			| empty
418 					{ $$ = NIL; }
419 			;
420 
421 procedure_description	: opcode_number IDENTIFIER '(' formal_list ')' timeout_override new_connection ';'
422                                         { if ($7 == RP2_FALSE) {
423                                             if ($1 == -1)
424                                                 $1 = next_opnum;
425                                             if ($1 < next_opnum) {
426                                               printf("RP2GEN: Opcode numbers must be always increasing\n");
427                                               exit(1);
428                                             }
429                                             next_opnum = $1 + 1;
430                                           }
431 					  insert(check_proc(make_proc($1, $2, make_formal_array(), $6, $7))); }
432 			;
433 
434 opcode_number		: NUMBER ':'
435 					{ $$ = atoi($1); }
436 
437 			| empty
438 					{ $$ = -1; }
439 
440 			;
441 
442 formal_list		: formal array_spec_var ',' formal_list
443 					{
444 					    VAR *maxvarp;
445 					    if (formal_list.counter >= MAX_FORMALS) {
446 						printf("RP2GEN: too many formals: %d\n", MAX_FORMALS);
447 						exit(1);
448 					    }
449 					    formal_list.formals[formal_list.counter++] = $1;
450 					    if ($2 != NIL) {
451 						if (formal_list.counter >= MAX_FORMALS) {
452 						    printf("RP2GEN: too many formals: %d\n", MAX_FORMALS);
453 						    exit(1);
454 						}
455 					        if ($1->type->type->tag != RPC2_STRUCT_TAG) {
456 						    printf("RP2GEN: array type unimplemented: %s\n", $1->name);
457 						    exit(1);
458 					        }
459 					        formal_list.formals[formal_list.counter++] = $2;
460 						$1->array = $2->name = createsize($1->name);
461 						$2->mode = $1->mode;
462 						if ($1->mode != IN_MODE) {
463 						    maxvarp = make_var(NIL, NO_MODE, find("RPC2_Unsigned"));
464 						    $1->arraymax = maxvarp->name = createmaxsize($1->name);
465 						    maxvarp->mode = MAX_BOUND;
466 						    formal_list.formals[formal_list.counter++] = maxvarp;
467 						}
468 					    }
469 					}
470 			| formal array_spec_var
471 					{
472 					    VAR *maxvarp;
473 					    formal_list.formals[0] = $1;
474 					    formal_list.counter = 1;
475 					    if ($2 != NIL) {
476 					        if ($1->type->type->tag != RPC2_STRUCT_TAG) {
477 						    printf("RP2GEN: array type unimplemented: %s\n",
478 						           $1->name);
479 						    exit(1);
480 					        }
481 					        formal_list.formals[formal_list.counter++] = $2;
482 						$1->array = $2->name = createsize($1->name);
483 						$2->mode = $1->mode;
484 						if ($1->mode != IN_MODE) {
485 						    maxvarp = make_var(NIL, NO_MODE, find("RPC2_Unsigned"));
486 						    $1->arraymax = maxvarp->name = createmaxsize($1->name);
487 						    maxvarp->mode = IN_MODE;
488 						    formal_list.formals[formal_list.counter++] = maxvarp;
489 						}
490 					    }
491 
492 					}
493 			| empty
494 					{ formal_list.counter = 0; }
495 			;
496 
497 formal			: usage type_name IDENTIFIER
498 					{
499 					  $$ = make_var($3, $1, $2);
500 					}
501 			;
502 
503 usage			: IN
504 					{ $$ = IN_MODE; }
505 			| OUT
506 					{ $$ = OUT_MODE; }
507 			| IN OUT
508 					{ $$ = IN_OUT_MODE; }
509 			;
510 
511 timeout_override	: TIMEOUT '(' DefinedNumber ')'
512 					{ $$ = $3; }
513 			| empty
514 					{ $$ = NIL; }
515 			;
516 
517 new_connection		: NEW_CONNECTION
518 					{ $$ = RP2_TRUE; }
519 			| empty
520 					{ $$ = RP2_FALSE; }
521 			;
522 
523 DefinedNumber		: NUMBER
524 					{ $$ = $1; }
525 			| IDENTIFIER
526 					{ $$ = $1; }
527 			;
528 
529 String			: STRING
530 					{ $$ = $1; }
531 /*
532 			| IDENTIFIER
533 					{ $$ = $1; }
534 */
535 			;
536 
537 empty			:
538 			;
539 %%
540