/* @(#)rpc_parse.c 1.1 87/11/04 3.9 RPCSRC */ /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape * media and as a part of the software program in whole or part. Users * may copy or modify Sun RPC without charge, but are not authorized * to license or distribute it to anyone else except as part of a product or * program developed by the user. * * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * Sun RPC is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 */ /* * rpc_parse.c, Parser for the RPC protocol compiler * Copyright (C) 1987 Sun Microsystems, Inc. */ #include #include #include #include #include "rpc_scan.h" #include "rpc_parse.h" #include "rpc_util.h" list *proc_defined[MAX_PACKAGES], *special_defined, *typedef_defined, *uniondef_defined, *complex_defined; char *SplitStart = NULL; char *SplitEnd = NULL; char *MasterPrefix = NULL; char *ServerPrefix = ""; char *PackagePrefix[MAX_PACKAGES]; char *PackageStatIndex[MAX_PACKAGES]; int no_of_stat_funcs = 0; /* * current function number in client interface * starts at 0 */ int no_of_stat_funcs_header[MAX_PACKAGES]; /* * Total number of functions in client * interface */ int no_of_opcodes[MAX_PACKAGES], master_no_of_opcodes = 0; int lowest_opcode[MAX_PACKAGES], master_lowest_opcode = 99999; int highest_opcode[MAX_PACKAGES], master_highest_opcode = 0; int master_opcodenumber = 99999; int opcodesnotallowed[MAX_PACKAGES]; int combinepackages = 0; int PackageIndex = -1; int PerProcCounter = 0; int Multi_Init = 0; int StatIndex = -1; /* * Character arrays to keep list of function names as we process the file */ char function_list[MAX_PACKAGES] [MAX_FUNCTIONS_PER_PACKAGE] [MAX_FUNCTION_NAME_LEN]; int function_list_index; /* static prototypes */ static void isdefined(definition * defp); static void def_struct(definition * defp); static void def_enum(definition * defp); static void def_const(definition * defp); static void def_union(definition * defp); static void def_typedef(definition * defp); static void get_declaration(declaration * dec, defkind dkind); static void get_type(char **prefixp, char **typep, defkind dkind); static void unsigned_dec(char **typep); static void def_package(definition * defp); static void def_prefix(definition * defp); static void def_statindex(definition * defp); static void def_startingopcode(definition * defp); static void def_split(definition * defp); static void customize_struct(definition * defp); static char *structname(char *name); static void def_special(declaration * dec, definition * defp); static void check_proc(definition * defp, token * tokp, int noname); static int InvalidConstant(char *name); static int opcodenum_is_defined(int opcode_num); static void analyze_ProcParams(definition * defp, token * tokp); static void generate_code(definition * defp, int proc_split_flag, int multi_flag); static void handle_split_proc(definition * defp, int multi_flag); static void do_split(definition * defp, int direction, int *numofparams, defkind param_kind, int restore_flag); static void hdle_param_tok(definition * defp, declaration * dec, token * tokp, defkind par_kind); static void get1_param_type(definition * defp, declaration * dec, char **param_type); static void get_param_type(definition * defp, declaration * dec, char **param_type, char **typename); static void cs_Proc_CodeGeneration(definition * defp, int split_flag, char *procheader); static void cs_ProcName_setup(definition * defp, char *procheader, int split_flag); static void cs_ProcParams_setup(definition * defp, int split_flag); static void cs_ProcMarshallInParams_setup(definition * defp, int split_flag); static void cs_ProcSendPacket_setup(definition * defp, int split_flag); static void cs_ProcUnmarshallOutParams_setup(definition * defp); static void cs_ProcTail_setup(definition * defp, int split_flag); static void ucs_ProcCallback_setup(definition * defp, char *cbheader); static void ucs_ProcName_setup(definition * defp, char *procheader, int split_flag); static void ucs_ProcParams_setup(definition * defp, int split_flag); static void ucs_ProcTail_setup(definition * defp, char *cbheader, int split_flag); static void ss_Proc_CodeGeneration(definition * defp); static void ss_ProcName_setup(definition * defp); static void ss_ProcParams_setup(definition * defp); static void ss_ProcSpecial_setup(definition * defp); static void ss_ProcUnmarshallInParams_setup(definition * defp); static void ss_ProcCallRealProc_setup(definition * defp); static void ss_ProcMarshallOutParams_setup(definition * defp); static void ss_ProcTail_setup(definition * defp); static int opcode_holes_exist(void); static void er_ProcDeclExterns_setup(void); static void er_ProcProcsArray_setup(void); static void er_ProcMainBody_setup(void); static void er_HeadofOldStyleProc_setup(void); static void er_HeadofOldStyleProc_setup2(void); static void er_BodyofOldStyleProc_setup(void); static void er_BodyofOldStyleProc_setup2(void); static void proc_er_case(definition * defp); static void er_TailofOldStyleProc_setup(void); static void er_TailofOldStyleProc_setup2(void); /* * return the next definition you see */ definition * get_definition(void) { definition *defp; token tok; defp = ALLOC(definition); memset(defp, 0, sizeof(definition)); get_token(&tok); switch (tok.kind) { case TOK_STRUCT: def_struct(defp); break; case TOK_UNION: def_union(defp); break; case TOK_TYPEDEF: def_typedef(defp); break; case TOK_ENUM: def_enum(defp); break; case TOK_CONST: def_const(defp); break; case TOK_EOF: free(defp); return NULL; case TOK_PACKAGE: def_package(defp); break; case TOK_PREFIX: def_prefix(defp); break; case TOK_STATINDEX: def_statindex(defp); break; case TOK_SPECIAL: { declaration dec; def_special(&dec, defp); break; } case TOK_STARTINGOPCODE: def_startingopcode(defp); break; case TOK_CUSTOMIZED: get_token(&tok); def_struct(defp); customize_struct(defp); break; case TOK_SPLITPREFIX: def_split(defp); break; case TOK_PROC: get_token(&tok); if (tok.kind == TOK_LPAREN) { unget_token(&tok); check_proc(defp, &tok, 1); } else check_proc(defp, &tok, 0); break; case TOK_IDENT: check_proc(defp, &tok, 0); break; case TOK_LPAREN: unget_token(&tok); check_proc(defp, &tok, 1); break; default: error("definition keyword expected"); } if (!IsRxgenToken(&tok)) { scan(TOK_SEMICOLON, &tok); isdefined(defp); } else pushed = 0; return (defp); } static void isdefined(definition * defp) { STOREVAL(&defined, defp); } static void def_struct(definition * defp) { token tok; declaration dec; decl_list *decls; decl_list **tailp; int special = 0; defp->def_kind = DEF_STRUCT; scan(TOK_IDENT, &tok); defp->def_name = tok.str; scan(TOK_LBRACE, &tok); tailp = &defp->def.st.decls; do { get_declaration(&dec, DEF_STRUCT); /* If a structure contains an array, then we're going * to need to be clever about freeing it */ if (dec.rel == REL_ARRAY) { special = 1; } decls = ALLOC(decl_list); decls->decl = dec; *tailp = decls; tailp = &decls->next; scan(TOK_SEMICOLON, &tok); peek(&tok); } while (tok.kind != TOK_RBRACE); get_token(&tok); *tailp = NULL; if (special) STOREVAL(&complex_defined, defp); } static void def_enum(definition * defp) { token tok; enumval_list *elist; enumval_list **tailp; defp->def_kind = DEF_ENUM; scan(TOK_IDENT, &tok); defp->def_name = tok.str; scan(TOK_LBRACE, &tok); tailp = &defp->def.en.vals; do { scan(TOK_IDENT, &tok); elist = ALLOC(enumval_list); elist->name = tok.str; elist->assignment = NULL; scan3(TOK_COMMA, TOK_RBRACE, TOK_EQUAL, &tok); if (tok.kind == TOK_EQUAL) { scan_num(&tok); elist->assignment = tok.str; scan2(TOK_COMMA, TOK_RBRACE, &tok); } *tailp = elist; tailp = &elist->next; } while (tok.kind != TOK_RBRACE); *tailp = NULL; } static void def_const(definition * defp) { token tok; defp->def_kind = DEF_CONST; scan(TOK_IDENT, &tok); defp->def_name = tok.str; scan(TOK_EQUAL, &tok); scan2(TOK_IDENT, TOK_STRCONST, &tok); defp->def.co = tok.str; } static void def_union(definition * defp) { token tok; declaration dec; case_list *cases; case_list **tailp; defp->def_kind = DEF_UNION; scan(TOK_IDENT, &tok); defp->def_name = tok.str; scan(TOK_SWITCH, &tok); scan(TOK_LPAREN, &tok); get_declaration(&dec, DEF_UNION); defp->def.un.enum_decl = dec; tailp = &defp->def.un.cases; scan(TOK_RPAREN, &tok); scan(TOK_LBRACE, &tok); scan(TOK_CASE, &tok); while (tok.kind == TOK_CASE) { scan(TOK_IDENT, &tok); cases = ALLOC(case_list); cases->case_name = tok.str; scan(TOK_COLON, &tok); get_declaration(&dec, DEF_UNION); cases->case_decl = dec; *tailp = cases; tailp = &cases->next; scan(TOK_SEMICOLON, &tok); scan3(TOK_CASE, TOK_DEFAULT, TOK_RBRACE, &tok); } *tailp = NULL; if (tok.kind == TOK_DEFAULT) { scan(TOK_COLON, &tok); get_declaration(&dec, DEF_UNION); defp->def.un.default_decl = ALLOC(declaration); *defp->def.un.default_decl = dec; scan(TOK_SEMICOLON, &tok); scan(TOK_RBRACE, &tok); } else { defp->def.un.default_decl = NULL; } } static void def_typedef(definition * defp) { declaration dec; memset(&dec, 0, sizeof(dec)); defp->def_kind = DEF_TYPEDEF; get_declaration(&dec, DEF_TYPEDEF); defp->def_name = dec.name; defp->def.ty.old_prefix = dec.prefix; defp->def.ty.old_type = dec.type; defp->def.ty.rel = dec.rel; defp->def.ty.array_max = dec.array_max; } static void get_declaration(declaration * dec, defkind dkind) { token tok; get_type(&dec->prefix, &dec->type, dkind); dec->rel = REL_ALIAS; if (streq(dec->type, "void")) { return; } scan2(TOK_STAR, TOK_IDENT, &tok); if (tok.kind == TOK_STAR) { dec->rel = REL_POINTER; scan(TOK_IDENT, &tok); } dec->name = tok.str; if (peekscan(TOK_LBRACKET, &tok)) { if (dec->rel == REL_POINTER) { error("no array-of-pointer declarations -- use typedef"); } dec->rel = REL_VECTOR; scan_num(&tok); dec->array_max = tok.str; scan(TOK_RBRACKET, &tok); } else if (peekscan(TOK_LANGLE, &tok)) { if (dec->rel == REL_POINTER) { error("no array-of-pointer declarations -- use typedef"); } dec->rel = REL_ARRAY; if (peekscan(TOK_RANGLE, &tok)) { if ((dkind == DEF_INPARAM) || (dkind == DEF_INOUTPARAM)) { error("input arrays must specify a max size"); } dec->array_max = "~0u"; /* unspecified size, use max */ } else { scan_num(&tok); dec->array_max = tok.str; scan(TOK_RANGLE, &tok); } } if (streq(dec->type, "opaque")) { if (dec->rel != REL_ARRAY && dec->rel != REL_VECTOR) { error("array declaration expected"); } } else if (streq(dec->type, "string")) { if (dec->rel != REL_ARRAY) { error(" variable-length array declaration expected"); } } } static void get_type(char **prefixp, char **typep, defkind dkind) { token tok; *prefixp = NULL; get_token(&tok); switch (tok.kind) { case TOK_IDENT: *typep = tok.str; break; case TOK_STRUCT: case TOK_ENUM: case TOK_UNION: *prefixp = tok.str; scan(TOK_IDENT, &tok); *typep = tok.str; break; case TOK_UNSIGNED: unsigned_dec(typep); break; case TOK_SHORT: *typep = "short"; (void)peekscan(TOK_INT, &tok); break; case TOK_INT32: *typep = "afs_int32"; (void)peekscan(TOK_INT, &tok); break; case TOK_VOID: if (dkind != DEF_UNION) { error("voids allowed only inside union definitions"); } *typep = tok.str; break; case TOK_STRING: case TOK_OPAQUE: case TOK_CHAR: case TOK_INT: case TOK_FLOAT: case TOK_DOUBLE: case TOK_BOOL: case TOK_AFSUUID: *typep = tok.str; break; default: error("expected type specifier"); } } static void unsigned_dec(char **typep) { token tok; peek(&tok); switch (tok.kind) { case TOK_CHAR: get_token(&tok); *typep = "u_char"; break; case TOK_SHORT: get_token(&tok); *typep = "u_short"; (void)peekscan(TOK_INT, &tok); break; case TOK_INT32: get_token(&tok); *typep = "afs_uint32"; (void)peekscan(TOK_INT, &tok); break; case TOK_INT: get_token(&tok); *typep = "u_int"; break; default: *typep = "u_int"; break; } } static void def_package(definition * defp) { token tok; defp->def_kind = DEF_PACKAGE; scan(TOK_IDENT, &tok); defp->def_name = tok.str; no_of_stat_funcs = 0; PackageIndex++; if (PackageIndex >= MAX_PACKAGES) error("Exceeded upper limit of package statements\n"); function_list_index = 0; PackagePrefix[PackageIndex] = tok.str; if (MasterPrefix == NULL) MasterPrefix = tok.str; no_of_opcodes[PackageIndex] = highest_opcode[PackageIndex] = opcodesnotallowed[PackageIndex] = 0; lowest_opcode[PackageIndex] = 99999; proc_defined[PackageIndex] = NULL; PackageStatIndex[PackageIndex] = NULL; } static void def_prefix(definition * defp) { token tok; defp->def_kind = DEF_PREFIX; scan(TOK_IDENT, &tok); defp->def_name = tok.str; ServerPrefix = tok.str; } static void def_statindex(definition * defp) { token tok; char *name; defp->def_kind = DEF_CONST; scan_num(&tok); if (PackageIndex < 0) error("'statindex' command must follow 'package' command!\n"); if (PackageStatIndex[PackageIndex]) error("Cannot have more then one 'statindex' per package!\n"); if (InvalidConstant(tok.str)) error("Index in 'statindex' command must be a constant!"); name = alloc(strlen(PackagePrefix[PackageIndex]) + strlen("STATINDEX") + 1); strcpy(name, PackagePrefix[PackageIndex]); strcat(name, "STATINDEX"); defp->def_name = name; defp->def.co = tok.str; PackageStatIndex[PackageIndex] = name; StatIndex = atoi(tok.str); } static void def_startingopcode(definition * defp) { token tok; defp->def_kind = DEF_STARTINGOPCODE; scan(TOK_IDENT, &tok); defp->def_name = tok.str; if (InvalidConstant(defp->def_name)) error("Opcode in 'startingopcode' command must be a constant!"); lowest_opcode[PackageIndex] = master_lowest_opcode = atoi(tok.str); if (lowest_opcode[PackageIndex] < 0 || lowest_opcode[PackageIndex] > 99999) error ("startingopcode number is out of bounds (must be >= 0 < 100000)"); master_opcodenumber = lowest_opcode[PackageIndex]; opcodesnotallowed[PackageIndex] = 1; } static void def_split(definition * defp) { token tok; defp->def_kind = DEF_SPLITPREFIX; do { get_token(&tok); switch (tok.kind) { case TOK_IN: scan(TOK_EQUAL, &tok); scan(TOK_IDENT, &tok); SplitStart = tok.str; break; case TOK_OUT: scan(TOK_EQUAL, &tok); scan(TOK_IDENT, &tok); SplitEnd = tok.str; break; case TOK_SEMICOLON: break; default: error("syntax error in the 'splitprefix' line"); } } while (tok.kind != TOK_SEMICOLON); if (!SplitStart && !SplitEnd) error("At least one param should be passed to 'splitprefix' cmd"); } static void customize_struct(definition * defp) { decl_list *listp; declaration *dec; definition *defp1 = ALLOC(definition); spec_list *specs, **tailp; defp->def_kind = DEF_CUSTOMIZED; defp1->def_kind = DEF_SPECIAL; tailp = &defp1->def.sd.specs; for (listp = defp->def.st.decls; listp; listp = listp->next) { dec = &listp->decl; if (streq(dec->type, "string") || (dec->rel == REL_POINTER)) { specs = ALLOC(spec_list); specs->sdef.string_name = dec->name; specs->sdef.string_value = defp->def_name; *tailp = specs; tailp = &specs->next; } } tailp = NULL; STOREVAL(&special_defined, defp1); } static char * structname(char *name) { static char namecontents[150]; char *pnt, *pnt1; strcpy(namecontents, name); pnt = namecontents; if (!strncmp(pnt, "struct", 6)) pnt += 6; while (isspace(*pnt)) pnt++; pnt1 = pnt; while (*pnt != ' ' && *pnt != '\0') pnt++; *pnt = '\0'; return pnt1; } static void def_special(declaration * dec, definition * defp) { char *typename; spec_list *specs, **tailp; token tok; defp->def_kind = DEF_SPECIAL; get_type(&dec->prefix, &dec->type, DEF_SPECIAL); dec->rel = REL_POINTER; scan(TOK_IDENT, &tok); tailp = &defp->def.sd.specs; do { specs = ALLOC(spec_list); specs->sdef.string_name = tok.str; get_param_type(defp, dec, &specs->sdef.string_value, &typename); *tailp = specs; tailp = &specs->next; scan2(TOK_COMMA, TOK_SEMICOLON, &tok); if (tok.kind == TOK_SEMICOLON) break; get_token(&tok); } while (tok.kind == TOK_IDENT); tailp = NULL; STOREVAL(&special_defined, defp); } proc1_list *Proc_list, **Proc_listp; static void check_proc(definition * defp, token * tokp, int noname) { token tok; int proc_split = 0; int proc_multi = 0; if (PackageIndex < 0) error("Procedure must be in a package!\n"); tokp->kind = TOK_PROC; defp->def_kind = DEF_PROC; if (noname) defp->pc.proc_name = ""; else defp->pc.proc_name = tokp->str; PerProcCounter = 0; defp->pc.proc_prefix = alloc(strlen(PackagePrefix[PackageIndex]) + 1); strcpy(defp->pc.proc_prefix, PackagePrefix[PackageIndex]); scan2(TOK_LPAREN, TOK_IDENT, &tok); defp->pc.proc_serverstub = NULL; if (tok.kind == TOK_IDENT) { defp->pc.proc_serverstub = tok.str; scan(TOK_LPAREN, &tok); } analyze_ProcParams(defp, &tok); defp->pc.proc_opcodenum = -1; scan4(TOK_SPLIT, TOK_MULTI, TOK_EQUAL, TOK_SEMICOLON, &tok); if (tok.kind == TOK_MULTI) { proc_multi = 1; defp->pc.multi_flag = 1; scan2(TOK_EQUAL, TOK_SEMICOLON, &tok); } else { defp->pc.multi_flag = 0; } if (tok.kind == TOK_SPLIT) { proc_split = 1; defp->pc.split_flag = 1; scan2(TOK_EQUAL, TOK_SEMICOLON, &tok); } else { defp->pc.split_flag = 0; } if (tok.kind == TOK_EQUAL) { if (opcodesnotallowed[PackageIndex]) error("Opcode assignment isn't allowed here!"); scan_num(&tok); if (InvalidConstant(tok.str)) error("Illegal Opcode assignment (Must be a constant opcode!)"); if (opcodenum_is_defined(atoi(tok.str))) error("The opcode number is already used by a previous proc"); defp->pc.proc_opcodename = tok.str; defp->pc.proc_opcodenum = atoi(tok.str); if (defp->pc.proc_opcodenum < lowest_opcode[PackageIndex]) lowest_opcode[PackageIndex] = defp->pc.proc_opcodenum; if (defp->pc.proc_opcodenum < master_lowest_opcode) master_lowest_opcode = defp->pc.proc_opcodenum; if (defp->pc.proc_opcodenum > highest_opcode[PackageIndex]) highest_opcode[PackageIndex] = defp->pc.proc_opcodenum; if (defp->pc.proc_opcodenum > master_highest_opcode) master_highest_opcode = defp->pc.proc_opcodenum; scan(TOK_SEMICOLON, &tok); } else { if (master_opcodenumber == 99999) master_opcodenumber = 0; defp->pc.proc_opcodenum = master_opcodenumber++; if (defp->pc.proc_opcodenum < lowest_opcode[PackageIndex]) lowest_opcode[PackageIndex] = defp->pc.proc_opcodenum; if (defp->pc.proc_opcodenum > highest_opcode[PackageIndex]) highest_opcode[PackageIndex] = defp->pc.proc_opcodenum; if (defp->pc.proc_opcodenum > master_highest_opcode) master_highest_opcode = defp->pc.proc_opcodenum; opcodesnotallowed[PackageIndex] = 1; /* force it */ } no_of_opcodes[PackageIndex]++, master_no_of_opcodes++; if (proc_multi) { generate_code(defp, 0, 1); if (Cflag || cflag) { generate_code(defp, 1, 1); } generate_multi_macros(defp); } else { generate_code(defp, proc_split, 0); } if (function_list_index >= MAX_FUNCTIONS_PER_INTERFACE) { error("too many functions in interface, " "increase MAX_FUNCTIONS_PER_INTERFACE"); } sprintf(function_list[PackageIndex][function_list_index], "%s%s%s", prefix, PackagePrefix[PackageIndex], defp->pc.proc_name); function_list_index++; defp->statindex = no_of_stat_funcs; no_of_stat_funcs_header[PackageIndex]++; no_of_stat_funcs++; *Proc_listp = NULL; } #define LEGALNUMS "0123456789" static int InvalidConstant(char *name) { char *map; int slen; map = LEGALNUMS; slen = (int)strlen(name); return (slen != strspn(name, map)); } static int opcodenum_is_defined(int opcode_num) { list *listp; definition *defp; for (listp = proc_defined[PackageIndex]; listp != NULL; listp = listp->next) { defp = (definition *) listp->val; if (opcode_num == defp->pc.proc_opcodenum) return 1; } return 0; } static void analyze_ProcParams(definition * defp, token * tokp) { declaration dec; decl_list *decls, **tailp; Proc_listp = &defp->pc.plists; tailp = &defp->def.st.decls; do { get_token(tokp); Proc_list = ALLOC(proc1_list); memset(Proc_list, 0, sizeof(proc1_list)); Proc_list->pl.param_flag = 0; switch (tokp->kind) { case TOK_IN: hdle_param_tok(defp, &dec, tokp, DEF_INPARAM); break; case TOK_OUT: hdle_param_tok(defp, &dec, tokp, DEF_OUTPARAM); break; case TOK_INOUT: hdle_param_tok(defp, &dec, tokp, DEF_INOUTPARAM); break; case TOK_RPAREN: break; default: unget_token(tokp); hdle_param_tok(defp, &dec, tokp, DEF_NULL); break; } *Proc_listp = Proc_list; Proc_listp = &Proc_list->next; decls = ALLOC(decl_list); memset(decls, 0, sizeof(decl_list)); if (tokp->kind != TOK_RPAREN) decls->decl = dec; *tailp = decls; tailp = &decls->next; } while (tokp->kind != TOK_RPAREN); *tailp = NULL; } static void generate_code(definition * defp, int proc_split_flag, int multi_flag) { if (proc_split_flag) handle_split_proc(defp, multi_flag); else { if (Cflag || cflag) { cs_Proc_CodeGeneration(defp, 0, ""); } if (Sflag || cflag) ss_Proc_CodeGeneration(defp); } if (Sflag || (cflag && xflag && !proc_split_flag) || hflag) STOREVAL(&proc_defined[PackageIndex], defp); } static void handle_split_proc(definition * defp, int multi_flag) { char *startname = SplitStart, *endname = SplitEnd; int numofparams = 0; if (!startname) startname = "Start"; if (!endname) endname = "End"; if (Cflag || cflag) { if (!cflag) { do_split(defp, OUT, &numofparams, DEF_OUTPARAM, 0); } cs_Proc_CodeGeneration(defp, 1, startname); if (!cflag) { do_split(defp, OUT, &numofparams, DEF_OUTPARAM, 1); do_split(defp, IN, &numofparams, DEF_INPARAM, 0); } cs_Proc_CodeGeneration(defp, (multi_flag ? 3 : 2), endname); if (!cflag) { do_split(defp, IN, &numofparams, DEF_INPARAM, 1); } } if (Sflag || cflag) ss_Proc_CodeGeneration(defp); } static void do_split(definition * defp, int direction, int *numofparams, defkind param_kind, int restore_flag) { proc1_list *plist; if (restore_flag) { defp->pc.paramtypes[direction] = *numofparams; for (plist = defp->pc.plists; plist; plist = plist->next) { if (plist->component_kind == DEF_NULL && plist->pl.param_kind == param_kind) plist->component_kind = DEF_PARAM; } } else { *numofparams = defp->pc.paramtypes[direction]; defp->pc.paramtypes[direction] = 0; for (plist = defp->pc.plists; plist; plist = plist->next) { if (plist->component_kind == DEF_PARAM && plist->pl.param_kind == param_kind) plist->component_kind = DEF_NULL; } } } static void hdle_param_tok(definition * defp, declaration * dec, token * tokp, defkind par_kind) { static defkind last_param_kind = DEF_NULL; if (par_kind == DEF_NULL) Proc_list->pl.param_kind = last_param_kind; else Proc_list->pl.param_kind = par_kind; last_param_kind = Proc_list->pl.param_kind; defp->pc.paramtypes[(int)last_param_kind]++; Proc_list->component_kind = DEF_PARAM; Proc_list->code = alloc(250); Proc_list->scode = alloc(250); get_declaration(dec, par_kind); Proc_list->pl.param_name = dec->name; get1_param_type(defp, dec, &Proc_list->pl.param_type); print_param(dec); scan2(TOK_COMMA, TOK_RPAREN, tokp); if (tokp->kind == TOK_COMMA) peek(tokp); } static void get1_param_type(definition * defp, declaration * dec, char **param_type) { char typecontents[100]; if (streq(dec->type, "string")) { *param_type = "char *"; } else { if (dec->prefix) { strcpy(typecontents, dec->prefix); strcat(typecontents, " "); strcat(typecontents, dec->type); strcat(typecontents, " *"); } else if (dec->rel == REL_POINTER) { strcpy(typecontents, dec->type); strcat(typecontents, " *"); } else strcpy(typecontents, dec->type); *param_type = alloc(100); strcpy(*param_type, typecontents); } } static void get_param_type(definition * defp, declaration * dec, char **param_type, char **typename) { char typecontents[100]; if (streq(dec->type, "string")) { *typename = "wrapstring"; *param_type = "char *"; } else { *typename = dec->type; if (dec->prefix) { strcpy(typecontents, dec->prefix); strcat(typecontents, " "); strcat(typecontents, dec->type); strcat(typecontents, " *"); dec->rel = REL_POINTER; } else if (dec->rel == REL_POINTER) { strcpy(typecontents, dec->type); strcat(typecontents, " *"); } else strcpy(typecontents, dec->type); *param_type = alloc(100); strcpy(*param_type, typecontents); } } static void cs_Proc_CodeGeneration(definition * defp, int split_flag, char *procheader) { defp->can_fail = 0; cs_ProcName_setup(defp, procheader, split_flag); if (!cflag) { cs_ProcParams_setup(defp, split_flag); cs_ProcMarshallInParams_setup(defp, split_flag); if (split_flag != 1) { cs_ProcSendPacket_setup(defp, split_flag); cs_ProcUnmarshallOutParams_setup(defp); } cs_ProcTail_setup(defp, split_flag); } if (!kflag && !split_flag && uflag) { if (!cflag) { ucs_ProcCallback_setup(defp, "ubik_call_"); } ucs_ProcName_setup(defp, "ubik_", split_flag); if (!cflag) { ucs_ProcParams_setup(defp, split_flag); ucs_ProcTail_setup(defp, "ubik_call_", split_flag); } } } static void cs_ProcName_setup(definition * defp, char *procheader, int split_flag) { proc1_list *plist; char *first_arg; if (ansic_flag) { if (split_flag) { first_arg = "struct rx_call *z_call"; } else { first_arg = "struct rx_connection *z_conn"; } } else { if (split_flag) { first_arg = "z_call"; } else { first_arg = "z_conn"; } } if (!cflag) { f_print(fout, "int %s%s%s%s(%s", procheader, prefix, PackagePrefix[PackageIndex], defp->pc.proc_name, first_arg); } if ((strlen(procheader) + strlen(prefix) + strlen(PackagePrefix[PackageIndex]) + strlen(defp->pc.proc_name)) >= MAX_FUNCTION_NAME_LEN) { error("function name is too long, increase MAX_FUNCTION_NAME_LEN"); } if (!cflag) { for (plist = defp->pc.plists; plist; plist = plist->next) { if (plist->component_kind == DEF_PARAM) { f_print(fout, ","); if (ansic_flag) { if (plist->pl.param_kind == DEF_INPARAM && strcmp(plist->pl.param_type, "char *") == 0) { f_print(fout, "const "); } if (plist->pl.param_flag & OUT_STRING) { f_print(fout, "%s *%s", plist->pl.param_type, plist->pl.param_name); } else { f_print(fout, "%s %s", plist->pl.param_type, plist->pl.param_name); } } else { f_print(fout, " %s", plist->pl.param_name); plist->pl.param_flag &= ~PROCESSED_PARAM; } } } f_print(fout, ")\n"); } } static void cs_ProcParams_setup(definition * defp, int split_flag) { proc1_list *plist, *plist1; if (ansic_flag) return; if (!split_flag) f_print(fout, "\tstruct rx_connection *z_conn;\n"); if (split_flag) { f_print(fout, "\tstruct rx_call *z_call;\n"); } for (plist = defp->pc.plists; plist; plist = plist->next) { if (plist->component_kind == DEF_PARAM && !(plist->pl.param_flag & PROCESSED_PARAM)) { if (plist->pl.param_flag & OUT_STRING) { f_print(fout, "\t%s *%s", plist->pl.param_type, plist->pl.param_name); } else { f_print(fout, "\t%s %s", plist->pl.param_type, plist->pl.param_name); } plist->pl.param_flag |= PROCESSED_PARAM; for (plist1 = defp->pc.plists; plist1; plist1 = plist1->next) { if ((plist1->component_kind == DEF_PARAM) && streq(plist->pl.param_type, plist1->pl.param_type) && !(plist1->pl.param_flag & PROCESSED_PARAM)) { char *star = ""; char *pntr = strchr(plist1->pl.param_type, '*'); if (pntr) star = "*"; if (plist1->pl.param_flag & OUT_STRING) { f_print(fout, ", *%s%s", star, plist1->pl.param_name); } else { f_print(fout, ", %s%s", star, plist1->pl.param_name); } plist1->pl.param_flag |= PROCESSED_PARAM; } } f_print(fout, ";\n"); } } } static void cs_ProcMarshallInParams_setup(definition * defp, int split_flag) { int noofparams, i = 0; proc1_list *plist; decl_list *dl; int noofallparams = defp->pc.paramtypes[IN] + defp->pc.paramtypes[INOUT] + defp->pc.paramtypes[OUT]; f_print(fout, "{\n"); if (!split_flag) f_print(fout, "\tstruct rx_call *z_call = rx_NewCall(z_conn);\n"); if ((!split_flag) || (split_flag == 1)) { if (opcodesnotallowed[PackageIndex]) { f_print(fout, "\tstatic int z_op = %d;\n", defp->pc.proc_opcodenum); } else { f_print(fout, "\tstatic int z_op = %s;\n", defp->pc.proc_opcodename); } } f_print(fout, "\tint z_result;\n"); if (!(split_flag > 1) || (noofallparams != 0)) { f_print(fout, "\tXDR z_xdrs;\n"); } if ((!split_flag) || (split_flag == 1)) { f_print(fout, "\txdrrx_create(&z_xdrs, z_call, XDR_ENCODE);\n"); f_print(fout, "\n\t/* Marshal the arguments */\n"); f_print(fout, "\tif ((!xdr_int(&z_xdrs, &z_op))"); noofparams = defp->pc.paramtypes[IN] + defp->pc.paramtypes[INOUT]; for (plist = defp->pc.plists, dl = defp->def.st.decls; plist; plist = plist->next, dl = dl->next) { if (plist->component_kind == DEF_PARAM && (plist->pl.param_kind == DEF_INPARAM || plist->pl.param_kind == DEF_INOUTPARAM)) { f_print(fout, "\n\t || (!%s)", plist->code); if (++i == noofparams) { f_print(fout, ") {\n\t\tz_result = RXGEN_CC_MARSHAL;\n\t\tgoto fail;\n\t}\n\n"); defp->can_fail = 1; } } } if (!i) { f_print(fout, ") {\n\t\tz_result = RXGEN_CC_MARSHAL;\n\t\tgoto fail;\n\t}\n\n"); defp->can_fail = 1; } } } static void cs_ProcSendPacket_setup(definition * defp, int split_flag) { int noofoutparams = defp->pc.paramtypes[INOUT] + defp->pc.paramtypes[OUT]; if (noofoutparams) { f_print(fout, "\t/* Un-marshal the reply arguments */\n"); if (split_flag) { f_print(fout, "\txdrrx_create(&z_xdrs, z_call, XDR_DECODE);\n"); } else { f_print(fout, "\tz_xdrs.x_op = XDR_DECODE;\n"); } } } static void cs_ProcUnmarshallOutParams_setup(definition * defp) { int noofparams, i; proc1_list *plist; decl_list *dl; noofparams = defp->pc.paramtypes[INOUT] + defp->pc.paramtypes[OUT]; if (noofparams) for (plist = defp->pc.plists, dl = defp->def.st.decls, i = 0; plist; plist = plist->next, dl = dl->next) { if (plist->component_kind == DEF_PARAM && (plist->pl.param_kind == DEF_OUTPARAM || plist->pl.param_kind == DEF_INOUTPARAM)) { if (!i) { f_print(fout, "\tif ((!%s)", plist->code); } else { f_print(fout, "\n\t || (!%s)", plist->code); } if (++i == noofparams) { f_print(fout, ") {\n\t\tz_result = RXGEN_CC_UNMARSHAL;\n\t\tgoto fail;\n\t}\n\n"); defp->can_fail = 1; } } } } static void cs_ProcTail_setup(definition * defp, int split_flag) { f_print(fout, "\tz_result = RXGEN_SUCCESS;\n"); if (defp->can_fail) { f_print(fout, "fail:\n"); } if (!split_flag) { f_print(fout, "\tz_result = rx_EndCall(z_call, z_result);\n"); } if (xflag && split_flag != 1) { f_print(fout, "\tif (rx_enable_stats) {\n"); if (PackageStatIndex[PackageIndex]) { f_print(fout, "\t rx_RecordCallStatistics(z_call, %s,\n", PackageStatIndex[PackageIndex]); } else { f_print(fout, "\t rx_RecordCallStatistics(z_call, \n" "\t\t(((afs_uint32)(ntohs(rx_ServiceIdOf(rx_ConnectionOf(z_call))) << 16)) |\n" "\t\t((afs_uint32)ntohs(rx_PortOf(rx_PeerOf(rx_ConnectionOf(z_call)))))),\n"); } f_print(fout, "\t\t%d, %sNO_OF_STAT_FUNCS, 1);\n", no_of_stat_funcs, PackagePrefix[PackageIndex]); f_print(fout, "\t}\n\n"); } f_print(fout, "\treturn z_result;\n}\n\n"); } static void ss_Proc_CodeGeneration(definition * defp) { extern char zflag; if (zflag) defp->can_fail = 0; else defp->can_fail = 1; ss_ProcName_setup(defp); if (!cflag) { ss_ProcParams_setup(defp); ss_ProcSpecial_setup(defp); ss_ProcUnmarshallInParams_setup(defp); ss_ProcCallRealProc_setup(defp); ss_ProcMarshallOutParams_setup(defp); ss_ProcTail_setup(defp); } } static void ss_ProcName_setup(definition * defp) { proc1_list *plist; if ((strlen(prefix) + strlen(PackagePrefix[PackageIndex]) + strlen(defp->pc.proc_name)) >= MAX_FUNCTION_NAME_LEN) { error("function name is too long, increase MAX_FUNCTION_NAME_LEN"); } if (!cflag) { f_print(fout, "static afs_int32 _%s%s%s(", prefix, PackagePrefix[PackageIndex], defp->pc.proc_name); f_print(fout, "struct rx_call *z_call, XDR *z_xdrs)\n{\n"); f_print(fout, "\t" "afs_int32 z_result;\n"); for (plist = defp->pc.plists; plist; plist = plist->next) if (plist->component_kind == DEF_PARAM) { plist->pl.param_flag &= ~(PROCESSED_PARAM); plist->pl.string_name = NULL; } } } static void ss_ProcParams_setup(definition * defp) { proc1_list *plist, *plist1; list *listp; definition *defp1; for (plist = defp->pc.plists; plist; plist = plist->next) { if ((plist->component_kind == DEF_PARAM) && !(plist->pl.param_flag & PROCESSED_PARAM)) { if (plist->pl.param_flag & INDIRECT_PARAM) { char pres = '\0', *pntr = strchr(plist->pl.param_type, '*'); if (pntr) { --pntr; pres = *pntr; *pntr = (char)0; } f_print(fout, "\t%s %s", plist->pl.param_type, plist->pl.param_name); if (pntr) *pntr = pres; } else if (strchr(plist->pl.param_type, '*') == 0) { f_print(fout, "\t%s %s", plist->pl.param_type, plist->pl.param_name); } else { plist->pl.param_flag |= FREETHIS_PARAM; f_print(fout, "\t%s %s=(%s)0", plist->pl.param_type, plist->pl.param_name, plist->pl.param_type); } plist->pl.param_flag |= PROCESSED_PARAM; for (plist1 = defp->pc.plists; plist1; plist1 = plist1->next) { if ((plist1->component_kind == DEF_PARAM) && streq(plist->pl.param_type, plist1->pl.param_type) && !(plist1->pl.param_flag & PROCESSED_PARAM)) { if (plist1->pl.param_flag & INDIRECT_PARAM) { f_print(fout, ", %s", plist1->pl.param_name); } else if (strchr(plist1->pl.param_type, '*') == 0) { f_print(fout, ", %s", plist1->pl.param_name); } else { plist1->pl.param_flag |= FREETHIS_PARAM; f_print(fout, ", *%s=(%s)0", plist1->pl.param_name, plist1->pl.param_type); } plist1->pl.param_flag |= PROCESSED_PARAM; } } f_print(fout, ";\n"); } } for (listp = typedef_defined; listp != NULL; listp = listp->next) { defp1 = (definition *) listp->val; for (plist = defp->pc.plists; plist; plist = plist->next) { if (plist->component_kind == DEF_PARAM && (plist->pl.param_kind == DEF_OUTPARAM || plist->pl.param_kind == DEF_INOUTPARAM) && !(plist->pl.param_flag & FREETHIS_PARAM)) { if (streq(defp1->def_name, structname(plist->pl.param_type))) { switch (defp1->pc.rel) { case REL_ARRAY: case REL_POINTER: default: break; } } } } } fprintf(fout, "\n"); } static void ss_ProcSpecial_setup(definition * defp) { proc1_list *plist; definition *defp1; list *listp; for (listp = special_defined; listp != NULL; listp = listp->next) { defp1 = (definition *) listp->val; for (plist = defp->pc.plists; plist; plist = plist->next) { if (plist->component_kind == DEF_PARAM && (plist->pl.param_kind == DEF_INPARAM || plist->pl.param_kind == DEF_INOUTPARAM)) { spec_list *spec = defp1->def.sd.specs; char string[40]; strcpy(string, structname(spec->sdef.string_value)); if (streq(string, structname(plist->pl.param_type))) { plist->pl.string_name = spec->sdef.string_name; plist->pl.param_flag |= FREETHIS_PARAM; } } } } for (listp = typedef_defined; listp != NULL; listp = listp->next) { defp1 = (definition *) listp->val; for (plist = defp->pc.plists; plist; plist = plist->next) { if (plist->component_kind == DEF_PARAM) { if (streq(defp1->def_name, structname(plist->pl.param_type))) { plist->pl.param_flag |= FREETHIS_PARAM; switch (defp1->pc.rel) { case REL_ARRAY: plist->pl.string_name = alloc(40); if (brief_flag) { s_print(plist->pl.string_name, "val"); } else { s_print(plist->pl.string_name, "%s_val", defp1->def_name); } break; case REL_POINTER: plist->pl.string_name = NULL; break; default: break; } } } } } for (listp = complex_defined; listp != NULL; listp = listp->next) { defp1 = (definition *) listp->val; for (plist = defp->pc.plists; plist; plist = plist->next) { if (plist->component_kind == DEF_PARAM) { if (streq(defp1->def_name, structname(plist->pl.param_type))) { plist->pl.param_flag |= FREETHIS_PARAM; } } } } for (plist = defp->pc.plists; plist; plist = plist->next) { if (plist->component_kind == DEF_PARAM) { fprintf(fout, "\n\tmemset(&%s, 0, sizeof(%s));", plist->pl.param_name, plist->pl.param_name); } } f_print(fout, "\n"); } static void ss_ProcUnmarshallInParams_setup(definition * defp) { int noofparams, noofoutparams, i; proc1_list *plist; noofparams = defp->pc.paramtypes[IN] + defp->pc.paramtypes[INOUT]; noofoutparams = defp->pc.paramtypes[INOUT] + defp->pc.paramtypes[OUT]; for (plist = defp->pc.plists, i = 0; plist; plist = plist->next) { if (plist->component_kind == DEF_PARAM && (plist->pl.param_kind == DEF_INPARAM || plist->pl.param_kind == DEF_INOUTPARAM)) { if (!i) { f_print(fout, "\n\tif ((!%s)", (plist->scode ? plist->scode : plist->code)); } else { f_print(fout, "\n\t || (!%s)", (plist->scode ? plist->scode : plist->code)); } if (++i == noofparams) { if (!noofoutparams) { f_print(fout, ") {\n"); } else { f_print(fout, ") {\n"); } f_print(fout, "\t\tz_result = RXGEN_SS_UNMARSHAL;\n\t\tgoto fail;\n\t}\n\n"); defp->can_fail = 1; } } } } static void ss_ProcCallRealProc_setup(definition * defp) { extern char zflag; proc1_list *plist; f_print(fout, "\tz_result = %s%s%s%s(z_call", prefix, ServerPrefix, PackagePrefix[PackageIndex], defp->pc.proc_name); for (plist = defp->pc.plists; plist; plist = plist->next) { if (plist->component_kind == DEF_PARAM) { if (plist->pl.param_flag & INDIRECT_PARAM) { f_print(fout, ", &%s", plist->pl.param_name); } else { if (plist->pl.param_flag & OUT_STRING) { f_print(fout, ", &%s", plist->pl.param_name); } else { f_print(fout, ", %s", plist->pl.param_name); } } } } f_print(fout, ");\n"); if (zflag) { f_print(fout, "\tif (z_result)\n\t\treturn z_result;\n"); } else { f_print(fout, "\tif (z_result)\n\t\tgoto fail;\n"); } } static void ss_ProcMarshallOutParams_setup(definition * defp) { proc1_list *plist; int noofparams, i; noofparams = defp->pc.paramtypes[INOUT] + defp->pc.paramtypes[OUT]; if (noofparams) f_print(fout, "\tz_xdrs->x_op = XDR_ENCODE;\n"); if (noofparams) { for (plist = defp->pc.plists, i = 0; plist; plist = plist->next) { if (plist->component_kind == DEF_PARAM && (plist->pl.param_kind == DEF_OUTPARAM || plist->pl.param_kind == DEF_INOUTPARAM)) { if (!i) { f_print(fout, "\tif ((!%s)", (plist->scode ? plist->scode : plist->code)); } else { f_print(fout, "\n\t || (!%s)", (plist->scode ? plist->scode : plist->code)); } if (++i == noofparams) { f_print(fout, ")\n\t\tz_result = RXGEN_SS_MARSHAL;\n"); } } } } } static void ss_ProcTail_frees(char *xdrfunc, int *somefrees) { if (!*somefrees) { f_print(fout, "\tz_xdrs->x_op = XDR_FREE;\n"); f_print(fout, "\tif ((!%s)", xdrfunc); *somefrees = 1; } else { f_print(fout, "\n\t || (!%s)", xdrfunc); } } static void ss_ProcTail_setup(definition * defp) { proc1_list *plist; definition *defp1; list *listp; int somefrees = 0; if (defp->can_fail) { f_print(fout, "fail:\n"); } for (plist = defp->pc.plists; plist; plist = plist->next) { if (plist->component_kind == DEF_PARAM && (plist->pl.param_flag & FREETHIS_PARAM)) ss_ProcTail_frees(plist->scode, &somefrees); } for (listp = typedef_defined; listp != NULL; listp = listp->next) { defp1 = (definition *) listp->val; for (plist = defp->pc.plists; plist; plist = plist->next) { if (plist->component_kind == DEF_PARAM && (plist->pl.param_kind == DEF_OUTPARAM || plist->pl.param_kind == DEF_INOUTPARAM) && !(plist->pl.param_flag & FREETHIS_PARAM)) { if (streq(defp1->def_name, structname(plist->pl.param_type))) { switch (defp1->pc.rel) { case REL_ARRAY: case REL_POINTER: ss_ProcTail_frees(plist->scode, &somefrees); break; default: break; } } } } } for (listp = uniondef_defined; listp != NULL; listp = listp->next) { defp1 = (definition *) listp->val; for (plist = defp->pc.plists; plist; plist = plist->next) { if (plist->component_kind == DEF_PARAM && (plist->pl.param_kind == DEF_OUTPARAM || plist->pl.param_kind == DEF_INOUTPARAM) && !(plist->pl.param_flag & FREETHIS_PARAM)) { if (streq(defp1->def_name, structname(plist->pl.param_type))) { if (plist->pl.param_flag & INDIRECT_PARAM) { ss_ProcTail_frees(plist->scode, &somefrees); } } } } } if (somefrees) { f_print(fout, ")\n"); f_print(fout, "\t\tz_result = RXGEN_SS_XDRFREE;\n\n"); } if (xflag) { f_print(fout, "\tif (rx_enable_stats) {\n"); f_print(fout, "\t rx_RecordCallStatistics(z_call,"); if (PackageStatIndex[PackageIndex]) { f_print(fout, " %s,\n", PackageStatIndex[PackageIndex]); } else { f_print(fout, "\n\t\t(((afs_uint32)(ntohs(rx_ServiceIdOf(rx_ConnectionOf(z_call))) << 16)) |\n" "\t\t((afs_uint32)ntohs(rx_ServiceOf(rx_ConnectionOf(z_call))->servicePort))),\n"); } f_print(fout, "\t\t%d, %sNO_OF_STAT_FUNCS, 0);\n", no_of_stat_funcs, PackagePrefix[PackageIndex]); f_print(fout, "\t}\n\n"); } f_print(fout, "\treturn z_result;\n"); f_print(fout, "}\n\n"); } static void ucs_ProcCallback_setup(definition * defp, char *cbheader) { proc1_list *plist; int any_params = 0; for (plist = defp->pc.plists; plist; plist = plist->next) { if (plist->component_kind == DEF_PARAM) { any_params = 1; break; } } if (any_params) { f_print(fout, "struct args_%s%s%s {\n", prefix, PackagePrefix[PackageIndex], defp->pc.proc_name); for (plist = defp->pc.plists; plist; plist = plist->next) { if (plist->component_kind == DEF_PARAM) { f_print(fout, "\t"); if (plist->pl.param_kind == DEF_INPARAM && strcmp(plist->pl.param_type, "char *") == 0) { f_print(fout, "const "); } if ((plist->pl.param_flag & OUT_STRING) != 0) { f_print(fout, "%s *%s", plist->pl.param_type, plist->pl.param_name); } else { f_print(fout, "%s %s", plist->pl.param_type, plist->pl.param_name); } f_print(fout, ";\n"); } } f_print(fout, "};\n"); } f_print(fout, "static int\n" "%s%s%s%s(struct ubik_callrock_info *info, void *z_rock)\n" "{\n", cbheader, prefix, PackagePrefix[PackageIndex], defp->pc.proc_name); if (any_params) { f_print(fout, "\tstruct args_%s%s%s *z_args = z_rock;\n", prefix, PackagePrefix[PackageIndex], defp->pc.proc_name); } f_print(fout, "\treturn %s%s%s(info->conn", prefix, PackagePrefix[PackageIndex], defp->pc.proc_name); for (plist = defp->pc.plists; plist; plist = plist->next) { if (plist->component_kind == DEF_PARAM) { f_print(fout, ",\n\t\t\tz_args->%s", plist->pl.param_name); } } f_print(fout, ");\n" "}\n"); } static void ucs_ProcName_setup(definition * defp, char *procheader, int split_flag) { proc1_list *plist; if (!cflag) { if (ansic_flag) { f_print(fout, "int %s%s%s%s(struct ubik_client *aclient, afs_int32 aflags", procheader, prefix, PackagePrefix[PackageIndex], defp->pc.proc_name); } else { f_print(fout, "int %s%s%s%s(aclient, aflags", procheader, prefix, PackagePrefix[PackageIndex], defp->pc.proc_name); } } if ((strlen(procheader) + strlen(prefix) + strlen(PackagePrefix[PackageIndex]) + strlen(defp->pc.proc_name)) >= MAX_FUNCTION_NAME_LEN) { error("function name is too long, increase MAX_FUNCTION_NAME_LEN"); } if (!cflag) { for (plist = defp->pc.plists; plist; plist = plist->next) { if (plist->component_kind == DEF_PARAM) { f_print(fout, ","); if (ansic_flag) { if (plist->pl.param_kind == DEF_INPARAM && strcmp(plist->pl.param_type, "char *") == 0) { f_print(fout, "const "); } if (plist->pl.param_flag & OUT_STRING) { f_print(fout, "%s *%s", plist->pl.param_type, plist->pl.param_name); } else { f_print(fout, "%s %s", plist->pl.param_type, plist->pl.param_name); } } else { plist->pl.param_flag &= ~PROCESSED_PARAM; f_print(fout, " %s", plist->pl.param_name); } } } f_print(fout, ")\n"); } } static void ucs_ProcParams_setup(definition * defp, int split_flag) { proc1_list *plist, *plist1; if (ansic_flag) return; f_print(fout, "\tstruct ubik_client *aclient;\n\tafs_int32 aflags;\n"); for (plist = defp->pc.plists; plist; plist = plist->next) { if (plist->component_kind == DEF_PARAM && !(plist->pl.param_flag & PROCESSED_PARAM)) { if (plist->pl.param_flag & OUT_STRING) { f_print(fout, "\t%s *%s", plist->pl.param_type, plist->pl.param_name); } else { f_print(fout, "\t%s %s", plist->pl.param_type, plist->pl.param_name); } plist->pl.param_flag |= PROCESSED_PARAM; for (plist1 = defp->pc.plists; plist1; plist1 = plist1->next) { if ((plist1->component_kind == DEF_PARAM) && streq(plist->pl.param_type, plist1->pl.param_type) && !(plist1->pl.param_flag & PROCESSED_PARAM)) { char *star = ""; char *pntr = strchr(plist1->pl.param_type, '*'); if (pntr) star = "*"; if (plist1->pl.param_flag & OUT_STRING) { f_print(fout, ", *%s%s", star, plist1->pl.param_name); } else { f_print(fout, ", %s%s", star, plist1->pl.param_name); } plist1->pl.param_flag |= PROCESSED_PARAM; } } f_print(fout, ";\n"); } } } static void ucs_ProcTail_setup(definition * defp, char *cbheader, int split_flag) { proc1_list *plist; int any_params = 0; f_print(fout, "{\n"); for (plist = defp->pc.plists; plist; plist = plist->next) { if (plist->component_kind == DEF_PARAM) { any_params = 1; break; } } if (any_params) { f_print(fout, "\tstruct args_%s%s%s args;\n", prefix, PackagePrefix[PackageIndex], defp->pc.proc_name); f_print(fout, "\tmemset(&args, 0, sizeof(args));\n\n"); for (plist = defp->pc.plists; plist; plist = plist->next) { if (plist->component_kind == DEF_PARAM) { plist->pl.param_flag &= ~PROCESSED_PARAM; f_print(fout, "\targs.%s = %s;\n", plist->pl.param_name, plist->pl.param_name); } } f_print(fout, "\n\treturn ubik_CallRock(aclient, aflags, %s%s%s%s, &args);\n", cbheader, prefix, PackagePrefix[PackageIndex], defp->pc.proc_name); } else { f_print(fout, "\treturn ubik_CallRock(aclient, aflags, %s%s%s%s, NULL);\n", cbheader, prefix, PackagePrefix[PackageIndex], defp->pc.proc_name); } f_print(fout, "}\n\n"); } static int opcode_holes_exist(void) { int i; for (i = lowest_opcode[PackageIndex]; i < highest_opcode[PackageIndex]; i++) { if (!opcodenum_is_defined(i)) return 1; } return 0; } void er_Proc_CodeGeneration(void) { int temp; temp = PackageIndex; if (!combinepackages) PackageIndex = 0; for (; PackageIndex <= temp; PackageIndex++) { if (proc_defined[PackageIndex] == NULL) continue; if (combinepackages || opcode_holes_exist()) { er_HeadofOldStyleProc_setup(); er_BodyofOldStyleProc_setup(); er_TailofOldStyleProc_setup(); er_HeadofOldStyleProc_setup2(); er_BodyofOldStyleProc_setup2(); er_TailofOldStyleProc_setup2(); } else { er_ProcDeclExterns_setup(); er_ProcProcsArray_setup(); er_ProcMainBody_setup(); } } PackageIndex = temp; } static void er_ProcDeclExterns_setup(void) { list *listp; definition *defp; if ( !Sflag ) return; f_print(fout, "\n"); for (listp = proc_defined[PackageIndex]; listp != NULL; listp = listp->next) { defp = (definition *) listp->val; if (defp->pc.proc_serverstub) { f_print(fout, "afs_int32 %s();\n", defp->pc.proc_serverstub); } } } static void er_ProcProcsArray_setup(void) { list *listp; definition *defp; if ((listp = proc_defined[PackageIndex])) { defp = (definition *) listp->val; if ( cflag ) { f_print(fout, "\nstatic char *opnames%d[] = {\"%s%s\"", PackageIndex, defp->pc.proc_prefix, defp->pc.proc_name); } else { if (defp->pc.proc_serverstub) { f_print(fout, "\nstatic afs_int32 (*StubProcsArray%d[])() = {%s", PackageIndex, defp->pc.proc_serverstub); } else { f_print(fout, "\nstatic afs_int32 (*StubProcsArray%d[])(struct rx_call *z_call, XDR *z_xdrs) = {_%s%s%s", PackageIndex, prefix, defp->pc.proc_prefix, ((definition *) listp->val)->pc.proc_name); } } listp = listp->next; } for (; listp != NULL; listp = listp->next) { defp = (definition *) listp->val; if ( cflag ) { f_print(fout, ", \"%s%s\"",defp->pc.proc_prefix,defp->pc.proc_name); } else { if (defp->pc.proc_serverstub) { f_print(fout, ",%s", defp->pc.proc_serverstub); } else { f_print(fout, ", _%s%s%s", prefix, defp->pc.proc_prefix, defp->pc.proc_name); } } } f_print(fout, "};\n\n"); } static void er_ProcMainBody_setup(void) { if ( cflag ) { f_print(fout, "char *%sTranslateOpCode(int op)\n{\n", PackagePrefix[PackageIndex]); f_print(fout, "\tif (op < %sLOWEST_OPCODE || op > %sHIGHEST_OPCODE)\n\t\treturn NULL;\n", PackagePrefix[PackageIndex], PackagePrefix[PackageIndex]); f_print(fout, "\treturn opnames%d[op - %sLOWEST_OPCODE];\n}\n", PackageIndex, PackagePrefix[PackageIndex]); f_print(fout, "struct %sstats *%sOpCodeStats(int op)\n{\n", PackagePrefix[PackageIndex], PackagePrefix[PackageIndex]); f_print(fout, "\tif (op < %sLOWEST_OPCODE || op > %sHIGHEST_OPCODE)\n\t\treturn NULL;\n", PackagePrefix[PackageIndex], PackagePrefix[PackageIndex]); f_print(fout, "\treturn NULL;/*%d %s*/\n}\n", PackageIndex, PackagePrefix[PackageIndex]); return; } f_print(fout, "int %s%sExecuteRequest(struct rx_call *z_call)\n", prefix, PackagePrefix[PackageIndex]); f_print(fout, "{\n\tint op;\n"); f_print(fout, "\tXDR z_xdrs;\n"); f_print(fout, "\t" "afs_int32 z_result;\n\n"); f_print(fout, "\txdrrx_create(&z_xdrs, z_call, XDR_DECODE);\n"); f_print(fout, "\tif (!xdr_int(&z_xdrs, &op))\n\t\tz_result = RXGEN_DECODE;\n"); f_print(fout, "\telse if (op < %sLOWEST_OPCODE || op > %sHIGHEST_OPCODE)\n\t\tz_result = RXGEN_OPCODE;\n", PackagePrefix[PackageIndex], PackagePrefix[PackageIndex]); f_print(fout, "\telse\n\t\tz_result = (*StubProcsArray%d[op - %sLOWEST_OPCODE])(z_call, &z_xdrs);\n", PackageIndex, PackagePrefix[PackageIndex]); f_print(fout, "\treturn hton_syserr_conv(z_result);\n}\n"); } static void er_HeadofOldStyleProc_setup2(void) { if ( cflag ) { f_print(fout, "int %sOpCodeIndex(int op)\n{\n", (combinepackages ? MasterPrefix : PackagePrefix[PackageIndex])); f_print(fout, "\tswitch (op) {\n"); } } static void er_HeadofOldStyleProc_setup(void) { if ( cflag ) { f_print(fout, "char *%sTranslateOpCode(int op)\n{\n", (combinepackages ? MasterPrefix : PackagePrefix[PackageIndex])); } else { f_print(fout, "\nint %s%sExecuteRequest (struct rx_call *z_call)\n", prefix, (combinepackages ? MasterPrefix : PackagePrefix[PackageIndex])); f_print(fout, "{\n"); f_print(fout, "\tint op;\n"); f_print(fout, "\tXDR z_xdrs;\n"); f_print(fout, "\t" "afs_int32 z_result;\n\n"); f_print(fout, "\txdrrx_create(&z_xdrs, z_call, XDR_DECODE);\n"); f_print(fout, "\tz_result = RXGEN_DECODE;\n"); f_print(fout, "\tif (!xdr_int(&z_xdrs, &op)) goto fail;\n"); } f_print(fout, "\tswitch (op) {\n"); } static void er_BodyofOldStyleProc_setup(void) { list *listp; if (combinepackages) { int temp = PackageIndex; for (PackageIndex = 0; PackageIndex <= temp; PackageIndex++) { for (listp = proc_defined[PackageIndex]; listp != NULL; listp = listp->next) proc_er_case((definition *) listp->val); } PackageIndex = temp; } else { for (listp = proc_defined[PackageIndex]; listp != NULL; listp = listp->next) proc_er_case((definition *) listp->val); } } static void proc_er_case(definition * defp) { if ( cflag ) { f_print(fout, "\t\tcase %d:", defp->pc.proc_opcodenum); f_print(fout, "\treturn \"%s%s\";\n", defp->pc.proc_prefix, defp->pc.proc_name); return; } if (opcodesnotallowed[PackageIndex]) { f_print(fout, "\t\tcase %d:\n", defp->pc.proc_opcodenum); } else { f_print(fout, "\t\tcase %s:\n", defp->pc.proc_opcodename); } if (defp->pc.proc_serverstub) { f_print(fout, "\t\t\tz_result = %s(z_call, &z_xdrs);\n", defp->pc.proc_serverstub); } else { f_print(fout, "\t\t\tz_result = _%s%s%s(z_call, &z_xdrs);\n", prefix, defp->pc.proc_prefix, defp->pc.proc_name); } f_print(fout, "\t\t\tbreak;\n"); } static void proc_op_case(definition * defp) { f_print(fout, "\t\tcase %d:", defp->pc.proc_opcodenum); f_print(fout, "\treturn %d;\n", defp->statindex); } static void er_BodyofOldStyleProc_setup2(void) { list *listp; if (!cflag) return; if (combinepackages) { int temp = PackageIndex; for (PackageIndex = 0; PackageIndex <= temp; PackageIndex++) { for (listp = proc_defined[PackageIndex]; listp != NULL; listp = listp->next) proc_op_case((definition *) listp->val); } PackageIndex = temp; } else { for (listp = proc_defined[PackageIndex]; listp != NULL; listp = listp->next) proc_op_case((definition *) listp->val); } } static void er_TailofOldStyleProc_setup2(void) { if ( cflag ) { f_print(fout, "\t\tdefault:\n"); f_print(fout, "\t\t\treturn -1;\n\t}\n}\n"); } } static void er_TailofOldStyleProc_setup(void) { f_print(fout, "\t\tdefault:\n"); if ( cflag ) { f_print(fout, "\t\t\treturn NULL;\n\t}\n}\n"); return; } f_print(fout, "\t\t\tz_result = RXGEN_OPCODE;\n"); f_print(fout, "\t\t\tbreak;\n\t}\n"); f_print(fout, "fail:\n"); f_print(fout, "\treturn z_result;\n}\n"); } static void h_ProcMainBody_setup(void) { f_print(fout,"\nextern int %s%sExecuteRequest(struct rx_call *);\n", prefix, PackagePrefix[PackageIndex]); } static void h_HeadofOldStyleProc_setup(void) { char *pprefix = (combinepackages ? MasterPrefix : PackagePrefix[PackageIndex]); f_print(fout,"\nstruct %sstats{\n\tint statsver;\n};", pprefix); f_print(fout,"\nextern int %s%sExecuteRequest(struct rx_call *);\n", prefix, pprefix); f_print(fout,"\nextern int %sOpCodeIndex(int op);\n", PackagePrefix[PackageIndex]); } void h_Proc_CodeGeneration(void) { int temp; temp = PackageIndex; if (!combinepackages) PackageIndex = 0; for (; PackageIndex <= temp; PackageIndex++) { if (combinepackages || opcode_holes_exist()) { h_HeadofOldStyleProc_setup(); } else { h_ProcMainBody_setup(); } } PackageIndex = temp; } static void proc_h_case(definition * defp) { f_print(fout, "#define opcode_%s%s \t((afs_uint64)((%uLL << 32) + %sOpCodeIndex(%u)))\n", defp->pc.proc_prefix, defp->pc.proc_name, StatIndex, defp->pc.proc_prefix, defp->pc.proc_opcodenum); } void h_opcode_stats_pkg(char *pprefix, int lowest, int highest, int nops, int statfuncs, char *ptype, list *proclist) { list *listp; if (!pprefix) return; f_print(fout, "\n/* Opcode-related useful stats for %spackage: %s */\n", ptype, pprefix); f_print(fout, "#define %sLOWEST_OPCODE %d\n", pprefix, lowest); f_print(fout, "#define %sHIGHEST_OPCODE %d\n", pprefix, highest); f_print(fout, "#define %sNUMBER_OPCODES %d\n\n", pprefix, nops); for (listp = proclist; listp != NULL; listp = listp->next) proc_h_case((definition *) listp->val); if (xflag) { f_print(fout, "#define %sNO_OF_STAT_FUNCS\t%d\n\n", pprefix, statfuncs); f_print(fout, "AFS_RXGEN_EXPORT\n"); f_print(fout, "extern const char *%sfunction_names[];\n\n", pprefix); } } void h_opcode_stats(void) { if (combinepackages) { h_opcode_stats_pkg(MasterPrefix, master_lowest_opcode, master_highest_opcode, master_no_of_opcodes, no_of_stat_funcs_header[0], "Master ", proc_defined[0]); } else { int i; for (i = 0; i <= PackageIndex; i++) { h_opcode_stats_pkg(PackagePrefix[i], lowest_opcode[i], highest_opcode[i], no_of_opcodes[i], no_of_stat_funcs_header[i], "", proc_defined[i]); } } } void generate_multi_macros(definition * defp) { char *startname = SplitStart, *endname = SplitEnd; proc1_list *plist; int numofparams; int first = 0; if (!hflag) return; if (!Multi_Init) { Multi_Init = 1; f_print(fout, "\n#include "); } f_print(fout, "\n#define multi_%s%s(", PackagePrefix[PackageIndex], defp->pc.proc_name); for (plist = defp->pc.plists; plist; plist = plist->next) { if (plist->component_kind == DEF_PARAM) { if (!first) { first = 1; f_print(fout, "%s", plist->pl.param_name); } else { f_print(fout, ", %s", plist->pl.param_name); } } } f_print(fout, ") \\\n"); if (!startname) startname = "Start"; if (!endname) endname = "End"; f_print(fout, "\tmulti_Body(%s%s%s(multi_call", startname, PackagePrefix[PackageIndex], defp->pc.proc_name); do_split(defp, OUT, &numofparams, DEF_OUTPARAM, 0); for (plist = defp->pc.plists; plist; plist = plist->next) { if (plist->component_kind == DEF_PARAM) f_print(fout, ", %s", plist->pl.param_name); } do_split(defp, OUT, &numofparams, DEF_OUTPARAM, 1); f_print(fout, "), %s%s%s(multi_call", endname, PackagePrefix[PackageIndex], defp->pc.proc_name); do_split(defp, IN, &numofparams, DEF_INPARAM, 0); for (plist = defp->pc.plists; plist; plist = plist->next) { if (plist->component_kind == DEF_PARAM) { f_print(fout, ", %s", plist->pl.param_name); } } do_split(defp, IN, &numofparams, DEF_INPARAM, 1); f_print(fout, "))\n\n"); } int IsRxgenToken(token * tokp) { if (tokp->kind == TOK_PACKAGE || tokp->kind == TOK_PREFIX || tokp->kind == TOK_SPECIAL || tokp->kind == TOK_STARTINGOPCODE || tokp->kind == TOK_SPLITPREFIX || tokp->kind == TOK_PROC || tokp->kind == TOK_STATINDEX) return 1; return 0; } int IsRxgenDefinition(definition * def) { 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) return 1; return 0; }