Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenclient.c
Go to the documentation of this file.
00001 /* 00002 * IDL Compiler 00003 * 00004 * Copyright 2005-2006 Eric Kohl 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00019 */ 00020 00021 #include "config.h" 00022 #include "wine/port.h" 00023 00024 #include <stdio.h> 00025 #include <stdlib.h> 00026 #ifdef HAVE_UNISTD_H 00027 # include <unistd.h> 00028 #endif 00029 #include <string.h> 00030 #include <ctype.h> 00031 00032 #include "widl.h" 00033 #include "utils.h" 00034 #include "parser.h" 00035 #include "header.h" 00036 00037 #include "widltypes.h" 00038 #include "typegen.h" 00039 #include "expr.h" 00040 00041 static FILE* client; 00042 static int indent = 0; 00043 00044 static void print_client( const char *format, ... ) __attribute__((format (printf, 1, 2))); 00045 static void print_client( const char *format, ... ) 00046 { 00047 va_list va; 00048 va_start(va, format); 00049 print(client, indent, format, va); 00050 va_end(va); 00051 } 00052 00053 static void write_client_func_decl( const type_t *iface, const var_t *func ) 00054 { 00055 const char *callconv = get_attrp(func->type->attrs, ATTR_CALLCONV); 00056 const var_list_t *args = type_get_function_args(func->type); 00057 type_t *rettype = type_function_get_rettype(func->type); 00058 00059 if (!callconv) callconv = "__cdecl"; 00060 write_type_decl_left(client, rettype); 00061 fprintf(client, " %s ", callconv); 00062 fprintf(client, "%s%s(\n", prefix_client, get_name(func)); 00063 indent++; 00064 if (args) 00065 write_args(client, args, iface->name, 0, TRUE); 00066 else 00067 print_client("void"); 00068 fprintf(client, ")\n"); 00069 indent--; 00070 } 00071 00072 static void write_function_stub( const type_t *iface, const var_t *func, 00073 int method_count, unsigned int proc_offset ) 00074 { 00075 unsigned char explicit_fc, implicit_fc; 00076 int has_full_pointer = is_full_pointer_function(func); 00077 type_t *rettype = type_function_get_rettype(func->type); 00078 const var_t *handle_var = get_func_handle_var( iface, func, &explicit_fc, &implicit_fc ); 00079 int has_ret = !is_void(rettype); 00080 00081 if (is_interpreted_func( iface, func )) 00082 { 00083 write_client_func_decl( iface, func ); 00084 write_client_call_routine( client, iface, func, iface->name, proc_offset ); 00085 return; 00086 } 00087 00088 print_client( "struct __frame_%s%s\n{\n", prefix_client, get_name(func) ); 00089 indent++; 00090 print_client( "__DECL_EXCEPTION_FRAME\n" ); 00091 print_client("MIDL_STUB_MESSAGE _StubMsg;\n"); 00092 if (handle_var) 00093 { 00094 if (explicit_fc == RPC_FC_BIND_GENERIC) 00095 print_client("%s %s;\n", 00096 get_explicit_generic_handle_type(handle_var)->name, handle_var->name ); 00097 print_client("RPC_BINDING_HANDLE _Handle;\n"); 00098 } 00099 00100 if (has_ret && decl_indirect(rettype)) 00101 { 00102 print_client("void *_p_%s;\n", "_RetVal" ); 00103 } 00104 indent--; 00105 print_client( "};\n\n" ); 00106 00107 print_client( "static void __finally_%s%s(", prefix_client, get_name(func) ); 00108 print_client( " struct __frame_%s%s *__frame )\n{\n", prefix_client, get_name(func) ); 00109 indent++; 00110 00111 if (has_full_pointer) 00112 write_full_pointer_free(client, indent, func); 00113 00114 print_client("NdrFreeBuffer(&__frame->_StubMsg);\n"); 00115 00116 if (explicit_fc == RPC_FC_BIND_GENERIC) 00117 { 00118 fprintf(client, "\n"); 00119 print_client("if (__frame->_Handle)\n"); 00120 indent++; 00121 print_client("%s_unbind(__frame->%s, __frame->_Handle);\n", 00122 get_explicit_generic_handle_type(handle_var)->name, handle_var->name); 00123 indent--; 00124 } 00125 indent--; 00126 print_client( "}\n\n" ); 00127 00128 write_client_func_decl( iface, func ); 00129 00130 /* write the functions body */ 00131 fprintf(client, "{\n"); 00132 indent++; 00133 print_client( "struct __frame_%s%s __f, * const __frame = &__f;\n", prefix_client, get_name(func) ); 00134 00135 /* declare return value '_RetVal' */ 00136 if (has_ret) 00137 { 00138 print_client("%s", ""); 00139 write_type_decl_left(client, rettype); 00140 fprintf(client, " _RetVal;\n"); 00141 } 00142 print_client("RPC_MESSAGE _RpcMessage;\n"); 00143 00144 if (handle_var) 00145 { 00146 print_client( "__frame->_Handle = 0;\n" ); 00147 if (explicit_fc == RPC_FC_BIND_GENERIC) 00148 print_client("__frame->%s = %s;\n", handle_var->name, handle_var->name ); 00149 } 00150 if (has_ret && decl_indirect(rettype)) 00151 { 00152 print_client("__frame->_p_%s = &%s;\n", 00153 "_RetVal", "_RetVal"); 00154 } 00155 fprintf(client, "\n"); 00156 00157 print_client( "RpcExceptionInit( 0, __finally_%s%s );\n", prefix_client, get_name(func) ); 00158 00159 if (has_full_pointer) 00160 write_full_pointer_init(client, indent, func, FALSE); 00161 00162 /* check pointers */ 00163 write_pointer_checks( client, indent, func ); 00164 00165 print_client("RpcTryFinally\n"); 00166 print_client("{\n"); 00167 indent++; 00168 00169 print_client("NdrClientInitializeNew(&_RpcMessage, &__frame->_StubMsg, &%s_StubDesc, %d);\n", 00170 iface->name, method_count); 00171 00172 if (is_attr(func->attrs, ATTR_IDEMPOTENT) || is_attr(func->attrs, ATTR_BROADCAST)) 00173 { 00174 print_client("_RpcMessage.RpcFlags = ( RPC_NCA_FLAGS_DEFAULT "); 00175 if (is_attr(func->attrs, ATTR_IDEMPOTENT)) 00176 fprintf(client, "| RPC_NCA_FLAGS_IDEMPOTENT "); 00177 if (is_attr(func->attrs, ATTR_BROADCAST)) 00178 fprintf(client, "| RPC_NCA_FLAGS_BROADCAST "); 00179 fprintf(client, ");\n\n"); 00180 } 00181 00182 switch (explicit_fc) 00183 { 00184 case RPC_FC_BIND_PRIMITIVE: 00185 print_client("__frame->_Handle = %s;\n", handle_var->name); 00186 fprintf(client, "\n"); 00187 break; 00188 case RPC_FC_BIND_GENERIC: 00189 print_client("__frame->_Handle = %s_bind(%s);\n", 00190 get_explicit_generic_handle_type(handle_var)->name, handle_var->name); 00191 fprintf(client, "\n"); 00192 break; 00193 case RPC_FC_BIND_CONTEXT: 00194 { 00195 /* if the context_handle attribute appears in the chain of types 00196 * without pointers being followed, then the context handle must 00197 * be direct, otherwise it is a pointer */ 00198 int is_ch_ptr = !is_aliaschain_attr(handle_var->type, ATTR_CONTEXTHANDLE); 00199 print_client("if (%s%s != 0)\n", is_ch_ptr ? "*" : "", handle_var->name); 00200 indent++; 00201 print_client("__frame->_Handle = NDRCContextBinding(%s%s);\n", 00202 is_ch_ptr ? "*" : "", handle_var->name); 00203 indent--; 00204 if (is_attr(handle_var->attrs, ATTR_IN) && !is_attr(handle_var->attrs, ATTR_OUT)) 00205 { 00206 print_client("else\n"); 00207 indent++; 00208 print_client("RpcRaiseException(RPC_X_SS_IN_NULL_CONTEXT);\n"); 00209 indent--; 00210 } 00211 fprintf(client, "\n"); 00212 break; 00213 } 00214 case 0: /* implicit handle */ 00215 if (handle_var) 00216 { 00217 print_client("__frame->_Handle = %s;\n", handle_var->name); 00218 fprintf(client, "\n"); 00219 } 00220 break; 00221 } 00222 00223 write_remoting_arguments(client, indent, func, "", PASS_IN, PHASE_BUFFERSIZE); 00224 00225 print_client("NdrGetBuffer(&__frame->_StubMsg, __frame->_StubMsg.BufferLength, "); 00226 if (handle_var) 00227 fprintf(client, "__frame->_Handle);\n\n"); 00228 else 00229 fprintf(client,"%s__MIDL_AutoBindHandle);\n\n", iface->name); 00230 00231 /* marshal arguments */ 00232 write_remoting_arguments(client, indent, func, "", PASS_IN, PHASE_MARSHAL); 00233 00234 /* send/receive message */ 00235 /* print_client("NdrNsSendReceive(\n"); */ 00236 /* print_client("(unsigned char *)__frame->_StubMsg.Buffer,\n"); */ 00237 /* print_client("(RPC_BINDING_HANDLE *) &%s__MIDL_AutoBindHandle);\n", iface->name); */ 00238 print_client("NdrSendReceive(&__frame->_StubMsg, __frame->_StubMsg.Buffer);\n\n"); 00239 00240 print_client("__frame->_StubMsg.BufferStart = _RpcMessage.Buffer;\n"); 00241 print_client("__frame->_StubMsg.BufferEnd = __frame->_StubMsg.BufferStart + _RpcMessage.BufferLength;\n"); 00242 00243 if (has_out_arg_or_return(func)) 00244 { 00245 fprintf(client, "\n"); 00246 00247 print_client("if ((_RpcMessage.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)\n"); 00248 indent++; 00249 print_client("NdrConvert(&__frame->_StubMsg, (PFORMAT_STRING)&__MIDL_ProcFormatString.Format[%u]);\n", 00250 proc_offset); 00251 indent--; 00252 } 00253 00254 /* unmarshall arguments */ 00255 fprintf(client, "\n"); 00256 write_remoting_arguments(client, indent, func, "", PASS_OUT, PHASE_UNMARSHAL); 00257 00258 /* unmarshal return value */ 00259 if (has_ret) 00260 { 00261 if (decl_indirect(rettype)) 00262 print_client("MIDL_memset(&%s, 0, sizeof(%s));\n", "_RetVal", "_RetVal"); 00263 else if (is_ptr(rettype) || is_array(rettype)) 00264 print_client("%s = 0;\n", "_RetVal"); 00265 write_remoting_arguments(client, indent, func, "", PASS_RETURN, PHASE_UNMARSHAL); 00266 } 00267 00268 indent--; 00269 print_client("}\n"); 00270 print_client("RpcFinally\n"); 00271 print_client("{\n"); 00272 indent++; 00273 print_client( "__finally_%s%s( __frame );\n", prefix_client, get_name(func) ); 00274 indent--; 00275 print_client("}\n"); 00276 print_client("RpcEndFinally\n"); 00277 00278 00279 /* emit return code */ 00280 if (has_ret) 00281 { 00282 fprintf(client, "\n"); 00283 print_client("return _RetVal;\n"); 00284 } 00285 00286 indent--; 00287 fprintf(client, "}\n"); 00288 fprintf(client, "\n"); 00289 } 00290 00291 static void write_function_stubs(type_t *iface, unsigned int *proc_offset) 00292 { 00293 const statement_t *stmt; 00294 const var_t *implicit_handle = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE); 00295 int method_count = 0; 00296 00297 if (!implicit_handle) 00298 print_client("static RPC_BINDING_HANDLE %s__MIDL_AutoBindHandle;\n\n", iface->name); 00299 00300 STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) ) 00301 { 00302 const var_t *func = stmt->u.var; 00303 write_function_stub( iface, func, method_count++, *proc_offset ); 00304 *proc_offset += get_size_procformatstring_func( iface, func ); 00305 } 00306 } 00307 00308 00309 static void write_stubdescdecl(type_t *iface) 00310 { 00311 print_client("static const MIDL_STUB_DESC %s_StubDesc;\n", iface->name); 00312 fprintf(client, "\n"); 00313 } 00314 00315 00316 static void write_stubdescriptor(type_t *iface, int expr_eval_routines) 00317 { 00318 const var_t *implicit_handle = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE); 00319 00320 print_client("static const MIDL_STUB_DESC %s_StubDesc =\n", iface->name); 00321 print_client("{\n"); 00322 indent++; 00323 print_client("(void *)& %s___RpcClientInterface,\n", iface->name); 00324 print_client("MIDL_user_allocate,\n"); 00325 print_client("MIDL_user_free,\n"); 00326 print_client("{\n"); 00327 indent++; 00328 if (implicit_handle) 00329 print_client("&%s,\n", implicit_handle->name); 00330 else 00331 print_client("&%s__MIDL_AutoBindHandle,\n", iface->name); 00332 indent--; 00333 print_client("},\n"); 00334 print_client("0,\n"); 00335 if (!list_empty( &generic_handle_list )) 00336 print_client("BindingRoutines,\n"); 00337 else 00338 print_client("0,\n"); 00339 if (expr_eval_routines) 00340 print_client("ExprEvalRoutines,\n"); 00341 else 00342 print_client("0,\n"); 00343 print_client("0,\n"); 00344 print_client("__MIDL_TypeFormatString.Format,\n"); 00345 print_client("1, /* -error bounds_check flag */\n"); 00346 print_client("0x%x, /* Ndr library version */\n", get_stub_mode() == MODE_Oif ? 0x50002 : 0x10001); 00347 print_client("0,\n"); 00348 print_client("0x50100a4, /* MIDL Version 5.1.164 */\n"); 00349 print_client("0,\n"); 00350 print_client("%s,\n", list_empty(&user_type_list) ? "0" : "UserMarshalRoutines"); 00351 print_client("0, /* notify & notify_flag routine table */\n"); 00352 print_client("1, /* Flags */\n"); 00353 print_client("0, /* Reserved3 */\n"); 00354 print_client("0, /* Reserved4 */\n"); 00355 print_client("0 /* Reserved5 */\n"); 00356 indent--; 00357 print_client("};\n"); 00358 fprintf(client, "\n"); 00359 } 00360 00361 00362 static void write_clientinterfacedecl(type_t *iface) 00363 { 00364 unsigned int ver = get_attrv(iface->attrs, ATTR_VERSION); 00365 const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID); 00366 const str_list_t *endpoints = get_attrp(iface->attrs, ATTR_ENDPOINT); 00367 00368 if (endpoints) write_endpoints( client, iface->name, endpoints ); 00369 00370 print_client("static const RPC_CLIENT_INTERFACE %s___RpcClientInterface =\n", iface->name ); 00371 print_client("{\n"); 00372 indent++; 00373 print_client("sizeof(RPC_CLIENT_INTERFACE),\n"); 00374 print_client("{{0x%08x,0x%04x,0x%04x,{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x}},{%d,%d}},\n", 00375 uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0], uuid->Data4[1], 00376 uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5], uuid->Data4[6], 00377 uuid->Data4[7], MAJORVERSION(ver), MINORVERSION(ver)); 00378 print_client("{{0x8a885d04,0x1ceb,0x11c9,{0x9f,0xe8,0x08,0x00,0x2b,0x10,0x48,0x60}},{2,0}},\n"); /* FIXME */ 00379 print_client("0,\n"); 00380 if (endpoints) 00381 { 00382 print_client("%u,\n", list_count(endpoints)); 00383 print_client("(PRPC_PROTSEQ_ENDPOINT)%s__RpcProtseqEndpoint,\n", iface->name); 00384 } 00385 else 00386 { 00387 print_client("0,\n"); 00388 print_client("0,\n"); 00389 } 00390 print_client("0,\n"); 00391 print_client("0,\n"); 00392 print_client("0,\n"); 00393 indent--; 00394 print_client("};\n"); 00395 if (old_names) 00396 print_client("RPC_IF_HANDLE %s_ClientIfHandle DECLSPEC_HIDDEN = (RPC_IF_HANDLE)& %s___RpcClientInterface;\n", 00397 iface->name, iface->name); 00398 else 00399 print_client("RPC_IF_HANDLE %s%s_v%d_%d_c_ifspec DECLSPEC_HIDDEN = (RPC_IF_HANDLE)& %s___RpcClientInterface;\n", 00400 prefix_client, iface->name, MAJORVERSION(ver), MINORVERSION(ver), iface->name); 00401 fprintf(client, "\n"); 00402 } 00403 00404 00405 static void write_implicithandledecl(type_t *iface) 00406 { 00407 const var_t *implicit_handle = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE); 00408 00409 if (implicit_handle) 00410 { 00411 write_type_decl( client, implicit_handle->type, implicit_handle->name ); 00412 fprintf(client, ";\n\n"); 00413 } 00414 } 00415 00416 00417 static void init_client(void) 00418 { 00419 if (client) return; 00420 if (!(client = fopen(client_name, "w"))) 00421 error("Could not open %s for output\n", client_name); 00422 00423 print_client("/*** Autogenerated by WIDL %s from %s - Do not edit ***/\n", PACKAGE_VERSION, input_name); 00424 print_client("#include <string.h>\n"); 00425 print_client( "\n"); 00426 print_client("#include \"%s\"\n", header_name); 00427 print_client( "\n"); 00428 print_client( "#ifndef DECLSPEC_HIDDEN\n"); 00429 print_client( "#define DECLSPEC_HIDDEN\n"); 00430 print_client( "#endif\n"); 00431 print_client( "\n"); 00432 } 00433 00434 00435 static void write_client_ifaces(const statement_list_t *stmts, int expr_eval_routines, unsigned int *proc_offset) 00436 { 00437 const statement_t *stmt; 00438 if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry ) 00439 { 00440 if (stmt->type == STMT_TYPE && type_get_type(stmt->u.type) == TYPE_INTERFACE) 00441 { 00442 int has_func = 0; 00443 const statement_t *stmt2; 00444 type_t *iface = stmt->u.type; 00445 if (!need_stub(iface)) 00446 return; 00447 00448 fprintf(client, "/*****************************************************************************\n"); 00449 fprintf(client, " * %s interface\n", iface->name); 00450 fprintf(client, " */\n"); 00451 fprintf(client, "\n"); 00452 00453 STATEMENTS_FOR_EACH_FUNC(stmt2, type_iface_get_stmts(iface)) 00454 { 00455 has_func = 1; 00456 break; 00457 } 00458 00459 if (has_func) 00460 { 00461 write_implicithandledecl(iface); 00462 00463 write_clientinterfacedecl(iface); 00464 write_stubdescdecl(iface); 00465 write_function_stubs(iface, proc_offset); 00466 00467 print_client("#if !defined(__RPC_WIN%u__)\n", pointer_size == 8 ? 64 : 32); 00468 print_client("#error Invalid build platform for this stub.\n"); 00469 print_client("#endif\n"); 00470 00471 fprintf(client, "\n"); 00472 write_stubdescriptor(iface, expr_eval_routines); 00473 } 00474 } 00475 else if (stmt->type == STMT_LIBRARY) 00476 write_client_ifaces(stmt->u.lib->stmts, expr_eval_routines, proc_offset); 00477 } 00478 } 00479 00480 static void write_generic_handle_routine_list(void) 00481 { 00482 generic_handle_t *gh; 00483 00484 if (list_empty( &generic_handle_list )) return; 00485 print_client( "static const GENERIC_BINDING_ROUTINE_PAIR BindingRoutines[] =\n" ); 00486 print_client( "{\n" ); 00487 indent++; 00488 LIST_FOR_EACH_ENTRY( gh, &generic_handle_list, generic_handle_t, entry ) 00489 { 00490 print_client( "{ (GENERIC_BINDING_ROUTINE)%s_bind, (GENERIC_UNBIND_ROUTINE)%s_unbind },\n", 00491 gh->name, gh->name ); 00492 } 00493 indent--; 00494 print_client( "};\n\n" ); 00495 } 00496 00497 static void write_client_routines(const statement_list_t *stmts) 00498 { 00499 unsigned int proc_offset = 0; 00500 int expr_eval_routines; 00501 00502 if (need_inline_stubs_file( stmts )) 00503 { 00504 write_exceptions( client ); 00505 print_client( "\n"); 00506 } 00507 00508 write_formatstringsdecl(client, indent, stmts, need_stub); 00509 expr_eval_routines = write_expr_eval_routines(client, client_token); 00510 if (expr_eval_routines) 00511 write_expr_eval_routine_list(client, client_token); 00512 write_generic_handle_routine_list(); 00513 write_user_quad_list(client); 00514 00515 write_client_ifaces(stmts, expr_eval_routines, &proc_offset); 00516 00517 fprintf(client, "\n"); 00518 00519 write_procformatstring(client, stmts, need_stub); 00520 write_typeformatstring(client, stmts, need_stub); 00521 } 00522 00523 void write_client(const statement_list_t *stmts) 00524 { 00525 if (!do_client) 00526 return; 00527 if (do_everything && !need_stub_files(stmts)) 00528 return; 00529 00530 init_client(); 00531 if (!client) 00532 return; 00533 00534 if (do_win32 && do_win64) 00535 { 00536 fprintf(client, "#ifndef _WIN64\n\n"); 00537 pointer_size = 4; 00538 write_client_routines( stmts ); 00539 fprintf(client, "\n#else /* _WIN64 */\n\n"); 00540 pointer_size = 8; 00541 write_client_routines( stmts ); 00542 fprintf(client, "\n#endif /* _WIN64 */\n"); 00543 } 00544 else if (do_win32) 00545 { 00546 pointer_size = 4; 00547 write_client_routines( stmts ); 00548 } 00549 else if (do_win64) 00550 { 00551 pointer_size = 8; 00552 write_client_routines( stmts ); 00553 } 00554 00555 fclose(client); 00556 } Generated on Sat May 26 2012 04:24:50 for ReactOS by
1.7.6.1
|