9008fb58b7c87bae2fcb4845edee4c8548daa833
[openafs.git] / src / rxgen / rpc_parse.c
1 /* @(#)rpc_parse.c      1.1 87/11/04 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_parse.c, Parser for the RPC protocol compiler 
33  * Copyright (C) 1987 Sun Microsystems, Inc.
34  */
35 #include <afsconfig.h>
36 #include <afs/param.h>
37
38 RCSID("$Header$");
39
40 #include <stdlib.h>
41 #include <stdio.h>
42 #include <ctype.h>
43 #ifdef HAVE_STRING_H
44 #include <string.h>
45 #else
46 #ifdef HAVE_STRINGS_H
47 #include <strings.h>
48 #endif
49 #endif
50 #include "rpc_scan.h"
51 #include "rpc_parse.h"
52 #include "rpc_util.h"
53
54 list *proc_defined[MAX_PACKAGES], *special_defined, *typedef_defined, *uniondef_defined;
55 char *SplitStart = NULL;
56 char *SplitEnd = NULL;
57 char *MasterPrefix = NULL;
58 char *ServerPrefix = "";
59 char *PackagePrefix[MAX_PACKAGES];
60 char *PackageStatIndex[MAX_PACKAGES];
61 int no_of_stat_funcs = 0; /*
62                                   * current function number in client interface
63                                   * starts at 0
64                                   */
65 int no_of_stat_funcs_header[MAX_PACKAGES]; /*
66                                          * Total number of functions in client
67                                          * interface
68                                          */
69 int no_of_opcodes[MAX_PACKAGES], master_no_of_opcodes = 0;
70 int lowest_opcode[MAX_PACKAGES], master_lowest_opcode = 99999;
71 int highest_opcode[MAX_PACKAGES], master_highest_opcode = 0;
72 int master_opcodenumber = 99999;
73 int opcodesnotallowed[MAX_PACKAGES];
74 int combinepackages = 0;
75 int PackageIndex = -1;
76 int PerProcCounter = 0;
77 int Multi_Init = 0;
78
79 /*
80  * Character arrays to keep list of function names as we process the file
81  */
82
83 char function_list[MAX_PACKAGES]
84                   [MAX_FUNCTIONS_PER_PACKAGE]
85                   [MAX_FUNCTION_NAME_LEN];
86 int function_list_index;
87
88 /* static prototypes */
89 static void isdefined(definition *defp);
90 static void def_struct(definition *defp);
91 static void def_program(definition *defp);
92 static void def_enum(definition *defp);
93 static void def_const(definition *defp);
94 static void def_union(definition *defp);
95 static void def_typedef(definition *defp);
96 static void get_declaration(declaration *dec, defkind dkind);
97 static void get_type(char **prefixp, char **typep, defkind dkind);
98 static void unsigned_dec(char **typep);
99 static void def_package(definition *defp);
100 static void def_prefix(definition *defp);
101 static void def_statindex(definition *defp);
102 static void def_startingopcode(definition *defp);
103 static void def_split(definition *defp);
104 static void customize_struct(definition *defp);
105 static char *structname(char *name);
106 static void def_special(declaration *dec, definition *defp);
107 static void check_proc(definition *defp, token *tokp, int noname);
108 static int InvalidConstant(char *name);
109 static int opcodenum_is_defined(int opcode_num);
110 static void analyze_ProcParams(definition *defp, token *tokp);
111 static void generate_code(definition *defp, int proc_split_flag, int multi_flag);
112 static void handle_split_proc(definition *defp, int multi_flag);
113 static void do_split(definition *defp, int direction, int *numofparams, defkind param_kind, int restore_flag);
114 static void hdle_param_tok(definition *defp, declaration *dec, token *tokp, defkind par_kind);
115 static void get1_param_type(definition *defp, declaration *dec, char **param_type);
116 static void get_param_type(definition *defp, declaration *dec, char **param_type, char **typename);
117 #ifdef undef
118 static void hndle_param_tail(definition *defp, declaration *dec, token *tokp, char *typename);
119 #endif
120 static void cs_Proc_CodeGeneration(definition *defp, int split_flag, char *procheader);
121 static void cs_ProcName_setup(definition *defp, char *procheader, int split_flag);
122 static void cs_ProcParams_setup(definition *defp, int split_flag);
123 static void cs_ProcMarshallInParams_setup(definition *defp, int split_flag);
124 static void cs_ProcSendPacket_setup(definition *defp, int split_flag);
125 static void cs_ProcUnmarshallOutParams_setup(definition *defp);
126 static void cs_ProcTail_setup(definition *defp, int split_flag);
127 static void ss_Proc_CodeGeneration(definition *defp);
128 static void ss_ProcName_setup(definition *defp);
129 static void ss_ProcParams_setup(definition *defp, int *somefrees);
130 static void ss_ProcSpecial_setup(definition *defp, int *somefrees);
131 static void ss_ProcUnmarshallInParams_setup(definition *defp);
132 static void ss_ProcCallRealProc_setup(definition *defp);
133 static void ss_ProcMarshallOutParams_setup(definition *defp);
134 static void ss_ProcTail_setup(definition *defp, int somefrees);
135 static int opcode_holes_exist(void);
136 static void er_ProcDeclExterns_setup(void);
137 static void er_ProcProcsArray_setup(void);
138 static void er_ProcMainBody_setup(void);
139 static void er_HeadofOldStyleProc_setup(void);
140 static void er_BodyofOldStyleProc_setup(void);
141 static void proc_er_case(definition *defp);
142 static void er_TailofOldStyleProc_setup(void);
143
144
145
146 /*
147  * return the next definition you see
148  */
149 definition *get_definition(void)
150 {
151         definition *defp;
152         token tok;
153
154         defp = ALLOC(definition);
155         memset((char *)defp, 0, sizeof(definition));
156         get_token(&tok);
157         switch (tok.kind) {
158         case TOK_STRUCT:
159                 def_struct(defp);
160                 break;
161         case TOK_UNION:
162                 def_union(defp);
163                 break;
164         case TOK_TYPEDEF:
165                 def_typedef(defp);
166                 break;
167         case TOK_ENUM:
168                 def_enum(defp);
169                 break;
170         case TOK_PROGRAM:
171                 def_program(defp);
172                 break;
173         case TOK_CONST:
174                 def_const(defp);
175                 break;
176         case TOK_EOF:
177                 return (NULL);
178                 break;
179         case TOK_PACKAGE:
180             def_package(defp);
181             break;
182         case TOK_PREFIX:
183             def_prefix(defp);
184             break;          
185         case TOK_STATINDEX:
186             def_statindex(defp);
187             break;
188         case TOK_SPECIAL:
189             {
190             declaration dec;
191             def_special(&dec, defp);
192             break;
193             }                       
194         case TOK_STARTINGOPCODE:
195             def_startingopcode(defp);
196             break;
197         case TOK_CUSTOMIZED:
198             get_token(&tok);
199             def_struct(defp);
200             customize_struct(defp);
201             break;
202         case TOK_SPLITPREFIX:
203             def_split(defp);
204             break;
205         case TOK_PROC:
206             get_token(&tok);
207             if (tok.kind == TOK_LPAREN) {
208                 unget_token(&tok);
209                 check_proc(defp, &tok, 1);
210             }
211             else
212                 check_proc(defp, &tok, 0);
213             break;
214         case TOK_IDENT:
215             check_proc(defp, &tok, 0);
216             break;
217         case TOK_LPAREN:
218             unget_token(&tok);
219             check_proc(defp, &tok, 1);
220             break;
221         default:
222                 error("definition keyword expected");
223         }
224         if (!IsRxgenToken(&tok))
225         {
226             scan(TOK_SEMICOLON,&tok);
227             isdefined(defp);
228         } else pushed = 0;
229         return (defp);
230 }
231
232 static void isdefined(definition *defp)
233 {
234         STOREVAL(&defined, defp);
235 }
236
237
238 static void def_struct(definition *defp)
239 {
240         token tok;
241         declaration dec;
242         decl_list *decls;
243         decl_list **tailp;
244
245         defp->def_kind = DEF_STRUCT;
246
247         scan(TOK_IDENT, &tok);
248         defp->def_name = tok.str;
249         scan(TOK_LBRACE, &tok);
250         tailp = &defp->def.st.decls;
251         do {
252                 get_declaration(&dec, DEF_STRUCT);
253                 decls = ALLOC(decl_list);
254                 decls->decl = dec;
255                 *tailp = decls;
256                 tailp = &decls->next;
257                 scan(TOK_SEMICOLON, &tok);
258                 peek(&tok);
259         } while (tok.kind != TOK_RBRACE);
260         get_token(&tok);
261         *tailp = NULL;
262 }
263
264 static void def_program(definition *defp)
265 {
266         token tok;
267         version_list *vlist;
268         version_list **vtailp;
269         proc_list *plist;
270         proc_list **ptailp;
271
272         defp->def_kind = DEF_PROGRAM;
273         scan(TOK_IDENT, &tok);
274         defp->def_name = tok.str;
275         scan(TOK_LBRACE, &tok);
276         vtailp = &defp->def.pr.versions;
277         scan(TOK_VERSION, &tok);
278         do {
279                 scan(TOK_IDENT, &tok);
280                 vlist = ALLOC(version_list);
281                 vlist->vers_name = tok.str;
282                 scan(TOK_LBRACE, &tok);
283                 ptailp = &vlist->procs;
284                 do {
285                         plist = ALLOC(proc_list);
286                         get_type(&plist->res_prefix, &plist->res_type, DEF_PROGRAM);
287                         if (streq(plist->res_type, "opaque")) {
288                                 error("illegal result type");
289                         }
290                         scan(TOK_IDENT, &tok);
291                         plist->proc_name = tok.str;
292                         scan(TOK_LPAREN, &tok);
293                         get_type(&plist->arg_prefix, &plist->arg_type, DEF_PROGRAM);
294                         if (streq(plist->arg_type, "opaque")) {
295                                 error("illegal argument type");
296                         }
297                         scan(TOK_RPAREN, &tok);
298                         scan(TOK_EQUAL, &tok);
299                         scan_num(&tok);
300                         scan(TOK_SEMICOLON, &tok);
301                         plist->proc_num = tok.str;
302                         *ptailp = plist;
303                         ptailp = &plist->next;
304                         peek(&tok);
305                 } while (tok.kind != TOK_RBRACE);
306                 *vtailp = vlist;
307                 vtailp = &vlist->next;
308                 scan(TOK_RBRACE, &tok);
309                 scan(TOK_EQUAL, &tok);
310                 scan_num(&tok);
311                 vlist->vers_num = tok.str;
312                 scan(TOK_SEMICOLON, &tok);
313                 scan2(TOK_VERSION, TOK_RBRACE, &tok);
314         } while (tok.kind == TOK_VERSION);
315         scan(TOK_EQUAL, &tok);
316         scan_num(&tok);
317         defp->def.pr.prog_num = tok.str;
318         *vtailp = NULL;
319 }
320
321 static void def_enum(definition *defp)
322 {
323         token tok;
324         enumval_list *elist;
325         enumval_list **tailp;
326
327         defp->def_kind = DEF_ENUM;
328         scan(TOK_IDENT, &tok);
329         defp->def_name = tok.str;
330         scan(TOK_LBRACE, &tok);
331         tailp = &defp->def.en.vals;
332         do {
333                 scan(TOK_IDENT, &tok);
334                 elist = ALLOC(enumval_list);
335                 elist->name = tok.str;
336                 elist->assignment = NULL;
337                 scan3(TOK_COMMA, TOK_RBRACE, TOK_EQUAL, &tok);
338                 if (tok.kind == TOK_EQUAL) {
339                         scan_num(&tok);
340                         elist->assignment = tok.str;
341                         scan2(TOK_COMMA, TOK_RBRACE, &tok);
342                 }
343                 *tailp = elist;
344                 tailp = &elist->next;
345         } while (tok.kind != TOK_RBRACE);
346         *tailp = NULL;
347 }
348
349 static void def_const(definition *defp)
350 {
351         token tok;
352
353         defp->def_kind = DEF_CONST;
354         scan(TOK_IDENT, &tok);
355         defp->def_name = tok.str;
356         scan(TOK_EQUAL, &tok);
357         scan2(TOK_IDENT, TOK_STRCONST, &tok);
358         defp->def.co = tok.str;
359 }
360
361 static void def_union(definition *defp)
362 {
363         token tok;
364         declaration dec;
365         case_list *cases;
366         case_list **tailp;
367
368         defp->def_kind = DEF_UNION;
369         scan(TOK_IDENT, &tok);
370         defp->def_name = tok.str;
371         scan(TOK_SWITCH, &tok);
372         scan(TOK_LPAREN, &tok);
373         get_declaration(&dec, DEF_UNION);
374         defp->def.un.enum_decl = dec;
375         tailp = &defp->def.un.cases;
376         scan(TOK_RPAREN, &tok);
377         scan(TOK_LBRACE, &tok);
378         scan(TOK_CASE, &tok);
379         while (tok.kind == TOK_CASE) {
380                 scan(TOK_IDENT, &tok);
381                 cases = ALLOC(case_list);
382                 cases->case_name = tok.str;
383                 scan(TOK_COLON, &tok);
384                 get_declaration(&dec, DEF_UNION);
385                 cases->case_decl = dec;
386                 *tailp = cases;
387                 tailp = &cases->next;
388                 scan(TOK_SEMICOLON, &tok);
389                 scan3(TOK_CASE, TOK_DEFAULT, TOK_RBRACE, &tok);
390         }
391         *tailp = NULL;
392         if (tok.kind == TOK_DEFAULT) {
393                 scan(TOK_COLON, &tok);
394                 get_declaration(&dec, DEF_UNION);
395                 defp->def.un.default_decl = ALLOC(declaration);
396                 *defp->def.un.default_decl = dec;
397                 scan(TOK_SEMICOLON, &tok);
398                 scan(TOK_RBRACE, &tok);
399         } else {
400                 defp->def.un.default_decl = NULL;
401         }
402 }
403
404
405 static void def_typedef(definition *defp)
406 {
407         declaration dec;
408
409         defp->def_kind = DEF_TYPEDEF;
410         get_declaration(&dec, DEF_TYPEDEF);
411         defp->def_name = dec.name;
412         defp->def.ty.old_prefix = dec.prefix;
413         defp->def.ty.old_type = dec.type;
414         defp->def.ty.rel = dec.rel;
415         defp->def.ty.array_max = dec.array_max;
416 }
417
418
419 static void get_declaration(declaration *dec, defkind dkind)
420 {
421         token tok;
422
423         get_type(&dec->prefix, &dec->type, dkind);
424         dec->rel = REL_ALIAS;
425         if (streq(dec->type, "void")) {
426                 return;
427         }
428         scan2(TOK_STAR, TOK_IDENT, &tok);
429         if (tok.kind == TOK_STAR) {
430                 dec->rel = REL_POINTER;
431                 scan(TOK_IDENT, &tok);
432         }
433         dec->name = tok.str;
434         if (peekscan(TOK_LBRACKET, &tok)) {
435                 if (dec->rel == REL_POINTER) {
436                         error("no array-of-pointer declarations -- use typedef");
437                 }
438                 dec->rel = REL_VECTOR;
439                 scan_num(&tok);
440                 dec->array_max = tok.str;
441                 scan(TOK_RBRACKET, &tok);
442         } else if (peekscan(TOK_LANGLE, &tok)) {
443                 if (dec->rel == REL_POINTER) {
444                         error("no array-of-pointer declarations -- use typedef");
445                 }
446                 dec->rel = REL_ARRAY;
447                 if (peekscan(TOK_RANGLE, &tok)) {
448                         dec->array_max = "~0";  /* unspecified size, use max */
449                 } else {
450                         scan_num(&tok);
451                         dec->array_max = tok.str;
452                         scan(TOK_RANGLE, &tok);
453                 }
454         }
455         if (streq(dec->type, "opaque")) {
456                 if (dec->rel != REL_ARRAY && dec->rel != REL_VECTOR) {
457                         error("array declaration expected");
458                 }
459         } else if (streq(dec->type, "string")) {
460                 if (dec->rel != REL_ARRAY) {
461                         error(" variable-length array declaration expected");
462                 }
463         }
464 }
465
466
467 static void get_type(char **prefixp, char **typep, defkind dkind)
468 {
469         token tok;
470
471         *prefixp = NULL;
472         get_token(&tok);
473         switch (tok.kind) {
474         case TOK_IDENT:
475                 *typep = tok.str;
476                 break;
477         case TOK_STRUCT:
478         case TOK_ENUM:
479         case TOK_UNION:
480                 *prefixp = tok.str;
481                 scan(TOK_IDENT, &tok);
482                 *typep = tok.str;
483                 break;
484         case TOK_UNSIGNED:
485                 unsigned_dec(typep);
486                 break;
487         case TOK_SHORT:
488                 *typep = "short";
489                 (void) peekscan(TOK_INT, &tok);
490                 break;
491         case TOK_INT32:
492                 *typep = "afs_int32";
493                 (void) peekscan(TOK_INT, &tok);
494                 break;
495         case TOK_VOID:
496                 if (dkind != DEF_UNION && dkind != DEF_PROGRAM) {
497                         error("voids allowed only inside union and program definitions");
498                 }
499                 *typep = tok.str;
500                 break;
501         case TOK_STRING:
502         case TOK_OPAQUE:
503         case TOK_CHAR:
504         case TOK_INT:
505         case TOK_FLOAT:
506         case TOK_DOUBLE:
507         case TOK_BOOL:
508         case TOK_AFSUUID:
509                 *typep = tok.str;
510                 break;
511         default:
512                 error("expected type specifier");
513         }
514 }
515
516
517 static void unsigned_dec(char **typep)
518 {
519         token tok;
520
521         peek(&tok);
522         switch (tok.kind) {
523         case TOK_CHAR:
524                 get_token(&tok);
525                 *typep = "u_char";
526                 break;
527         case TOK_SHORT:
528                 get_token(&tok);
529                 *typep = "u_short";
530                 (void) peekscan(TOK_INT, &tok);
531                 break;
532         case TOK_INT32:
533                 get_token(&tok);
534                 *typep = "afs_uint32";
535                 (void) peekscan(TOK_INT, &tok);
536                 break;
537         case TOK_INT:
538                 get_token(&tok);
539                 *typep = "u_int";
540                 break;
541         default:
542                 *typep = "u_int";
543                 break;
544         }
545 }
546
547
548 static void def_package(definition *defp)
549 {
550     token tok;
551
552     defp->def_kind = DEF_PACKAGE;
553     scan(TOK_IDENT, &tok);
554     defp->def_name = tok.str;
555     no_of_stat_funcs = 0;
556     if (PackageIndex++ >= MAX_PACKAGES)
557         error("Exceeded upper limit of package statements\n");
558     function_list_index = 0;
559     PackagePrefix[PackageIndex] = tok.str;
560     if (MasterPrefix == NULL)
561         MasterPrefix = tok.str;
562     no_of_opcodes[PackageIndex] = highest_opcode[PackageIndex] = opcodesnotallowed[PackageIndex] = 0;
563     lowest_opcode[PackageIndex] = 99999;
564     proc_defined[PackageIndex] = NULL;
565     PackageStatIndex[PackageIndex] = NULL;
566 }
567
568 static void def_prefix(definition *defp)
569 {
570     token tok;
571
572     defp->def_kind = DEF_PREFIX;
573     scan(TOK_IDENT, &tok);
574     defp->def_name = tok.str;
575     ServerPrefix = tok.str;
576 }
577
578 static void def_statindex(definition *defp)
579 {
580     token tok;
581     char *name;
582
583     defp->def_kind = DEF_CONST;
584     scan_num(&tok);
585     if (PackageIndex < 0)
586         error("'statindex' command must follow 'package' command!\n");
587     if (PackageStatIndex[PackageIndex])
588         error("Cannot have more then one 'statindex' per package!\n");
589     if (InvalidConstant(tok.str))
590         error("Index in 'statindex' command must be a constant!");
591     name = alloc(strlen(PackagePrefix[PackageIndex])+strlen("STATINDEX")+1);
592     strcpy(name, PackagePrefix[PackageIndex]);
593     strcat(name, "STATINDEX");
594     defp->def_name = name;
595     defp->def.co = tok.str;
596     PackageStatIndex[PackageIndex] = name;
597 }
598
599 static void def_startingopcode(definition *defp)
600 {
601     token tok;
602
603     defp->def_kind = DEF_STARTINGOPCODE;
604     scan(TOK_IDENT, &tok);
605     defp->def_name = tok.str;
606     if (InvalidConstant(defp->def_name))
607         error("Opcode in 'startingopcode' command must be a constant!");
608     lowest_opcode[PackageIndex] = master_lowest_opcode = atoi(tok.str);
609     if (lowest_opcode[PackageIndex] < 0 || lowest_opcode[PackageIndex] > 99999)
610         error("startingopcode number is out of bounds (must be >= 0 < 100000)");
611     master_opcodenumber = lowest_opcode[PackageIndex];
612     opcodesnotallowed[PackageIndex]=1;
613 }
614
615 static void def_split(definition *defp)
616 {
617     token tok;
618
619     defp->def_kind = DEF_SPLITPREFIX;
620     do {
621         get_token(&tok);
622         switch (tok.kind) {
623                 case TOK_IN:
624                     scan(TOK_EQUAL, &tok);
625                     scan(TOK_IDENT, &tok);
626                     SplitStart = tok.str;
627                     break;
628                 case TOK_OUT:
629                     scan(TOK_EQUAL, &tok);
630                     scan(TOK_IDENT, &tok);
631                     SplitEnd = tok.str;
632                     break;
633                 case TOK_SEMICOLON:
634                     break;
635                 default:
636                     error("syntax error in the 'splitprefix' line");
637         }
638     } while (tok.kind != TOK_SEMICOLON);
639     if (!SplitStart && !SplitEnd)
640         error("At least one param should be passed to 'splitprefix' cmd");
641 }
642
643
644 static void customize_struct(definition *defp)
645 {
646     decl_list *listp;
647     declaration *dec;
648     definition *defp1 = ALLOC(definition);
649     spec_list *specs, **tailp;
650
651     defp->def_kind = DEF_CUSTOMIZED;
652     defp1->def_kind = DEF_SPECIAL;
653     tailp = &defp1->def.sd.specs;
654     for (listp = defp->def.st.decls; listp; listp = listp->next) {
655         dec = &listp->decl;
656         if (streq(dec->type, "string") || (dec->rel == REL_POINTER)) {
657             specs = ALLOC(spec_list);
658             specs->sdef.string_name = dec->name;
659             specs->sdef.string_value = defp->def_name;
660             *tailp = specs;
661             tailp = &specs->next;
662         }
663     }
664     tailp = NULL;
665     STOREVAL(&special_defined, defp1);
666 }
667
668 static char *structname(char *name)
669 {
670     char namecontents[150], *pnt, *pnt1;
671
672     strcpy(namecontents, name);
673     pnt = namecontents;
674     if (!strncmp(pnt, "struct", 6)) pnt += 6;
675     while (isspace(*pnt)) pnt++;
676     pnt1 = pnt;
677     while (*pnt != ' ' && *pnt != '\0') pnt++;
678     *pnt = '\0';
679     return pnt1;
680 }
681
682
683 static void def_special(declaration *dec, definition *defp)
684 {
685     char *typename;
686     spec_list *specs, **tailp;
687     token tok;
688
689     defp->def_kind = DEF_SPECIAL;
690     get_type(&dec->prefix, &dec->type, DEF_SPECIAL);
691     dec->rel = REL_POINTER;
692     scan(TOK_IDENT, &tok);
693     tailp = &defp->def.sd.specs;
694     do {
695         specs = ALLOC(spec_list);
696         specs->sdef.string_name = tok.str;
697         get_param_type(defp, dec, &specs->sdef.string_value, &typename);
698         *tailp = specs;
699         tailp = &specs->next;
700         scan2(TOK_COMMA, TOK_SEMICOLON, &tok);
701         if (tok.kind == TOK_SEMICOLON)
702             break;
703         get_token(&tok);
704     } while (tok.kind == TOK_IDENT);
705     tailp = NULL;
706     STOREVAL(&special_defined, defp);
707 }
708
709  
710 proc1_list *Proc_list, **Proc_listp;
711
712 static void check_proc(definition *defp, token *tokp, int noname)
713 {
714     token tok;
715     int proc_split = 0;
716     int proc_multi = 0;
717
718     tokp->kind = TOK_PROC;
719     defp->def_kind = DEF_PROC;
720     if (noname)
721         defp->pc.proc_name = "";
722     else
723         defp->pc.proc_name = tokp->str;
724     PerProcCounter = 0;
725     defp->pc.proc_prefix = alloc(strlen(PackagePrefix[PackageIndex])+1);
726     strcpy(defp->pc.proc_prefix, PackagePrefix[PackageIndex]);
727     scan2(TOK_LPAREN, TOK_IDENT, &tok);
728     defp->pc.proc_serverstub = NULL;
729     if (tok.kind == TOK_IDENT) {
730         defp->pc.proc_serverstub = tok.str;
731         scan(TOK_LPAREN, &tok);
732     }
733     analyze_ProcParams(defp, &tok);
734     defp->pc.proc_opcodenum = -1;
735     scan4(TOK_SPLIT, TOK_MULTI, TOK_EQUAL, TOK_SEMICOLON, &tok);
736     if (tok.kind == TOK_MULTI) {
737         proc_multi = 1;
738         scan2(TOK_EQUAL, TOK_SEMICOLON, &tok);
739     }
740     if (tok.kind  == TOK_SPLIT) {
741         proc_split = 1;
742         defp->pc.split_flag = 1;
743         scan2(TOK_EQUAL, TOK_SEMICOLON, &tok);
744     }
745     else {
746             defp->pc.split_flag = 0;
747     }
748     if (tok.kind == TOK_EQUAL) {
749         if (opcodesnotallowed[PackageIndex])
750             error("Opcode assignment isn't allowed here!");
751         scan_num(&tok);
752         if (InvalidConstant(tok.str))
753             error("Illegal Opcode assignment (Must be a constant opcode!)");
754         if (opcodenum_is_defined(atoi(tok.str)))
755             error("The opcode number is already used by a previous proc");
756         defp->pc.proc_opcodename = tok.str;
757         defp->pc.proc_opcodenum = atoi(tok.str);
758         if (defp->pc.proc_opcodenum < lowest_opcode[PackageIndex])
759             lowest_opcode[PackageIndex] = defp->pc.proc_opcodenum;
760         if (defp->pc.proc_opcodenum < master_lowest_opcode)
761             master_lowest_opcode = defp->pc.proc_opcodenum;
762         if (defp->pc.proc_opcodenum > highest_opcode[PackageIndex])
763             highest_opcode[PackageIndex] = defp->pc.proc_opcodenum;
764         if (defp->pc.proc_opcodenum > master_highest_opcode)
765             master_highest_opcode = defp->pc.proc_opcodenum;
766         scan(TOK_SEMICOLON, &tok);
767     } else {
768         if (master_opcodenumber == 99999) master_opcodenumber = 0;
769         defp->pc.proc_opcodenum = master_opcodenumber++;
770         if (defp->pc.proc_opcodenum < lowest_opcode[PackageIndex])
771             lowest_opcode[PackageIndex] = defp->pc.proc_opcodenum;
772         if (defp->pc.proc_opcodenum > highest_opcode[PackageIndex])
773             highest_opcode[PackageIndex] = defp->pc.proc_opcodenum;
774         if (defp->pc.proc_opcodenum > master_highest_opcode)
775             master_highest_opcode = defp->pc.proc_opcodenum;
776         opcodesnotallowed[PackageIndex] = 1;    /* force it */
777     }
778     no_of_opcodes[PackageIndex]++, master_no_of_opcodes++;
779     if (proc_multi) {
780         generate_code(defp, 0, 1);
781         if (Cflag || cflag) {
782             generate_code(defp, 1, 1);
783         }
784         generate_multi_macros(defp);
785     } else {
786         generate_code(defp, proc_split, 0);
787     }
788
789     if (function_list_index >= MAX_FUNCTIONS_PER_INTERFACE) {
790         error("too many functions in interface, "
791               "increase MAX_FUNCTIONS_PER_INTERFACE");
792     }
793     sprintf(function_list[PackageIndex][function_list_index],
794             "%s%s%s",
795             prefix,
796             PackagePrefix[PackageIndex],
797             defp->pc.proc_name);
798
799     function_list_index++;
800     no_of_stat_funcs_header[PackageIndex]++;
801     no_of_stat_funcs++;
802     *Proc_listp = NULL;
803 }
804
805
806 #define LEGALNUMS "0123456789"
807 static int InvalidConstant(char *name)
808 {
809     char *map;
810     int slen;
811
812     map = LEGALNUMS;
813     slen = strlen(name);
814     return(slen != strspn(name, map));
815 }
816
817 static int opcodenum_is_defined(int opcode_num)
818 {
819     list *listp;
820     definition *defp;
821     
822     for (listp = proc_defined[PackageIndex]; listp != NULL; listp = listp->next) {
823         defp = (definition *)listp->val;
824         if (opcode_num == defp->pc.proc_opcodenum)
825             return 1;
826     }
827     return 0;
828 }
829
830
831 static void analyze_ProcParams(definition *defp, token *tokp)
832 {
833     declaration dec;
834     decl_list *decls, **tailp;
835
836     Proc_listp = &defp->pc.plists;
837     tailp = &defp->def.st.decls;
838     do {
839         get_token(tokp);
840         Proc_list = ALLOC(proc1_list);
841         memset((char *)Proc_list, 0, sizeof(proc1_list));
842         Proc_list->pl.param_flag = 0;
843         switch (tokp->kind) {
844             case TOK_IN:
845                 hdle_param_tok(defp, &dec, tokp, DEF_INPARAM);
846                 break;
847             case TOK_OUT:
848                 hdle_param_tok(defp, &dec, tokp, DEF_OUTPARAM);
849                 break;
850             case TOK_INOUT:
851                 hdle_param_tok(defp, &dec, tokp, DEF_INOUTPARAM);
852                 break;
853             case TOK_RPAREN:
854                 break;
855             default:
856                 unget_token(tokp);
857                 hdle_param_tok(defp, &dec, tokp, DEF_NULL);
858                 break;
859         }
860         *Proc_listp = Proc_list;
861         Proc_listp = &Proc_list->next;
862         decls = ALLOC(decl_list);
863         memset((char *)decls, 0, sizeof(decl_list));
864         decls->decl = dec;
865         *tailp = decls;
866         tailp = &decls->next;
867     } while (tokp->kind != TOK_RPAREN);
868     *tailp = NULL;
869 }
870
871
872 static void generate_code(definition *defp, int proc_split_flag, int multi_flag)
873 {
874     if (proc_split_flag)
875         handle_split_proc(defp, multi_flag);
876     else {
877         if (Cflag || cflag) {
878             cs_Proc_CodeGeneration(defp, 0, "");
879         }
880         if (Sflag || cflag)
881             ss_Proc_CodeGeneration(defp);
882     }
883     if (Sflag)
884         STOREVAL(&proc_defined[PackageIndex], defp);
885 }
886
887
888 static void handle_split_proc(definition *defp, int multi_flag)
889 {
890     char *startname = SplitStart, *endname = SplitEnd;
891     int numofparams;
892
893     if (!startname) 
894         startname = "Start";
895     if (!endname) 
896         endname = "End";
897     if (Cflag || cflag) {
898         if (!cflag) {
899             do_split(defp, OUT, &numofparams, DEF_OUTPARAM, 0);
900         }
901         cs_Proc_CodeGeneration(defp, 1, startname);
902         if (!cflag) {
903             do_split(defp, OUT, &numofparams, DEF_OUTPARAM, 1);
904             do_split(defp, IN, &numofparams, DEF_INPARAM, 0);
905         }
906         cs_Proc_CodeGeneration(defp, (multi_flag ? 3 : 2), endname);
907         if (!cflag) {
908             do_split(defp, IN, &numofparams, DEF_INPARAM, 1);
909         }
910     }
911     if (Sflag || cflag)
912         ss_Proc_CodeGeneration(defp);
913 }
914
915
916 static void do_split(definition *defp, int direction, int *numofparams, defkind param_kind, int restore_flag)
917 {
918     proc1_list *plist;
919
920     if (restore_flag) {
921         defp->pc.paramtypes[direction] = *numofparams;
922         for (plist = defp->pc.plists; plist; plist = plist->next) {
923             if (plist->component_kind == DEF_NULL && plist->pl.param_kind == param_kind)
924                 plist->component_kind = DEF_PARAM;
925         }
926     } else {
927         *numofparams = defp->pc.paramtypes[direction];
928         defp->pc.paramtypes[direction] = 0;
929         for (plist = defp->pc.plists; plist; plist = plist->next) {
930             if (plist->component_kind == DEF_PARAM && plist->pl.param_kind == param_kind)
931                 plist->component_kind = DEF_NULL;
932         }
933     }
934 }
935
936
937 static void hdle_param_tok(definition *defp, declaration *dec, token *tokp, defkind par_kind)
938 {
939     static defkind last_param_kind = DEF_NULL;
940     
941     if (par_kind == DEF_NULL)
942         Proc_list->pl.param_kind = last_param_kind;
943     else
944         Proc_list->pl.param_kind = par_kind;
945     last_param_kind = Proc_list->pl.param_kind;
946     defp->pc.paramtypes[(int)last_param_kind]++;
947     Proc_list->component_kind = DEF_PARAM;
948     Proc_list->code = alloc(250);
949     Proc_list->scode =  alloc(250);
950     get_declaration(dec, DEF_PARAM);
951     Proc_list->pl.param_name = dec->name;
952     get1_param_type(defp, dec, &Proc_list->pl.param_type);
953     print_param(dec);
954     scan2(TOK_COMMA, TOK_RPAREN, tokp);
955     if (tokp->kind == TOK_COMMA)
956         peek(tokp);
957 }
958
959
960 static void get1_param_type(definition *defp, declaration *dec, char **param_type)
961 {
962     char typecontents[100];
963
964     if (streq(dec->type,"string")) {    
965         *param_type = "char *";
966     } else {
967         if (dec->prefix) {
968             strcpy(typecontents, dec->prefix);  
969             strcat(typecontents, " ");
970             strcat(typecontents, dec->type);
971             strcat(typecontents, " *");
972         } else if (dec->rel == REL_POINTER) {
973             strcpy(typecontents, dec->type);
974             strcat(typecontents, " *");
975         } else
976             strcpy(typecontents, dec->type);
977         *param_type = alloc(100);
978         strcpy(*param_type, typecontents);
979     }
980 }
981
982
983 static void get_param_type(definition *defp, declaration *dec, char **param_type, char **typename)
984 {
985     char typecontents[100];
986
987     if (streq(dec->type,"string")) {    
988         *typename = "wrapstring";    
989         *param_type = "char *";
990     } else {
991         *typename = dec->type;
992         if (dec->prefix) {
993             strcpy(typecontents, dec->prefix);  
994             strcat(typecontents, " ");
995             strcat(typecontents, dec->type);
996             strcat(typecontents, " *");
997             dec->rel = REL_POINTER;
998         } else if (dec->rel == REL_POINTER) {
999             strcpy(typecontents, dec->type);
1000             strcat(typecontents, " *");
1001         } else
1002             strcpy(typecontents, dec->type);
1003         *param_type = alloc(100);
1004         strcpy(*param_type, typecontents);
1005     }
1006 }
1007
1008
1009 #ifdef undef
1010 static void hndle_param_tail(definition *defp, declaration *dec, token *tokp, char *typename)
1011 {
1012     char *amp;
1013
1014     if (dec->rel == REL_POINTER)
1015         Proc_list->pl.param_flag |= INDIRECT_PARAM;
1016     else
1017         Proc_list->pl.param_flag &= ~INDIRECT_PARAM;
1018     amp = "";
1019     if (!(Proc_list->pl.param_flag & INDIRECT_PARAM))
1020         amp = "&";
1021
1022     sprintf(Proc_list->code, "xdr_%s(&z_xdrs, %s%s)", typename, amp, Proc_list->pl.param_name);
1023     sprintf(Proc_list->scode, "xdr_%s(z_xdrs, &%s)", typename, Proc_list->pl.param_name);
1024     scan2(TOK_COMMA, TOK_RPAREN, tokp);
1025     if (tokp->kind == TOK_COMMA)
1026         peek(tokp);
1027 }
1028 #endif
1029
1030
1031 static void cs_Proc_CodeGeneration(definition *defp, int split_flag, char *procheader)
1032 {
1033     defp->can_fail = 0;
1034     cs_ProcName_setup(defp, procheader, split_flag);
1035     if (!cflag) {
1036         cs_ProcParams_setup(defp, split_flag);
1037         cs_ProcMarshallInParams_setup(defp, split_flag);
1038         if (split_flag != 1) {
1039             cs_ProcSendPacket_setup(defp, split_flag);
1040             cs_ProcUnmarshallOutParams_setup(defp);
1041         }
1042         cs_ProcTail_setup(defp, split_flag);
1043     }
1044 }
1045
1046
1047 static void cs_ProcName_setup(definition *defp, char *procheader, int split_flag)
1048 {
1049     proc1_list *plist;
1050
1051     if (!cflag) {
1052         if (split_flag) {
1053             f_print(fout, "int %s%s%s%s(z_call", procheader, prefix, PackagePrefix[PackageIndex], defp->pc.proc_name);
1054         } else {
1055             f_print(fout, "int %s%s%s%s(z_conn", procheader, prefix, PackagePrefix[PackageIndex], defp->pc.proc_name);
1056         }
1057     }
1058     if ((strlen(procheader) + strlen(prefix) + strlen(PackagePrefix[PackageIndex]) + strlen(defp->pc.proc_name)) >= MAX_FUNCTION_NAME_LEN) {
1059         error("function name is too long, increase MAX_FUNCTION_NAME_LEN");
1060     }
1061     if (!cflag) {
1062         for (plist = defp->pc.plists; plist; plist = plist->next) {
1063             if (plist->component_kind == DEF_PARAM) {
1064                 plist->pl.param_flag &= ~PROCESSED_PARAM;
1065                 f_print(fout, ", %s", plist->pl.param_name);
1066             }
1067         }
1068         f_print(fout, ")\n");  
1069     }
1070 }
1071
1072
1073 static void cs_ProcParams_setup(definition *defp, int split_flag)
1074 {
1075     proc1_list *plist, *plist1;
1076
1077     if (!split_flag)
1078         f_print(fout, "\tregister struct rx_connection *z_conn;\n");    
1079     if (split_flag) {
1080         f_print(fout, "\tregister struct rx_call *z_call;\n");
1081     }
1082     for (plist = defp->pc.plists; plist; plist = plist->next) {
1083         if (plist->component_kind == DEF_PARAM && !(plist->pl.param_flag & PROCESSED_PARAM)) {
1084             if (plist->pl.param_flag & OUT_STRING) {
1085                 f_print(fout, "\t%s *%s", plist->pl.param_type, plist->pl.param_name);
1086             } else {
1087                 f_print(fout, "\t%s %s", plist->pl.param_type, plist->pl.param_name);
1088             }
1089             plist->pl.param_flag |= PROCESSED_PARAM;
1090             for (plist1 = defp->pc.plists; plist1; plist1 = plist1->next) {
1091                 if ((plist1->component_kind == DEF_PARAM) && streq(plist->pl.param_type, plist1->pl.param_type) && !(plist1->pl.param_flag & PROCESSED_PARAM)) {
1092                     char *star="";
1093                     char *pntr = strchr(plist1->pl.param_type, '*');
1094                     if (pntr) star = "*";
1095                     if (plist1->pl.param_flag & OUT_STRING) {
1096                         f_print(fout, ", *%s%s", star, plist1->pl.param_name);
1097                     } else {
1098                         f_print(fout, ", %s%s", star, plist1->pl.param_name);
1099                     }
1100                     plist1->pl.param_flag |= PROCESSED_PARAM;
1101                 }
1102             }
1103             f_print(fout, ";\n");
1104         }
1105     }
1106 }
1107
1108
1109 static void cs_ProcMarshallInParams_setup(definition *defp, int split_flag)
1110 {
1111     int noofparams, i=0;
1112     proc1_list *plist;
1113     decl_list *dl;
1114     int noofallparams = defp->pc.paramtypes[IN] + defp->pc.paramtypes[INOUT] +
1115                         defp->pc.paramtypes[OUT];
1116
1117     f_print(fout, "{\n");
1118     if (!split_flag)
1119         f_print(fout, "\tstruct rx_call *z_call = rx_NewCall(z_conn);\n");
1120     if ((!split_flag) || (split_flag == 1)) {
1121         if (opcodesnotallowed[PackageIndex]) {
1122             f_print(fout, "\tstatic int z_op = %d;\n", defp->pc.proc_opcodenum);
1123         } else {
1124             f_print(fout, "\tstatic int z_op = %s;\n", defp->pc.proc_opcodename);
1125         }
1126     }
1127     f_print(fout, "\tint z_result;\n");
1128     if (!(split_flag > 1) || (noofallparams != 0)) {
1129         f_print(fout, "\tXDR z_xdrs;\n");
1130     }
1131     /*
1132      * Print out client side stat gathering call
1133      */
1134     if (xflag && split_flag != 1) {
1135         f_print(fout, "\tstruct clock __QUEUE, __EXEC;\n");
1136     }
1137
1138     if ((!split_flag) || (split_flag == 1)) {
1139         f_print(fout, "\txdrrx_create(&z_xdrs, z_call, XDR_ENCODE);\n");
1140         f_print(fout, "\n\t/* Marshal the arguments */\n");
1141         f_print(fout, "\tif ((!xdr_int(&z_xdrs, &z_op))");
1142         noofparams = defp->pc.paramtypes[IN] + defp->pc.paramtypes[INOUT];
1143         for (plist = defp->pc.plists, dl=defp->def.st.decls; plist; plist = plist->next, dl = dl->next) {
1144             if (plist->component_kind == DEF_PARAM && (plist->pl.param_kind == DEF_INPARAM || plist->pl.param_kind == DEF_INOUTPARAM)) {
1145                 f_print(fout, "\n\t     || (!%s)", plist->code);
1146                 if (++i == noofparams) {
1147                     f_print(fout, ") {\n\t\tz_result = RXGEN_CC_MARSHAL;\n\t\tgoto fail;\n\t}\n\n");
1148                     defp->can_fail = 1;
1149                 }
1150             }
1151         }
1152         if (!i) {
1153             f_print(fout, ") {\n\t\tz_result = RXGEN_CC_MARSHAL;\n\t\tgoto fail;\n\t}\n\n");
1154             defp->can_fail = 1;
1155         }
1156     }
1157 }
1158
1159
1160 static void cs_ProcSendPacket_setup(definition *defp, int split_flag)
1161 {
1162     int noofoutparams = defp->pc.paramtypes[INOUT] + defp->pc.paramtypes[OUT];
1163
1164     if (noofoutparams) {
1165             f_print(fout, "\t/* Un-marshal the reply arguments */\n");
1166             if (split_flag) {
1167                 f_print(fout, "\txdrrx_create(&z_xdrs, z_call, XDR_DECODE);\n");
1168             } else {
1169                 f_print(fout, "\tz_xdrs.x_op = XDR_DECODE;\n");
1170             }
1171     }
1172 }
1173
1174
1175 static void cs_ProcUnmarshallOutParams_setup(definition *defp)
1176 {
1177     int noofparams, i;
1178     proc1_list *plist;
1179     decl_list *dl;
1180
1181     noofparams = defp->pc.paramtypes[INOUT] + defp->pc.paramtypes[OUT];
1182     if (noofparams)
1183         for (plist = defp->pc.plists, dl=defp->def.st.decls,i = 0; plist; plist = plist->next, dl=dl->next) {
1184             if (plist->component_kind == DEF_PARAM && (plist->pl.param_kind == DEF_OUTPARAM || plist->pl.param_kind == DEF_INOUTPARAM)) {
1185                     if (!i) {
1186                         f_print(fout, "\tif ((!%s)", plist->code);
1187                     } else {
1188                         f_print(fout, "\n\t     || (!%s)", plist->code);
1189                     }
1190                 if (++i == noofparams) {
1191                     f_print(fout, ") {\n\t\tz_result = RXGEN_CC_UNMARSHAL;\n\t\tgoto fail;\n\t}\n\n");
1192                     defp->can_fail = 1;
1193                 }
1194             }       
1195         }
1196 }
1197
1198
1199 static void cs_ProcTail_setup(definition *defp, int split_flag)
1200 {
1201     f_print(fout, "\tz_result = RXGEN_SUCCESS;\n");
1202     if (defp->can_fail) {
1203         f_print(fout, "fail:\n");
1204     }
1205     if (!split_flag) {
1206         f_print(fout, "\tz_result = rx_EndCall(z_call, z_result);\n");
1207     }
1208     if (xflag && split_flag != 1) {
1209         f_print(fout, "\tif (rx_enable_stats) {\n");
1210         f_print(fout, "\t    clock_GetTime(&__EXEC);\n");
1211         f_print(fout, "\t    clock_Sub(&__EXEC, &z_call->startTime);\n");
1212         f_print(fout, "\t    __QUEUE = z_call->startTime;\n");
1213         f_print(fout, "\t    clock_Sub(&__QUEUE, &z_call->queueTime);\n");
1214         if (PackageStatIndex[PackageIndex]) {
1215             if (!split_flag) {
1216                 f_print(fout,
1217                     "\t    rx_IncrementTimeAndCount(z_conn->peer, %s,\n",
1218                     PackageStatIndex[PackageIndex]);
1219             } else {
1220                 f_print(fout,
1221                     "\t    rx_IncrementTimeAndCount(z_call->conn->peer, %s,\n",
1222                     PackageStatIndex[PackageIndex]);
1223             }
1224         } else {
1225             if (!split_flag) {
1226                 f_print(fout,
1227                     "\t    rx_IncrementTimeAndCount(z_conn->peer,\n"
1228                     "\t\t(((afs_uint32)(ntohs(z_conn->serviceId) << 16)) \n"
1229                     "\t\t| ((afs_uint32)ntohs(z_conn->peer->port))),\n");
1230             } else {
1231                 f_print(fout,
1232                     "\t    rx_IncrementTimeAndCount(z_call->conn->peer,\n"
1233                     "\t\t(((afs_uint32)(ntohs(z_call->conn->serviceId) << 16)) |\n"
1234                     "\t\t((afs_uint32)ntohs(z_call->conn->peer->port))),\n");
1235             }
1236         }
1237         if (xflag) {
1238             f_print(fout, "\t\t%d, %sNO_OF_STAT_FUNCS, &__QUEUE, &__EXEC,\n",
1239                           no_of_stat_funcs,
1240                           PackagePrefix[PackageIndex]);
1241             f_print(fout, "\t\t&z_call->bytesSent, &z_call->bytesRcvd, 1);\n");
1242         }
1243         f_print(fout, "\t}\n\n");
1244     }
1245     f_print(fout, "\treturn z_result;\n}\n\n");
1246 }
1247
1248
1249 static void ss_Proc_CodeGeneration(definition *defp)
1250 {
1251     int somefrees=0;
1252
1253     defp->can_fail = 0;
1254     ss_ProcName_setup(defp);
1255     if (!cflag) {
1256         ss_ProcParams_setup(defp, &somefrees);
1257         ss_ProcSpecial_setup(defp, &somefrees);
1258         ss_ProcUnmarshallInParams_setup(defp);
1259         ss_ProcCallRealProc_setup(defp);
1260         ss_ProcMarshallOutParams_setup(defp);
1261         ss_ProcTail_setup(defp, somefrees);
1262     }
1263 }
1264
1265
1266 static void ss_ProcName_setup(definition *defp)
1267 {
1268     proc1_list *plist;
1269
1270     if ((strlen(prefix) + strlen(PackagePrefix[PackageIndex]) + strlen(defp->pc.proc_name)) >= MAX_FUNCTION_NAME_LEN) {
1271         error("function name is too long, increase MAX_FUNCTION_NAME_LEN");
1272     }
1273
1274     if (!cflag) {
1275         f_print(fout, "static afs_int32 _%s%s%s(", prefix, PackagePrefix[PackageIndex], defp->pc.proc_name);
1276         f_print(fout, "struct rx_call *z_call, XDR *z_xdrs)\n{\n");
1277         f_print(fout, "\t" "afs_int32 z_result;\n");
1278         if (xflag) {
1279             f_print(fout, "\tstruct clock __QUEUE, __EXEC;\n");
1280         }
1281
1282         for (plist = defp->pc.plists; plist; plist = plist->next) 
1283             if (plist->component_kind == DEF_PARAM) {
1284                 plist->pl.param_flag &= ~(PROCESSED_PARAM);
1285                 plist->pl.string_name = NULL;
1286             }
1287     }
1288 }
1289
1290
1291 static void ss_ProcParams_setup(definition *defp, int *somefrees)
1292 {
1293     proc1_list *plist, *plist1;
1294     list *listp;
1295     definition *defp1;
1296
1297     for (plist = defp->pc.plists; plist; plist = plist->next) {
1298         if ((plist->component_kind == DEF_PARAM) && !(plist->pl.param_flag & PROCESSED_PARAM)) {
1299             if (plist->pl.param_flag & INDIRECT_PARAM) {
1300                     char pres='\0', *pntr = strchr(plist->pl.param_type, '*');
1301                     if (pntr){ --pntr; pres = *pntr; *pntr = (char)0; }
1302                     f_print(fout, "\t%s %s", plist->pl.param_type, plist->pl.param_name);
1303                     *pntr = pres;
1304             } else if (strchr(plist->pl.param_type, '*') == 0) {
1305                 f_print(fout, "\t%s %s", plist->pl.param_type, plist->pl.param_name);
1306             } else {
1307                 plist->pl.param_flag |= FREETHIS_PARAM;
1308                 *somefrees = 1;
1309                 f_print(fout, "\t%s %s=(%s)0", plist->pl.param_type, plist->pl.param_name, plist->pl.param_type);
1310             }
1311             plist->pl.param_flag |= PROCESSED_PARAM;
1312             for (plist1 = defp->pc.plists; plist1; plist1 = plist1->next) {
1313                 if ((plist1->component_kind == DEF_PARAM) && streq(plist->pl.param_type, plist1->pl.param_type) && !(plist1->pl.param_flag & PROCESSED_PARAM)) {
1314                     if (plist1->pl.param_flag & INDIRECT_PARAM) {
1315                             f_print(fout, ", %s", plist1->pl.param_name);
1316                     } else if (strchr(plist1->pl.param_type, '*') == 0) {
1317                         f_print(fout, ", %s", plist1->pl.param_name);
1318                     } else {
1319                         plist1->pl.param_flag |= FREETHIS_PARAM;
1320                         *somefrees = 1;
1321                         f_print(fout, ", *%s=(%s)0", plist1->pl.param_name, plist1->pl.param_type);
1322                     }
1323                     plist1->pl.param_flag |= PROCESSED_PARAM;
1324                 }
1325             }
1326             f_print(fout, ";\n");
1327         }
1328     }
1329     for (listp = typedef_defined; listp != NULL; listp = listp->next) {
1330         defp1 = (definition *)listp->val;
1331         for (plist=defp->pc.plists; plist; plist=plist->next) {
1332             if (plist->component_kind == DEF_PARAM && (plist->pl.param_kind == DEF_OUTPARAM || plist->pl.param_kind == DEF_INOUTPARAM) && !(plist->pl.param_flag & FREETHIS_PARAM)) {
1333                 if (streq(defp1->def_name, structname(plist->pl.param_type))) {
1334                     switch (defp1->pc.rel) {
1335                         case REL_ARRAY:
1336                         case REL_POINTER:
1337                             break;
1338                     }
1339                 }
1340             }
1341         }
1342     }   
1343     fprintf(fout, "\n");
1344 }
1345
1346
1347 static void ss_ProcSpecial_setup(definition *defp, int *somefrees)
1348 {
1349     proc1_list *plist;
1350     definition *defp1;
1351     list *listp;
1352
1353    for (listp = special_defined; listp != NULL; listp = listp->next) {
1354         defp1 = (definition *)listp->val;
1355         for (plist=defp->pc.plists; plist; plist=plist->next) {
1356             if (plist->component_kind == DEF_PARAM && (plist->pl.param_kind == DEF_INPARAM || plist->pl.param_kind == DEF_INOUTPARAM)) {
1357                 spec_list *spec = defp1->def.sd.specs;
1358                 char string[40];
1359                 strcpy(string, structname(spec->sdef.string_value));
1360                 if (streq(string, structname(plist->pl.param_type))) {
1361                     plist->pl.string_name = spec->sdef.string_name;
1362                     plist->pl.param_flag |= FREETHIS_PARAM;
1363                     *somefrees = 1;
1364                     fprintf(fout, "\n\t%s.%s = 0;", plist->pl.param_name, spec->sdef.string_name);
1365                 }
1366             }
1367         }
1368     }
1369     if (!*somefrees)
1370         fprintf(fout, "\n");
1371     for (listp = typedef_defined; listp != NULL; listp = listp->next) {
1372         defp1 = (definition *)listp->val;
1373         for (plist=defp->pc.plists; plist; plist=plist->next) {
1374             if (plist->component_kind == DEF_PARAM ) {
1375                 if (streq(defp1->def_name, structname(plist->pl.param_type))) {
1376                     plist->pl.param_flag |= FREETHIS_PARAM;
1377                     *somefrees = 1;
1378                     switch (defp1->pc.rel) {
1379                         case REL_ARRAY:
1380                             f_print(fout, "\n\t%s.%s_val = 0;", plist->pl.param_name, defp1->def_name);
1381                             f_print(fout, "\n\t%s.%s_len = 0;", plist->pl.param_name, defp1->def_name);
1382                             plist->pl.string_name = alloc(40);
1383                             s_print(plist->pl.string_name, "%s_val", defp1->def_name);
1384                             break;
1385                         case REL_POINTER:
1386                             f_print(fout, "\n\t%s = 0;", plist->pl.param_name);
1387                             plist->pl.string_name = NULL;
1388                             break;
1389                     }
1390                 }
1391             }
1392         }
1393     }   
1394     f_print(fout, "\n");
1395 }
1396
1397
1398 static void ss_ProcUnmarshallInParams_setup(definition *defp)
1399 {
1400     int noofparams, noofoutparams, i;
1401     proc1_list *plist;
1402
1403     noofparams = defp->pc.paramtypes[IN] + defp->pc.paramtypes[INOUT];
1404     noofoutparams = defp->pc.paramtypes[INOUT] + defp->pc.paramtypes[OUT];
1405     for (plist = defp->pc.plists, i=0; plist; plist = plist->next) {
1406         if (plist->component_kind == DEF_PARAM && (plist->pl.param_kind == DEF_INPARAM || plist->pl.param_kind == DEF_INOUTPARAM)) {
1407                 if (!i) {
1408                     f_print(fout, "\n\tif ((!%s)", (plist->scode ? plist->scode : plist->code));
1409                 } else {
1410                     f_print(fout, "\n\t     || (!%s)", (plist->scode ? plist->scode : plist->code));
1411                 }
1412             if (++i == noofparams) {
1413                 if (!noofoutparams) {
1414                     f_print(fout, ") {\n");
1415                 } else {
1416                     f_print(fout, ") {\n");
1417                 }
1418                 f_print(fout, "\t\tz_result = RXGEN_SS_UNMARSHAL;\n\t\tgoto fail;\n\t}\n\n");
1419                 defp->can_fail = 1;
1420             }
1421         }
1422     }
1423 }
1424
1425
1426 static void ss_ProcCallRealProc_setup(definition *defp)
1427 {
1428     extern char zflag;
1429     proc1_list *plist;
1430
1431     f_print(fout, "\tz_result = %s%s%s%s(z_call", prefix, ServerPrefix, PackagePrefix[PackageIndex], defp->pc.proc_name);
1432     for (plist = defp->pc.plists; plist; plist = plist->next) {
1433         if (plist->component_kind == DEF_PARAM) {
1434             if (plist->pl.param_flag & INDIRECT_PARAM) {
1435                     f_print(fout, ", &%s", plist->pl.param_name);
1436             } else {
1437                 if (plist->pl.param_flag & OUT_STRING) {
1438                     f_print(fout, ", &%s", plist->pl.param_name);
1439                 } else {
1440                     f_print(fout, ", %s", plist->pl.param_name);
1441                 }
1442             }
1443         }
1444     }
1445     f_print(fout, ");\n");
1446     if (zflag) {
1447         f_print(fout, "\tif (z_result)\n\t\treturn z_result;\n");
1448     }
1449 }
1450
1451
1452 static void ss_ProcMarshallOutParams_setup(definition *defp)
1453 {
1454     proc1_list *plist;
1455     int noofparams, i;
1456
1457     noofparams = defp->pc.paramtypes[INOUT] + defp->pc.paramtypes[OUT];
1458     if (noofparams)
1459         f_print(fout, "\tz_xdrs->x_op = XDR_ENCODE;\n");
1460     if (noofparams) {
1461         for (plist = defp->pc.plists, i=0; plist; plist = plist->next) {
1462             if (plist->component_kind == DEF_PARAM && (plist->pl.param_kind == DEF_OUTPARAM || plist->pl.param_kind == DEF_INOUTPARAM)) {
1463                 if (!i) {
1464                     f_print(fout, "\tif ((!%s)", (plist->scode ? plist->scode : plist->code));
1465                 } else {
1466                     f_print(fout, "\n\t     || (!%s)", (plist->scode ? plist->scode : plist->code));
1467                 }
1468                 if (++i == noofparams) {
1469                     f_print(fout, ")\n\t\tz_result = RXGEN_SS_MARSHAL;\n");
1470                 }
1471             }
1472         }               
1473     }
1474 }
1475
1476
1477 static void ss_ProcTail_setup(definition *defp, int somefrees)
1478 {
1479     proc1_list *plist;
1480     definition *defp1;
1481     list *listp;
1482     int firsttime = 0;
1483
1484     if (defp->can_fail) {
1485         f_print(fout, "fail:\n");
1486     }
1487     for (plist = defp->pc.plists; plist; plist = plist->next) {    
1488         if (plist->component_kind == DEF_PARAM && (plist->pl.param_flag & FREETHIS_PARAM))
1489             somefrees = 1;
1490     }
1491     if (somefrees)
1492         f_print(fout, "\tz_xdrs->x_op = XDR_FREE;\n");
1493     for (plist = defp->pc.plists; plist; plist = plist->next) {    
1494         if (plist->component_kind == DEF_PARAM && (plist->pl.param_flag & FREETHIS_PARAM)) {
1495             char *dot = "", *extens = "";
1496             if (plist->pl.string_name) {
1497                 dot = ".";
1498                 extens = plist->pl.string_name;
1499             }
1500             f_print(fout, "\tif (!%s) goto fail1;\n", plist->scode);
1501         }
1502     }
1503     for (listp = typedef_defined; listp != NULL; listp = listp->next) {
1504         defp1 = (definition *)listp->val;
1505         for (plist=defp->pc.plists; plist; plist=plist->next) {
1506             if (plist->component_kind == DEF_PARAM && (plist->pl.param_kind == DEF_OUTPARAM || plist->pl.param_kind == DEF_INOUTPARAM) && !(plist->pl.param_flag & FREETHIS_PARAM)) {
1507                 if (streq(defp1->def_name, structname(plist->pl.param_type))) {
1508                     switch (defp1->pc.rel) {
1509                         case REL_ARRAY:
1510                         case REL_POINTER:
1511                             if (!somefrees && !firsttime) {
1512                                 firsttime = 1;
1513                                 f_print(fout, "\tz_xdrs->x_op = XDR_FREE;\n");
1514                             }
1515                             somefrees = 1;
1516                             f_print(fout, "\tif (!%s) goto fail1;\n", plist->scode);
1517                             break;
1518                     }
1519                 }
1520             }
1521         }
1522     }   
1523     for (listp = uniondef_defined; listp != NULL; listp = listp->next) {
1524         defp1 = (definition *)listp->val;
1525         for (plist=defp->pc.plists; plist; plist=plist->next) {
1526             if (plist->component_kind == DEF_PARAM && (plist->pl.param_kind == DEF_OUTPARAM || plist->pl.param_kind == DEF_INOUTPARAM) && !(plist->pl.param_flag & FREETHIS_PARAM)) {
1527                 if (streq(defp1->def_name, structname(plist->pl.param_type))) {
1528                     if (plist->pl.param_flag & INDIRECT_PARAM) {
1529                         if (!somefrees && !firsttime) {
1530                             firsttime = 1;
1531                             f_print(fout, "\tz_xdrs->x_op = XDR_FREE;\n");
1532                         }
1533                         somefrees = 1;
1534                         f_print(fout, "\tif (!%s) goto fail1;\n", plist->scode);
1535                     }
1536                 }
1537             }
1538         }
1539     }   
1540
1541     if (xflag) {
1542         f_print(fout, "\tif (rx_enable_stats) {\n");
1543         f_print(fout, "\t    clock_GetTime(&__EXEC);\n");
1544         f_print(fout, "\t    clock_Sub(&__EXEC, &z_call->startTime);\n");
1545         f_print(fout, "\t    __QUEUE = z_call->startTime;\n");
1546         f_print(fout, "\t    clock_Sub(&__QUEUE, &z_call->queueTime);\n");
1547         f_print(fout, "\t    rx_IncrementTimeAndCount(z_call->conn->peer,");
1548         if (PackageStatIndex[PackageIndex]) {
1549             f_print(fout, " %s,\n", PackageStatIndex[PackageIndex]);
1550         } else {
1551             f_print(fout, 
1552                 "\n\t\t(((afs_uint32)(ntohs(z_call->conn->serviceId) << 16)) |\n"
1553                 "\t\t((afs_uint32)ntohs(z_call->conn->service->servicePort))),\n");
1554         }
1555         f_print(fout, "\t\t%d, %sNO_OF_STAT_FUNCS, &__QUEUE, &__EXEC,\n",
1556                       no_of_stat_funcs,
1557                       PackagePrefix[PackageIndex]);
1558         f_print(fout, "\t\t&z_call->bytesSent, &z_call->bytesRcvd, 0);\n");
1559         f_print(fout, "\t}\n\n");
1560     }
1561
1562     f_print(fout, "\treturn z_result;\n");
1563     if (somefrees) {
1564         f_print(fout, "fail1:\n");
1565
1566         if (xflag) {
1567             f_print(fout, "\tif (rx_enable_stats) {\n");
1568             f_print(fout, "\t    clock_GetTime(&__EXEC);\n");
1569             f_print(fout, "\t    clock_Sub(&__EXEC, &z_call->startTime);\n");
1570             f_print(fout, "\t    __QUEUE = z_call->startTime;\n");
1571             f_print(fout, "\t    clock_Sub(&__QUEUE, &z_call->queueTime);\n");
1572             f_print(fout, "\t    rx_IncrementTimeAndCount(z_call->conn->peer,");
1573             if (PackageStatIndex[PackageIndex]) {
1574                 f_print(fout, " %s,\n", PackageStatIndex[PackageIndex]);
1575             } else {
1576                 f_print(fout,
1577                     "\n\t\t(((afs_uint32)(ntohs(z_call->conn->serviceId) << 16)) |\n"
1578                     "\t\t((afs_uint32)ntohs(z_call->conn->service->servicePort))),\n");
1579             }
1580             f_print(fout, "\t\t%d, %sNO_OF_STAT_FUNCS, &__QUEUE, &__EXEC,\n",
1581                           no_of_stat_funcs,
1582                           PackagePrefix[PackageIndex]);
1583             f_print(fout, "\t\t&z_call->bytesSent, &z_call->bytesRcvd, 0);\n");
1584             f_print(fout, "\t}\n\n");
1585         }
1586
1587         f_print(fout, "\treturn RXGEN_SS_XDRFREE;\n}\n\n");
1588     } else {
1589         f_print(fout, "}\n\n");
1590     }
1591 }
1592
1593
1594 static int opcode_holes_exist(void)
1595 {
1596     int i;
1597     
1598     for (i=lowest_opcode[PackageIndex]; i<highest_opcode[PackageIndex]; i++) {
1599         if (!opcodenum_is_defined(i))
1600             return 1;
1601     }
1602     return 0;
1603 }
1604
1605         
1606 void er_Proc_CodeGeneration(void)
1607 {
1608     int temp;
1609
1610     temp = PackageIndex;
1611     if (!combinepackages) PackageIndex = 0;
1612     for (; PackageIndex <= temp; PackageIndex++) {
1613         if (proc_defined[PackageIndex] == NULL) continue;
1614         if (combinepackages || opcode_holes_exist()) {
1615             er_HeadofOldStyleProc_setup();
1616             er_BodyofOldStyleProc_setup();
1617             er_TailofOldStyleProc_setup();
1618         } else {
1619             er_ProcDeclExterns_setup();
1620             er_ProcProcsArray_setup();
1621             er_ProcMainBody_setup();
1622         }
1623     }
1624     PackageIndex = temp;
1625 }
1626
1627
1628 static void er_ProcDeclExterns_setup(void)
1629 {
1630     list *listp;
1631     definition *defp;
1632
1633     f_print(fout, "\n");
1634     for (listp = proc_defined[PackageIndex]; listp != NULL; listp = listp->next) {
1635         defp = (definition *)listp->val;
1636         if (defp->pc.proc_serverstub) {
1637             f_print(fout, "afs_int32 %s();\n", defp->pc.proc_serverstub);
1638         }
1639     }
1640 }
1641
1642
1643 static void er_ProcProcsArray_setup(void)
1644 {
1645     list *listp;
1646     definition *defp;
1647
1648     if ((listp = proc_defined[PackageIndex])) {
1649         defp = (definition *)listp->val;
1650         if (defp->pc.proc_serverstub){
1651             f_print(fout, "\nstatic afs_int32 (*StubProcsArray%d[])() = {%s", 
1652                 PackageIndex, defp->pc.proc_serverstub);
1653         } else {
1654             f_print(fout, 
1655                 "\nstatic afs_int32 (*StubProcsArray%d[])(struct rx_call *z_call, XDR *z_xdrs) = {_%s%s%s", 
1656                 PackageIndex, prefix, defp->pc.proc_prefix, 
1657                 ((definition *)listp->val)->pc.proc_name);
1658             defp = (definition *)listp->val;
1659         }
1660         listp = listp->next;
1661     }
1662     for (; listp != NULL; listp = listp->next) {
1663         defp = (definition *)listp->val;
1664         if (defp->pc.proc_serverstub) {
1665             f_print(fout, ",%s", defp->pc.proc_serverstub);
1666         } else {
1667             f_print(fout, ", _%s%s%s", prefix, defp->pc.proc_prefix, defp->pc.proc_name);
1668         }
1669     }
1670     f_print(fout, "};\n\n");
1671 }
1672
1673
1674 static void er_ProcMainBody_setup(void)
1675 {
1676     f_print(fout, "int %s%sExecuteRequest(register struct rx_call *z_call)\n", prefix,  PackagePrefix[PackageIndex]);
1677     f_print(fout, "{\n\tint op;\n");
1678     f_print(fout, "\tXDR z_xdrs;\n");
1679     f_print(fout, "\t" "afs_int32 z_result;\n\n");
1680     f_print(fout, "\txdrrx_create(&z_xdrs, z_call, XDR_DECODE);\n");
1681     f_print(fout, "\tif (!xdr_int(&z_xdrs, &op))\n\t\tz_result = RXGEN_DECODE;\n");
1682     f_print(fout, "\telse if (op < %sLOWEST_OPCODE || op > %sHIGHEST_OPCODE)\n\t\tz_result = RXGEN_OPCODE;\n", PackagePrefix[PackageIndex], PackagePrefix[PackageIndex]);
1683     f_print(fout, "\telse\n\t\tz_result = (*StubProcsArray%d[op - %sLOWEST_OPCODE])(z_call, &z_xdrs);\n", PackageIndex, PackagePrefix[PackageIndex]);
1684     f_print(fout, "\treturn hton_syserr_conv(z_result);\n}\n");
1685 }
1686
1687
1688 static void er_HeadofOldStyleProc_setup(void)
1689 {
1690     f_print(fout, "\nint %s%sExecuteRequest (register struct rx_call *z_call)\n", 
1691                 prefix, (combinepackages ? MasterPrefix : PackagePrefix[PackageIndex]));
1692     f_print(fout, "{\n");
1693     f_print(fout, "\tint op;\n");
1694     f_print(fout, "\tXDR z_xdrs;\n");
1695     f_print(fout, "\t" "afs_int32 z_result;\n\n");
1696     f_print(fout, "\txdrrx_create(&z_xdrs, z_call, XDR_DECODE);\n");
1697     f_print(fout, "\tz_result = RXGEN_DECODE;\n");
1698     f_print(fout, "\tif (!xdr_int(&z_xdrs, &op)) goto fail;\n");
1699     f_print(fout, "\tswitch (op) {\n");
1700 }
1701
1702 static void er_BodyofOldStyleProc_setup(void)
1703 {
1704     list *listp;
1705
1706     if (combinepackages) {
1707         int temp = PackageIndex;
1708         for (PackageIndex = 0; PackageIndex <= temp; PackageIndex++) {
1709             for (listp = proc_defined[PackageIndex]; listp != NULL; listp = listp->next)
1710                 proc_er_case((definition *)listp->val);     
1711         }
1712         PackageIndex = temp;
1713     } else {
1714     for (listp = proc_defined[PackageIndex]; listp != NULL; listp = listp->next)
1715         proc_er_case((definition *)listp->val);
1716     }
1717 }
1718
1719
1720 static void proc_er_case(definition *defp)
1721 {
1722     if (opcodesnotallowed[PackageIndex]) {
1723         f_print(fout, "\t\tcase %d:\n", defp->pc.proc_opcodenum);
1724     } else {
1725         f_print(fout, "\t\tcase %s:\n", defp->pc.proc_opcodename);
1726     }
1727     if (defp->pc.proc_serverstub) {
1728         f_print(fout, "\t\t\tz_result = %s(z_call, &z_xdrs);\n", defp->pc.proc_serverstub);
1729     } else {
1730         f_print(fout, "\t\t\tz_result = _%s%s%s(z_call, &z_xdrs);\n", prefix, defp->pc.proc_prefix, defp->pc.proc_name);
1731     }
1732     f_print(fout, "\t\t\tbreak;\n");    
1733 }
1734
1735
1736 static void er_TailofOldStyleProc_setup(void)
1737 {
1738     f_print(fout, "\t\tdefault:\n");
1739     f_print(fout, "\t\t\tz_result = RXGEN_OPCODE;\n");
1740     f_print(fout, "\t\t\tbreak;\n\t}\n");
1741     f_print(fout, "fail:\n");
1742     f_print(fout, "\treturn z_result;\n}\n");
1743 }
1744
1745
1746 void h_opcode_stats(void)
1747 {
1748     if (combinepackages) {
1749         f_print(fout, "\n/* Opcode-related useful stats for Master package: %s */\n", MasterPrefix);
1750         f_print(fout, "#define %sLOWEST_OPCODE   %d\n", MasterPrefix, master_lowest_opcode);
1751         f_print(fout, "#define %sHIGHEST_OPCODE %d\n", MasterPrefix, master_highest_opcode);
1752         f_print(fout, "#define %sNUMBER_OPCODES %d\n\n", MasterPrefix, master_no_of_opcodes);
1753         if (xflag) {
1754             f_print(fout, "#define %sNO_OF_STAT_FUNCS\t%d\n\n", MasterPrefix, no_of_stat_funcs_header[0]);
1755             f_print(fout, "AFS_RXGEN_EXPORT\n");
1756             f_print(fout, "extern const char *%sfunction_names[];\n\n", MasterPrefix);
1757         }
1758     } else {
1759         int i;
1760         for (i=0; i <= PackageIndex; i++) {
1761             f_print(fout, "\n/* Opcode-related useful stats for package: %s */\n", PackagePrefix[i]); 
1762             f_print(fout, "#define %sLOWEST_OPCODE   %d\n", PackagePrefix[i], lowest_opcode[i]);
1763             f_print(fout, "#define %sHIGHEST_OPCODE     %d\n", PackagePrefix[i], highest_opcode[i]);
1764             f_print(fout, "#define %sNUMBER_OPCODES     %d\n\n", PackagePrefix[i], no_of_opcodes[i]);
1765             if (xflag) {
1766                 f_print(fout, "#define %sNO_OF_STAT_FUNCS\t%d\n\n", PackagePrefix[i], no_of_stat_funcs_header[i]);
1767                 f_print(fout, "AFS_RXGEN_EXPORT\n");
1768                 f_print(fout, "extern const char *%sfunction_names[];\n\n", PackagePrefix[i]);
1769             }
1770         }
1771     }
1772 }
1773
1774
1775 void generate_multi_macros(definition *defp)
1776 {
1777     char *startname = SplitStart, *endname = SplitEnd;
1778     proc1_list *plist;
1779     int numofparams;
1780     int first = 0;
1781
1782     if (!hflag) return;
1783     if (!Multi_Init) {
1784         Multi_Init = 1;
1785         f_print(fout, "\n#include <rx/rx_multi.h>");
1786     }
1787     f_print(fout, "\n#define multi_%s%s(", PackagePrefix[PackageIndex],defp->pc.proc_name);
1788     for (plist = defp->pc.plists; plist; plist = plist->next) {
1789         if (plist->component_kind == DEF_PARAM) {
1790             if (!first) {
1791                 first = 1;
1792                 f_print(fout, "%s", plist->pl.param_name);
1793             } else {
1794                 f_print(fout, ", %s", plist->pl.param_name);
1795             }
1796         }
1797     }
1798     f_print(fout, ") \\\n");
1799     if (!startname) startname = "Start";
1800     if (!endname) endname = "End";
1801     f_print(fout, "\tmulti_Body(%s%s%s(multi_call", startname, PackagePrefix[PackageIndex], defp->pc.proc_name);
1802     do_split(defp, OUT, &numofparams, DEF_OUTPARAM, 0);
1803     for (plist = defp->pc.plists; plist; plist = plist->next) {
1804         if (plist->component_kind == DEF_PARAM)
1805             f_print(fout, ", %s", plist->pl.param_name);
1806     }
1807     do_split(defp, OUT, &numofparams, DEF_OUTPARAM, 1);
1808     f_print(fout, "), %s%s%s(multi_call", endname, PackagePrefix[PackageIndex], defp->pc.proc_name);
1809     do_split(defp, IN, &numofparams, DEF_INPARAM, 0);
1810     for (plist = defp->pc.plists; plist; plist = plist->next) {
1811         if (plist->component_kind == DEF_PARAM) {
1812             f_print(fout, ", %s", plist->pl.param_name);
1813         }
1814     }
1815     do_split(defp, IN, &numofparams, DEF_INPARAM, 1);
1816     f_print(fout, "))\n\n");
1817 }
1818
1819
1820 int IsRxgenToken(token *tokp)
1821 {
1822     if (tokp->kind == TOK_PACKAGE || tokp->kind == TOK_PREFIX ||
1823          tokp->kind == TOK_SPECIAL || tokp->kind == TOK_STARTINGOPCODE ||
1824          tokp->kind == TOK_SPLITPREFIX || tokp->kind == TOK_PROC ||
1825          tokp->kind == TOK_STATINDEX)
1826         return 1;
1827     return 0;
1828 }
1829
1830 int IsRxgenDefinition(definition *def)
1831 {
1832     if (def->def_kind == DEF_PACKAGE || def->def_kind == DEF_PREFIX || def->def_kind == DEF_SPECIAL || def->def_kind == DEF_STARTINGOPCODE || def->def_kind == DEF_SPLITPREFIX || def->def_kind == DEF_PROC)
1833         return 1;
1834     return 0;
1835 }