Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 303 lines (245 sloc) 8.712 kb
d69e4d8 Claes Wikstrom ""
authored
1 %%%----------------------------------------------------------------------
2 %%% File : yaws_compile.erl
3 %%% Author : Claes Wikstrom <klacke@hyber.org>
4 %%% Purpose :
5 %%% Created : 20 Feb 2002 by Claes Wikstrom <klacke@hyber.org>
6 %%%----------------------------------------------------------------------
7
8 -module(yaws_compile).
9 -author('klacke@hyber.org').
10
11 -compile(export_all).
3c06a9e Claes Wikstrom rearr of includefiles
authored
12
13
14
15 -include_lib("yaws/include/yaws.hrl").
16 -include_lib("yaws/include/yaws_api.hrl").
17 -include("yaws_debug.hrl").
d69e4d8 Claes Wikstrom ""
authored
18
19
20
21 %% tada !!
22 %% returns a CodeSpec which is:
23 %% a list {data, NumChars} |
24 %% {mod, LineNo, YawsFile, NumSkipChars, Mod, Func} |
25 %% {error, NumSkipChars, E}}
26
27 % each erlang fragment inside <erl> .... </erl> is compiled into
28 % its own module
29
30
31 -record(comp, {
32 gc, %% global conf
33 sc, %% server conf
34 startline = 0,
35 modnum = 1,
36 infile,
37 infd,
38 outfile,
39 outfd}).
40
41
42
43 comp_opts(GC) ->
6c9c37f Claes Wikstrom ""
authored
44 ?Debug("I=~p~n", [GC#gconf.include_dir]),
d69e4d8 Claes Wikstrom ""
authored
45 I = lists:map(fun(Dir) -> {i, Dir} end, GC#gconf.include_dir),
8722844 Claes Wikstrom a file which has at least one compilation error shouldn't be cached in t...
authored
46 Opts = [binary, report_errors | I],
d69e4d8 Claes Wikstrom ""
authored
47 ?Debug("Compile opts = ~p~n", [Opts]),
48 Opts.
49
50
51 compile_file(File, GC, SC) ->
52 case file:open(File, [read]) of
53 {ok, Fd} ->
54 Spec = compile_file(#comp{infile = File,
55 infd = Fd, gc = GC, sc = SC},
56 1,
8722844 Claes Wikstrom a file which has at least one compilation error shouldn't be cached in t...
authored
57 io:get_line(Fd, ''), init, 0, [], 0),
2129adc Claes Wikstrom ""
authored
58 Spec;
59 _Err ->
d69e4d8 Claes Wikstrom ""
authored
60 yaws:elog("can't open ~s~n", [File]),
61 exit(normal)
62 end.
63
8722844 Claes Wikstrom a file which has at least one compilation error shouldn't be cached in t...
authored
64 compile_file(C, _LineNo, eof, _Mode, NumChars, Ack, Errors) ->
d69e4d8 Claes Wikstrom ""
authored
65 file:close(C#comp.infd),
8722844 Claes Wikstrom a file which has at least one compilation error shouldn't be cached in t...
authored
66 {ok, [{errors, Errors} |lists:reverse([{data, NumChars} |Ack])]};
d69e4d8 Claes Wikstrom ""
authored
67
68
39c94ab Claes Wikstrom ""
authored
69 %% skip initial space if first thing is <erl> otherwise not
8722844 Claes Wikstrom a file which has at least one compilation error shouldn't be cached in t...
authored
70 compile_file(C, LineNo, Chars, init, NumChars, Ack, Errs) ->
d69e4d8 Claes Wikstrom ""
authored
71 case Chars -- [$\s, $\t, $\n, $\r] of
72 [] ->
961926f Claes Wikstrom ""
authored
73 ?Debug("SKIP ~p~n", [Chars]),
74 L=length(Chars),
8722844 Claes Wikstrom a file which has at least one compilation error shouldn't be cached in t...
authored
75 compile_file(C, LineNo+1, line(C), init, NumChars-L, Ack, Errs);
39c94ab Claes Wikstrom ""
authored
76 "<erl>" ++ _ -> %% first chunk is erl, skip whistespace
8722844 Claes Wikstrom a file which has at least one compilation error shouldn't be cached in t...
authored
77 compile_file(C, LineNo, Chars, html, NumChars, Ack, Errs);
d69e4d8 Claes Wikstrom ""
authored
78 _ ->
39c94ab Claes Wikstrom ""
authored
79 %% first chunk is html, keep whitespace
80 Fd=C#comp.infd,
81 file:position(Fd, bof),
8722844 Claes Wikstrom a file which has at least one compilation error shouldn't be cached in t...
authored
82 compile_file(C,1,io:get_line(Fd,''),html,0,[], Errs)
d69e4d8 Claes Wikstrom ""
authored
83 end;
84
8722844 Claes Wikstrom a file which has at least one compilation error shouldn't be cached in t...
authored
85 compile_file(C, LineNo, Chars = "<erl>" ++ _Tail, html, NumChars, Ack,Es) ->
d69e4d8 Claes Wikstrom ""
authored
86 ?Debug("start erl:~p",[LineNo]),
87 C2 = new_out_file(LineNo, C, C#comp.gc),
88 C3 = C2#comp{startline = LineNo},
89 L = length(Chars),
90 if
91 NumChars > 0 ->
92 compile_file(C3, LineNo+1, line(C) , erl,L,
8722844 Claes Wikstrom a file which has at least one compilation error shouldn't be cached in t...
authored
93 [{data, NumChars} | Ack], Es);
d69e4d8 Claes Wikstrom ""
authored
94 true -> %% just ignore zero byte data segments
8722844 Claes Wikstrom a file which has at least one compilation error shouldn't be cached in t...
authored
95 compile_file(C3, LineNo+1, line(C) , erl, L + (-NumChars),
96 Ack, Es) %hack
d69e4d8 Claes Wikstrom ""
authored
97 end;
98
8722844 Claes Wikstrom a file which has at least one compilation error shouldn't be cached in t...
authored
99 compile_file(C, LineNo, Chars = "</erl>" ++ _Tail, erl, NumChars, Ack, Es) ->
d69e4d8 Claes Wikstrom ""
authored
100 ?Debug("stop erl:~p",[LineNo]),
101 file:close(C#comp.outfd),
102 NumChars2 = NumChars + length(Chars),
103 case proc_compile_file(C#comp.outfile, comp_opts(C#comp.gc)) of
104 {ok, ModuleName, Binary} ->
105 case code:load_binary(ModuleName, C#comp.outfile, Binary) of
106 {module, ModuleName} ->
107 C2 = C#comp{modnum = C#comp.modnum+1},
108 L2 = check_exported(C, LineNo,NumChars2, ModuleName),
8722844 Claes Wikstrom a file which has at least one compilation error shouldn't be cached in t...
authored
109 compile_file(C2, LineNo+1, line(C),html,0,L2++Ack, Es);
d69e4d8 Claes Wikstrom ""
authored
110 Err ->
111 A2 = gen_err(C, LineNo, NumChars2,
112 ?F("Cannot load module ~p: ~p",
113 [ModuleName, Err])),
114 compile_file(C, LineNo+1, line(C),
8722844 Claes Wikstrom a file which has at least one compilation error shouldn't be cached in t...
authored
115 html, 0, [A2|Ack], Es+1)
d69e4d8 Claes Wikstrom ""
authored
116 end;
2129adc Claes Wikstrom ""
authored
117 {error, Errors, _Warnings} ->
d69e4d8 Claes Wikstrom ""
authored
118 %% FIXME remove outfile here ... keep while debuging
119 A2 = comp_err(C, LineNo, NumChars2, Errors),
8722844 Claes Wikstrom a file which has at least one compilation error shouldn't be cached in t...
authored
120 compile_file(C, LineNo+1, line(C), html, 0, [A2|Ack], Es+1);
d69e4d8 Claes Wikstrom ""
authored
121 {error, Str} ->
122 %% this is boring but does actually happen
123 %% in order to get proper user errors here we need to catch i/o
124 %% or hack compiler/parser
125 yaws:elog("Dynamic compile error in file ~s, line~w",
126 [C#comp.infile, LineNo]),
127 A2 = {error, NumChars2, ?F("<pre> Dynamic compile error in file "
128 " ~s line ~w~n~s </pre>",
129 [C#comp.infile, LineNo, Str])},
8722844 Claes Wikstrom a file which has at least one compilation error shouldn't be cached in t...
authored
130 compile_file(C, LineNo+1, line(C), html, 0, [A2|Ack], Es+1)
d69e4d8 Claes Wikstrom ""
authored
131 end;
132
8722844 Claes Wikstrom a file which has at least one compilation error shouldn't be cached in t...
authored
133 compile_file(C, LineNo, Chars = "<pre>" ++ _Tail, html, NumChars, Ack, Es) ->
d69e4d8 Claes Wikstrom ""
authored
134 ?Debug("start pre:~p",[LineNo]),
8722844 Claes Wikstrom a file which has at least one compilation error shouldn't be cached in t...
authored
135 compile_file(C, LineNo+1, line(C) , pre, NumChars + length(Chars), Ack,Es);
d69e4d8 Claes Wikstrom ""
authored
136
8722844 Claes Wikstrom a file which has at least one compilation error shouldn't be cached in t...
authored
137 compile_file(C, LineNo, Chars = "</pre>" ++ _Tail, pre, NumChars, Ack,Es) ->
d69e4d8 Claes Wikstrom ""
authored
138 ?Debug("stop pre:~p",[LineNo]),
8722844 Claes Wikstrom a file which has at least one compilation error shouldn't be cached in t...
authored
139 compile_file(C, LineNo+1, line(C) , html, NumChars + length(Chars), Ack,Es);
d69e4d8 Claes Wikstrom ""
authored
140
8722844 Claes Wikstrom a file which has at least one compilation error shouldn't be cached in t...
authored
141 compile_file(C, LineNo, Chars, erl, NumChars, Ack,Es) ->
0d623c1 Claes Wikstrom ""
authored
142 case has_tag(Chars, "</erl>") of
143 {ok, Skipped, Chars2} ->
8722844 Claes Wikstrom a file which has at least one compilation error shouldn't be cached in t...
authored
144 compile_file(C, LineNo, Chars2, erl, NumChars + Skipped, Ack,Es);
0d623c1 Claes Wikstrom ""
authored
145 false ->
146 io:format(C#comp.outfd, "~s", [Chars]),
147 compile_file(C, LineNo+1, line(C), erl, NumChars +
8722844 Claes Wikstrom a file which has at least one compilation error shouldn't be cached in t...
authored
148 length(Chars), Ack,Es)
0d623c1 Claes Wikstrom ""
authored
149 end;
150
d69e4d8 Claes Wikstrom ""
authored
151
8722844 Claes Wikstrom a file which has at least one compilation error shouldn't be cached in t...
authored
152 compile_file(C, LineNo, Chars, html, NumChars, Ack,Es) ->
0d623c1 Claes Wikstrom ""
authored
153 case has_tag(Chars, "<erl>") of
154 {ok, Skipped, Chars2} ->
8722844 Claes Wikstrom a file which has at least one compilation error shouldn't be cached in t...
authored
155 compile_file(C, LineNo, Chars2, html, NumChars+Skipped, Ack,Es);
0d623c1 Claes Wikstrom ""
authored
156 false ->
157 compile_file(C, LineNo+1, line(C), html, NumChars +
8722844 Claes Wikstrom a file which has at least one compilation error shouldn't be cached in t...
authored
158 length(Chars), Ack,Es)
0d623c1 Claes Wikstrom ""
authored
159 end;
d69e4d8 Claes Wikstrom ""
authored
160
8722844 Claes Wikstrom a file which has at least one compilation error shouldn't be cached in t...
authored
161 compile_file(C, LineNo, Chars, pre, NumChars, Ack,Es) ->
162 compile_file(C, LineNo+1, line(C), pre, NumChars + length(Chars), Ack,Es).
d69e4d8 Claes Wikstrom ""
authored
163
164
165
0d623c1 Claes Wikstrom ""
authored
166 has_tag(L, Str) ->
167 has_tag(L, Str, 0).
168 has_tag([H|T], Tag, Num) ->
169 case yaws:is_space(H) of
170 true ->
171 has_tag(T, Tag, Num+1);
172 false ->
173 case lists:prefix(Tag, [H|T]) of
174 true ->
175 {ok, Num, [H|T]};
176 false ->
177 false
178 end
179 end;
180 has_tag(_,_,_) ->
181 false.
d69e4d8 Claes Wikstrom ""
authored
182
183 check_exported(C, LineNo, NumChars, Mod) ->
184 case is_exported(out, 1, Mod) of
185 true ->
186 [{mod, C#comp.startline, C#comp.infile,
187 NumChars,Mod,out}];
188 false ->
189 ?Debug("XX ~p~n", [C]),
190 [gen_err(C, LineNo, NumChars,
191 "out/1 is not defined ")]
192 end.
193
194 line(C) ->
195 io:get_line(C#comp.infd, '').
196
197 is_exported(Fun, A, Mod) ->
198 case (catch Mod:module_info()) of
199 List when list(List) ->
200 case lists:keysearch(exports, 1, List) of
201 {value, {exports, Exp}} ->
202 lists:member({Fun, A}, Exp);
203 _ ->
204 false
205 end;
206 _ ->
207 false
208 end.
209
210
211 %% this will generate 9 lines
212 new_out_file(Line, C, GC) ->
213 Mnum = gen_server:call(yaws_server, mnum),
214 Module = [$m | integer_to_list(Mnum)],
3dc56a7 Claes Wikstrom javascript support in ehtml
authored
215 OutFile = lists:flatten(
216 io_lib:format(
217 "/tmp/yaws/~s/~s.erl",[GC#gconf.uid, Module])),
218
219 %% "/tmp/yaws/" ++ Module ++ ".erl",
220
d69e4d8 Claes Wikstrom ""
authored
221 ?Debug("Writing outout file~s~n", [OutFile]),
222 {ok, Out} = file:open(OutFile, [write]),
223 ok = io:format(Out, "-module(~s).~n-compile(export_all).~n~n", [Module]),
224 io:format(Out, "%%~n%% code at line ~w from file ~s~n%%~n",
225 [Line, C#comp.infile]),
226
227 io:format(Out, "-import(yaws_api, [f/2, fl/1, parse_post_data/2]). ~n~n", []),
228 io:format(Out, '-include("~s/include/yaws_api.hrl").~n',
229 [GC#gconf.yaws_dir]),
230 C#comp{outfd = Out,
231 outfile = OutFile}.
232
233
2129adc Claes Wikstrom ""
authored
234 gen_err(C, _LineNo, NumChars, Err) ->
d69e4d8 Claes Wikstrom ""
authored
235 S = io_lib:format("<p> Error in File ~s Erlang code beginning "
236 "at line ~w~n"
237 "Error is: ~p~n", [C#comp.infile, C#comp.startline,
238 Err]),
239 yaws:elog("~s~n", [S]),
240 {error, NumChars, S}.
241
242
2129adc Claes Wikstrom ""
authored
243 comp_err(C, _LineNo, NumChars, Err) ->
d69e4d8 Claes Wikstrom ""
authored
244 case Err of
2129adc Claes Wikstrom ""
authored
245 [{_FileName, [ErrInfo|_]} |_] ->
d69e4d8 Claes Wikstrom ""
authored
246 {Line0, Mod, E}=ErrInfo,
247 Line = Line0 + C#comp.startline - 9,
2129adc Claes Wikstrom ""
authored
248 ?Debug("XX ~p~n", [{_LineNo, Line0}]),
d69e4d8 Claes Wikstrom ""
authored
249 Str = io_lib:format("~s:~w: ~s\n",
250 [C#comp.infile, Line,
251 apply(Mod, format_error, [E])]),
252 HtmlStr = ?F("~n<pre>~nDynamic compile error: ~s~n</pre>~n",
253 [Str]),
254 yaws:elog("Dynamic compiler err ~s", [Str]),
255 {error, NumChars, HtmlStr};
2129adc Claes Wikstrom ""
authored
256 _Other ->
d69e4d8 Claes Wikstrom ""
authored
257 yaws:elog("Dynamic compile error", []),
258 {error, NumChars, ?F("<pre> Compile error - "
259 "Other err ~p</pre>~n", [Err])}
260 end.
261
262
263 %% due to compiler not producing proper error
264 %% we NEED to catch all io produced by the compiler
265
266 proc_compile_file(F, Opts) ->
267 G = group_leader(),
268 group_leader(self(), self()),
269 P = proc_lib:spawn(?MODULE, compiler_proc, [self(), F, Opts]),
270 Res = get_compiler_data(P, []),
271 group_leader(G, self()),
272 Res.
273
274 compiler_proc(Top, F, Opts) ->
275 R = (catch compile:file(F, Opts)),
276 Top ! {self(), result, R}.
277
278
279 get_compiler_data(P, Ack) ->
280 receive
281 {P, result, {ok, Mod, Bin}} ->
282 {ok, Mod, Bin};
283 {io_request, P1, P2, {put_chars, M, F, A}} ->
284 P1 ! {io_reply, P2, ok},
285 Str = apply(M, F, A),
286 get_compiler_data(P, [Str|Ack]);
287 {P, result, {error, Errors, Warnings}} ->
288 {error, Errors, Warnings};
289 {P, result, error} ->
290 S = lists:map(
291 fun(S) -> S ++ "\n" end, lists:reverse(Ack)),
292 {error, S}
293 end.
294
295
296
297
298
299
300
301
302
Something went wrong with that request. Please try again.