3 * @brief RPC tools--API definition file syntax definition and read/front-end processing
7 /*---------------------------------------------------------------------------*/
8 /* C declarative statement */
9 /*---------------------------------------------------------------------------*/
12 #define YYERROR_VERBOSE 1
18 * YACC to C I/F functions
20 extern int yylex(void); /* LEX I/F */
21 extern int yyerror(const char *); /* dummy */
25 /* YACC to C I/F functions */
26 static void AddHeader(const char *header_file);
27 static int push_function_arg(int arg_type, int num_of_bytes,
29 int is_vararray, int is_array_size,
30 const char *var_type_name,
31 int is_out, const char *var_name);
32 static void process_function(const char *funcname);
33 static void free_string(char *funcname);
36 static int num_of_bytes;
37 static int is_pointer;
39 static int is_vararray;
40 static int is_array_size;
41 static char *var_type_name = NULL;
45 /*---------------------------------------------------------------------------*/
46 /* Bison declarations */
47 /*---------------------------------------------------------------------------*/
62 %token <strval> rpc_INCLUDE 257
63 %token <strval> RPC_RESULT 258
64 %token <strval> rpc_NAME_DOT 259
65 %token <strval> rpc_NAME 260
66 %type <strval> funcdefs funcdef args
67 %type <strval> nonvoid_args arg var_type
68 %type <strval> var_primitive_type var_string_type var_user_defined_type
70 %token <strval> rpc_OUT
72 %token <strval> rpc_INOUT 261
73 %token <strval> rpc_CONST 262
74 %token <strval> rpc_VARARRAY 263
75 %token <strval> rpc_ARRAYSIZE 264
76 %token <ival> rpc_NUM 265
77 %token <strval> rpc_VOID 266
78 %token <ival> rpc_CHAR 267
79 %token <ival> rpc_INT 268
80 %token <ival> rpc_SINT 269
81 %token <ival> rpc_UINT 270
82 %token <ival> rpc_INT8 271
83 %token <ival> rpc_INT16 272
84 %token <ival> rpc_INT32 273
85 %token <ival> rpc_INT64 274
86 %token <ival> rpc_UINT8 275
87 %token <ival> rpc_UINT16 276
88 %token <ival> rpc_UINT32 277
89 %token <ival> rpc_UINT64 278
90 %token <ival> rpc_FLOAT 279
91 %token <ival> rpc_DOUBLE 280
92 %token <ival> rpc_STRING 281
93 %token <ival> rpc_USER_DEFINED 282
94 %token <ival> rpc_UNKNOWN 283
96 /*---------------------------------------------------------------------------*/
98 /*---------------------------------------------------------------------------*/
100 input: includes funcdefs
103 includes: /* empty input */
107 include: rpc_INCLUDE '<' rpc_NAME_DOT '>'
108 { AddHeader($3); free_string($3); }
115 funcdef: RPC_RESULT rpc_NAME '(' args ')' ';'
116 { process_function($2); free_string($2);}
124 | nonvoid_args ',' arg
127 arg: var_type rpc_NAME
129 if (push_function_arg(var_type, num_of_bytes, is_pointer,
130 is_vararray, is_array_size,
131 var_type_name, in_out, $2) < 0) {
134 if (var_type_name) { free_string(var_type_name); }
135 var_type_name = NULL;
140 if (push_function_arg(var_type, num_of_bytes, is_pointer,
141 is_vararray, is_array_size,
142 var_type_name, in_out, NULL) < 0) {
145 if (var_type_name) { free_string(var_type_name); }
146 var_type_name = NULL;
151 * Standard IN pointers are not allowed.
152 * When used as an array address, it is not clear how many bytes to copy.
153 * ->You are asked to declare the type and pass the address.
154 * Otherwise, you can simply pass it by value.
156 var_type: var_primitive_type /* INT8, .. DOUBLE */
157 { is_pointer = 0; is_vararray = 0; is_array_size = 0; in_out =RPC_IN_ARG; }
158 | var_primitive_type '*' /* OUT INT8 *, ... OUT DOUBLE * */
159 { is_pointer = 1; is_vararray = 0; is_array_size = 0; in_out = RPC_OUT_ARG; }
160 /* if allow primitive IN pointer
161 | rpc_CONST var_primitive_type '*'
162 { is_pointer = 1; in_out = RPC_IN_ARG; }
165 /* OUT STRING128, ... */
166 { is_pointer = 1; is_vararray = 0; is_array_size = 0; in_out = RPC_OUT_ARG; }
167 | rpc_CONST var_string_type
168 /* IN STRING128, ... */
169 { is_pointer = 1; is_vararray = 0; is_array_size = 0; in_out = RPC_IN_ARG; }
170 | var_user_defined_type
171 { is_pointer = 0; is_vararray = 0; is_array_size = 0; in_out = RPC_IN_ARG; }
172 | var_user_defined_type '*'
173 { is_pointer = 1; is_vararray = 0; is_array_size = 0; in_out = RPC_OUT_ARG; }
174 | rpc_CONST var_user_defined_type '*'
175 { is_pointer = 1; is_vararray = 0; is_array_size = 0; in_out = RPC_IN_ARG; }
177 /* INOUT specification */
178 | rpc_INOUT var_string_type
179 /* IN STRING128, ... */
180 { is_pointer = 1; is_vararray = 0; is_array_size = 0; in_out = RPC_INOUT_ARG; }
181 | rpc_INOUT var_user_defined_type '*'
182 { is_pointer = 1; is_vararray = 0; is_array_size = 0; in_out = RPC_INOUT_ARG; }
184 /* Variable-length arrays */
185 | rpc_CONST rpc_VARARRAY var_primitive_type '*'
186 { is_pointer = 1; is_vararray = 1; is_array_size = 0; in_out = RPC_IN_ARG; }
187 | rpc_VARARRAY var_primitive_type '*'
188 { is_pointer = 1; is_vararray = 1; is_array_size = 0; in_out = RPC_OUT_ARG; }
189 | rpc_INOUT rpc_VARARRAY var_primitive_type '*'
190 { is_pointer = 1; is_vararray = 1; is_array_size = 0; in_out = RPC_INOUT_ARG; }
191 | rpc_CONST rpc_VARARRAY var_user_defined_type '*'
192 { is_pointer = 1; is_vararray = 1; is_array_size = 0; in_out = RPC_IN_ARG; }
193 | rpc_VARARRAY var_user_defined_type '*'
194 { is_pointer = 1; is_vararray = 1; is_array_size = 0; in_out = RPC_OUT_ARG; }
195 | rpc_INOUT rpc_VARARRAY var_user_defined_type '*'
196 { is_pointer = 1; is_vararray = 1; is_array_size = 0; in_out = RPC_INOUT_ARG; }
198 /* Variable length array size */
199 | rpc_ARRAYSIZE var_primitive_type
200 { is_pointer = 0; is_vararray = 0; is_array_size = 1; in_out = RPC_IN_ARG; }
204 rpc_CHAR { var_type = $1; num_of_bytes = 0; var_type_name = NULL; }
205 | rpc_INT { var_type = $1; num_of_bytes = 0; var_type_name = NULL; }
206 | rpc_SINT { var_type = $1; num_of_bytes = 0; var_type_name = NULL; }
207 | rpc_UINT { var_type = $1; num_of_bytes = 0; var_type_name = NULL; }
208 | rpc_INT8 { var_type = $1; num_of_bytes = 0; var_type_name = NULL; }
209 | rpc_UINT8 { var_type = $1; num_of_bytes = 0; var_type_name = NULL; }
210 | rpc_INT16 { var_type = $1; num_of_bytes = 0; var_type_name = NULL; }
211 | rpc_UINT16 { var_type = $1; num_of_bytes = 0; var_type_name = NULL; }
212 | rpc_INT32 { var_type = $1; num_of_bytes = 0; var_type_name = NULL; }
213 | rpc_UINT32 { var_type = $1; num_of_bytes = 0; var_type_name = NULL; }
214 | rpc_INT64 { var_type = $1; num_of_bytes = 0; var_type_name = NULL; }
215 | rpc_UINT64 { var_type = $1; num_of_bytes = 0; var_type_name = NULL; }
216 | rpc_FLOAT { var_type = $1; num_of_bytes = 0; var_type_name = NULL; }
217 | rpc_DOUBLE { var_type = $1; num_of_bytes = 0; var_type_name = NULL; }
220 var_string_type: rpc_STRING rpc_NUM
221 { var_type = $1; num_of_bytes = $2; var_type_name = NULL; }
224 var_user_defined_type: rpc_NAME
225 { var_type = rpc_USER_DEFINED; num_of_bytes = 0; var_type_name = $1; }
230 /*---------------------------------------------------------------------------*/
231 /* C additional code */
232 /*---------------------------------------------------------------------------*/
233 /* Including an older bison results in an error */
234 /*#include "apidef.tab.h"*/
240 * YACC/Lex interface functions/variables
242 extern int yydebug; /* for YACC debug */
243 extern int yyparse(void);
245 extern int yy_flex_debug; /* for FLEX debug */
246 /* my own function to free the buffer flex allocates */
247 extern void free_flex_buffer(void);
255 AddHeader(const char *filename)
257 ApidefAddHeader(filename);
261 push_function_arg(int arg_type, int num_of_bytes, int is_pointer,
262 int is_vararray, int is_array_size,
263 const char *var_type_name, int in_out, const char *var_name)
281 case rpc_USER_DEFINED:
282 return ApidefPushFunctionArg(arg_type, num_of_bytes, is_pointer,
283 is_vararray, is_array_size,
284 var_type_name, in_out, var_name);
294 process_function(const char *funcname)
296 ApidefProcessFunction(funcname);
303 fprintf(stderr, "freed %s\n", s);
309 extract_id(const char *filename, char **id)
318 dotapi = strrchr(filename, '.');
319 if (dotapi == NULL) {
322 if (strcmp(dotapi, ".api")) {
326 slash = strrchr(filename, '/');
332 *id = malloc((size_t)(dotapi - start + 1));
336 strncpy(*id, start, (size_t)(dotapi - start));
337 (*id)[dotapi - start] = '\0';
341 usage(const char *prog)
344 "How to use: %s [CPPFLAGS] ... API definition file name\n",
346 fprintf(stdout, "Examples1: %s XXX.api\n", prog);
347 fprintf(stdout, "Examples2: %s -DSOME_DEFINES XXX.api\n", prog);
350 #define CPP_PROG "cpp"
351 static void free_cpp_argv(char **argv);
354 prepare_cpp_argv(int argc, char *argv[])
359 cpp_argv = malloc(sizeof(char *) * (long unsigned int)(argc+1));
360 if (cpp_argv == NULL) {
363 memset(cpp_argv, 0, sizeof(char *) * (long unsigned int)(argc+1));
366 cpp_argv[0] = malloc(strlen(CPP_PROG)+1);
367 if (cpp_argv[0] == NULL) {
371 strcpy(cpp_argv[0], CPP_PROG);
374 for( ; *argv != NULL ; argv++, cpp_argv++) {
375 *cpp_argv = malloc(strlen(*argv)+1);
376 if (*cpp_argv == NULL) {
380 strcpy(*cpp_argv, *argv);
387 free_cpp_argv(char **argv)
389 char **orig; orig = argv;
390 while(*argv != NULL) {
398 * @brief RPCtool main functions
400 * Perform the following processing.
402 * - Lexical context analysis of the API definition file(See apidef.y and apidef.l)
403 * - The API function definition read from the definition file is stored in the APIDef class.
404 * - Outputs stub and header files from function definitions stored in APIDef after a successful read
407 main(int argc, char *argv[])
423 if (!strcmp(argv[1], "-d")) {
436 * If the second-to-last argument is a log specification
438 if ( ( argc >= 2 ) && (!strcmp(argv[argc-2], "-log")) ) {
446 * Extract ID from last argument (API definition file name)
451 extract_id(argv[argc-1], &moduleid);
452 if (moduleid == NULL) {
453 fprintf(stdout, "%s: The API definition file name is invalid.\n", argv[0]);
457 ApidefDefineId(moduleid);
462 * Preparing options to exec CPPs
464 cpp_argv = prepare_cpp_argv(argc, argv + start);
465 if (cpp_argv == NULL) {
466 printf("No Memory!\n");
473 if (pipe(pipefd) != 0) {
479 if (pid < 0) {/* fork error */
480 close(pipefd[PIPE_READ]);
481 close(pipefd[PIPE_WRITE]);
485 if (pid == 0) {/* child process */
488 * force stdout to be pipefd[PIPE_WRITE]
490 close(pipefd[PIPE_READ]);
492 must_be_1 = dup(pipefd[PIPE_WRITE]);
493 assert(must_be_1 == 1);
494 close(pipefd[PIPE_WRITE]);
496 * invoke C preprocessor with flags
498 execvp(CPP_PROG, cpp_argv);
506 free_cpp_argv(cpp_argv);
509 * force stdin to be pipefd[PIPE_READ]
511 close(pipefd[PIPE_WRITE]);
513 must_be_0 = dup(pipefd[PIPE_READ]);
514 assert(must_be_0 == 0);
515 close(pipefd[PIPE_READ]);
522 if (ret == 0) {/* Parsed successfully */
523 //ApidefListFunctions(1);
525 } else {/* Parse error occurred */
526 fputs("The APIs that have been analyzed so far are as follows.\n", stdout);
527 fputs("-----start-----\n", stdout);
528 ApidefListFunctions(0);
529 fputs("------end------\n", stdout);
530 fputs("Check this API definition\n", stdout);
532 ApidefFreeAllocation();
538 yyerror(const char *s)
540 printf("\nError: %s\n", s);
550 static char const *Types[] = {
568 static const int TypeCodes[] = {
587 TypeCodeString(const int code)
591 num = sizeof(TypeCodes) / sizeof(int);
593 for(i = 0 ; i < num ; i++) {
594 if (code == TypeCodes[i]) {
602 IsTypeCodeNumeric( const int code )
606 for(i = 0 ; i < sizeof(TypeCodes) / sizeof(TypeCodes[0]) ; i++) {
607 if (TypeCodes[i] == rpc_FLOAT) {
610 if (code == TypeCodes[i]) {