1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20%%
21%%-----------------------------------------------------------------
22%% File: icenum.erl
23%%
24%%
25%%-----------------------------------------------------------------
26%%
27%% Code generation for enum's.
28%%-----------------------------------------------------------------
29-module(icenum).
30
31-import(ic_codegen, [emit/2, emit/3, emit/4, emit_c_enc_rpt/4, emit_c_dec_rpt/4]).
32
33-include("icforms.hrl").
34-include("ic.hrl").
35
36%%-----------------------------------------------------------------
37%% External exports
38%%-----------------------------------------------------------------
39-export([enum_gen/4]).
40
41%%-----------------------------------------------------------------
42%% Internal exports
43%%-----------------------------------------------------------------
44-export([]).
45
46enum_gen(G, N, X, c) when is_record(X, enum) ->
47    emit_c_enum(G, N, X);
48enum_gen(_G, _N, _X, _L) ->
49    ok.
50
51
52emit_c_enum(G, N, X) ->
53    case ic_genobj:is_hrlfile_open(G) of
54	true ->
55	    EnumName = [ic_forms:get_id2(X) | N],
56
57	    case ic_pragma:is_local(G,EnumName) of
58		true ->
59
60		    Fd = ic_genobj:hrlfiled(G),
61		    EnumNameStr = ic_util:to_undersc(EnumName),
62		    ic_code:insert_typedef(G, EnumNameStr, {enum, EnumNameStr}),
63		    {tk_enum,_,_,EList} = ic_forms:get_tk(X),
64		    emit(Fd, "\n#ifndef __~s__\n",[ic_util:to_uppercase(EnumNameStr)]),
65		    emit(Fd, "#define __~s__\n",[ic_util:to_uppercase(EnumNameStr)]),
66		    ic_codegen:mcomment_light(Fd,
67					      [io_lib:format("Enum definition: ~s",
68							     [EnumNameStr])],
69					      c),
70		    emit(Fd, "typedef CORBA_enum {", []),
71		    emit_c_enum_values(G, N, Fd, EList),
72		    emit(Fd, "} ~s ;\n\n", [EnumNameStr]),
73		    create_c_enum_file(G, N, EnumNameStr, EList),
74		    emit(Fd, "\n#endif\n\n");
75
76		false ->   %% Do not generate included types att all.
77		    ok
78	    end;
79
80	false ->
81	    ok
82    end.
83
84
85emit_c_enum_values(_G, N, Fd, [E]) ->
86    emit(Fd, "~s", [ic_util:to_undersc([E| N])]);
87emit_c_enum_values(G, N, Fd, [E |Es]) ->
88    emit(Fd, "~s, ", [ic_util:to_undersc([E| N])]),
89    emit_c_enum_values(G, N, Fd, Es).
90
91
92open_c_coding_file(G, Name) ->
93    SName = string:concat(ic_util:mk_oe_name(G, "code_"), Name),
94    FName =
95        ic_file:join(ic_options:get_opt(G, stubdir),ic_file:add_dot_c(SName)),
96    case file:open(FName, [write]) of
97        {ok, Fd} ->
98            {Fd, SName};
99        Other ->
100            exit(Other)
101    end.
102
103
104create_c_enum_file(G, N, Name, Elist) ->
105
106    {Fd , SName} = open_c_coding_file(G, Name),
107    HFd = ic_genobj:hrlfiled(G), %% Write on stubfile header
108    HrlFName = filename:basename(ic_genobj:include_file(G)),
109    ic_codegen:emit_stub_head(G, Fd, SName, c),
110    emit(Fd, "#include \"~s\"\n\n",[HrlFName]),
111
112    %%  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
113    %%  Fd = ic_genobj:stubfiled(G), %% Write on stubfile
114    %%  HFd = ic_genobj:hrlfiled(G), %% Write on stubfile header
115    %%  HrlFName = filename:basename(ic_genobj:include_file(G)),
116    %%  emit(Fd, "#include \"~s\"\n\n",[HrlFName]),
117    %%  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
118
119    emit(Fd, "char* ~s[~p] = {\n", [ic_util:mk_oe_name(G, Name),
120				    length(Elist)]),
121    emit_c_enum_array_values(Fd, Elist),
122    emit(Fd, "};\n\n",[]),
123    emit_sizecount(G, N, Fd, HFd, Name, Elist),
124    emit_encode(G, N, Fd, HFd, Name, Elist),
125    emit_decode(G, N, Fd, HFd, Name, Elist),
126    file:close(Fd).
127
128emit_c_enum_array_values(Fd, [E]) ->
129    emit(Fd, "  ~p\n", [E]);
130emit_c_enum_array_values(Fd, [E |Es]) ->
131    emit(Fd, "  ~p,\n", [E]),
132    emit_c_enum_array_values(Fd, Es).
133
134
135emit_sizecount(G, _N, Fd, HFd, Name, _Elist) ->
136
137    emit(HFd, "int ~s~s(CORBA_Environment *oe_env, int*, int*);\n",
138	 [ic_util:mk_oe_name(G, "sizecalc_"), Name]),
139
140    emit(Fd, "int ~s~s(CORBA_Environment *oe_env, int* oe_size_count_index, int* oe_size)\n"
141	 "{\n",
142	 [ic_util:mk_oe_name(G, "sizecalc_"), Name]),
143    emit(Fd, "  int oe_error_code = 0;\n\n",[]),
144
145    AlignName = lists:concat(["*oe_size + sizeof(",Name,")"]),
146    emit(Fd, "  *oe_size = ~s;\n\n",[ic_util:mk_align(AlignName)]),
147
148    emit(Fd, "  if ((oe_error_code = ei_decode_atom(oe_env->_inbuf, oe_size_count_index, 0)) < 0) {\n"),
149    emit_c_enc_rpt(Fd, "    ", "ei_decode_atom", []),
150    emit(Fd, "    return oe_error_code;\n   }\n"),
151    emit(Fd, "  return 0;\n\n",[]),
152    emit(Fd, "}\n\n",[]).
153
154
155emit_encode(G, _N, Fd, HFd, Name, _Elist) ->
156
157    emit(HFd, "int ~s~s(CORBA_Environment *oe_env, ~s);\n",
158	 [ic_util:mk_oe_name(G, "encode_"), Name, Name]),
159
160    emit(Fd, "int ~s~s(CORBA_Environment *oe_env, ~s oe_rec) {\n",
161	 [ic_util:mk_oe_name(G, "encode_"), Name, Name]),
162    emit(Fd, "  int oe_error_code = 0;\n\n",[]),
163
164    emit(Fd, "  if ((oe_error_code = oe_ei_encode_atom(oe_env, ~s[oe_rec])) < 0) {\n",
165	 [ic_util:mk_oe_name(G, Name)]),
166    emit_c_enc_rpt(Fd, "    ", "oe_ei_encode_atom", []),
167    emit(Fd, "    return oe_error_code;\n  }\n"),
168
169    emit(Fd, "  return 0;\n\n",[]),
170    emit(Fd, "}\n\n",[]).
171
172emit_decode(G, _N, Fd, HFd, Name, Elist) ->
173
174    emit(HFd, "int ~s~s(CORBA_Environment *oe_env, char *, int*, ~s *);\n",
175	 [ic_util:mk_oe_name(G, "decode_"), Name, Name]),
176
177    emit(Fd, "int ~s~s(CORBA_Environment *oe_env, char *oe_first, int* oe_outindex, "
178	 "~s *oe_out) {\n\n",
179	 [ic_util:mk_oe_name(G, "decode_"), Name, Name]),
180    emit(Fd, "  int oe_error_code = 0;\n",[]),
181    emit(Fd, "  int oe_i;\n",[]),
182    emit(Fd, "  char oe_atom[256];\n\n",[]),
183
184    AlignName = lists:concat(["*oe_outindex + sizeof(",Name,")"]),
185    emit(Fd, "  *oe_outindex = ~s;\n\n",[ic_util:mk_align(AlignName)]),
186
187    emit(Fd, "  if ((oe_error_code = ei_decode_atom(oe_env->_inbuf, &oe_env->_iin, oe_atom)) < 0) {\n"),
188    emit_c_enc_rpt(Fd, "    ", "ei_decode_atom", []),
189    emit(Fd, "    return oe_error_code;\n  }\n"),
190
191    Len = length(Elist),
192    emit(Fd, "  for(oe_i = 0; oe_i < ~p && strcmp(oe_atom, ~s[oe_i]); oe_i++);\n",
193	 [Len, ic_util:mk_oe_name(G, Name)]),
194    emit(Fd, "    *oe_out = oe_i;\n\n", []),
195
196    emit(Fd, "  if (oe_i == ~p) {\n",[Len]),
197    emit_c_enc_rpt(Fd, "    ", "decode atom failure", []),
198    emit(Fd, "    return oe_error_code;\n  }\n"),
199
200    emit(Fd, "  return 0;\n",[]),
201    emit(Fd, "}\n\n",[]).
202
203
204
205
206
207