123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125(* Js_of_ocaml compiler
* http://www.ocsigen.org/js_of_ocaml/
* Copyright (C) 2014 Hugo Heuzard
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, with linking exception;
* either version 2.1 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*)open!Stdlibletexpand_pathextsrealvirt=letreclooprealfilevirtfileacc=iftrySys.is_directoryrealfilewith_->falsethenletl=Array.to_list(Sys.readdirrealfile)|>List.sort~cmp:String.compareinList.fold_leftl~init:acc~f:(funaccs->loop(Filename.concatrealfiles)(Filename.concatvirtfiles)acc)elsetryletexmatch=tryletb=Filename.basenamerealfileinleti=String.rindexb'.'inlete=String.subb~pos:(i+1)~len:(String.lengthb-i-1)inList.meme~set:extswithNot_found->List.mem""~set:extsinifList.is_emptyexts||exmatchthen(virtfile,realfile)::accelseaccwithexc->warn"ignoring %s: %s@."realfile(Printexc.to_stringexc);accinlooprealvirt[]letlist_filesnamepaths=letname,virtname=matchString.lsplit2name~on:':'with|Some(src,dest)->ifString.lengthdest>0&¬(Char.equaldest.[0]'/')thenfailwith(Printf.sprintf"path '%s' for file '%s' must be absolute"destsrc);letvirtname=ifChar.equaldest.[String.lengthdest-1]'/'thendest^Filename.basenamesrcelsedestinsrc,virtname|None->(* by default, files are store in /static/ directory *)name,"/static/"^Filename.basenamenameinletname,exts(* extensions filter *)=matchString.lsplit2name~on:'='with|Some(name,exts)->name,String.split_char~sep:','exts|None->name,[]inletfile=matchFindlib.findpathsnamewith|None->failwith(Printf.sprintf"file '%s' not found"name)|Somefile->fileinexpand_pathextsfilevirtnameletfind_cmipathsbase=matchList.find_map[String.uncapitalize_asciibase^".cmi";String.capitalize_asciibase^".cmi"]~f:(funname->matchFs.find_in_pathpathsnamewith|Somecmi->Some(name,cmi)|None->None)with|Some(name,filename)->Some(Filename.concat"/static/cmis"name,filename)|None->Noneletinstr_of_name_contentprim~name~content=letopenCodeinletprim=matchprimwith|`create_file->"jsoo_create_file"|`create_file_extern->"jsoo_create_file_extern"inLet(Var.fresh(),Prim(Externprim,[Pc(NativeStringname);Pc(NativeStringcontent)]))letembed_file~name~filename=instr_of_name_content`create_file_extern~name~content:(Fs.read_filefilename)letinit()=Code.(Let(Var.fresh(),Prim(Extern"caml_fs_init",[])))letf~prim~cmis~files~paths=letcmi_files,missing_cmis=StringSet.fold(funs(acc,missing)->matchfind_cmipathsswith|Some(name,filename)->(name,Fs.read_filefilename)::acc,missing|None->acc,s::missing)cmis([],[])inifnot(List.is_emptymissing_cmis)then(warn"Some OCaml interface files were not found.@.";warn"Use [-I dir_of_cmis] option to bring them into scope@.";(* [`ocamlc -where`/expunge in.byte out.byte moduleA moduleB ... moduleN] *)List.itermissing_cmis~f:(funnm->warn" %s@."nm));letother_files=List.mapfiles~f:(funf->List.map(list_filesfpaths)~f:(fun(name,filename)->name,Fs.read_filefilename))|>List.concatinList.map(other_files@cmi_files)~f:(fun(name,content)->instr_of_name_contentprim~name~content)