1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
|
open Str
(*
let gen dest_filename =
let basename = Filename.basename dest_filename in
let directory = Filename.dirname dest_filename in
let dirname = Filename.basename directory in
let up_directory = Filename.dirname directory in
let templates = Filename.concat up_directory "template" in
let template, keyword =
let keyword = ref "" in
let template = ref "" in
try
let len = String.length basename in
for i = 0 to len - 1 do
match basename.[i] with
'A' ..'Z' ->
template := "template" ^ (String.sub basename i (len-i));
keyword := String.sub basename 0 i;
!keyword.[0] <- Char.uppercase !keyword.[0];
raise Exit
| _ -> ()
done;
assert false
with Exit -> !template, !keyword
in
(*
prerr_endline (Printf.sprintf "FILE [%s]" dest_filename);
prerr_endline (Printf.sprintf "Replace [%s] by [%s]" "Template" keyword);
*)
let ts = "Template" in
let ts_len = String.length ts in
let full_template = Filename.concat templates template in
let ic = open_in full_template in
let oc = open_out dest_filename in
let rec iter_line i =
let line = input_line ic in
let buf = Buffer.create 100 in
let len = String.length line in
(* Printf.printf "LINE [%d]" len; print_newline (); *)
if len >= ts_len then
let rec iter i =
(* Printf.printf "[%d]" i; print_newline (); *)
if i <= len - ts_len then
if line.[i] = 'T' && String.sub line i ts_len = ts then begin
Buffer.add_string buf keyword;
iter (i+ts_len)
end else begin
Buffer.add_char buf line.[i];
iter (i+1)
end
else
Buffer.add_string buf (String.sub line i (len-i))
in
iter 0;
output_string oc (Buffer.contents buf);
else
output_string oc line;
output_char oc '\n';
iter_line (i+1)
in
try
Printf.fprintf oc "(*\n\n WARNING: this file is automatically generated from: \n\t%s\n\n*)\n\n" full_template;
Printf.fprintf oc "# 1 \"%s\"\n" full_template;
iter_line 0
with End_of_file ->
close_out oc;
close_in ic
let depend dest_filename =
if Sys.file_exists dest_filename then begin
let dest_filename = String.sub dest_filename 0 (String.length dest_filename - 1) in
let basename = Filename.basename dest_filename in
let directory = Filename.dirname dest_filename in
let dirname = Filename.basename directory in
let up_directory = Filename.dirname directory in
let templates = Filename.concat up_directory "template" in
let template, keyword =
let keyword = ref "" in
let template = ref "" in
try
let len = String.length basename in
for i = 0 to len - 1 do
match basename.[i] with
'A' ..'Z' ->
template := "template" ^ (String.sub basename i (len-i));
keyword := String.sub basename 0 i;
!keyword.[0] <- Char.uppercase !keyword.[0];
raise Exit
| _ -> ()
done;
assert false
with Exit -> !template, !keyword
in
let full_template = Filename.concat templates template in
Printf.printf "%s: %s\n" dest_filename full_template
end
*)
type command =
Include of string * (Str.regexp * string) list
| Line of int * string
| Regexps of (Str.regexp * string) list
(*
| Define of string
| Ifdef of string
| Else
| Endif
*)
type env = {
regexps : (Str.regexp * string) list;
defines : string list;
ifs : bool list;
}
let new_env = { regexps = []; defines = []; ifs = [] }
open Genlex
let lexer = make_lexer [
"include"; "where"; "and" ;
"define"; "enddef";
"ifdef"; "else"; "endif";
"=" ; "#" ]
let rec parse_line = parser
[< 'Kwd "#"; key = parse_key >] -> key
and parse_key = parser
[< 'Kwd "include"; 'String filename; regexps = parse_where >] ->
Include (filename, regexps)
| [< 'Int line; 'String filename >] ->
Line (line, filename)
| [< 'Kwd "where"; 'String reg; 'Kwd "="; 'String templ;
regexps = parse_where >] ->
Regexps ( (Str.regexp reg, templ) :: regexps)
and parse_where = parser
[< 'Kwd "where"; 'String reg; 'Kwd "="; 'String templ;
regexps = parse_where >] ->
(Str.regexp reg, templ) :: regexps
| [< 'Kwd "and"; 'String reg; 'Kwd "="; 'String templ;
regexps = parse_where >] ->
(Str.regexp reg, templ) :: regexps
| [< >] -> []
let rec preprocess filename env =
let ic = open_in filename in
let line_warning line =
Printf.fprintf stdout "(*\n\n WARNING: this file is automatically generated from: \n\t%s\n\n*)\n\n" filename;
Printf.fprintf stdout "# %d \"%s\"\n" (line+1) filename;
in
let rec iter_line i env =
let line = input_line ic in
let line = iter_regexps line env.regexps in
let len = String.length line in
let env =
if len > 1 && line.[0] = '#' then begin
begin
let s = Stream.of_string line in
try
match parse_line (lexer s) with
Include (filename, regexps2) ->
preprocess filename
{ env with regexps = regexps2 @ env.regexps };
line_warning (i+1);
env
| Line (line, filename) ->
Printf.fprintf stdout "# %d \"%s\"\n" line filename;
env
| Regexps regexps2 ->
line_warning (i+1);
{ env with regexps = regexps2 @ env.regexps }
with
| e ->
Printf.fprintf stderr "Line [%s]:\n"
(String.escaped line);
Printf.fprintf stderr "Error %s in \"%s\" line %d (%d)\n"
(Printexc.to_string e) filename i (Stream.count s + 1);
exit 2
end;
end else begin
output_string stdout line;
output_char stdout '\n';
env
end
in
iter_line (i+1) env
and iter_regexps line regexps =
match regexps with
[] -> line
| (reg, templ) :: regexps ->
(* Printf.fprintf stderr "Checking replacement for %s\n" templ; *)
let line = Str.global_replace reg templ line in
iter_regexps line regexps
in
try
line_warning 0;
iter_line 0 env
with End_of_file ->
close_in ic
let pp filename = preprocess filename new_env
let add_depend filedep filename depends =
if not (List.mem filename !depends) then begin
Printf.fprintf stdout "%s: %s\n" filedep filename;
depends := filename :: !depends
end
let rec dep filedep filename env depends =
let ic = open_in filename in
let rec iter_line i env =
let line = input_line ic in
let line = iter_regexps line env.regexps in
let len = String.length line in
let env =
if len > 1 && line.[0] = '#' then begin
let s = Stream.of_string line in
try
match parse_line (lexer s) with
Include (filename, regexps2) ->
add_depend filedep filename depends;
dep filedep filename
{ env with regexps = regexps2 @ env.regexps } depends;
env
| Line (line, filename) ->
add_depend filedep filename depends;
env
| Regexps regexps2 ->
{ env with regexps = regexps2 @ env.regexps }
with
| e ->
Printf.fprintf stderr "Line [%s]:\n"
(String.escaped line);
Printf.fprintf stderr "Error \"%s\" line %d (%d)\n"
filename i (Stream.count s + 1);
exit 2
end
else env
in
iter_line (i+1) env
and iter_regexps line regexps =
match regexps with
[] -> line
| (reg, templ) :: regexps ->
let line = Str.global_replace reg templ line in
iter_regexps line regexps
in
try
ignore (iter_line 0 env)
with End_of_file ->
close_in ic
let depend filename =
if Sys.file_exists filename then
if Filename.check_suffix filename ".mlt" then
let filedep = (Filename.chop_suffix filename ".mlt") ^ ".ml" in
dep filedep filename new_env (ref [])
else begin
Printf.fprintf stderr "Don't know what to do with %s\n" filename;
exit 2
end
let _ =
Arg.parse
[
(* "-gen", Arg.String gen, " <filename> : generate filename"; *)
"-pp", Arg.String pp, " <filename> : preprocess filename";
] depend ""
|