From 947c78887e791596d4a5ec2d1079f8b1a049628b Mon Sep 17 00:00:00 2001 From: takeshi_hoshina Date: Tue, 27 Oct 2020 11:16:21 +0900 Subject: basesystem 0.1 --- otherservice/rpc_library/tool/apidef.cc | 1104 +++++++++++++++++++++++++++++++ 1 file changed, 1104 insertions(+) create mode 100644 otherservice/rpc_library/tool/apidef.cc (limited to 'otherservice/rpc_library/tool/apidef.cc') diff --git a/otherservice/rpc_library/tool/apidef.cc b/otherservice/rpc_library/tool/apidef.cc new file mode 100644 index 00000000..5a5df1c2 --- /dev/null +++ b/otherservice/rpc_library/tool/apidef.cc @@ -0,0 +1,1104 @@ +/* + * @copyright Copyright (c) 2016-2019 TOYOTA MOTOR CORPORATION. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file apidef.cc + * @brief RPC tools--Main processing(Implementations of APIDef classes) + * + */ +#include +#include +#include +#include + +#include + +#include "apidef.h" +#include "apidef.tab.h" + +static APIDef *API_Def; + +extern "C" { // C interface functions + +void +ApidefDefineId(const char *id) { + if (id != NULL) { + if (API_Def == NULL) { + API_Def = new APIDef(); + } + API_Def->DefineId(id); + } +} + +void +ApidefAddHeader(const char *filename) { + if (filename != NULL) { + if (API_Def == NULL) { + API_Def = new APIDef(); + } + API_Def->AddHeader(filename); + } +} + +int +ApidefPushFunctionArg(int arg_code, int buffer_bytes, int is_pointer, + int is_vararray, int is_array_size, + const char *var_type_name, int in_out, + const char *var_name) { + if (API_Def == NULL) { + API_Def = new APIDef(); + } + return API_Def->AddFunctionArg(arg_code, buffer_bytes, is_pointer, + is_vararray, is_array_size, + var_type_name, in_out, var_name); +} + +void +ApidefProcessFunction(const char *name) { + if (API_Def == NULL) { + API_Def = new APIDef(); + } + API_Def->NameFunction(name); +} + +void +ApidefListFunctions(int with_args) { + if (API_Def != NULL) { + API_Def->Print(with_args); + } +} + +void +ApidefFreeAllocation(void) { + if (API_Def != NULL) { + delete API_Def; + API_Def = NULL; + } +} + +int +ApidefMakeStubs(void) { + if (API_Def != NULL) { + API_Def->MakeStubs(); + return 0; + } else { + return 1; + } +} + +} // extern "C" + +/* + * Retrieving Argument Names Without Decorators + */ +void +Arg::GetUndecolatedName(string& name /* OUT */, int num) { + name = "v"; + if (num > 0) { + /* Making Variable Names Sequential Numbers */ + char num_str[5]; + sprintf(num_str, "%d", num); + name += num_str; + } else { + /* Use a user-supplied pseudo-variable name */ + name = m_name; + } +} + +int +Arg::PrintUndecoratedName(fstream& out, int num) { + /* Pointer argument */ + if (m_is_pointer) { + out << "*"; + } + + if (num > 0) { + /* Making Variable Names Sequential Numbers */ + out << "v" << num; + } else { + /* Use a user-supplied pseudo-variable name */ + out << m_name; + } + + return 0; +} + +/* + * Outputs one argument in a function prototype declaration + * out: Destination file + * num: Handling of Formal Argument Names + * 0 :Formal argument name specified in the API definition file + * Non-zero: Use "v" + specified number(Examples: v1, v2, ...) + */ +int +Arg::PrintPrototype(fstream& out, int num) { + const char *type = TypeCodeString(m_code); + if (type == NULL) { + type = m_type_name.c_str(); + } + if (type == NULL) { + cout << "Internal Error Occurrence!!\n"; + return 1; + } + + /* Const non-output pointers */ + if ((m_in_out & RPC_OUT_ARG) == 0 && (m_bytes != 0 || m_is_pointer != 0)) { + out << "const "; + } + out << type << " "; + if (m_is_pointer && m_bytes == 0) {/* Non-string pointer arguments */ + out << "*"; + } + + if (num > 0) {/* Making variable names sequential numbers */ + out << "v" << num; + } else {/* Use a user-supplied pseudo-variable name */ + out << m_name; + } + + /* Variable-length arrays */ + if (m_is_vararray != 0) { + out << "/* VAR_ARRAY */"; + } + + /* Variable-length arrays length */ + if (m_is_array_size != 0) { + out << "/* VAR_SIZE */"; + } + + /* + * Commenting on OUT/INOUT Arguments + * Maximum number of bytes of a string argument added to a comment + */ + if ((m_in_out & RPC_OUT_ARG) != 0 || m_bytes != 0) { + out << "/* "; + if ((m_in_out & RPC_OUT_ARG) != 0) { + if ((m_in_out & RPC_IN_ARG) != 0) { + out << "IN"; + } + out << "OUT "; + } + if (m_bytes) { + out << m_bytes << "Byte "; + } + out << "*/"; + } + + return 0; +} + +int +Arg::CreateMarshallArgs(fstream& out, int num) { + return CreateMarshallArgs(out, num, (RPC_IN_ARG|RPC_OUT_ARG)); +} + +int +Arg::CreateMarshallArgs(fstream& out, int num, string &array_size_name) { + return CreateMarshallArgs(out, num, (RPC_IN_ARG|RPC_OUT_ARG), array_size_name); +} + +int +Arg::CreateMarshallArgs(fstream& out, int num, int in_out) { + string dummy = ""; + return CreateMarshallArgs(out, num, in_out, dummy); +} + +/* + * The arguments to rpc_marshall_args() are generated for each API argument. + * for each API argument. + * out: Destination file + * num: Number given to the variable name of the argument (Examples: 1 for v1) + * in_out: Specifying the IN or OUT Attributes + * Output only if the argument has the specified attribute + */ +int +Arg::CreateMarshallArgs(fstream& out, int num, int in_out, string &array_size_name) { + if ((m_in_out & in_out) != 0) { + /* + * Collectively passes the argument type, pointer/non-pointer, IN/OUT attribute, + * and the maximum number of bytes of the argument type to one integer. + */ + RPC_marshall_flag flag; + flag.bits.code = m_code & ((1<= RPC_MAX_API_ARG_NUM) { + cout << "Too many API function arguments.\n"; + return -1; + } + Arg *a = new Arg(code, bytes, is_pointer, is_vararray, is_array_size, + var_type_name, in_out, var_name); + m_args.push_back(*a); + delete a; + return 0; +} + +/* + * Generate prototype declarations for a single API function + * out: Destination file + */ +int +Function::PrintPrototype(fstream& out, int server) { + int ret = 0; + + const char *return_type + = server ? RPC_API_SERVER_RETURN : RPC_API_CLIENT_RETURN; +#ifdef DBG_ENABLE + if ((server) || (!rpc_log_enable)) { + out << return_type << " " << m_name << "("; + } else { + out << return_type << " __" << m_name << "("; + } +#else + out << return_type << " " << m_name << "("; +#endif + + list::size_type num_args = m_args.size(); + if (num_args > 0) { + list::iterator a; + a = m_args.begin(); + for (list::size_type i = 1; i <= num_args; ++i, ++a) { + a->PrintPrototype(out); +#ifdef DBG_ENABLE + if ((server) || (!rpc_log_enable)) { + if (i != num_args) { + out << ", "; + } + } else { + out << ", "; + } +#else + if (i != num_args) { + out << ", "; + } +#endif + } + } else { +#ifdef DBG_ENABLE + if ((server) || (!rpc_log_enable)) { + out << "void"; + } +#else + out << "void"; +#endif + } +#ifdef DBG_ENABLE + /* Debug information */ + if ((!server) && (rpc_log_enable)) { + out << "const char *filename, const char *funcname, int line "; + } +#endif + out << ");\n"; + return ret; +} + +#ifdef DBG_ENABLE +int +Function::PrintMacro(fstream& out) { + int ret = 0; + out << "#define " << m_name << "("; + + int num_args = m_args.size(); + if (num_args > 0) { + int i; + char c; + for (i = 1, c = 'a'; i <= num_args; i++, c++) { + out << c; + if (i != num_args) { + out << ", "; + } + } + out << ") \\\n\t"; + + /* Entity */ + out << "__" << m_name << "("; + for (i = 1, c = 'a'; i <= num_args; i++, c++) { + out << c << ", "; + } + out << "__FILE__, __func__, __LINE__)\n"; + } else { /* Without arguments */ + out << ") " << "__" << m_name << "(__FILE__, __func__, __LINE__)\n"; + } + + return ret; +} +#endif + +int +APIDef::MakeHeaderFiles(int server) { + char filename[MAX_FILENAME_LEN+1]; + sprintf(filename, "%s%s", m_lowerid.c_str(), + (server ? SERVER_HEADER_FILE : CLIENT_HEADER_FILE)); + int ret = 0; + + fstream out(filename, ios::out); + if (!out.is_open()) { + cout << "ERROR: File " << filename << " Could not open.\n"; + return 1; + } + cout << "info: Header file " << filename << " Creating.\n"; + + const char *define_str = + server ? SERVER_HEADER_DEFINE : CLIENT_HEADER_DEFINE; + const char *title = server ? SERVER_HEADER_TITLE : CLIENT_HEADER_TITLE; + + out << "#ifndef _" << m_lowerid << define_str << "\n"; + out << "#define _" << m_lowerid << define_str << "\n"; + out << "/*\n"; + out << " * " << m_id << " " << title << " " << filename << "\n"; + out << " *\n"; + out << RPCTOOL_WARNING_STRING << "\n"; + out << " */\n\n"; + + list::iterator i; + for (i = m_headers.begin(); i != m_headers.end(); ++i) { + out << "#include <" << *i << ">\n"; + } + out << "\n"; + + if (server) { + + out << EXTERN_C_START << "\n"; + + out << RPC_API_DISPATCH_RETURN << " " + << m_id << RPC_API_DISPATCH_FUNC_FULL << ";\n"; + + out << "#ifdef RPC_DISPATCH_FUNC\n" + << "#undef RPC_DISPATCH_FUNC\n" + << "#define RPC_DISPATCH_FUNC " << m_id << RPC_API_DISPATCH_FUNC_NAME + << "\n#else /* !RPC_DISPATCH_FUNC */\n" + << "#error \"Please include first!!\"\n" + << "#endif /* !RPC_DISPATCH_FUNC */\n\n"; + + out << EXTERN_C_END << "\n"; + + } +#ifdef DBG_ENABLE + else if (rpc_log_enable) { + /* DEBUG INFORMATION EMBEDDED MACRO */ + out << "/* Debug information embedded macro definition */\n"; + list::iterator f; + for (f = m_funcs.begin(); f != m_funcs.end(); ++f) { + if (f->PrintMacro(out) != 0) { + ret = 1; + break; + } + } + out << "\n"; + } +#endif + + out << EXTERN_C_START << "\n"; + + out << "/* API definitions */\n"; + list::iterator f; + for (f = m_funcs.begin(); f != m_funcs.end(); ++f) { + if (f->PrintPrototype(out, server) != 0) { + ret = 1; + break; + } + } + out << "\n"; + + out << EXTERN_C_END << "\n"; + + out << "#endif /* _" << m_lowerid << define_str << " */\n"; + out.close(); + return ret; +} + +int +Function::PrintServerStub(fstream& out) { + int num_args = NumOfArgs(); + + out << "\tcase " << RPC_API_NUM_PREFIX << m_name << ": {\n"; + + list::iterator a = m_args.begin(); + for (int i = 1; i <= num_args; ++i, ++a) { + const char *type = TypeCodeString(a->Code()); + if (type == NULL) { + type = (a->TypeName()).c_str(); + } + if (type == NULL) { + return 1; + } + out << "\t\t" << type << " "; + if (a->Bytes() > 0 || a->IsPointer()) {/* Pointer-passing argument */ + if (a->Bytes() > 0) { + out << "v" << i << " = NULL;\n"; + } else if (a->IsPointer()) { + out << "*v" << i << " = NULL;\n"; + } + } else {/* Pass-by-value argument */ + out << "v" << i << ";\n"; + } + } + if (num_args > 0) { + out << "\t\tif (" << RPC_DEMARSHALL_FUNCTION + << " (args_string, args_size, 1, " << num_args << ",\n"; + /* In the STUB of servers for all pre-call demarshall */ + /* Passing Pointers to Local Variables in Server STUB */ + /* Pointer/ Buffer will alloc the required space in demarshall_arguments() */ + + a = m_args.begin(); + for (int i = 1; i <= num_args; ++i, ++a) { + if (a->IsVararray() != 0) { /* Variable-length arrays */ + a->CreateDemarshallArgs(out, 1, i, m_array_size_name); + } else { + a->CreateDemarshallArgs(out, 1, i); + } + if (i < num_args) { + out << ","; + } + out << "\n"; + } + out << "\t\t ) < 0) {\n"; + out << "\t\t\tgoto _" << m_name << "_Error;\n"; + out << "\t\t}\n"; + } + + out << "\t\tresult = " << m_name << "("; + for (int i = 1; i <= num_args; i++) { + out << "v" << i; + if (i < num_args) { + out << ", "; + } + } + out << ");\n"; + + int to_process = NumOfInOutArgs(RPC_OUT_ARG); + if (to_process > 0) { + /* Only OUT-arguments marshall after the server stub is called. */ + out << "\t\t/*if (result == RPC_OK) {*/\n"; + out << "\t\t *ret_string = " << RPC_MARSHALL_FUNCTION + << "(ret_size, 0, " << to_process << ",\n"; + + a = m_args.begin(); + int processed = 0; + int ret; + for (int i = 1; i <= num_args; ++i, ++a) { + if (a->IsVararray() != 0) { /* Variable-length arrays */ + ret = a->CreateMarshallArgs(out, i, RPC_OUT_ARG, m_array_size_name); + } else { + ret = a->CreateMarshallArgs(out, i, RPC_OUT_ARG); + } + if (ret) { + processed++; + if (processed < to_process) { + out << ","; + } + out << "\n"; + } + } + out << "\t\t );\n" + << "\t\t if (*ret_string == NULL) {\n" + << "\t\t\tresult = " << RPC_API_SERVER_ERROR << ";\n" + << "\t\t }\n" + << "\t\t/*}*/\n"; + } + + if (num_args > 0) { + out << "_" << m_name << "_Error:\n"; + } + int num_pointer_args = 0; + a = m_args.begin(); + for (int i = 1; i <= num_args; ++i, ++a) { + if (a->Bytes() || a->IsPointer()) { + num_pointer_args++; + } + } + if (num_pointer_args > 0) { + int processed = 0; + out << "\t\t" << RPC_MARSHALL_FREE_FUNCTION + << "(" << num_pointer_args << ", "; + a = m_args.begin(); + for (int i = 1; i <= num_args; ++i, ++a) { + if (a->Bytes() || a->IsPointer()) { + out << "v" << i; + processed++; + if (processed < num_pointer_args) { + out << ", "; + } + } + } + out << ");\n"; + } + out << "\t\tbreak;\n\t}\n"; + return 0; +} + +int +APIDef::MakeServerStub(void) { + char filename[MAX_FILENAME_LEN+1]; + sprintf(filename, "%s%s", m_lowerid.c_str(), SERVER_STUB_FILE); + int ret = 0; + + fstream out(filename, ios::out); + if (!out.is_open()) { + cout << "File " << filename << " Could not open.\n"; + return 1; + } + cout << "info: Stub file " << filename << " Creating.\n"; + + const char *title = SERVER_STUB_TITLE; + + out << "/*\n"; + out << " * " << m_id << " " << title << " " << filename << "\n"; + out << " *\n"; + out << RPCTOOL_WARNING_STRING << "\n"; + out << " */\n"; + out << "#include <" RPC_GLOBAL_HEADER_FILE << ">\n"; + out << "#include \"" << m_lowerid << SERVER_HEADER_FILE << "\"\n"; + out << "#include /* for ntohs() */\n\n"; + + int api_num = 1; + list::iterator f; + + for (f = m_funcs.begin(); f != m_funcs.end(); ++f, ++api_num) { + if (api_num >= (1<<16)) { + cout << "Too many API functions.(Up to 65535)\n"; + return 1; + } + out << "#define " << RPC_API_NUM_PREFIX << f->Name() + << " " << api_num << "\n"; + } + out << "\n"; + + out << "RPC_Result\n"; + out << m_id << RPC_API_DISPATCH_FUNC_FULL << "\n"; + out << "{\n"; + out << "\tRPC_Result result = " << RPC_API_SERVER_ERROR << ";\n"; + out << "\t*ret_string = NULL;\n"; + out << "\tswitch(api_num) {\n"; + + for (f = m_funcs.begin(); f != m_funcs.end(); ++f) { + if (f->PrintServerStub(out) != 0) { + ret = 1; + break; + } + } + + if (ret != 0) { + return ret; + } + + out << "\tdefault:\n\t\tbreak;\n\t}\n"; + out << "\treturn result;\n"; + out << "}\n"; + + return ret; +} + +int +Function::PrintClientStub(const char *moduleid, fstream& out) { + int ret = 0; + + list::iterator a; + /* Function Names and Arguments */ + out << RPC_API_CLIENT_RETURN << "\n"; +#ifdef DBG_ENABLE + if (rpc_log_enable) { + out << "__" << m_name << "("; + } else { + out << m_name << "("; + } +#else + out << m_name << "("; +#endif + int num_args = (int)(m_args.size()); + if (num_args > 0) { + a = m_args.begin(); + for (int i = 1; i <= num_args; ++i, ++a) { + if (a->PrintPrototype(out, i)) { + return 1; + } +#ifdef DBG_ENABLE + if (rpc_log_enable) { + out << ", "; + } else { + if (i < num_args) { + out << ", "; + } + } +#else + if (i < num_args) { + out << ", "; + } +#endif + } + } else { +#ifndef DBG_ENABLE + out << "void"; +#else + if (!rpc_log_enable) { + out << "void"; + } +#endif + } +#ifdef DBG_ENABLE + if (rpc_log_enable) { + out << "const char *filename, const char *funcname, int line "; + } +#endif + out << ")\n"; + + out << "{\n"; + + /* Contents of stub functions */ + + /* If the argument is present and the variable-length array does not exist */ + if ((num_args > 0) && (m_array_size_pos == 0)) { + int is_exist_mytype = 0; + /* Restricted specifications */ + out << "#ifdef RPC_STATIC_ASSERT\n"; + out << "\tchar RPC_TOTAL_ARGSIZE_ERROR_in_" << m_name << "[\n"; + out << "\t((("; + a = m_args.begin(); + for (int i = 1; i <= num_args; ++i, ++a) { + if (i > 1) { + out << " + "; + } + out << "sizeof("; + a->PrintUndecoratedName(out, i); + out << ")"; + /* For user types */ + if ((!is_exist_mytype) && (NULL == TypeCodeString(a->Code()))) { + is_exist_mytype = 1; + } + } + out << ") > RPC_MAX_API_ARG_TOTAL_SIZE) ? -1: 1)\n"; + out << "\t]__attribute__((unused));\n"; + + /* Have a user type */ + if (is_exist_mytype) { + char c[3]; + a = m_args.begin(); + for (int i = 1; i <= num_args; ++i, ++a) { + if (NULL == TypeCodeString(a->Code())) { + sprintf(c, "%d", i); + out << "\tchar RPC_ARGSIZE_ERROR_in_" << m_name << "_arg" << c; + out << "[\n\t(sizeof("; + a->PrintUndecoratedName(out, i); + out << ") > RPC_MAX_API_ARG_SIZE) ? -1: 1\n"; + out << "\t]__attribute__((unused));\n"; + } + } + } + + out << "#endif /* RPC_STATIC_ASSERT */\n"; + + } + + out << "\tRPC_Result result = " << RPC_API_CLIENT_ERROR << ";\n"; + out << "\tunsigned int args_size = 0, ret_size;\n"; + out << "\tchar retcode[9];\n"; + + if (num_args > 0) { + /* Advance preparation==Marshalling of arguments */ + out << "\tchar *args_string = " << RPC_MARSHALL_FUNCTION + << "(&args_size, 1, " << num_args << ",\n"; + /* In the clients STUB for all pre-call marshall */ + a = m_args.begin(); + for (int i = 1; i <= num_args; ++i, ++a) { + if (a->IsVararray() != 0) { /* Variable-length arrays */ + a->CreateMarshallArgs(out, i, m_array_size_name); + } else { + a->CreateMarshallArgs(out, i); + } + if (i < num_args) { + out << ","; + } + out << "\n"; + } + out << "\t);\n"; + out << "\tif (args_string == NULL) {\n" + << "\t\tgoto _" << m_name << "_Error;\n\t}\n"; + } else { + out << "\tchar *args_string = NULL;\n"; + } + +#ifdef DBG_ENABLE + if (rpc_log_enable) { + out << "\tif (" << moduleid << "_record_dbg_log(filename, funcname, line, \""; + out << m_name << "\") != 0) {\n"; + out << "\t\tgoto _" << m_name << "_Error;\n\t}\n"; + } +#endif + + /* RPC API call */ + out << "\tchar *ret_string = NULL; /* pgr0431 */\n"; +#ifdef RPC_STRING_ID + out << "\tresult=RPC_API_call(\"" << moduleid << "\", "; +#else + out << "\tresult=RPC_API_call(" << moduleid << "_RPC_ID, "; +#endif + out << RPC_API_NUM_PREFIX << m_name; + out << ", args_string, args_size, &ret_string, &ret_size);\n"; + + // 2007.08.25 To avoid over run within the sscanf + // Locally copies strings needed for determining return values and uses strtol instead of sscanf + // (Since there is no guarantee that the byte sequence to be grabbed by communication is 0-terminated) + out << "\n" + << "\tif (result == RPC_OK && ret_string != NULL) {\n" + << "\t strncpy(retcode, ret_string, 8);\n" + << "\t retcode[8] = '\\0';\n" + << "\t result = (RPC_Result)strtoul(retcode, NULL, 16);\n"; + + /* Post-processing==Arguments de-marshalling, free() */ + int num_of_out_args = NumOfInOutArgs(RPC_OUT_ARG); + if (num_of_out_args > 0) { + out << "\t if (" << RPC_DEMARSHALL_FUNCTION + << "(ret_string + RPC_RETCODE_LEN, ret_size - RPC_RETCODE_LEN, 0, " + << num_of_out_args << ",\n"; + + a = m_args.begin(); + int processed = 0; + int ret; + for (int i = 1; i <= num_args; ++i, ++a) { + if (a->IsVararray() != 0) { /* Variable-length arrays */ + ret = a->CreateDemarshallArgs(out, 0, i, RPC_OUT_ARG, m_array_size_name); + } else { + ret = a->CreateDemarshallArgs(out, 0, i, RPC_OUT_ARG); + } + if (ret) { + processed++; + if (processed < num_of_out_args) { + out << ","; + } + out << "\n"; + } + } + out << "\t ) < 0) {\n" + << "\t\tresult = " << RPC_API_CLIENT_ERROR << ";\n" + << "\t }\n"; + } + + out << "\t} else {\n\t //result = " << RPC_API_CLIENT_ERROR << ";\n" + << "\t}\n"; + + out << "\t" << RPC_RETURN_FREE_FUNCTION << "(ret_string);\n"; + out << "\t" << RPC_MARSHALL_FREE_FUNCTION << "(1, args_string);\n"; + + /* END, RETURN */ +#ifndef DBG_ENABLE + if (num_args) +#else + if ((num_args)||(rpc_log_enable)) +#endif + { + out << "_" << m_name << "_Error:\n"; + } + + out << "\treturn result;\n}\n"; + + return ret; +} + +int +APIDef::MakeClientStub(void) { + char filename[MAX_FILENAME_LEN+1]; + sprintf(filename, "%s%s", m_lowerid.c_str(), CLIENT_STUB_FILE); + int ret = 0; + + fstream out(filename, ios::out); + if (!out.is_open()) { + cout << "File " << filename << " Could not open.\n"; + return 1; + } + cout << "info: Stub file " << filename << " Creating.\n"; + + const char *title = CLIENT_STUB_TITLE; + + out << "/*\n"; + out << " * " << m_id << " " << title << " " << filename << "\n"; + out << " *\n"; + out << RPCTOOL_WARNING_STRING << "\n"; + out << " */\n"; + out << "#include <" RPC_GLOBAL_HEADER_FILE << ">\n"; + out << "#include <" << m_lowerid << CLIENT_HEADER_FILE << ">\n\n"; + out << "#include /* for sscanf() */\n"; + out << "#include /* for getenv() */\n"; + out << "#include /* for strncpy() */\n"; + out << "#include /* for ntohs() */\n\n"; + + int api_num = 1; + list::iterator f; + for (f = m_funcs.begin(); f != m_funcs.end(); ++f, ++api_num) { + if (api_num >= (1<<16)) { + cout << "Too many API functions.(Up to 65535)\n"; + return 1; + } + out << "#define " << RPC_API_NUM_PREFIX << f->Name() + << " " << api_num << "\n"; + } + out << "\n"; + + /* Specification Restriction Debug Constants */ + out << "/*#define RPC_STATIC_ASSERT*/\n"; + out << "\n"; + +#ifdef DBG_ENABLE + if (rpc_log_enable) { + int m_id_work_cnt; + string m_id_work = m_id; + for (m_id_work_cnt = 0; m_id_work_cnt < m_id_work.length(); m_id_work_cnt++) { + m_id_work[m_id_work_cnt] = toupper(m_id_work[m_id_work_cnt]); + } + out << "int\n" << m_id << "_record_dbg_log(const char *filename, " << + "const char *funcname, int line, const char *apiname)\n"; + out << "{\n\t"; + out << "if (getenv(\"" << m_id_work << "_RPC_LOG\") != NULL) {\n\t\t"; + out << "return RPC_record_dbg_log(filename, funcname, line, apiname);\n\t"; + out << "}\n\t"; + out << "return 0;\n"; + out << "}\n\n"; + } +#endif + + /* API definitions */ + for (f = m_funcs.begin(); f != m_funcs.end(); ++f) { + if (f->PrintClientStub(m_id.c_str(), out) != 0) { + ret = 1; + break; + } + } + return ret; +} + +int +Arg::IsArraySize(void) { + if (m_is_array_size != 0) { + if (IsTypeCodeNumeric(m_code) == 1) { + return 1; + } else { + cout << "Variable-length array length specification variables must be integers.\n"; + return -1; + } + } + return 0; +} + +int +Function::CheckFuncArraySize(void) { + int num_args = (int)(m_args.size()); + list::iterator a; + a = m_args.begin(); + for (int i = 1; i <= num_args; ++i, ++a) { + int ret = a->IsArraySize(); + if (ret > 0) { + if (m_array_size_pos != 0) + { + cout << "Two or more variable array length specification arguments exist.\n"; + return 1; + } + m_array_size_pos = i; + a->GetUndecolatedName(m_array_size_name, i); + } else if (ret < 0) { + return 1; + } + } + return 0; +} + +int +APIDef::CheckAllArraySize(void) { + list::iterator f; + for (f = m_funcs.begin(); f != m_funcs.end(); ++f) { + if (f->CheckFuncArraySize() != 0) { + return 1; + } + } + return 0; +} + +int +APIDef::MakeStubs(void) { + if (m_id.size() == 0) { + cout << "The module name is not specified.\n"; + return 1; + } + + if (m_id.size() > MAX_FILENAME_LEN - strlen(SERVER_STUB_FILE)) { + cout << "The module name is too long.\n"; + return 1; + } + + /* Pre-examine the ARRAYSIZE specification */ + //cout << "\n"; + if (CheckAllArraySize() != 0) { + return 1; + } + + //cout << "\n"; + if (MakeHeaderFiles(1) != 0) { + return 1; + } + + //cout << "\n"; + if (MakeHeaderFiles(0) != 0) { + return 1; + } + + if (MakeServerStub() != 0) { + return 1; + } + + if (MakeClientStub() != 0) { + return 1; + } + + return 0; +} + +void +Arg::Print(void) { + cout << "\t"; + if (m_name.size() > 0) { + cout << "Variable name=" << m_name << " "; + } + cout << "Type=" << TypeCodeString(m_code) << "In bytes=" << m_bytes << " "; + if (m_is_pointer) { + cout << "Pointer "; + } + if ((m_in_out & RPC_OUT_ARG) != 0) { + cout << "Output "; + } + cout << "\n"; +} + +void +Function::Print(int with_args) { + printf("Function name=%s\n", m_name.c_str()); + if (with_args) { + list::iterator a; + for (a = m_args.begin(); a != m_args.end(); ++a) { + a->Print(); + } + } +} + +void +APIDef::Print(int with_args) { + list::iterator f; + for (f = m_funcs.begin(); f != m_funcs.end(); ++f) { + f->Print(with_args); + } +} + +void +APIDef::IdTolower(void) { + char *lower = new char[m_id.size() + 1]; + strcpy(lower, m_id.c_str()); + char *p; + for (p = lower; *p; p++) { + *p = (char)(tolower(*p)); + } + m_lowerid = lower; + delete[] lower; +} -- cgit 1.2.3-korg