prebuild.ml 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. open Json
  2. exception Prebuild_error of string
  3. type parsed_warning = {
  4. w_name : string;
  5. w_doc : string;
  6. w_parent : string option;
  7. w_generic : bool;
  8. }
  9. let as_string = function
  10. | JString s -> Some s
  11. | _ -> None
  12. let as_int = function
  13. | JInt i -> Some i
  14. | _ -> None
  15. let as_params = function
  16. | JArray s -> Some (List.map (function
  17. | JString s -> s
  18. | _ -> raise (Prebuild_error "parameter description should be a string")
  19. ) s)
  20. | _ -> None
  21. let as_platforms = function
  22. | JArray s -> Some (List.map (function
  23. | JString "cross" -> "Cross"
  24. | JString "js" -> "Js"
  25. | JString "lua" -> "Lua"
  26. | JString "neko" -> "Neko"
  27. | JString "flash" -> "Flash"
  28. | JString "php" -> "Php"
  29. | JString "cpp" -> "Cpp"
  30. | JString "cs" -> "Cs"
  31. | JString "java" -> "Java"
  32. | JString "python" -> "Python"
  33. | JString "hl" -> "Hl"
  34. | JString "eval" -> "Eval"
  35. | _ -> raise (Prebuild_error "invalid platform")
  36. ) s)
  37. | _ -> None
  38. let as_targets = function
  39. | JArray s -> Some (List.map (function
  40. | JString "TClass" -> "TClass"
  41. | JString "TClassField" -> "TClassField"
  42. | JString "TAbstract" -> "TAbstract"
  43. | JString "TAbstractField" -> "TAbstractField"
  44. | JString "TEnum" -> "TEnum"
  45. | JString "TTypedef" -> "TTypedef"
  46. | JString "TAnyField" -> "TAnyField"
  47. | JString "TExpr" -> "TExpr"
  48. | JString "TTypeParameter" -> "TTypeParameter"
  49. | _ -> raise (Prebuild_error "invalid metadata target")
  50. ) s)
  51. | _ -> None
  52. let as_bool = function
  53. | JBool b -> Some b
  54. | _ -> None
  55. let as_links = function
  56. | JArray s -> Some (List.map (function
  57. | JString s -> s
  58. | _ -> raise (Prebuild_error "link should be a string")
  59. ) s)
  60. | _ -> None
  61. let get_optional_field name map default fields =
  62. try
  63. let field = List.find (fun (n, _) -> n = name) fields in
  64. let value = map (snd field) in
  65. match value with
  66. | None -> raise (Prebuild_error ("field `" ^ name ^ "` has invalid data"))
  67. | Some v -> v
  68. with Not_found -> default
  69. let get_optional_field2 name map fields =
  70. try
  71. let field = List.find (fun (n, _) -> n = name) fields in
  72. let value = map (snd field) in
  73. match value with
  74. | None -> raise (Prebuild_error ("field `" ^ name ^ "` has invalid data"))
  75. | Some v -> Some v
  76. with Not_found ->
  77. None
  78. let get_field name map fields =
  79. let field = try List.find (fun (n, _) -> n = name) fields with Not_found -> raise (Prebuild_error ("no `" ^ name ^ "` field")) in
  80. let value = map (snd field) in
  81. match value with
  82. | None -> raise (Prebuild_error ("field `" ^ name ^ "` has invalid data"))
  83. | Some v -> v
  84. let parse_define json =
  85. let fields = match json with
  86. | JObject fl -> fl
  87. | _ -> raise (Prebuild_error "not an object")
  88. in
  89. (* name *) get_field "name" as_string fields,
  90. (* define *) get_field "define" as_string fields,
  91. (* doc *) get_field "doc" as_string fields,
  92. (* params *) get_optional_field "params" as_params [] fields,
  93. (* platforms *) get_optional_field "platforms" as_platforms [] fields,
  94. (* links *) get_optional_field "links" as_links [] fields
  95. let parse_meta json =
  96. let fields = match json with
  97. | JObject fl -> fl
  98. | _ -> raise (Prebuild_error "not an object")
  99. in
  100. (* name *) get_field "name" as_string fields,
  101. (* metadata *) get_field "metadata" as_string fields,
  102. (* doc *) get_field "doc" as_string fields,
  103. (* params *) get_optional_field "params" as_params [] fields,
  104. (* platforms *) get_optional_field "platforms" as_platforms [] fields,
  105. (* targets *) get_optional_field "targets" as_targets [] fields,
  106. (* internal *) get_optional_field "internal" as_bool false fields,
  107. (* links *) get_optional_field "links" as_links [] fields
  108. let parse_warning json =
  109. let fields = match json with
  110. | JObject fl -> fl
  111. | _ -> raise (Prebuild_error "not an object")
  112. in
  113. {
  114. w_name = get_field "name" as_string fields;
  115. w_doc = get_field "doc" as_string fields;
  116. w_parent = get_optional_field2 "parent" as_string fields;
  117. w_generic = get_optional_field "generic" as_bool false fields;
  118. }
  119. let parse_file_array path map =
  120. let file = open_in path in
  121. let data = Std.input_all file in
  122. let open Json.Reader in
  123. let lexbuf = Sedlexing.Utf8.from_string data in
  124. let json = read_json lexbuf in
  125. match json with
  126. | JArray s -> List.map map s
  127. | _ -> raise (Prebuild_error "not an array")
  128. let s_escape ?(hex=true) s =
  129. let b = Buffer.create (String.length s) in
  130. for i = 0 to (String.length s) - 1 do
  131. match s.[i] with
  132. | '\n' -> Buffer.add_string b "\\n"
  133. | '\t' -> Buffer.add_string b "\\t"
  134. | '\r' -> Buffer.add_string b "\\r"
  135. | '"' -> Buffer.add_string b "\\\""
  136. | '\\' -> Buffer.add_string b "\\\\"
  137. | c when int_of_char c < 32 && hex -> Buffer.add_string b (Printf.sprintf "\\x%.2X" (int_of_char c))
  138. | c -> Buffer.add_char b c
  139. done;
  140. Buffer.contents b
  141. let gen_platforms = function
  142. | [] -> []
  143. | platforms -> ["Platforms [" ^ (String.concat ";" platforms) ^ "]"]
  144. let gen_params = List.map (function param -> "HasParam \"" ^ param ^ "\"" )
  145. let gen_links = List.map (function link -> "Link \"" ^ link ^ "\"" )
  146. let gen_define_type defines =
  147. String.concat "\n" (List.map (function (name, _, _, _, _, _) -> "\t| " ^ name) defines)
  148. let gen_define_info defines =
  149. let define_str = List.map (function
  150. (name, define, doc, params, platforms, links) ->
  151. let platforms_str = gen_platforms platforms in
  152. let params_str = gen_params params in
  153. let links_str = gen_links links in
  154. let define = String.concat "_" (ExtString.String.nsplit define "-") in
  155. "\t| " ^ name ^ " -> \"" ^ define ^ "\",(" ^ (Printf.sprintf "%S" doc) ^ ",[" ^ (String.concat "; " (platforms_str @ params_str @ links_str)) ^ "])"
  156. ) defines in
  157. String.concat "\n" define_str
  158. let gen_meta_type metas =
  159. String.concat "\n" (List.map (function
  160. | ("InlineConstructorArgument", _, _, _, _, _, _, _) -> "\t| InlineConstructorArgument of int * int"
  161. | (name, _, _, _, _, _, _, _) -> "\t| " ^ name
  162. ) metas)
  163. let gen_meta_info metas =
  164. let meta_str = List.map (function
  165. (name, metadata, doc, params, platforms, targets, internal, links) ->
  166. let platforms_str = gen_platforms platforms in
  167. let params_str = gen_params params in
  168. let targets_str = (match targets with
  169. | [] -> []
  170. | targets -> ["UsedOn [" ^ (String.concat ";" targets) ^ "]"]
  171. ) in
  172. let internal_str = if internal then ["UsedInternally"] else [] in
  173. let links_str = gen_links links in
  174. let name = (match name with
  175. (* this is a hacky, I know *)
  176. | "InlineConstructorArgument" -> "InlineConstructorArgument _"
  177. | _ -> name
  178. ) in
  179. "\t| " ^ name ^ " -> \"" ^ metadata ^ "\",(" ^ (Printf.sprintf "%S" doc) ^ ",[" ^ (String.concat "; " (platforms_str @ params_str @ targets_str @ internal_str @ links_str)) ^ "])"
  180. ) metas in
  181. String.concat "\n" meta_str
  182. let gen_warning_type warnings =
  183. let warning_str = List.map (function
  184. w ->
  185. Printf.sprintf "\t| %s" w.w_name
  186. ) warnings in
  187. String.concat "\n" warning_str
  188. let gen_warning_parse warnings =
  189. let warning_str = List.map (function
  190. w ->
  191. Printf.sprintf "\t| \"%s\" -> %s" w.w_name w.w_name
  192. ) warnings in
  193. let warning_str = warning_str @ ["\t| _ -> raise Exit"] in
  194. String.concat "\n" warning_str
  195. let gen_warning_obj warnings =
  196. let warning_str = List.map (fun w ->
  197. let w_parent = match w.w_parent with
  198. | None -> if w.w_name = "WAll" then "None" else "Some WAll"
  199. | Some w -> Printf.sprintf "Some %s" w
  200. in
  201. Printf.sprintf "\t| %s -> {w_name = \"%s\"; w_doc = \"%s\"; w_generic = %b; w_parent = %s}" w.w_name w.w_name (s_escape w.w_doc) w.w_generic w_parent
  202. ) warnings in
  203. String.concat "\n" warning_str
  204. let autogen_header = "(* This file is auto-generated using prebuild from files in src-json *)
  205. (* Do not edit manually! *)
  206. "
  207. let define_header = autogen_header ^ "
  208. open Globals
  209. type define_parameter =
  210. | HasParam of string
  211. | Platforms of platform list
  212. | Link of string
  213. "
  214. let meta_header = autogen_header ^ "
  215. open Globals
  216. type meta_usage =
  217. | TClass
  218. | TClassField
  219. | TAbstract
  220. | TAbstractField
  221. | TEnum
  222. | TTypedef
  223. | TAnyField
  224. | TExpr
  225. | TTypeParameter
  226. | TVariable
  227. type meta_parameter =
  228. | HasParam of string
  229. | Platforms of platform list
  230. | UsedOn of meta_usage list
  231. | UsedInternally
  232. | Link of string
  233. "
  234. ;;
  235. match Array.to_list (Sys.argv) with
  236. | [_; "define"; define_path]->
  237. let defines = parse_file_array define_path parse_define in
  238. Printf.printf "%s" define_header;
  239. Printf.printf "type strict_defined =\n";
  240. Printf.printf "%s" (gen_define_type defines);
  241. Printf.printf "\n\t| Last\n\n"; (* must be last *)
  242. Printf.printf "let infos = function\n";
  243. Printf.printf "%s" (gen_define_info defines);
  244. Printf.printf "\n\t| Last -> die \"\" __LOC__\n"
  245. | [_; "meta"; meta_path]->
  246. let metas = parse_file_array meta_path parse_meta in
  247. Printf.printf "%s" meta_header;
  248. Printf.printf "type strict_meta =\n";
  249. Printf.printf "%s" (gen_meta_type metas);
  250. Printf.printf "\n\t| Last\n\t| Dollar of string\n\t| Custom of string\n\n";
  251. Printf.printf "let get_info = function\n";
  252. Printf.printf "%s" (gen_meta_info metas);
  253. Printf.printf "\n\t| Last -> die \"\" __LOC__\n\t| Dollar s -> \"$\" ^ s,(\"\",[])\n\t| Custom s -> s,(\"\",[])\n"
  254. | [_; "warning"; warning_path]->
  255. let warnings = parse_file_array warning_path parse_warning in
  256. print_endline "type warning =";
  257. print_endline (gen_warning_type warnings);
  258. print_endline "";
  259. print_endline "type warning_obj = {";
  260. print_endline "\tw_name : string;";
  261. print_endline "\tw_doc : string;";
  262. print_endline "\tw_generic : bool;";
  263. print_endline "\tw_parent : warning option;";
  264. print_endline "}";
  265. print_endline "";
  266. print_endline "let warning_obj = function";
  267. print_endline (gen_warning_obj warnings);
  268. print_endline "";
  269. print_endline "let from_string = function";
  270. print_endline (gen_warning_parse warnings);
  271. | _ :: "libparams" :: params ->
  272. Printf.printf "(%s)" (String.concat " " (List.map (fun s -> Printf.sprintf "\"%s\"" s) params))
  273. | [_ ;"version";add_revision;branch;sha] ->
  274. begin match add_revision with
  275. | "0" | "" ->
  276. print_endline "let version_extra = None"
  277. | _ ->
  278. Printf.printf "let version_extra = Some (\"git build %s\",\"%s\")" branch sha
  279. end
  280. | args ->
  281. print_endline (String.concat ", " args)