%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
%%
%% 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 online 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.
%%
%% %CopyrightEnd%
%%
%%
-module(icstruct).
-export([struct_gen/4, except_gen/4, create_c_array_coding_file/5]).
%%------------------------------------------------------------
%%
%% Internal stuff
%%
%%------------------------------------------------------------
-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").
%%------------------------------------------------------------
%%------------------------------------------------------------
%%
%% File handling stuff
%%
%%------------------------------------------------------------
%%------------------------------------------------------------
%%
%% Generation loop
%%
%% The idea is to traverse everything and find every struct that
%% may be hiding down in nested types. All structs that are found
%% are generated to a hrl file.
%%
%% struct_gen is entry point for structs and types, except_gen is
%% for exceptions
%%
%%------------------------------------------------------------
except_gen(G, N, X, L) when is_record(X, except) ->
N2 = [ic_forms:get_id2(X) | N],
if
L == c ->
io:format("Warning : Exception not defined for c mapping\n", []);
true ->
emit_struct(G, N, X, L)
end,
struct_gen_list(G, N2, ic_forms:get_body(X), L).
struct_gen(G, N, X, L) when is_record(X, struct) ->
N2 = [ic_forms:get_id2(X) | N],
struct_gen_list(G, N2, ic_forms:get_body(X), L),
emit_struct(G, N, X, L);
struct_gen(G, N, X, L) when is_record(X, union) ->
N2 = [ic_forms:get_id2(X) | N],
if
L == c ->
%% Produce the "body" first
struct_gen_list(G, N2, ic_forms:get_body(X), L),
icunion:union_gen(G, N, X, c);
true ->
struct_gen(G, N, ic_forms:get_type(X), L),
struct_gen_list(G, N2, ic_forms:get_body(X), L)
end,
emit_union(G, N, X, L);
struct_gen(G, N, X, L) when is_record(X, member) ->
struct_gen(G, N, ic_forms:get_type(X), L);
struct_gen(G, N, X, L) when is_record(X, typedef) ->
struct_gen(G, N, ic_forms:get_body(X), L),
emit_typedef(G, N, X, L);
struct_gen(G, N, X, L) when is_record(X, type_dcl) ->
struct_gen_list(G, N, ic_forms:get_type(X), L);
struct_gen(G, N, X, L) when is_record(X, case_dcl) ->
struct_gen(G, N, ic_forms:get_type(X), L);
struct_gen(G, N, X, L) when is_record(X, sequence) ->
struct_gen(G, N, ic_forms:get_type(X), L),
X;
struct_gen(G, N, X, L) when is_record(X, enum) ->
icenum:enum_gen(G, N, X, L);
struct_gen(_G, _N, _X, _L) ->
ok.
%% List clause for struct_gen
struct_gen_list(G, N, Xs, L) ->
lists:foreach(
fun(X) ->
R = struct_gen(G, N, X, L),
if
L == c ->
if
is_record(R,sequence) ->
emit_sequence_head_def(G,N,X,R,L);
true ->
ok
end;
true ->
ok
end
end, Xs).
%% emit primitive for structs.
emit_struct(G, N, X, erlang) ->
case ic_genobj:is_hrlfile_open(G) of
true ->
%% Make a straight list of all member ids (this is a
%% variant of flatten)
EList = lists:map(
fun(XX) ->
lists:map(
fun(XXX) ->
ic_util:to_atom(ic_forms:get_id2(XXX))
end,
ic_forms:get_idlist(XX))
end,
ic_forms:get_body(X)),
ic_codegen:record(G, X,
ic_util:to_undersc([ic_forms:get_id2(X) | N]),
ictk:get_IR_ID(G, N, X), lists:flatten(EList)),
mkFileRecObj(G,N,X,erlang);
false ->
ok
end;
emit_struct(G, N, X, c) ->
N1 = [ic_forms:get_id2(X) | N],
case ic_pragma:is_local(G,N1) of
true ->
emit_c_struct(G, N, X,local);
false ->
emit_c_struct(G, N, X,included)
end.
emit_c_struct(_G, _N, _X, included) ->
%% Do not generate included types att all.
ok;
emit_c_struct(G, N, X, local) ->
case ic_genobj:is_hrlfile_open(G) of
true ->
Fd = ic_genobj:hrlfiled(G),
N1 = [ic_forms:get_id2(X) | N],
StructName = ic_util:to_undersc(N1),
%% Make a straight list of all member ids (this is a
%% variant of flatten)
M = lists:map(
fun(XX) ->
lists:map(
fun(XXX) ->
if
is_record(XXX, array) ->
Type = ic_forms:get_type(XX),
Name = element(3,element(2,XXX)),
{_, _, StructTK, _} =
ic_symtab:get_full_scoped_name(
G,
N,
ic_symtab:scoped_id_new(
ic_forms:get_id2(X))),
ArrayTK =
get_structelement_tk(StructTK,
Name),
Dim = extract_dim(ArrayTK),
%% emit array file
emit(Fd, "\n#ifndef __~s__\n",
[ic_util:to_uppercase(
StructName ++ "_"
++ Name)]),
emit(Fd, "#define __~s__\n\n",
[ic_util:to_uppercase(
StructName ++ "_"
++ Name)]),
create_c_array_coding_file(
G,
N,
{StructName ++ "_" ++ Name, Dim},
Type,
no_typedef),
emit(Fd, "\n#endif\n\n"),
{{Type, XXX},
ic_forms:get_id2(XXX)};
true ->
%% Ugly work around to fix the ETO
%% return patch problem
Name =
case ic_forms:get_id2(XXX) of
"return" ->
"return1";
Other ->
Other
end,
{ic_forms:get_type(XX), Name}
end
end,
ic_forms:get_idlist(XX))
end,
ic_forms:get_body(X)),
EList = lists:flatten(M),
%%io:format("Elist = ~p~n",[EList]),
emit(Fd, "\n#ifndef __~s__\n",[ic_util:to_uppercase(StructName)]),
emit(Fd, "#define __~s__\n",[ic_util:to_uppercase(StructName)]),
ic_codegen:mcomment_light(Fd,
[io_lib:format("Struct definition: ~s",
[StructName])],
c),
emit(Fd, "typedef struct {\n"),
lists:foreach(
fun({Type, Name}) ->
emit_struct_member(Fd, G, N1, X, Name, Type)
end,
EList),
emit(Fd, "} ~s;\n\n", [StructName]),
create_c_struct_coding_file(G, N, X, nil, StructName,
EList, struct),
emit(Fd, "\n#endif\n\n");
false ->
ok
end.
%% Extracts array dimention(s)
get_structelement_tk({tk_struct, _, _, EList}, EN) ->
{value, {EN, ArrayTK}} = lists:keysearch(EN, 1, EList),
ArrayTK.
extract_dim({tk_array, {tk_array, T, D1}, D}) ->
[integer_to_list(D) | extract_dim({tk_array, T, D1})];
extract_dim({tk_array, _, D}) ->
[integer_to_list(D)].
%% Makes the array name
mk_array_name(Name,Dim) ->
Name ++ mk_array_name(Dim).
mk_array_name([]) ->
"";
mk_array_name([Dim|Dims]) ->
"[" ++ Dim ++ "]" ++ mk_array_name(Dims).
emit_struct_member(Fd, G, N, X, Name,{Type,Array}) when is_record(Array, array)->
{_, _, StructTK, _} =
ic_symtab:get_full_scoped_name(
G,
N,
ic_symtab:scoped_id_new(ic_forms:get_id2(X))),
ArrayTK = get_structelement_tk(StructTK, Name),
Dim = extract_dim(ArrayTK),
emit(Fd, " ~s ~s;\n",
[ic_cbe:mk_c_type(G, N, Type),mk_array_name(Name,Dim)]);
emit_struct_member(Fd, _G, N, _X, Name, Union) when is_record(Union, union)->
emit(Fd, " ~s ~s;\n",
[ic_util:to_undersc([ic_forms:get_id2(Union) | N]),Name]);
emit_struct_member(Fd, _G, _N, _X, Name, {string, _}) ->
emit(Fd, " CORBA_char *~s;\n",
[Name]);
emit_struct_member(Fd, _G, N, _X, Name, {sequence, _Type, _Length}) ->
%% Sequence used as struct
emit(Fd, " ~s ~s;\n",
[ic_util:to_undersc([Name | N]), Name]);
emit_struct_member(Fd, G, N, X, Name, Type)
when element(1, Type) == scoped_id ->
CType = ic_cbe:mk_c_type(G, N, Type, evaluate_not),
emit_struct_member(Fd, G, N, X, Name, CType);
emit_struct_member(Fd, G, N, _X, Name, {enum, Type}) ->
emit(Fd, " ~s ~s;\n",
[ic_cbe:mk_c_type(G, N, Type),
Name]);
emit_struct_member(Fd, _G, _N, _X, Name, "ETERM*") ->
emit(Fd, " ETERM* ~s;\n",
[Name]);
emit_struct_member(Fd, _G, _N, _X, Name, Type) when is_list(Type) ->
emit(Fd, " ~s ~s;\n",
[Type, Name]);
emit_struct_member(Fd, G, N, _X, Name, Type) ->
emit(Fd, " ~s ~s;\n",
[ic_cbe:mk_c_type(G, N, Type),
Name]).
emit_typedef(G, N, X, erlang) ->
case X of
{typedef,_,[{array,_,_}],_} -> %% Array but not a typedef of
%% an array definition
case ic_options:get_opt(G, be) of
noc ->
mkFileArrObj(G,N,X,erlang);
_ ->
%% Search the table to see if the type is local or
%% inherited.
PTab = ic_genobj:pragmatab(G),
Id = ic_forms:get_id2(X),
case ets:match(PTab,{file_data_local,'_','_',
typedef,N,Id,
ic_util:to_undersc([Id | N]),
'_','_'}) of
[[]] ->
%% Local, create erlang file for the array
mkFileArrObj(G,N,X,erlang);
_ ->
%% Inherited, do nothing
ok
end
end;
{typedef,{sequence,_,_},_,{tk_sequence,_,_}} ->
%% Sequence but not a typedef of
%% a typedef of a sequence definition
case ic_options:get_opt(G, be) of
noc ->
mkFileRecObj(G,N,X,erlang);
_ ->
%% Search the table to see if the type is local or
%% inherited.
PTab = ic_genobj:pragmatab(G),
Id = ic_forms:get_id2(X),
case ets:match(PTab,{file_data_local,'_','_',typedef,
N,Id,
ic_util:to_undersc([Id | N]),
'_','_'}) of
[[]] ->
%% Local, create erlang file for the sequence
mkFileRecObj(G,N,X,erlang);
_ ->
%% Inherited, do nothing
ok
end
end;
_ ->
ok
end;
emit_typedef(G, N, X, c) ->
B = ic_forms:get_body(X),
if
is_record(B, sequence) ->
emit_sequence_head_def(G, N, X, B, c);
true ->
lists:foreach(fun(D) ->
emit_typedef(G, N, D, B, c)
end,
ic_forms:get_idlist(X))
end.
emit_typedef(G, N, D, Type, c) when is_record(D, array) ->
emit_array(G, N, D, Type);
emit_typedef(G, N, D, Type, c) ->
Name = ic_util:to_undersc([ic_forms:get_id2(D) | N]),
CType = ic_cbe:mk_c_type(G, N, Type),
TDType = mk_base_type(G, N, Type),
ic_code:insert_typedef(G, Name, TDType),
case ic_genobj:is_hrlfile_open(G) of
true ->
Fd = ic_genobj:hrlfiled(G),
emit(Fd, "\n#ifndef __~s__\n",[ic_util:to_uppercase(Name)]),
emit(Fd, "#define __~s__\n",[ic_util:to_uppercase(Name)]),
ic_codegen:mcomment_light(Fd,
[io_lib:format("Type definition ~s "
"for type ~s",
[Name, CType])],
c),
emit(Fd, "typedef ~s ~s;\n",
[CType, Name]),
emit(Fd, "\n#endif\n\n"),
ic_codegen:nl(Fd);
false ->
ok
end.
mk_base_type(G, N, S) when element(1, S) == scoped_id ->
{FullScopedName, _T, _TK, _} = ic_symtab:get_full_scoped_name(G, N, S),
BT = ic_code:get_basetype(G, ic_util:to_undersc(FullScopedName)),
case BT of
"erlang_binary" ->
"erlang_binary";
"erlang_pid" ->
"erlang_pid";
"erlang_port" ->
"erlang_port";
"erlang_ref" ->
"erlang_ref";
"erlang_term" ->
"ETERM*";
Type ->
Type
end;
mk_base_type(_G, _N, S) ->
S.
emit_array(G, N, D, Type) ->
case ic_genobj:is_hrlfile_open(G) of
true ->
Fd = ic_genobj:hrlfiled(G),
Name = ic_util:to_undersc([ic_forms:get_id2(D) | N]),
{_, _, ArrayTK, _} =
ic_symtab:get_full_scoped_name(G, N,
ic_symtab:scoped_id_new(
ic_forms:get_id(D))),
Dim = extract_dim(ArrayTK),
CType = ic_cbe:mk_c_type(G, N, Type),
emit(Fd, "\n#ifndef __~s__\n",[ic_util:to_uppercase(Name)]),
emit(Fd, "#define __~s__\n",[ic_util:to_uppercase(Name)]),
ic_codegen:mcomment_light(Fd,
[io_lib:format("Array definition ~s "
"for type ~s",
[Name, CType])],
c),
emit(Fd, "typedef ~s ~s~s;\n",
[CType, Name, ic_cbe:mk_dim(Dim)]),
emit(Fd, "typedef ~s ~s_slice~s;\n",
[CType, Name, ic_cbe:mk_slice_dim(Dim)]),
ic_codegen:nl(Fd),
create_c_array_coding_file(G, N, {Name, Dim}, Type, typedef),
emit(Fd, "\n#endif\n\n");
false ->
ok
end.
open_c_coding_file(G, Name) ->
SName = string:concat(ic_util:mk_oe_name(G, "code_"), Name),
FName =
ic_file:join(ic_options:get_opt(G, stubdir),ic_file:add_dot_c(SName)),
case file:open(FName, [write]) of
{ok, Fd} ->
{Fd, SName};
Other ->
exit(Other)
end.
create_c_array_coding_file(G, N, {Name, Dim}, Type, TypeDefFlag) ->
{Fd , SName} = open_c_coding_file(G, Name),
HFd = ic_genobj:hrlfiled(G), %% Write on stubfile header
HrlFName = filename:basename(ic_genobj:include_file(G)),
ic_codegen:emit_stub_head(G, Fd, SName, c),
emit(Fd, "#include \"~s\"\n\n",[HrlFName]),
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Fd = ic_genobj:stubfiled(G), %% Write on stubfile
%% HFd = ic_genobj:hrlfiled(G), %% Write on stubfile header
%% HrlFName = filename:basename(ic_genobj:include_file(G)),
%% emit(Fd, "#include \"~s\"\n\n",[HrlFName]),
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
put(op_variable_count, 0),
put(tmp_declarations, []),
emit(HFd, "int ~s~s(CORBA_Environment *oe_env, int*, int*);\n",
[ic_util:mk_oe_name(G, "sizecalc_"), Name]),
emit(Fd, "int ~s~s(CORBA_Environment *oe_env, int* oe_size_count_index, "
"int* oe_size) {\n", [ic_util:mk_oe_name(G, "sizecalc_"), Name]),
emit(Fd, " int oe_malloc_size = 0;\n",[]),
emit(Fd, " int oe_error_code = 0;\n",[]),
emit(Fd, " int oe_type = 0;\n",[]),
emit(Fd, " int oe_array_size = 0;\n",[]),
{ok, RamFd} = ram_file:open([], [binary, write]),
emit_sizecount(array, G, N, nil, RamFd, {Name, Dim}, Type),
ic_cbe:emit_tmp_variables(Fd),
ic_codegen:nl(Fd),
%% Move data from ram file to output file.
{ok, Data} = ram_file:get_file(RamFd),
emit(Fd, Data),
ram_file:close(RamFd),
emit(Fd, " return 0;\n\n",[]),
emit(Fd, "}\n",[]),
put(op_variable_count, 0),
put(tmp_declarations, []),
RefStr = get_refStr(Dim),
case TypeDefFlag of
typedef ->
emit(HFd, "int ~s~s(CORBA_Environment *oe_env, ~s);\n",
[ic_util:mk_oe_name(G, "encode_"), Name, Name]),
emit(Fd, "int ~s~s(CORBA_Environment *oe_env, ~s oe_rec) {\n",
[ic_util:mk_oe_name(G, "encode_"), Name, Name]);
no_typedef ->
emit(HFd, "int ~s~s(CORBA_Environment *oe_env, ~s oe_rec~s);\n",
[ic_util:mk_oe_name(G, "encode_"),
Name,
ic_cbe:mk_c_type(G, N, Type),
RefStr]),
emit(Fd, "int ~s~s(CORBA_Environment *oe_env, ~s oe_rec~s) {\n",
[ic_util:mk_oe_name(G, "encode_"),
Name,
ic_cbe:mk_c_type(G, N, Type),
RefStr])
end,
emit(Fd, " int oe_error_code = 0;\n",[]),
{ok, RamFd1} = ram_file:open([], [binary, write]),
case TypeDefFlag of
typedef ->
emit_encode(array, G, N, nil, RamFd1, {Name, Dim}, Type);
no_typedef ->
emit_encode(array_no_typedef, G, N, nil, RamFd1, {Name, Dim}, Type)
end,
ic_cbe:emit_tmp_variables(Fd),
ic_codegen:nl(Fd),
%% Move data from ram file to output file.
{ok, Data1} = ram_file:get_file(RamFd1),
emit(Fd, Data1),
ram_file:close(RamFd1),
emit(Fd, " return 0;\n\n",[]),
emit(Fd, "}\n",[]),
put(op_variable_count, 0),
put(tmp_declarations, []),
case TypeDefFlag of
typedef ->
emit(HFd, "int ~s~s(CORBA_Environment *oe_env, char *, "
"int*, ~s);\n",
[ic_util:mk_oe_name(G, "decode_"), Name, Name]),
emit(Fd, "int ~s~s(CORBA_Environment *oe_env, char *oe_first, "
"int* oe_outindex, ~s oe_out) {\n",
[ic_util:mk_oe_name(G, "decode_"), Name, Name]);
no_typedef ->
emit(HFd, "int ~s~s(CORBA_Environment *oe_env, char *, int*, "
"~s oe_rec~s);\n",
[ic_util:mk_oe_name(G, "decode_"),
Name,
ic_cbe:mk_c_type(G, N, Type),
RefStr]),
emit(Fd, "int ~s~s(CORBA_Environment *oe_env, char *oe_first, "
"int* oe_outindex, ~s oe_out~s) {\n",
[ic_util:mk_oe_name(G, "decode_"),
Name,
ic_cbe:mk_c_type(G, N, Type),
RefStr])
end,
emit(Fd, " int oe_error_code = 0;\n",[]),
emit(Fd, " int oe_array_size = 0;\n",[]),
{ok, RamFd2} = ram_file:open([], [binary, write]),
case TypeDefFlag of
typedef ->
emit_decode(array, G, N, nil, RamFd2, {Name, Dim}, Type);
no_typedef ->
emit_decode(array_no_typedef, G, N, nil, RamFd2, {Name, Dim}, Type)
end,
ic_cbe:emit_tmp_variables(Fd),
ic_codegen:nl(Fd),
%% Move data from ram file to output file.
{ok, Data2} = ram_file:get_file(RamFd2),
emit(Fd, Data2),
ram_file:close(RamFd2),
emit(Fd, " *oe_outindex = ~s;\n\n",[align("*oe_outindex")]),
emit(Fd, " return 0;\n\n",[]),
emit(Fd, "}\n",[]),
file:close(Fd).
get_refStr([]) ->
"";
get_refStr([X|Xs]) ->
"[" ++ X ++ "]" ++ get_refStr(Xs).
emit_sequence_head_def(G, N, X, T, c) ->
%% T is the sequence
case ic_genobj:is_hrlfile_open(G) of
true ->
Fd = ic_genobj:hrlfiled(G),
SeqName = ic_util:to_undersc([ic_forms:get_id2(X) | N]),
emit(Fd, "\n#ifndef __~s__\n",[ic_util:to_uppercase(SeqName)]),
emit(Fd, "#define __~s__\n",[ic_util:to_uppercase(SeqName)]),
ic_codegen:mcomment_light(Fd,
[io_lib:format("Struct definition: ~s",
[SeqName])],
c),
emit(Fd, "typedef struct {\n"),
emit(Fd, " CORBA_unsigned_long _maximum;\n"),
emit(Fd, " CORBA_unsigned_long _length;\n"),
emit_seq_buffer(Fd, G, N, T#sequence.type),
emit(Fd, "} ~s;\n\n", [SeqName]),
create_c_struct_coding_file(G, N, X, T, SeqName,
T#sequence.type, sequence_head),
emit(Fd, "\n#endif\n\n");
false ->
ok
end.
emit_seq_buffer(Fd, G, N, Type) ->
emit(Fd, " ~s* _buffer;\n",
[ic_cbe:mk_c_type(G, N, Type)]).
%%------------------------------------------------------------
%%
%% Emit decode bodies for functions in C for array, sequences and
%% structs.
%%
%%------------------------------------------------------------
emit_decode(array, G, N, _T, Fd, {_Name, Dim}, Type) ->
emit(Fd, " if((char*) oe_out == oe_first)\n",[]),
AlignName =
lists:concat(["*oe_outindex + ", dim_multiplication(Dim),
" * sizeof(", ic_cbe:mk_c_type(G, N, Type),")"]),
emit(Fd, " *oe_outindex = ~s;\n\n",[align(AlignName)]),
array_decode_dimension_loop(G, N, Fd, Dim, "", Type, array);
emit_decode(array_no_typedef, G, N, _T, Fd, {_Name, Dim}, Type) ->
emit(Fd, " if((char*) oe_out == oe_first)\n",[]),
AlignName =
lists:concat(["*oe_outindex + ", dim_multiplication(Dim),
" * sizeof(", ic_cbe:mk_c_type(G, N, Type),")"]),
emit(Fd, " *oe_outindex = ~s;\n\n",[align(AlignName)]),
array_decode_dimension_loop(G, N, Fd, Dim, "", Type, array_no_typedef);
emit_decode(sequence_head, G, N, T, Fd, SeqName, ElType) ->
ic_cbe:store_tmp_decl(" int oe_seq_len = 0;\n", []),
ic_cbe:store_tmp_decl(" int oe_seq_count = 0;\n", []),
ic_cbe:store_tmp_decl(" int oe_seq_dummy = 0;\n", []),
TmpBuf =
case ictype:isBasicTypeOrEterm(G, N, ElType) of
true ->
Tmp = "oe_seq_tmpbuf",
ic_cbe:store_tmp_decl(" char* ~s = 0;\n", [Tmp]),
Tmp;
false ->
"NOT USED"
end,
MaxSize = get_seq_max(T),
emit(Fd, " if((char*) oe_out == oe_first)\n",[]),
emit(Fd, " *oe_outindex = ~s;\n\n",
[align(["*oe_outindex + sizeof(", SeqName, ")"])]),
Ctype = ic_cbe:mk_c_type(G, N, ElType),
emit(Fd, " if ((oe_error_code = ei_decode_list_header(oe_env->_inbuf, "
"&oe_env->_iin, &oe_seq_len)) < 0) {\n"),
case ictype:isBasicTypeOrEterm(G, N, ElType) of
true ->
emit(Fd, " int oe_type = 0;\n"),
emit(Fd, " (int) ei_get_type(oe_env->_inbuf, &oe_env->_iin, "
"&oe_type, &oe_seq_len);\n\n"),
if
MaxSize == infinity ->
ok;
true ->
emit(Fd, " if (oe_seq_len > ~w) {\n", [MaxSize]),
emit(Fd, " CORBA_exc_set(oe_env, "
"CORBA_SYSTEM_EXCEPTION, DATA_CONVERSION, "
"\"Length of sequence `~s' out of bound\");\n"
" return -1;\n }\n", [SeqName])
end,
emit(Fd, " oe_out->_maximum = oe_seq_len;\n"),
emit(Fd, " oe_out->_length = oe_seq_len;\n"),
emit(Fd, " oe_out->_buffer = (void *) (oe_first + "
"*oe_outindex);\n"),
emit(Fd, " *oe_outindex = ~s;\n",
[align(["*oe_outindex + (sizeof(", Ctype, ") * "
"oe_out->_length)"])]),
emit(Fd,
" if ((~s = malloc(oe_seq_len + 1)) == NULL) {\n"
" CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, "
"NO_MEMORY, \"Cannot malloc\");\n"
" return -1;\n"
" }\n", [TmpBuf]),
emit(Fd, " if ((oe_error_code = ei_decode_string("
"oe_env->_inbuf, &oe_env->_iin, ~s)) < 0) {\n", [TmpBuf]),
emit(Fd, " CORBA_free(~s);\n\n", [TmpBuf]),
emit_c_dec_rpt(Fd, " ", "string1", []),
emit(Fd, " return oe_error_code;\n }\n"),
emit(Fd, " for (oe_seq_count = 0; "
"oe_seq_count < oe_out->_length; oe_seq_count++)\n"),
case ictype:isBasicType(G, N, ElType) of
true ->
emit(Fd, " oe_out->_buffer[oe_seq_count] = (unsigned char) "
"~s[oe_seq_count];\n\n", [TmpBuf]);
false -> %% Term
emit(Fd, " oe_out->_buffer[oe_seq_count] = "
"erl_mk_int(~s[oe_seq_count]);\n\n",[TmpBuf]) % XXXX What?
end,
emit(Fd, " CORBA_free(~s);\n\n", [TmpBuf]);
false ->
emit(Fd, " return oe_error_code;\n")
end,
emit(Fd, " } else {\n"),
if
MaxSize == infinity ->
ok;
true ->
emit(Fd, " if (oe_seq_len > ~w) {\n", [MaxSize]),
emit(Fd, " CORBA_exc_set(oe_env, "
"CORBA_SYSTEM_EXCEPTION, DATA_CONVERSION, "
"\"Length of sequence `~s' out of bound\");\n"
" return -1;\n }\n", [SeqName])
end,
emit(Fd, " oe_out->_maximum = oe_seq_len;\n"),
emit(Fd, " oe_out->_length = oe_seq_len;\n"),
emit(Fd, " oe_out->_buffer = (void *) (oe_first + *oe_outindex);\n"),
emit(Fd, " *oe_outindex = ~s;\n\n",
[align(["*oe_outindex + (sizeof(", Ctype, ") * oe_out->_length)"])]),
if
Ctype == "CORBA_char *" ->
emit(Fd, " for (oe_seq_count = 0; "
"oe_seq_count < oe_out->_length; oe_seq_count++) {\n"),
emit(Fd, " oe_out->_buffer[oe_seq_count] = "
"(void*) (oe_first + *oe_outindex);\n\n"),
ic_cbe:emit_decoding_stmt(G, N, Fd, ElType,
"oe_out->_buffer[oe_seq_count]",
"",
"oe_env->_inbuf", 0, "", caller_dyn),
emit(Fd, " *oe_outindex = ~s;",
[align(["*oe_outindex + strlen(oe_out->_buffer["
"oe_seq_count]) + 1"])]);
true ->
emit(Fd, " for (oe_seq_count = 0; "
"oe_seq_count < oe_out->_length; oe_seq_count++) {\n"),
case ictype:isArray(G, N, ElType) of
%% XXX Silly. There is no real difference between the
%% C statements produced by the following calls.
true ->
ic_cbe:emit_decoding_stmt(G, N, Fd, ElType,
"oe_out->_buffer[oe_seq_count]",
"",
"oe_env->_inbuf",
0, "oe_outindex", generator);
false ->
ic_cbe:emit_decoding_stmt(G, N, Fd, ElType,
"oe_out->_buffer + oe_seq_count",
"",
"oe_env->_inbuf",
0, "oe_outindex", generator)
end
end,
emit(Fd, " }\n"),
emit(Fd, " if (oe_out->_length != 0) {\n"),
emit(Fd, " if ((oe_error_code = ei_decode_list_header("
"oe_env->_inbuf, &oe_env->_iin, &oe_seq_dummy)) < 0) {\n"),
emit_c_dec_rpt(Fd, " ", "ei_decode_list_header", []),
emit(Fd, " return oe_error_code;\n }\n"),
emit(Fd, " } else\n"),
emit(Fd, " oe_out->_buffer = NULL;\n"),
emit(Fd, " }\n");
emit_decode(struct, G, N, _T, Fd, StructName, ElTypes) ->
Length = length(ElTypes) + 1,
Tname = ic_cbe:mk_variable_name(op_variable_count),
Tname1 = ic_cbe:mk_variable_name(op_variable_count),
ic_cbe:store_tmp_decl(" int ~s = 0;\n",[Tname]),
ic_cbe:store_tmp_decl(" char ~s[256];\n\n",[Tname1]),
emit(Fd, " if((char*) oe_out == oe_first)\n",[]),
AlignName = lists:concat(["*oe_outindex + sizeof(",StructName,")"]),
emit(Fd, " *oe_outindex = ~s;\n\n", [align(AlignName)]),
emit(Fd, " if ((oe_error_code = ei_decode_tuple_header(oe_env->_inbuf, "
"&oe_env->_iin, &~s)) < 0) {\n", [Tname]),
emit_c_dec_rpt(Fd, " ", "ei_decode_tuple_header", []),
emit(Fd, " return oe_error_code;\n }\n"),
emit(Fd, " if (~s != ~p) {\n",[Tname, Length]),
emit_c_dec_rpt(Fd, " ", "tuple header size != ~p", [Length]),
emit(Fd, " return -1;\n }\n"),
emit(Fd, " if ((oe_error_code = ei_decode_atom(oe_env->_inbuf, "
"&oe_env->_iin, ~s)) < 0) {\n", [Tname1]),
emit_c_dec_rpt(Fd, " ", "ei_decode_atom", []),
emit(Fd, " return oe_error_code;\n }\n"),
emit(Fd, " if (strcmp(~s, ~p) != 0)\n",[Tname1, StructName]),
emit(Fd, " return -1;\n\n"),
lists:foreach(
fun({ET, EN}) ->
case ic_cbe:is_variable_size(G, N, ET) of
true ->
case ET of
{struct, _, _, _} ->
%% Sequence member = a struct
ic_cbe:emit_decoding_stmt(G, N, Fd,
StructName ++ "_" ++
ic_forms:get_id2(ET),
"&oe_out->" ++ EN,
"", "oe_env->_inbuf",
0,
"oe_outindex",
generator);
{sequence, _, _} ->
%% Sequence member = a struct XXX ??
ic_cbe:emit_decoding_stmt(G, N, Fd,
StructName ++ "_" ++
EN,
"&oe_out->" ++ EN,
"",
"oe_env->_inbuf",
0,
"oe_outindex",
generator);
{_,{array, _, _}} ->
emit(Fd, " oe_out->~s = (void *) "
"(oe_first+*oe_outindex);\n\n",[EN]),
ic_cbe:emit_decoding_stmt(G, N, Fd,
StructName ++ "_" ++
EN, "oe_out->" ++ EN ,
"",
"oe_env->_inbuf",
0,
"oe_outindex",
generator);
{union, _, _, _, _} ->
%% Sequence member = a union
ic_cbe:emit_decoding_stmt(G, N, Fd,
StructName ++ "_" ++
ic_forms:get_id2(ET),
"&oe_out->" ++ EN,
"",
"oe_env->_inbuf",
0,
"oe_outindex",
generator);
{string,_} ->
ic_cbe:emit_decoding_stmt(G, N, Fd,
ET,
"oe_out->" ++ EN ,
"",
"oe_env->_inbuf",
0,
"oe_outindex",
generator_malloc);
{scoped_id,_,_,_} ->
case ictype:member2type(G,StructName,EN) of
array ->
ic_cbe:emit_decoding_stmt(G, N, Fd,
ET,
"oe_out->" ++
EN,
"",
"oe_env->"
"_inbuf",
0,
"oe_outindex",
generator);
struct ->
ic_cbe:emit_decoding_stmt(G, N, Fd,
ET,
"&oe_out->" ++
EN ,
"",
"oe_env->"
"_inbuf",
0,
"oe_outindex",
generator);
sequence ->
ic_cbe:emit_decoding_stmt(G, N, Fd,
ET,
"&oe_out->" ++
EN,
"",
"oe_env->"
"_inbuf",
0,
"oe_outindex",
generator);
union ->
ic_cbe:emit_decoding_stmt(G, N, Fd,
ET,
"&oe_out->" ++
EN,
"",
"oe_env->"
"_inbuf",
0,
"oe_outindex",
generator);
_ ->
ic_cbe:emit_decoding_stmt(G, N, Fd,
ET,
"oe_out->" ++
EN,
"",
"oe_env->"
"_inbuf",
0,
"oe_outindex",
generator)
end;
_ ->
emit(Fd, " oe_out->~s = (void *) "
"(oe_first+*oe_outindex);\n\n",[EN]),
ic_cbe:emit_decoding_stmt(G, N, Fd,
ET,
"oe_out->" ++ EN ,
"",
"oe_env->_inbuf",
0, "oe_outindex",
generator)
end;
false ->
case ET of
{struct, _, _, _} ->
%% A struct member
ic_cbe:emit_decoding_stmt(G, N, Fd,
StructName ++ "_" ++
ic_forms:get_id2(ET),
"&oe_out->" ++ EN ,
"",
"oe_env->_inbuf",
0,
"oe_outindex",
generator);
{_,{array, _, _}} ->
ic_cbe:emit_decoding_stmt(G, N, Fd,
StructName ++ "_" ++
EN,
"oe_out->" ++ EN ,
"",
"oe_env->_inbuf",
0,
"oe_outindex",
generator);
{union, _, _, _, _} ->
%% Sequence member = a union
ic_cbe:emit_decoding_stmt(G, N, Fd,
StructName ++ "_" ++
ic_forms:get_id2(ET),
"&oe_out->" ++ EN ,
"",
"oe_env->_inbuf",
0,
"oe_outindex",
generator);
{_,_} ->
ic_cbe:emit_decoding_stmt(G, N, Fd,
ET,
"&oe_out->" ++ EN ,
"",
"oe_env->_inbuf",
0,
"oe_outindex",
generator);
{scoped_id,_,_,_} ->
case ic_symtab:get_full_scoped_name(G, N, ET) of
{_FullScopedName, _, {tk_array,_,_}, _} ->
ic_cbe:emit_decoding_stmt(G, N, Fd,
ET,
"oe_out->" ++
EN,
"",
"oe_env->"
"_inbuf",
0,
"oe_outindex",
generator);
{_FullScopedName, _, {tk_string,_}, _} ->
ic_cbe:emit_decoding_stmt(G, N, Fd,
ET,
"oe_out->" ++
EN,
"",
"oe_env->"
"_inbuf",
0,
"oe_outindex",
generator);
{_FullScopedName, _, {tk_struct,_,_,_}, _} ->
ic_cbe:emit_decoding_stmt(G, N, Fd,
ET,
"&oe_out->" ++
EN,
"",
"oe_env->"
"_inbuf",
0,
"oe_outindex",
generator);
{_FullScopedName, _,
{tk_union,_,_,_,_,_}, _} ->
ic_cbe:emit_decoding_stmt(G, N, Fd,
ET,
"&oe_out->" ++
EN,
"",
"oe_env->"
"_inbuf",
0,
"oe_outindex",
generator);
_ ->
ic_cbe:emit_decoding_stmt(G, N, Fd,
ET,
"&oe_out->" ++
EN,
"",
"oe_env->"
"_inbuf",
0,
"oe_outindex",
generator)
end
end
end
end,
ElTypes).
ref_array_static_dec(array, true) ->
%% Typedef, Static, Basic Type
"&(oe_out)";
ref_array_static_dec(array, false) ->
%% Typedef, Static, Constr Type
"&(oe_out)";
ref_array_static_dec(array_no_typedef, true) ->
%% No Typedef, Static, Basic Type
"&oe_out";
ref_array_static_dec(array_no_typedef, false) ->
%% No Typedef, Static, Constr Type
"&oe_out".
ref_array_dynamic_dec(G, N, T, array) ->
case ictype:isString(G, N, T) of
true -> % Typedef, Dynamic, String
"oe_out";
false -> % Typedef, Dynamic, No String
"&(oe_out)"
end;
ref_array_dynamic_dec(G, N, T, array_no_typedef) ->
case ictype:isString(G, N, T) of
true -> % No Typedef, Dynamic, String
"oe_out";
false -> % No Typedef, Dynamic, No String
"&oe_out"
end.
array_decode_dimension_loop(G, N, Fd, [Dim], Dimstr, Type, TDFlag) ->
Tname = ic_cbe:mk_variable_name(op_variable_count),
ic_cbe:store_tmp_decl(" int ~s = 0;\n",[Tname]),
emit(Fd, " if ((oe_error_code = ei_decode_tuple_header(oe_env->_inbuf, "
"&oe_env->_iin, &oe_array_size)) < 0) {\n",
[]),
emit_c_dec_rpt(Fd, " ", "ei_decode_tuple_header", []),
emit(Fd, " return oe_error_code;\n }\n"),
%% This is disabled due to a bug in erl_interface :
%% tuples inside tuples hae no correct data about the size
%% of the tuple........( allways = 0 )
%%emit(Fd, " if (oe_array_size != ~s)\n",[Dim]),
%%emit(Fd, " return -1;\n\n"),
emit(Fd, " for (~s = 0; ~s < ~s; ~s++) {\n",
[Tname, Tname, Dim, Tname]),
ArrAccess =
case ic_cbe:is_variable_size(G, N, Type) of
true ->
ref_array_dynamic_dec(G, N, Type, TDFlag) ++
Dimstr ++ "[" ++ Tname ++ "]";
false ->
ref_array_static_dec(TDFlag, ictype:isBasicType(G,N,Type)) ++
Dimstr ++ "[" ++ Tname ++ "]"
end,
ic_cbe:emit_decoding_stmt(G, N, Fd, Type,
ArrAccess,
"", "oe_env->_inbuf", 0,
"oe_outindex", generator),
%% emit(Fd, "\n *oe_outindex +=
%% sizeof(~s);\n",[ic_cbe:mk_c_type(G, N, Type)]),
emit(Fd, " }\n");
array_decode_dimension_loop(G, N, Fd, [Dim | Ds], _Dimstr, Type, TDFlag) ->
Tname = ic_cbe:mk_variable_name(op_variable_count),
ic_cbe:store_tmp_decl(" int ~s = 0;\n",[Tname]),
emit(Fd, " if ((oe_error_code = ei_decode_tuple_header(oe_env->_inbuf, "
"&oe_env->_iin, &oe_array_size)) < 0) {\n",
[]),
emit_c_dec_rpt(Fd, " ", "ei_decode_tuple_header", []),
emit(Fd, " return oe_error_code;\n }\n"),
%% This is disabled due to a bug in erl_interface :
%% tuples inside tuples hae no correct data about the size
%% of the tuple........( allways = 0 )
%%emit(Fd, " if (oe_array_size != ~s)\n",[Dim]),
%%emit(Fd, " return -1;\n\n"),
emit(Fd, " for (~s = 0; ~s < ~s; ~s++) {\n",
[Tname, Tname, Dim, Tname]),
array_decode_dimension_loop(G, N, Fd, Ds, "[" ++ Tname ++ "]" , Type,
TDFlag),
emit(Fd, " }\n").
dim_multiplication([D]) ->
D;
dim_multiplication([D |Ds]) ->
D ++ "*" ++ dim_multiplication(Ds).
emit_encode(array, G, N, _T, Fd, {_Name, Dim}, Type) ->
array_encode_dimension_loop(G, N, Fd, Dim, {"",""}, Type, array);
emit_encode(array_no_typedef, G, N, _T, Fd, {_Name, Dim}, Type) ->
array_encode_dimension_loop(G, N, Fd, Dim, {"",""}, Type,
array_no_typedef);
emit_encode(sequence_head, G, N, T, Fd, SeqName, ElType) ->
Tname = ic_cbe:mk_variable_name(op_variable_count),
ic_cbe:store_tmp_decl(" int ~s = 0;\n\n",[Tname]),
MaxSize = get_seq_max(T),
if
MaxSize == infinity ->
ok;
true ->
emit(Fd, " if (oe_rec->_length > ~w) {\n", [MaxSize]),
emit(Fd, " CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, "
"DATA_CONVERSION, \"Length of sequence `~s' "
"out of bound\");\n"
" return -1;\n }\n", [SeqName])
end,
emit(Fd, " if (oe_rec->_length != 0) {\n"),
emit(Fd, " if ((oe_error_code = oe_ei_encode_list_header(oe_env, "
"oe_rec->_length)) < 0) {\n",
[]),
emit_c_enc_rpt(Fd, " ", "oi_ei_encode_list_header", []),
emit(Fd, " return oe_error_code;\n }\n"),
emit(Fd, " for (~s = 0; ~s < oe_rec->_length; ~s++) {\n",
[Tname, Tname, Tname]),
case ElType of
{_,_} -> %% ElType = elementary type or pointer type
ic_cbe:emit_encoding_stmt(G, N, Fd, ElType, "oe_rec->_buffer[" ++
Tname ++ "]", "oe_env->_outbuf");
{scoped_id,local,_,["term","erlang"]} ->
ic_cbe:emit_encoding_stmt(G, N, Fd, ElType, "oe_rec->_buffer[" ++
Tname ++ "]", "oe_env->_outbuf");
{scoped_id,_,_,_} ->
case ic_symtab:get_full_scoped_name(G, N, ElType) of
{_, typedef, TDef, _} ->
case TDef of
{tk_struct,_,_,_} ->
ic_cbe:emit_encoding_stmt(G, N, Fd, ElType,
"&oe_rec->_buffer[" ++
Tname ++ "]",
"oe_env->_outbuf");
{tk_sequence,_,_} ->
ic_cbe:emit_encoding_stmt(G, N, Fd, ElType,
"&oe_rec->_buffer[" ++
Tname ++ "]",
"oe_env->_outbuf");
{tk_union,_,_,_,_,_} ->
ic_cbe:emit_encoding_stmt(G, N, Fd, ElType,
"&oe_rec->_buffer[" ++
Tname ++ "]",
"oe_env->_outbuf");
_ ->
ic_cbe:emit_encoding_stmt(G, N, Fd, ElType,
"oe_rec->_buffer[" ++
Tname ++ "]",
"oe_env->_outbuf")
end;
{_,enum,_,_} ->
ic_cbe:emit_encoding_stmt(G, N, Fd, ElType,
"oe_rec->_buffer[" ++
Tname ++ "]",
"oe_env->_outbuf");
_ ->
ic_cbe:emit_encoding_stmt(G, N, Fd, ElType,
"&oe_rec->_buffer[" ++
Tname ++ "]",
"oe_env->_outbuf")
end;
_ -> %% ElType = structure
ic_cbe:emit_encoding_stmt(G, N, Fd, ElType,
"&oe_rec->_buffer[" ++ Tname ++ "]",
"oe_env->_outbuf")
end,
emit(Fd, " }\n"),
emit(Fd, " }\n"),
emit(Fd, " if ((oe_error_code = oe_ei_encode_empty_list(oe_env)) < 0) {\n"),
emit_c_enc_rpt(Fd, " ", "oe_ei_encode_empty_list", []),
emit(Fd, " return oe_error_code;\n }\n");
emit_encode(struct, G, N, _T, Fd, StructName, ElTypes) ->
Length = length(ElTypes) + 1,
emit(Fd, " if ((oe_error_code = "
"oe_ei_encode_tuple_header(oe_env, ~p)) < 0) {\n", [Length]),
emit_c_enc_rpt(Fd, " ", "oe_ei_encode_tuple_header", []),
emit(Fd, " return oe_error_code;\n }\n"),
emit(Fd, " if ((oe_error_code = "
"oe_ei_encode_atom(oe_env, ~p)) < 0) {\n", [StructName]),
emit_c_enc_rpt(Fd, " ", "oe_ei_encode_atom", []),
emit(Fd, " return oe_error_code;\n }\n"),
lists:foreach(
fun({ET, EN}) ->
case ET of
{sequence, _, _} ->
%% Sequence = struct
ic_cbe:emit_encoding_stmt(G, N, Fd,
StructName ++ "_" ++ EN,
"&oe_rec->" ++ EN,
"oe_env->_outbuf");
{_,{array, _, _Dims}} ->
ic_cbe:emit_encoding_stmt(G, N, Fd,
StructName ++ "_" ++ EN,
"oe_rec->" ++ EN,
"oe_env->_outbuf");
{union,_,_,_,_} ->
ic_cbe:emit_encoding_stmt(G, N, Fd,
StructName ++ "_" ++
ic_forms:get_id2(ET),
"&oe_rec->" ++ EN,
"oe_env->_outbuf");
{struct,_,_,_} ->
ic_cbe:emit_encoding_stmt(G, N, Fd,
StructName ++ "_" ++
ic_forms:get_id2(ET),
"&oe_rec->" ++ EN,
"oe_env->_outbuf");
{scoped_id,_,_,_} ->
case ictype:member2type(G,StructName,EN) of
struct ->
ic_cbe:emit_encoding_stmt(G, N, Fd,
ET,
"&oe_rec->" ++ EN,
"oe_env->_outbuf");
sequence ->
ic_cbe:emit_encoding_stmt(G, N, Fd,
ET,
"&oe_rec->" ++ EN,
"oe_env->_outbuf");
union ->
ic_cbe:emit_encoding_stmt(G, N, Fd,
ET,
"&oe_rec->" ++ EN,
"oe_env->_outbuf");
array ->
ic_cbe:emit_encoding_stmt(G, N, Fd,
ET,
"oe_rec->" ++ EN,
"oe_env->_outbuf");
_ ->
ic_cbe:emit_encoding_stmt(G, N, Fd,
ET,
"oe_rec->" ++ EN,
"oe_env->_outbuf")
end;
_ ->
ic_cbe:emit_encoding_stmt(G, N, Fd,
ET,
"oe_rec->" ++ EN,
"oe_env->_outbuf")
end
end,
ElTypes).
ref_array_static_enc(array, true) ->
%% Typedef, Static, Basic Type
"oe_rec";
ref_array_static_enc(array, false) ->
%% Typedef, Static, Constr Type
"&(oe_rec)";
ref_array_static_enc(array_no_typedef, true) ->
%% No Typedef, Static, Basic Type
"oe_rec";
ref_array_static_enc(array_no_typedef, false) ->
%% No Typedef, Static, Constr Type
"&oe_rec".
ref_array_dynamic_enc(G, N, T, array) ->
case ictype:isString(G, N, T) of
true -> % Typedef, Dynamic, String
"oe_rec";
false -> % Typedef, Dynamic, No String
"&(oe_rec)"
end;
ref_array_dynamic_enc(G, N, T, array_no_typedef) ->
case ictype:isString(G, N, T) of
true -> % No Typedef, Dynamic, String
"oe_rec";
false -> % No Typedef, Dynamic, No String
"&oe_rec"
end.
array_encode_dimension_loop(G, N, Fd, [Dim], {Str1,_Str2}, Type, TDFlag) ->
Tname = ic_cbe:mk_variable_name(op_variable_count),
ic_cbe:store_tmp_decl(" int ~s = 0;\n",[Tname]),
emit(Fd, " if ((oe_error_code = "
"oe_ei_encode_tuple_header(oe_env, ~s)) < 0) {\n", [Dim]),
emit_c_enc_rpt(Fd, " ", "oe_ei_encode_tuple_header", []),
emit(Fd, " return oe_error_code;\n }\n"),
emit(Fd, " for (~s = 0; ~s < ~s; ~s++) {\n",
[Tname, Tname, Dim, Tname]),
ArrAccess =
case ic_cbe:is_variable_size(G, N, Type) of
true ->
ref_array_dynamic_enc(G, N, Type, TDFlag) ++
Str1 ++ "[" ++ Tname ++ "]";
false ->
ref_array_static_enc(TDFlag, ictype:isBasicType(G,N,Type)) ++
Str1 ++ "[" ++ Tname ++ "]"
end,
ic_cbe:emit_encoding_stmt(G, N, Fd, Type, ArrAccess, "oe_env->_outbuf"),
emit(Fd, " }\n");
array_encode_dimension_loop(G, N, Fd, [Dim | Ds],{Str1,Str2}, Type, TDFlag) ->
Tname = ic_cbe:mk_variable_name(op_variable_count),
ic_cbe:store_tmp_decl(" int ~s = 0;\n",[Tname]),
emit(Fd, " if ((oe_error_code = "
"oe_ei_encode_tuple_header(oe_env, ~s)) < 0) {\n", [Dim]),
emit_c_enc_rpt(Fd, " ", "oe_ei_encode_tuple_header", []),
emit(Fd, " return oe_error_code;\n }\n"),
emit(Fd, " for (~s = 0; ~s < ~s; ~s++) {\n",
[Tname, Tname, Dim, Tname]),
array_encode_dimension_loop(G, N, Fd, Ds,
{Str1 ++ "[" ++ Tname ++ "]", Str2},
Type, TDFlag),
emit(Fd, " }\n").
emit_sizecount(array, G, N, _T, Fd, {_Name, Dim}, Type) ->
emit(Fd, " if(*oe_size == 0)\n",[]),
AlignName = lists:concat(["*oe_size + ", dim_multiplication(Dim),
" * sizeof(", ic_cbe:mk_c_type(G, N, Type),")"]),
emit(Fd, " *oe_size = ~s;\n\n",[align(AlignName)]),
array_size_dimension_loop(G, N, Fd, Dim, Type),
emit(Fd, " *oe_size = ~s;\n\n",
[align("*oe_size + oe_malloc_size")]),
ic_codegen:nl(Fd);
emit_sizecount(sequence_head, G, N, T, Fd, SeqName, ElType) ->
ic_cbe:store_tmp_decl(" int oe_seq_len = 0;\n", []),
ic_cbe:store_tmp_decl(" int oe_seq_count = 0;\n", []),
emit(Fd, " if(*oe_size == 0)\n",[]),
emit(Fd, " *oe_size = ~s;\n\n",
[align(["*oe_size + sizeof(", SeqName, ")"])]),
MaxSize = get_seq_max(T),
emit(Fd, " if ((oe_error_code = ei_get_type(oe_env->_inbuf, "
"oe_size_count_index, &oe_type, &oe_seq_len)) < 0) {\n"),
emit_c_dec_rpt(Fd, " ", "ei_get_type", []),
emit(Fd, " return oe_error_code;\n }\n"),
if
MaxSize == infinity ->
ok;
true ->
emit(Fd, " if (oe_seq_len > ~w) {\n", [MaxSize]),
emit(Fd, " CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, "
"DATA_CONVERSION, \"Length of sequence `~s' "
"out of bound\");\n"
" return -1;\n }\n", [SeqName])
end,
CType = ic_cbe:mk_c_type(G, N, ElType),
emit(Fd, " if ((oe_error_code = ei_decode_list_header(oe_env->_inbuf, "
"oe_size_count_index, NULL)) < 0) {\n"),
case ictype:isBasicTypeOrEterm(G, N, ElType) of
true ->
emit(Fd, " if ((oe_error_code = ei_decode_string(oe_env->"
"_inbuf, oe_size_count_index, NULL)) < 0) {\n"),
emit_c_dec_rpt(Fd, " ", "ei_decode_string", []),
emit(Fd, " return oe_error_code;\n }\n"),
emit(Fd, " oe_malloc_size = ~s;\n\n",
[align(["sizeof(", CType, ") * oe_seq_len"])]);
false ->
emit_c_dec_rpt(Fd, " ", "non mea culpa", []),
emit(Fd, " return oe_error_code;\n\n")
end,
emit(Fd, " } else {\n"),
emit(Fd, " oe_malloc_size = ~s;\n\n",
[align(["sizeof(", CType, ") * oe_seq_len"])]),
emit(Fd, " for (oe_seq_count = 0; oe_seq_count < oe_seq_len; "
"oe_seq_count++) {\n"),
ic_cbe:emit_malloc_size_stmt(G, N, Fd, ElType,
"oe_env->_inbuf", 0, generator),
emit(Fd, " }\n"),
emit(Fd, " if (oe_seq_len != 0) \n"),
emit(Fd, " if ((oe_error_code = ei_decode_list_header(oe_env->_inbuf,"
"oe_size_count_index, NULL)) < 0) {\n"),
emit_c_dec_rpt(Fd, " ", "ei_decode_list_header", []),
emit(Fd, " return oe_error_code;\n }\n"),
emit(Fd, " }\n"),
emit(Fd, " *oe_size = ~s;\n\n", [align("*oe_size + oe_malloc_size")]);
emit_sizecount(struct, G, N, _T, Fd, StructName, ElTypes) ->
Length = length(ElTypes) + 1,
Tname = ic_cbe:mk_variable_name(op_variable_count),
ic_cbe:store_tmp_decl(" int ~s = 0;\n\n",[Tname]),
emit(Fd, " if(*oe_size == 0)\n",[]),
AlignName = lists:concat(["*oe_size + sizeof(",StructName,")"]),
emit(Fd, " *oe_size = ~s;\n\n", [align(AlignName)]),
ic_codegen:nl(Fd),
emit(Fd, " if ((oe_error_code = "
"ei_get_type(oe_env->_inbuf, oe_size_count_index, &oe_type, "
"&~s)) < 0) {\n", [Tname]),
emit_c_dec_rpt(Fd, " ", "ei_get_type", []),
emit(Fd, " return oe_error_code;\n }\n"),
emit(Fd, " if (~s != ~p) {\n",[Tname, Length]),
emit_c_dec_rpt(Fd, " ", "~s != ~p", [Tname, Length]),
emit(Fd, " return -1;\n }\n"),
emit(Fd, " if ((oe_error_code = "
"ei_decode_tuple_header(oe_env->_inbuf, "
"oe_size_count_index, 0)) < 0) {\n"),
emit_c_dec_rpt(Fd, " ", "ei_decode_tuple_header", []),
emit(Fd, " return oe_error_code;\n }\n"),
emit(Fd, " if ((oe_error_code = "
"ei_decode_atom(oe_env->_inbuf, oe_size_count_index, 0)) < 0) {\n", []),
emit_c_dec_rpt(Fd, " ", "ei_decode_atom", []),
emit(Fd, " return oe_error_code;\n }\n"),
lists:foreach(
fun({ET, EN}) ->
case ic_cbe:is_variable_size(G, N, ET) of
true ->
case ET of
{sequence, _, _} ->
ic_cbe:emit_malloc_size_stmt(
G, N, Fd,
StructName ++ "_" ++ EN,
"oe_env->_inbuf",
0,
generator);
{_,{array, _, _}} ->
ic_cbe:emit_malloc_size_stmt(
G, N, Fd,
StructName ++ "_" ++ EN,
"oe_env->_inbuf",
0,
generator);
{union,_,_,_,_} ->
ic_cbe:emit_malloc_size_stmt(
G, N, Fd,
StructName ++ "_" ++ ic_forms:get_id2(ET),
"oe_env->_inbuf",
0,
generator);
{struct,_,_,_} ->
ic_cbe:emit_malloc_size_stmt(
G, N, Fd,
StructName ++ "_" ++ ic_forms:get_id2(ET),
"oe_env->_inbuf",
0,
generator);
_ ->
ic_cbe:emit_malloc_size_stmt(
G, N, Fd,
ET,
"oe_env->_inbuf",
0,
generator)
end;
false ->
case ET of
{_,{array, _, _}} ->
ic_cbe:emit_malloc_size_stmt(
G, N, Fd,
StructName ++ "_" ++ EN,
"oe_env->_inbuf",
0,
generator);
{union,_,_,_,_} ->
ic_cbe:emit_malloc_size_stmt(
G, N, Fd,
StructName ++ "_" ++ ic_forms:get_id2(ET),
"oe_env->_inbuf",
0,
generator);
{struct,_,_,_} ->
ic_cbe:emit_malloc_size_stmt(
G, N, Fd,
StructName ++ "_" ++ ic_forms:get_id2(ET),
"oe_env->_inbuf",
0,
generator);
_ ->
ic_cbe:emit_malloc_size_stmt(
G, N, Fd,
ET,
"oe_env->_inbuf",
1,
generator)
end
end
end,
ElTypes),
emit(Fd, " *oe_size = ~s;\n\n",
[align("*oe_size + oe_malloc_size")]).
array_size_dimension_loop(G, N, Fd, [Dim], Type) ->
Tname = ic_cbe:mk_variable_name(op_variable_count),
ic_cbe:store_tmp_decl(" int ~s = 0;\n",[Tname]),
emit(Fd, " if ((oe_error_code = "
"ei_get_type(oe_env->_inbuf, oe_size_count_index, "
"&oe_type, &oe_array_size)) < 0) {\n",
[]),
emit_c_dec_rpt(Fd, " ", "ei_get_type", []),
emit(Fd, " return oe_error_code;\n }\n"),
emit(Fd, " if (oe_array_size != ~s) {\n",[Dim]),
emit_c_dec_rpt(Fd, " ", "array size != ~s", [Dim]),
emit(Fd, " return -1;\n }\n"),
emit(Fd, " if ((oe_error_code = ei_decode_tuple_header(oe_env->_inbuf, "
"oe_size_count_index, 0)) < 0) {\n", []),
emit_c_dec_rpt(Fd, " ", "ei_decode_tuple_header", []),
emit(Fd, " return oe_error_code;\n }\n"),
emit(Fd, " for (~s = 0; ~s < ~s; ~s++) {\n",
[Tname, Tname, Dim, Tname]),
ic_cbe:emit_malloc_size_stmt(G, N, Fd,
Type, "oe_env->_inbuf", 0, generator),
emit(Fd, " }\n");
array_size_dimension_loop(G, N, Fd, [Dim | Ds], Type) ->
Tname = ic_cbe:mk_variable_name(op_variable_count),
ic_cbe:store_tmp_decl(" int ~s = 0;\n",[Tname]),
emit(Fd, " if ((oe_error_code = "
"ei_get_type(oe_env->_inbuf, oe_size_count_index, "
"&oe_type, &oe_array_size)) < 0) {\n", []),
emit_c_dec_rpt(Fd, " ", "ei_get_type", []),
emit(Fd, " return oe_error_code;\n }\n"),
emit(Fd, " if (oe_array_size != ~s) {\n",[Dim]),
emit_c_dec_rpt(Fd, " ", "array size != ~s", [Dim]),
emit(Fd, " return -1;\n }\n"),
emit(Fd, " if ((oe_error_code = ei_decode_tuple_header(oe_env->_inbuf, "
"oe_size_count_index, 0)) < 0) {\n",
[]),
emit_c_dec_rpt(Fd, " ", "ei_decode_tuple_header", []),
emit(Fd, " return oe_error_code;\n }\n"),
emit(Fd, " for (~s = 0; ~s < ~s; ~s++) {\n",
[Tname, Tname, Dim, Tname]),
array_size_dimension_loop(G, N, Fd, Ds, Type),
emit(Fd, " }\n").
create_c_struct_coding_file(G, N, _X, T, StructName, ElTypes, StructType) ->
{Fd , SName} = open_c_coding_file(G, StructName), % stub file
HFd = ic_genobj:hrlfiled(G), % stub header file
HrlFName = filename:basename(ic_genobj:include_file(G)),
ic_codegen:emit_stub_head(G, Fd, SName, c),
HrlFName = filename:basename(ic_genobj:include_file(G)),
emit(Fd, "#include \"~s\"\n\n",[HrlFName]),
%% Size count
put(op_variable_count, 0),
put(tmp_declarations, []),
emit(HFd, "int ~s~s(CORBA_Environment *oe_env, int*, int*);\n",
[ic_util:mk_oe_name(G, "sizecalc_"), StructName]),
emit(Fd, "int ~s~s(CORBA_Environment *oe_env, "
"int* oe_size_count_index, int* oe_size)\n{\n",
[ic_util:mk_oe_name(G, "sizecalc_"), StructName]),
emit(Fd, " int oe_malloc_size = 0;\n",[]),
emit(Fd, " int oe_error_code = 0;\n",[]),
emit(Fd, " int oe_type = 0;\n",[]),
{ok, RamFd} = ram_file:open([], [binary, write]),
emit_sizecount(StructType, G, N, T, RamFd, StructName, ElTypes),
ic_cbe:emit_tmp_variables(Fd),
ic_codegen:nl(Fd),
%% Move data from ram file to output file.
{ok, Data} = ram_file:get_file(RamFd),
emit(Fd, Data),
ram_file:close(RamFd),
emit(Fd, " return 0;\n\n",[]),
emit(Fd, "}\n\n",[]),
%% Encode
put(op_variable_count, 0),
put(tmp_declarations, []),
emit(HFd, "int ~s~s(CORBA_Environment *oe_env, ~s*);\n",
[ic_util:mk_oe_name(G, "encode_"), StructName, StructName]),
emit(Fd, "int ~s~s(CORBA_Environment *oe_env, ~s* oe_rec)\n{\n",
[ic_util:mk_oe_name(G, "encode_"), StructName, StructName]),
emit(Fd, " int oe_error_code = 0;\n",[]),
{ok, RamFd1} = ram_file:open([], [binary, write]),
emit_encode(StructType, G, N, T, RamFd1, StructName, ElTypes),
ic_cbe:emit_tmp_variables(Fd),
ic_codegen:nl(Fd),
%% Move data from ram file to output file.
{ok, Data1} = ram_file:get_file(RamFd1),
emit(Fd, Data1),
ram_file:close(RamFd1),
emit(Fd, " return 0;\n\n",[]),
emit(Fd, "}\n\n",[]),
%% Decode
put(op_variable_count, 0),
put(tmp_declarations, []),
emit(HFd, "int ~s~s(CORBA_Environment *oe_env, char *, int*, ~s *);\n",
[ic_util:mk_oe_name(G, "decode_"), StructName, StructName]),
emit(Fd, "int ~s~s(CORBA_Environment *oe_env, char *oe_first, "
"int* oe_outindex, "
"~s *oe_out)\n{\n",
[ic_util:mk_oe_name(G, "decode_"), StructName, StructName]),
emit(Fd, " int oe_error_code = 0;\n",[]),
{ok, RamFd2} = ram_file:open([], [binary, write]),
emit_decode(StructType, G, N, T, RamFd2, StructName, ElTypes),
ic_cbe:emit_tmp_variables(Fd),
ic_codegen:nl(Fd),
%% Move data from ram file to output file.
{ok, Data2} = ram_file:get_file(RamFd2),
emit(Fd, Data2),
ram_file:close(RamFd2),
emit(Fd, " *oe_outindex = ~s;\n",[align("*oe_outindex")]),
emit(Fd, " return 0;\n\n",[]),
emit(Fd, "}\n\n",[]),
file:close(Fd).
%%------------------------------------------------------------
%%
%% emit primitive for unions.
%%
%%------------------------------------------------------------
emit_union(G, N, X, erlang) ->
case ic_genobj:is_hrlfile_open(G) of
true ->
ic_codegen:record(G, X,
ic_util:to_undersc([ic_forms:get_id2(X) | N]),
nil,nil),
mkFileRecObj(G,N,X,erlang);
false -> ok
end;
emit_union(_G, _N, _X, c) -> %% Not supported in c backend
true.
%%------------------------------------------------------------
%%
%% emit erlang modules for objects with record definitions
%% (such as unions or structs), or sequences
%%
%% The record files, other than headers are only generated
%% for CORBA...... If wished an option could allows even
%% for other backends ( not necessary anyway )
%%
%%------------------------------------------------------------
mkFileRecObj(G,N,X,erlang) ->
case ic_options:get_opt(G, be) of
erl_corba ->
SName =
ic_util:to_undersc([ic_forms:get_id2(X) | N]),
FName =
ic_file:join(ic_options:get_opt(G, stubdir),
ic_file:add_dot_erl(SName)),
case file:open(FName, [write]) of
{ok, Fd} ->
HrlFName = filename:basename(ic_genobj:include_file(G)),
ic_codegen:emit_stub_head(G, Fd, SName, erlang),
emit(Fd, "-include(~p).\n\n",[HrlFName]),
emit_exports(G,Fd),
emit_rec_methods(G,N,X,SName,Fd),
ic_codegen:nl(Fd),
ic_codegen:nl(Fd),
file:close(Fd);
Other ->
exit(Other)
end;
_ ->
true
end.
%%------------------------------------------------------------
%%
%% emit erlang modules for objects with array definitions..
%%
%%------------------------------------------------------------
mkFileArrObj(G,N,X,erlang) ->
SName =
ic_util:to_undersc([ic_forms:get_id2(X) | N]),
FName =
ic_file:join(ic_options:get_opt(G, stubdir),
ic_file:add_dot_erl(SName)),
case file:open(FName, [write]) of
{ok, Fd} ->
HrlFName = filename:basename(ic_genobj:include_file(G)),
ic_codegen:emit_stub_head(G, Fd, SName, erlang),
emit(Fd, "-include(~p).\n\n",[HrlFName]),
emit_exports(G,Fd),
emit_arr_methods(G,N,X,SName,Fd),
ic_codegen:nl(Fd),
ic_codegen:nl(Fd),
file:close(Fd);
Other ->
exit(Other)
end.
%%------------------------------------------------------------
%%
%% emit exports for erlang modules which represent records.
%%
%%------------------------------------------------------------
emit_exports(G,Fd) ->
case ic_options:get_opt(G, be) of
erl_corba ->
emit(Fd, "-export([tc/0,id/0,name/0]).\n\n\n\n",[]);
_ ->
emit(Fd, "-export([id/0,name/0]).\n\n\n\n",[])
end.
%%------------------------------------------------------------
%%
%% emit erlang module functions which represent records, yields
%% record information such as type code, identity and name.
%%
%%------------------------------------------------------------
emit_rec_methods(G,N,X,Name,Fd) ->
IR_ID = ictk:get_IR_ID(G, N, X),
case ic_options:get_opt(G, be) of
erl_corba ->
TK = ic_forms:get_tk(X),
case TK of
undefined ->
STK = ic_forms:search_tk(G,ictk:get_IR_ID(G, N, X)),
emit(Fd, "%% returns type code\n",[]),
emit(Fd, "tc() -> ~p.\n\n",[STK]),
emit(Fd, "%% returns id\n",[]),
emit(Fd, "id() -> ~p.\n\n",[IR_ID]),
emit(Fd, "%% returns name\n",[]),
emit(Fd, "name() -> ~p.\n\n",[Name]);
_ ->
emit(Fd, "%% returns type code\n",[]),
emit(Fd, "tc() -> ~p.\n\n",[TK]),
emit(Fd, "%% returns id\n",[]),
emit(Fd, "id() -> ~p.\n\n",[IR_ID]),
emit(Fd, "%% returns name\n",[]),
emit(Fd, "name() -> ~p.\n\n",[Name])
end;
_ ->
emit(Fd, "%% returns id\n",[]),
emit(Fd, "id() -> ~p.\n\n",[IR_ID]),
emit(Fd, "%% returns name\n",[]),
emit(Fd, "name() -> ~p.\n\n",[Name])
end.
%%------------------------------------------------------------
%%
%% emit erlang module functions which represent arrays, yields
%% record information such as type code, identity and name.
%%
%%------------------------------------------------------------
emit_arr_methods(G,N,X,Name,Fd) ->
IR_ID = ictk:get_IR_ID(G, N, X),
case ic_options:get_opt(G, be) of
erl_corba ->
TK = ic_forms:get_type_code(G, N, X),
emit(Fd, "%% returns type code\n",[]),
emit(Fd, "tc() -> ~p.\n\n",[TK]),
emit(Fd, "%% returns id\n",[]),
emit(Fd, "id() -> ~p.\n\n",[IR_ID]),
emit(Fd, "%% returns name\n",[]),
emit(Fd, "name() -> ~p.\n\n",[Name]);
_ ->
emit(Fd, "%% returns id\n",[]),
emit(Fd, "id() -> ~p.\n\n",[IR_ID]),
emit(Fd, "%% returns name\n",[]),
emit(Fd, "name() -> ~p.\n\n",[Name])
end.
get_seq_max(T) when is_record(T, sequence) andalso T#sequence.length == 0 ->
infinity;
get_seq_max(T) when is_record(T, sequence) andalso is_tuple(T#sequence.length) ->
list_to_integer(element(3, T#sequence.length)).
align(Cs) ->
ic_util:mk_align(Cs).