ic_cclient.erl

来自「OTP是开放电信平台的简称」· ERL 代码 · 共 1,213 行 · 第 1/3 页

ERL
1,213
字号
%% ``The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in%% compliance with the License. You should have received a copy of the%% Erlang Public License along with this software. If not, it can be%% retrieved via the world wide web at http://www.erlang.org/.%% %% Software distributed under the License is distributed on an "AS IS"%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See%% the License for the specific language governing rights and limitations%% under the License.%% %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings%% AB. All Rights Reserved.''%% %%     $Id$%%-module(ic_cclient).%% This module implements generation of C client code, where the%% client acts as an Erlang C-node, and where the communication thus%% is according to the Erlang distribution protocol.%%%% TODO:%% 1. ic_cbe:extract_info/3 is a silly name. %% 2. ParList, ParTypes, TypeList etc. what are they?%% 3. Zip is merging two lists (of the same length).%%-export([do_gen/3]).%%------------------------------------------------------------%% IMPLEMENTATION CONVENTIONS%%------------------------------------------------------------%% Functions:%%%% mk_*       returns things to be used. No side effects.%% emit_*     Writes to file. Has Fd in arguments.%% gen_*      Same, but has no Fd. Usually for larger things.%%%% Terminology for generating C:%%%% par_list   list of identifiers with types, types only, or with %%            parameters (arguments) only. %% arg_list   list of identifiers only (for function calls)%%%%------------------------------------------------------------%% Internal stuff%%-------------------------------------------------------------import(lists, [foreach/2, foldl/3, foldr/3]).-import(ic_codegen, [emit/2, emit/3, emit/4, emit_c_enc_rpt/4, emit_c_dec_rpt/4]).-include("icforms.hrl").-include("ic.hrl").-include_lib("stdlib/include/erl_compile.hrl").-define(IC_HEADER, "ic.h").-define(ERL_INTERFACEHEADER, "erl_interface.h").-define(EICONVHEADER, "ei.h").-define(ERLANGATOMLENGTH, "256").%%------------------------------------------------------------%% ENTRY POINT%%------------------------------------------------------------do_gen(G, File, Form) ->     OeName = ic_util:mk_oe_name(G, remove_ext(ic_util:to_list(File))),     G2 = ic_file:filename_push(G, [], OeName, c),     gen_headers(G2, [], Form),     R = gen(G2, [], Form),     ic_file:filename_pop(G2, c),     R.remove_ext(File) ->    filename:rootname(filename:basename(File)).%%------------------------------------------------------------%%%% Generate client side C stubs. %%%% - each module definition results in a separate file.%% - each interface definition results in a separate file.%%%%  G = record(genobj) (see ic.hrl)%%  N = scoped names in reverse%%  X = current form to consider. %%------------------------------------------------------------gen(G, N, [X| Xs]) when record(X, preproc) ->    G1 = change_file_stack(G, N, X),     gen(G1, N, Xs);gen(G, N, [X| Xs]) when record(X, module) ->    CD = ic_code:codeDirective(G, X),     G2 = ic_file:filename_push(G, N, X, CD),     N2 = [ic_forms:get_id2(X)| N],     gen_headers(G2, N2, X),     gen(G2, N2, ic_forms:get_body(X)),     G3 = ic_file:filename_pop(G2, CD),     gen(G3, N, Xs);gen(G, N, [X| Xs]) when record(X, interface) ->    G2 = ic_file:filename_push(G, N, X, c),     N2 = [ic_forms:get_id2(X)| N],     %% Sets the temporary variable counter.    put(op_variable_count, 0),     put(tmp_declarations, []),     gen_headers(G2, N2, X),     gen(G2, N2, ic_forms:get_body(X)),     lists:foreach(      fun({_Name, Body}) -> 	      gen(G2, N2, Body) end,       X#interface.inherit_body),     %% Generate Prototypes    gen_prototypes(G2, N2, X),     %% Generate generic preparation for decoding    gen_receive_info(G2, N2, X),     G3 = ic_file:filename_pop(G2, c),     gen(G3, N, Xs);gen(G, N, [X| Xs]) when record(X, const) ->    emit_constant(G, N, X),     gen(G, N, Xs);gen(G, N, [X| Xs]) when record(X, op) ->    {OpName, ArgNames, RetParTypes} = ic_cbe:extract_info(G, N, X),     %% XXX Note: N is the list of scoped ids of the *interface*.    gen_operation(G, N, X, OpName, ArgNames, RetParTypes),     gen_encoder(G, N, X, OpName, ArgNames, RetParTypes),     gen_decoder(G, N, X, OpName, ArgNames, RetParTypes),     gen(G, N, Xs);gen(G, N, [X| Xs]) when record(X, attr) ->    gen(G, N, Xs);gen(G, N, [X| Xs]) when record(X, except) ->    icstruct:except_gen(G, N, X, c),     gen(G, N, Xs);gen(G, N, [X| Xs]) when record(X, enum) ->    icenum:enum_gen(G, N, X, c),     gen(G, N, Xs);gen(G, N, [X| Xs]) when record(X, typedef) ->    icstruct:struct_gen(G, N, X, c),    gen(G, N, Xs);gen(G, N, [X| Xs]) when record(X, struct) ->    icstruct:struct_gen(G, N, X, c),    gen(G, N, Xs);gen(G, N, [X| Xs]) when record(X, union) ->    icstruct:struct_gen(G, N, X, c),    gen(G, N, Xs);gen(G, N, [_X| Xs]) ->    %% XXX Should have debug message here.    gen(G, N, Xs);gen(_G, _N, []) ->     ok.%%------------------------------------------------------------%% Change file stack%%------------------------------------------------------------change_file_stack(G, _N, X) when X#preproc.cat == line_nr ->    Id = ic_forms:get_id2(X),     Flags = X#preproc.aux,     case Flags of	[] -> 	    ic_genobj:push_file(G, Id);	_ ->	    foldr(	      fun({_, _, "1"}, G1) -> 		      ic_genobj:push_file(G1, Id);		 ({_, _, "2"}, G1) -> 		      ic_genobj:pop_file(G1, Id);		 ({_, _, "3"}, G1) -> 		      ic_genobj:sys_file(G1, Id) 	      end, G, Flags)    end;change_file_stack(G, _N, _X) ->    G.%%------------------------------------------------------------%% Generate headers in stubfiles and header files %%------------------------------------------------------------gen_headers(G, N, X) when record(X, interface) ->    case ic_genobj:is_hrlfile_open(G) of	true ->	    %% Set the temporary variable counter	    put(op_variable_count, 0), 	    put(tmp_declarations, []), 	    HFd = ic_genobj:hrlfiled(G), 	    IncludeFileStack = ic_genobj:include_file_stack(G), 	    L = length(N), 	    Filename =		if		    L < 2 ->			lists:nth(L + 1, IncludeFileStack);		    true ->			lists:nth(2, IncludeFileStack)		end, 	    emit(HFd, "#include \"~s\"\n", [filename:basename(Filename)]), 	    ic_code:gen_includes(HFd, G, X, c_client), 	    IfName = ic_util:to_undersc(N), 	    IfNameUC = ic_util:to_uppercase(IfName), 	    emit(HFd, "\n#ifndef __~s__\n", [IfNameUC]), 	    emit(HFd, "#define __~s__\n", [IfNameUC]), 	    LCmt = io_lib:format("Interface object definition: ~s", [IfName]), 	    ic_codegen:mcomment_light(HFd, [LCmt], c), 	    case get_c_timeout(G, "") of		"" ->		    ok;		{SendTmo, RecvTmo} ->		    emit(HFd, "#define OE_~s_SEND_TIMEOUT  ~s\n", 			 [IfNameUC, SendTmo]), 		    emit(HFd, "#define OE_~s_RECV_TIMEOUT  ~s\n", 			 [IfNameUC, RecvTmo]), 		    emit(HFd, "#ifndef EI_HAVE_TIMEOUT\n"),		    emit(HFd, "#error Functions for send and receive with "			 "timeout not defined in erl_interface\n"),		    emit(HFd, "#endif\n\n")	    end,	    emit(HFd, "typedef CORBA_Object ~s;\n", [IfName]), 	    emit(HFd, "#endif\n\n");	false -> ok    end,     case ic_genobj:is_stubfile_open(G) of	true ->	    Fd = ic_genobj:stubfiled(G), 	    ic_codegen:nl(Fd), 	    emit(Fd, "#include <stdlib.h>\n"), 	    emit(Fd, "#include <string.h>\n"), 	    case ic_options:get_opt(G, c_report) of 		true ->		    emit(Fd, "#ifndef OE_C_REPORT\n"), 		    emit(Fd, "#define OE_C_REPORT\n"), 		    emit(Fd, "#include <stdio.h>\n"), 		    emit(Fd, "#endif\n");		_  ->		    ok	    end,	    emit(Fd, "#include \"~s\"\n", [?IC_HEADER]), 	    emit(Fd, "#include \"~s\"\n", [?ERL_INTERFACEHEADER]), 	    emit(Fd, "#include \"~s\"\n", [?EICONVHEADER]), 	    emit(Fd, "#include \"~s\"\n", 		 [filename:basename(ic_genobj:include_file(G))]), 	    ic_codegen:nl(Fd), ic_codegen:nl(Fd), 	    Fd;					% XXX ??	false ->	    ok    end;%% Some items have extra includesgen_headers(G, N, X) when record(X, module) ->    case ic_genobj:is_hrlfile_open(G) of	true ->	    HFd = ic_genobj:hrlfiled(G), 	    IncludeFileStack = ic_genobj:include_file_stack(G), 	    Filename = lists:nth(length(N) + 1, IncludeFileStack), 	    emit(HFd, "#include \"~s\"\n", [filename:basename(Filename)]), 	    ic_code:gen_includes(HFd, G, X, c_client);	false -> ok    end;gen_headers(G, [], _X) ->     case ic_genobj:is_hrlfile_open(G) of	true ->	    HFd = ic_genobj:hrlfiled(G), 	    case ic_options:get_opt(G, c_report) of 		true ->		    emit(HFd, "#ifndef OE_C_REPORT\n"), 		    emit(HFd, "#define OE_C_REPORT\n"), 		    emit(HFd, "#include <stdio.h>\n"), 		    emit(HFd, "#endif\n");		_  ->		    ok	    end,	    emit(HFd, "#include \"~s\"\n", [?IC_HEADER]), 	    emit(HFd, "#include \"~s\"\n", [?ERL_INTERFACEHEADER]), 	    emit(HFd, "#include \"~s\"\n", [?EICONVHEADER]), 	    ic_code:gen_includes(HFd, G, c_client);	false -> ok    end;gen_headers(_G, _N, _X) ->     ok.%%------------------------------------------------------------%% Generate all prototypes (for interface)%%------------------------------------------------------------gen_prototypes(G, N, X) ->    case ic_genobj:is_hrlfile_open(G) of	false -> 	    ok;	true ->	    HFd = ic_genobj:hrlfiled(G), 	    IfName = ic_util:to_undersc(N), 	    %% Emit generated function prototypes	    emit(HFd, "\n/* Operation functions  */\n"), 	    lists:foreach(fun({_Name, Body}) ->				  emit_operation_prototypes(G, HFd, N, Body)			  end, [{x, ic_forms:get_body(X)}| 				X#interface.inherit_body]), 	    UserProto = get_user_proto(G, false),	    %% Emit generic function prototypes	    case UserProto of		false ->		    ok;		UserProto ->		    emit(HFd, 			 "\n/* Generic user defined encoders */\n"), 		    emit(HFd, 			 "int ~s_prepare_notification_encoding("			 "CORBA_Environment*);"			 "\n", [UserProto]), 		    emit(HFd, 			 "int ~s_prepare_request_encoding(CORBA_Environment*);"			 "\n", [UserProto])	    end,	    %% Emit encoding function prototypes	    emit(HFd, "\n/* Input encoders */\n"), 	    lists:foreach(fun({_Name, Body}) ->				  emit_encoder_prototypes(G, HFd, N, Body) 			  end, 			  [{x, ic_forms:get_body(X)}| 			   X#interface.inherit_body]), 	    %% Emit generic function prototypes	    emit(HFd, "\n/* Generic decoders */\n"), 	    emit(HFd, "int ~s__receive_info(~s, CORBA_Environment*);\n", 		 [IfName, IfName]), 	    case UserProto of		false ->		    ok;		UserProto ->		    emit(HFd, "\n/* Generic user defined decoders */\n"), 		    emit(HFd, 			 "int ~s_prepare_reply_decoding(CORBA_Environment*);"			 "\n", [UserProto]) 	    end,	    %% Emit decode function prototypes	    emit(HFd, "\n/* Result decoders */\n"), 	    lists:foreach(fun({_Name, Body}) ->				  emit_decoder_prototypes(G, HFd, N, Body) 			  end, [{x, ic_forms:get_body(X)}| 				X#interface.inherit_body]), 	    case UserProto of		false ->		    ok;		UserProto ->		    %% Emit generic send and receive_prototypes		    {Sfx, TmoType} = case get_c_timeout(G, "") of				     "" ->					 {"", ""};				     _ ->					 {"_tmo", ", unsigned int"} 			     end,		    emit(HFd, 			 "\n/* Generic user defined send and receive "			 "functions */\n"), 		    emit(HFd, 			 "int ~s_send_notification~s(CORBA_Environment*~s);\n",			 [UserProto, Sfx, TmoType]), 		    emit(HFd, 			 "int ~s_send_request_and_receive_reply~s("			 "CORBA_Environment*~s~s);\n", 			 [UserProto, Sfx, TmoType, TmoType])	    end    end.%%------------------------------------------------------------%% Generate receive_info() (generic part for message reception) %% (for interface). For backward compatibility only.%%------------------------------------------------------------gen_receive_info(G, N, _X) ->    case ic_genobj:is_stubfile_open(G) of	false ->	    ok;	true ->	    Fd = ic_genobj:stubfiled(G), 	    IfName = ic_util:to_undersc(N), 	    UserProto = get_user_proto(G, oe),	    Code = 		"

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?