aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ic/src/ic_cclient.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ic/src/ic_cclient.erl')
-rw-r--r--lib/ic/src/ic_cclient.erl1210
1 files changed, 0 insertions, 1210 deletions
diff --git a/lib/ic/src/ic_cclient.erl b/lib/ic/src/ic_cclient.erl
deleted file mode 100644
index 8591acf33f..0000000000
--- a/lib/ic/src/ic_cclient.erl
+++ /dev/null
@@ -1,1210 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--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.
-%%
-
--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 is_record(X, preproc) ->
- G1 = change_file_stack(G, N, X),
- gen(G1, N, Xs);
-
-gen(G, N, [X| Xs]) when is_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 is_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 is_record(X, const) ->
- emit_constant(G, N, X),
- gen(G, N, Xs);
-
-gen(G, N, [X| Xs]) when is_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 is_record(X, attr) ->
- gen(G, N, Xs);
-
-gen(G, N, [X| Xs]) when is_record(X, except) ->
- icstruct:except_gen(G, N, X, c),
- gen(G, N, Xs);
-
-gen(G, N, [X| Xs]) when is_record(X, enum) ->
- icenum:enum_gen(G, N, X, c),
- gen(G, N, Xs);
-
-gen(G, N, [X| Xs]) when is_record(X, typedef) ->
- icstruct:struct_gen(G, N, X, c),
- gen(G, N, Xs);
-
-gen(G, N, [X| Xs]) when is_record(X, struct) ->
- icstruct:struct_gen(G, N, X, c),
- gen(G, N, Xs);
-
-gen(G, N, [X| Xs]) when is_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 is_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 includes
-gen_headers(G, N, X) when is_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 =
- "
-/*
- * Generic function, used to return received message information.
- * Not used by oneways. Always generated. For backward compatibility only.
- */
-
-int ~s__receive_info(~s oe_obj, CORBA_Environment *oe_env)
-{
- return ~s_prepare_reply_decoding(oe_env);
-}\n",
- emit(Fd, Code, [IfName, IfName, UserProto])
-end.
-
-%%------------------------------------------------------------
-%% Emit constant
-%%------------------------------------------------------------
-
-emit_constant(G, N, ConstRecord) ->
- case ic_genobj:is_hrlfile_open(G) of
- false -> ok;
- true ->
- Fd = ic_genobj:hrlfiled(G),
- CName = ic_util:to_undersc(
- [ic_forms:get_id(ConstRecord#const.id)| N]),
- UCName = ic_util:to_uppercase(CName),
-
- emit(Fd, "\n#ifndef __~s__\n", [UCName]),
- emit(Fd, "#define __~s__\n", [UCName]),
-
- emit(Fd, "/* Constant: ~s */\n", [CName]),
-
- if is_record(ConstRecord#const.type, wstring) ->
- %% If wstring, add 'L'
- emit(Fd, "#define ~s L~p\n",
- [CName, ConstRecord#const.val]);
- true ->
- emit(Fd, "#define ~s ~p\n",
- [CName, ConstRecord#const.val])
- end,
- emit(Fd, "#endif\n\n")
- end.
-
-%%------------------------------------------------------------
-%% Generate operation (for interface)
-%%------------------------------------------------------------
-
-%% N is the list of scoped ids of the *interface*.
-%% X is the operation
-gen_operation(G, N, X, OpName, ArgNames, RetParTypes) ->
- case ic_genobj:is_stubfile_open(G) of
- true ->
- do_gen_operation(G, N, X, OpName, ArgNames, RetParTypes);
- false ->
- ok
- end.
-
-do_gen_operation(G, N, X, OpName, ArgNames, RetParTypes) ->
- Fd = ic_genobj:stubfiled(G),
- IfName = ic_util:to_undersc(N),
- IfNameUC = ic_util:to_uppercase(IfName),
-
- {R, ParTypes, _} = RetParTypes,
-
- IsOneway = ic_forms:is_oneway(X),
-
- emit(Fd, "\n"
- "/***\n"
- " *** Operation function \"~s\" ~s\n"
- " ***/\n\n",
- [OpName, ifelse(IsOneway, "(oneway)", "")]),
-
- RV = element(1, R),
- Ret = case IsOneway of
- false ->
- if RV /= void ->
- mk_ret_type(G, N, R);
- true ->
- "void"
- end;
- true ->
- "void"
- end,
- ParListStr = ic_util:chain(mk_par_type_list(G, N, X, [in, out],
- [types, args],
- ParTypes, ArgNames), ", "),
- emit(Fd,
- "~s ~s(~s, ~sCORBA_Environment *oe_env)\n{\n",
- [Ret, OpName, [IfName, " ", "oe_obj"], ParListStr]),
-
- case IsOneway of
- true ->
- ok;
- false ->
- case ictype:isArray(G, N, R) of
- true ->
- emit(Fd, " ~s oe_return = NULL;\n\n",
- [mk_ret_type(G, N, R)]);
- false ->
- if RV /= void ->
- emit(Fd, " ~s oe_return;\n\n",
- [Ret]);
- true ->
- ok
- end
- end,
- emit(Fd,
- " /* Initiating the message reference */\n"
- " ic_init_ref(oe_env, &oe_env->_unique);\n")
- end,
-
- emit(Fd,
- " /* Initiating exception indicator */ \n"
- " oe_env->_major = CORBA_NO_EXCEPTION;\n"),
-
- %% XXX Add pointer checks: checks of in-parameter
- %% pointers, and non-variable out-parameter pointers.
-
- emit(Fd," /* Creating ~s message */ \n",
- [ifelse(IsOneway, "cast", "call")]),
-
- EncParListStr = ic_util:chain(mk_arg_list_for_encoder(G, N, X,
- ParTypes, ArgNames),
- ", "),
- emit(Fd,
- " if (~s__client_enc(oe_obj, ~s""oe_env) < 0) {\n",
- [OpName, EncParListStr]),
- emit(Fd,
- " CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, "
- "DATA_CONVERSION, \"Cannot encode message\");\n"),
-
- RetVar = ifelse(RV /= void, " oe_return", ""),
- emit_c_enc_rpt(Fd, " ", "client operation ~s\\n====\\n", [OpName]),
-
- emit(Fd, " return~s;\n }\n", [RetVar]),
-
- emit(Fd," /* Sending ~s message */ \n",
- [ifelse(IsOneway, "cast", "call")]),
-
- UserProto = get_user_proto(G, oe),
- {Sfx, SendTmo, RecvTmo} = case get_c_timeout(G, "") of
- "" ->
- {"", "", ""};
- _ ->
- {"_tmo",
- [", OE_", IfNameUC, "_SEND_TIMEOUT"],
- [", OE_", IfNameUC, "_RECV_TIMEOUT"]}
- end,
-
- case IsOneway of
- true ->
- emit(Fd,
- " if (~s_send_notification~s(oe_env~s) < 0)\n"
- " return~s;\n", [UserProto, Sfx, SendTmo, RetVar]);
- false ->
- emit(Fd,
- " if (~s_send_request_and_receive_reply~s(oe_env~s~s) < 0)\n"
- " return~s;\n",
- [UserProto, Sfx, SendTmo, RecvTmo, RetVar]),
-
- DecParList0 = mk_arg_list_for_decoder(G, N, X,
- ParTypes, ArgNames),
- DecParList1 = case mk_ret_type(G, N, R) of
- "void" ->
- DecParList0;
- _ ->
- ["&oe_return"| DecParList0]
- end,
-
- DecParListStr = ic_util:chain(DecParList1, ", "),
- %% YYY Extracting results
- emit(Fd,
- " /* Extracting result value(s) */ \n"
- " if (~s__client_dec(oe_obj, ~s""oe_env) < 0) {\n",
- [OpName, DecParListStr]),
- emit(Fd,
- " CORBA_exc_set(oe_env, "
- "CORBA_SYSTEM_EXCEPTION, DATA_CONVERSION, "
- "\"Bad result value(s)\");\n"),
- emit_c_dec_rpt(Fd, " ", "client operation ~s\\n=====\\n", [OpName]),
- emit(Fd,
- " return~s;\n"
- " }\n", [RetVar])
- end,
- emit(Fd, " return~s;\n", [RetVar]),
- emit(Fd, "}\n\n\n").
-
-%%------------------------------------------------------------
-%% Generate encoder
-%%------------------------------------------------------------
-%% N is the list of scoped ids of the *interface*.
-%% X is the operation
-gen_encoder(G, N, X, OpName, ArgNames, RetParTypes)->
- case ic_genobj:is_stubfile_open(G) of
- true ->
- Fd = ic_genobj:stubfiled(G),
- IfName = ic_util:to_undersc(N),
- {_R, ParTypes, _} = RetParTypes,
- TypeAttrArgs = mk_type_attr_arg_list(ParTypes, ArgNames),
- emit(Fd, "/*\n * Encode operation input for \"~s\"\n */\n\n",
- [OpName]),
- ParList = ic_util:chain(
- mk_par_type_list(G, N, X, [in], [types, args],
- ParTypes, ArgNames), ", "),
- emit(Fd,
- "int ~s__client_enc(~s oe_obj, ~s"
- "CORBA_Environment *oe_env)\n{\n",
- [OpName, IfName, ParList]),
-
- InTypeAttrArgs = lists:filter(fun({_, in, _}) -> true;
- ({_, _, _}) -> false
- end, TypeAttrArgs),
- case InTypeAttrArgs of
- [] ->
- ok;
- _ ->
- emit(Fd,
- " int oe_error_code = 0;\n\n")
- end,
-
- emit_encodings(G, N, Fd, X, InTypeAttrArgs,
- ic_forms:is_oneway(X)),
- emit(Fd, " return 0;\n}\n\n"),
- ok;
-
- false ->
- ok
- end.
-
-%%------------------------------------------------------------
-%% Generate decoder
-%%------------------------------------------------------------
-%% N is the list of scoped ids of the *interface*.
-%% X is the operation
-gen_decoder(G, N, X, OpName, ArgNames, RetParTypes)->
- case ic_forms:is_oneway(X) of
- true ->
- ok;
- false ->
- case ic_genobj:is_stubfile_open(G) of
- true ->
- Fd = ic_genobj:stubfiled(G),
- IfName = ic_util:to_undersc(N),
- {R, ParTypes, _} = RetParTypes,
- TypeAttrArgs = mk_type_attr_arg_list(ParTypes, ArgNames),
- emit(Fd, "/*\n * Decode operation results for "
- "\"~s\"\n */\n\n", [OpName]),
- ParList0 = mk_par_type_list(G, N, X, [out],
- [types, args],
- ParTypes, ArgNames),
- PARLIST = case mk_ret_type(G, N, R) of
- "void" ->
- ParList0;
- Else ->
- [Else ++ "* oe_return"| ParList0]
- end,
- PLFCD = ic_util:chain(PARLIST, ", "),
- emit(Fd,
- "int ~s__client_dec(~s oe_obj, ~s"
- "CORBA_Environment *oe_env)\n{\n",
- [OpName, IfName, PLFCD]),
- emit(Fd, " int oe_error_code = 0;\n"),
- OutTypeAttrArgs = lists:filter(fun({_, out, _}) -> true;
- ({_, _, _}) -> false
- end, TypeAttrArgs),
- emit_decodings(G, N, Fd, R, OutTypeAttrArgs),
- emit(Fd, " return 0;\n}\n\n"),
- ok;
-
- false ->
- ok
- end
- end.
-
-%%------------------------------------------------------------
-%% EMIT ENCODINGS/DECODINGS
-%%------------------------------------------------------------
-%%------------------------------------------------------------
-%% Emit encodings
-%%------------------------------------------------------------
-%% N is the list of scoped ids of the *interface*.
-%% X is the operation
-%% emit_encodings(G, N, Fd, X, TypeAttrArgs, IsOneWay)
-%%
-emit_encodings(G, N, Fd, X, TypeAttrArgs, true) ->
- %% Cast
- UserProto = get_user_proto(G, oe),
- emit(Fd,
- " if (~s_prepare_notification_encoding(oe_env) < 0)\n"
- " return -1;\n", [UserProto]),
- emit_encodings_1(G, N, Fd, X, TypeAttrArgs);
-emit_encodings(G, N, Fd, X, TypeAttrArgs, false) ->
- %% Call
- UserProto = get_user_proto(G, oe),
- emit(Fd,
- " if (~s_prepare_request_encoding(oe_env) < 0)\n"
- " return -1;\n", [UserProto]),
- emit_encodings_1(G, N, Fd, X, TypeAttrArgs).
-
-emit_encodings_1(G, N, Fd, X, TypeAttrArgs) ->
- {ScopedName, _, _} = ic_cbe:extract_info(G, N, X),
- Name = case ic_options:get_opt(G, scoped_op_calls) of
- true ->
- ScopedName;
- false ->
- ic_forms:get_id2(X)
- end,
- if
- TypeAttrArgs /= [] ->
- emit(Fd, " if (oe_ei_encode_tuple_header(oe_env, ~p) < 0) {\n",
- [length(TypeAttrArgs) + 1]),
- emit_c_enc_rpt(Fd, " ", "ei_encode_tuple_header", []),
- emit(Fd, " return -1;\n }\n");
- true ->
- ok
- end,
- emit(Fd, " if (oe_ei_encode_atom(oe_env, ~p) < 0) {\n", [Name]),
- emit_c_enc_rpt(Fd, " ", "oe_ei_encode_atom", []),
- emit(Fd, " return -1;\n }\n"),
-
- foreach(fun({{'void', _}, _, _}) ->
- ok;
- ({T1, A1, N1}) ->
- IndOp = mk_ind_op(A1),
- emit_coding_comment(G, N, Fd, "Encode", IndOp,
- T1, N1),
- ic_cbe:emit_encoding_stmt(G, N, X, Fd, T1, IndOp ++ N1,
- "oe_env->_outbuf")
- end, TypeAttrArgs),
- ok.
-
-%%------------------------------------------------------------
-%% Emit dedodings
-%%------------------------------------------------------------
-%% XXX Unfortunately we have to retain the silly `oe_first' variable,
-%% since its name is hardcoded in other modules (icstruct, icunion,
-%% etc).
-%% N is the list of scoped ids of the *interface*.
-%% X is the operation
-emit_decodings(G, N, Fd, RetType, TypeAttrArgs) ->
- if
- TypeAttrArgs /= [] ->
- %% Only if there are out parameters
- emit(Fd, " if ((oe_error_code = ei_decode_tuple_header("
- "oe_env->_inbuf, &oe_env->_iin, "
- "&oe_env->_received)) < 0) {\n"),
- emit_c_dec_rpt(Fd, " ", "ei_decode_tuple_header", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- Len = length(TypeAttrArgs) + 1,
- emit(Fd, " if (oe_env->_received != ~p) {\n", [Len]),
- emit_c_dec_rpt(Fd, " ", "tuple header size != ~p", [Len]),
- emit(Fd, " return -1;\n }\n");
- true ->
- ok
- end,
-
- %% Fetch the return value
- emit_coding_comment(G, N, Fd, "Decode return value", "*", RetType, "oe_return"),
- APars =
- case ic_cbe:is_variable_size(G, N, RetType) of
- true ->
- emit(Fd,
- " {\n"
- " int oe_size_count_index = oe_env->_iin;\n"
- " int oe_malloc_size = 0;\n"
- " void *oe_first = NULL;\n"),
- ic_cbe:emit_malloc_size_stmt(G, N, Fd, RetType,
- "oe_env->_inbuf",
- 1, caller),
- %% XXX Add malloc prefix from option
- emit(Fd,
- " OE_MALLOC_SIZE_CHECK(oe_env, oe_malloc_size);\n"
- " if ((*oe_return = oe_first = "
- "malloc(oe_malloc_size)) == NULL) {\n"
- " CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, "
- "NO_MEMORY, \"Cannot malloc\");\n"
- " return -1;\n"
- " }\n"),
- Pars = ["*oe_return"],
- DecType = case ictype:isArray(G, N, RetType) of
- true -> array_dyn;
- false -> caller_dyn
- end,
- ic_cbe:emit_decoding_stmt(G, N, Fd, RetType,
- "(*oe_return)",
- "", "oe_env->_inbuf", 1,
- "&oe_outindex", DecType,
- Pars),
- emit(Fd, " }\n"),
- Pars;
- false ->
- case ictype:isArray(G, N, RetType) of
- true ->
- Pars = ["*oe_return"],
- emit(Fd,
- " {\n"
- " int oe_size_count_index = oe_env->_iin;\n"
- " int oe_malloc_size = 0;\n"
- " void *oe_first = NULL;\n"),
- ic_cbe:emit_malloc_size_stmt(G, N, Fd, RetType,
- "oe_env->_inbuf",
- 1, caller),
- %% XXX Add malloc prefix from option
- emit(Fd,
- " OE_MALLOC_SIZE_CHECK(oe_env, "
- "oe_malloc_size);\n"
- " if ((*oe_return = oe_first = "
- "malloc(oe_malloc_size)) == NULL) {\n"
- " CORBA_exc_set(oe_env, "
- "CORBA_SYSTEM_EXCEPTION, NO_MEMORY, "
- "\"Cannot malloc\");\n"
- " return -1;"
- " }\n"),
- ic_cbe:emit_decoding_stmt(G, N, Fd, RetType,
- "oe_return", "",
- "oe_env->_inbuf", 1,
- "&oe_outindex",
- array_fix_ret,
- Pars),
- emit(Fd, " }\n"),
- Pars;
- false ->
- Pars = [],
- %% The last parameter "oe_outindex" is not interesting
- %% in the static case.
- ic_cbe:emit_decoding_stmt(G, N, Fd, RetType,
- "oe_return", "",
- "oe_env->_inbuf", 1,
- "&oe_outindex",
- caller, Pars),
- ic_codegen:nl(Fd),
- Pars
- end
- end,
-
- foldl(fun({{'void', _}, _, _}, Acc) ->
- Acc;
- ({T, A, N1}, Acc) ->
- emit_one_decoding(G, N, Fd, T, A, N1, Acc)
- end, APars, TypeAttrArgs),
- ok.
-
-emit_one_decoding(G, N, Fd, T, A, N1, Acc) ->
- IndOp = mk_ind_op(A),
- case ic_cbe:is_variable_size(G, N, T) of
- true ->
- emit_coding_comment(G, N, Fd, "Decode", IndOp,
- T, N1),
- emit(Fd,
- " {\n"
- " int oe_size_count_index = oe_env->_iin;\n"
- " int oe_malloc_size = 0;\n"
- " void *oe_first = NULL;\n"),
- ic_cbe:emit_malloc_size_stmt(G, N, Fd, T,
- "oe_env->_inbuf",
- 1, caller),
- %% XXX Add malloc prefix from option
- emit(Fd,
- " OE_MALLOC_SIZE_CHECK(oe_env, oe_malloc_size);\n"
- " if ((~s~s = oe_first = "
- "malloc(oe_malloc_size)) == NULL) {\n", [IndOp, N1]),
- ic_cbe:emit_dealloc_stmts(Fd, " ", Acc),
- emit(Fd,
- " CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, "
- "NO_MEMORY, \"Cannot malloc\");\n"
- " return -1;\n"
- " }\n"),
- NAcc = [IndOp ++ N1| Acc],
- DecType = case ictype:isArray(G, N, T) of
- true ->
- array_dyn;
- false ->
- caller_dyn
- end,
- ic_cbe:emit_decoding_stmt(G, N, Fd, T,
- "(" ++ IndOp
- ++ N1 ++ ")", "",
- "oe_env->_inbuf", 1,
- "&oe_outindex",
- DecType, NAcc),
- emit(Fd, " }\n"),
- NAcc;
- false ->
- case ictype:isArray(G, N, T) of
- true ->
- emit_coding_comment(G, N, Fd, "Decode", "",
- T, N1),
- ic_cbe:emit_decoding_stmt(G, N, Fd, T, N1,
- "", "oe_env->_inbuf",
- 1, "&oe_outindex",
- array_fix_out, Acc),
- ic_codegen:nl(Fd),
- [N1| Acc];
- false ->
- %% The last parameter "oe_outindex" is
- %% not interesting in the static case, but
- %% must be present anyhow.
- emit_coding_comment(G, N, Fd, "Decode",
- IndOp, T, N1),
- ic_cbe:emit_decoding_stmt(G, N, Fd, T, N1,
- "", "oe_env->_inbuf",
- 1, "&oe_outindex",
- caller, Acc),
- ic_codegen:nl(Fd),
- Acc
- end
- end.
-
-%%------------------------------------------------------------
-%% GENERATE PROTOTYPES
-%%------------------------------------------------------------
-%%------------------------------------------------------------
-%% Generate operation prototypes
-%%------------------------------------------------------------
-emit_operation_prototypes(G, Fd, N, Xs) ->
- lists:foreach(
- fun(X) when is_record(X, op) ->
- {ScopedName, ArgNames, RetParTypes} =
- ic_cbe:extract_info(G, N, X),
- {R, ParTypes, _} = RetParTypes,
- IfName = ic_util:to_undersc(N),
- RT = mk_ret_type(G, N, R),
- ParList =
- ic_util:chain(
- mk_par_type_list(G, N, X, [in, out], [types],
- ParTypes, ArgNames),
- ", "),
- emit(Fd, "~s ~s(~s, ~sCORBA_Environment*);\n",
- [RT, ScopedName, IfName, ParList]);
- (_) ->
- ok
- end, Xs).
-
-%%------------------------------------------------------------
-%% Generate encoder prototypes
-%%------------------------------------------------------------
-emit_encoder_prototypes(G, Fd, N, Xs) ->
- lists:foreach(
- fun(X) when is_record(X, op) ->
- {ScopedName, ArgNames, RetParTypes} =
- ic_cbe:extract_info(G, N, X),
- {_R, ParTypes, _} = RetParTypes,
- IfName = ic_util:to_undersc(N),
- ParList = ic_util:chain(
- mk_par_type_list(G, N, X, [in], [types],
- ParTypes, ArgNames),
- ", "),
- emit(Fd, "int ~s__client_enc(~s, ~sCORBA_Environment*);\n",
- [ScopedName, IfName, ParList]);
- (_) ->
- ok
- end, Xs).
-
-%%------------------------------------------------------------
-%% Generate decoder prototypes
-%%------------------------------------------------------------
-emit_decoder_prototypes(G, Fd, N, Xs) ->
- lists:foreach(
- fun(X) when is_record(X, op) ->
- case ic_forms:is_oneway(X) of
- true ->
- true;
- false ->
- IfName = ic_util:to_undersc(N),
- {ScopedName, ArgNames, RetParTypes} =
- ic_cbe:extract_info(G, N, X),
- {R, ParTypes, _} = RetParTypes,
- ParList0 =
- mk_par_type_list(G, N, X, [out], [types],
- ParTypes, ArgNames),
- PARLIST = case mk_ret_type(G, N, R) of
- "void" ->
- ParList0;
- Else ->
- [Else ++ "*"| ParList0]
- end,
- ParList = ic_util:chain(PARLIST, ", "),
- emit(Fd, "int ~s__client_dec(~s, ~s"
- "CORBA_Environment*);\n",
- [ScopedName, IfName, ParList])
- end;
- (_) ->
- ok
- end, Xs).
-
-%%------------------------------------------------------------
-%% PARAMETER TYPE LISTS
-%%------------------------------------------------------------
-%%------------------------------------------------------------
-%% Make parameter type list
-%%
-%% InOrOut = in | out | [in | out]
-%% TypesOrArgs = types | args | [types | args]
-%%------------------------------------------------------------
-mk_par_type_list(G, N, X, InOrOut, TypesOrArgs, Types, Args) ->
- TypeAttrArgs =
- filterzip(
- fun(_, {inout, Arg}) ->
- ic_error:error(G, {inout_spec_for_c, X, Arg}),
- false;
- (Type, {Attr, Arg}) ->
- case lists:member(Attr, InOrOut) of
- true ->
- {true, {Type, Attr, Arg}};
- false ->
- false
- end
- end, Types, Args),
- lists:map(
- fun({Type, Attr, Arg}) ->
- Ctype = ic_cbe:mk_c_type(G, N, Type),
- IsArray = ictype:isArray(G, N, Type),
- IsStruct = ictype:isStruct(G, N, Type),
- IsUnion = ictype:isUnion(G, N, Type),
- Dyn =
- case ic_cbe:is_variable_size(G, N, Type) of
- true ->
- if
- is_record(Type, string) -> "";
- Ctype == "CORBA_char *" -> "";
- is_record(Type, wstring) -> "";
- Ctype == "CORBA_wchar *" -> "";
- true ->
- case IsArray of
- true ->
- "_slice*";
- false ->
- "*"
- end
- end;
- false ->
- if
- Attr == in, Ctype == "erlang_pid" ->
- "*";
- Attr == in, Ctype == "erlang_port" ->
- "*";
- Attr == in, Ctype == "erlang_ref" ->
- "*";
- Attr == in, IsStruct == true ->
- "*";
- Attr == in, IsUnion == true ->
- "*";
- Attr == in, IsArray == true ->
- "_slice*";
- Attr == out, IsArray == true ->
- "_slice";
- true ->
- ""
- end
- end,
- IndOp = mk_ind_op(Attr),
- case {lists:member(types, TypesOrArgs),
- lists:member(args, TypesOrArgs)} of
- {true, true} ->
- Ctype ++ Dyn ++ IndOp ++ " " ++ Arg;
- {true, false} ->
- Ctype ++ Dyn ++ IndOp;
- {false, true} ->
- Arg;
- {false, false} ->
- ""
- end
- end, TypeAttrArgs).
-
-%%------------------------------------------------------------
-%% ENCODER ARG LIST
-%%------------------------------------------------------------
-%%------------------------------------------------------------
-%% Make encoder argument list XXX
-%%------------------------------------------------------------
-mk_arg_list_for_encoder(G, _N, X, Types, Args) ->
- filterzip(
- fun(_, {out, _}) ->
- false;
- (_, {inout, Arg}) ->
- ic_error:error(G, {inout_spec_for_c, X, Arg}),
- false;
- (_Type, {in, Arg}) ->
- {true, Arg}
- end, Types, Args).
-
-%%------------------------------------------------------------
-%% DECODER ARG LIST
-%%------------------------------------------------------------
-%%------------------------------------------------------------
-%% Make decoder argument list XXX
-%%------------------------------------------------------------
-mk_arg_list_for_decoder(G, _N, X, Types, Args) ->
- filterzip(fun(_, {in, _}) ->
- false;
- (_, {inout, Arg}) ->
- ic_error:error(G, {inout_spec_for_c, X, Arg}),
- false;
- (_, {out, Arg}) ->
- {true, Arg}
- end, Types, Args).
-
-%%------------------------------------------------------------
-%% MISC
-%%------------------------------------------------------------
-%%------------------------------------------------------------
-%% Make list of {Type, Attr, Arg}
-%%------------------------------------------------------------
-mk_type_attr_arg_list(Types, Args) ->
- filterzip(fun(Type, {Attr, Arg}) ->
- {true, {Type, Attr, Arg}}
- end, Types, Args).
-
-%%------------------------------------------------------------
-%% Make return type
-%%------------------------------------------------------------
-mk_ret_type(G, N, Type) ->
- Ctype = ic_cbe:mk_c_type(G, N, Type),
- Dyn = case ic_cbe:is_variable_size(G, N, Type) of
- true ->
- if
- is_record(Type, string) ->
- "";
- Ctype == "CORBA_char *" ->
- "";
- is_record(Type, wstring) ->
- "";
- Ctype == "CORBA_wchar *" ->
- "";
- true ->
- case ictype:isArray(G, N, Type) of
- true ->
- "_slice*";
- false ->
- "*"
- end
- end;
- false ->
- case ictype:isArray(G, N, Type) of
- true ->
- "_slice*";
- false ->
- ""
- end
- end,
- Ctype ++ Dyn.
-
-
-%%------------------------------------------------------------
-%% Make indirection operator (to "*" or not to "*").
-%%------------------------------------------------------------
-mk_ind_op(in) ->
- "";
-mk_ind_op(inout) ->
- error;
-mk_ind_op(out) ->
- "*".
-
-%%------------------------------------------------------------
-%% Emit encoding/decoding comment
-%%------------------------------------------------------------
-emit_coding_comment(G, N, Fd, String, RefOrVal, Type, Name) ->
- emit(Fd, " /* ~s parameter: ~s~s ~s */\n",
- [String, ic_cbe:mk_c_type(G, N, Type), RefOrVal, Name]).
-
-%%------------------------------------------------------------
-%% User protocol prefix for generic functions
-%%------------------------------------------------------------
-get_user_proto(G, Default) ->
- case ic_options:get_opt(G, user_protocol) of
- false ->
- Default;
- Pfx ->
- Pfx
- end.
-
-%%------------------------------------------------------------
-%% Timeout. Returns a string (or Default).
-%%------------------------------------------------------------
-get_c_timeout(G, Default) ->
- case ic_options:get_opt(G, c_timeout) of
- Tmo when is_integer(Tmo) ->
- TmoStr = integer_to_list(Tmo),
- {TmoStr, TmoStr};
- {SendTmo, RecvTmo} when is_integer(SendTmo) andalso is_integer(RecvTmo) ->
- {integer_to_list(SendTmo), integer_to_list(RecvTmo)};
- false ->
- Default
- end.
-
-%%------------------------------------------------------------
-%% ZIPPERS (merging of successive elements of two lists).
-%%------------------------------------------------------------
-
-%% zip([H1| T1], [H2| T2]) ->
-%% [{H1, H2}| zip(T1, T2)];
-%% zip([], []) ->
-%% [].
-
-filterzip(F, [H1| T1], [H2| T2]) ->
- case F(H1, H2) of
- false ->
- filterzip(F, T1, T2);
- {true, Val} ->
- [Val| filterzip(F, T1, T2)]
- end;
-filterzip(_, [], []) ->
- [].
-
-
-ifelse(true, A, _) ->
- A;
-ifelse(false, _, B) ->
- B.