Gentoo Archives: gentoo-commits

From: "Christian Faulhammer (fauli)" <fauli@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] gentoo-x86 commit in net-im/ejabberd/files: ejabberd-2.0.5-erlang-13.patch
Date: Wed, 03 Jun 2009 06:07:22
Message-Id: E1MBjdA-0008EO-7v@stork.gentoo.org
1 fauli 09/06/03 06:07:20
2
3 Added: ejabberd-2.0.5-erlang-13.patch
4 Log:
5 revision bump to fix runtime failures with Erlang 13, as reported and fixed by Karl-Johan Karlsson <creideiki+gentoo-bugzilla AT lysator DOT liu DOT se> in bug 267524
6 (Portage version: 2.1.6.11/cvs/Linux i686)
7
8 Revision Changes Path
9 1.1 net-im/ejabberd/files/ejabberd-2.0.5-erlang-13.patch
10
11 file : http://sources.gentoo.org/viewcvs.py/gentoo-x86/net-im/ejabberd/files/ejabberd-2.0.5-erlang-13.patch?rev=1.1&view=markup
12 plain: http://sources.gentoo.org/viewcvs.py/gentoo-x86/net-im/ejabberd/files/ejabberd-2.0.5-erlang-13.patch?rev=1.1&content-type=text/plain
13
14 Index: ejabberd-2.0.5-erlang-13.patch
15 ===================================================================
16 diff --git a/src/dynamic_compile.erl b/src/dynamic_compile.erl
17 new file mode 100644
18 index 0000000..1fe2dca
19 --- /dev/null
20 +++ dynamic_compile.erl
21 @@ -0,0 +1,268 @@
22 +%% Copyright (c) 2007
23 +%% Mats Cronqvist <mats.cronqvist@××××××××.com>
24 +%% Chris Newcombe <chris.newcombe@×××××.com>
25 +%% Jacob Vorreuter <jacob.vorreuter@×××××.com>
26 +%%
27 +%% Permission is hereby granted, free of charge, to any person
28 +%% obtaining a copy of this software and associated documentation
29 +%% files (the "Software"), to deal in the Software without
30 +%% restriction, including without limitation the rights to use,
31 +%% copy, modify, merge, publish, distribute, sublicense, and/or sell
32 +%% copies of the Software, and to permit persons to whom the
33 +%% Software is furnished to do so, subject to the following
34 +%% conditions:
35 +%%
36 +%% The above copyright notice and this permission notice shall be
37 +%% included in all copies or substantial portions of the Software.
38 +%%
39 +%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
40 +%% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
41 +%% OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
42 +%% NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
43 +%% HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
44 +%% WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
45 +%% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
46 +%% OTHER DEALINGS IN THE SOFTWARE.
47 +
48 +%%%-------------------------------------------------------------------
49 +%%% File : dynamic_compile.erl
50 +%%% Description :
51 +%%% Authors : Mats Cronqvist <mats.cronqvist@××××××××.com>
52 +%%% Chris Newcombe <chris.newcombe@×××××.com>
53 +%%% Jacob Vorreuter <jacob.vorreuter@×××××.com>
54 +%%% TODO :
55 +%%% - add support for limit include-file depth (and prevent circular references)
56 +%%% prevent circular macro expansion set FILE correctly when -module() is found
57 +%%% -include_lib support $ENVVAR in include filenames
58 +%%% substitute-stringize (??MACRO)
59 +%%% -undef/-ifdef/-ifndef/-else/-endif
60 +%%% -file(File, Line)
61 +%%%-------------------------------------------------------------------
62 +-module(dynamic_compile).
63 +
64 +%% API
65 +-export([from_string/1, from_string/2]).
66 +
67 +-import(lists, [reverse/1, keyreplace/4]).
68 +
69 +%%====================================================================
70 +%% API
71 +%%====================================================================
72 +%%--------------------------------------------------------------------
73 +%% Function:
74 +%% Description:
75 +%% Returns a binary that can be used with
76 +%% code:load_binary(Module, ModuleFilenameForInternalRecords, Binary).
77 +%%--------------------------------------------------------------------
78 +from_string(CodeStr) ->
79 + from_string(CodeStr, []).
80 +
81 +% takes Options as for compile:forms/2
82 +from_string(CodeStr, CompileFormsOptions) ->
83 + %% Initialise the macro dictionary with the default predefined macros,
84 + %% (adapted from epp.erl:predef_macros/1
85 + Filename = "compiled_from_string",
86 + %%Machine = list_to_atom(erlang:system_info(machine)),
87 + Ms0 = dict:new(),
88 + % Ms1 = dict:store('FILE', {[], "compiled_from_string"}, Ms0),
89 + % Ms2 = dict:store('LINE', {[], 1}, Ms1), % actually we might add special code for this
90 + % Ms3 = dict:store('MODULE', {[], undefined}, Ms2),
91 + % Ms4 = dict:store('MODULE_STRING', {[], undefined}, Ms3),
92 + % Ms5 = dict:store('MACHINE', {[], Machine}, Ms4),
93 + % InitMD = dict:store(Machine, {[], true}, Ms5),
94 + InitMD = Ms0,
95 +
96 + %% From the docs for compile:forms:
97 + %% When encountering an -include or -include_dir directive, the compiler searches for header files in the following directories:
98 + %% 1. ".", the current working directory of the file server;
99 + %% 2. the base name of the compiled file;
100 + %% 3. the directories specified using the i option. The directory specified last is searched first.
101 + %% In this case, #2 is meaningless.
102 + IncludeSearchPath = ["." | reverse([Dir || {i, Dir} <- CompileFormsOptions])],
103 + {RevForms, _OutMacroDict} = scan_and_parse(CodeStr, Filename, 1, [], InitMD, IncludeSearchPath),
104 + Forms = reverse(RevForms),
105 +
106 + %% note: 'binary' is forced as an implicit option, whether it is provided or not.
107 + case compile:forms(Forms, CompileFormsOptions) of
108 + {ok, ModuleName, CompiledCodeBinary} when is_binary(CompiledCodeBinary) ->
109 + {ModuleName, CompiledCodeBinary};
110 + {ok, ModuleName, CompiledCodeBinary, []} when is_binary(CompiledCodeBinary) -> % empty warnings list
111 + {ModuleName, CompiledCodeBinary};
112 + {ok, _ModuleName, _CompiledCodeBinary, Warnings} ->
113 + throw({?MODULE, warnings, Warnings});
114 + Other ->
115 + throw({?MODULE, compile_forms, Other})
116 + end.
117 +
118 +%%====================================================================
119 +%% Internal functions
120 +%%====================================================================
121 +%%% Code from Mats Cronqvist
122 +%%% See http://www.erlang.org/pipermail/erlang-questions/2007-March/025507.html
123 +%%%## 'scan_and_parse'
124 +%%%
125 +%%% basically we call the OTP scanner and parser (erl_scan and
126 +%%% erl_parse) line-by-line, but check each scanned line for (or
127 +%%% definitions of) macros before parsing.
128 +%% returns {ReverseForms, FinalMacroDict}
129 +scan_and_parse([], _CurrFilename, _CurrLine, RevForms, MacroDict, _IncludeSearchPath) ->
130 + {RevForms, MacroDict};
131 +
132 +scan_and_parse(RemainingText, CurrFilename, CurrLine, RevForms, MacroDict, IncludeSearchPath) ->
133 + case scanner(RemainingText, CurrLine, MacroDict) of
134 + {tokens, NLine, NRemainingText, Toks} ->
135 + {ok, Form} = erl_parse:parse_form(Toks),
136 + scan_and_parse(NRemainingText, CurrFilename, NLine, [Form | RevForms], MacroDict, IncludeSearchPath);
137 + {macro, NLine, NRemainingText, NMacroDict} ->
138 + scan_and_parse(NRemainingText, CurrFilename, NLine, RevForms,NMacroDict, IncludeSearchPath);
139 + {include, NLine, NRemainingText, IncludeFilename} ->
140 + IncludeFileRemainingTextents = read_include_file(IncludeFilename, IncludeSearchPath),
141 + %%io:format("include file ~p contents: ~n~p~nRemainingText = ~p~n", [IncludeFilename,IncludeFileRemainingTextents, RemainingText]),
142 + %% Modify the FILE macro to reflect the filename
143 + %%IncludeMacroDict = dict:store('FILE', {[],IncludeFilename}, MacroDict),
144 + IncludeMacroDict = MacroDict,
145 +
146 + %% Process the header file (inc. any nested header files)
147 + {RevIncludeForms, IncludedMacroDict} = scan_and_parse(IncludeFileRemainingTextents, IncludeFilename, 1, [], IncludeMacroDict, IncludeSearchPath),
148 + %io:format("include file results = ~p~n", [R]),
149 + %% Restore the FILE macro in the NEW MacroDict (so we keep any macros defined in the header file)
150 + %%NMacroDict = dict:store('FILE', {[],CurrFilename}, IncludedMacroDict),
151 + NMacroDict = IncludedMacroDict,
152 +
153 + %% Continue with the original file
154 + scan_and_parse(NRemainingText, CurrFilename, NLine, RevIncludeForms ++ RevForms, NMacroDict, IncludeSearchPath);
155 + done ->
156 + scan_and_parse([], CurrFilename, CurrLine, RevForms, MacroDict, IncludeSearchPath)
157 + end.
158 +
159 +scanner(Text, Line, MacroDict) ->
160 + case erl_scan:tokens([],Text,Line) of
161 + {done, {ok,Toks,NLine}, LeftOverChars} ->
162 + case pre_proc(Toks, MacroDict) of
163 + {tokens, NToks} -> {tokens, NLine, LeftOverChars, NToks};
164 + {macro, NMacroDict} -> {macro, NLine, LeftOverChars, NMacroDict};
165 + {include, Filename} -> {include, NLine, LeftOverChars, Filename}
166 + end;
167 + {more, _Continuation} ->
168 + %% This is supposed to mean "term is not yet complete" (i.e. a '.' has
169 + %% not been reached yet).
170 + %% However, for some bizarre reason we also get this if there is a comment after the final '.' in a file.
171 + %% So we check to see if Text only consists of comments.
172 + case is_only_comments(Text) of
173 + true ->
174 + done;
175 + false ->
176 + throw({incomplete_term, Text, Line})
177 + end
178 + end.
179 +
180 +is_only_comments(Text) -> is_only_comments(Text, not_in_comment).
181 +
182 +is_only_comments([], _) -> true;
183 +is_only_comments([$ |T], not_in_comment) -> is_only_comments(T, not_in_comment); % skipping whitspace outside of comment
184 +is_only_comments([$\t |T], not_in_comment) -> is_only_comments(T, not_in_comment); % skipping whitspace outside of comment
185 +is_only_comments([$\n |T], not_in_comment) -> is_only_comments(T, not_in_comment); % skipping whitspace outside of comment
186 +is_only_comments([$% |T], not_in_comment) -> is_only_comments(T, in_comment); % found start of a comment
187 +is_only_comments(_, not_in_comment) -> false;
188 +% found any significant char NOT in a comment
189 +is_only_comments([$\n |T], in_comment) -> is_only_comments(T, not_in_comment); % found end of a comment
190 +is_only_comments([_ |T], in_comment) -> is_only_comments(T, in_comment). % skipping over in-comment chars
191 +
192 +%%%## 'pre-proc'
193 +%%%
194 +%%% have to implement a subset of the pre-processor, since epp insists
195 +%%% on running on a file.
196 +%%% only handles 2 cases;
197 +%% -define(MACRO, something).
198 +%% -define(MACRO(VAR1,VARN),{stuff,VAR1,more,stuff,VARN,extra,stuff}).
199 +pre_proc([{'-',_},{atom,_,define},{'(',_},{_,_,Name}|DefToks],MacroDict) ->
200 + false = dict:is_key(Name, MacroDict),
201 + case DefToks of
202 + [{',',_} | Macro] ->
203 + {macro, dict:store(Name, {[], macro_body_def(Macro, [])}, MacroDict)};
204 + [{'(',_} | Macro] ->
205 + {macro, dict:store(Name, macro_params_body_def(Macro, []), MacroDict)}
206 + end;
207 +
208 +pre_proc([{'-',_}, {atom,_,include}, {'(',_}, {string,_,Filename}, {')',_}, {dot,_}], _MacroDict) ->
209 + {include, Filename};
210 +
211 +pre_proc(Toks,MacroDict) ->
212 + {tokens, subst_macros(Toks, MacroDict)}.
213 +
214 +macro_params_body_def([{')',_},{',',_} | Toks], RevParams) ->
215 + {reverse(RevParams), macro_body_def(Toks, [])};
216 +macro_params_body_def([{var,_,Param} | Toks], RevParams) ->
217 + macro_params_body_def(Toks, [Param | RevParams]);
218 +macro_params_body_def([{',',_}, {var,_,Param} | Toks], RevParams) ->
219 + macro_params_body_def(Toks, [Param | RevParams]).
220 +
221 +macro_body_def([{')',_}, {dot,_}], RevMacroBodyToks) ->
222 + reverse(RevMacroBodyToks);
223 +macro_body_def([Tok|Toks], RevMacroBodyToks) ->
224 + macro_body_def(Toks, [Tok | RevMacroBodyToks]).
225 +
226 +subst_macros(Toks, MacroDict) ->
227 + reverse(subst_macros_rev(Toks, MacroDict, [])).
228 +
229 +%% returns a reversed list of tokes
230 +subst_macros_rev([{'?',_}, {_,LineNum,'LINE'} | Toks], MacroDict, RevOutToks) ->
231 + %% special-case for ?LINE, to avoid creating a new MacroDict for every line in the source file
232 + subst_macros_rev(Toks, MacroDict, [{integer,LineNum,LineNum}] ++ RevOutToks);
233 +
234 +subst_macros_rev([{'?',_}, {_,_,Name}, {'(',_} = Paren | Toks], MacroDict, RevOutToks) ->
235 + case dict:fetch(Name, MacroDict) of
236 + {[], MacroValue} ->
237 + %% This macro does not have any vars, so ignore the fact that the invocation is followed by "(...stuff"
238 + %% Recursively expand any macro calls inside this macro's value
239 + %% TODO: avoid infinite expansion due to circular references (even indirect ones)
240 + RevExpandedOtherMacrosToks = subst_macros_rev(MacroValue, MacroDict, []),
241 + subst_macros_rev([Paren|Toks], MacroDict, RevExpandedOtherMacrosToks ++ RevOutToks);
242 + ParamsAndBody ->
243 + %% This macro does have vars.
244 + %% Collect all of the passe arguments, in an ordered list
245 + {NToks, Arguments} = subst_macros_get_args(Toks, []),
246 + %% Expand the varibles
247 + ExpandedParamsToks = subst_macros_subst_args_for_vars(ParamsAndBody, Arguments),
248 + %% Recursively expand any macro calls inside this macro's value
249 + %% TODO: avoid infinite expansion due to circular references (even indirect ones)
250 + RevExpandedOtherMacrosToks = subst_macros_rev(ExpandedParamsToks, MacroDict, []),
251 + subst_macros_rev(NToks, MacroDict, RevExpandedOtherMacrosToks ++ RevOutToks)
252 + end;
253 +
254 +subst_macros_rev([{'?',_}, {_,_,Name} | Toks], MacroDict, RevOutToks) ->
255 + %% This macro invocation does not have arguments.
256 + %% Therefore the definition should not have parameters
257 + {[], MacroValue} = dict:fetch(Name, MacroDict),
258 +
259 + %% Recursively expand any macro calls inside this macro's value
260 + %% TODO: avoid infinite expansion due to circular references (even indirect ones)
261 + RevExpandedOtherMacrosToks = subst_macros_rev(MacroValue, MacroDict, []),
262 + subst_macros_rev(Toks, MacroDict, RevExpandedOtherMacrosToks ++ RevOutToks);
263 +
264 +subst_macros_rev([Tok|Toks], MacroDict, RevOutToks) ->
265 +subst_macros_rev(Toks, MacroDict, [Tok|RevOutToks]);
266 +subst_macros_rev([], _MacroDict, RevOutToks) -> RevOutToks.
267 +
268 +subst_macros_get_args([{')',_} | Toks], RevArgs) ->
269 + {Toks, reverse(RevArgs)};
270 +subst_macros_get_args([{',',_}, {var,_,ArgName} | Toks], RevArgs) ->
271 + subst_macros_get_args(Toks, [ArgName| RevArgs]);
272 +subst_macros_get_args([{var,_,ArgName} | Toks], RevArgs) ->
273 + subst_macros_get_args(Toks, [ArgName | RevArgs]).
274 +
275 +subst_macros_subst_args_for_vars({[], BodyToks}, []) ->
276 + BodyToks;
277 +subst_macros_subst_args_for_vars({[Param | Params], BodyToks}, [Arg|Args]) ->
278 + NBodyToks = keyreplace(Param, 3, BodyToks, {var,1,Arg}),
279 + subst_macros_subst_args_for_vars({Params, NBodyToks}, Args).
280 +
281 +read_include_file(Filename, IncludeSearchPath) ->
282 + case file:path_open(IncludeSearchPath, Filename, [read, raw, binary]) of
283 + {ok, IoDevice, FullName} ->
284 + {ok, Data} = file:read(IoDevice, filelib:file_size(FullName)),
285 + file:close(IoDevice),
286 + binary_to_list(Data);
287 + {error, Reason} ->
288 + throw({failed_to_read_include_file, Reason, Filename, IncludeSearchPath})
289 + end.
290 \ No newline at end of file
291 diff --git a/src/ejabberd.app b/src/ejabberd.app
292 index 1ff41ec..7f0948f 100644
293 --- ejabberd.app
294 +++ ejabberd.app
295 @@ -115,7 +115,6 @@
296 nodetree_virtual,
297 p1_fsm,
298 p1_mnesia,
299 - ram_file_io_server,
300 randoms,
301 sha,
302 shaper,
303 diff --git a/src/ejabberd_loglevel.erl b/src/ejabberd_loglevel.erl
304 index 3134d4d..2a34060 100644
305 --- ejabberd_loglevel.erl
306 +++ ejabberd_loglevel.erl
307 @@ -38,51 +38,30 @@
308 -define(LOGMODULE, "error_logger").
309
310 %% Error levels:
311 -%% 0 -> No log
312 -%% 1 -> Critical
313 -%% 2 -> Error
314 -%% 3 -> Warning
315 -%% 4 -> Info
316 -%% 5 -> Debug
317 +-define(LOG_LEVELS,[ {0, no_log, "No log"}
318 + ,{1, critical, "Critical"}
319 + ,{2, error, "Error"}
320 + ,{3, warning, "Warning"}
321 + ,{4, info, "Info"}
322 + ,{5, debug, "Debug"}
323 + ]).
324 +
325 +set(LogLevel) when is_atom(LogLevel) ->
326 + set(level_to_integer(LogLevel));
327 set(Loglevel) when is_integer(Loglevel) ->
328 - Forms = compile_string(?LOGMODULE, ejabberd_logger_src(Loglevel)),
329 - load_logger(Forms, ?LOGMODULE, Loglevel);
330 + try
331 + {Mod,Code} = dynamic_compile:from_string(ejabberd_logger_src(Loglevel)),
332 + code:load_binary(Mod, ?LOGMODULE ++ ".erl", Code)
333 + catch
334 + Type:Error -> ?CRITICAL_MSG("Error compiling logger (~p): ~p~n", [Type, Error])
335 + end;
336 set(_) ->
337 exit("Loglevel must be an integer").
338 -
339 -%% --------------------------------------------------------------
340 -%% Compile a string into a module and returns the binary
341 -compile_string(Mod, Str) ->
342 - Fname = Mod ++ ".erl",
343 - {ok, Fd} = open_ram_file(Fname),
344 - file:write(Fd, Str),
345 - file:position(Fd, 0),
346 - case epp_dodger:parse(Fd) of
347 - {ok, Tree} ->
348 - Forms = revert_tree(Tree),
349 - close_ram_file(Fd),
350 - Forms;
351 - Error ->
352 - close_ram_file(Fd),
353 - Error
354 - end.
355 -
356 -open_ram_file(Fname) ->
357 - ram_file_io_server:start(self(), Fname, [read,write]).
358 -
359 -close_ram_file(Fd) ->
360 - file:close(Fd).
361 -
362 -revert_tree(Tree) ->
363 - [erl_syntax:revert(T) || T <- Tree].
364
365 -load_logger(Forms, Mod, Loglevel) ->
366 - Fname = Mod ++ ".erl",
367 - case compile:forms(Forms, [binary, {d,'LOGLEVEL',Loglevel}]) of
368 - {ok, M, Bin} ->
369 - code:load_binary(M, Fname, Bin);
370 - Error ->
371 - ?CRITICAL_MSG("Error ~p~n", [Error])
372 +level_to_integer(Level) ->
373 + case lists:keyfind(Level, 2, ?LOG_LEVELS) of
374 + {Int, Level, _Desc} -> Int;
375 + _ -> erlang:error({no_such_loglevel, Level})
376 end.