[erlang-questions] : compile module from string, containing macro definitions

Ulf Wiger (TN/EAB) <>
Thu Mar 15 10:33:34 CET 2007


I maintain that the easiest way forward is to make
a ram_file_io_server, based on file_io_server, and
thus make the ram files capable of supporting normal
file operations (not just 'raw' mode).

It would also require a small change in epp.

The only drawback with this suggestion, as I see it,
is that OTP needs to do it. (:

(Ok, another drawback is that it's not a good solution
for parsing a byte stream, and one does need to copy 
the string into the ram file.)

It doesn't preclude string ports or other approaches
to doing similar things, but ram files are useful, and
could be made even more so.

BR,
Ulf W


Ok, here's a short demo of a ram_file_io_server module
and a slightly modified epp.erl. It shows a ram file 
used as a normal file, and an epp that accepts being 
handed a file descriptor (it needs a name too).

Eshell V5.5.3  (abort with ^G)
1> f(),{ok,Fd} =
ram_file_io_server:start(self(),"test.erl",[read,write]).
{ok,<0.44.0>}
2> {ok,Bin} = file:read_file("test.erl").

{ok,<<"-module(test).\n-export([f/1]).\n\n-define(X, x).\n\nf(Y) ->\n
{?X, Y}.\n">>}
3> file:write(Fd,Bin).
ok
4> file:position(Fd,0).
{ok,0}
5> {ok,Epp} = epp:use_fd(Fd,"test.erl",[]).
{ok,<0.49.0>}
6> epp:parse_erl_form(Epp).
{ok,{attribute,1,file,{"test.erl",1}}}
7> epp:parse_erl_form(Epp).
{ok,{attribute,1,module,test}}
8> epp:parse_erl_form(Epp).
{ok,{attribute,2,export,[{f,1}]}}
9> epp:parse_erl_form(Epp).
{ok,{function,6,
              f,
              1,
              [{clause,6,
                       [{var,6,'Y'}],
                       [],
                       [{tuple,7,[{atom,7,x},{var,7,'Y'}]}]}]}}
10> epp:parse_erl_form(Epp).
{eof,8}
11> epp:close(Epp).
ok
12> file:close(Fd).
ok
BREAK: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded
       (v)ersion (k)ill (D)b-tables (d)istribution
a
$> diff ram_file_io_server.erl
$OTP_ROOT/lib/kernel-2.10.11/src/file_io_server.erl 
18c18
< -module(ram_file_io_server).
---
> -module(file_io_server).
27c27
< -define(PRIM_FILE, ram_file).
---
> -define(PRIM_FILE, prim_file).
$> diff epp.erl $OTP_ROOT/lib/stdlib-1.13.10/src/epp.erl
23d22
< -export([use_fd/3,use_fd/4]).
29d27
<             mode,                             % file or fd
60,68d57
< use_fd(Fd, File, Path) ->
<     use_fd(Fd, File, Path, []).
< 
< use_fd(Fd, File, Path, Pdm) ->
<     Self = self(),
<     Epp = spawn(fun() -> server(Self, fd, Fd, File, Path, Pdm) end),
<     epp_request(Epp).
<                        
< 
144,151d132
<     case file:open(Name, [read]) of
<       {ok, File} ->
<           server(Pid, file, File, Name, Path, Pdm);
<       {error,E} ->
<           epp_reply(Pid, {error,E})
<     end.
< 
< server(Pid, Mode, Fd, Name, Path, Pdm) ->
153,161c134,147
<     put(user_path, Path),
<     Ms0 = predef_macros(Name),
<     case user_predef(Pdm, Ms0) of
<       {ok,Ms1} ->
<           epp_reply(Pid, {ok,self()}),
<           St = #epp{file=Fd,mode=Mode,name=Name,macs=Ms1},
<           From = wait_request(St),
<           enter_file_reply(From, Name, 1),
<           wait_req_scan(St);
---
>     case file:open(Name, read) of
>       {ok,File} ->
>           put(user_path, Path),
>           Ms0 = predef_macros(Name),
>           case user_predef(Pdm, Ms0) of
>               {ok,Ms1} ->
>                   epp_reply(Pid, {ok,self()}),
>                   St = #epp{file=File,name=Name,macs=Ms1},
>                   From = wait_request(St),
>                   enter_file_reply(From, Name, 1),
>                   wait_req_scan(St);
>               {error,E} ->
>                   epp_reply(Pid, {error,E})
>           end;
166,171d151
< file_close(fd, _) ->
<     %% let the user close the file (which may not even be a file)
<     ok;
< file_close(file, Fd) ->
<     file:close(Fd).
< 
292c272
<                   file_close(St#epp.mode, St#epp.file),
---
>                   file:close(St#epp.file),

The change to epp.erl wasn't as big as the diff suggests.
I reorganized the server() function slightly, and diff marked 
the whole block as changed.

Obviously, corresponding changes are needed in file.erl, in order
to recognize a 'normal' ram file.

BR,
Ulf W




More information about the erlang-questions mailing list