├── site-lib-src ├── dbm │ ├── interfaces.in │ └── META.in ├── num │ ├── interfaces.in │ └── META.in ├── str │ ├── interfaces.in │ └── META.in ├── bytes │ ├── interfaces.out │ ├── interfaces.in │ ├── META.in │ └── README ├── stdlib │ ├── interfaces.in │ └── META.in ├── unix │ ├── interfaces.in │ └── META.in ├── bigarray │ ├── interfaces.in │ └── META.in ├── dynlink │ ├── interfaces.in │ └── META.in ├── graphics │ ├── interfaces.in │ └── META.in ├── labltk │ ├── interfaces.in │ └── META.in ├── raw_spacetime │ ├── interfaces.in │ └── META.in ├── threads │ ├── interfaces.in │ └── META.in ├── ocamldoc │ └── META.in ├── num-top │ └── META.in ├── ocamlbuild │ └── META.in ├── compiler-libs │ └── META.in ├── camlp4.309 │ └── META.in └── camlp4.310 │ └── META.in ├── itest-aux ├── ppx.ml ├── remdir.ml ├── simple.ml ├── os_type.ml ├── simple_graphics.ml ├── simple_num.ml ├── simple_str.ml ├── simple_unix.ml ├── simple_camlp4.ml ├── simple_labltk.ml ├── Makefile ├── simple_bigarray.ml ├── simple_camltk.ml ├── simple_dbm.ml └── simple_threads.ml ├── findlib.conf.in ├── tools ├── file_exists ├── extract_args │ ├── Makefile │ └── extract_args.mll ├── collect_files ├── cmd_from_same_dir ├── patch ├── safe_camlp4 └── make-package-macosx ├── ocaml-stub ├── TODO ├── ocamlfind.install ├── README.md ├── src ├── bytes │ ├── META │ ├── README │ ├── bytes.ml │ └── Makefile ├── findlib-toolbox │ ├── selected.xpm │ ├── directory.xpm │ ├── unselected.xpm │ └── Makefile └── findlib │ ├── num_top.mli │ ├── num_top_printers.ml │ ├── num_top_printers.mli │ ├── findlib_config.mlp │ ├── fl_metatoken.ml │ ├── num_top.ml │ ├── META.in │ ├── fl_topo.mli │ ├── topfind_rd0.p │ ├── fl_meta.mll │ ├── fl_dynload.mli │ ├── topfind_rd1.p │ ├── fl_dynload.ml │ ├── test_parser.ml │ ├── fl_args.ml │ ├── fl_metascanner.mli │ ├── fl_lint.ml │ ├── fl_split.ml │ ├── topfind.mli │ ├── fl_package_base.mli │ ├── Makefile │ ├── fl_topo.ml │ ├── topfind.ml.in │ └── fl_metascanner.ml ├── REVISIONS ├── .gitignore ├── doc ├── DOCINFO ├── src │ ├── findlib_reference.sgml │ ├── findlib.dsl │ ├── findlib_ref.dsl │ ├── findlib_ref.sgml │ ├── findlib_sitelib.mod │ ├── findlib_mli.mod │ └── findlib_topfind.mod ├── config.xml ├── readme.dtd ├── Makefile ├── QUICKSTART.xml └── common.xml ├── release ├── LICENSE ├── opam ├── patches └── findlib-1.1-win32.diff ├── itest ├── Makefile.config.pattern ├── mini └── README ├── findlib.files ├── INSTALL ├── Makefile └── findlib-ppc.patch /site-lib-src/dbm/interfaces.in: -------------------------------------------------------------------------------- 1 | dbm.cma 2 | -------------------------------------------------------------------------------- /site-lib-src/num/interfaces.in: -------------------------------------------------------------------------------- 1 | nums.cma 2 | -------------------------------------------------------------------------------- /site-lib-src/str/interfaces.in: -------------------------------------------------------------------------------- 1 | str.cma 2 | -------------------------------------------------------------------------------- /itest-aux/ppx.ml: -------------------------------------------------------------------------------- 1 | Toploop.preprocess_phrase;; 2 | -------------------------------------------------------------------------------- /site-lib-src/bytes/interfaces.out: -------------------------------------------------------------------------------- 1 | Bytes 2 | 3 | -------------------------------------------------------------------------------- /site-lib-src/stdlib/interfaces.in: -------------------------------------------------------------------------------- 1 | stdlib.cma 2 | -------------------------------------------------------------------------------- /site-lib-src/unix/interfaces.in: -------------------------------------------------------------------------------- 1 | unix.cma 2 | -------------------------------------------------------------------------------- /itest-aux/remdir.ml: -------------------------------------------------------------------------------- 1 | #remove_directory ".";; 2 | 3 | -------------------------------------------------------------------------------- /itest-aux/simple.ml: -------------------------------------------------------------------------------- 1 | print_string "OK\n";; 2 | 3 | -------------------------------------------------------------------------------- /site-lib-src/bigarray/interfaces.in: -------------------------------------------------------------------------------- 1 | bigarray.cma 2 | -------------------------------------------------------------------------------- /site-lib-src/bytes/interfaces.in: -------------------------------------------------------------------------------- 1 | bytes.cmo 2 | 3 | -------------------------------------------------------------------------------- /site-lib-src/dynlink/interfaces.in: -------------------------------------------------------------------------------- 1 | dynlink.cma 2 | -------------------------------------------------------------------------------- /itest-aux/os_type.ml: -------------------------------------------------------------------------------- 1 | print_endline Sys.os_type 2 | ;; 3 | -------------------------------------------------------------------------------- /site-lib-src/graphics/interfaces.in: -------------------------------------------------------------------------------- 1 | graphics.cma 2 | 3 | -------------------------------------------------------------------------------- /site-lib-src/labltk/interfaces.in: -------------------------------------------------------------------------------- 1 | labltk/*.cma 2 | 3 | -------------------------------------------------------------------------------- /findlib.conf.in: -------------------------------------------------------------------------------- 1 | destdir="@SITELIB@" 2 | path="@FINDLIB_PATH@" 3 | -------------------------------------------------------------------------------- /site-lib-src/raw_spacetime/interfaces.in: -------------------------------------------------------------------------------- 1 | raw_spacetime_lib.cma 2 | -------------------------------------------------------------------------------- /site-lib-src/threads/interfaces.in: -------------------------------------------------------------------------------- 1 | vmthreads/threads.cma 2 | 3 | -------------------------------------------------------------------------------- /itest-aux/simple_graphics.ml: -------------------------------------------------------------------------------- 1 | Graphics.open_graph ""; 2 | 3 | print_string "OK\n";; 4 | 5 | -------------------------------------------------------------------------------- /itest-aux/simple_num.ml: -------------------------------------------------------------------------------- 1 | let _ = Num.num_of_int 5 in 2 | 3 | print_string "OK\n";; 4 | 5 | -------------------------------------------------------------------------------- /itest-aux/simple_str.ml: -------------------------------------------------------------------------------- 1 | let _ = Str.regexp ".*" in 2 | 3 | print_string "OK\n";; 4 | 5 | -------------------------------------------------------------------------------- /itest-aux/simple_unix.ml: -------------------------------------------------------------------------------- 1 | let _ = Unix.getpid() in 2 | 3 | print_string "OK\n";; 4 | 5 | -------------------------------------------------------------------------------- /tools/file_exists: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # Approximation of: test -e $1 4 | 5 | test -d "$1" -o -f "$1" 6 | -------------------------------------------------------------------------------- /itest-aux/simple_camlp4.ml: -------------------------------------------------------------------------------- 1 | (* This is revised syntax: *) 2 | 3 | value x = 1; 4 | 5 | print_endline "OK"; 6 | -------------------------------------------------------------------------------- /ocaml-stub: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | BINDIR=$(dirname "$(command -v ocamlc)") 4 | "$BINDIR/ocaml" -I "$OCAML_TOPLEVEL_PATH" "$@" 5 | -------------------------------------------------------------------------------- /itest-aux/simple_labltk.ml: -------------------------------------------------------------------------------- 1 | open Tk;; 2 | 3 | let _ = openTk() in 4 | update(); 5 | closeTk() 6 | ;; 7 | 8 | print_string "OK\n" 9 | ;; 10 | 11 | -------------------------------------------------------------------------------- /itest-aux/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | 3 | clean: 4 | rm -f simple simple.exe *.cmi *.cmo *.cma *.cmx *.o *.obj *.a *.lib 5 | rm -f err.out 6 | rm -f testdb* 7 | 8 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | Document archive(plugin) 2 | 3 | Suggestion (gasche): -show-command only outputs the constructed 4 | command, but does not run it. 5 | 6 | Get ready for -ppx 7 | -------------------------------------------------------------------------------- /itest-aux/simple_bigarray.ml: -------------------------------------------------------------------------------- 1 | open Bigarray.Array1;; 2 | let a = create Bigarray.int Bigarray.c_layout 4 in 3 | a.{0} <- 5 4 | ;; 5 | 6 | print_endline "OK";; 7 | 8 | -------------------------------------------------------------------------------- /itest-aux/simple_camltk.ml: -------------------------------------------------------------------------------- 1 | open Tk;; 2 | 3 | let top = openTk() in 4 | Frx_after.idle 5 | closeTk; 6 | mainLoop() 7 | ;; 8 | 9 | print_string "OK\n" 10 | ;; 11 | 12 | -------------------------------------------------------------------------------- /site-lib-src/bytes/META.in: -------------------------------------------------------------------------------- 1 | name="bytes" 2 | version="[distributed with OCaml 4.02 or above]" 3 | description="dummy backward-compatibility package for mutable strings" 4 | requires="" 5 | -------------------------------------------------------------------------------- /ocamlfind.install: -------------------------------------------------------------------------------- 1 | bin: [ 2 | "src/findlib/ocamlfind" {"ocamlfind"} 3 | "?src/findlib/ocamlfind_opt" {"ocamlfind"} 4 | "?tools/safe_camlp4" 5 | ] 6 | toplevel: ["src/findlib/topfind"] 7 | -------------------------------------------------------------------------------- /site-lib-src/ocamldoc/META.in: -------------------------------------------------------------------------------- 1 | # Specification for the "ocamldoc" library 2 | requires = "compiler-libs" 3 | version = "[distributed with Ocaml]" 4 | description = "ocamldoc plugin interface" 5 | directory= "^ocamldoc" 6 | -------------------------------------------------------------------------------- /itest-aux/simple_dbm.ml: -------------------------------------------------------------------------------- 1 | (try 2 | Sys.remove "itest-aux/testdb.db" 3 | with 4 | _ -> ()); 5 | 6 | let _ = 7 | Dbm.opendbm "itest-aux/testdb" [ Dbm.Dbm_rdwr; Dbm.Dbm_create ] 0o777 in 8 | 9 | print_string "OK\n";; 10 | 11 | -------------------------------------------------------------------------------- /site-lib-src/num-top/META.in: -------------------------------------------------------------------------------- 1 | # Specification for the "num-top" library add-on: 2 | requires = "num.core" 3 | version = "%%findlib_version%%" 4 | description = "Add-on for num inside toploops" 5 | archive(byte,toploop) = "num_top.cma" 6 | 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Findlib 2 | 3 | - [Project page](http://projects.camlcity.org/projects/findlib.html) 4 | with links to download tarballs and documentation 5 | 6 | - [README.xml with changelog](doc/README.xml) 7 | 8 | - [Installation](INSTALL) 9 | 10 | - [License](LICENSE) 11 | 12 | -------------------------------------------------------------------------------- /site-lib-src/stdlib/META.in: -------------------------------------------------------------------------------- 1 | # Specifications for the standard library: 2 | # (Only included because of findlib-browser) 3 | requires = "" 4 | description = "Standard library" 5 | version = "[distributed with Ocaml]" 6 | directory = "^" 7 | browse_interfaces = "%%interfaces%%" 8 | 9 | 10 | -------------------------------------------------------------------------------- /site-lib-src/ocamlbuild/META.in: -------------------------------------------------------------------------------- 1 | # Specification for the "ocamlbuild" library 2 | requires = "unix" 3 | version = "[distributed with Ocaml]" 4 | description = "ocamlbuild support library" 5 | directory= "^ocamlbuild" 6 | archive(byte) = "ocamlbuildlib.cma" 7 | archive(native) = "ocamlbuildlib.cmxa" 8 | 9 | -------------------------------------------------------------------------------- /tools/extract_args/Makefile: -------------------------------------------------------------------------------- 1 | all: extract_args 2 | 3 | extract_args.ml: extract_args.mll 4 | ocamllex -o extract_args.ml extract_args.mll 5 | 6 | extract_args: extract_args.ml 7 | ocamlc -o extract_args extract_args.ml 8 | 9 | clean: 10 | rm -f *.cmo *.cmi *.cma extract_args extract_args.ml 11 | -------------------------------------------------------------------------------- /site-lib-src/dynlink/META.in: -------------------------------------------------------------------------------- 1 | # Specifications for the "dynlink" library: 2 | requires = "" 3 | version = "[distributed with Ocaml]" 4 | description = "Dynamic loading and linking of object files" 5 | directory = "%%dynlink_dir%%" 6 | browse_interfaces = "%%interfaces%%" 7 | archive(byte) = "dynlink.cma" 8 | %%natdynlink%% 9 | -------------------------------------------------------------------------------- /src/bytes/META: -------------------------------------------------------------------------------- 1 | name="bytes" 2 | version="[OCaml strictly before 4.02]" 3 | description="backward-compatibility package for mutable strings" 4 | requires="" 5 | browse_interfaces = "String" 6 | archive(byte)="bytes.cma" 7 | archive(native)="bytes.cmxa" 8 | plugin(byte)="bytes.cma" 9 | plugin(native)="bytes.cmxs" 10 | -------------------------------------------------------------------------------- /site-lib-src/labltk/META.in: -------------------------------------------------------------------------------- 1 | # Specifications for the "labltk" library: 2 | requires = "" 3 | version = "[distributed with Ocaml]" 4 | description = "The Tk windowing toolkit" 5 | directory = "+labltk" 6 | browse_interfaces = "%%interfaces%%" 7 | archive(byte) = "labltk.cma" 8 | archive(native) = "labltk.cmxa" 9 | linkopts = "" 10 | 11 | -------------------------------------------------------------------------------- /src/findlib-toolbox/selected.xpm: -------------------------------------------------------------------------------- 1 | #define selected_width 16 2 | #define selected_height 16 3 | static unsigned char selected_bits[] = { 4 | 0x55, 0x55, 0x00, 0x80, 0x01, 0x1c, 0x00, 0x82, 0x01, 0x02, 0x00, 0x81, 5 | 0x01, 0x01, 0x80, 0x80, 0x81, 0x00, 0x98, 0x80, 0xa1, 0x00, 0xa0, 0x80, 6 | 0xc1, 0x00, 0xc0, 0x80, 0x01, 0x00, 0xaa, 0xaa}; 7 | -------------------------------------------------------------------------------- /src/findlib-toolbox/directory.xpm: -------------------------------------------------------------------------------- 1 | #define directory_width 16 2 | #define directory_height 16 3 | static unsigned char directory_bits[] = { 4 | 0xf8, 0x01, 0xfc, 0x03, 0xfe, 0x7f, 0x01, 0x80, 0x55, 0xd5, 0x01, 0x80, 5 | 0xab, 0xaa, 0x01, 0x80, 0x55, 0xd5, 0x01, 0x80, 0xab, 0xaa, 0x01, 0x80, 6 | 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 7 | -------------------------------------------------------------------------------- /src/findlib-toolbox/unselected.xpm: -------------------------------------------------------------------------------- 1 | #define unselected_width 16 2 | #define unselected_height 16 3 | static unsigned char unselected_bits[] = { 4 | 0x55, 0x55, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 5 | 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 6 | 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0xaa, 0xaa}; 7 | -------------------------------------------------------------------------------- /itest-aux/simple_threads.ml: -------------------------------------------------------------------------------- 1 | let tl = 2 | List.map 3 | (fun _ -> 4 | Thread.create 5 | (fun () -> 6 | for i = 1 to 1000 do 7 | let _ = 1+1 in () 8 | done) 9 | ()) 10 | [ (); (); (); (); () ] 11 | in 12 | 13 | List.iter Thread.join tl 14 | ;; 15 | 16 | print_string "OK\n";; 17 | 18 | -------------------------------------------------------------------------------- /site-lib-src/dbm/META.in: -------------------------------------------------------------------------------- 1 | # Specification for the "dbm" library 2 | requires = "" 3 | version = "[distributed with Ocaml]" 4 | description = "Access to NDBM databases" 5 | directory = "^" 6 | browse_interfaces = "%%interfaces%%" 7 | archive(byte) = "dbm.cma" 8 | archive(native) = "dbm.cmxa" 9 | plugin(byte) = "dbm.cma" 10 | plugin(native) = "dbm.cmxs" 11 | -------------------------------------------------------------------------------- /tools/collect_files: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # 3 | # $Id$ 4 | # ---------------------------------------------------------------------- 5 | # 6 | # usage: collect_files file ... 7 | # 8 | # Prints the names of the files passed as arguments which actually 9 | # exist and are regular files. 10 | 11 | for x in "$@"; do 12 | if [ -f "$x" ]; then 13 | echo "$x" 14 | fi 15 | done 16 | 17 | -------------------------------------------------------------------------------- /site-lib-src/graphics/META.in: -------------------------------------------------------------------------------- 1 | # Specifications for the "graphics" library: 2 | requires = "" 3 | version = "[distributed with Ocaml]" 4 | description = "Portable drawing primitives" 5 | directory = "^" 6 | browse_interfaces = "%%interfaces%%" 7 | archive(byte) = "graphics.cma" 8 | archive(native) = "graphics.cmxa" 9 | plugin(byte) = "graphics.cma" 10 | plugin(native) = "graphics.cmxs" 11 | -------------------------------------------------------------------------------- /site-lib-src/str/META.in: -------------------------------------------------------------------------------- 1 | # Specifications for the "str" library: 2 | requires = "" 3 | description = "Regular expressions and string processing" 4 | version = "[distributed with Ocaml]" 5 | directory = "%%str_dir%%" 6 | browse_interfaces = "%%interfaces%%" 7 | archive(byte) = "str.cma" 8 | archive(native) = "str.cmxa" 9 | plugin(byte) = "str.cma" 10 | plugin(native) = "str.cmxs" 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/bytes/README: -------------------------------------------------------------------------------- 1 | backward-compatibility package for the standard Bytes module of 4.02 2 | 3 | Starting from 4.02, the OCaml standard library splits String into two 4 | modules, String for now-immutable strings and Bytes for mutable byte 5 | sequences. This package exports a Bytes package mimicking the new 6 | interface to older OCaml version, letting you write code using Bytes 7 | that works with OCaml < 4.02. 8 | -------------------------------------------------------------------------------- /site-lib-src/bigarray/META.in: -------------------------------------------------------------------------------- 1 | # Specifications for the "bigarray" library: 2 | requires = "unix" 3 | version = "[distributed with Ocaml]" 4 | description = "Large statically allocated arrays" 5 | directory = "^" 6 | browse_interfaces = "%%interfaces%%" 7 | archive(byte) = "bigarray.cma" 8 | archive(native) = "bigarray.cmxa" 9 | plugin(byte) = "bigarray.cma" 10 | plugin(native) = "bigarray.cmxs" 11 | linkopts = "" 12 | -------------------------------------------------------------------------------- /REVISIONS: -------------------------------------------------------------------------------- 1 | The following table shows which Subversion revision of the 2 | repository corresponds with which released version of 3 | findlib. 4 | 5 | Released versions up to 0.9 are checked in into CVS, and 6 | not Subversion. 7 | 8 | Released version = Subversion revision 9 | ---------------------------------------------------------------------- 10 | 1.0 54 11 | 1.0.1 57 12 | 1.0.2 63 13 | 1.0.3 69 14 | 1.0.4 72 15 | -------------------------------------------------------------------------------- /site-lib-src/raw_spacetime/META.in: -------------------------------------------------------------------------------- 1 | # Specifications for the "spacetime" library: 2 | requires = "" 3 | description = "Support library for the spacetime profiler" 4 | version = "[distributed with Ocaml]" 5 | directory = "^" 6 | browse_interfaces = "%%interfaces%%" 7 | archive(byte) = "raw_spacetime_lib.cma" 8 | archive(native) = "raw_spacetime_lib.cmxa" 9 | plugin(byte) = "raw_spacetime_lib.cma" 10 | plugin(native) = "raw_spacetime_lib.cmxs" 11 | 12 | -------------------------------------------------------------------------------- /src/findlib/num_top.mli: -------------------------------------------------------------------------------- 1 | (* $Id$ 2 | * ---------------------------------------------------------------------- 3 | * 4 | *) 5 | 6 | (** 7 | Load this module in the toplevel to install printers for the following types 8 | defined in the "num" library: 9 | - Nat.nat 10 | - Big_int.big_int 11 | - Ratio.ratio 12 | - Num.num 13 | 14 | No functions exported. 15 | 16 | Copyright (C) 2003 Stefano Zacchiroli 17 | *) 18 | 19 | -------------------------------------------------------------------------------- /site-lib-src/unix/META.in: -------------------------------------------------------------------------------- 1 | # Specifications for the "unix" library: 2 | requires = "" 3 | description = "Unix system calls" 4 | version = "[distributed with Ocaml]" 5 | directory = "%%unix_dir%%" 6 | browse_interfaces = "%%interfaces%%" 7 | archive(byte) = "unix.cma" 8 | archive(native) = "unix.cmxa" 9 | archive(byte,mt_vm) = "vmthreads/unix.cma" 10 | plugin(byte) = "unix.cma" 11 | plugin(native) = "unix.cmxs" 12 | plugin(byte,mt_vm) = "vmthreads/unix.cma" 13 | 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.cmi 3 | *.cmo 4 | *.cma 5 | *.cmx 6 | *.o 7 | *.cmxa 8 | *.cmxs 9 | *.a 10 | *.so 11 | META 12 | 13 | Makefile.config 14 | Makefile.packages 15 | findlib.conf 16 | ocargs.log 17 | src/findlib/depend 18 | src/findlib/findlib_config.ml 19 | src/findlib/fl_meta.ml 20 | src/findlib/ocaml_args.ml 21 | src/findlib/ocamlfind 22 | src/findlib/topfind 23 | src/findlib/topfind.ml 24 | tools/extract_args/extract_args 25 | tools/extract_args/extract_args.ml 26 | -------------------------------------------------------------------------------- /site-lib-src/bytes/README: -------------------------------------------------------------------------------- 1 | dummy forward-compatibility package for the standard Bytes module 2 | 3 | Starting from 4.02, the OCaml standard library splits String into two 4 | modules, String for now-immutable strings and Bytes for mutable byte 5 | sequences. A 'bytes' package is made available to older OCaml version 6 | that wish to use a Bytes module. This dummy 'bytes' package, intended 7 | to be installed on 4.02 and above, makes user-code depending on 8 | 'bytes' forward-compatible. 9 | -------------------------------------------------------------------------------- /site-lib-src/num/META.in: -------------------------------------------------------------------------------- 1 | # Specification for the "num" library: 2 | requires = "num.core" 3 | requires(toploop) = "num.core,num-top" 4 | version = "[distributed with Ocaml]" 5 | description = "Arbitrary-precision rational arithmetic" 6 | package "core" ( 7 | directory = "^" 8 | version = "[internal]" 9 | browse_interfaces = "%%interfaces%%" 10 | archive(byte) = "nums.cma" 11 | archive(native) = "nums.cmxa" 12 | plugin(byte) = "nums.cma" 13 | plugin(native) = "nums.cmxs" 14 | ) 15 | -------------------------------------------------------------------------------- /src/findlib/num_top_printers.ml: -------------------------------------------------------------------------------- 1 | (* $Id$ 2 | * ---------------------------------------------------------------------- 3 | * 4 | *) 5 | 6 | let nat_printer fmt v = 7 | Format.fprintf fmt "" (Nat.string_of_nat v) 8 | 9 | let big_int_printer fmt v = 10 | Format.fprintf fmt "" (Big_int.string_of_big_int v) 11 | 12 | let ratio_printer fmt v = 13 | Format.fprintf fmt "" (Ratio.string_of_ratio v) 14 | 15 | let num_printer fmt v = 16 | Format.fprintf fmt "" (Num.string_of_num v) 17 | 18 | -------------------------------------------------------------------------------- /doc/DOCINFO: -------------------------------------------------------------------------------- 1 | To build the html and manual pages from the SGML sources, you need the 2 | following tools: 3 | 4 | - The DocBook DTD 5 | (http://www.davenport.com) 6 | - James Clark's SGML tools (jade, sx suffice) 7 | (http://www.jclark.com) 8 | - Normal Walsh's DSSSL stylesheets to make the HTML pages 9 | (http://nwalsh.com/docbook/dsssl) 10 | - My db2man tool to make the manual pages 11 | (http://www.ocaml-programming.de/packages) 12 | 13 | The latter also requires Christian Lindig's XML parser 14 | (//http://www.cs.tu-bs.de/softech/people/lindig/software/tony.html). 15 | 16 | -------------------------------------------------------------------------------- /doc/src/findlib_reference.sgml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | ]> 9 | 10 | 11 | Reference 12 | &findlibocamlfind; 13 | &findlibmeta; 14 | &findlibconf; 15 | &findlibsitelib; 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/findlib/num_top_printers.mli: -------------------------------------------------------------------------------- 1 | (* $Id$ 2 | * ---------------------------------------------------------------------- 3 | * 4 | *) 5 | 6 | (** 7 | Printers for types defined in the "num" library. Meant to be used as printers 8 | in the ocaml toplevel. See num_top.mli. 9 | 10 | Copyright (C) 2003 Stefano Zacchiroli 11 | 12 | Released under the same terms as findlib. 13 | *) 14 | 15 | val nat_printer : Format.formatter -> Nat.nat -> unit 16 | val big_int_printer : Format.formatter -> Big_int.big_int -> unit 17 | val ratio_printer : Format.formatter -> Ratio.ratio -> unit 18 | val num_printer: Format.formatter -> Num.num -> unit 19 | 20 | -------------------------------------------------------------------------------- /doc/src/findlib.dsl: -------------------------------------------------------------------------------- 1 | 3 | ]> 4 | 5 | 6 | 7 | 8 | 9 | (define %footnotes-at-end% 10 | ;; Should footnotes appear at the end of HTML pages? 11 | #t) 12 | 13 | (define %html-ext% 14 | ;; Default extension for HTML output files 15 | ".html") 16 | 17 | (define %root-filename% 18 | ;; Name for the root HTML document 19 | "index") 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /doc/src/findlib_ref.dsl: -------------------------------------------------------------------------------- 1 | 3 | ]> 4 | 5 | 6 | 7 | 8 | 9 | (define %footnotes-at-end% 10 | ;; Should footnotes appear at the end of HTML pages? 11 | #t) 12 | 13 | (define %html-ext% 14 | ;; Default extension for HTML output files 15 | ".html") 16 | 17 | (define %root-filename% 18 | ;; Name for the root HTML document 19 | "index") 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /doc/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | %readme:html:previous; 11 | %readme:html:up; 12 | %readme:html:next; 13 | '> 14 | 15 | "> 17 | 18 | %bar;"> 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/findlib/findlib_config.mlp: -------------------------------------------------------------------------------- 1 | (* $Id$ 2 | * ---------------------------------------------------------------------- 3 | * 4 | *) 5 | 6 | let config_file = "@CONFIGFILE@";; 7 | 8 | let ocaml_stdlib = "@STDLIB@";; 9 | 10 | let ocaml_ldconf = Filename.concat ocaml_stdlib "ld.conf";; 11 | 12 | let ocaml_has_autolinking = @AUTOLINK@;; 13 | 14 | let libexec_name = "stublibs";; 15 | 16 | let system = "@SYSTEM@";; 17 | (* - "mingw", "mingw64", "win32", "cygwin", "linux_elf", ... *) 18 | 19 | let dll_suffix = 20 | match Sys.os_type with 21 | | "Unix" | "BeOS" -> ".so" 22 | | "Win32" | "Cygwin" -> ".dll" 23 | | "MacOS" -> "" (* don't know *) 24 | | _ -> failwith "Unknown Sys.os_type" 25 | ;; 26 | -------------------------------------------------------------------------------- /tools/cmd_from_same_dir: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # Check whether ocamlc and ocamlc.opt are installed in the same 4 | # directory (or whatever command names are passed as $1). 5 | 6 | get_path () { 7 | IFS=":" 8 | for d in $PATH; do 9 | if test -x "$d/$1"; then 10 | IFS="$oldifs" 11 | echo "$d/$1" 12 | return 13 | fi 14 | done 15 | IFS="$oldifs" 16 | #--- The following is not portable enough: 17 | # if test -x `type -p ls`; then 18 | # # type -p works! 19 | # type -p $1 20 | # else 21 | # # use 'which' instead 22 | # p=`which $1` 23 | # test -x "$p" && echo $p 24 | # fi 25 | } 26 | 27 | p1="$(get_path "$1").opt" 28 | p2="$(get_path "$1.opt")" 29 | 30 | [ "X$p1" = "X$p2" ] 31 | -------------------------------------------------------------------------------- /doc/readme.dtd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 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 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/findlib/fl_metatoken.ml: -------------------------------------------------------------------------------- 1 | (* $Id$ 2 | * ---------------------------------------------------------------------- 3 | * 4 | *) 5 | 6 | 7 | type token = 8 | Name of string 9 | | LParen 10 | | RParen 11 | | Equal 12 | | PlusEqual 13 | | Minus 14 | | Comma 15 | | String of string 16 | | Space 17 | | Newline 18 | | Eof 19 | | Unknown 20 | ;; 21 | 22 | 23 | let name_tok = function 24 | | Name s -> Some s 25 | | _ -> None 26 | 27 | let string_tok = function 28 | | String s -> Some s 29 | | _ -> None 30 | 31 | let const_tok constant tok = 32 | match constant with 33 | | Name _ | String _ -> failwith "expect: only for constant tokens" 34 | | LParen | RParen | Equal | PlusEqual | Minus 35 | | Comma | Space | Newline | Eof | Unknown -> 36 | if constant = tok then Some () 37 | else None 38 | -------------------------------------------------------------------------------- /src/bytes/bytes.ml: -------------------------------------------------------------------------------- 1 | include String 2 | 3 | let empty = "" 4 | let of_string = copy 5 | let to_string = copy 6 | 7 | let sub_string = sub 8 | let blit_string = blit 9 | 10 | let unsafe_to_string : t -> string = fun s -> s 11 | let unsafe_of_string : string -> t = fun s -> s 12 | 13 | let extend s left right = 14 | (* length of the final string *) 15 | let dstlen = left + length s + right in 16 | (* length of the included portion of the input string *) 17 | let srclen = min 0 left + length s + min 0 right in 18 | let t = create dstlen in 19 | if srclen > 0 then blit s (max 0 (-left)) t (max 0 left) srclen; 20 | t 21 | 22 | let init len f = 23 | let s = create len in 24 | for i = 0 to len - 1 do 25 | set s i (f i); 26 | done; 27 | s 28 | 29 | let mapi f input = 30 | let output = create (length input) in 31 | for i = 0 to length input - 1 do 32 | output.[i] <- f i input.[i]; 33 | done; 34 | output 35 | 36 | let cat = (^) 37 | -------------------------------------------------------------------------------- /tools/patch: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # Usage: patch @VARIABLE@ value [extra-args-for-cygpath] 4 | # Environment variable USE_CYGPATH is honoured. 5 | 6 | varname="$1" 7 | varvalue="$2" 8 | 9 | if [ "${USE_CYGPATH}" = "1" ]; then 10 | #varvalue="$(echo "$varvalue" | sed -e 's;/;\\;g')" 11 | varvalue="$(cygpath -w -l $3 "$varvalue")" 12 | varvalue="$(echo "$varvalue" | sed -e 's;\\;\\\\\\\\;g')" 13 | # e.g. c:\file is transformed to c:\\\\file 14 | else 15 | case `uname` in 16 | MINGW*) 17 | varvalue="$(echo "$varvalue" | sed -e 's;\\;\\\\\\\\;g')" 18 | # Convert the first letter drive to DOS style (naive). 19 | # This is necessary because OCaml uses DOS paths even if 20 | # run under MSYS. 21 | varvalue="$(echo "$varvalue" | sed -e 's;^/\([a-z]\)/;\1:/;g')" 22 | ;; 23 | esac 24 | fi 25 | 26 | sed -e 's;'"$varname"';'"$varvalue"';g' 27 | # e.g. c:\\\\file is parsed by sed as c:\\file which is correct for the 28 | # ocaml string 29 | -------------------------------------------------------------------------------- /src/findlib/num_top.ml: -------------------------------------------------------------------------------- 1 | (* $Id$ 2 | * ---------------------------------------------------------------------- 3 | * 4 | *) 5 | 6 | let print_outcome = false 7 | let error_fmt = Format.err_formatter 8 | 9 | let printers = [ 10 | "Num_top_printers.nat_printer"; 11 | "Num_top_printers.big_int_printer"; 12 | "Num_top_printers.ratio_printer"; 13 | "Num_top_printers.num_printer"; 14 | ] 15 | 16 | let eval_phrase s = 17 | let lexbuf = Lexing.from_string s in 18 | let phrase = !Toploop.parse_toplevel_phrase lexbuf in 19 | Toploop.execute_phrase print_outcome error_fmt phrase 20 | 21 | let install_all () = 22 | List.fold_left 23 | (fun outcome phrase -> 24 | outcome && eval_phrase (Printf.sprintf "#install_printer %s;;" phrase)) 25 | true printers 26 | 27 | let _ = 28 | if not (install_all ()) then begin 29 | Format.fprintf error_fmt 30 | "Something weird appened while installing Num library printers"; 31 | Format.pp_print_flush error_fmt () 32 | end 33 | -------------------------------------------------------------------------------- /release: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | set -e 4 | 5 | version=`./configure -version 2>/dev/null` 6 | destdir="findlib-$version" 7 | 8 | mkdir -p packages 9 | rm -rf "packages/$destdir" 10 | makepkg -spec findlib.files -intree . -outtree "packages/$destdir" 11 | (cd packages; tar czf "$destdir.tar.gz" "$destdir") 12 | echo "Wrote packages/$destdir.tar.gz" 13 | 14 | # Checking git: 15 | 16 | master="$(git branch | grep '* master')" 17 | if [ -z "$master" ]; then 18 | echo "Error: not on master branch" 19 | exit 1 20 | fi 21 | 22 | status="$(git status -uno -s)" 23 | 24 | if [ -n "$status" ]; then 25 | echo "Error: git status not clean" 26 | exit 1 27 | else 28 | printf "Tag revision (y/n)? " 29 | read answer 30 | case "$answer" in 31 | y|Y|yes|YES) 32 | git tag -a -m "findlib-$version" findlib-$version 33 | git push --tags origin master 34 | echo "New tag: findlib-$version" 35 | ;; 36 | *) 37 | echo "Nothing tagged." 38 | ;; 39 | esac 40 | fi 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 1999 by Gerd Stolpmann 2 | 3 | The package "findlib" is copyright by Gerd Stolpmann. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this document and the "findlib" software (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included 14 | in all copies or substantial portions of the Software. 15 | 16 | The Software is provided ``as is'', without warranty of any kind, express 17 | or implied, including but not limited to the warranties of 18 | merchantability, fitness for a particular purpose and noninfringement. 19 | In no event shall Gerd Stolpmann be liable for any claim, damages or 20 | other liability, whether in an action of contract, tort or otherwise, 21 | arising from, out of or in connection with the Software or the use or 22 | other dealings in the software. 23 | -------------------------------------------------------------------------------- /src/findlib/META.in: -------------------------------------------------------------------------------- 1 | # specifications for "findlib": 2 | description = "Package manager" 3 | requires = "findlib.internal" 4 | requires(toploop) += "findlib.top" 5 | requires(create_toploop) += "findlib.top" 6 | version = "@VERSION@" 7 | 8 | package "internal" ( 9 | version = "@VERSION@" 10 | description = "Package manager" 11 | requires = "@REQUIRES@" 12 | archive(byte) = "findlib.cma" 13 | archive(native) = "findlib.cmxa" 14 | plugin(byte) = "findlib.cma" 15 | plugin(native) = "findlib.cmxs" 16 | ) 17 | 18 | package "dynload" ( 19 | version = "@VERSION@" 20 | description = "Package manager dynamic loader" 21 | requires = "findlib dynlink" 22 | archive(byte) = "findlib_dynload.cma" 23 | archive(native) = "findlib_dynload.cmxa" 24 | #Even if it strange and discouraged to dynload this package 25 | plugin(byte) = "findlib_dynload.cma" 26 | plugin(native) = "findlib_dynload.cmxs" 27 | linkopts = "-linkall" 28 | ) 29 | 30 | package "top" ( 31 | version = "@VERSION@" 32 | description = "Package manager toplevel support" 33 | requires = "findlib.internal" 34 | archive(byte) = "findlib_top.cma" 35 | archive(native) = "findlib_top.cmxa" 36 | ) 37 | -------------------------------------------------------------------------------- /site-lib-src/threads/META.in: -------------------------------------------------------------------------------- 1 | # Specifications for the "threads" library: 2 | version = "[distributed with Ocaml]" 3 | description = "Multi-threading" 4 | requires(mt,mt_vm) = "threads.vm" 5 | requires(mt,mt_posix) = "threads.posix" 6 | directory = "^" 7 | type_of_threads = "%%type_of_threads%%" 8 | 9 | browse_interfaces = "%%interfaces%%" 10 | 11 | warning(-mt) = "Linking problems may arise because of the missing -thread or -vmthread switch" 12 | warning(-mt_vm,-mt_posix) = "Linking problems may arise because of the missing -thread or -vmthread switch" 13 | 14 | package "vm" ( 15 | # --- Bytecode-only threads: 16 | requires = "unix" 17 | directory = "+vmthreads" 18 | exists_if = "threads.cma" 19 | archive(byte,mt,mt_vm) = "threads.cma" 20 | version = "[internal]" 21 | ) 22 | 23 | package "posix" ( 24 | # --- POSIX-threads: 25 | requires = "unix" 26 | directory = "+threads" 27 | exists_if = "threads.cma" 28 | archive(byte,mt,mt_posix) = "threads.cma" 29 | archive(native,mt,mt_posix) = "threads.cmxa" 30 | version = "[internal]" 31 | ) 32 | 33 | package "none" ( 34 | error = "threading is not supported on this platform" 35 | version = "[internal]" 36 | ) 37 | 38 | -------------------------------------------------------------------------------- /src/findlib/fl_topo.mli: -------------------------------------------------------------------------------- 1 | (* $Id$ 2 | * ---------------------------------------------------------------------- 3 | * 4 | *) 5 | 6 | (* The type topo.t is a partially ordered relation. You can add an element 7 | * by giving all descendents ... 8 | *) 9 | 10 | module type IdentifiedType = 11 | sig 12 | type t 13 | type id_t 14 | val id : t -> id_t 15 | end 16 | 17 | exception Inconsistent_ordering 18 | 19 | module type S = 20 | sig 21 | type key 22 | type el_t 23 | type t 24 | val create : unit -> t 25 | val add : t -> el_t -> unit 26 | val let_le : t -> key -> key -> unit 27 | val find : t -> key -> el_t 28 | val le_than : t -> key -> key -> bool 29 | val key : el_t -> key 30 | val iter_up : (el_t -> unit) -> t -> unit 31 | val iter_down : (el_t -> unit) -> t -> unit 32 | val iter_up_at : (el_t -> unit) -> t -> key list -> unit 33 | val iter_down_at : (el_t -> unit) -> t -> key list -> unit 34 | val clear : t -> unit 35 | val replace : t -> key -> el_t -> unit 36 | val delete : t -> key -> unit 37 | val copy : t -> t 38 | end 39 | 40 | module Make(H: IdentifiedType): 41 | (S with type el_t = H.t 42 | and type key = H.id_t) 43 | -------------------------------------------------------------------------------- /src/bytes/Makefile: -------------------------------------------------------------------------------- 1 | BYTE_FILES=bytes.cmi bytes.cma 2 | NATIVE_FILES=bytes.cmx bytes$(LIB_SUFFIX) bytes.cmxa 3 | NATIVE_FILES_DYNLINK=bytes.cmxs 4 | 5 | TOP=../.. 6 | include $(TOP)/Makefile.config 7 | 8 | OCAMLC = ocamlc 9 | OCAMLOPT = ocamlopt $(OCAMLOPT_G) 10 | 11 | build: all opt 12 | 13 | all: 14 | $(OCAMLC) -a -o bytes.cma bytes.ml 15 | 16 | opt: 17 | $(OCAMLOPT) -a -o bytes.cmxa bytes.ml 18 | if [ $(HAVE_NATDYNLINK) -gt 0 ]; then \ 19 | $(OCAMLOPT) -shared -o bytes.cmxs bytes.cmxa; \ 20 | fi 21 | 22 | install: all 23 | $(INSTALLDIR) "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/bytes" 24 | $(INSTALLFILE) META $(BYTE_FILES) "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/bytes/" 25 | for f in $(NATIVE_FILES) $(NATIVE_FILES_DYNLINK); do if [ -f "$$f" ]; then $(INSTALLFILE) $$f "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/bytes/"; fi; done 26 | 27 | uninstall: 28 | rm -rf "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/bytes" 29 | 30 | # install-self and uninstall-self use ocamlfind already. This is a bit 31 | # questionable here. 32 | 33 | install-self: all 34 | ocamlfind install bytes META $(BYTE_FILES) -optional $(NATIVE_FILES) $(NATIVE_FILES_DYNLINK) 35 | 36 | uninstall-self: 37 | ocamlfind remove bytes 38 | 39 | clean: 40 | ocamlbuild -clean 41 | -------------------------------------------------------------------------------- /tools/safe_camlp4: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # Call camlp4 with fallback method if dynamic loading is not supported 4 | 5 | dl_string="dynamic loading not supported on this platform" 6 | fn_string="The external function .* is not available" 7 | 8 | tmp_stderr="tmp.safe_camlp4_stderr.$$" 9 | tmp_camlp4="tmp.safe_camlp4_camlp4.$$" 10 | 11 | trap "rm -f $tmp_stderr $tmp_camlp4" 0 12 | 13 | print_stderr=1 14 | code=0 15 | 16 | camlp4 "$@" 2>$tmp_stderr || { 17 | code=$? 18 | grep "$dl_string" $tmp_stderr >/dev/null 2>&1; t1=$? 19 | grep "$fn_string" $tmp_stderr >/dev/null 2>&1; t2=$? 20 | if [ $t1 -eq 0 -o $t2 -eq 0 ]; then 21 | # Fallback: 22 | print_stderr=0 23 | cp4_mods="" 24 | cp4_args="" 25 | i=0 26 | for arg in "$@"; do 27 | if [ $i -gt 0 ]; then 28 | cp4_mods="$cp4_mods -I $arg" 29 | cp4_args="$cp4_args -I $arg" 30 | i=0 31 | else 32 | case "$arg" in 33 | *.cma|*.cmo) 34 | cp4_mods="$cp4_mods $arg" ;; 35 | -I) 36 | i=1 ;; 37 | *) 38 | cp4_args="$cp4_args $arg" ;; 39 | esac 40 | fi 41 | done 42 | mkcamlp4 -o $tmp_camlp4 $cp4_mods || exit 43 | ./$tmp_camlp4 $cp4_args || exit 44 | code=0 45 | fi 46 | } 47 | 48 | if [ $print_stderr -gt 0 ]; then 49 | cat $tmp_stderr >&2 50 | fi 51 | 52 | exit $code 53 | -------------------------------------------------------------------------------- /opam: -------------------------------------------------------------------------------- 1 | opam-version: "2.0" 2 | name: "ocamlfind" 3 | version: "1.9.6.git" 4 | license: "MIT" 5 | synopsis: "A library manager for OCaml" 6 | maintainer: "Thomas Gazagnaire " 7 | authors: "Gerd Stolpmann " 8 | homepage: "http://projects.camlcity.org/projects/findlib.html" 9 | bug-reports: "https://github.com/ocaml/ocamlfind/issues" 10 | dev-repo: "git+https://github.com/ocaml/ocamlfind.git" 11 | description: """ 12 | Findlib is a library manager for OCaml. It provides a convention how 13 | to store libraries, and a file format ("META") to describe the 14 | properties of libraries. There is also a tool (ocamlfind) for 15 | interpreting the META files, so that it is very easy to use libraries 16 | in programs and scripts. 17 | """ 18 | build: [ 19 | [ 20 | "./configure" 21 | "-bindir" bin 22 | "-sitelib" lib 23 | "-mandir" man 24 | "-config" "%{lib}%/findlib.conf" 25 | "-no-custom" 26 | "-no-camlp4" {!ocaml:preinstalled & ocaml:version >= "4.02.0"} 27 | "-no-topfind" {ocaml:preinstalled} 28 | ] 29 | [make "all"] 30 | [make "opt"] {ocaml:native} 31 | ] 32 | install: [ 33 | [make "install"] 34 | ["install" "-m" "0755" "ocaml-stub" "%{bin}%/ocaml"] {ocaml:preinstalled} 35 | ] 36 | depends: [ 37 | "ocaml" {>= "3.08.0"} 38 | ] 39 | depopts: ["graphics"] 40 | -------------------------------------------------------------------------------- /src/findlib-toolbox/Makefile: -------------------------------------------------------------------------------- 1 | TOP=../.. 2 | include $(TOP)/Makefile.config 3 | 4 | .PHONY: all opt install uninstall clean 5 | 6 | all: make_wizard$(EXEC_SUFFIX) 7 | 8 | opt: 9 | true 10 | 11 | make_wizard$(EXEC_SUFFIX): make_wizard.ml 12 | ocamlc -o make_wizard$(EXEC_SUFFIX) -I +unix -I +labltk -I ../findlib \ 13 | unix.cma str.cma labltk.cma findlib.cma make_wizard.ml 14 | 15 | install: 16 | $(INSTALLFILE) make_wizard$(EXEC_SUFFIX) make_wizard.pattern $(DESTDIR)$(prefix)$(OCAML_SITELIB)/findlib/ 17 | 18 | # uninstall: Nothing to do, because the removal of the findlib core also 19 | # deinstalls the make_wizard 20 | uninstall: 21 | true 22 | 23 | # ---------------------------------------------------------------------- 24 | 25 | tree: lx_spots.mli lx_spots.ml lx_tree.mli lx_tree.ml test_tree.ml 26 | ocamlfind ocamlc -o tree -package labltk,unix,str -linkpkg \ 27 | lx_spots.mli lx_spots.ml lx_tree.mli lx_tree.ml test_tree.ml 28 | 29 | tree_editor: lx_spots.mli lx_spots.ml lx_tree.mli lx_tree.ml tree_editor.ml 30 | ocamlfind ocamlc -o tree_editor -package labltk,unix,str -linkpkg \ 31 | lx_spots.mli lx_spots.ml lx_tree.mli lx_tree.ml tree_editor.ml 32 | 33 | # ---------------------------------------------------------------------- 34 | 35 | clean: 36 | rm -f *.cmi *.cmo 37 | rm -f make_wizard$(EXEC_SUFFIX) # tree tree_editor 38 | -------------------------------------------------------------------------------- /src/findlib/topfind_rd0.p: -------------------------------------------------------------------------------- 1 | (* $Id$ -*- tuareg -*- *) 2 | 3 | (* For Ocaml-3.03 and up, so you can do: #use "topfind" and get a 4 | * working findlib toploop. 5 | *) 6 | 7 | #directory "@SITELIB@/findlib";; 8 | (* OCaml-4.00 requires to have #directory before we load anything *) 9 | 10 | (* First test whether findlib_top is already loaded. If not, load it now. 11 | * The test works by executing the toplevel phrase "Topfind.reset" and 12 | * checking whether this causes an error. 13 | *) 14 | let exec_test s = 15 | let l = Lexing.from_string s in 16 | let ph = !Toploop.parse_toplevel_phrase l in 17 | let fmt = Format.make_formatter (fun _ _ _ -> ()) (fun _ -> ()) in 18 | try 19 | Toploop.execute_phrase false fmt ph 20 | with 21 | _ -> false 22 | in 23 | 24 | if not(exec_test "Topfind.reset;;") then ( 25 | Topdirs.dir_load Format.err_formatter "@SITELIB@/findlib/findlib.cma"; 26 | Topdirs.dir_load Format.err_formatter "@SITELIB@/findlib/findlib_top.cma"; 27 | );; 28 | 29 | (* Old: *) 30 | (* #load "@SITELIB@/findlib/findlib.cma";; *) 31 | (* #load "@SITELIB@/findlib/findlib_top.cma";; *) 32 | 33 | 34 | (* The following is always executed. It is harmless if findlib was already 35 | * initialized 36 | *) 37 | 38 | Topfind.add_predicates [ "byte"; "toploop" ]; 39 | Topfind.don't_load ["findlib"]; 40 | Topfind.announce();; 41 | -------------------------------------------------------------------------------- /site-lib-src/compiler-libs/META.in: -------------------------------------------------------------------------------- 1 | # The compiler itself 2 | requires = "" 3 | version = "[distributed with Ocaml]" 4 | description = "compiler-libs support library" 5 | directory= "+compiler-libs" 6 | 7 | package "common" ( 8 | requires = "compiler-libs" 9 | version = "[distributed with Ocaml]" 10 | description = "Common compiler routines" 11 | archive(byte) = "ocamlcommon.cma" 12 | archive(native) = "ocamlcommon.cmxa" 13 | ) 14 | 15 | package "bytecomp" ( 16 | requires = "compiler-libs.common" 17 | version = "[distributed with Ocaml]" 18 | description = "Bytecode compiler" 19 | archive(byte) = "ocamlbytecomp.cma" 20 | archive(native) = "ocamlbytecomp.cmxa" 21 | ) 22 | 23 | package "optcomp" ( 24 | requires = "compiler-libs.common" 25 | version = "[distributed with Ocaml]" 26 | description = "Native-code compiler" 27 | archive(byte) = "ocamloptcomp.cma" 28 | archive(native) = "ocamloptcomp.cmxa" 29 | exists_if = "ocamloptcomp.cma" 30 | ) 31 | 32 | package "toplevel" ( 33 | requires = "compiler-libs.bytecomp" 34 | version = "[distributed with Ocaml]" 35 | description = "Toplevel interactions" 36 | archive(byte) = "ocamltoplevel.cma" 37 | ) 38 | 39 | package "native-toplevel" ( 40 | requires = "compiler-libs.optcomp dynlink" 41 | version = "[distributed with Ocaml]" 42 | description = "Toplevel interactions" 43 | archive(native) = "ocamltoplevel.cmxa" 44 | exists_if = "ocamltoplevel.cmxa" 45 | ) 46 | -------------------------------------------------------------------------------- /src/findlib/fl_meta.mll: -------------------------------------------------------------------------------- 1 | (* $Id$ 2 | * ---------------------------------------------------------------------- 3 | * 4 | *) 5 | 6 | { open Fl_metatoken } 7 | 8 | rule token = 9 | parse [ 'A'-'Z' 'a'-'z' '_' '0'-'9' '.' ]+ 10 | { 11 | Name (Lexing.lexeme lexbuf) 12 | } 13 | 14 | | '(' 15 | { 16 | LParen 17 | } 18 | 19 | | ')' 20 | { 21 | RParen 22 | } 23 | 24 | | "+=" 25 | { 26 | PlusEqual 27 | } 28 | 29 | | '=' 30 | { 31 | Equal 32 | } 33 | 34 | | '-' 35 | { 36 | Minus 37 | } 38 | 39 | | ',' 40 | { 41 | Comma 42 | } 43 | 44 | | '"' [^ '"' '\\' ]* ( ( "\\\\" | "\\\"" ) [^ '"' '\\' ]* )* '"' 45 | { 46 | let s1 = Lexing.lexeme lexbuf in 47 | let s2 = String.sub s1 1 (String.length s1 - 2) in 48 | let l2 = String.length s2 in 49 | let b = Buffer.create 80 in 50 | let rec fill i = 51 | if i Buffer.add_char b s2.[i+1]; fill (i+2) 54 | | c -> Buffer.add_char b c; fill (i+1) in 55 | fill 0; 56 | String (Buffer.contents b) 57 | } 58 | 59 | | [ ' ' '\t' '\r' ] 60 | { 61 | Space 62 | } 63 | 64 | | '\n' 65 | { 66 | Newline 67 | } 68 | 69 | | '#' [^ '\n']* '\n' 70 | { 71 | Newline 72 | } 73 | 74 | | '#' [^ '\n']* eof 75 | { 76 | Eof 77 | } 78 | 79 | | eof 80 | { 81 | Eof 82 | } 83 | 84 | | _ 85 | { 86 | Unknown 87 | } 88 | 89 | {} 90 | 91 | -------------------------------------------------------------------------------- /doc/src/findlib_ref.sgml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | %gps.common; 10 | ]> 11 | 12 | 13 | 14 | The findlib Reference Manual 15 | 16 | 17 | 18 | 19 | Gerd 20 | Stolpmann 21 | 22 | 23 |
24 | gerd@gerd-stolpmann.de 25 |
26 |
27 |
28 |
29 |
30 | 31 | 32 | 1999-2003Gerd Stolpmann 33 | 34 | 35 |
36 | 37 | 38 | Commands 39 | &findlibocamlfind; 40 | 41 | 42 | 43 | Files 44 | &findlibmeta; 45 | 46 | &findlibconf; 47 | 48 | &findlibsitelib; 49 | 50 | 51 | 52 | Library 53 | 54 | The findlib library 55 | 56 | The findlib library 57 | 58 | 59 | 60 | 61 |
62 | -------------------------------------------------------------------------------- /src/findlib/fl_dynload.mli: -------------------------------------------------------------------------------- 1 | (* $Id$ *) 2 | 3 | (** Utilities for loading dynamically packages *) 4 | 5 | val load_packages : ?debug:bool -> string list -> unit 6 | (** Load the given packages and all their dependencies dynamically. Packages 7 | already loaded or already in-core are not loaded again. The predicates 8 | are taken from {!Findlib.recorded_predicates}, which are normally the 9 | predicates from the link-time of the executable. 10 | 11 | In order to initialize this module correctly, you need to link the 12 | executable in a special way. This is done by including "findlib.dynload" 13 | in the [ocamlfind] command, e.g. 14 | 15 | {[ ocamlfind ocamlopt -o program -package findlib.dynload -linkpkg m.ml ]} 16 | 17 | It is not sufficient to just link [findlib_dynload.cm(x)a] into the 18 | executable. The above command adds special initialization code that 19 | (a) records the predicates and (b) records the packages already present 20 | in the executable. Also [-linkall] is implicitly added. 21 | 22 | The dynamic package loader works both for bytecode and native code. 23 | The META files of the packages need to specify the cma or cmxs files 24 | in the following way: 25 | 26 | - First, the "plugin" variable is checked (instead of "archive"), e.g. 27 | {[ 28 | plugin(byte) = "my_plugin.cma" 29 | plugin(native) = "my_plugin.cmxs" 30 | ]} 31 | This is the preferred style. 32 | - Second, for bytecode only, the normal "archive" variable is 33 | also accepted if "plugin" is not present. (Because bytecode archives 34 | can normally be dynamically loaded without special preparation.) 35 | - Third, for native-code only, the "archive(plugin)" variable 36 | is also accepted. This is for legacy packages. 37 | *) 38 | -------------------------------------------------------------------------------- /src/findlib/topfind_rd1.p: -------------------------------------------------------------------------------- 1 | (* $Id$ -*- tuareg -*- *) 2 | 3 | (* For Ocaml-3.03 and up, so you can do: #use "topfind" and get a 4 | * working findlib toploop. 5 | *) 6 | 7 | #directory "@SITELIB@/findlib";; 8 | (* OCaml-4.00 requires to have #directory before we load anything *) 9 | 10 | #directory "+compiler-libs";; 11 | (* For OCaml-4.00. This directory will be later removed from path *) 12 | 13 | (* First test whether findlib_top is already loaded. If not, load it now. 14 | * The test works by executing the toplevel phrase "Topfind.reset" and 15 | * checking whether this causes an error. 16 | *) 17 | let exec_test s = 18 | let l = Lexing.from_string s in 19 | let ph = !Toploop.parse_toplevel_phrase l in 20 | let fmt = Format.make_formatter (fun _ _ _ -> ()) (fun _ -> ()) in 21 | try 22 | Toploop.execute_phrase false fmt ph 23 | with 24 | _ -> false 25 | in 26 | let is_native = 27 | (* one of the few observable differences... *) 28 | Gc.((get()).stack_limit) = 0 in 29 | let suffix = 30 | if is_native then "cmxs" else "cma" in 31 | if not(exec_test "Topfind.reset;;") then ( 32 | Topdirs.dir_load Format.err_formatter ("@SITELIB@/findlib/findlib." ^ suffix); 33 | Topdirs.dir_load Format.err_formatter ("@SITELIB@/findlib/findlib_top." ^ suffix); 34 | ); 35 | ;; 36 | 37 | #remove_directory "+compiler-libs";; 38 | 39 | (* Old: *) 40 | (* #load "@SITELIB@/findlib/findlib.cma";; *) 41 | (* #load "@SITELIB@/findlib/findlib_top.cma";; *) 42 | 43 | 44 | (* The following is always executed. It is harmless if findlib was already 45 | * initialized 46 | *) 47 | 48 | let is_native = 49 | (* one of the few observable differences... *) 50 | Gc.((get()).stack_limit) = 0 in 51 | let pred = 52 | if is_native then "native" else "byte" in 53 | Topfind.add_predicates [ pred; "toploop" ]; 54 | Topfind.don't_load ["findlib"]; 55 | Topfind.announce();; 56 | -------------------------------------------------------------------------------- /src/findlib/fl_dynload.ml: -------------------------------------------------------------------------------- 1 | (* $Id$ *) 2 | 3 | (* Utilities for loading dynamically packages *) 4 | 5 | open Printf 6 | 7 | let load_pkg ~debug pkg = 8 | if not (Findlib.is_recorded_package pkg) then ( 9 | if debug then 10 | eprintf "[DEBUG] Fl_dynload: about to load: %s\n%!" pkg; 11 | (* Determine the package directory: *) 12 | let d = Findlib.package_directory pkg in 13 | (* First try the new "plugin" variable: *) 14 | let preds = Findlib.recorded_predicates() in 15 | let archive = 16 | try 17 | Findlib.package_property preds pkg "plugin" 18 | with 19 | | Not_found -> 20 | (* Legacy: use "archive" but require that the predicate 21 | "plugin" is mentioned in the definition 22 | *) 23 | try 24 | let v, fpreds = 25 | Findlib.package_property_2 ("plugin"::preds) pkg "archive" in 26 | let need_plugin = 27 | List.mem "native" preds in 28 | if need_plugin && not (List.mem (`Pred "plugin") fpreds) then 29 | "" 30 | else 31 | v 32 | with Not_found -> "" in 33 | (* Split the plugin/archive property and resolve the files: *) 34 | let files = Fl_split.in_words archive in 35 | if debug then 36 | eprintf "[DEBUG] Fl_dynload: files=%S\n%!" archive; 37 | List.iter 38 | (fun file -> 39 | if debug then 40 | eprintf "[DEBUG] Fl_dynload: loading %S\n%!" file; 41 | let file = Findlib.resolve_path ~base:d file in 42 | Dynlink.loadfile file 43 | ) files; 44 | Findlib.record_package Findlib.Record_load pkg 45 | ) 46 | else 47 | if debug then 48 | eprintf "[DEBUG] Fl_dynload: not loading: %s\n%!" pkg 49 | 50 | 51 | let load_packages ?(debug=false) pkgs = 52 | let preds = Findlib.recorded_predicates() in 53 | let eff_pkglist = 54 | Findlib.package_deep_ancestors preds pkgs in 55 | List.iter (load_pkg ~debug) eff_pkglist 56 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | DOCBOOK_HTML = /usr/share/sgml/docbook/stylesheet/dsssl/modular/html 2 | DOCBOOK_PRINT = /usr/share/sgml/docbook/stylesheet/dsssl/modular/print 3 | SRC = $(PWD)/src 4 | 5 | EXPORTED = findlib.mli fl_package_base.mli fl_metascanner.mli \ 6 | fl_dynload.mli topfind.mli 7 | 8 | .PHONY: guide-html ref-html ref-man 9 | 10 | default: guide-html ref-html ref-man README QUICKSTART 11 | 12 | guide-html: guide-html/TIMESTAMP 13 | ref-html: ref-html/TIMESTAMP 14 | ref-man: ref-man/TIMESTAMP 15 | 16 | guide-html/TIMESTAMP: src/*.sgml src/*.mod QUICKSTART.xml common.xml config.xml 17 | mkdir -p guide-html 18 | cd guide-html; \ 19 | rm -f *.htm*; \ 20 | openjade -t sgml -D$(DOCBOOK_HTML) -D$(SRC) findlib.sgml; \ 21 | true 22 | readme -html QUICKSTART.xml >guide-html/quickstart.html 23 | touch guide-html/TIMESTAMP 24 | 25 | ref-html/TIMESTAMP: src/*.sgml src/*.mod common.xml config.xml $(EXPORTED:%=../src/findlib/%) 26 | mkdir -p ref-html 27 | cd ref-html; \ 28 | rm -f *.htm*; \ 29 | openjade -t sgml -D$(DOCBOOK_HTML) -D$(SRC) findlib_ref.sgml; \ 30 | true 31 | mkdir -p ref-html/lib 32 | cd ../src/findlib && \ 33 | ocamldoc -html -d $(PWD)/ref-html/lib -stars -t "The Findlib Library" $(EXPORTED) 34 | touch ref-html/TIMESTAMP 35 | 36 | src/findlib_reference.xml: src/*.sgml src/*.mod 37 | osx -D$(DOCBOOK_HTML) -D$(SRC) \ 38 | findlib_reference.sgml >src/findlib_reference.xml ; \ 39 | true 40 | 41 | ref-man/TIMESTAMP: src/findlib_reference.xml 42 | mkdir -p ref-man 43 | cd ref-man; \ 44 | rm -f *.[0-9] TIMESTAMP; \ 45 | db2man <../src/findlib_reference.xml 46 | touch ref-man/TIMESTAMP 47 | 48 | # Unfortunately, output of ocamldoc -man is too bad to be useful. 49 | # cd ../src/findlib && \ 50 | # ocamldoc -man -man-mini -d $(PWD)/ref-man -man-suffix 3 -stars -t "The Findlib Library" $(EXPORTED) 51 | 52 | .SUFFIXES: .xml .sgml 53 | 54 | .sgml.xml: 55 | sx -xndata $< >$@; true 56 | 57 | 58 | 59 | clean: 60 | rm -rf guide-html guide-man ref-html/TIMESTAMP 61 | rm -f src/*.xml 62 | 63 | distclean: 64 | rm -f src/*.xml 65 | rm -f src/*~ 66 | rm -f *~ 67 | 68 | QUICKSTART: QUICKSTART.xml 69 | readme -text QUICKSTART.xml >QUICKSTART 70 | 71 | README: README.xml 72 | readme -text README.xml >README 73 | 74 | -------------------------------------------------------------------------------- /patches/findlib-1.1-win32.diff: -------------------------------------------------------------------------------- 1 | --- ./itest-aux/simple_dbm.ml.orig 2005-11-07 13:38:01.203976400 +0100 2 | +++ ./itest-aux/simple_dbm.ml 2005-11-07 13:38:11.498265600 +0100 3 | @@ -1,9 +1,9 @@ 4 | -(try 5 | +(try 6 | Sys.remove "itest-aux/testdb.db" 7 | -with 8 | +with 9 | _ -> ()); 10 | 11 | -let dbm = 12 | +let _dbm = 13 | Dbm.opendbm "itest-aux/testdb" [ Dbm.Dbm_rdwr; Dbm.Dbm_create ] 0o777 in 14 | 15 | print_string "OK\n";; 16 | --- ./itest-aux/simple_labltk.ml.orig 2005-11-07 13:39:25.931584300 +0100 17 | +++ ./itest-aux/simple_labltk.ml 2005-11-07 13:39:34.954108200 +0100 18 | @@ -1,6 +1,6 @@ 19 | open Tk;; 20 | 21 | -let top = openTk() in 22 | +let _top = openTk() in 23 | update(); 24 | closeTk() 25 | ;; 26 | --- ./itest-aux/simple_num.ml.orig 2005-11-07 13:39:00.956917700 +0100 27 | +++ ./itest-aux/simple_num.ml 2005-11-07 13:39:05.973881600 +0100 28 | @@ -1,4 +1,4 @@ 29 | -let n = Num.num_of_int 5 in 30 | +let _n = Num.num_of_int 5 in 31 | 32 | print_string "OK\n";; 33 | 34 | --- ./itest-aux/simple_str.ml.orig 2005-11-07 13:35:56.037998100 +0100 35 | +++ ./itest-aux/simple_str.ml 2005-11-07 13:35:58.661692300 +0100 36 | @@ -1,4 +1,4 @@ 37 | -let b = Str.regexp ".*" in 38 | +let _b = Str.regexp ".*" in 39 | 40 | print_string "OK\n";; 41 | 42 | --- ./itest-aux/simple_unix.ml.orig 2005-11-07 13:37:28.257845000 +0100 43 | +++ ./itest-aux/simple_unix.ml 2005-11-07 13:37:34.927235600 +0100 44 | @@ -1,4 +1,4 @@ 45 | -let p = Unix.getpid() in 46 | +let _p = Unix.getpid() in 47 | 48 | print_string "OK\n";; 49 | 50 | --- ./tools/extract_args/extract_args.ml.orig 2005-11-07 13:27:58.494279900 +0100 51 | +++ ./tools/extract_args/extract_args.ml 2005-11-07 13:32:33.393117500 +0100 52 | @@ -25,13 +25,17 @@ 53 | 54 | let get_help cmd = 55 | let temp_file = 56 | - Filename.temp_file "findlib" ".txt" in 57 | + Filename.temp_file "findlib" ".txt" 58 | + and quote s = 59 | + match Sys.os_type with 60 | + "Win32" -> s 61 | + | _ -> Filename.quote s in 62 | let help_out = 63 | try 64 | let code = 65 | - Sys.command (sprintf "%s -help >%s" 66 | - (Filename.quote cmd) 67 | - (Filename.quote temp_file)) in 68 | + Sys.command (sprintf "%s -help >%s" 69 | + (quote cmd) 70 | + (quote temp_file)) in 71 | if code <> 0 then 72 | raise Not_found; (* Assume command does not exist! *) 73 | let lines = read_lines temp_file in 74 | -------------------------------------------------------------------------------- /itest: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # $Id$ 3 | # ---------------------------------------------------------------------- 4 | # 5 | 6 | case `uname` in 7 | CYGWIN*) 8 | execsuffix=.exe ;; 9 | *) 10 | execsuffix= ;; 11 | esac 12 | ocamlfind="src/findlib/ocamlfind${execsuffix}" 13 | 14 | PATH="./tools:$PATH" 15 | export PATH 16 | 17 | check_linkage () { 18 | p=$1 19 | shift 20 | rm -f itest-aux/simple 21 | $ocamlfind ocamlc -linkall -linkpkg -custom "$@" -o itest-aux/simple itest-aux/simple_$p.ml >itest-aux/err.out 2>&1 22 | output=`cat itest-aux/err.out | sed -e '/WARNING.*/ d'` 23 | error=0 24 | if [ -n "$output" ]; then 25 | echo "* When trying to compile with" 26 | echo " $ocamlfind ocamlc -linkall -linkpkg -custom "$@" -o itest-aux/simple itest-aux/simple_$p.ml" 27 | echo " an error has occurred. The error error message has been written" 28 | echo " to itest-aux/err.out." 29 | error=1 30 | fi 31 | if [ "$error" = "0" ]; then 32 | result=`itest-aux/simple${execsuffix}` 33 | [ "x$result" = "xOK" ] 34 | else 35 | return $error 36 | fi 37 | } 38 | 39 | problems () { 40 | echo "* This test failed. Please check the settings in site-lib-src/$1/META," 41 | echo " especially the 'linkopts' variable, and try again. You can invoke" 42 | echo " this test directly by: ./itest $1" 43 | } 44 | 45 | 46 | do_test () { 47 | case "$1" in 48 | dbm|graphics|num|str|unix|bigarray|labltk) 49 | echo "* Checking linker options for $1 library" 50 | rm -f itest-aux/testdb* 51 | if check_linkage $1 -package $1; then 52 | echo "ok" 53 | else 54 | problems $1 55 | fi 56 | ;; 57 | threads) 58 | echo "* Checking linker options for threads library" 59 | if check_linkage $1 -package $1 -thread; then 60 | echo "ok" 61 | else 62 | problems $1 63 | fi 64 | ;; 65 | 66 | camlp4) 67 | echo "* Checking options for camlp4 preprocessor" 68 | if check_linkage $1 -package $1 -syntax camlp4r; then 69 | echo "ok" 70 | else 71 | problems $1 72 | fi 73 | ;; 74 | 75 | *) 76 | echo "unknown test: $1" 77 | ;; 78 | esac 79 | } 80 | 81 | 82 | OCAMLPATH="./site-lib-src" 83 | export OCAMLPATH 84 | 85 | if [ ! -f "$ocamlfind" ]; then 86 | echo "Sorry, you must first compile the library before you can invoke" 1>&2 87 | echo "the integration test." 1>&2 88 | exit 1 89 | fi 90 | 91 | if [ "$#" = "0" ]; then 92 | for t in unix str dbm graphics num threads bigarray labltk camlp4; do 93 | if [ -f "site-lib-src/$t/META" ]; then 94 | echo "------------------------------------------------------------------------------" 95 | do_test $t 96 | echo 97 | fi 98 | done 99 | else 100 | do_test $1 101 | fi 102 | -------------------------------------------------------------------------------- /src/findlib/test_parser.ml: -------------------------------------------------------------------------------- 1 | let with_open_in file func = 2 | let chan = open_in file in 3 | let result = 4 | try func chan 5 | with exn -> close_in chan; raise exn 6 | in 7 | close_in chan; result 8 | ;; 9 | 10 | type test_mode = Compare_both | Only of (old_or_new * int) 11 | and old_or_new = Old | New 12 | 13 | let read_file file = 14 | let buf = Buffer.create 100 in 15 | with_open_in file (fun ch -> 16 | try while true do Buffer.add_string buf (input_line ch) done 17 | with End_of_file -> ()); 18 | Buffer.contents buf 19 | 20 | let test mode file = 21 | match mode with 22 | | Compare_both -> 23 | let ast1 = with_open_in file Fl_metascanner.parse in 24 | let ast2 = with_open_in file Fl_metascanner.parse2 in 25 | Printf.printf "%s tested %s\n" file (if ast1 = ast2 then "OK" else "FAIL") 26 | | Only (old_or_new, niter) -> 27 | let content = read_file file in 28 | for i = 1 to niter do 29 | let parse = match old_or_new with 30 | | Old -> Fl_metascanner.parse_lexing 31 | | New -> Fl_metascanner.parse2_lexing in 32 | ignore (parse (Lexing.from_string content)) 33 | done 34 | 35 | let rec explore mode path = 36 | if Sys.is_directory path then 37 | let traverse file = explore mode (Filename.concat path file) in 38 | Array.iter traverse (Sys.readdir path) 39 | else if Filename.basename path = "META" then 40 | test mode path 41 | 42 | let () = 43 | let test_mode, targets = (* command-line option handling *) 44 | let only_old = ref false in 45 | let only_new = ref false in 46 | let niter = ref 1 in 47 | let targets = ref [] in 48 | let usage = "test_parser ....\n \ 49 | recursively traverse paths and compare the two parsers \ 50 | on each file named META" 51 | in 52 | let options = [ 53 | ("--niter", Arg.Set_int niter, "iterate the parser for performance comparison (only in --only-old or --only-new modes)"); 54 | ("--only-old", Arg.Set only_old, "only test the old parser"); 55 | ("--only-new", Arg.Set only_new, "only test the new parser"); 56 | ] in 57 | let action path = targets := path :: !targets in 58 | Arg.parse options action usage; 59 | let quit_with_usage () = Arg.usage options usage; exit 1 in 60 | let test_mode = 61 | match !only_old, !only_new with 62 | | false, false -> Compare_both 63 | | false, true -> Only (New, !niter) 64 | | true, false -> Only (Old, !niter) 65 | | true, true -> 66 | prerr_endline "--only-only and --new-only cannot be \ 67 | both set at the same time"; 68 | quit_with_usage (); 69 | in 70 | if !targets = [] then quit_with_usage (); 71 | test_mode, !targets 72 | in 73 | let traverse path = 74 | if Sys.file_exists path then explore test_mode path 75 | else Printf.eprintf "Error: path %s does not exist and was ignored.\n" path 76 | in 77 | List.iter traverse targets 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /src/findlib/fl_args.ml: -------------------------------------------------------------------------------- 1 | (* $Id$ *) 2 | 3 | (* Rewrite a list of arguments args (from Sys.args) so that contracted 4 | options like -L are transformed to -L , and become parseable 5 | by Arg. 6 | *) 7 | 8 | let make_ht (l:string list) = 9 | let ht = Hashtbl.create 10 in 10 | List.iter (fun x -> Hashtbl.add ht x ()) l; 11 | ht 12 | 13 | let is_prefix s1 s2 = 14 | let l1 = String.length s1 in 15 | let l2 = String.length s2 in 16 | l2 >= l1 && String.sub s2 0 l1 = s1 17 | 18 | let rewrite_contracted_args spec contracted_opts args = 19 | let args = Array.to_list args in 20 | let switches = 21 | List.map 22 | (fun (name,kind,text) -> name) 23 | (List.filter 24 | (fun (name,kind,text) -> 25 | match kind with 26 | | Arg.Unit _ 27 | | Arg.Set _ 28 | | Arg.Clear _ -> true 29 | | Arg.Tuple _ -> 30 | failwith 31 | "Fl_args.rewrite_for_contracted_args: Arg.Tuple unsupported" 32 | | _ -> false 33 | ) 34 | spec 35 | ) in 36 | let unary_opts = 37 | List.map 38 | (fun (name,kind,text) -> name) 39 | (List.filter 40 | (fun (name,kind,text) -> 41 | match kind with 42 | | Arg.String _ 43 | | Arg.Set_string _ 44 | | Arg.Int _ 45 | | Arg.Set_int _ 46 | | Arg.Float _ 47 | | Arg.Set_float _ -> true 48 | | _ -> false 49 | ) 50 | spec 51 | ) in 52 | let rest_opts = 53 | List.map 54 | (fun (name,kind,text) -> name) 55 | (List.filter 56 | (fun (name,kind,text) -> 57 | match kind with 58 | | Arg.Rest _ -> true 59 | | _ -> false 60 | ) 61 | spec 62 | ) in 63 | 64 | let sw_ht = make_ht switches in 65 | let unary_ht = make_ht unary_opts in 66 | let rest_ht = make_ht rest_opts in 67 | 68 | let rec rewrite (args:string list) = 69 | match args with 70 | | arg :: args_rest when Hashtbl.mem sw_ht arg -> 71 | arg :: rewrite args_rest 72 | | arg :: args_rest when Hashtbl.mem rest_ht arg -> 73 | args 74 | | arg1 :: arg2 :: args_rest when Hashtbl.mem unary_ht arg1 -> 75 | arg1 :: arg2 :: rewrite args_rest 76 | | arg :: args_rest -> 77 | ( try 78 | let args1 = expand arg contracted_opts in 79 | let args2 = rewrite args_rest in 80 | args1 @ args2 81 | with 82 | | Not_found -> 83 | arg :: rewrite args_rest 84 | ) 85 | | [] -> 86 | [] 87 | 88 | and expand arg olo = 89 | match olo with 90 | | olo1 :: olo_rest -> 91 | if is_prefix olo1 arg then 92 | let p = String.length olo1 in 93 | let l = String.length arg in 94 | [ olo1; 95 | String.sub arg p (l-p) 96 | ] 97 | else 98 | expand arg olo_rest 99 | | [] -> 100 | raise Not_found 101 | 102 | in 103 | 104 | Array.of_list (rewrite args) 105 | -------------------------------------------------------------------------------- /Makefile.config.pattern: -------------------------------------------------------------------------------- 1 | # You can manually set up your configuration using this 2 | # pattern. The final name of the file must be "Makefile.config". 3 | # Note that there are other files containing parts of the 4 | # configuration, especially the site-lib/*/META files. 5 | # 6 | #---------------------------------------------------------------------- 7 | # Where the OCAML core is installed: 8 | #---------------------------------------------------------------------- 9 | OCAML_CORE_STDLIB=/usr/local/lib/ocaml 10 | OCAML_CORE_BIN=/usr/local/bin 11 | OCAML_CORE_MAN=/usr/local/man 12 | 13 | #---------------------------------------------------------------------- 14 | # Type of multi-threading support: either vm or posix 15 | # (Note: Since OCaml 3.07, "posix" includes "vm", because a build 16 | # supporting posix also supports vm.) 17 | #---------------------------------------------------------------------- 18 | OCAML_THREADS=vm 19 | #OCAML_THREADS=posix 20 | 21 | #---------------------------------------------------------------------- 22 | # Where the site-lib directory will be 23 | #---------------------------------------------------------------------- 24 | OCAML_SITELIB=/usr/local/lib/ocaml/site-lib 25 | 26 | #---------------------------------------------------------------------- 27 | # What the path setting will be 28 | #---------------------------------------------------------------------- 29 | FINDLIB_PATH=/usr/local/lib/ocaml/site-lib:/usr/local/lib/ocaml 30 | 31 | #---------------------------------------------------------------------- 32 | # Where binaries and manual pages will be installed 33 | #---------------------------------------------------------------------- 34 | OCAMLFIND_BIN=/usr/local/bin 35 | OCAMLFIND_MAN=/usr/local/man 36 | 37 | #---------------------------------------------------------------------- 38 | # The absolute location of the configuration file 39 | #---------------------------------------------------------------------- 40 | OCAMLFIND_CONF=/usr/local/etc/ocamlfind.conf 41 | 42 | #---------------------------------------------------------------------- 43 | # Autolinking is usually on 44 | #---------------------------------------------------------------------- 45 | OCAML_AUTOLINK=true 46 | 47 | #---------------------------------------------------------------------- 48 | # Windows only: set this to .exe 49 | #---------------------------------------------------------------------- 50 | EXEC_SUFFIX= 51 | 52 | #---------------------------------------------------------------------- 53 | # Windows MSVC port: set this to .lib 54 | #---------------------------------------------------------------------- 55 | LIB_SUFFIX=.a 56 | 57 | #---------------------------------------------------------------------- 58 | # Which parts are to be built: findlib, findlib-toolbox (space-separated 59 | # list) 60 | #---------------------------------------------------------------------- 61 | PARTS=findlib findlib-toolbox 62 | 63 | #---------------------------------------------------------------------- 64 | # Whether the "topfind" script is installed in $(OCAML_CORE_STDLIB): 65 | #---------------------------------------------------------------------- 66 | INSTALL_TOPFIND=1 67 | 68 | #---------------------------------------------------------------------- 69 | # Whether make install should update Makefile.packages just before 70 | # running 71 | #---------------------------------------------------------------------- 72 | CHECK_BEFORE_INSTALL=0 73 | -------------------------------------------------------------------------------- /site-lib-src/camlp4.309/META.in: -------------------------------------------------------------------------------- 1 | # Specifications for the "camlp4" preprocessor: 2 | requires = "" 3 | version = "[distributed with Ocaml]" 4 | description = "Base for Camlp4 syntax extensions" 5 | directory = "%%camlp4_dir%%" 6 | 7 | # For the toploop: 8 | archive(byte,toploop,camlp4o) = "camlp4o.cma" 9 | archive(byte,toploop,camlp4r) = "camlp4r.cma" 10 | 11 | # Scheme-like syntax: 12 | # Do #predicates "syntax,camlp4scheme", followed by #require "camlp4" 13 | archive(byte,toploop,camlp4scheme) = "camlp4sch.cma" 14 | 15 | # Standard ML-like syntax: 16 | # Do #predicates "syntax,camlp4sml", followed by #require "camlp4" 17 | archive(byte,toploop,camlp4sml) = "gramlib.cma camlp4_top.cma pa_sml.cmo" 18 | 19 | # Lisp-like syntax: 20 | # Do #predicates "syntax,camlp4lisp", followed by #require "camlp4" 21 | archive(byte,toploop,camlp4lisp) = "gramlib.cma camlp4_top.cma pa_lisp.cmo" 22 | 23 | # For the preprocessor itself: 24 | archive(syntax,preprocessor,camlp4o) = "pa_o.cmo pa_op.cmo pr_dump.cmo" 25 | archive(syntax,preprocessor,camlp4r) = "pa_r.cmo pa_rp.cmo pr_dump.cmo" 26 | archive(syntax,preprocessor,camlp4sml) = "pa_sml.cmo pr_dump.cmo" 27 | archive(syntax,preprocessor,camlp4scheme) = "pa_scheme.cmo pr_dump.cmo" 28 | archive(syntax,preprocessor,camlp4lisp) = "pa_lisp.cmo pr_dump.cmo" 29 | preprocessor = "%%camlp4_cmd%% -nolib" 30 | 31 | package "gramlib" ( 32 | requires(toploop) = "camlp4" 33 | version = "[distributed with Ocaml]" 34 | description = "Grammar library to create syntax extensions" 35 | archive(byte) = "gramlib.cma" 36 | archive(byte,toploop) = "" # already contained in camlp4*.cma 37 | archive(native) = "gramlib.cmxa" 38 | ) 39 | 40 | package "quotations" ( 41 | requires = "camlp4" 42 | version = "[distributed with Ocaml]" 43 | description = "Syntax extension: Quotations to create AST nodes" 44 | archive(syntax,preprocessor) = "q_MLast.cmo" 45 | archive(syntax,toploop) = "q_MLast.cmo" 46 | ) 47 | 48 | package "phony_quotations" ( 49 | requires = "camlp4" 50 | version = "[distributed with Ocaml]" 51 | description = "Syntax extension: Phony quotations" 52 | archive(syntax,preprocessor) = "q_phony.cmo" 53 | archive(syntax,toploop) = "q_phony.cmo" 54 | ) 55 | 56 | package "extend" ( 57 | requires = "camlp4" 58 | version = "[distributed with Ocaml]" 59 | description = "Syntax extension: EXTEND the camlp4 grammar" 60 | archive(syntax,preprocessor) = "pa_extend.cmo" 61 | archive(syntax,toploop) = "pa_extend.cmo" 62 | ) 63 | 64 | package "extfun" ( 65 | requires = "camlp4" 66 | version = "[distributed with Ocaml]" 67 | description = "Syntax extension: Extensible functions" 68 | archive(syntax,preprocessor) = "pa_extfun.cmo" 69 | archive(syntax,toploop) = "pa_extfun.cmo" 70 | ) 71 | 72 | package "fstream" ( 73 | requires = "camlp4" 74 | version = "[distributed with Ocaml]" 75 | description = "Syntax extension: Functional stream parsers" 76 | archive(syntax,preprocessor) = "pa_fstream.cmo" 77 | archive(syntax,toploop) = "pa_fstream.cmo" 78 | ) 79 | 80 | package "macro" ( 81 | requires = "camlp4" 82 | version = "[distributed with Ocaml]" 83 | description = "Syntax extension: Conditional compilation" 84 | archive(syntax,preprocessor) = "pa_macro.cmo" 85 | archive(syntax,toploop) = "pa_macro.cmo" 86 | ) 87 | 88 | package "unit_constraints" ( 89 | requires = "camlp4" 90 | version = "[distributed with Ocaml]" 91 | description = "Syntax extension: Type constraints of type unit (revised syntax only)" 92 | archive(syntax,preprocessor,camlp4r) = "pa_ru.cmo" 93 | archive(syntax,toploop,camlp4r) = "pa_ru.cmo" 94 | error(syntax,-camlp4r) = "Not available" 95 | ) 96 | -------------------------------------------------------------------------------- /mini/README: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------- 2 | ocamlfind-mini 3 | ---------------------------------------------------------------------- 4 | 5 | ocamlfind-mini is an OCaml script that implements a subset of the 6 | full functionality of ocamlfind. It consists only of one file, so it 7 | is easy to distribute it with any software. 8 | 9 | The subset is normally sufficient to compile a library and to 10 | install the library; but it is insufficient to link the library 11 | into an executable. 12 | 13 | ---------------------------------------------------------------------- 14 | SUPPORTED OPERATING SYSTEMS: 15 | ---------------------------------------------------------------------- 16 | 17 | For Unixes, the script runs out of the box. It uses the ocaml system 18 | found in the command path. 19 | 20 | I think the script also runs in Windows, but I have not yet checked that. 21 | Anyway, you cannot call it directly, but by doing 22 | ocaml ocamlfind-mini ... 23 | 24 | Macintosh is not supported; I don't have enough knowledge for a Mac port. 25 | 26 | ---------------------------------------------------------------------- 27 | FUNCTIONALITY: 28 | ---------------------------------------------------------------------- 29 | 30 | Overall: The configuration file ocamlfind.conf is ignored. However, 31 | some environment variables are respected (see below). 32 | 33 | A package directory is recognized by checking whether there is a META 34 | file in it. However, the contents of that file are ignored. 35 | 36 | The following subset has been implemented: 37 | 38 | - ocamlfind-mini [ocamlc|ocamlopt|ocamlcp|ocamlmktop] ... 39 | 40 | The -package option works, but you must set the environment variable 41 | OCAMLPATH (see below). 42 | 43 | The options -linkpkg, -predicates, -dontlink, -syntax, -ppopt are 44 | rejected. 45 | 46 | This normally means that you can compile modules as in: 47 | 48 | ocamlfind-mini ocamlc -c -package p1,p2,p3 my_module.ml 49 | 50 | However, you cannot create executables because -linkpkg is not 51 | supported. 52 | 53 | Note that ocamlfind-mini is unable to figure out the prerequisite 54 | packages, so the -package option must enumerate _all_ needed packages. 55 | 56 | Note that ocamlfind-mini does not support the alternate directory 57 | layout where all META files are collected in one directory. 58 | 59 | - ocamlfind-mini install ... 60 | 61 | Installs the files in the package directory for . You must help 62 | ocamlfind-mini by specifying the destination directory: 63 | 64 | * Setting the -destdir option: 65 | 66 | ocamlfind-mini install -destdir ... 67 | 68 | This command installs the new package into /. 69 | 70 | * Setting the OCAMLFIND_DESTDIR variable: 71 | 72 | export OCAMLFIND_DESTDIR= 73 | ocamlfind-mini install ... 74 | 75 | This command installs the new package into /, too. 76 | 77 | - ocamlfind-mini remove 78 | 79 | Removes the package . Again, you must specify the destination 80 | directory by either setting the -destdir option or by setting the 81 | OCAMLFIND_DESTDIR variable. 82 | 83 | ---------------------------------------------------------------------- 84 | ENVIRONMENT: 85 | ---------------------------------------------------------------------- 86 | 87 | The following variables are supported: 88 | 89 | - OCAMLPATH 90 | 91 | A colon (Win: semicolon)-separated list of directories: 92 | OCAMLPATH=::... 93 | 94 | When ocamlfind-mini searches a package , it checks whether 95 | //META exists for K=1, 2, ... 96 | 97 | - OCAMLFIND_DESTDIR 98 | 99 | The destination directory for "install" and "remove". 100 | 101 | - OCAMLFIND_METADIR 102 | 103 | The destination directory for META files. It is not recommended to set 104 | this variable. 105 | -------------------------------------------------------------------------------- /tools/extract_args/extract_args.mll: -------------------------------------------------------------------------------- 1 | (* $Id$ *) 2 | 3 | (* Runs ocamlc -help and extract the command-line signature *) 4 | 5 | { 6 | open Printf 7 | } 8 | 9 | let whitespace = [ ' ' '\t' ] 10 | 11 | rule get_switch = parse 12 | | whitespace* ('-' [ '-' 'a'-'z' 'A'-'Z' '0'-'9' '_' ',' ]+ as switch_name) 13 | whitespace? (_* as help_text) eof 14 | {Some (switch_name, help_text)} 15 | | whitespace* '-' whitespace+ (_* as help_text) eof 16 | {Some ("-", help_text)} 17 | | _? 18 | {None} 19 | 20 | and has_argument = parse 21 | | whitespace* [ '<' '[' '{' ] 22 | {true} 23 | | _? 24 | {false} 25 | 26 | { 27 | let read_lines file = 28 | let f = open_in file in 29 | let lines = ref [] in 30 | try 31 | while true do 32 | lines := input_line f :: !lines 33 | done; 34 | assert false 35 | with 36 | | End_of_file -> 37 | close_in f; 38 | List.rev !lines 39 | | error -> 40 | close_in f; 41 | raise error 42 | ;; 43 | 44 | 45 | let get_help cmd = 46 | let temp_file = 47 | Filename.temp_file "findlib" ".txt" in 48 | let help_out = 49 | try 50 | let code = 51 | Sys.command (sprintf "%s -help >%s 2>&1" 52 | cmd 53 | (Filename.quote temp_file)) in 54 | if code <> 0 then 55 | raise Not_found; (* Assume command does not exist! *) 56 | let lines = read_lines temp_file in 57 | Sys.remove temp_file; 58 | lines 59 | with error -> 60 | Sys.remove temp_file; raise error in 61 | help_out 62 | ;; 63 | 64 | 65 | let get_switch s = get_switch (Lexing.from_string s) 66 | let has_argument s = has_argument (Lexing.from_string s) 67 | 68 | 69 | let rec extract_signature lines = 70 | match lines with 71 | | [] -> 72 | [] 73 | | line :: lines' -> 74 | match get_switch line with 75 | | Some (switch_name, help_text) -> 76 | let has_arg = has_argument help_text in 77 | let help_lines, lines'' = extract_help_continuation lines' in 78 | let help_text' = String.concat "\n" (help_text :: help_lines) in 79 | let r = 80 | (switch_name, has_arg, help_text') in 81 | r :: extract_signature lines'' 82 | | None -> 83 | extract_signature lines' 84 | 85 | and extract_help_continuation lines = 86 | match lines with 87 | | [] -> 88 | ( [], [] ) 89 | | line :: lines' -> 90 | if get_switch line <> None then 91 | ( [], lines ) 92 | else 93 | let help_lines, lines'' = extract_help_continuation lines' in 94 | (line :: help_lines, lines'') 95 | ;; 96 | 97 | 98 | let rm_help_switch switches = 99 | List.filter 100 | (fun (name, _, _) -> 101 | name <> "-help" && name <> "--help") 102 | switches 103 | ;; 104 | 105 | 106 | let output_some_signature f name switches = 107 | fprintf f "let %s_spec = Some [\n" name; 108 | List.iter 109 | (fun (switch_name, has_arg, help_text) -> 110 | fprintf f " \"%s\",\n" (String.escaped switch_name); 111 | fprintf f " %b,\n" has_arg; 112 | fprintf f " \"%s\";\n\n" (String.escaped help_text) 113 | ) 114 | switches; 115 | fprintf f "];;\n\n" 116 | ;; 117 | 118 | 119 | let output_none f name = 120 | fprintf f "let %s_spec = None;;\n\n" name 121 | ;; 122 | 123 | 124 | let main() = 125 | let f = ref stdout in 126 | let progs = ref [] in 127 | Arg.parse 128 | [ "-o", Arg.String (fun s -> f := open_out s), 129 | " Save generated module to this file"; 130 | ] 131 | (fun arg -> progs := arg :: !progs) 132 | "usage: extract_args ..."; 133 | 134 | progs := List.rev !progs; 135 | 136 | List.iter 137 | (fun prog -> 138 | try 139 | let help_lines = get_help prog in (* or Not_found *) 140 | let switches = rm_help_switch (extract_signature help_lines) in 141 | output_some_signature !f prog switches 142 | with 143 | Not_found -> 144 | output_none !f prog 145 | ) 146 | !progs; 147 | 148 | close_out !f 149 | ;; 150 | 151 | 152 | main();; 153 | } 154 | -------------------------------------------------------------------------------- /src/findlib/fl_metascanner.mli: -------------------------------------------------------------------------------- 1 | (* $Id$ 2 | * ---------------------------------------------------------------------- 3 | * 4 | *) 5 | 6 | (** Parses META files *) 7 | 8 | open Fl_metatoken 9 | 10 | type formal_pred = 11 | [ `Pred of string (** Positive occurence of a formal predicate var *) 12 | | `NegPred of string (** Negative occurence of a formal predicate var *) 13 | ] 14 | 15 | type flavour = 16 | [ `BaseDef 17 | | `Appendix 18 | ] 19 | (** [`BaseDef] refers to META definitions using the "=" operator, 20 | * and [`Appendix] refers to definitions using the "+=" operator. 21 | *) 22 | 23 | type pkg_definition = 24 | { def_var : string; (** The name of the defined variable *) 25 | def_flav : flavour; (** The flavour of the definition *) 26 | def_preds : formal_pred list; (** The formal predicates of the def *) 27 | def_value : string; (** The value assigned to the variable *) 28 | } 29 | (** A [pkg_definition] is expressed by the syntax 30 | * {[ var(p1,p2,...) = "value" ]} (flavour `BaseDef), 31 | * or the syntax 32 | * {[ var(p1,p2,...) += "value" ]} (flavour `Appendix) 33 | * in the META file. The list of predicates may be omitted. Predicates 34 | * may be negated by using "-", e.g. "-x". 35 | *) 36 | 37 | type pkg_expr = 38 | { pkg_defs : pkg_definition list; 39 | pkg_children : (string * pkg_expr) list; 40 | } 41 | (** A value of type [pkg_expr] denotes the contents of a META file. 42 | * The component [pkg_defs] are the variable definitions. 43 | * The component [pkg_children] contains 44 | * the definitions of the subpackages. 45 | *) 46 | 47 | exception Error of string 48 | 49 | 50 | val parse : in_channel -> pkg_expr 51 | (** [parse ch:] 52 | * scans and parses the file connected with channel [ch]. The file must 53 | * have a syntax compatible with the META format. The return value 54 | * contains the found definitions for the package and all subpackages. 55 | * 56 | * [exception Error of string:] is 57 | * raised on syntax errors. The string explains the error. 58 | *) 59 | 60 | val parse_lexing : Lexing.lexbuf -> pkg_expr 61 | 62 | 63 | val print_def : out_channel -> pkg_definition -> unit 64 | (** [print_def ch def]: 65 | * Outputs the definition to a channel. 66 | *) 67 | 68 | val print : out_channel -> pkg_expr -> unit 69 | (** [print ch expr]: 70 | * Outputs the package expression to a channel. 71 | *) 72 | 73 | 74 | val lookup : 75 | string -> string list -> pkg_definition list -> string 76 | (** [lookup variable_name predicate_list def]: 77 | * 78 | * Returns the value of [variable_name] in [def] under the assumption 79 | * that the predicates in [predicate_list] hold, but no other predicates. 80 | * 81 | * The rules are as follows: In the step (A), only the [`BaseDef] 82 | * definitions are considered. The first base definition is determined where 83 | * all predicates are satisfied and that has the longest predicate list. 84 | * In the step (B) only the [`Appendix] definitions are considered. 85 | * All definitions are determined where all predicates are satisfied. 86 | * The final result is the concatenation of the single result of (A) 87 | * and all results of (B) (in the order they are defined). A space 88 | * character is inserted between two concatenated strings. 89 | * 90 | * When step (A) does not find any matching definition, the exception 91 | * [Not_found] is raised. 92 | *) 93 | 94 | 95 | val lookup_2 : 96 | string -> string list -> pkg_definition list -> string * formal_pred list 97 | (** Like [lookup], but also returns the list of predicates that had to 98 | be considered to select the particular variable definition. 99 | *) 100 | 101 | 102 | val predicate_exists : 103 | string -> pkg_definition list -> bool 104 | (** [predicate_exists variable_name def]: 105 | 106 | Whether [variable_name] is explicitly mentioned in [def]. 107 | *) 108 | -------------------------------------------------------------------------------- /src/findlib/fl_lint.ml: -------------------------------------------------------------------------------- 1 | (* $Id$ -*- tuareg -*- 2 | * ---------------------------------------------------------------------- 3 | * 4 | *) 5 | 6 | open Fl_metascanner 7 | 8 | module Have = struct 9 | module T = struct 10 | type mode = [`Byte | `Native | `Toploop | `Preprocessor | `Ppx_driver] 11 | type t = [ 12 | `Mode of [ `TooMany | `None] 13 | (** problem in the number of mode (byte,native,syntax,...) 14 | in the variable *) 15 | | `Archive of [`Plugin|`NoPlugin] * mode 16 | (** archive(plugin,...) or archive(...)) *) 17 | | `Plugin of [`Plugin|`NoPlugin] * mode 18 | (** plugin(...) *) 19 | | `Description 20 | | `Requires 21 | | `Version 22 | ] 23 | let compare = compare 24 | end 25 | include T 26 | module Set = Set.Make(T) 27 | module Map = Map.Make(T) 28 | end 29 | 30 | let scan_def acc def = 31 | let add have = Have.Map.add have def acc in 32 | let has_plugin_pred = List.mem (`Pred "plugin") def.def_preds in 33 | let plugin = if has_plugin_pred then `Plugin else `NoPlugin in 34 | let modes = [ "byte", `Byte; 35 | "native", `Native; 36 | "toploop", `Toploop; 37 | "preprocessor", `Preprocessor; 38 | "ppx_driver", `Ppx_driver 39 | ] in 40 | let modes = 41 | List.filter 42 | (fun (p,_) -> List.mem (`Pred p) def.def_preds) 43 | modes 44 | in 45 | let modes = List.map snd modes in 46 | match def.def_var, modes with 47 | (** For archive the modes are used in multiple ways, so we can't 48 | check exhaustiveness or presence. 49 | *) 50 | | "plugin", [] -> add (`Mode(`None)) 51 | | "plugin", _::_::_ -> add (`Mode(`TooMany)) 52 | 53 | | "archive", [mode] -> add (`Archive(plugin,mode)) 54 | | "plugin", [mode] -> add (`Plugin(plugin,mode)) 55 | | "description", _ -> add `Description 56 | | "requires", _ -> add `Requires 57 | | "version", _ -> add `Version 58 | | _ -> acc 59 | 60 | 61 | let warn_def ~warned pkg = 62 | let haves = 63 | List.fold_left scan_def Have.Map.empty pkg.pkg_defs 64 | in 65 | let mem x = Have.Map.mem x haves in 66 | let find x = Have.Map.find x haves in 67 | let warning fmt = warned := true; Printf.printf fmt in 68 | let if_ ?has ?(has_not=[]) msg = 69 | match has, has_not with 70 | | Some has, [] when mem has -> 71 | warning "%a%s\n\n" print_def (find has) msg; 72 | | Some has, has_not when mem has && not (List.exists mem has_not) -> 73 | warning "%a%s\n\n" print_def (find has) msg; 74 | | None, has_not when not (List.exists mem has_not) -> 75 | warning "%s\n\n" msg; 76 | | _ -> () 77 | in 78 | if_ ~has_not:[`Description] 79 | "You should add a description."; 80 | if_ ~has_not:[`Version] 81 | "You should add a version."; 82 | if_ ~has_not:[`Requires] 83 | "You should add the required libraries. You can silent this \ 84 | warning by using the empty string."; 85 | if_ ~has:(`Mode(`TooMany)) 86 | "This variable should have only one mode 87 | (\"byte\", \"native\")."; 88 | if_ ~has:(`Mode(`None)) 89 | "This variable should have at least the predicate \ 90 | \"byte\" or \"native\"."; 91 | let with_mode mode = 92 | if_ ~has:(`Plugin (`Plugin,mode)) 93 | "You must not add the predicate \"plugin\" to the variable \ 94 | \"plugin\"."; 95 | if_ ~has:(`Archive (`Plugin,mode)) ~has_not:[`Plugin (`NoPlugin,mode)] 96 | "This specification of dynamic loading is deprecated, you should add a \ 97 | \"plugin(...)\" variable."; 98 | if_ ~has:(`Archive (`NoPlugin,mode)) 99 | ~has_not:[`Plugin (`NoPlugin,mode);`Archive (`Plugin,mode)] 100 | "This variable indicates how to link statically, you should add a \ 101 | \"plugin(...)\" variable for linking dynamically."; 102 | in 103 | with_mode `Byte; 104 | with_mode `Native 105 | 106 | let warn pkg = 107 | let warned = ref false in 108 | let rec aux pkg = 109 | warn_def ~warned pkg; 110 | List.iter (fun (_,pkg) -> aux pkg) pkg.pkg_children; 111 | in 112 | aux pkg; 113 | !warned 114 | -------------------------------------------------------------------------------- /src/findlib/fl_split.ml: -------------------------------------------------------------------------------- 1 | (* $Id$ 2 | * ---------------------------------------------------------------------- 3 | * 4 | *) 5 | 6 | 7 | let in_words s = 8 | (* splits s in words separated by commas and/or whitespace *) 9 | let l = String.length s in 10 | let rec split i j = 11 | if j < l then 12 | match s.[j] with 13 | (' '|'\t'|'\n'|'\r'|',') -> 14 | if i 17 | split i (j+1) 18 | else 19 | if i 32 | if i 35 | split i (j+1) 36 | else 37 | if i 52 | if i 55 | split i (j+1) 56 | else 57 | if i ':' 75 | | "Cygwin" -> ';' (* You might want to change this *) 76 | | "Win32" -> ';' 77 | | "MacOS" -> failwith "Findlib: I do not know what is the correct path separator for MacOS. If you can help me, write a mail to gerd@gerd-stolpmann.de" 78 | | _ -> failwith "Findlib: unknown operating system" 79 | ;; 80 | 81 | 82 | let path str = 83 | (* split "str" into parts separated by "path_separator" *) 84 | let l = String.length str in 85 | let rec split_up j k = 86 | if k < l then begin 87 | let c = str.[k] in 88 | if c = path_separator then begin 89 | if k - j > 0 then 90 | String.sub str j (k-j) :: split_up (k+1) (k+1) 91 | else 92 | split_up (k+1) (k+1) 93 | end 94 | else 95 | split_up j (k+1) 96 | end 97 | else 98 | if k - j > 0 then 99 | [ String.sub str j (k-j) ] 100 | else 101 | [] 102 | in 103 | split_up 0 0 104 | ;; 105 | 106 | 107 | let norm_dir s = 108 | (* Converts the file name of the directory [d] to the normal form. 109 | * For Unix, the '/' characters at the end are removed, and multiple 110 | * '/' are deleted. 111 | * For Windows, all '/' characters are converted to '\'. Two 112 | * backslashes at the beginning are tolerated. 113 | *) 114 | let b = Buffer.create 80 in 115 | let l = String.length s in 116 | let norm_dir_unix() = 117 | Buffer.add_char b s.[0]; 118 | for k = 1 to l - 1 do 119 | let c = s.[k] in 120 | if not ((c = '/' && s.[k-1] = '/') || (c = '/' && k = l-1)) then 121 | Buffer.add_char b c 122 | done 123 | in 124 | let is_slash = 125 | function 126 | | '/' | '\\' -> true 127 | | _ -> false in 128 | let norm_dir_win() = 129 | if l >= 1 && s.[0] = '/' then 130 | Buffer.add_char b '\\' else Buffer.add_char b s.[0]; 131 | if l >= 2 && s.[1] = '/' then 132 | Buffer.add_char b '\\' else Buffer.add_char b s.[1]; 133 | for k = 2 to l - 1 do 134 | let c = s.[k] in 135 | if is_slash c then ( 136 | if not (is_slash s.[k-1] || k = l-1) then 137 | Buffer.add_char b '\\' 138 | ) else 139 | Buffer.add_char b c 140 | done 141 | in 142 | match Sys.os_type with 143 | "Unix" | "BeOS" | "Cygwin" -> norm_dir_unix(); Buffer.contents b 144 | | "Win32" -> norm_dir_win(); Buffer.contents b 145 | | _ -> failwith "This os_type is not supported" 146 | ;; 147 | -------------------------------------------------------------------------------- /findlib.files: -------------------------------------------------------------------------------- 1 | # SYNTAX OF findlib.files: 2 | # 3 | # d DIRPATH 4 | # 5 | # include this subdirectory 6 | # 7 | # f FILEPATH 8 | # 9 | # include this file (or symlink) 10 | # 11 | # x FILEPATH 12 | # 13 | # exclude this file 14 | # 15 | # p DIRPATH/FILEPATTERN 16 | # 17 | # include all files of the directory that match the regular expression 18 | # FILEPATTERN (Str-type regexp) 19 | # 20 | # w DIRPATH/FILEPATTERN 21 | # 22 | # output a warning if one of the matching files matches 23 | # 24 | # Exclusions must be mentioned before inclusions. 25 | 26 | f configure 27 | f opam 28 | f ocamlfind.install 29 | f findlib.conf.in 30 | f INSTALL 31 | f LICENSE 32 | f Makefile 33 | f Makefile.config.pattern 34 | f itest 35 | f ocaml-stub 36 | 37 | d itest-aux 38 | f itest-aux/Makefile 39 | p itest-aux/.*\.ml 40 | 41 | d mini 42 | f mini/README 43 | f mini/ocamlfind-mini 44 | 45 | d tools 46 | f tools/collect_files 47 | f tools/file_exists 48 | d tools/extract_args 49 | f tools/extract_args/Makefile 50 | f tools/extract_args/extract_args.mll 51 | f tools/safe_camlp4 52 | f tools/make-package-macosx 53 | f tools/patch 54 | f tools/cmd_from_same_dir 55 | 56 | d site-lib-src 57 | d site-lib-src/bigarray 58 | f site-lib-src/bigarray/META.in 59 | f site-lib-src/bigarray/interfaces.in 60 | d site-lib-src/camlp4.309 61 | f site-lib-src/camlp4.309/META.in 62 | d site-lib-src/camlp4.310 63 | f site-lib-src/camlp4.310/META.in 64 | d site-lib-src/dbm 65 | f site-lib-src/dbm/META.in 66 | f site-lib-src/dbm/interfaces.in 67 | d site-lib-src/dynlink 68 | f site-lib-src/dynlink/META.in 69 | f site-lib-src/dynlink/interfaces.in 70 | d site-lib-src/graphics 71 | f site-lib-src/graphics/META.in 72 | f site-lib-src/graphics/interfaces.in 73 | d site-lib-src/labltk 74 | f site-lib-src/labltk/META.in 75 | f site-lib-src/labltk/interfaces.in 76 | d site-lib-src/num 77 | f site-lib-src/num/META.in 78 | f site-lib-src/num/interfaces.in 79 | d site-lib-src/num-top 80 | f site-lib-src/num-top/META.in 81 | d site-lib-src/stdlib 82 | f site-lib-src/stdlib/META.in 83 | f site-lib-src/stdlib/interfaces.in 84 | d site-lib-src/str 85 | f site-lib-src/str/META.in 86 | f site-lib-src/str/interfaces.in 87 | d site-lib-src/threads 88 | f site-lib-src/threads/META.in 89 | f site-lib-src/threads/interfaces.in 90 | d site-lib-src/unix 91 | f site-lib-src/unix/META.in 92 | f site-lib-src/unix/interfaces.in 93 | d site-lib-src/ocamlbuild 94 | f site-lib-src/ocamlbuild/META.in 95 | d site-lib-src/ocamldoc 96 | f site-lib-src/ocamldoc/META.in 97 | d site-lib-src/compiler-libs 98 | f site-lib-src/compiler-libs/META.in 99 | d site-lib-src/bytes 100 | f site-lib-src/bytes/META.in 101 | f site-lib-src/bytes/interfaces.in 102 | d site-lib-src/raw_spacetime 103 | f site-lib-src/raw_spacetime/interfaces.in 104 | f site-lib-src/raw_spacetime/META.in 105 | 106 | 107 | d src 108 | 109 | d src/findlib 110 | f src/findlib/Makefile 111 | f src/findlib/META.in 112 | f src/findlib/findlib_config.mlp 113 | f src/findlib/topfind.ml.in 114 | x src/findlib/fl_meta.ml 115 | x src/findlib/findlib_config.ml 116 | x src/findlib/ocaml_args.ml 117 | x src/findlib/topfind.ml 118 | p src/findlib/.*\.ml 119 | p src/findlib/.*\.mli 120 | p src/findlib/.*\.mll 121 | p src/findlib/.*\.src 122 | p src/findlib/.*\.p 123 | 124 | d src/findlib-toolbox 125 | f src/findlib-toolbox/Makefile 126 | f src/findlib-toolbox/make_wizard.ml 127 | f src/findlib-toolbox/make_wizard.pattern 128 | 129 | d src/bytes 130 | f src/bytes/Makefile 131 | f src/bytes/README 132 | f src/bytes/bytes.ml 133 | f src/bytes/META 134 | 135 | d doc 136 | f doc/DOCINFO 137 | f doc/QUICKSTART 138 | f doc/README 139 | p doc/.*\.xml 140 | p doc/.*\.dtd 141 | f doc/Makefile 142 | 143 | d doc/guide-html 144 | f doc/guide-html/index.html 145 | p doc/guide-html/.*\.html 146 | f doc/guide-html/TIMESTAMP 147 | 148 | d doc/ref-html 149 | d doc/ref-html/lib 150 | f doc/ref-html/index.html 151 | p doc/ref-html/.*\.html 152 | f doc/ref-html/TIMESTAMP 153 | f doc/ref-html/lib/index.html 154 | p doc/ref-html/lib/.*\.html 155 | p doc/ref-html/lib/.*\.css 156 | 157 | d doc/ref-man 158 | f doc/ref-man/ocamlfind.1 159 | f doc/ref-man/findlib.conf.5 160 | f doc/ref-man/META.5 161 | f doc/ref-man/site-lib.5 162 | f doc/ref-man/TIMESTAMP 163 | 164 | d doc/src 165 | p doc/src/.*\.dsl 166 | p doc/src/.*\.mod 167 | p doc/src/.*\.sgml 168 | p doc/src/.*\.xml 169 | 170 | 171 | -------------------------------------------------------------------------------- /src/findlib/topfind.mli: -------------------------------------------------------------------------------- 1 | (* $Id$ 2 | * ---------------------------------------------------------------------- 3 | * 4 | *) 5 | 6 | (** Load packages from toploops and scripts 7 | * 8 | * The [Topfind] module is part of the [findlib] package. The module 9 | * depends on the presence of a toploop. When building a toploop, it is 10 | * automatically linked in if "findlib" is linked in, e.g. 11 | * {[ 12 | * ocamlfind ocamlmktop ...options... -package findlib -linkpkg 13 | * ]} 14 | * 15 | * When the platform supports DLLs, another possibility to get a toploop 16 | * with findlib directives is to load the file "topfind" (normally installed 17 | * in the standard library directory): 18 | * {[ 19 | * $ ocaml 20 | * Objective Caml version 3.04 21 | * # #use "topfind";; 22 | * Findlib has been successfully loaded. Additional directives: 23 | * #require "package";; to load a package 24 | * #list;; to list the available packages 25 | * #camlp4o;; to load camlp4 (standard syntax) 26 | * #camlp4r;; to load camlp4 (revised syntax) 27 | * Topfind.reset();; to force that packages will be reloaded 28 | * ~ : unit = () 29 | * # _ 30 | * ]} 31 | * 32 | * This works even in scripts (but the startup message is suppressed in this 33 | * case). 34 | * 35 | * The module is not thread-safe; if used in a multi-threaded script, all 36 | * packgage loading must have happened before the first thread forks. 37 | * 38 | * The Topfind module contains some functions simplifying package loading 39 | * in scripts. Most important, there is a new directive [#require] for 40 | * the same purpose (see below). 41 | * 42 | * The [Topfind] module needs some initialization, in particular the 43 | * [predicates] variable needs to be 44 | * set, and the packages already compiled into the toploop needs to be 45 | * declared by the [don't_load] 46 | * function. If the toploop has been built by [ocamlfind], 47 | * the necessary initialization is 48 | * automatically compiled in. 49 | *) 50 | 51 | (** {1 Directives} 52 | * 53 | * This module also defines the following directives for the toploop: 54 | * 55 | * - [#require ""] 56 | * loads the package (and if necessary the prerequisites of the package) 57 | * - [#camlp4o] 58 | * loads camlp4 and selects standard syntax 59 | * - [#camlp4r] 60 | * loads camlp4 and selects revised syntax 61 | * - [#list] 62 | * lists the available packages (calls external command "ocamlfind") 63 | * - [#thread] 64 | * enables multi-threading if possible 65 | * - [#predicates "p1,p2,..."] 66 | * adds these predicates 67 | *) 68 | 69 | (** {1 Functions and variables} *) 70 | 71 | val predicates : string list ref 72 | (** The list of predicates used for package loading *) 73 | 74 | val add_predicates : string list -> unit 75 | (** Adds predicates to the list of predicates *) 76 | 77 | val syntax : string -> unit 78 | (** Emulates the [-syntax] option *) 79 | 80 | val standard_syntax : unit -> unit 81 | (** Adds predicates that select the standard syntax. Same as 82 | * [syntax "camlp4o"] 83 | *) 84 | 85 | val revised_syntax : unit -> unit 86 | (** Adds predicates that select the revised syntax. Same as 87 | * [syntax "camlp4r"] 88 | *) 89 | 90 | val don't_load : string list -> unit 91 | (** The packages named in pkglist are added to the list of packages which 92 | * are already loaded. 93 | *) 94 | 95 | val don't_load_deeply : string list -> unit 96 | (** The packages named in pkglist and all direct and indirect ancestors 97 | * are added to the list of packages which are already loaded. 98 | *) 99 | 100 | val load : string list -> unit 101 | (** The packages from the passed package list are loaded, from left to 102 | * right, but packages that have already been loaded are left out. 103 | *) 104 | 105 | val load_deeply : string list -> unit 106 | (** The packages from the passed package list and all direct or indirect 107 | * ancestors are loaded in topological order. Packages that have already 108 | * been loaded are left out. 109 | *) 110 | 111 | val reset : unit -> unit 112 | (** All entries in the list of loaded packages that have been added by 113 | * [load] or [load_deeply] functions are removed from this list. This 114 | * means that if you execute the same [load] or [load_deeply] functions 115 | * again, the packages will be reloaded. 116 | *) 117 | 118 | val announce : unit -> unit 119 | (** Output the startup message *) 120 | 121 | val log : (string -> unit) ref 122 | (** Function used to log messages from this module. *) 123 | -------------------------------------------------------------------------------- /tools/make-package-macosx: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Shell script from Pietro Abate to create 4 | # Mac OS X packages. Call from Makefile by "make package-macosx". 5 | 6 | ######################################################################### 7 | # # 8 | # Objective Caml # 9 | # # 10 | # Damien Doligez, projet Moscova, INRIA Rocquencourt # 11 | # # 12 | # Copyright 2003 Institut National de Recherche en Informatique et # 13 | # en Automatique. All rights reserved. This file is distributed # 14 | # under the terms of the Q Public License version 1.0. # 15 | # # 16 | ######################################################################### 17 | 18 | # $Id: make-package-macosx,v 1.10.2.2 2006/01/04 13:05:49 doligez Exp $ 19 | # adapted to findlib by Pietro.Abate 20 | 21 | set -x 22 | 23 | cd package-macosx 24 | rm -rf findlib.pkg findlib-rw.dmg 25 | mkdir -p resources 26 | 27 | cat >Description.plist < 29 | 31 | 32 | 33 | IFPkgDescriptionDeleteWarning 34 | 35 | IFPkgDescriptionDescription 36 | The findlib library manager 37 | IFPkgDescriptionTitle 38 | Findlib 39 | IFPkgDescriptionVersion 40 | ${VERSION} 41 | 42 | 43 | EOF 44 | 45 | cat >Info.plist < 47 | 49 | 50 | 51 | CFBundleGetInfoString 52 | The findlib library manager ${VERSION} 53 | CFBundleIdentifier 54 | http://www.ocaml-programming.de/packages/ 55 | CFBundleName 56 | Findlib 57 | CFBundleShortVersionString 58 | ${VERSION} 59 | IFPkgFlagAllowBackRev 60 | 61 | IFPkgFlagAuthorizationAction 62 | AdminAuthorization 63 | IFPkgFlagDefaultLocation 64 | / 65 | IFPkgFlagInstallFat 66 | 67 | IFPkgFlagIsRequired 68 | 69 | IFPkgFlagRelocatable 70 | 71 | IFPkgFlagRestartAction 72 | NoRestart 73 | IFPkgFlagRootVolumeOnly 74 | 75 | IFPkgFlagUpdateInstalledLanguages 76 | 77 | IFPkgFormatVersion 78 | 0.10000000149011612 79 | 80 | 81 | EOF 82 | 83 | # stop here -> | 84 | cat >resources/ReadMe.txt <&2 116 | exit 3 117 | fi 118 | open "/Volumes/Findlib" 119 | hdiutil detach $name 120 | 121 | rm -rf "findlib-${VERSION}.dmg" 122 | hdiutil convert findlib-rw.dmg -format UDZO -o "findlib-${VERSION}.dmg" 123 | -------------------------------------------------------------------------------- /doc/src/findlib_sitelib.mod: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | site-lib 5 | 5 6 | The findlib package manager for OCaml 7 | 8 | 9 | 10 | site-lib 11 | [Location of package directories] 12 | 13 | 14 | 15 | 16 | STANDARD LAYOUT 17 | 18 | ...somewhere in the filesystem hierarchy... 19 | | 20 | \ 21 | site-lib 22 | | 23 | +- (optional) stublibs 24 | +- (optional) postinstall 25 | +- (optional) postremove 26 | | 27 | +- package1 28 | | | 29 | | +- META 30 | | +- archive files 31 | | +- interface definitions 32 | | 33 | +- package2 34 | + 35 | : 36 | : 37 | \ 38 | packageN 39 | 40 | 41 | 42 | 43 | DESCRIPTION 44 | 45 | Every installation of "findlib" has a default location for package 46 | directories, which is normally a directory called "site-lib". The 47 | location can be set by the configuration variables 48 | path (used to look up packages), and 49 | destdir (used to install new packages); 50 | see findlib.conf. 51 | 52 | 53 | 54 | The name of a package is the name of the package directory. For 55 | example, if destdir=/usr/local/lib/ocaml/site-lib, the 56 | package p will be installed in the subdirectory 57 | /usr/local/lib/ocaml/site-lib/p. This subdirectory 58 | must contain the META file and all other files belonging to the package. 59 | Package names must not contain the '.' character. 60 | 61 | 62 | 63 | The variable destdir specifies the directory for 64 | new packages. You can only have one such directory at a time; but of 65 | course you can change this directory in findlib.conf. The command 66 | ocamlfind install puts new packages into this 67 | directory; it is recommended to use this command for installation 68 | because it ensures that the directory layout is right. 69 | 70 | 71 | 72 | For searching packages, findlib uses (only) the variable 73 | path which may name several locations to look at. 74 | 75 | 76 | 77 | For systems with DLL support another directory may exist: stublibs. 78 | If present, findlib will install DLLs into this directory that is 79 | shared by all packages at the same site-lib location. Findlib remembers 80 | which DLL belongs to which package by special files with the suffix 81 | ".owner"; e.g. for the DLL "dllpcre.so" there is another file 82 | "dllpcre.so.owner" containing the string "pcre", so findlib knows 83 | that the package "pcre" owns this DLL. It is not possible that a DLL 84 | is owned by several packages. 85 | 86 | 87 | 88 | If the stublibs directory does not exist, DLLs are installed regularly 89 | in the package directories like any other file. 90 | 91 | 92 | 93 | For special needs, a postinstall and/or a postremove script may be 94 | installed in the site-lib directory. These scripts are invoked after 95 | installation or removal of a package, respectively. 96 | 97 | 98 | 99 | 100 | 101 | 102 | ALTERNATE LAYOUT 103 | 104 | 105 | 106 | ...somewhere in the filesystem hierarchy... 107 | | 108 | \ 109 | site-lib 110 | | 111 | +- (optional) stublibs 112 | +- (optional) postinstall 113 | +- (optional) postremove 114 | | 115 | +- package1 116 | | | 117 | | +- archive files 118 | | +- interface definitions 119 | | 120 | +- package2 121 | + 122 | : 123 | : 124 | \ 125 | : packageN 126 | | 127 | \ 128 | metaregistry 129 | | 130 | +- META.package1 131 | +- META.package2 132 | + 133 | : 134 | \ 135 | META.packageN 136 | 137 | 138 | 139 | 140 | This is an alternate directory layout collecting all META files in one 141 | directory. You can configure this layout by setting 142 | path to the absolute location of 143 | metaregistry. Findlib recognizes that there are 144 | META files in this directory and uses them; it is not necessary to 145 | include site-lib into the path. 146 | 147 | 148 | 149 | In order to work, the META files must contain a 150 | directory directive pointing to the corresponding 151 | package directory that resides below site-lib. 152 | 153 | 154 | 155 | The command ocamlfind install copes with this 156 | layout, too. The variable destdir must contain the 157 | absolute location of site-lib, and the variable 158 | metadir must contain the absolute location of 159 | metaregistry. Note that ocamlfind 160 | install automatically adds a directory 161 | directive to the META file, so you need not do it manually. 162 | 163 | 164 | 165 | 166 | -------------------------------------------------------------------------------- /site-lib-src/camlp4.310/META.in: -------------------------------------------------------------------------------- 1 | # Specifications for the "camlp4" preprocessor: 2 | requires = "" 3 | version = "[distributed with Ocaml]" 4 | description = "Base for Camlp4 syntax extensions" 5 | directory = "+camlp4" 6 | 7 | # For the toploop: 8 | requires(byte,toploop) = "%%camlp4_dynlink%%" 9 | archive(byte,toploop,camlp4o) = "camlp4o.cma" 10 | archive(byte,toploop,camlp4r) = "camlp4r.cma" 11 | 12 | # For the preprocessor itself: 13 | archive(syntax,preprocessor,camlp4o) = "-parser o -parser op -printer p" 14 | archive(syntax,preprocessor,camlp4r) = "-parser r -parser rp -printer p" 15 | preprocessor = "%%camlp4_cmd%%" 16 | 17 | package "lib" ( 18 | requires = "camlp4 %%camlp4_dynlink%%" 19 | version = "[distributed with Ocaml]" 20 | description = "Camlp4 library" 21 | archive(byte) = "camlp4lib.cma" 22 | archive(byte,toploop) = "" # already contained in camlp4*.cma 23 | archive(native) = "camlp4lib.cmxa" 24 | ) 25 | 26 | package "gramlib" ( 27 | requires = "camlp4.lib" 28 | version = "[distributed with Ocaml]" 29 | description = "Compatibilty name for camlp4.lib" 30 | ) 31 | 32 | # don't use camlp4.lib and camlp4.fulllib together 33 | package "fulllib" ( 34 | requires = "camlp4 %%camlp4_dynlink%%" 35 | version = "[distributed with Ocaml]" 36 | description = "Camlp4 library" 37 | error(pkg_camlp4.lib) = "camlp4.lib and camlp4.fulllib are incompatible" 38 | archive(byte) = "camlp4fulllib.cma" 39 | archive(byte,toploop) = "" # already contained in camlp4*.cma 40 | archive(native) = "camlp4fulllib.cmxa" 41 | ) 42 | 43 | package "quotations" ( 44 | version = "[distributed with Ocaml]" 45 | description = "Syntax extension: Quotations to create AST nodes" 46 | requires = "camlp4.quotations.r" # backward compat 47 | # We must have a non-empty archive, otherwise this pkg is ignored 48 | # for constructing the preprocessor command. We can pass -ignore arg 49 | # to camlp4 as dummy argument: 50 | archive(syntax,preprocessor) = "-ignore foo" 51 | package "o" ( 52 | requires = "camlp4" 53 | version = "[distributed with Ocaml]" 54 | description = "Syntax extension: Quotations to create AST nodes (original syntax)" 55 | archive(syntax,preprocessor) = "-parser Camlp4QuotationCommon -parser Camlp4OCamlOriginalQuotationExpander" 56 | archive(syntax,toploop) = "Camlp4Parsers/Camlp4QuotationCommon.cmo Camlp4Parsers/Camlp4OCamlOriginalQuotationExpander.cmo" 57 | ) 58 | package "r" ( 59 | requires = "camlp4" 60 | version = "[distributed with Ocaml]" 61 | description = "Syntax extension: Quotations to create AST nodes (revised syntax)" 62 | archive(syntax,preprocessor) = "-parser Camlp4QuotationCommon -parser Camlp4OCamlRevisedQuotationExpander" 63 | archive(syntax,toploop) = "Camlp4Parsers/Camlp4QuotationCommon.cmo Camlp4Parsers/Camlp4OCamlRevisedQuotationExpander.cmo" 64 | ) 65 | ) 66 | 67 | package "extend" ( 68 | requires = "camlp4" 69 | version = "[distributed with Ocaml]" 70 | description = "Syntax extension: EXTEND the camlp4 grammar" 71 | archive(syntax,preprocessor) = "-parser Camlp4GrammarParser" 72 | archive(syntax,toploop) = "Camlp4Parsers/Camlp4GrammarParser.cmo" 73 | ) 74 | 75 | package "listcomprehension" ( 76 | requires = "camlp4" 77 | version = "[distributed with Ocaml]" 78 | description = "Syntax extension for list comprehensions" 79 | archive(syntax,preprocessor) = "-parser Camlp4ListComprehension" 80 | archive(syntax,toploop) = "Camlp4Parsers/Camlp4ListComprehension.cmo" 81 | ) 82 | 83 | package "macro" ( 84 | requires = "camlp4" 85 | version = "[distributed with Ocaml]" 86 | description = "Syntax extension: Conditional compilation" 87 | archive(syntax,preprocessor) = "-parser Camlp4MacroParser" 88 | archive(syntax,toploop) = "Camlp4Parsers/Camlp4MacroParser.cmo" 89 | ) 90 | 91 | package "mapgenerator" ( 92 | requires = "camlp4" 93 | version = "[distributed with Ocaml]" 94 | description = "Syntax filter: Traverse data structure (map style)" 95 | archive(syntax,preprocessor) = "-filter Camlp4MapGenerator" 96 | archive(syntax,toploop) = "Camlp4Filters/Camlp4MapGenerator.cmo" 97 | ) 98 | 99 | package "foldgenerator" ( 100 | requires = "camlp4" 101 | version = "[distributed with Ocaml]" 102 | description = "Syntax filter: Traverse data structure (fold style)" 103 | archive(syntax,preprocessor) = "-filter Camlp4FoldGenerator" 104 | archive(syntax,toploop) = "Camlp4Filters/Camlp4FoldGenerator.cmo" 105 | ) 106 | 107 | package "metagenerator" ( 108 | requires = "camlp4" 109 | version = "[distributed with Ocaml]" 110 | description = "Syntax filter: Generate AST generator for data structure" 111 | archive(syntax,preprocessor) = "-filter Camlp4MetaGenerator" 112 | archive(syntax,toploop) = "Camlp4Filters/Camlp4MetaGenerator.cmo" 113 | ) 114 | 115 | package "locationstripper" ( 116 | requires = "camlp4" 117 | version = "[distributed with Ocaml]" 118 | description = "Syntax filter: Remove location info from AST" 119 | archive(syntax,preprocessor) = "-filter Camlp4LocationStripper" 120 | archive(syntax,toploop) = "Camlp4Filters/Camlp4LocationStripper.cmo" 121 | ) 122 | 123 | package "tracer" ( 124 | requires = "camlp4" 125 | version = "[distributed with Ocaml]" 126 | description = "Syntax filter: Trace execution" 127 | archive(syntax,preprocessor) = "-filter Camlp4Tracer" 128 | archive(syntax,toploop) = "Camlp4Filters/Camlp4Tracer.cmo" 129 | ) 130 | 131 | package "exceptiontracer" ( 132 | requires = "camlp4" 133 | version = "[distributed with Ocaml]" 134 | description = "Syntax filter: Trace exception execution" 135 | archive(syntax,preprocessor) = "-filter Camlp4ExceptionTracer" 136 | archive(syntax,toploop) = "Camlp4Filters/Camlp4ExceptionTracer.cmo" 137 | ) 138 | 139 | package "profiler" ( 140 | requires = "camlp4" 141 | version = "[distributed with Ocaml]" 142 | description = "Syntax filter: Count events during execution" 143 | archive(syntax,preprocessor) = "-filter Camlp4Profiler" 144 | archive(syntax,toploop) = "Camlp4Filters/Camlp4Profiler.cmo" 145 | archive(byte) = "camlp4prof.cmo" 146 | archive(native) = "camlp4prof.cmx" 147 | ) 148 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | The installation procedure consists of the steps: 2 | 3 | 1) configure the "findlib" library 4 | 2) compile "findlib" and the "ocamlfind" frontend of "findlib" 5 | 3) install "findlib" and the core library configuration 6 | 7 | Optionally, you can run ./itest after step 2 to check the 8 | configuration. Problems with the configuration are unlikely, however. 9 | 10 | At the end of this file you find notes about MacOS and Windows. 11 | 12 | 13 | ---------------------------------------------------------------------- 14 | 15 | STEP 1: DEFAULT CONFIGURATION 16 | 17 | The findlib module and its ocamlfind frontend come with a "configure" 18 | script that should almost always be able to figure out a good 19 | configuration. 20 | 21 | Just type: 22 | 23 | ./configure 24 | 25 | First the linker options for the various core libraries are figured 26 | out, then reasonable installation paths are checked. 27 | 28 | If the results are not ok, you can modify them using the following 29 | options: 30 | 31 | -bindir 32 | 33 | set the location where the ocamlfind command should be 34 | installed. 35 | Default: same location as "ocamlc" 36 | 37 | -mandir 38 | 39 | set the location where the man page should be installed. 40 | Default: a heuristics, and "/usr/local/man" as fallback. 41 | 42 | -sitelib 43 | 44 | set the default "site-lib" directory. 45 | Default: For installations in the /usr hierarchy, 46 | "$stdlib/site-lib", where $stdlib is the location of 47 | Ocaml's standard library. 48 | 49 | For installations in the /opt hierarchy, 50 | "$stdlib/../site-lib", i.e. parallel to $stdlib. 51 | 52 | -config 53 | 54 | set the location of the configuration file. 55 | Default: /../etc/findlib.conf 56 | 57 | -no-topfind 58 | 59 | the "topfind" script is not installed in the standard 60 | library directory. (This is not a good idea in general, 61 | because #use "topfind" will not work when this option 62 | is enabled.) 63 | 64 | -with-toolbox 65 | also compile and install the "toolbox". This requires 66 | that labltk is available. The toolbox contains the 67 | "make_wizard" to easily create findlib-enabled Makefiles. 68 | 69 | -cygpath 70 | Cygwin environment only: If "ocamlc -where" does not 71 | output a Unix-style path, this option can be used 72 | to apply the "cygpath" command to it. Use this option 73 | if you see backslashes or drive letters in Makefile.config. 74 | 75 | ALTERNATIVES: 76 | 77 | If the "configure" script does not work properly (very unlikely), do 78 | 79 | cp Makefile.config.pattern Makefile.config 80 | 81 | and edit Makefile.config by hand. 82 | 83 | If the generated META files do not work, edit them (this is very very unlikely). 84 | 85 | Note: The META files are generated from the META.in files in the same 86 | directories by sed: 87 | 88 | sed -e 's/%%os%%//g' site-lib//META.in 89 | >site-lib//META 90 | 91 | You may invoke sed manually to create different META files, but this 92 | is currently not documented. 93 | 94 | 95 | 96 | ---------------------------------------------------------------------- 97 | 98 | STEP 2: COMPILATION 99 | 100 | After configuration has been done, compile with 101 | 102 | make all 103 | 104 | This creates findlib.cma, findlib_mt.cma (the thread-safe version), 105 | and ocamlfind. 106 | 107 | If you have ocamlopt, do also 108 | 109 | make opt 110 | 111 | This creates findlib.cmxa, findlib_mt.cmxa, and ocamlfind_opt. 112 | 113 | ---------------------------------------------------------------------- 114 | 115 | STEP 3: INSTALLATION 116 | 117 | Install the findlib library, the ocamlfind frontend, and the core library 118 | configurations with: 119 | 120 | make install 121 | 122 | (A "make uninstall" removes them.) 123 | 124 | With 125 | make clean 126 | 127 | the build directory is cleaned up. 128 | 129 | 130 | OPTIONAL (BUT RECOMMENDED): 131 | 132 | If you want a separate directory for DLLs, create this directory 133 | now: 134 | 135 | mkdir `ocamlfind printconf destdir`/stublibs 136 | 137 | If you do this, you must also tell OCaml that DLLs can be found in 138 | this directory: Add the absolute path of this directory to 139 | the ld.conf file (type "ocamlfind printconf ldconf" to get the 140 | location of the ld.conf file). Every line of this text file lists 141 | one possible directory for DLLs. 142 | 143 | ---------------------------------------------------------------------- 144 | 145 | MACOS X: 146 | 147 | Findlib can be installed as described. There is even a script to 148 | create a MacOS X package, use "make package-macosx" to invoke it. As I 149 | do not have access to a Mac box, I cannot test this script, but I 150 | fully trust the author that it works. 151 | 152 | ---------------------------------------------------------------------- 153 | 154 | WINDOWS: 155 | 156 | Ocaml for Windows exists in three flavours: 157 | 158 | (1) Ocaml as Cygwin program 159 | (2) Ocaml as Mingw program (i.e. the gcc toolchain is used but 160 | Ocaml is a native Windows program) 161 | (3) Ocaml as VC program 162 | 163 | In all three cases you need Cygwin to build and install findlib, 164 | because "configure" and the Makefile are both Cygwin scripts. The 165 | golden rule to make everything work is this: 166 | 167 | PASS CYGWIN-STYLE PATHS TO CONFIGURE! 168 | 169 | Even in cases (2) and (3)! That means use something like 170 | /cygdrive/c/path and not c:\path when you specify where -bindir, 171 | -config etc. are. The point is that "configure" itself is a Cygwin 172 | script, and therefore expects Cygwin input. At the right moment, the 173 | paths are back-translated to their Windows counterparts. 174 | 175 | Until OCaml 3.08 you must specify whether you have (2) or (3) by 176 | the configure switches 177 | 178 | - "-system mingw" for (2) 179 | - "-system win32" for (3) 180 | - nothing for (1) 181 | 182 | Since OCaml 3.09 this is no longer necessary because "ocamlc -config" 183 | outputs the required information. 184 | 185 | In previous versions of Findlib there was a single switch -cygpath 186 | for both (2) and (3). It is now interpreted as -system mingw (as 187 | it was meant as that). 188 | -------------------------------------------------------------------------------- /doc/src/findlib_mli.mod: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Findlib 5 | 3 6 | The findlib package manager for OCaml 7 | 8 | 9 | 10 | Findlib 11 | [Module for package management] 12 | 13 | 14 | 15 | 16 | SIGNATURE 17 | 18 | module Findlib : 19 | sig 20 | 22 | 24 | 26 | 28 | 30 | 31 | (* Note: This signature is incomplete. See findlib.mli for the 32 | * full signature. 33 | *) 34 | 35 | end 36 | 37 | 38 | 39 | 40 | 41 | PACKAGING 42 | 43 | 44 | The Findlib module is part of the "findlib" package. In order to link 45 | it in, it is sufficient to link "findlib" in, e.g. 46 | 47 | 48 | 49 | ocamlfind ocamlc options -package findlib -linkpkg options 50 | 51 | 52 | 53 | There are archives for the bytecode compiler and for the native 54 | compiler; for single-threaded and for multi-threaded applications, and 55 | there is a special addition for toploops. 56 | 57 | 58 | 59 | 60 | 61 | DESCRIPTION 62 | 63 | 64 | The Findlib module is the primary interface of the findlib library. It 65 | contains functions to lookup packages, to interpret files, and to determine the ancestors of 67 | packages. 68 | 69 | 70 | 71 | 72 | <anchor id="Findlib.package-directory"> 73 | Findlib.package_directory <replaceable>pkg</replaceable> 74 | 75 | val package_directory : string -> string 76 | 77 | 78 | Gets the absolute path of the directory where the package 79 | pkg is stored. The exception Not_found is 80 | raised if the package could not be found. 81 | Other exceptions may occur as file I/O is done. 82 | 83 | 84 | 85 | 86 | 87 | 88 | <anchor id="Findlib.package-property"> 89 | Findlib.package_property <replaceable>predicates</replaceable> 90 | <replaceable>pkg</replaceable> <replaceable>variable</replaceable> 91 | 92 | 93 | val package_property : string list -> string -> string -> string 94 | 95 | 96 | Determines the value of the variable 97 | defined in the file of package 98 | pkg with the given set of 99 | predicates. The exception Not_found is 100 | raised if the package or the variable could not be found. Other 101 | exceptions may occur as file I/O is done. 102 | 103 | 104 | Examples 105 | 106 | Get the value of the "requires" variable of package "p" with an empty 107 | set of predicates: 108 | 109 | 110 | Findlib.package_property [] "p" "requires" 111 | 112 | 113 | Get the value of the "archive" variable of package "p" for 114 | multi-threaded bytecode applications: 115 | 116 | 117 | Findlib.package_property [ "mt"; "byte" ] "p" "archive" 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | <anchor id="Findlib.package-ancestors"> 126 | Findlib.package_ancestors <replaceable>predicates</replaceable> 127 | <replaceable>pkg</replaceable> 128 | 129 | 130 | val package_ancestors : string list -> string -> string list 131 | 132 | 133 | Determines the direct ancestors of package 134 | pkg for the set of 135 | predicates. The returned list has no 136 | specific order. The exception Not_found is raised if the package could 137 | not be found. The exception Failure is raised if one of the ancestors 138 | could not be found, or if a circular dependency has been 139 | detected. Other exceptions may occur as file I/O is done. 140 | 141 | 142 | 143 | 144 | 145 | 146 | <anchor id="Findlib.package-deep-ancestors"> 147 | Findlib.package_deep_ancestors <replaceable>predicates</replaceable> 148 | <replaceable>pkglist</replaceable> 149 | 150 | 151 | val package_deep_ancestors : string list -> string list -> string list 152 | 153 | 154 | Determines the list of direct or indirect ancestors of the packages in 155 | pkglist for the set of 156 | predicates. The returned list is 157 | topologically sorted. 158 | The exception Not_found is raised if the package could 159 | not be found. The exception Failure is raised if one of the ancestors 160 | could not be found, or if a circular dependency has been 161 | detected. Other exceptions may occur as file I/O is done. 162 | 163 | 164 | 165 | 166 | 167 | 168 | <anchor id="Findlib.default-location"> 169 | Findlib.default_location () 170 | 171 | val default_location : unit -> string 172 | 173 | 174 | Gets the default location where new packages will be installed. 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # make all: compile to bytecode 2 | # make opt: compile to native code 3 | # make install: install bytecode and/or native code 4 | #---------------------------------------------------------------------- 5 | 6 | include Makefile.config 7 | -include Makefile.packages 8 | 9 | TOP=. 10 | 11 | .PHONY: all opt install uninstall clean 12 | 13 | all: 14 | for p in $(PARTS); do ( cd src/$$p; $(MAKE) all ) || exit; done 15 | $(MAKE) all-config 16 | 17 | opt: 18 | for p in $(PARTS); do ( cd src/$$p; $(MAKE) opt ) || exit; done 19 | 20 | install: check-installation 21 | $(INSTALLDIR) "$(DESTDIR)$(prefix)$(OCAMLFIND_BIN)" 22 | $(INSTALLDIR) "$(DESTDIR)$(prefix)$(OCAMLFIND_MAN)" 23 | $(MAKE) install-config 24 | for p in $(PARTS); do ( cd src/$$p; $(MAKE) install ); done 25 | $(MAKE) install-meta 26 | test ! -f 'site-lib-src/num-top/META' || { cd src/findlib; $(MAKE) install-num-top; } 27 | test ! -f 'site-lib-src/camlp4/META' || $(INSTALLFILE) tools/safe_camlp4 "$(DESTDIR)$(prefix)$(OCAMLFIND_BIN)" 28 | $(MAKE) install-doc 29 | 30 | uninstall: check-installation 31 | $(MAKE) uninstall-doc 32 | $(MAKE) uninstall-meta 33 | for p in `cd src; echo *`; do ( cd src/$$p; $(MAKE) uninstall ); done 34 | $(MAKE) uninstall-config 35 | 36 | clean: 37 | for p in `cd src; echo *`; do ( cd src/$$p; $(MAKE) clean ); done 38 | (cd itest-aux; $(MAKE) clean) 39 | (cd tools/extract_args; $(MAKE) clean) 40 | rm -f findlib.conf Makefile.packages 41 | 42 | .PHONY: release 43 | release: README 44 | ./release 45 | 46 | README: doc/README 47 | ln -s doc/README . 48 | 49 | 50 | .PHONY: all-config 51 | all-config: findlib.conf 52 | 53 | findlib.conf: findlib.conf.in 54 | USE_CYGPATH="$(USE_CYGPATH)"; \ 55 | export USE_CYGPATH; \ 56 | cat findlib.conf.in | \ 57 | $(SH) tools/patch '@SITELIB@' '$(OCAML_SITELIB)' | \ 58 | $(SH) tools/patch '@FINDLIB_PATH@' '$(FINDLIB_PATH)' -p >findlib.conf 59 | if ./tools/cmd_from_same_dir ocamlc; then \ 60 | echo 'ocamlc="ocamlc.opt"' >>findlib.conf; \ 61 | fi 62 | if ./tools/cmd_from_same_dir ocamlopt; then \ 63 | echo 'ocamlopt="ocamlopt.opt"' >>findlib.conf; \ 64 | fi 65 | if ./tools/cmd_from_same_dir ocamldep; then \ 66 | echo 'ocamldep="ocamldep.opt"' >>findlib.conf; \ 67 | fi 68 | if ./tools/cmd_from_same_dir ocamldoc; then \ 69 | echo 'ocamldoc="ocamldoc.opt"' >>findlib.conf; \ 70 | fi 71 | 72 | .PHONY: install-doc 73 | install-doc: 74 | $(INSTALLDIR) "$(DESTDIR)$(prefix)$(OCAMLFIND_MAN)/man1" "$(DESTDIR)$(prefix)$(OCAMLFIND_MAN)/man3" "$(DESTDIR)$(prefix)$(OCAMLFIND_MAN)/man5" 75 | -$(INSTALLFILE) doc/ref-man/ocamlfind.1 "$(DESTDIR)$(prefix)$(OCAMLFIND_MAN)/man1" 76 | -$(INSTALLFILE) doc/ref-man/META.5 doc/ref-man/site-lib.5 doc/ref-man/findlib.conf.5 "$(DESTDIR)$(prefix)$(OCAMLFIND_MAN)/man5" 77 | 78 | .PHONY: uninstall-doc 79 | uninstall-doc: 80 | rm -f "$(DESTDIR)$(prefix)$(OCAMLFIND_MAN)/man1/ocamlfind.1" 81 | rm -f "$(DESTDIR)$(prefix)$(OCAMLFIND_MAN)/man3/Findlib.3" 82 | rm -f "$(DESTDIR)$(prefix)$(OCAMLFIND_MAN)/man3/Topfind.3" 83 | rm -f "$(DESTDIR)$(prefix)$(OCAMLFIND_MAN)/man5/META.5" 84 | rm -f "$(DESTDIR)$(prefix)$(OCAMLFIND_MAN)/man5/site-lib.5" 85 | 86 | 87 | .PHONY: check-installation 88 | check-installation: 89 | if [ "$(CHECK_BEFORE_INSTALL)" -eq 1 ]; then \ 90 | for x in camlp4 dbm graphics labltk num ocamlbuild; do \ 91 | if [ -f "$(prefix)$(OCAML_SITELIB)/$$x/META" ]; then \ 92 | if ! grep -Fq '[distributed with Ocaml]' "$(prefix)/$(OCAML_SITELIB)/$$x/META"; then \ 93 | rm -f site-lib-src/$$x/META; \ 94 | fi; \ 95 | fi; \ 96 | done; \ 97 | test -f "site-lib-src/num/META" || rm -f "site-lib-src/num-top/META"; \ 98 | fi 99 | echo 'SITELIB_META =' > Makefile.packages.in 100 | for x in `ls site-lib-src`; do test ! -f "site-lib-src/$$x/META" || echo $$x >> Makefile.packages.in; done 101 | tr '\n' ' ' < Makefile.packages.in > Makefile.packages 102 | rm Makefile.packages.in 103 | 104 | .PHONY: install-meta 105 | install-meta: 106 | for x in $(SITELIB_META); do $(INSTALLDIR) "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/$$x"; $(INSTALLFILE) site-lib-src/$$x/META "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/$$x/META.tmp" && mv "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/$$x/META.tmp" "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/$$x/META"; done 107 | $(INSTALLDIR) "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/findlib"; $(INSTALLFILE) Makefile.packages "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/findlib/Makefile.packages" 108 | 109 | .PHONY: uninstall-meta 110 | uninstall-meta: 111 | for x in $(SITELIB_META); do rm -rf "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/$$x"; done 112 | 113 | .PHONY: install-config 114 | install-config: 115 | $(INSTALLDIR) "`dirname \"$(DESTDIR)$(prefix)$(OCAMLFIND_CONF)\"`" 116 | @if [ -f "$(DESTDIR)$(prefix)$(OCAMLFIND_CONF)" ]; then echo "!!! Keeping old $(DESTDIR)$(prefix)$(OCAMLFIND_CONF) !!!"; fi 117 | test -f "$(DESTDIR)$(prefix)$(OCAMLFIND_CONF)" || $(INSTALLFILE) findlib.conf "$(DESTDIR)$(prefix)$(OCAMLFIND_CONF)" 118 | 119 | .PHONY: uninstall-config 120 | uninstall-config: 121 | @echo Leaving "$(OCAMLFIND_CONF)" installed, consider manual removal 122 | 123 | .PHONY: interface-lists 124 | interface-lists: 125 | d=`ocamlc -where`; \ 126 | for x in `ls site-lib-src`; do \ 127 | iflist=""; \ 128 | if [ ! -f "site-lib-src/$$x/interfaces.in" ]; then continue; fi; \ 129 | cma_spec=`cat site-lib-src/$$x/interfaces.in`; \ 130 | for cma in $$d/$$cma_spec; do \ 131 | intf=`ocamlobjinfo $$cma | \ 132 | grep 'Unit name:' | \ 133 | sed -e 's/^ Unit name: //' | \ 134 | sort | \ 135 | tr '\n' ' '`; \ 136 | iflist="$$iflist $$intf"; \ 137 | done; \ 138 | echo "$$iflist" >"site-lib-src/$$x/interfaces.out"; \ 139 | done 140 | 141 | ###################################################################### 142 | # The following is from Pietro Abata 143 | # to create MacOS X packages. I did not test it, just include it. 144 | 145 | .PHONY: package-macosx 146 | 147 | package-macosx: all opt 148 | $(INSTALLDIR) package-macosx/root 149 | export prefix=`pwd`/package-macosx/root && make install 150 | export VERSION=1.1.2 && sh tools/make-package-macosx 151 | 152 | clean-macosx: 153 | sudo rm -rf package-macosx 154 | -------------------------------------------------------------------------------- /findlib-ppc.patch: -------------------------------------------------------------------------------- 1 | diff -ur --unidirectional-new-file findlib-1.1.2pl1/Makefile findlib-1.1.2pl1.modify/Makefile 2 | --- findlib-1.1.2pl1/Makefile 2006-01-17 10:04:50.000000000 +1100 3 | +++ findlib-1.1.2pl1.modify/Makefile 2006-10-23 11:50:38.000000000 +1000 4 | @@ -17,12 +17,15 @@ 5 | for p in $(PARTS); do ( cd src/$$p; $(MAKE) opt ); done 6 | 7 | install: 8 | + mkdir -p $(prefix)$(OCAMLFIND_BIN) 9 | + mkdir -p $(prefix)$(OCAMLFIND_LIB) 10 | + mkdir -p $(prefix)$(OCAMLFIND_MAN) 11 | for p in $(PARTS); do ( cd src/$$p; $(MAKE) install ); done 12 | $(MAKE) install-doc 13 | $(MAKE) install-meta 14 | cd src/findlib; $(MAKE) install-num-top 15 | $(MAKE) install-config 16 | - cp tools/safe_camlp4 $(OCAMLFIND_BIN) 17 | + cp tools/safe_camlp4 $(prefix)$(OCAMLFIND_BIN) 18 | 19 | uninstall: 20 | $(MAKE) uninstall-doc 21 | @@ -30,12 +33,26 @@ 22 | for p in `cd src; echo *`; do ( cd src/$$p; $(MAKE) uninstall ); done 23 | $(MAKE) uninstall-config 24 | 25 | -clean: 26 | +clean: clean-macosx 27 | for p in `cd src; echo *`; do ( cd src/$$p; $(MAKE) clean ); done 28 | (cd itest-aux; $(MAKE) clean) 29 | (cd tools/extract_args; $(MAKE) clean) 30 | rm -f findlib.conf 31 | 32 | +# Make MacOS X package 33 | + 34 | +.PHONY: package-macosx 35 | + 36 | +package-macosx: all opt 37 | + mkdir -p package-macosx/root 38 | + export prefix=`pwd`/package-macosx/root && make install 39 | + export VERSION=1.1.2 && tools/make-package-macosx 40 | + #rm -rf package-macosx/root 41 | + 42 | +clean-macosx: 43 | + sudo rm -rf package-macosx 44 | + #rm -rf package-macosx/*.pkg package-macosx/*.dmg 45 | + 46 | .PHONY: release 47 | release: README 48 | ./release 49 | diff -ur --unidirectional-new-file findlib-1.1.2pl1/configure findlib-1.1.2pl1.modify/configure 50 | --- findlib-1.1.2pl1/configure 2006-01-17 10:04:49.000000000 +1100 51 | +++ findlib-1.1.2pl1.modify/configure 2006-10-23 11:50:43.000000000 +1000 52 | @@ -427,6 +427,7 @@ 53 | echo "EXEC_SUFFIX=${exec_suffix}" >>Makefile.config 54 | echo "PARTS=${parts}" >>Makefile.config 55 | echo "INSTALL_TOPFIND=${with_topfind}" >>Makefile.config 56 | +echo "VERSION=${version}" >> Makefile.config 57 | 58 | # All OK 59 | 60 | diff -ur --unidirectional-new-file findlib-1.1.2pl1/tools/make-package-macosx findlib-1.1.2pl1.modify/tools/make-package-macosx 61 | --- findlib-1.1.2pl1/tools/make-package-macosx 1970-01-01 10:00:00.000000000 +1000 62 | +++ findlib-1.1.2pl1.modify/tools/make-package-macosx 2006-10-23 11:50:52.000000000 +1000 63 | @@ -0,0 +1,119 @@ 64 | +#!/bin/sh 65 | + 66 | +######################################################################### 67 | +# # 68 | +# Objective Caml # 69 | +# # 70 | +# Damien Doligez, projet Moscova, INRIA Rocquencourt # 71 | +# # 72 | +# Copyright 2003 Institut National de Recherche en Informatique et # 73 | +# en Automatique. All rights reserved. This file is distributed # 74 | +# under the terms of the Q Public License version 1.0. # 75 | +# # 76 | +######################################################################### 77 | + 78 | +# $Id: make-package-macosx,v 1.10.2.2 2006/01/04 13:05:49 doligez Exp $ 79 | +# adapted to findlib by Pietro.Abate 80 | + 81 | +set -x 82 | + 83 | +cd package-macosx 84 | +rm -rf findlib.pkg findlib-rw.dmg 85 | +mkdir -p resources 86 | + 87 | +cat >Description.plist < 89 | + 91 | + 92 | + 93 | + IFPkgDescriptionDeleteWarning 94 | + 95 | + IFPkgDescriptionDescription 96 | + The findlib library manager 97 | + IFPkgDescriptionTitle 98 | + Findlib 99 | + IFPkgDescriptionVersion 100 | + ${VERSION} 101 | + 102 | + 103 | +EOF 104 | + 105 | +cat >Info.plist < 107 | + 109 | + 110 | + 111 | + CFBundleGetInfoString 112 | + The findlib library manager ${VERSION} 113 | + CFBundleIdentifier 114 | + http://www.ocaml-programming.de/packages/ 115 | + CFBundleName 116 | + Findlib 117 | + CFBundleShortVersionString 118 | + ${VERSION} 119 | + IFPkgFlagAllowBackRev 120 | + 121 | + IFPkgFlagAuthorizationAction 122 | + AdminAuthorization 123 | + IFPkgFlagDefaultLocation 124 | + / 125 | + IFPkgFlagInstallFat 126 | + 127 | + IFPkgFlagIsRequired 128 | + 129 | + IFPkgFlagRelocatable 130 | + 131 | + IFPkgFlagRestartAction 132 | + NoRestart 133 | + IFPkgFlagRootVolumeOnly 134 | + 135 | + IFPkgFlagUpdateInstalledLanguages 136 | + 137 | + IFPkgFormatVersion 138 | + 0.10000000149011612 139 | + 140 | + 141 | +EOF 142 | + 143 | +# stop here -> | 144 | +cat >resources/ReadMe.txt <&2 176 | + exit 3 177 | +fi 178 | +open "/Volumes/Findlib" 179 | +hdiutil detach $name 180 | + 181 | +rm -rf "findlib-${VERSION}.dmg" 182 | +hdiutil convert findlib-rw.dmg -format UDZO -o "findlib-${VERSION}.dmg" 183 | -------------------------------------------------------------------------------- /src/findlib/fl_package_base.mli: -------------------------------------------------------------------------------- 1 | (* $Id$ 2 | * ---------------------------------------------------------------------- 3 | * 4 | *) 5 | 6 | (** Direct access to the package graph and package files *) 7 | 8 | type package = 9 | { package_name : string; 10 | (** The fully qualified package name, i.e. for subpackages the 11 | * names of the containing packages are prepended and the name 12 | * components are separated by '.' 13 | *) 14 | package_dir : string; 15 | (** The directory where to lookup package files *) 16 | package_meta : string; 17 | (** The path to the META file *) 18 | package_defs : Fl_metascanner.pkg_definition list; 19 | (** The definitions in the META file *) 20 | package_priv : package_priv; 21 | (** Private part of the definition *) 22 | } 23 | (** The definition of a package *) 24 | 25 | and package_priv 26 | 27 | 28 | val init : string list -> string -> string list -> unit 29 | (** This function must be called before [Fl_package_base] can be used. 30 | * The first string corresponds to the [OCAMLPATH] setting, the second 31 | * string is the location of the standard library. The second is the 32 | * list of directories with ignored duplicate cmi files. 33 | * 34 | * This function is called by {!Findlib.init} and {!Findlib.init_manually}, 35 | * so it is already sufficient to initialize the [Findlib] module. 36 | *) 37 | 38 | 39 | (** {1 The package graph} *) 40 | 41 | (** The functions in this section operate on a representation of the 42 | * package graph in memory. The graph is usually only partially available, 43 | * as only packages are loaded that are queried for. 44 | *) 45 | 46 | 47 | exception No_such_package of string * string 48 | (** First arg is the package name not found, second arg contains additional 49 | * info for the user. - This is the same exception as in [Findlib]. 50 | *) 51 | 52 | exception Package_loop of string 53 | (** A package is required by itself. The arg is the name of the 54 | * package. - This is the same exception as in [Findlib]. 55 | *) 56 | 57 | val query : string -> package 58 | (** Returns the [package] definition for the fully-qualified package name, 59 | * or raises [No_such_package]. It is allowed to query for subpackages. 60 | * 61 | * This function loads package definitions into the graph kept in memory. 62 | *) 63 | 64 | val requires : preds:string list -> string -> string list 65 | (** Analyzes the direct requirements of the package whose name is passed as 66 | * second argument under the assumption that the predicates [preds] 67 | * hold. The function returns the names of the required packages. 68 | * It is checked whether these packages exist. 69 | * 70 | * If there is the "mt" predicate, missing dependencies on "threads" 71 | * are silently added. 72 | * 73 | * The function may raise [No_such_package] or [Package_loop]. 74 | * 75 | * This function loads package definitions into the graph kept in memory. 76 | *) 77 | 78 | val requires_deeply : preds:string list -> string list -> string list 79 | (** Analyzes the direct or indirect requirements of the packages whose names 80 | * are passed as second argument under the assumption that the predicates 81 | * [preds] hold. The function returns the names of the required packages. 82 | * It is checked whether these packages exist. 83 | * 84 | * If there is the "mt" predicate, missing dependencies on "threads" 85 | * are silently added. 86 | * 87 | * The function may raise [No_such_package] or [Package_loop]. 88 | * 89 | * This function loads package definitions into the graph kept in memory. 90 | *) 91 | 92 | val package_conflict_report : 93 | ?identify_dir:(string -> 'a) -> unit -> unit 94 | (** Checks whether there are several META files for the same main 95 | * packages. Complaints are printed to stderr. 96 | * 97 | * Only packages in the loaded part of the package graph are checked (i.e. 98 | * packages for which there was a query). 99 | * 100 | * It is recommended to pass the ~identify_dir function whose task 101 | * it is to return a unique value for every existing directory. 102 | * For example, 103 | * {[ fun d -> 104 | * let s = Unix.stat d in 105 | * (s.Unix.st_dev, s.Unix.st_ino) 106 | * ]} 107 | * could be an implementation for this function. The default is 108 | * the identity (and not this nice implementation to avoid dependencies 109 | * on the Unix module). 110 | *) 111 | 112 | val module_conflict_report : ?identify_dir:(string -> 'a) -> string list -> unit 113 | (** Checks whether there are cmi files for the same modules. The 114 | * directories passed as first argument are checked. (Note: 115 | * Neither the '+' nor the '@' notation are recognized.) 116 | * Complaints about double cmi files are printed to stderr. 117 | * 118 | * @param identify_dir See [package_conflict_report]. 119 | *) 120 | 121 | val load_base : ?prefix:string -> unit -> unit 122 | (** Ensures that the complete package graph is loaded into memory. 123 | * This is a time-consuming operation. Warnings may be printed to 124 | * stderr. 125 | * 126 | * @param prefix Limit to the packages that starts with it. Default: unlimited 127 | *) 128 | 129 | val list_packages : ?prefix:string -> unit -> string list 130 | (** Ensures that the complete package graph is loaded into memory 131 | * (like [load_base]), and returns the (unsorted) list of all 132 | * packages. 133 | * 134 | * @param prefix Limit to the packages that starts with it. Default: unlimited 135 | *) 136 | 137 | val package_users : preds:string list -> string list -> string list 138 | (** Ensures that the complete package graph is loaded into memory 139 | * (like [load_base]), and determines the packages using one of 140 | * the packages passed as second argument. The [preds] are assumed 141 | * for the evaluation of the [requires] directives. 142 | * The returned list is sorted in ascending order. 143 | * 144 | * If there is the "mt" predicate, missing dependencies on "threads" 145 | * are silently added. 146 | * 147 | * Raises [No_such_package] if one of the passed packages cannot 148 | * be found. 149 | *) 150 | 151 | 152 | (** {1 Parsing META files} *) 153 | 154 | (** The functions in this section access directly files and directories. 155 | * The package graph is unknown. 156 | *) 157 | 158 | val packages_in_meta_file : 159 | ?directory_required:bool -> 160 | name:string -> dir:string -> meta_file:string -> unit -> package list 161 | (** Parses the META file whose name is [meta_file]. In [name], the 162 | * name of the main package must be passed. [dir] is the 163 | * directory associated with the package by default (i.e. before 164 | * it is overriden by the "directory" directive). 165 | * 166 | * Returns the package records found in this file. The "directory" 167 | * directive is already applied. 168 | * 169 | * @param directory_required If true, it is checked whether there is a 170 | * "directory" directive in the main package. If this directive is missing, 171 | * the function will fail. 172 | *) 173 | 174 | val package_definitions : search_path:string list -> string -> string list 175 | (** Return all META files defining this package that occur in the 176 | * directories mentioned in [search_path]. The package name must be 177 | * fully-qualified. For simplicity, however, only the name of the main 178 | * package is taken into account (so it is a good idea to call this 179 | * function only for main packages). 180 | *) 181 | 182 | -------------------------------------------------------------------------------- /src/findlib/Makefile: -------------------------------------------------------------------------------- 1 | # make all: compile to bytecode 2 | # make opt: compile to native code 3 | # make install: install bytecode and/or native code 4 | # 5 | # See Makefile.config for configurable variables. 6 | # Runtime configurations might also be necessary in the site-lib/*/META 7 | # files. 8 | #---------------------------------------------------------------------- 9 | 10 | TOP=../.. 11 | include $(TOP)/Makefile.config 12 | 13 | NAME = findlib 14 | 15 | # Need compiler-libs since ocaml-4.00 16 | OCAMLC = ocamlc -I +compiler-libs 17 | OCAMLOPT = ocamlopt -I +compiler-libs $(OCAMLOPT_G) 18 | OCAMLDEP = ocamldep 19 | OCAMLLEX = ocamllex 20 | #CAMLP4O = camlp4 pa_o.cmo pa_op.cmo pr_o.cmo -- 21 | #CAMLP4O = camlp4 pa_o.cmo pa_op.cmo pr_dump.cmo -- 22 | 23 | 24 | OBJECTS = findlib_config.cmo fl_split.cmo fl_metatoken.cmo fl_meta.cmo \ 25 | fl_metascanner.cmo fl_topo.cmo fl_package_base.cmo \ 26 | findlib.cmo fl_args.cmo fl_lint.cmo 27 | TOBJECTS = topfind.cmo 28 | 29 | XOBJECTS = $(OBJECTS:.cmo=.cmx) 30 | TXOBJECTS = topfind.cmx 31 | 32 | OCAMLFIND_OBJECTS = ocaml_args.cmo frontend.cmo 33 | OCAMLFIND_XOBJECTS = ocaml_args.cmx frontend.cmx 34 | 35 | # OCAMLFIND_ARCHIVES: set in Makefile.config 36 | OCAMLFIND_XARCHIVES = $(OCAMLFIND_ARCHIVES:.cma=.cmxa) 37 | 38 | NUMTOP_OBJECTS = num_top_printers.cmo num_top.cmo 39 | 40 | DYNLOAD_OBJECTS = fl_dynload.cmo 41 | DYNLOAD_XOBJECTS = $(DYNLOAD_OBJECTS:.cmo=.cmx) 42 | 43 | 44 | all: ocamlfind$(EXEC_SUFFIX) findlib.cma findlib_top.cma topfind $(NUMTOP) \ 45 | findlib_dynload.cma 46 | 47 | opt: ocamlfind_opt$(EXEC_SUFFIX) findlib.cmxa findlib_top.cmxa topfind \ 48 | findlib_dynload.cmxa 49 | 50 | num-top: num_top.cma 51 | 52 | ocamlfind$(EXEC_SUFFIX): findlib.cma $(OCAMLFIND_OBJECTS) 53 | $(OCAMLC) $(CUSTOM) -o ocamlfind$(EXEC_SUFFIX) -g $(OCAMLFIND_ARCHIVES) \ 54 | $(OCAMLC_FLAGS) $(OCAMLFIND_OCAMLFLAGS) $(OCAMLFIND_OBJECTS) 55 | 56 | ocamlfind_opt$(EXEC_SUFFIX): findlib.cmxa $(OCAMLFIND_XOBJECTS) 57 | $(OCAMLOPT) -o ocamlfind_opt$(EXEC_SUFFIX) $(OCAMLFIND_XARCHIVES) \ 58 | $(OCAMLOPT_FLAGS) $(OCAMLFIND_OCAMLFLAGS) $(OCAMLFIND_XOBJECTS) 59 | 60 | test_parser$(EXEC_SUFFIX): fl_metascanner.cmx test_parser.cmx fl_metatoken.cmx fl_meta.cmx 61 | $(OCAMLOPT) -o test_parser$(EXEC_SUFFIX) fl_meta.cmx fl_metatoken.cmx fl_metascanner.cmx test_parser.cmx 62 | 63 | findlib.cma: $(OBJECTS) 64 | $(OCAMLC) -a -o findlib.cma $(OBJECTS) 65 | 66 | findlib_top.cma: $(TOBJECTS) 67 | $(OCAMLC) -a -o findlib_top.cma $(TOBJECTS) 68 | 69 | findlib.cmxa: $(XOBJECTS) 70 | $(OCAMLOPT) -a -o findlib.cmxa $(XOBJECTS) 71 | if [ $(HAVE_NATDYNLINK) -gt 0 ]; then \ 72 | $(OCAMLOPT) -shared -o findlib.cmxs $(XOBJECTS); \ 73 | fi 74 | 75 | findlib_top.cmxa: $(TXOBJECTS) 76 | $(OCAMLOPT) -a -o findlib_top.cmxa $(TXOBJECTS) 77 | if [ $(HAVE_NATDYNLINK) -gt 0 ]; then \ 78 | $(OCAMLOPT) -shared -o findlib_top.cmxs $(TXOBJECTS); \ 79 | fi 80 | 81 | findlib_dynload.cma: $(DYNLOAD_OBJECTS) 82 | $(OCAMLC) -a -o findlib_dynload.cma $(DYNLOAD_OBJECTS) 83 | 84 | findlib_dynload.cmxa: $(DYNLOAD_XOBJECTS) 85 | $(OCAMLOPT) -a -o findlib_dynload.cmxa $(DYNLOAD_XOBJECTS) 86 | if [ $(HAVE_NATDYNLINK) -gt 0 ]; then \ 87 | $(OCAMLOPT) -shared -o findlib_dynload.cmxs $(DYNLOAD_XOBJECTS); \ 88 | fi 89 | 90 | findlib_config.ml: findlib_config.mlp $(TOP)/Makefile.config 91 | USE_CYGPATH="$(USE_CYGPATH)"; \ 92 | export USE_CYGPATH; \ 93 | cat findlib_config.mlp | \ 94 | $(SH) $(TOP)/tools/patch '@CONFIGFILE@' '$(OCAMLFIND_CONF)' | \ 95 | $(SH) $(TOP)/tools/patch '@STDLIB@' '$(OCAML_CORE_STDLIB)' | \ 96 | sed -e 's;@AUTOLINK@;$(OCAML_AUTOLINK);g' \ 97 | -e 's;@SYSTEM@;$(SYSTEM);g' \ 98 | >findlib_config.ml 99 | 100 | topfind.ml: topfind.ml.in 101 | if [ "$(ENABLE_TOPFIND_PPXOPT)" = "true" ]; then \ 102 | cp topfind.ml.in topfind.ml; \ 103 | else \ 104 | sed -e '/PPXOPT_BEGIN/,/PPXOPT_END/ d' topfind.ml.in \ 105 | > topfind.ml ; \ 106 | fi 107 | 108 | topfind: topfind_rd$(OCAML_REMOVE_DIRECTORY).p 109 | USE_CYGPATH="$(USE_CYGPATH)"; \ 110 | export USE_CYGPATH; \ 111 | cat topfind_rd$(OCAML_REMOVE_DIRECTORY).p | \ 112 | $(SH) $(TOP)/tools/patch '@SITELIB@' '$(OCAML_SITELIB)' \ 113 | >topfind 114 | 115 | num_top.cma: $(NUMTOP_OBJECTS) 116 | $(OCAMLC) -a -o num_top.cma $(NUMTOP_OBJECTS) 117 | 118 | clean: 119 | rm -f *.cmi *.cmo *.cma *.cmx *.a *.lib *.o *.obj *.cmxa \ 120 | fl_meta.ml findlib_config.ml findlib.mml topfind.ml topfind \ 121 | ocamlfind$(EXEC_SUFFIX) ocamlfind_opt$(EXEC_SUFFIX) 122 | 123 | install: all 124 | $(INSTALLDIR) "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/$(NAME)" 125 | $(INSTALLDIR) "$(DESTDIR)$(prefix)$(OCAMLFIND_BIN)" 126 | test $(INSTALL_TOPFIND) -eq 0 || $(INSTALLDIR) "$(DESTDIR)$(prefix)$(OCAML_CORE_STDLIB)" 127 | test $(INSTALL_TOPFIND) -eq 0 || $(INSTALLFILE) topfind "$(DESTDIR)$(prefix)$(OCAML_CORE_STDLIB)/" 128 | files=`$(SH) $(TOP)/tools/collect_files $(TOP)/Makefile.config \ 129 | findlib.cmi findlib.mli findlib.cma findlib.cmxa findlib$(LIB_SUFFIX) findlib.cmxs \ 130 | findlib_config.cmi findlib_config.ml topfind.cmi topfind.mli \ 131 | fl_args.cmi fl_lint.cmi fl_meta.cmi fl_split.cmi fl_topo.cmi ocaml_args.cmi \ 132 | fl_package_base.mli fl_package_base.cmi fl_metascanner.mli fl_metascanner.cmi \ 133 | fl_metatoken.cmi findlib_top.cma findlib_top.cmxa findlib_top$(LIB_SUFFIX) findlib_top.cmxs \ 134 | findlib_dynload.cma findlib_dynload.cmxa findlib_dynload$(LIB_SUFFIX) findlib_dynload.cmxs fl_dynload.mli fl_dynload.cmi \ 135 | META` && \ 136 | $(INSTALLFILE) $$files "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/$(NAME)/" 137 | f="ocamlfind$(EXEC_SUFFIX)"; { test -f ocamlfind_opt$(EXEC_SUFFIX) && f="ocamlfind_opt$(EXEC_SUFFIX)"; }; \ 138 | $(INSTALLFILE) $$f "$(DESTDIR)$(prefix)$(OCAMLFIND_BIN)/ocamlfind$(EXEC_SUFFIX)" 139 | # the following "if" block is only needed for 4.00beta2 140 | if [ $(OCAML_REMOVE_DIRECTORY) -eq 0 -a -f "$(OCAML_CORE_STDLIB)/compiler-libs/topdirs.cmi" ]; then \ 141 | cd "$(OCAML_CORE_STDLIB)/compiler-libs/"; \ 142 | $(INSTALLFILE) topdirs.cmi toploop.cmi "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/$(NAME)/"; \ 143 | fi 144 | 145 | install-num-top: 146 | $(INSTALLDIR) "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/num-top" 147 | $(INSTALLFILE) num_top.cma num_top.cmi num_top_printers.cmi \ 148 | "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/num-top/" 149 | 150 | # Note: uninstall-num-top is part of the removal of the META files. 151 | 152 | uninstall: 153 | rm -f $(DESTDIR)$(prefix)$(OCAML_CORE_STDLIB)/findlib 154 | rm -rf $(DESTDIR)$(prefix)$(OCAML_SITELIB)/$(NAME) 155 | rm -f $(DESTDIR)$(prefix)$(OCAMLFIND_BIN)/ocamlfind$(EXEC_SUFFIX) 156 | 157 | 158 | depend: *.ml *.mli fl_meta.ml fl_metascanner.ml findlib_config.ml topfind.ml 159 | $(OCAMLDEP) *.ml *.mli >depend 160 | 161 | # Some 'make' implementations require that .SUFFIXES must occur before 162 | # the first suffix rule. (E.g. AIX) 163 | .SUFFIXES: .mll .cmo .cmi .cmx .ml .mli .mml 164 | # .src 165 | 166 | .mml.cmo: 167 | $(OCAMLC) $(OPAQUE) $(OCAMLC_FLAGS) $(OCAMLFIND_OCAMLFLAGS) -g -vmthread -c -impl $< 168 | 169 | .mml.cmx: 170 | $(OCAMLOPT) $(OPAQUE) $(OCAMLOPT_FLAGS) $(OCAMLFIND_OCAMLFLAGS) -thread -c -impl $< 171 | 172 | .ml.cmx: 173 | $(OCAMLOPT) $(OPAQUE) $(OCAMLOPT_FLAGS) $(OCAMLFIND_OCAMLFLAGS) -c $< 174 | 175 | .ml.cmo: 176 | $(OCAMLC) $(OPAQUE) $(OCAMLC_FLAGS) $(OCAMLFIND_OCAMLFLAGS) -g -c $< 177 | 178 | .mli.cmi: 179 | $(OCAMLC) $(OPAQUE) $(OCAMLC_FLAGS) $(OCAMLFIND_OCAMLFLAGS) -c $< 180 | 181 | #.src.ml: 182 | # $(CAMLP4O) -impl $< -o $@ 183 | 184 | # Solaris make does not like the suffix rule .mll.ml, 185 | # so I replaced it by its single application: 186 | fl_meta.ml: fl_meta.mll 187 | $(OCAMLLEX) fl_meta.mll 188 | 189 | # Don't remove fl_metascanner.ml: 190 | .PRECIOUS: fl_metascanner.ml 191 | 192 | include depend 193 | 194 | -------------------------------------------------------------------------------- /doc/QUICKSTART.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | %common; 6 | 7 | 8 | up'> 9 | 10 | 11 | %config; 12 | 13 | ]> 14 | 15 | 16 | 17 | Intro 18 |

See the file INSTALL for instructions how to build and install 19 | findlib.

20 |
21 | 22 | 23 | Findlib and the toploop 24 | 25 |

For a number of platforms, OCaml can load bytecode-compiled 26 | libraries dynamically. For these platforms, findlib is very simple to 27 | use as explained in the following. For other platforms, see the paragraph 28 | below about "custom toploops".

29 | 30 |

After the toploop has been started, it is possible to load the special 31 | findlib support:In previous versions, #use "findlib" loaded the 32 | library. However, this caused a name conflict for a certain type of 33 | installation. Because of this, the name of the loader script has been changed 34 | to "topfind", but "findlib", and "ocamlfind" (Debian) are also available 35 | for backwards compatibility. 36 | 37 | 38 | $ ocaml 39 | Objective Caml version 3.07 40 | 41 | # #use "topfind";; 42 | Findlib has been successfully loaded. Additional directives: 43 | #require "package";; to load a package 44 | #list;; to list the available packages 45 | #camlp4o;; to load camlp4 (standard syntax) 46 | #camlp4r;; to load camlp4 (revised syntax) 47 | #predicates "p,q,...";; to set these predicates 48 | Topfind.reset();; to force that packages will be reloaded 49 | #thread;; to enable threads 50 | 51 | - : unit = () 52 | 53 | 54 | You can now list the available packages: 55 | 56 | 57 | # #list;; 58 | bigarray (version: [distributed with Ocaml]) 59 | camlp4 (version: Camlp4 version 3.03 ALPHA) 60 | dbm (version: [distributed with Ocaml]) 61 | dynlink (version: [distributed with Ocaml]) 62 | findlib (version: 0.6) 63 | graphics (version: [distributed with Ocaml]) 64 | labltk (version: [distributed with Ocaml]) 65 | netstring (version: 0.10) 66 | num (version: [distributed with Ocaml]) 67 | stdlib (version: [distributed with Ocaml]) 68 | str (version: [distributed with Ocaml]) 69 | threads (version: [distributed with Ocaml]) 70 | unix (version: [distributed with Ocaml]) 71 | xstrp4 (version: 1.1) 72 | 73 | 74 | and load packages by simply typing: 75 | 76 | 77 | # #require "netstring";; 78 | Loading /opt/ocaml/lib/unix.cma 79 | Loading /opt/ocaml/lib/str.cma 80 | Loading /opt/ocaml/site-lib/netstring/netstring.cma 81 | Loading /opt/ocaml/site-lib/netstring/netstring_top.cmo 82 | 83 | 84 | Findlib takes care to load packages that are required by loaded packages 85 | first. For example, "netstring" uses "unix" and "str" internally, but you 86 | do not need to load them because findlib does it for you. In this example 87 | you can also see that findlib loads netstring_top.cmo containing printers 88 | for the toploop.

89 | 90 |

You can also enable the Camlp4 parsers by simply typing 91 | 92 | 93 | # #camlp4o;; 94 | Loading /opt/ocaml-3.03a/lib/camlp4/camlp4o.cma 95 | Camlp4 Parsing version 3.03 ALPHA 96 | 97 | 98 | for the standard syntax or 99 | 100 | 101 | # #camlp4r;; 102 | Loading /opt/ocaml-3.03a/lib/camlp4/camlp4r.cma 103 | Camlp4 Parsing version 3.03 ALPHA 104 | 105 | 106 | for the revised syntax. (But you cannot switch between the syntaxes.) 107 |

108 |
109 | 110 | 111 | Custom Toploops 112 | 113 |

For some platforms, OCaml does not implement loading external 114 | libraries (e.g. Cygwin). One has to create a so-called custom toploop 115 | that statically links with these libraries. Example: 116 | 117 | 118 | $ ocamlfind ocamlmktop -o mytop -package findlib,unix -linkpkg 119 | $ ./mytop 120 | Objective Caml version 3.07 121 | 122 | # #use "topfind";; 123 | Findlib has been successfully loaded. Additional directives: 124 | #require "package";; to load a package 125 | #list;; to list the available packages 126 | #camlp4o;; to load camlp4 (standard syntax) 127 | #camlp4r;; to load camlp4 (revised syntax) 128 | #predicates "p,q,...";; to set these predicates 129 | Topfind.reset();; to force that packages will be reloaded 130 | #thread;; to enable threads 131 | 132 | - : unit = () 133 | 134 | 135 | Now "#require" works for all libraries referring to the special "unix" 136 | functions. 137 |

138 |
139 | 140 | 141 | Findlib and scripts 142 | 143 |

The #require directive can also be used in scripts. Example: 144 | 145 | 146 | #use "topfind";; 147 | #require "netstring";; 148 | 149 | open Cgi;; 150 | ... 151 | 152 | 153 | This makes it possible to write scripts that do not contain #directory 154 | directives that are specific for certain installations.

155 | 156 |

For Unix environments, you can start scripts directly if you 157 | apply the following trick: 158 | 159 | 160 | #! /bin/sh 161 | # (* 162 | exec ocaml "$0" "$@" 163 | *) use "topfind";; 164 | #require "netstring";; 165 | 166 | open Cgi;; 167 | ... 168 | 169 | 170 | This works wherever OCaml is installed.

171 |
172 | 173 | 174 | Compiling programs 175 | 176 |

Assumed you want to compile a program that uses the Netstring package. 177 | Do it the following way: 178 | 179 | 180 | $ ocamlfind ocamlc -package netstring -c myprogram.ml 181 | 182 | 183 | This way you do not need to add "-I" options to locate Netstring.

184 | 185 |

If you want to create an executable, do not forget to add the 186 | -linkpkg switch: 187 | 188 | 189 | $ ocamlfind ocamlc -o myprogram -package netstring -linkpkg myprogram.cmo 190 | 191 | 192 | This switch causes that the mentioned packages are added to the resulting 193 | executable.

194 | 195 |

If you want to include several packages, you can either add several 196 | "-package" options, or you can enumerate the packages separated by commas: 197 | -package netstring,labltk.

198 |
199 | 200 | 201 | Camlp4 202 | 203 |

If you add a -syntax option, the compiler will be told to parse the 204 | source file using camlp4: 205 | 206 | 207 | $ ocamlfind ocamlc -package netstring -syntax camlp4o -c myprogram.ml 208 | 209 | 210 | Use -syntax camlp4o for the standard syntax or -syntax camlp4r for the 211 | revised syntax.

212 | 213 |

Additionally, you can mention packages that add new syntax features. 214 | The package xstrp4 is an example of this: 215 | 216 | 217 | $ ocamlfind ocamlc -package xstrp4,netstring -syntax camlp4o -c myprogram.ml 218 | 219 | 220 | Now you can use the $ notation that is implemented by xstrp4 in the 221 | source file myprogram.ml.

222 | 223 |

Note that you can also invoke ocamldep from ocamlfind: 224 | 225 | 226 | $ ocamlfind ocamldep -package xstrp4 -syntax camlp4o *.ml *.mli >.depend 227 | 228 | 229 | This enables the syntax extensions, too.

230 |
231 | 232 | 233 | ocamlbrowser 234 |

Since findlib-0.7, it is also possible to start ocamlbrowser from 235 | ocamlfind. For example, 236 | 237 | 238 | $ ocamlfind browser -package xstrp4 239 | 240 | 241 | adds the correct path specification such that the modules contained in the 242 | package xstrp4 are also displayed. With 243 | 244 | 245 | $ ocamlfind browser -all 246 | 247 | 248 | all package are added to the path spec. 249 |

250 |
251 | 252 | 253 | The Makefile wizard 254 |

There is a wizard that makes it very easy to write Makefiles. Call the 255 | wizard by 256 | 257 | $ ocamlfind findlib/make_wizard 258 | 259 | (the wizard requires that the labltk library is available). A new window 260 | pops up, and by very few clicks you can describe your own library. Finally, 261 | a Makefile is written. 262 |

263 |
264 | 265 | 266 | There is no magic! 267 | 268 |

Findlib is neither a patch of OCaml nor uses it internal features of 269 | the OCaml programming environment. It is only a convention to install 270 | software components in filesystem hierarchies, a library interpreting 271 | this convention, and some frontend applications making the library useable for 272 | you.

273 | 274 |

One important consequence is that you can only refer to those 275 | software components that have previously been installed in a way findlib 276 | understands. This convention is beyond the scope of this QUICKSTART guide, 277 | see the reference manual for details. You can always check whether findlib 278 | accepts a component as "findlib package" by the command 279 | 280 | 281 | $ ocamlfind list 282 | 283 | 284 | (this is the same as the #list directive in the toploop). If the package 285 | occurs in the list, it is found, otherwise not.

286 |
287 |
288 | 289 | -------------------------------------------------------------------------------- /src/findlib/fl_topo.ml: -------------------------------------------------------------------------------- 1 | (* $Id$ 2 | * ---------------------------------------------------------------------- 3 | * 4 | *) 5 | 6 | (* TODO: 7 | * - Use a hashtable in 'find' 8 | * - implement le_than with an 'iter' like method 9 | *) 10 | 11 | 12 | (**********************************************************************) 13 | 14 | 15 | module type IdentifiedType = 16 | sig 17 | type t 18 | type id_t 19 | val id : t -> id_t 20 | end 21 | 22 | exception Inconsistent_ordering 23 | 24 | module type S = 25 | sig 26 | type key 27 | type el_t 28 | type t 29 | val create : unit -> t 30 | val add : t -> el_t -> unit 31 | val let_le : t -> key -> key -> unit 32 | val find : t -> key -> el_t 33 | val le_than : t -> key -> key -> bool 34 | val key : el_t -> key 35 | val iter_up : (el_t -> unit) -> t -> unit 36 | val iter_down : (el_t -> unit) -> t -> unit 37 | val iter_up_at : (el_t -> unit) -> t -> key list -> unit 38 | val iter_down_at : (el_t -> unit) -> t -> key list -> unit 39 | 40 | val clear : t -> unit 41 | val replace : t -> key -> el_t -> unit 42 | val delete : t -> key -> unit 43 | 44 | val copy : t -> t 45 | end 46 | 47 | 48 | (**********************************************************************) 49 | 50 | module Make(H: IdentifiedType) = 51 | struct 52 | 53 | type key = H.id_t 54 | 55 | type el_t = H.t 56 | 57 | type 'a node = 58 | { mutable content : 'a; 59 | mutable smaller : 'a node list; 60 | mutable bigger : 'a node list; 61 | mutable mark : bool; (* used in 'iter' *) 62 | (* mutable ppmark : bool *) (* used in 'private_property' *) 63 | } 64 | 65 | type t = 66 | { mutable cnt : el_t node list; 67 | mutable lock : bool 68 | } 69 | 70 | let copy ord = 71 | (* This operation is quite expensive when the graph has already 72 | * relations. In findlib, this case is avoided, and is here only 73 | * implemented for completeness. 74 | *) 75 | let ord' = 76 | { cnt = List.map (fun n -> { n with 77 | smaller = []; 78 | bigger = []; 79 | mark = false }) ord.cnt; 80 | lock = false 81 | } in 82 | let combined_list = List.combine ord.cnt ord'.cnt in 83 | let lookup_node n = 84 | (* Find the new node corresponding to old node n *) 85 | try List.assq n combined_list 86 | with Not_found -> assert false 87 | in 88 | List.iter2 89 | (fun n n' -> 90 | (* n: old node, n': new node *) 91 | let smaller = List.map lookup_node n.smaller in 92 | let bigger = List.map lookup_node n.bigger in 93 | n'.smaller <- smaller; 94 | n'.bigger <- bigger; 95 | ) 96 | ord.cnt 97 | ord'.cnt; 98 | ord' 99 | 100 | 101 | let rec delete_all p l = 102 | match l with 103 | x::l' -> 104 | if p x then delete_all p l' else x :: delete_all p l' 105 | | [] -> [] 106 | 107 | 108 | (******************************************************************) 109 | 110 | let create () = { cnt = []; lock = false } 111 | 112 | let clear ordering = 113 | ordering.cnt <- []; 114 | ordering.lock <- false 115 | 116 | (******************************************************************) 117 | 118 | let add ordering x = 119 | (* Is there already a node with the same key? *) 120 | let k = H.id x in 121 | if List.exists (fun y -> H.id y.content = k) ordering.cnt then 122 | raise Inconsistent_ordering; 123 | 124 | (* Ok, add the node to the list *) 125 | let nx = { content = x; 126 | smaller = []; 127 | bigger = []; 128 | mark = false 129 | } in 130 | ordering.cnt <- nx :: ordering.cnt 131 | 132 | 133 | (******************************************************************) 134 | 135 | let find_node ordering kx = 136 | let rec search l = 137 | match l with 138 | [] -> raise Not_found 139 | | y :: l' -> if H.id y.content = kx then y else search l' 140 | in 141 | search ordering.cnt 142 | 143 | 144 | let find ordering kx = (find_node ordering kx).content 145 | 146 | (******************************************************************) 147 | 148 | let replace ordering kx x' = 149 | let x = find_node ordering kx in 150 | x.content <- x' 151 | 152 | (******************************************************************) 153 | 154 | let delete ordering kx = 155 | let x = find_node ordering kx in 156 | ordering.cnt <- delete_all (fun a -> a == x) ordering.cnt; 157 | List.iter 158 | (fun x -> 159 | x.smaller <- delete_all (fun a -> a == x) x.smaller; 160 | x.bigger <- delete_all (fun a -> a == x) x.bigger) 161 | ordering.cnt 162 | 163 | 164 | (******************************************************************) 165 | 166 | let le_than ordering kx ky = 167 | (* Find x, y: *) 168 | let x = find_node ordering kx in 169 | let y = find_node ordering ky in 170 | 171 | let rec search x1 = 172 | if x1 == y then 173 | true 174 | else 175 | List.exists search x1.bigger 176 | 177 | in 178 | search x 179 | 180 | (******************************************************************) 181 | 182 | let let_le ordering kx ky = 183 | (* Find x, y: *) 184 | let x = find_node ordering kx in 185 | let y = find_node ordering ky in 186 | 187 | (* If already done just return (this is an idempotent function) *) 188 | if not (List.memq x y.smaller) then begin 189 | 190 | (* let x <= y. This is only allowed if not (y <= x) *) 191 | if le_than ordering ky kx then 192 | raise Inconsistent_ordering; 193 | 194 | (* Ok, add the relation *) 195 | x.bigger <- y :: x.bigger; 196 | y.smaller <- x :: y.smaller 197 | end 198 | 199 | (******************************************************************) 200 | 201 | let key x = H.id x 202 | 203 | (******************************************************************) 204 | 205 | let iter upwards f ordering = 206 | 207 | let in_direction n = 208 | if upwards then n.bigger else n.smaller in 209 | 210 | let against_direction n = 211 | if upwards then n.smaller else n.bigger in 212 | 213 | (* the following is written as if for iter_up. *) 214 | 215 | let rec find_biggest ordlist = 216 | (* find biggest, non-marked node *) 217 | match ordlist with 218 | [] -> raise Not_found 219 | | nx :: ordlist' -> if not nx.mark && in_direction nx = [] 220 | then nx 221 | else find_biggest ordlist' 222 | in 223 | 224 | let rec run_up n = 225 | (* iterate over all nodes <= x and return their number *) 226 | 227 | let rec run_up_list l = 228 | match l with 229 | [] -> 0 230 | | x :: l' -> run_up x + run_up_list l' 231 | in 232 | 233 | if n.mark then 234 | (* have already visited this node *) 235 | 0 236 | else 237 | let u = run_up_list (against_direction n) in 238 | n.mark <- true; 239 | f n.content; 240 | u + 1 241 | in 242 | 243 | (* Lock *) 244 | if ordering.lock then 245 | failwith "iter_up: recursive application not allowed"; 246 | ordering.lock <- true; 247 | 248 | (* clear all marks *) 249 | List.iter (fun nx -> nx.mark <- false) ordering.cnt; 250 | 251 | (* Catch exceptions *) 252 | 253 | try 254 | (* while there is a biggest node... *) 255 | let c = ref 0 in (* counter *) 256 | while !c < List.length ordering.cnt do 257 | 258 | (* Find a biggest node *) 259 | let n_biggest = find_biggest ordering.cnt in 260 | 261 | (* run through the graph *) 262 | c := !c + run_up n_biggest 263 | 264 | done; 265 | 266 | (* unlock *) 267 | ordering.lock <- false 268 | 269 | with 270 | any -> (* unlock, too *) 271 | ordering.lock <- false; 272 | raise any 273 | 274 | 275 | let iter_up = iter true 276 | let iter_down = iter false 277 | 278 | 279 | (******************************************************************) 280 | 281 | let iter_at upwards f ordering startpoints = 282 | 283 | (* 284 | let in_direction n = 285 | if upwards then n.bigger else n.smaller in 286 | *) 287 | 288 | let against_direction n = 289 | if upwards then n.smaller else n.bigger in 290 | 291 | (* the following is written as if for iter_up. *) 292 | 293 | let rec run_up n = 294 | (* iterate over all nodes <= x and return their number *) 295 | 296 | let rec run_up_list l = 297 | match l with 298 | [] -> 0 299 | | x :: l' -> run_up x + run_up_list l' 300 | in 301 | 302 | if n.mark then 303 | (* have already visited this node *) 304 | 0 305 | else 306 | let u = run_up_list (against_direction n) in 307 | n.mark <- true; 308 | f n.content; 309 | u + 1 310 | in 311 | 312 | (* Lock *) 313 | if ordering.lock then 314 | failwith "iter_up: recursive application not allowed"; 315 | ordering.lock <- true; 316 | 317 | (* clear all marks *) 318 | List.iter (fun nx -> nx.mark <- false) ordering.cnt; 319 | 320 | (* Catch exceptions *) 321 | 322 | try 323 | 324 | List.iter 325 | (fun start -> 326 | let _ = run_up (find_node ordering start) in ()) 327 | startpoints; 328 | 329 | (* unlock *) 330 | ordering.lock <- false 331 | 332 | with 333 | any -> (* unlock, too *) 334 | ordering.lock <- false; 335 | raise any 336 | 337 | 338 | let iter_up_at = iter_at true 339 | let iter_down_at = iter_at false 340 | 341 | 342 | (******************************************************************) 343 | 344 | end 345 | -------------------------------------------------------------------------------- /doc/common.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | 10 | 12 | 13 | 15 | 16 | 18 | 19 | 21 | 22 | 24 | 25 | 27 | 28 | 30 | 31 | 33 | 34 | 38 | 39 | 41 | 42 | 44 | 45 | 47 | 48 | 50 | 51 | 53 | 54 | 56 | 57 | 59 | 60 | 62 | 63 | 65 | 66 | 68 | 69 | 70 | 72 | 73 | 75 | 76 | 78 | 79 | 81 | 82 | 84 | 85 | 87 | 88 | 89 | 90 | 91 | 92 | 94 | 95 | 97 | 98 | 100 | 101 | 103 | 104 | 106 | 107 | 109 | 110 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 121 | 122 | 124 | 125 | 127 | 128 | 130 | 131 | 132 | 133 | 135 | 136 | 137 | 139 | 140 | 142 | 143 | 145 | 146 | 147 | 148 | 150 | 151 | 153 | 154 | 156 | 157 | 158 | 159 | 161 | 162 | 164 | 165 | 167 | 168 | 170 | 171 | 173 | 174 | 176 | 177 | 179 | 180 | 181 | 182 | 184 | 185 | 187 | 188 | 190 | 191 | 192 | 193 | 195 | 196 | 198 | 199 | 201 | 202 | 203 | 204 | 206 | 207 | 209 | 210 | 212 | 213 | 214 | 215 | 217 | 218 | 220 | 221 | 223 | 224 | 225 | 226 | 228 | 229 | 231 | 232 | 234 | 235 | 236 | 238 | 239 | 240 | 241 | 243 | 244 | 246 | 247 | 249 | 250 | 252 | 253 | 255 | 256 | 258 | 259 | 261 | 262 | 264 | 265 | 267 | 268 | 270 | 271 | 272 | 273 | 275 | 276 | 278 | 279 | 281 | 282 | 284 | 285 | 287 | 288 | 290 | 291 | 293 | 294 | 296 | 297 | 298 | 299 | 301 | 303 | 305 | 306 | 307 | 309 | 310 | 312 | 313 | 314 | 316 | 318 | 320 | 322 | 323 | 325 | 326 | 328 | 329 | 330 | 332 | 334 | 335 | 336 | 337 | 338 | 340 | 341 | 342 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | Gerd Stolpmann'> 351 | 352 | 354 | -------------------------------------------------------------------------------- /doc/src/findlib_topfind.mod: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Topfind 5 | 3 6 | The findlib package manager for OCaml 7 | 8 | 9 | 10 | Topfind 11 | [Module to load packages into toploops] 12 | 13 | 14 | 15 | 16 | SIGNATURE 17 | 18 | module Topfind : 19 | sig 20 | 22 | 24 | 26 | 28 | 30 | 32 | 34 | 36 | 38 | 40 | end 41 | 42 | 43 | 44 | 45 | 46 | DIRECTIVES 47 | 48 | 50 | 52 | 54 | 56 | 57 | 58 | 59 | 60 | 61 | PACKAGING 62 | 63 | 64 | The Topfind module is part of the "findlib" package. The module 65 | depends on the presence of a toploop. When building a toploop, it is 66 | automatically linked in if "findlib" is linked in, e.g. 67 | 68 | 69 | 70 | ocamlfind ocamlmktop options -package findlib -linkpkg options 71 | 72 | 73 | 74 | When the platform supports DLLs, another possibility to get a toploop 75 | with findlib directives is to load the file "topfind" (normally installed 76 | in the standard library directory): 77 | 78 | 79 | 80 | ~ > ocaml 81 | Objective Caml version 3.04 82 | 83 | # #use "topfind";; 84 | Findlib has been successfully loaded. Additional directives: 85 | #require "package";; to load a package 86 | #list;; to list the available packages 87 | #camlp4o;; to load camlp4 (standard syntax) 88 | #camlp4r;; to load camlp4 (revised syntax) 89 | Topfind.reset();; to force that packages will be reloaded 90 | 91 | - : unit = () 92 | # _ 93 | 94 | 95 | 96 | This works even in scripts (but the startup message is suppressed in this 97 | case). 98 | 99 | 100 | 101 | The module is not thread-safe; if used in a multi-threaded script, all 102 | packgage loading must have happened before the first thread forks. 103 | 104 | 105 | 106 | 107 | 108 | DESCRIPTION 109 | 110 | 111 | The Topfind module contains some functions simplifying package loading 112 | in scripts. Most important, there is a new directive "#require" for 113 | the same purpose. 114 | 115 | 116 | 117 | The Topfind module needs some initialization, in particular the predicates variable needs to be 119 | set, and the packages already compiled into the toploop needs to be 120 | declared by the don't_load 121 | function. If the toploop has been built by , the necessary initialization is 123 | automatically compiled in. 124 | 125 | 126 | 127 | 128 | <anchor id="Topfind.predicates"> 129 | The variable Topfind.predicates 130 | 131 | 132 | val predicates : string list ref 133 | 134 | 135 | The variable contains the set of predicates that is assumed when 136 | packages are loaded. 137 | 138 | 139 | 140 | 141 | 142 | <anchor id="Topfind.add-predicates"> 143 | Topfind.add_predicates <replaceable>predlist</replaceable> 144 | 145 | 146 | val add_predicates : string list -> unit 147 | 148 | 149 | This function adds the passed predicates predlist 150 | to the variable 151 | predicates. 152 | 153 | 154 | 155 | 156 | 157 | <anchor id="Topfind.syntax"> 158 | Topfind.syntax <replaceable>variant</replaceable> 159 | 160 | 161 | val syntax : string -> unit 162 | 163 | 164 | This function emulates the -syntax command line 165 | switch of ocamlfind. 166 | 167 | 168 | 169 | 170 | 171 | <anchor id="Topfind.standard-syntax"> 172 | Topfind.standard_syntax () 173 | 174 | 175 | val standard_syntax : unit -> unit 176 | 177 | 178 | The same as syntax "camlp4o". 179 | 180 | 181 | 182 | 183 | 184 | <anchor id="Topfind.revised-syntax"> 185 | Topfind.revised_syntax () 186 | 187 | 188 | val revised_syntax : unit -> unit 189 | 190 | 191 | The same as syntax "camlp4r". 192 | 193 | 194 | 195 | 196 | 197 | <anchor id="Topfind.dont-load"> 198 | Topfind.don't_load <replaceable>pkglist</replaceable> 199 | 200 | 201 | val don't_load : string list -> unit 202 | 203 | 204 | Declares the packages enumerated in pkglist 205 | as being linked into the toploop. 206 | 207 | 208 | 209 | 210 | 211 | <anchor id="Topfind.dont-load-deeply"> 212 | Topfind.don't_load_deeply <replaceable>pkglist</replaceable> 213 | 214 | 215 | val don't_load_deeply : string list -> unit 216 | 217 | 218 | Declares the packages enumerated in pkglist 219 | and all direct and indirect ancestors as being linked into the toploop. 220 | 221 | 222 | 223 | 224 | 225 | <anchor id="Topfind.load"> 226 | Topfind.load <replaceable>pkglist</replaceable> 227 | 228 | 229 | val load : string list -> unit 230 | 231 | 232 | The packages enumerated in pkglist are 233 | loaded in turn; packages that have already been loaded or that have 234 | been declared as linked in are skipped. 235 | 236 | 237 | 238 | 239 | 240 | <anchor id="Topfind.load-deeply"> 241 | Topfind.load_deeply <replaceable>pkglist</replaceable> 242 | 243 | 244 | val load_deeply : string list -> unit 245 | 246 | 247 | The packages enumerated in pkglist and all 248 | direct or indirect ancestors are loaded in topological order; 249 | packages that have already been loaded or that have 250 | been declared as linked in are skipped. 251 | 252 | 253 | 254 | 255 | 256 | <anchor id="Topfind.reset"> 257 | Topfind.reset () 258 | 259 | 260 | val reset : unit -> unit 261 | 262 | 263 | This function causes that Topfind forgets that any package has already 264 | been loaded. Infomation about packages linked into the toploop remain 265 | intact. The effect of this function is that all dynamically loaded 266 | packages will be loaded again when load, load_deeply functions, or the 269 | #require directive are executed. 270 | 271 | 272 | 273 | 274 | 275 | 276 | <anchor id="Topfind.require"> 277 | #require "<replaceable>package-name-list</replaceable>";; 278 | 279 | 280 | #require "package-name-list";; 281 | 282 | 283 | The argument of the directive is a list of package names, separated by 284 | commas and/or whitespace. The directive has the same effect as load_deeply, i.e. the listed 286 | packages and all 287 | direct or indirect ancestors are loaded in topological order; 288 | packages that have already been loaded or that have 289 | been declared as linked in are skipped. 290 | 291 | 292 | 293 | 294 | 295 | <anchor id="Topfind.camlp4o"> 296 | #camlp4o ;; 297 | 298 | 299 | #camlp4o ;; 300 | 301 | 302 | Selects the standard syntax and loads the camlp4 preprocessor. 303 | 304 | 305 | 306 | 307 | 308 | <anchor id="Topfind.camlp4r"> 309 | #camlp4r ;; 310 | 311 | 312 | #camlp4r ;; 313 | 314 | 315 | Selects the revised syntax and loads the camlp4 preprocessor. 316 | 317 | 318 | 319 | 320 | <anchor id="Topfind.list"> 321 | #list ;; 322 | 323 | 324 | #list ;; 325 | 326 | 327 | Lists the packages that are in the search path. 328 | 329 | 330 | 331 | 332 | 333 | 334 | -------------------------------------------------------------------------------- /src/findlib/topfind.ml.in: -------------------------------------------------------------------------------- 1 | (* $Id$ 2 | * ---------------------------------------------------------------------- 3 | * 4 | *) 5 | 6 | let predicates = ref ("toploop" :: Findlib.recorded_predicates());; 7 | (* We also want things like "syntax" here which are not allowed in 8 | Findlib, hence we maintain our own list 9 | *) 10 | 11 | let ocaml_stdlib = lazy (Findlib.ocaml_stdlib ());; 12 | let directories = ref [ ] ;; 13 | 14 | 15 | (* Note: Sys.interactive is always _true_ during toploop startup. 16 | * When a script is executed, it is set to false just before the 17 | * script starts. This is important for ocamlmktop-generated toploops: 18 | * For initialization code linked into the toploop, Sys.interactive 19 | * is _true_. It is set to false just before the script starts. 20 | *) 21 | 22 | let real_toploop = 23 | !Sys.interactive;; 24 | 25 | let log = ref (if real_toploop then prerr_endline else ignore) 26 | 27 | let rec remove_dups l = 28 | match l with 29 | x :: l' -> 30 | if List.mem x l' then remove_dups l' else x::remove_dups l' 31 | | [] -> [] 32 | ;; 33 | 34 | let add_predicates pl = 35 | predicates := remove_dups (pl @ !predicates); 36 | Findlib.record_package_predicates !predicates;; 37 | 38 | let syntax s = 39 | add_predicates [ "syntax"; s ];; 40 | 41 | let standard_syntax () = syntax "camlp4o";; 42 | let revised_syntax () = syntax "camlp4r";; 43 | 44 | 45 | let add_dir d = 46 | let d = Fl_split.norm_dir d in 47 | let ocaml_stdlib = Lazy.force ocaml_stdlib in 48 | if d <> ocaml_stdlib && not (List.mem d !directories) then begin 49 | Topdirs.dir_directory d; 50 | directories := d :: !directories; 51 | !log (d ^ ": added to search path") 52 | end 53 | ;; 54 | 55 | let exec_string s = 56 | let l = Lexing.from_string s in 57 | let ph = !Toploop.parse_toplevel_phrase l in 58 | (* PPXOPT_BEGIN *) 59 | let ph = Toploop.preprocess_phrase Format.err_formatter ph in 60 | (* PPXOPT_END *) 61 | let fmt = Format.make_formatter (fun _ _ _ -> ()) (fun _ -> ()) in 62 | try 63 | Toploop.execute_phrase false fmt ph 64 | with 65 | _ -> false 66 | ;; 67 | 68 | let load pkglist = 69 | List.iter 70 | (fun pkg -> 71 | let _stdlibdir = Findlib.ocaml_stdlib() in 72 | let loaded = 73 | Findlib.is_recorded_package pkg && 74 | Findlib.type_of_recorded_package pkg = Findlib.Record_load in 75 | let incore = 76 | Findlib.is_recorded_package pkg && 77 | Findlib.type_of_recorded_package pkg = Findlib.Record_core in 78 | if not loaded then begin 79 | (* Determine the package directory: *) 80 | let d = Findlib.package_directory pkg in 81 | add_dir d; 82 | (* Leave pkg out if mentioned in !forbidden *) 83 | if not incore then begin 84 | (* Determine the 'archive' property: *) 85 | let archive = 86 | try Findlib.package_property !predicates pkg "archive" 87 | with 88 | Not_found -> "" 89 | in 90 | (* Split the 'archive' property and load the files: *) 91 | let archives = Fl_split.in_words archive in 92 | List.iter 93 | (fun arch -> 94 | let arch' = Findlib.resolve_path ~base:d arch in 95 | !log (arch' ^ ": loaded"); 96 | Topdirs.dir_load 97 | Format.std_formatter arch') 98 | archives; 99 | (* Determine the 'ppx' property: *) 100 | let ppx = 101 | try 102 | Some(Findlib.resolve_path 103 | ~base:d ~explicit:true 104 | (Findlib.package_property !predicates pkg "ppx") 105 | ) 106 | with Not_found -> None 107 | and ppxopts = 108 | try 109 | List.map 110 | (fun opt -> 111 | match Fl_split.in_words opt with 112 | | pkg :: opts -> 113 | pkg, 114 | List.map 115 | (Findlib.resolve_path ~base:d ~explicit:true) opts 116 | | _ -> assert false) 117 | (Fl_split.in_words_ws 118 | (Findlib.package_property !predicates pkg "ppxopt")) 119 | with Not_found -> [] in 120 | (* Feed the 'ppx' property into the toplevel. To remain compatible 121 | with pre-4.01 OCaml, construct and execute a phrase instead of directly 122 | altering Clflags. *) 123 | begin match ppx with 124 | | Some ppx -> 125 | 126 | 127 | begin try 128 | match Hashtbl.find Toploop.directive_table "ppx" with 129 | | Toploop.Directive_string fn -> 130 | fn ppx; !log (ppx ^ ": activated") 131 | | _ -> assert false 132 | with Not_found -> 133 | failwith "Package defines a ppx preprocessor, but OCaml is too old. \ 134 | Use OCaml >= 4.02.0 for ppx support." 135 | end 136 | | None -> () 137 | end; 138 | (* Feed the 'ppxopt' property into the toplevel. *) 139 | match ppxopts with 140 | | [] -> () 141 | | _ -> 142 | (* PPXOPT_BEGIN *) 143 | List.iter 144 | (fun (pkg, opts) -> 145 | ignore (exec_string ("[@@@findlib.ppxopt " ^ 146 | (String.concat ", " 147 | (List.map (Printf.sprintf "%S") (pkg :: opts))) ^ 148 | "];;")); 149 | !log (pkg ^ ": " ^ (String.concat " " opts) ^ 150 | ": option added")) 151 | ppxopts 152 | (* 153 | (* PPXOPT_END *) 154 | failwith "Package defines a ppx preprocessor option, but OCaml is too old. \ 155 | Use OCaml >=4.02.1 for ppxopt support." 156 | (* PPXOPT_BEGIN *) 157 | *) 158 | (* PPXOPT_END *) 159 | end; 160 | (* The package is loaded: *) 161 | Findlib.record_package Findlib.Record_load pkg 162 | end) 163 | pkglist 164 | ;; 165 | 166 | 167 | let load_deeply pkglist = 168 | (* Get the sorted list of ancestors *) 169 | let eff_pkglist = 170 | Findlib.package_deep_ancestors !predicates pkglist in 171 | List.iter (fun pkg -> 172 | try let error = Findlib.package_property !predicates pkg "error" in 173 | failwith ("Error from package `" ^ pkg ^ "': " ^ error) 174 | with Not_found -> ()) eff_pkglist ; 175 | (* Load the packages in turn: *) 176 | load eff_pkglist 177 | ;; 178 | 179 | 180 | let check_existence pkglist = 181 | List.iter 182 | (fun pkg -> 183 | let _ = Findlib.package_directory pkg in () 184 | ) 185 | pkglist 186 | ;; 187 | 188 | 189 | let don't_load pkglist = 190 | check_existence pkglist; 191 | List.iter (Findlib.record_package Findlib.Record_core) pkglist 192 | ;; 193 | 194 | 195 | let don't_load_deeply pkglist = 196 | (* Check if packages exist: *) 197 | check_existence pkglist; 198 | (* Get the sorted list of ancestors *) 199 | let eff_pkglist = 200 | Findlib.package_deep_ancestors !predicates pkglist in 201 | (* Add this to the list of core packages: *) 202 | List.iter (Findlib.record_package Findlib.Record_core) eff_pkglist 203 | ;; 204 | 205 | 206 | let reset() = 207 | Findlib.reset_recordings() 208 | ;; 209 | 210 | 211 | let have_mt_support() = 212 | Findlib.package_property [] "threads" "type_of_threads" = "posix" 213 | ;; 214 | 215 | 216 | let load_mt_support() = 217 | (* Load only if package "threads" is not yet loaded. *) 218 | if not(Findlib.is_recorded_package "threads") then ( 219 | (* This works only for POSIX threads. *) 220 | if have_mt_support() then ( 221 | add_predicates ["mt"; "mt_posix"]; 222 | add_dir (Filename.concat (Findlib.ocaml_stdlib()) "threads"); 223 | load_deeply ["unix"]; 224 | load_deeply ["threads"]; 225 | ) 226 | else ( 227 | failwith "It is not possible to load support for vmthreads dynamically. Use\n 228 | 'ocamlfind ocamlmktop -o vmtop -package threads,findlib -linkpkg -vmthread'\n 229 | to create a toploop with integrated vmthreads library." 230 | ) 231 | ) 232 | ;; 233 | 234 | 235 | let list_packages() = 236 | Findlib.list_packages stdout; 237 | flush stdout 238 | ;; 239 | 240 | 241 | let protect f arg = 242 | try 243 | let _ = f arg in () 244 | with 245 | Failure s -> 246 | print_endline s 247 | | Fl_package_base.No_such_package(pkg, reason) -> 248 | print_endline ("No such package: " ^ pkg ^ 249 | (if reason <> "" then " - " ^ reason else "")) 250 | | Fl_package_base.Package_loop pkg -> 251 | print_endline ("Package requires itself: " ^ pkg) 252 | ;; 253 | 254 | 255 | (* Add "#require" directive: *) 256 | 257 | Hashtbl.add 258 | Toploop.directive_table 259 | "require" 260 | (Toploop.Directive_string 261 | (fun s -> 262 | protect load_deeply (Fl_split.in_words s) 263 | )) 264 | ;; 265 | 266 | (* Add "#predicates" directive: *) 267 | Hashtbl.add 268 | Toploop.directive_table 269 | "predicates" 270 | (Toploop.Directive_string 271 | (fun s -> 272 | protect add_predicates (Fl_split.in_words s) 273 | )) 274 | ;; 275 | 276 | 277 | (* Add "#camlp4o" directive: *) 278 | 279 | Hashtbl.add 280 | Toploop.directive_table 281 | "camlp4o" 282 | (Toploop.Directive_none 283 | (fun () -> 284 | protect (fun () -> 285 | standard_syntax(); 286 | load_deeply ["camlp4"]) () 287 | )) 288 | ;; 289 | 290 | (* Add "#camlp4r" directive: *) 291 | 292 | Hashtbl.add 293 | Toploop.directive_table 294 | "camlp4r" 295 | (Toploop.Directive_none 296 | (fun () -> 297 | protect (fun () -> 298 | revised_syntax(); 299 | load_deeply ["camlp4"]) () 300 | )) 301 | ;; 302 | 303 | 304 | (* Add "#list" directive: *) 305 | 306 | Hashtbl.add 307 | Toploop.directive_table 308 | "list" 309 | (Toploop.Directive_none 310 | (fun () -> 311 | protect list_packages () 312 | )) 313 | ;; 314 | 315 | 316 | (* Add "#thread" directive: *) 317 | 318 | Hashtbl.add 319 | Toploop.directive_table 320 | "thread" 321 | (Toploop.Directive_none 322 | (fun () -> 323 | protect load_mt_support () 324 | )) 325 | ;; 326 | 327 | 328 | let announce() = 329 | if real_toploop then begin 330 | (* Assume we are in a toploop and not a script *) 331 | let msg_thread = 332 | " #thread;; to enable threads\n" in 333 | print_endline 334 | ("Findlib has been successfully loaded. Additional directives:\n" ^ 335 | " #require \"package\";; to load a package\n" ^ 336 | " #list;; to list the available packages\n" ^ 337 | " #camlp4o;; to load camlp4 (standard syntax)\n" ^ 338 | " #camlp4r;; to load camlp4 (revised syntax)\n" ^ 339 | " #predicates \"p,q,...\";; to set these predicates\n" ^ 340 | " Topfind.reset();; to force that packages will be reloaded\n" ^ 341 | (if have_mt_support() then msg_thread else "")) 342 | end ;; 343 | -------------------------------------------------------------------------------- /src/findlib/fl_metascanner.ml: -------------------------------------------------------------------------------- 1 | (* $Id$ -*- tuareg -*- 2 | * ---------------------------------------------------------------------- 3 | * 4 | *) 5 | open Fl_metatoken 6 | 7 | open Printf 8 | 9 | type formal_pred = [ | `Pred of string | `NegPred of string ] 10 | 11 | type flavour = [ | `BaseDef | `Appendix ] 12 | 13 | type pkg_definition = 14 | { def_var : string; def_flav : flavour; def_preds : formal_pred list; 15 | def_value : string 16 | } 17 | 18 | type pkg_expr = 19 | { pkg_defs : pkg_definition list; pkg_children : (string * pkg_expr) list 20 | } 21 | 22 | exception Error of string 23 | 24 | let string_of_preds pl = 25 | let print = function | `Pred n -> n | `NegPred n -> "-" ^ n 26 | in 27 | if pl = [] 28 | then "" 29 | else "(" ^ ((String.concat "," (List.map print pl)) ^ ")") 30 | 31 | 32 | let scan_lexing buf = 33 | (* transform an in_channel to a token stream; 'Space' tokens are left 34 | * out. 35 | *) 36 | let (line_ref, pos0_ref, eof_found) = ((ref 1), (ref 0), (ref false)) 37 | in 38 | fun () -> 39 | let rec next line pos0 = 40 | let t = Fl_meta.token buf 41 | in 42 | match t with 43 | | Space -> next line pos0 44 | | Newline -> next (line + 1) (Lexing.lexeme_end buf) 45 | | Eof -> (eof_found := true; produce line pos0 Eof) 46 | | _ -> produce line pos0 t 47 | and produce line pos0 t = 48 | (line_ref := line; 49 | pos0_ref := pos0; 50 | let pos = (Lexing.lexeme_start buf) - pos0 in (line, pos, t)) 51 | in 52 | if !eof_found 53 | then produce !line_ref !pos0_ref Eof 54 | else next !line_ref !pos0_ref 55 | 56 | let scan ch = scan_lexing (Lexing.from_channel ch) 57 | 58 | let parse_lexing lexbuf = 59 | let rec mk_set l = 60 | match l with 61 | | x :: l' -> if List.mem x l' then mk_set l' else x :: (mk_set l') 62 | | [] -> [] in 63 | let error_msg msg line col = 64 | Printf.sprintf "%s at line %d position %d" msg line col in 65 | let next_token = scan_lexing lexbuf in 66 | let raise_err error_fun line col = 67 | raise (Error (error_fun line col)) in 68 | let get_tok test error_fun = 69 | let (line, col, tok) = next_token () 70 | in 71 | match test tok with 72 | | None -> raise_err error_fun line col 73 | | Some result -> result in 74 | let get_rule rule arg error_fmt line col = 75 | try rule arg with | Error _ -> raise_err error_fmt line col in 76 | let rec parse_all need_rparen = 77 | match next_token () with 78 | | (line, col, Name "package") -> 79 | let n = 80 | get_tok string_tok 81 | (error_msg "String literal expected after 'package'") in 82 | let () = 83 | get_tok (const_tok LParen) (error_msg "'(' expected after string") in 84 | let subpkg = 85 | get_rule parse_all true 86 | (error_msg "Error in subpackage definition") line col in 87 | let rest = parse_all need_rparen 88 | in 89 | { 90 | pkg_defs = rest.pkg_defs; 91 | pkg_children = (n, subpkg) :: rest.pkg_children; 92 | } 93 | | (line, col, Name n) -> 94 | let (args, flav, value) = 95 | get_rule parse_properties () 96 | (error_msg "Error in 'name = value' clause") line col in 97 | let rest = parse_all need_rparen in (* TODO: Check args *) 98 | let args' = List.sort compare (mk_set args) in 99 | let def = 100 | { 101 | def_var = n; 102 | def_flav = flav; 103 | def_preds = args'; 104 | def_value = value; 105 | } 106 | in 107 | { 108 | pkg_defs = def :: rest.pkg_defs; 109 | pkg_children = rest.pkg_children; 110 | } 111 | | (line, col, Eof) -> 112 | (if need_rparen 113 | then 114 | raise_err 115 | (Printf.sprintf "Unexpected end of file in line %d position %d") 116 | line col 117 | else (); 118 | { pkg_defs = []; pkg_children = []; }) 119 | | (line, col, RParen) -> 120 | (if not need_rparen 121 | then 122 | raise_err 123 | (Printf.sprintf "Unexpected end of file in line %d position %d") 124 | line col 125 | else (); 126 | { pkg_defs = []; pkg_children = []; }) 127 | | (line, col, _) -> 128 | raise_err (error_msg "Expected 'name = value' clause") line col 129 | and parse_properties () = 130 | match next_token () with 131 | | (line, col, LParen) -> 132 | let arg1 = parse_argument () in 133 | let args = parse_arguments () in 134 | let flav = parse_flavour () in 135 | let s = 136 | get_tok string_tok (error_msg "Expected string constant after '='") 137 | in ((arg1 :: args), flav, s) 138 | | (line, col, Equal) -> 139 | let s = 140 | get_tok string_tok 141 | (error_msg "'=' must be followed by a string constant") 142 | in ([], `BaseDef, s) 143 | | (line, col, PlusEqual) -> 144 | let s = 145 | get_tok string_tok 146 | (error_msg "'+=' must be followed by a string constant") 147 | in ([], `Appendix, s) 148 | | (line, col, _) -> 149 | raise_err (error_msg "Expected a '=' or a '(arguments,...)=' clause") 150 | line col 151 | and parse_arguments () = 152 | match next_token () with 153 | | (line, col, Comma) -> 154 | let arg = parse_argument () in 155 | let args = parse_arguments () in arg :: args 156 | | (_, _, RParen) -> [] 157 | | (line, col, _) -> 158 | raise_err (error_msg "Another predicate or a ')' expected") line col 159 | and parse_argument () = 160 | match next_token () with 161 | | (line, col, Name n) -> `Pred n 162 | | (line, col, Minus) -> 163 | let n = get_tok name_tok (error_msg "Name expected after '-'") 164 | in `NegPred n 165 | | (line, col, _) -> 166 | raise_err (error_msg "Name or -Name expected") line col 167 | and parse_flavour () = 168 | match next_token () with 169 | | (line, col, Equal) -> `BaseDef 170 | | (line, col, PlusEqual) -> `Appendix 171 | | (line, col, _) -> raise_err (error_msg "'+' or '+=' expected") line col in 172 | let rec check_defs p l = 173 | match l with 174 | | [] -> () 175 | | def :: l' -> 176 | (List.iter 177 | (fun def' -> 178 | if 179 | (def.def_var = def'.def_var) && 180 | ((def.def_preds = def'.def_preds) && 181 | ((def.def_flav = `BaseDef) && (def'.def_flav = `BaseDef))) 182 | then 183 | (let prefix = 184 | if p = "" then "" else "In subpackage " ^ (p ^ ": ") in 185 | let args = string_of_preds def.def_preds 186 | in 187 | raise 188 | (Error 189 | (prefix ^ 190 | ("Double definition of '" ^ 191 | (def.def_var ^ (args ^ "'")))))) 192 | else ()) 193 | l'; 194 | check_defs p l') in 195 | let rec check_pkg p pkg = 196 | (check_defs p pkg.pkg_defs; 197 | let l = ref [] 198 | in 199 | List.iter 200 | (fun (n, subpkg) -> 201 | let p' = if p = "" then n else p ^ ("." ^ n) 202 | in 203 | (if List.mem n !l 204 | then 205 | raise 206 | (Error ("Double definition for subpackage " ^ p')) 207 | else (); 208 | if String.contains n '.' 209 | then 210 | raise 211 | (Error 212 | ("Subpackage name must not contain '.': \"" ^ 213 | (n ^ "\""))) 214 | else (); 215 | check_pkg p' subpkg; 216 | l := n :: !l)) 217 | pkg.pkg_children) 218 | in 219 | try let pkg = parse_all false in (check_pkg "" pkg; pkg) 220 | with | Error "" -> raise (Error "Syntax Error") 221 | 222 | let parse ch = parse_lexing (Lexing.from_channel ch) 223 | 224 | let escape s = (* no Str available :-( *) 225 | let b = Buffer.create (String.length s) 226 | in 227 | (for k = 0 to (String.length s) - 1 do 228 | (match s.[k] with 229 | | '\\' -> Buffer.add_string b "\\\\" 230 | | '"' -> Buffer.add_string b "\\\"" 231 | | c -> Buffer.add_char b c) 232 | done; 233 | Buffer.contents b) 234 | 235 | let print_def f def = 236 | let format_pred = function | `Pred s -> s | `NegPred s -> "-" ^ s in 237 | fprintf f "%s%s %s \"%s\"\n" def.def_var 238 | (match def.def_preds with 239 | | [] -> "" 240 | | l -> "(" ^ ((String.concat "," (List.map format_pred l)) ^ ")")) 241 | (match def.def_flav with | `BaseDef -> "=" | `Appendix -> "+=") 242 | (escape def.def_value) 243 | 244 | 245 | let rec print f pkg = 246 | (List.iter (print_def f) pkg.pkg_defs; 247 | List.iter 248 | (fun (name, child) -> 249 | (fprintf f "\npackage \"%s\" (\n" (escape name); 250 | print f child; 251 | fprintf f ")\n")) 252 | pkg.pkg_children) 253 | 254 | let rec remove_dups l = 255 | (* FIXME: O(n^2) *) 256 | match l with 257 | x :: l' -> 258 | if List.mem x l' then remove_dups l' else x::remove_dups l' 259 | | [] -> [] 260 | 261 | let lookup_2 name predicate_list def = 262 | let fulfills actual_preds formal_preds = 263 | List.for_all 264 | (function 265 | | `Pred n -> List.mem n predicate_list 266 | | `NegPred n -> not (List.mem n predicate_list)) 267 | formal_preds in 268 | let rec search_base best_n best_value l = 269 | match l with 270 | | [] -> if best_n >= 0 then best_value else raise Not_found 271 | | def :: l' -> 272 | if 273 | (name = def.def_var) && 274 | ((def.def_flav = `BaseDef) && 275 | ((fulfills predicate_list def.def_preds) && 276 | ((List.length def.def_preds) > best_n))) 277 | then search_base 278 | (List.length def.def_preds) 279 | (def.def_value, def.def_preds) 280 | l' 281 | else search_base best_n best_value l' in 282 | let rec search_appdx l = 283 | match l with 284 | | [] -> [] 285 | | def :: l' -> 286 | if 287 | (name = def.def_var) && 288 | ((def.def_flav = `Appendix) && 289 | (fulfills predicate_list def.def_preds)) 290 | then (def.def_value, def.def_preds) :: (search_appdx l') 291 | else search_appdx l' in 292 | let value_a, preds_a = search_base (-1) ("",[]) def in 293 | let additions = search_appdx def in 294 | let values_b = List.map fst additions in 295 | let preds_b = List.flatten (List.map snd additions) in 296 | let value = String.concat " " (value_a :: values_b) in 297 | let preds = remove_dups (preds_a @ preds_b) in 298 | (value, preds) 299 | 300 | let lookup name predicate_list def = 301 | fst(lookup_2 name predicate_list def) 302 | 303 | let predicate_exists p defs = 304 | List.exists 305 | (fun def -> 306 | List.exists (function | `Pred n -> n = p | `NegPred n -> n = p) 307 | def.def_preds) 308 | defs 309 | 310 | 311 | --------------------------------------------------------------------------------