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