1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2008-2018. 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%% Some utilities
21
22-module(gen_util).
23-compile(export_all).
24
25lowercase([F|R]) when F >= $A, F =< $Z ->   [F+($a-$A)|R];
26lowercase(Str) when is_list(Str) ->   Str.
27
28lowercase_all([F|R]) when F >= $A, F =< $Z -> [F+($a-$A)|lowercase_all(R)];
29lowercase_all([F|R])  ->               [F|lowercase_all(R)];
30lowercase_all([]) ->                   [].
31
32uppercase([F|R]) when F >= $a, F =< $z ->    [F+($A-$a)|R];
33uppercase(Str) when is_list(Str) ->   Str.
34
35uppercase_all([F|R]) when F >= $a, F =< $z -> [F+($A-$a)|uppercase_all(R)];
36uppercase_all([A|R]) ->             [A|uppercase_all(R)];
37uppercase_all([]) ->                [].
38
39
40strip_name([H|R1],[H|R2]) ->
41    strip_name(R1,R2);
42strip_name(String,[]) -> String.
43
44
45get_hook(_Type, undefined) -> ignore;
46get_hook(Type, List) -> proplists:get_value(Type, List, ignore).
47
48get_taylor_made(Str, Name) ->
49    re:run(Str, "<<"++Name++"(.*)"++Name++">>",
50	   [dotall, {capture, all_but_first, list}]).
51
52open_write(File) ->
53    open_write(File, []).
54open_write(File, Opts) ->
55    %% io:format("Generating ~s~n",[File]),
56    {ok, Fd} = file:open(File++".temp", [write|Opts]),
57    put(current_file, {Fd,File}).
58
59
60close() ->
61    case get(current_file) of
62	undefined ->
63	    ok;
64	{closed, File} ->
65	    io:format("Closing twice ~s~n",[File]);
66	{Fd,File} ->
67	    file:close(Fd),
68            Prefix = case os:getenv("WSLENV") of
69                         false -> "";
70                         _ -> "wsl.exe "
71                     end,
72	    case os:cmd(Prefix ++ "diff " ++ File ++ " " ++ File ++ ".temp") of
73		[] ->
74		    ok = file:delete(File ++ ".temp");
75		Diff ->
76		    case check_diff(Diff) of
77			copyright -> %% We ignore copyright changes only
78			    ok = file:delete(File ++ ".temp");
79			_ ->
80			    io:format("Diff in ~s~n~.1000s ~n", [File, string:trim(Diff)]),
81			    case file:rename(File ++ ".temp", File) of
82				ok -> ok;
83				_ ->  io:format("*****  Failed to save file ~p ~n",[File])
84			    end
85		    end
86	    end,
87	    put(current_file, {closed, File})
88    end.
89
90
91check_diff(Diff) ->
92    try
93	[_,D1,_,D2|Tail] = re:split(Diff, "\n"),
94	case Tail of
95	    [] -> ok;
96	    [<<>>] -> ok;
97	    _ -> throw(diff)
98	end,
99	copyright(D1),
100	copyright(D2),
101	copyright
102    catch
103	throw:diff -> diff;
104	error:{badmatch,_} ->
105	    diff;
106	_:What:Stacktrace ->
107	    io:format("~p:~p: ~p ~p~n", [?MODULE,?LINE, What, Stacktrace]),
108	    diff
109    end.
110
111copyright(<<_, _, "%% Copyright", _/binary>>) -> ok;
112copyright(<<_, _, " * Copyright", _/binary>>) -> ok;
113copyright(_) -> throw(diff).
114
115w(Str) ->
116    w(Str, []).
117w(Str,Args) ->
118    {Fd,_} = get(current_file),
119    io:format(Fd, Str, Args).
120
121args(Fun, Limit, List) ->
122    args(Fun, Limit, List, infinity, 0).
123
124args(Fun, Limit, List, Max) ->
125    args(Fun, Limit, List, Max, 0).
126
127args(_Fun, _Limit, [], _Max, _) -> "";  %% No args
128args(Fun, _Limit, [Last], _Max, _Pos) ->
129    case Fun(Last) of
130	skip -> ""; %% FIXME bug if last skips
131	Str  -> Str
132    end;
133args(Fun, Limit, [H|R], Max, Pos) ->
134    case Fun(H) of
135	skip -> args(Fun,Limit,R, Max, Pos);
136	Str  ->
137	    {NL, NewPos} =
138		case string:length(Str) + Pos of
139		    Curr when Curr > Max ->
140			{"\n  ", 0};
141		    Curr ->
142			{"", Curr}
143		end,
144	    case args(Fun,Limit,R, Max, NewPos) of
145		"" -> Str;
146		End -> Str ++ Limit ++ NL ++ End
147	    end
148    end.
149
150
151
152
153tokens(S) ->
154    tokens1(S, " \t\r\n(){}*;,@", []).
155tokens(S,Seps) ->
156    tokens1(S, Seps, []).
157
158tokens1([C|S], Seps, Toks) ->
159    case lists:member(C, Seps) of
160        true -> tokens1(S, Seps, [C|Toks]);
161        false -> tokens2(S, Seps, Toks, [C])
162    end;
163tokens1([], _Seps, Toks) ->
164    replace_and_remove(Toks, []).
165
166tokens2([C|S], Seps, Toks, Cs) ->
167    case lists:member(C, Seps) of
168        true -> tokens1(S, Seps, [C, lists:reverse(Cs) |Toks]);
169        false -> tokens2(S, Seps, Toks, [C|Cs])
170    end;
171tokens2([], _Seps, Toks, Cs) ->
172    replace_and_remove([lists:reverse(Cs)|Toks], []).
173
174replace_and_remove([E|R], Acc) when is_list(E) -> %% Keep everything that is a word
175    replace_and_remove(R, [E|Acc]);
176replace_and_remove([$\n | R], Acc) ->   %% It is semi line oriented so keep eol
177    replace_and_remove(R, [eol|Acc]);
178replace_and_remove([$( | R], Acc) ->
179    replace_and_remove(R, ["("|Acc]);
180replace_and_remove([$) | R], Acc) ->
181    replace_and_remove(R, [")"|Acc]);
182replace_and_remove([${ | R], Acc) ->
183    replace_and_remove(R, ["{"|Acc]);
184replace_and_remove([$} | R], Acc) ->
185    replace_and_remove(R, ["}"|Acc]);
186replace_and_remove([$| | R], Acc) ->
187    replace_and_remove(R, ["|"|Acc]);
188replace_and_remove([$* | R], Acc) ->
189    replace_and_remove(R, ["*"|Acc]);
190replace_and_remove([$+ | R], Acc) ->
191    replace_and_remove(R, ["+"|Acc]);
192replace_and_remove([$& | R], Acc) ->
193    replace_and_remove(R, [$&|Acc]);
194replace_and_remove([$<,$< | R], Acc) ->
195    replace_and_remove(R, ["<<"|Acc]);
196replace_and_remove([$, | R], Acc) ->
197    replace_and_remove(R, [cont|Acc]);
198replace_and_remove([$; | R], Acc) ->
199    replace_and_remove(R, [eoe|Acc]);
200replace_and_remove([$@ | R], Acc) ->
201    replace_and_remove(R, [directive|Acc]);
202
203replace_and_remove([_E|R], Acc) ->       %% Ignore everything else
204    replace_and_remove(R, Acc);
205replace_and_remove([], Acc) ->
206    Acc.
207
208halt(Reason) ->
209    case process_info(group_leader(), status) of
210	{_,waiting} ->
211	    %% Now all output data is down in the driver.
212	    %% Give the driver some extra time before halting.
213	    receive after 10 -> ok end,
214	    erlang:halt(Reason);
215	_ ->
216	    %% Probably still processing I/O requests.
217	    receive after 20 -> ok end,
218	    gen_util:halt(Reason)
219    end.
220
221erl_copyright() ->
222    StartYear = start_year(get(current_class)),
223    {CurrentYear,_,_}   = erlang:date(),
224    w("%%~n",[]),
225    w("%% %CopyrightBegin%~n",[]),
226    w("%%~n",[]),
227    w("%% Copyright Ericsson AB ~p-~p. All Rights Reserved.~n",
228      [StartYear, CurrentYear]),
229    w("%%~n",[]),
230    w("%% Licensed under the Apache License, Version 2.0 (the \"License\");~n",[]),
231    w("%% you may not use this file except in compliance with the License.~n",[]),
232    w("%% You may obtain a copy of the License at~n",[]),
233    w("%%~n",[]),
234    w("%%     http://www.apache.org/licenses/LICENSE-2.0~n",[]),
235    w("%%~n",[]),
236    w("%% Unless required by applicable law or agreed to in writing, software~n",[]),
237    w("%% distributed under the License is distributed on an \"AS IS\" BASIS,~n",[]),
238    w("%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.~n",[]),
239    w("%% See the License for the specific language governing permissions and~n",[]),
240    w("%% limitations under the License.~n",[]),
241    w("%%~n",[]),
242    w("%% %CopyrightEnd%~n",[]).
243
244c_copyright() ->
245    {CurrentYear,_,_}   = erlang:date(),
246    w("/*~n",[]),
247    w(" * %CopyrightBegin%~n",[]),
248    w(" *~n",[]),
249    w(" * Copyright Ericsson AB 2008-~p. All Rights Reserved.~n",[CurrentYear]),
250    w(" *~n",[]),
251    w(" * Licensed under the Apache License, Version 2.0 (the \"License\");~n",[]),
252    w(" * you may not use this file except in compliance with the License.~n",[]),
253    w(" * You may obtain a copy of the License at~n",[]),
254    w(" *~n",[]),
255    w(" *     http://www.apache.org/licenses/LICENSE-2.0~n",[]),
256    w(" *~n",[]),
257    w(" * Unless required by applicable law or agreed to in writing, software~n",[]),
258    w(" * distributed under the License is distributed on an \"AS IS\" BASIS,~n",[]),
259    w(" * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.~n",[]),
260    w(" * See the License for the specific language governing permissions and~n",[]),
261    w(" * limitations under the License.~n",[]),
262    w(" *~n",[]),
263    w(" * %CopyrightEnd%~n",[]),
264    w("*/~n",[]).
265
266start_year("wxAuiManagerEvent") -> 2009;
267start_year("wxAuiNotebookEvent") -> 2009;
268start_year("wxChoicebook") -> 2009;
269start_year("wxGridCellBoolEditor") -> 2009;
270start_year("wxGridCellBoolRenderer") -> 2009;
271start_year("wxGridCellChoiceEditor") -> 2009;
272start_year("wxGridCellFloatEditor") -> 2009;
273start_year("wxGridCellFloatRenderer") -> 2009;
274start_year("wxGridCellNumberEditor") -> 2009;
275start_year("wxGridCellNumberRenderer") -> 2009;
276start_year("wxGridCellStringRenderer") -> 2009;
277start_year("wxGridCellTextEditor") -> 2009;
278start_year("wxHtmlLinkEvent") -> 2009;
279start_year("wxHtmlWindow") -> 2009;
280start_year("wxListbook") -> 2009;
281start_year("wxLogNull") -> 2009;
282start_year("wxSpinEvent") -> 2009;
283start_year("wxSplitterEvent") -> 2009;
284start_year("wxSplitterWindow") -> 2009;
285start_year("wxToolbook") -> 2009;
286start_year("wxTreebook") -> 2009;
287start_year(_) -> 2008.
288