X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;ds=sidebyside;f=service%2Fother%2Frpc_library%2Ftool%2Fapidef.y;fp=service%2Fother%2Frpc_library%2Ftool%2Fapidef.y;h=ce20c9c12ee82ca0f5a660c3b91a5f8747fee80b;hb=17cf21bcf8a2e29d2cbcf0a313474d2a4ee44f5d;hp=0000000000000000000000000000000000000000;hpb=9e86046cdb356913ae026f616e5bf17f6f238aa5;p=staging%2Fbasesystem.git diff --git a/service/other/rpc_library/tool/apidef.y b/service/other/rpc_library/tool/apidef.y new file mode 100755 index 0000000..ce20c9c --- /dev/null +++ b/service/other/rpc_library/tool/apidef.y @@ -0,0 +1,615 @@ +/** + * @file apidef.y + * @brief RPC tools--API definition file syntax definition and read/front-end processing + * + */ + +/*---------------------------------------------------------------------------*/ +/* C declarative statement */ +/*---------------------------------------------------------------------------*/ +%{ +#define YYDEBUG 1 +#define YYERROR_VERBOSE 1 + +#include +#include + +/* + * YACC to C I/F functions + */ +extern int yylex(void); /* LEX I/F */ +extern int yyerror(const char *); /* dummy */ + +#include "apidef.h" + +/* YACC to C I/F functions */ +static void AddHeader(const char *header_file); +static int push_function_arg(int arg_type, int num_of_bytes, + int is_pointer, + int is_vararray, int is_array_size, + const char *var_type_name, + int is_out, const char *var_name); +static void process_function(const char *funcname); +static void free_string(char *funcname); + +static int var_type; +static int num_of_bytes; +static int is_pointer; +static int in_out; +static int is_vararray; +static int is_array_size; +static char *var_type_name = NULL; + +%} + +/*---------------------------------------------------------------------------*/ +/* Bison declarations */ +/*---------------------------------------------------------------------------*/ +%union { + int ival; + char *strval; +} + +%token '"' +%left ',' +%left '(' +%right ')' +%left '*' +%token '{' +%token '}' +%token ';' +%token '\n' +%token rpc_INCLUDE 257 +%token RPC_RESULT 258 +%token rpc_NAME_DOT 259 +%token rpc_NAME 260 +%type funcdefs funcdef args +%type nonvoid_args arg var_type +%type var_primitive_type var_string_type var_user_defined_type +/* +%token rpc_OUT +*/ +%token rpc_INOUT 261 +%token rpc_CONST 262 +%token rpc_VARARRAY 263 +%token rpc_ARRAYSIZE 264 +%token rpc_NUM 265 +%token rpc_VOID 266 +%token rpc_CHAR 267 +%token rpc_INT 268 +%token rpc_SINT 269 +%token rpc_UINT 270 +%token rpc_INT8 271 +%token rpc_INT16 272 +%token rpc_INT32 273 +%token rpc_INT64 274 +%token rpc_UINT8 275 +%token rpc_UINT16 276 +%token rpc_UINT32 277 +%token rpc_UINT64 278 +%token rpc_FLOAT 279 +%token rpc_DOUBLE 280 +%token rpc_STRING 281 +%token rpc_USER_DEFINED 282 +%token rpc_UNKNOWN 283 + +/*---------------------------------------------------------------------------*/ +/* Grammar rule */ +/*---------------------------------------------------------------------------*/ +%% +input: includes funcdefs +; + +includes: /* empty input */ + | includes include +; + +include: rpc_INCLUDE '<' rpc_NAME_DOT '>' + { AddHeader($3); free_string($3); } +; + +funcdefs: funcdef + | funcdefs funcdef +; + +funcdef: RPC_RESULT rpc_NAME '(' args ')' ';' + { process_function($2); free_string($2);} +; + +args: rpc_VOID + | nonvoid_args +; + +nonvoid_args: arg + | nonvoid_args ',' arg +; + +arg: var_type rpc_NAME + { + if (push_function_arg(var_type, num_of_bytes, is_pointer, + is_vararray, is_array_size, + var_type_name, in_out, $2) < 0) { + YYERROR; + } + if (var_type_name) { free_string(var_type_name); } + var_type_name = NULL; + free_string($2); + } + | var_type + { + if (push_function_arg(var_type, num_of_bytes, is_pointer, + is_vararray, is_array_size, + var_type_name, in_out, NULL) < 0) { + YYERROR; + } + if (var_type_name) { free_string(var_type_name); } + var_type_name = NULL; + } +; + +/* + * Standard IN pointers are not allowed. + * When used as an array address, it is not clear how many bytes to copy. + * ->You are asked to declare the type and pass the address. + * Otherwise, you can simply pass it by value. + */ +var_type: var_primitive_type /* INT8, .. DOUBLE */ + { is_pointer = 0; is_vararray = 0; is_array_size = 0; in_out =RPC_IN_ARG; } + | var_primitive_type '*' /* OUT INT8 *, ... OUT DOUBLE * */ + { is_pointer = 1; is_vararray = 0; is_array_size = 0; in_out = RPC_OUT_ARG; } + /* if allow primitive IN pointer + | rpc_CONST var_primitive_type '*' + { is_pointer = 1; in_out = RPC_IN_ARG; } + */ + | var_string_type + /* OUT STRING128, ... */ + { is_pointer = 1; is_vararray = 0; is_array_size = 0; in_out = RPC_OUT_ARG; } + | rpc_CONST var_string_type + /* IN STRING128, ... */ + { is_pointer = 1; is_vararray = 0; is_array_size = 0; in_out = RPC_IN_ARG; } + | var_user_defined_type + { is_pointer = 0; is_vararray = 0; is_array_size = 0; in_out = RPC_IN_ARG; } + | var_user_defined_type '*' + { is_pointer = 1; is_vararray = 0; is_array_size = 0; in_out = RPC_OUT_ARG; } + | rpc_CONST var_user_defined_type '*' + { is_pointer = 1; is_vararray = 0; is_array_size = 0; in_out = RPC_IN_ARG; } + + /* INOUT specification */ + | rpc_INOUT var_string_type + /* IN STRING128, ... */ + { is_pointer = 1; is_vararray = 0; is_array_size = 0; in_out = RPC_INOUT_ARG; } + | rpc_INOUT var_user_defined_type '*' + { is_pointer = 1; is_vararray = 0; is_array_size = 0; in_out = RPC_INOUT_ARG; } + + /* Variable-length arrays */ + | rpc_CONST rpc_VARARRAY var_primitive_type '*' + { is_pointer = 1; is_vararray = 1; is_array_size = 0; in_out = RPC_IN_ARG; } + | rpc_VARARRAY var_primitive_type '*' + { is_pointer = 1; is_vararray = 1; is_array_size = 0; in_out = RPC_OUT_ARG; } + | rpc_INOUT rpc_VARARRAY var_primitive_type '*' + { is_pointer = 1; is_vararray = 1; is_array_size = 0; in_out = RPC_INOUT_ARG; } + | rpc_CONST rpc_VARARRAY var_user_defined_type '*' + { is_pointer = 1; is_vararray = 1; is_array_size = 0; in_out = RPC_IN_ARG; } + | rpc_VARARRAY var_user_defined_type '*' + { is_pointer = 1; is_vararray = 1; is_array_size = 0; in_out = RPC_OUT_ARG; } + | rpc_INOUT rpc_VARARRAY var_user_defined_type '*' + { is_pointer = 1; is_vararray = 1; is_array_size = 0; in_out = RPC_INOUT_ARG; } + + /* Variable length array size */ + | rpc_ARRAYSIZE var_primitive_type + { is_pointer = 0; is_vararray = 0; is_array_size = 1; in_out = RPC_IN_ARG; } +; + +var_primitive_type: + rpc_CHAR { var_type = $1; num_of_bytes = 0; var_type_name = NULL; } + | rpc_INT { var_type = $1; num_of_bytes = 0; var_type_name = NULL; } + | rpc_SINT { var_type = $1; num_of_bytes = 0; var_type_name = NULL; } + | rpc_UINT { var_type = $1; num_of_bytes = 0; var_type_name = NULL; } + | rpc_INT8 { var_type = $1; num_of_bytes = 0; var_type_name = NULL; } + | rpc_UINT8 { var_type = $1; num_of_bytes = 0; var_type_name = NULL; } + | rpc_INT16 { var_type = $1; num_of_bytes = 0; var_type_name = NULL; } + | rpc_UINT16 { var_type = $1; num_of_bytes = 0; var_type_name = NULL; } + | rpc_INT32 { var_type = $1; num_of_bytes = 0; var_type_name = NULL; } + | rpc_UINT32 { var_type = $1; num_of_bytes = 0; var_type_name = NULL; } + | rpc_INT64 { var_type = $1; num_of_bytes = 0; var_type_name = NULL; } + | rpc_UINT64 { var_type = $1; num_of_bytes = 0; var_type_name = NULL; } + | rpc_FLOAT { var_type = $1; num_of_bytes = 0; var_type_name = NULL; } + | rpc_DOUBLE { var_type = $1; num_of_bytes = 0; var_type_name = NULL; } +; + +var_string_type: rpc_STRING rpc_NUM + { var_type = $1; num_of_bytes = $2; var_type_name = NULL; } +; + +var_user_defined_type: rpc_NAME + { var_type = rpc_USER_DEFINED; num_of_bytes = 0; var_type_name = $1; } +; + +%% + +/*---------------------------------------------------------------------------*/ +/* C additional code */ +/*---------------------------------------------------------------------------*/ +/* Including an older bison results in an error */ +/*#include "apidef.tab.h"*/ + +#include +#include +#include +/* + * YACC/Lex interface functions/variables + */ +extern int yydebug; /* for YACC debug */ +extern int yyparse(void); +extern FILE *yyin; +extern int yy_flex_debug; /* for FLEX debug */ +/* my own function to free the buffer flex allocates */ +extern void free_flex_buffer(void); + +#ifdef DBG_ENABLE +char rpc_log_enable; +#endif + +/**/ +static void +AddHeader(const char *filename) +{ + ApidefAddHeader(filename); +} + +static int +push_function_arg(int arg_type, int num_of_bytes, int is_pointer, + int is_vararray, int is_array_size, + const char *var_type_name, int in_out, const char *var_name) +{ + switch(arg_type) { + case rpc_CHAR: + case rpc_INT: + case rpc_SINT: + case rpc_UINT: + case rpc_INT8: + case rpc_INT16: + case rpc_INT32: + case rpc_INT64: + case rpc_UINT8: + case rpc_UINT16: + case rpc_UINT32: + case rpc_UINT64: + case rpc_FLOAT: + case rpc_DOUBLE: + case rpc_STRING: + case rpc_USER_DEFINED: + return ApidefPushFunctionArg(arg_type, num_of_bytes, is_pointer, + is_vararray, is_array_size, + var_type_name, in_out, var_name); + break; + + default: + return -1; + break; + } +} + +static void +process_function(const char *funcname) +{ + ApidefProcessFunction(funcname); +} + +static void +free_string(char *s) +{ +#ifdef DEBUG + fprintf(stderr, "freed %s\n", s); +#endif + free(s); +} + +static void +extract_id(const char *filename, char **id) +{ + char *dotapi; + char *slash; + const char *start; + + if (id == NULL) { + return; + } + dotapi = strrchr(filename, '.'); + if (dotapi == NULL) { + return; + } + if (strcmp(dotapi, ".api")) { + return; + } + + slash = strrchr(filename, '/'); + start = filename; + if (slash != NULL) { + start = slash + 1; + } + + *id = malloc((size_t)(dotapi - start + 1)); + if (*id == NULL) { + return; + } + strncpy(*id, start, (size_t)(dotapi - start)); + (*id)[dotapi - start] = '\0'; +} + +static void +usage(const char *prog) +{ + fprintf(stdout, + "How to use: %s [CPPFLAGS] ... API definition file name\n", + prog); + fprintf(stdout, "Examples1: %s XXX.api\n", prog); + fprintf(stdout, "Examples2: %s -DSOME_DEFINES XXX.api\n", prog); +} + +#define CPP_PROG "cpp" +static void free_cpp_argv(char **argv); + +static char ** +prepare_cpp_argv(int argc, char *argv[]) +{ + char **cpp_argv; + char **ret; + + cpp_argv = malloc(sizeof(char *) * (long unsigned int)(argc+1)); + if (cpp_argv == NULL) { + return NULL; + } + memset(cpp_argv, 0, sizeof(char *) * (long unsigned int)(argc+1)); + ret = cpp_argv; + + cpp_argv[0] = malloc(strlen(CPP_PROG)+1); + if (cpp_argv[0] == NULL) { + free_cpp_argv(ret); + return NULL; + } + strcpy(cpp_argv[0], CPP_PROG); + cpp_argv++; + + for( ; *argv != NULL ; argv++, cpp_argv++) { + *cpp_argv = malloc(strlen(*argv)+1); + if (*cpp_argv == NULL) { + free_cpp_argv(ret); + return NULL; + } + strcpy(*cpp_argv, *argv); + } + *cpp_argv = NULL; + return ret; +} + +static void +free_cpp_argv(char **argv) +{ + char **orig; orig = argv; + while(*argv != NULL) { + free(*argv); + argv++; + } + free(orig); +} + +/** @ingroup RPCtool + * @brief RPCtool main functions + * + * Perform the following processing. + * + * - Lexical context analysis of the API definition file(See apidef.y and apidef.l) + * - The API function definition read from the definition file is stored in the APIDef class. + * - Outputs stub and header files from function definitions stored in APIDef after a successful read + */ +int +main(int argc, char *argv[]) +{ + int start; + char **cpp_argv; + int pipefd[2]; + int pid; + int ret; + + if (argc < 2) { + usage(argv[0]); + return 1; + } + + start = 1; + yy_flex_debug = 0; + + if (!strcmp(argv[1], "-d")) { + yydebug=1; + yy_flex_debug = 1; + if (argc > 2) { + start++; + } else { + usage(argv[0]); + return 1; + } + } + +#ifdef DBG_ENABLE + /* + * If the second-to-last argument is a log specification + */ + if ( ( argc >= 2 ) && (!strcmp(argv[argc-2], "-log")) ) { + rpc_log_enable = 1; + } else { + rpc_log_enable = 0; + } +#endif + + /* + * Extract ID from last argument (API definition file name) + */ + { + char *moduleid; + moduleid = NULL; + extract_id(argv[argc-1], &moduleid); + if (moduleid == NULL) { + fprintf(stdout, "%s: The API definition file name is invalid.\n", argv[0]); + usage(argv[0]); + return 1; + } + ApidefDefineId(moduleid); + free(moduleid); + } + + /* + * Preparing options to exec CPPs + */ + cpp_argv = prepare_cpp_argv(argc, argv + start); + if (cpp_argv == NULL) { + printf("No Memory!\n"); + return 1; + } + +#define PIPE_READ 0 +#define PIPE_WRITE 1 + + if (pipe(pipefd) != 0) { + perror("pipe"); + return 1; + } + + pid = fork(); + if (pid < 0) {/* fork error */ + close(pipefd[PIPE_READ]); + close(pipefd[PIPE_WRITE]); + perror("fork"); + return 1; + } + if (pid == 0) {/* child process */ + int must_be_1; + /* + * force stdout to be pipefd[PIPE_WRITE] + */ + close(pipefd[PIPE_READ]); + close(1); + must_be_1 = dup(pipefd[PIPE_WRITE]); + assert(must_be_1 == 1); + close(pipefd[PIPE_WRITE]); + /* + * invoke C preprocessor with flags + */ + execvp(CPP_PROG, cpp_argv); + perror("execvp"); + exit(0); + } else { + /* + * parent process + */ + int must_be_0; + free_cpp_argv(cpp_argv); + + /* + * force stdin to be pipefd[PIPE_READ] + */ + close(pipefd[PIPE_WRITE]); + close(0); + must_be_0 = dup(pipefd[PIPE_READ]); + assert(must_be_0 == 0); + close(pipefd[PIPE_READ]); + } + + ret = yyparse(); + + free_flex_buffer(); + + if (ret == 0) {/* Parsed successfully */ + //ApidefListFunctions(1); + ApidefMakeStubs(); + } else {/* Parse error occurred */ + fputs("The APIs that have been analyzed so far are as follows.\n", stdout); + fputs("-----start-----\n", stdout); + ApidefListFunctions(0); + fputs("------end------\n", stdout); + fputs("Check this API definition\n", stdout); + } + ApidefFreeAllocation(); + + return ret; +} + +int +yyerror(const char *s) +{ + printf("\nError: %s\n", s); + return 0; +} + +int +yywrap() +{ + return 1; +} + +static char const *Types[] = { + "char", + "int", + "signed int", + "unsigned int", + "INT8", + "INT16", + "INT32", + "INT64", + "UINT8", + "UINT16", + "UINT32", + "UINT64", + "float", + "double", + "char *", +}; + +static const int TypeCodes[] = { + rpc_CHAR, + rpc_INT, + rpc_SINT, + rpc_UINT, + rpc_INT8, + rpc_INT16, + rpc_INT32, + rpc_INT64, + rpc_UINT8, + rpc_UINT16, + rpc_UINT32, + rpc_UINT64, + rpc_FLOAT, + rpc_DOUBLE, + rpc_STRING, +}; + +const char * +TypeCodeString(const int code) +{ + int i; + int num; + num = sizeof(TypeCodes) / sizeof(int); + + for(i = 0 ; i < num ; i++) { + if (code == TypeCodes[i]) { + return Types[i]; + } + } + return NULL; +} + +int +IsTypeCodeNumeric( const int code ) +{ + int i; + + for(i = 0 ; i < sizeof(TypeCodes) / sizeof(TypeCodes[0]) ; i++) { + if (TypeCodes[i] == rpc_FLOAT) { + break; + } + if (code == TypeCodes[i]) { + return 1; + } + } + return 0; +}