2 * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 * @brief RPC tools--Main processing(Implementations of APIDef classes)
25 #include <netinet/in.h>
27 #include <other_service/rpc.h>
30 #include "apidef.tab.h"
32 static APIDef *API_Def;
34 extern "C" { // C interface functions
37 ApidefDefineId(const char *id) {
39 if (API_Def == NULL) {
40 API_Def = new APIDef();
42 API_Def->DefineId(id);
47 ApidefAddHeader(const char *filename) {
48 if (filename != NULL) {
49 if (API_Def == NULL) {
50 API_Def = new APIDef();
52 API_Def->AddHeader(filename);
57 ApidefPushFunctionArg(int arg_code, int buffer_bytes, int is_pointer,
58 int is_vararray, int is_array_size,
59 const char *var_type_name, int in_out,
60 const char *var_name) {
61 if (API_Def == NULL) {
62 API_Def = new APIDef();
64 return API_Def->AddFunctionArg(arg_code, buffer_bytes, is_pointer,
65 is_vararray, is_array_size,
66 var_type_name, in_out, var_name);
70 ApidefProcessFunction(const char *name) {
71 if (API_Def == NULL) {
72 API_Def = new APIDef();
74 API_Def->NameFunction(name);
78 ApidefListFunctions(int with_args) {
79 if (API_Def != NULL) {
80 API_Def->Print(with_args);
85 ApidefFreeAllocation(void) {
86 if (API_Def != NULL) {
93 ApidefMakeStubs(void) {
94 if (API_Def != NULL) {
105 * Retrieving Argument Names Without Decorators
108 Arg::GetUndecolatedName(string& name /* OUT */, int num) {
111 /* Making Variable Names Sequential Numbers */
113 sprintf(num_str, "%d", num);
116 /* Use a user-supplied pseudo-variable name */
122 Arg::PrintUndecoratedName(fstream& out, int num) {
123 /* Pointer argument */
129 /* Making Variable Names Sequential Numbers */
132 /* Use a user-supplied pseudo-variable name */
140 * Outputs one argument in a function prototype declaration
141 * out: Destination file
142 * num: Handling of Formal Argument Names
143 * 0 :Formal argument name specified in the API definition file
144 * Non-zero: Use "v" + specified number(Examples: v1, v2, ...)
147 Arg::PrintPrototype(fstream& out, int num) {
148 const char *type = TypeCodeString(m_code);
150 type = m_type_name.c_str();
153 cout << "Internal Error Occurrence!!\n";
157 /* Const non-output pointers */
158 if ((m_in_out & RPC_OUT_ARG) == 0 && (m_bytes != 0 || m_is_pointer != 0)) {
162 if (m_is_pointer && m_bytes == 0) {/* Non-string pointer arguments */
166 if (num > 0) {/* Making variable names sequential numbers */
168 } else {/* Use a user-supplied pseudo-variable name */
172 /* Variable-length arrays */
173 if (m_is_vararray != 0) {
174 out << "/* VAR_ARRAY */";
177 /* Variable-length arrays length */
178 if (m_is_array_size != 0) {
179 out << "/* VAR_SIZE */";
183 * Commenting on OUT/INOUT Arguments
184 * Maximum number of bytes of a string argument added to a comment
186 if ((m_in_out & RPC_OUT_ARG) != 0 || m_bytes != 0) {
188 if ((m_in_out & RPC_OUT_ARG) != 0) {
189 if ((m_in_out & RPC_IN_ARG) != 0) {
195 out << m_bytes << "Byte ";
204 Arg::CreateMarshallArgs(fstream& out, int num) {
205 return CreateMarshallArgs(out, num, (RPC_IN_ARG|RPC_OUT_ARG));
209 Arg::CreateMarshallArgs(fstream& out, int num, string &array_size_name) {
210 return CreateMarshallArgs(out, num, (RPC_IN_ARG|RPC_OUT_ARG), array_size_name);
214 Arg::CreateMarshallArgs(fstream& out, int num, int in_out) {
216 return CreateMarshallArgs(out, num, in_out, dummy);
220 * The arguments to rpc_marshall_args() are generated for each API argument.
221 * for each API argument.
222 * out: Destination file
223 * num: Number given to the variable name of the argument (Examples: 1 for v1)
224 * in_out: Specifying the IN or OUT Attributes
225 * Output only if the argument has the specified attribute
228 Arg::CreateMarshallArgs(fstream& out, int num, int in_out, string &array_size_name) {
229 if ((m_in_out & in_out) != 0) {
231 * Collectively passes the argument type, pointer/non-pointer, IN/OUT attribute,
232 * and the maximum number of bytes of the argument type to one integer.
234 RPC_marshall_flag flag;
235 flag.bits.code = m_code & ((1<<RPC_MARSHALL_FLAG_BITS_CODE)-1);
236 flag.bits.is_vararray = ((array_size_name.size() != 0) ? 1: 0) &
237 ((1<<RPC_MARSHALL_FLAG_BITS_IS_VARARRAY)-1);
238 flag.bits.is_pointer = m_is_pointer & ((1<<RPC_MARSHALL_FLAG_BITS_IS_POINTER)-1);
239 flag.bits.in_out = m_in_out & ((1<<RPC_MARSHALL_FLAG_BITS_IN_OUT)-1);
240 flag.bits.bytes = (UINT16)(m_bytes);
242 sprintf(str, "0x%x", htonl(flag.all));
243 out << "\t\t\t" << str;
246 * Add size of user-defined type to argument
248 if (m_code == rpc_USER_DEFINED) {
249 if (array_size_name.size() != 0) {
250 out << " + ntohs(sizeof(" << m_type_name << ") * " << array_size_name << ")";
252 out << " + ntohs(sizeof(" << m_type_name << "))";
254 } else if (array_size_name.size() != 0) {
255 out << " + ntohs(sizeof(" << TypeCodeString(m_code) << ") * " << array_size_name << ")";
266 Arg::CreateDemarshallArgs(fstream& out, int deliver_pointer, int num) {
267 return CreateDemarshallArgs(out, deliver_pointer, num, (RPC_IN_ARG|RPC_OUT_ARG));
271 Arg::CreateDemarshallArgs(fstream& out, int deliver_pointer, int num, string &array_size_name) {
272 return CreateDemarshallArgs(out, deliver_pointer, num, (RPC_IN_ARG|RPC_OUT_ARG), array_size_name);
276 Arg::CreateDemarshallArgs(fstream& out, int deliver_pointer, int num, int in_out) {
278 return CreateDemarshallArgs(out, deliver_pointer, num, in_out, dummy);
282 * The arguments to rpc_demarshall_args() are generated for each API argument.
283 * for each API argument.
284 * out: Destination file
285 * deliver_pointer: Passing a Variable Pointer(non-0)
286 * num: Number given to the variable name of the argument (Examples: 1 for v1)
287 * in_out: Specifying the IN or OUT Attributes
288 * Output only if the argument has the specified attribute
291 Arg::CreateDemarshallArgs(fstream& out, int deliver_pointer, int num, int in_out, string &array_size_name) {
292 if ((m_in_out & in_out) != 0) {
294 * Collectively passes the argument type, pointer/non-pointer, IN/OUT attribute,
295 * and the maximum number of bytes of the argument type to one integer.
297 RPC_marshall_flag flag;
298 flag.bits.code = m_code & ((1<<RPC_MARSHALL_FLAG_BITS_CODE)-1);
299 flag.bits.is_vararray = ((array_size_name.size() != 0) ? 1: 0) &
300 ((1<<RPC_MARSHALL_FLAG_BITS_IS_VARARRAY)-1);
301 flag.bits.is_pointer = m_is_pointer & ((1<<RPC_MARSHALL_FLAG_BITS_IS_POINTER)-1);
302 flag.bits.in_out = m_in_out & ((1<<RPC_MARSHALL_FLAG_BITS_IN_OUT)-1);
303 flag.bits.bytes = (UINT16)(m_bytes);
305 sprintf(str, "0x%x", htonl(flag.all));
306 out << "\t\t\t" << str;
309 * Add size of user-defined type to argument
311 if (m_code == rpc_USER_DEFINED) {
312 out << " + ntohs(sizeof(" << m_type_name << "))";
316 if (deliver_pointer) {
328 Function::AppendArg(int code, int bytes, int is_pointer,
329 int is_vararray, int is_array_size,
330 const char *var_type_name, int in_out, const char *var_name) {
331 if (NumOfArgs() >= RPC_MAX_API_ARG_NUM) {
332 cout << "Too many API function arguments.\n";
335 Arg *a = new Arg(code, bytes, is_pointer, is_vararray, is_array_size,
336 var_type_name, in_out, var_name);
337 m_args.push_back(*a);
343 * Generate prototype declarations for a single API function
344 * out: Destination file
347 Function::PrintPrototype(fstream& out, int server) {
350 const char *return_type
351 = server ? RPC_API_SERVER_RETURN : RPC_API_CLIENT_RETURN;
353 if ((server) || (!rpc_log_enable)) {
354 out << return_type << " " << m_name << "(";
356 out << return_type << " __" << m_name << "(";
359 out << return_type << " " << m_name << "(";
362 list<Arg>::size_type num_args = m_args.size();
364 list<Arg>::iterator a;
366 for (list<Arg>::size_type i = 1; i <= num_args; ++i, ++a) {
367 a->PrintPrototype(out);
369 if ((server) || (!rpc_log_enable)) {
384 if ((server) || (!rpc_log_enable)) {
392 /* Debug information */
393 if ((!server) && (rpc_log_enable)) {
394 out << "const char *filename, const char *funcname, int line ";
403 Function::PrintMacro(fstream& out) {
405 out << "#define " << m_name << "(";
407 int num_args = m_args.size();
411 for (i = 1, c = 'a'; i <= num_args; i++, c++) {
420 out << "__" << m_name << "(";
421 for (i = 1, c = 'a'; i <= num_args; i++, c++) {
424 out << "__FILE__, __func__, __LINE__)\n";
425 } else { /* Without arguments */
426 out << ") " << "__" << m_name << "(__FILE__, __func__, __LINE__)\n";
434 APIDef::MakeHeaderFiles(int server) {
435 char filename[MAX_FILENAME_LEN+1];
436 sprintf(filename, "%s%s", m_lowerid.c_str(),
437 (server ? SERVER_HEADER_FILE : CLIENT_HEADER_FILE));
440 fstream out(filename, ios::out);
441 if (!out.is_open()) {
442 cout << "ERROR: File " << filename << " Could not open.\n";
445 cout << "info: Header file " << filename << " Creating.\n";
447 const char *define_str =
448 server ? SERVER_HEADER_DEFINE : CLIENT_HEADER_DEFINE;
449 const char *title = server ? SERVER_HEADER_TITLE : CLIENT_HEADER_TITLE;
451 out << "#ifndef _" << m_lowerid << define_str << "\n";
452 out << "#define _" << m_lowerid << define_str << "\n";
454 out << " * " << m_id << " " << title << " " << filename << "\n";
456 out << RPCTOOL_WARNING_STRING << "\n";
459 list<string>::iterator i;
460 for (i = m_headers.begin(); i != m_headers.end(); ++i) {
461 out << "#include <" << *i << ">\n";
467 out << EXTERN_C_START << "\n";
469 out << RPC_API_DISPATCH_RETURN << " "
470 << m_id << RPC_API_DISPATCH_FUNC_FULL << ";\n";
472 out << "#ifdef RPC_DISPATCH_FUNC\n"
473 << "#undef RPC_DISPATCH_FUNC\n"
474 << "#define RPC_DISPATCH_FUNC " << m_id << RPC_API_DISPATCH_FUNC_NAME
475 << "\n#else /* !RPC_DISPATCH_FUNC */\n"
476 << "#error \"Please include <rpc.h> first!!\"\n"
477 << "#endif /* !RPC_DISPATCH_FUNC */\n\n";
479 out << EXTERN_C_END << "\n";
483 else if (rpc_log_enable) {
484 /* DEBUG INFORMATION EMBEDDED MACRO */
485 out << "/* Debug information embedded macro definition */\n";
486 list<Function>::iterator f;
487 for (f = m_funcs.begin(); f != m_funcs.end(); ++f) {
488 if (f->PrintMacro(out) != 0) {
497 out << EXTERN_C_START << "\n";
499 out << "/* API definitions */\n";
500 list<Function>::iterator f;
501 for (f = m_funcs.begin(); f != m_funcs.end(); ++f) {
502 if (f->PrintPrototype(out, server) != 0) {
509 out << EXTERN_C_END << "\n";
511 out << "#endif /* _" << m_lowerid << define_str << " */\n";
517 Function::PrintServerStub(fstream& out) {
518 int num_args = NumOfArgs();
520 out << "\tcase " << RPC_API_NUM_PREFIX << m_name << ": {\n";
522 list<Arg>::iterator a = m_args.begin();
523 for (int i = 1; i <= num_args; ++i, ++a) {
524 const char *type = TypeCodeString(a->Code());
526 type = (a->TypeName()).c_str();
531 out << "\t\t" << type << " ";
532 if (a->Bytes() > 0 || a->IsPointer()) {/* Pointer-passing argument */
533 if (a->Bytes() > 0) {
534 out << "v" << i << " = NULL;\n";
535 } else if (a->IsPointer()) {
536 out << "*v" << i << " = NULL;\n";
538 } else {/* Pass-by-value argument */
539 out << "v" << i << ";\n";
543 out << "\t\tif (" << RPC_DEMARSHALL_FUNCTION
544 << " (args_string, args_size, 1, " << num_args << ",\n";
545 /* In the STUB of servers for all pre-call demarshall */
546 /* Passing Pointers to Local Variables in Server STUB */
547 /* Pointer/ Buffer will alloc the required space in demarshall_arguments() */
550 for (int i = 1; i <= num_args; ++i, ++a) {
551 if (a->IsVararray() != 0) { /* Variable-length arrays */
552 a->CreateDemarshallArgs(out, 1, i, m_array_size_name);
554 a->CreateDemarshallArgs(out, 1, i);
561 out << "\t\t ) < 0) {\n";
562 out << "\t\t\tgoto _" << m_name << "_Error;\n";
566 out << "\t\tresult = " << m_name << "(";
567 for (int i = 1; i <= num_args; i++) {
575 int to_process = NumOfInOutArgs(RPC_OUT_ARG);
576 if (to_process > 0) {
577 /* Only OUT-arguments marshall after the server stub is called. */
578 out << "\t\t/*if (result == RPC_OK) {*/\n";
579 out << "\t\t *ret_string = " << RPC_MARSHALL_FUNCTION
580 << "(ret_size, 0, " << to_process << ",\n";
585 for (int i = 1; i <= num_args; ++i, ++a) {
586 if (a->IsVararray() != 0) { /* Variable-length arrays */
587 ret = a->CreateMarshallArgs(out, i, RPC_OUT_ARG, m_array_size_name);
589 ret = a->CreateMarshallArgs(out, i, RPC_OUT_ARG);
593 if (processed < to_process) {
600 << "\t\t if (*ret_string == NULL) {\n"
601 << "\t\t\tresult = " << RPC_API_SERVER_ERROR << ";\n"
607 out << "_" << m_name << "_Error:\n";
609 int num_pointer_args = 0;
611 for (int i = 1; i <= num_args; ++i, ++a) {
612 if (a->Bytes() || a->IsPointer()) {
616 if (num_pointer_args > 0) {
618 out << "\t\t" << RPC_MARSHALL_FREE_FUNCTION
619 << "(" << num_pointer_args << ", ";
621 for (int i = 1; i <= num_args; ++i, ++a) {
622 if (a->Bytes() || a->IsPointer()) {
625 if (processed < num_pointer_args) {
632 out << "\t\tbreak;\n\t}\n";
637 APIDef::MakeServerStub(void) {
638 char filename[MAX_FILENAME_LEN+1];
639 sprintf(filename, "%s%s", m_lowerid.c_str(), SERVER_STUB_FILE);
642 fstream out(filename, ios::out);
643 if (!out.is_open()) {
644 cout << "File " << filename << " Could not open.\n";
647 cout << "info: Stub file " << filename << " Creating.\n";
649 const char *title = SERVER_STUB_TITLE;
652 out << " * " << m_id << " " << title << " " << filename << "\n";
654 out << RPCTOOL_WARNING_STRING << "\n";
656 out << "#include <" RPC_GLOBAL_HEADER_FILE << ">\n";
657 out << "#include \"" << m_lowerid << SERVER_HEADER_FILE << "\"\n";
658 out << "#include <netinet/in.h> /* for ntohs() */\n\n";
661 list<Function>::iterator f;
663 for (f = m_funcs.begin(); f != m_funcs.end(); ++f, ++api_num) {
664 if (api_num >= (1<<16)) {
665 cout << "Too many API functions.(Up to 65535)\n";
668 out << "#define " << RPC_API_NUM_PREFIX << f->Name()
669 << " " << api_num << "\n";
673 out << "RPC_Result\n";
674 out << m_id << RPC_API_DISPATCH_FUNC_FULL << "\n";
676 out << "\tRPC_Result result = " << RPC_API_SERVER_ERROR << ";\n";
677 out << "\t*ret_string = NULL;\n";
678 out << "\tswitch(api_num) {\n";
680 for (f = m_funcs.begin(); f != m_funcs.end(); ++f) {
681 if (f->PrintServerStub(out) != 0) {
691 out << "\tdefault:\n\t\tbreak;\n\t}\n";
692 out << "\treturn result;\n";
699 Function::PrintClientStub(const char *moduleid, fstream& out) {
702 list<Arg>::iterator a;
703 /* Function Names and Arguments */
704 out << RPC_API_CLIENT_RETURN << "\n";
706 if (rpc_log_enable) {
707 out << "__" << m_name << "(";
709 out << m_name << "(";
712 out << m_name << "(";
714 int num_args = (int)(m_args.size());
717 for (int i = 1; i <= num_args; ++i, ++a) {
718 if (a->PrintPrototype(out, i)) {
722 if (rpc_log_enable) {
739 if (!rpc_log_enable) {
745 if (rpc_log_enable) {
746 out << "const char *filename, const char *funcname, int line ";
753 /* Contents of stub functions */
755 /* If the argument is present and the variable-length array does not exist */
756 if ((num_args > 0) && (m_array_size_pos == 0)) {
757 int is_exist_mytype = 0;
758 /* Restricted specifications */
759 out << "#ifdef RPC_STATIC_ASSERT\n";
760 out << "\tchar RPC_TOTAL_ARGSIZE_ERROR_in_" << m_name << "[\n";
763 for (int i = 1; i <= num_args; ++i, ++a) {
768 a->PrintUndecoratedName(out, i);
771 if ((!is_exist_mytype) && (NULL == TypeCodeString(a->Code()))) {
775 out << ") > RPC_MAX_API_ARG_TOTAL_SIZE) ? -1: 1)\n";
776 out << "\t]__attribute__((unused));\n";
778 /* Have a user type */
779 if (is_exist_mytype) {
782 for (int i = 1; i <= num_args; ++i, ++a) {
783 if (NULL == TypeCodeString(a->Code())) {
785 out << "\tchar RPC_ARGSIZE_ERROR_in_" << m_name << "_arg" << c;
786 out << "[\n\t(sizeof(";
787 a->PrintUndecoratedName(out, i);
788 out << ") > RPC_MAX_API_ARG_SIZE) ? -1: 1\n";
789 out << "\t]__attribute__((unused));\n";
794 out << "#endif /* RPC_STATIC_ASSERT */\n";
798 out << "\tRPC_Result result = " << RPC_API_CLIENT_ERROR << ";\n";
799 out << "\tunsigned int args_size = 0, ret_size;\n";
800 out << "\tchar retcode[9];\n";
803 /* Advance preparation==Marshalling of arguments */
804 out << "\tchar *args_string = " << RPC_MARSHALL_FUNCTION
805 << "(&args_size, 1, " << num_args << ",\n";
806 /* In the clients STUB for all pre-call marshall */
808 for (int i = 1; i <= num_args; ++i, ++a) {
809 if (a->IsVararray() != 0) { /* Variable-length arrays */
810 a->CreateMarshallArgs(out, i, m_array_size_name);
812 a->CreateMarshallArgs(out, i);
820 out << "\tif (args_string == NULL) {\n"
821 << "\t\tgoto _" << m_name << "_Error;\n\t}\n";
823 out << "\tchar *args_string = NULL;\n";
827 if (rpc_log_enable) {
828 out << "\tif (" << moduleid << "_record_dbg_log(filename, funcname, line, \"";
829 out << m_name << "\") != 0) {\n";
830 out << "\t\tgoto _" << m_name << "_Error;\n\t}\n";
835 out << "\tchar *ret_string = NULL; /* pgr0431 */\n";
837 out << "\tresult=RPC_API_call(\"" << moduleid << "\", ";
839 out << "\tresult=RPC_API_call(" << moduleid << "_RPC_ID, ";
841 out << RPC_API_NUM_PREFIX << m_name;
842 out << ", args_string, args_size, &ret_string, &ret_size);\n";
844 // 2007.08.25 To avoid over run within the sscanf
845 // Locally copies strings needed for determining return values and uses strtol instead of sscanf
846 // (Since there is no guarantee that the byte sequence to be grabbed by communication is 0-terminated)
848 << "\tif (result == RPC_OK && ret_string != NULL) {\n"
849 << "\t strncpy(retcode, ret_string, 8);\n"
850 << "\t retcode[8] = '\\0';\n"
851 << "\t result = (RPC_Result)strtoul(retcode, NULL, 16);\n";
853 /* Post-processing==Arguments de-marshalling, free() */
854 int num_of_out_args = NumOfInOutArgs(RPC_OUT_ARG);
855 if (num_of_out_args > 0) {
856 out << "\t if (" << RPC_DEMARSHALL_FUNCTION
857 << "(ret_string + RPC_RETCODE_LEN, ret_size - RPC_RETCODE_LEN, 0, "
858 << num_of_out_args << ",\n";
863 for (int i = 1; i <= num_args; ++i, ++a) {
864 if (a->IsVararray() != 0) { /* Variable-length arrays */
865 ret = a->CreateDemarshallArgs(out, 0, i, RPC_OUT_ARG, m_array_size_name);
867 ret = a->CreateDemarshallArgs(out, 0, i, RPC_OUT_ARG);
871 if (processed < num_of_out_args) {
877 out << "\t ) < 0) {\n"
878 << "\t\tresult = " << RPC_API_CLIENT_ERROR << ";\n"
882 out << "\t} else {\n\t //result = " << RPC_API_CLIENT_ERROR << ";\n"
885 out << "\t" << RPC_RETURN_FREE_FUNCTION << "(ret_string);\n";
886 out << "\t" << RPC_MARSHALL_FREE_FUNCTION << "(1, args_string);\n";
892 if ((num_args)||(rpc_log_enable))
895 out << "_" << m_name << "_Error:\n";
898 out << "\treturn result;\n}\n";
904 APIDef::MakeClientStub(void) {
905 char filename[MAX_FILENAME_LEN+1];
906 sprintf(filename, "%s%s", m_lowerid.c_str(), CLIENT_STUB_FILE);
909 fstream out(filename, ios::out);
910 if (!out.is_open()) {
911 cout << "File " << filename << " Could not open.\n";
914 cout << "info: Stub file " << filename << " Creating.\n";
916 const char *title = CLIENT_STUB_TITLE;
919 out << " * " << m_id << " " << title << " " << filename << "\n";
921 out << RPCTOOL_WARNING_STRING << "\n";
923 out << "#include <" RPC_GLOBAL_HEADER_FILE << ">\n";
924 out << "#include <" << m_lowerid << CLIENT_HEADER_FILE << ">\n\n";
925 out << "#include <stdio.h> /* for sscanf() */\n";
926 out << "#include <stdlib.h> /* for getenv() */\n";
927 out << "#include <string.h> /* for strncpy() */\n";
928 out << "#include <netinet/in.h> /* for ntohs() */\n\n";
931 list<Function>::iterator f;
932 for (f = m_funcs.begin(); f != m_funcs.end(); ++f, ++api_num) {
933 if (api_num >= (1<<16)) {
934 cout << "Too many API functions.(Up to 65535)\n";
937 out << "#define " << RPC_API_NUM_PREFIX << f->Name()
938 << " " << api_num << "\n";
942 /* Specification Restriction Debug Constants */
943 out << "/*#define RPC_STATIC_ASSERT*/\n";
947 if (rpc_log_enable) {
949 string m_id_work = m_id;
950 for (m_id_work_cnt = 0; m_id_work_cnt < m_id_work.length(); m_id_work_cnt++) {
951 m_id_work[m_id_work_cnt] = toupper(m_id_work[m_id_work_cnt]);
953 out << "int\n" << m_id << "_record_dbg_log(const char *filename, " <<
954 "const char *funcname, int line, const char *apiname)\n";
956 out << "if (getenv(\"" << m_id_work << "_RPC_LOG\") != NULL) {\n\t\t";
957 out << "return RPC_record_dbg_log(filename, funcname, line, apiname);\n\t";
959 out << "return 0;\n";
964 /* API definitions */
965 for (f = m_funcs.begin(); f != m_funcs.end(); ++f) {
966 if (f->PrintClientStub(m_id.c_str(), out) != 0) {
975 Arg::IsArraySize(void) {
976 if (m_is_array_size != 0) {
977 if (IsTypeCodeNumeric(m_code) == 1) {
980 cout << "Variable-length array length specification variables must be integers.\n";
988 Function::CheckFuncArraySize(void) {
989 int num_args = (int)(m_args.size());
990 list<Arg>::iterator a;
992 for (int i = 1; i <= num_args; ++i, ++a) {
993 int ret = a->IsArraySize();
995 if (m_array_size_pos != 0)
997 cout << "Two or more variable array length specification arguments exist.\n";
1000 m_array_size_pos = i;
1001 a->GetUndecolatedName(m_array_size_name, i);
1002 } else if (ret < 0) {
1010 APIDef::CheckAllArraySize(void) {
1011 list<Function>::iterator f;
1012 for (f = m_funcs.begin(); f != m_funcs.end(); ++f) {
1013 if (f->CheckFuncArraySize() != 0) {
1021 APIDef::MakeStubs(void) {
1022 if (m_id.size() == 0) {
1023 cout << "The module name is not specified.\n";
1027 if (m_id.size() > MAX_FILENAME_LEN - strlen(SERVER_STUB_FILE)) {
1028 cout << "The module name is too long.\n";
1032 /* Pre-examine the ARRAYSIZE specification */
1033 //cout << "<check_all_array_size>\n";
1034 if (CheckAllArraySize() != 0) {
1038 //cout << "<MakeHeaderFiles(0)>\n";
1039 if (MakeHeaderFiles(1) != 0) {
1043 //cout << "<MakeHeaderFiles(1)>\n";
1044 if (MakeHeaderFiles(0) != 0) {
1048 if (MakeServerStub() != 0) {
1052 if (MakeClientStub() != 0) {
1062 if (m_name.size() > 0) {
1063 cout << "Variable name=" << m_name << " ";
1065 cout << "Type=" << TypeCodeString(m_code) << "In bytes=" << m_bytes << " ";
1069 if ((m_in_out & RPC_OUT_ARG) != 0) {
1076 Function::Print(int with_args) {
1077 printf("Function name=%s\n", m_name.c_str());
1079 list<Arg>::iterator a;
1080 for (a = m_args.begin(); a != m_args.end(); ++a) {
1087 APIDef::Print(int with_args) {
1088 list<Function>::iterator f;
1089 for (f = m_funcs.begin(); f != m_funcs.end(); ++f) {
1090 f->Print(with_args);
1095 APIDef::IdTolower(void) {
1096 char *lower = new char[m_id.size() + 1];
1097 strcpy(lower, m_id.c_str());
1099 for (p = lower; *p; p++) {
1100 *p = (char)(tolower(*p));