Erlang: Remove #include directives from all cpp files

I’m certain this can be done better and with fewer lines of code, but it’s my first Erlang jig.

-module(cppdev).
-compile(export_all).
 
quote_re([]) ->
    [];
quote_re([$.|Rest]) ->
    "\\." ++ quote_re(Rest);
quote_re([C|Rest]) ->
    [C|quote_re(Rest)].
 
filter_include(Data, Include) ->
    {ok, Pattern} = re:compile("^\\s*#\\s*include\\s*[<\"](?:(?i)" ++ quote_re(Include) ++ ")[>\"]\\s*$"),
    grep_v(Data, Pattern).
 
extract_line(Text) ->
    case lists:splitwith(fun(C) -> C =/= $\n end, Text) of
        {Line, [C|Rest]} -> {Line ++ [C],Rest};
        {Line, Rest}     -> {Line, Rest}
    end.
 
grep_v(Data, Pattern) ->
    grep_v([], Data, Pattern).
 
grep_v(Accum, [], _) ->
    lists:flatten(lists:reverse(Accum));
grep_v(Accum, Data, Pattern) ->
    {Line,Rest} = extract_line(Data),
    case re:run(Line, Pattern) of
        {match,_} -> grep_v(Accum, Rest, Pattern);
        _         -> grep_v([Line|Accum], Rest, Pattern)
    end.
 
transform_file(Fun, Filename) ->
	{ok, Data} = file:read_file(Filename),
	NewData = list_to_binary(Fun(binary_to_list(Data))),
	if
	  Data =:= NewData ->
        nochange;
	  true ->
        ok = file:write_file(Filename ++ "-", Data),
        ok = file:write_file(Filename, NewData)
	end.
 
find_files(Fun, Root) ->
    find_files([], Fun, [Root]).
 
find_files(Accum, _, []) ->
    Accum;
find_files(Accum, Fun, [Root|RestOfRoots]) ->
    {ok,Files} = file:list_dir(Root),
    Files2 = lists:filter(fun(FN) -> string:to_lower(FN) =/= ".svn" end, Files),
    PathedFiles = lists:map(fun(FN) -> Root ++ "\\" ++ FN end, Files2),
    Dirs = lists:filter(fun(P) -> filelib:is_dir(P) end, PathedFiles),
    FilteredFiles = lists:filter(Fun, PathedFiles),
    find_files(Accum ++ FilteredFiles, Fun, RestOfRoots ++ Dirs).
 
 
fix() ->
    StripHeaderF = fun(D) -> filter_include(D, "ISOMsgEx.h") end,
    TransformF = fun(FN) -> transform_file(StripHeaderF, FN) end,
    FilenameTestF = fun(FN) -> string:to_lower(string:right(FN, 4)) =:= ".cpp" end,
    lists:map(TransformF, find_files(FilenameTestF, "Components")).
Posted by: Jason Felice on August 3, 2009 • Tags: , • Posted in: Jigs

Comments are closed for this entry.