summaryrefslogtreecommitdiff
path: root/ocaml-binary-annot/ocamldoc
diff options
context:
space:
mode:
Diffstat (limited to 'ocaml-binary-annot/ocamldoc')
-rw-r--r--ocaml-binary-annot/ocamldoc/.cvsignore17
-rw-r--r--ocaml-binary-annot/ocamldoc/.depend253
-rw-r--r--ocaml-binary-annot/ocamldoc/Changes.txt209
-rw-r--r--ocaml-binary-annot/ocamldoc/Makefile371
-rw-r--r--ocaml-binary-annot/ocamldoc/Makefile.nt272
-rw-r--r--ocaml-binary-annot/ocamldoc/generators/odoc_literate.ml207
-rw-r--r--ocaml-binary-annot/ocamldoc/generators/odoc_todo.ml225
-rw-r--r--ocaml-binary-annot/ocamldoc/ocamldoc.hva19
-rw-r--r--ocaml-binary-annot/ocamldoc/ocamldoc.sty58
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc.ml137
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_analyse.ml539
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_analyse.mli31
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_args.ml245
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_args.mli27
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_ast.ml1738
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_ast.mli104
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_class.ml253
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_comments.ml348
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_comments.mli74
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_comments_global.ml51
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_comments_global.mli50
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_config.ml18
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_config.mli20
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_control.ml12
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_cross.ml1006
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_cross.mli20
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_dag2html.ml1750
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_dag2html.mli29
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_dep.ml219
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_dot.ml146
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_env.ml249
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_env.mli76
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_exception.ml30
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_gen.ml38
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_gen.mli22
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_global.ml89
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_global.mli104
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_html.ml2577
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_info.ml323
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_info.mli988
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_inherit.ml12
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_latex.ml1201
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_latex_style.ml91
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_lexer.mll413
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_man.ml1089
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_merge.ml988
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_merge.mli35
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_messages.ml357
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_misc.ml494
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_misc.mli115
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_module.ml535
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_name.ml217
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_name.mli69
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_ocamlhtml.mll545
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_parameter.ml123
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_parser.mly176
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_print.ml104
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_print.mli32
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_scan.ml156
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_search.ml636
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_search.mli199
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_see_lexer.mll102
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_sig.ml1305
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_sig.mli177
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_str.ml277
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_str.mli51
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_test.ml118
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_texi.ml1244
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_text.ml164
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_text.mli24
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_text_lexer.mll798
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_text_parser.mly197
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_to_text.ml603
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_type.ml55
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_types.ml136
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_types.mli136
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_value.ml144
-rwxr-xr-xocaml-binary-annot/ocamldoc/remove_DEBUG22
-rw-r--r--ocaml-binary-annot/ocamldoc/runocamldoc12
79 files changed, 26096 insertions, 0 deletions
diff --git a/ocaml-binary-annot/ocamldoc/.cvsignore b/ocaml-binary-annot/ocamldoc/.cvsignore
new file mode 100644
index 0000000000..0372a09821
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/.cvsignore
@@ -0,0 +1,17 @@
+ocamldoc
+ocamldoc.opt
+odoc_crc.ml
+odoc_lexer.ml
+odoc_ocamlhtml.ml
+odoc_parser.ml
+odoc_parser.mli
+odoc_see_lexer.ml
+odoc_text_lexer.ml
+odoc_text_parser.ml
+odoc_text_parser.mli
+stdlib_man
+*.output
+test_stdlib
+test_latex
+test
+*.a
diff --git a/ocaml-binary-annot/ocamldoc/.depend b/ocaml-binary-annot/ocamldoc/.depend
new file mode 100644
index 0000000000..6467d445b3
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/.depend
@@ -0,0 +1,253 @@
+odoc.cmo: ../typing/typedtree.cmi odoc_messages.cmo odoc_info.cmi \
+ odoc_global.cmi odoc_gen.cmi odoc_config.cmi odoc_args.cmi \
+ odoc_analyse.cmi ../utils/misc.cmi ../utils/config.cmi \
+ ../utils/clflags.cmi
+odoc.cmx: ../typing/typedtree.cmx odoc_messages.cmx odoc_info.cmx \
+ odoc_global.cmx odoc_gen.cmx odoc_config.cmx odoc_args.cmx \
+ odoc_analyse.cmx ../utils/misc.cmx ../utils/config.cmx \
+ ../utils/clflags.cmx
+odoc_analyse.cmo: ../utils/warnings.cmi ../typing/typetexp.cmi \
+ ../typing/types.cmi ../typing/typemod.cmi ../typing/typedtree.cmi \
+ ../typing/typedecl.cmi ../typing/typecore.cmi ../typing/typeclass.cmi \
+ ../bytecomp/translcore.cmi ../bytecomp/translclass.cmi \
+ ../parsing/syntaxerr.cmi ../parsing/parse.cmi odoc_types.cmi \
+ odoc_text.cmi odoc_sig.cmi odoc_module.cmo odoc_misc.cmi \
+ odoc_messages.cmo odoc_merge.cmi odoc_global.cmi odoc_dep.cmo \
+ odoc_cross.cmi odoc_comments.cmi odoc_class.cmo odoc_ast.cmi \
+ ../utils/misc.cmi ../parsing/location.cmi ../parsing/lexer.cmi \
+ ../typing/includemod.cmi ../typing/env.cmi ../typing/ctype.cmi \
+ ../utils/config.cmi ../utils/clflags.cmi ../utils/ccomp.cmi \
+ odoc_analyse.cmi
+odoc_analyse.cmx: ../utils/warnings.cmx ../typing/typetexp.cmx \
+ ../typing/types.cmx ../typing/typemod.cmx ../typing/typedtree.cmx \
+ ../typing/typedecl.cmx ../typing/typecore.cmx ../typing/typeclass.cmx \
+ ../bytecomp/translcore.cmx ../bytecomp/translclass.cmx \
+ ../parsing/syntaxerr.cmx ../parsing/parse.cmx odoc_types.cmx \
+ odoc_text.cmx odoc_sig.cmx odoc_module.cmx odoc_misc.cmx \
+ odoc_messages.cmx odoc_merge.cmx odoc_global.cmx odoc_dep.cmx \
+ odoc_cross.cmx odoc_comments.cmx odoc_class.cmx odoc_ast.cmx \
+ ../utils/misc.cmx ../parsing/location.cmx ../parsing/lexer.cmx \
+ ../typing/includemod.cmx ../typing/env.cmx ../typing/ctype.cmx \
+ ../utils/config.cmx ../utils/clflags.cmx ../utils/ccomp.cmx \
+ odoc_analyse.cmi
+odoc_args.cmo: odoc_types.cmi odoc_texi.cmo odoc_messages.cmo odoc_man.cmo \
+ odoc_latex.cmo odoc_html.cmo odoc_global.cmi odoc_gen.cmi odoc_dot.cmo \
+ odoc_config.cmi ../utils/misc.cmi ../utils/config.cmi odoc_args.cmi
+odoc_args.cmx: odoc_types.cmx odoc_texi.cmx odoc_messages.cmx odoc_man.cmx \
+ odoc_latex.cmx odoc_html.cmx odoc_global.cmx odoc_gen.cmx odoc_dot.cmx \
+ odoc_config.cmx ../utils/misc.cmx ../utils/config.cmx odoc_args.cmi
+odoc_ast.cmo: ../typing/types.cmi ../typing/typedtree.cmi \
+ ../typing/predef.cmi ../typing/path.cmi ../parsing/parsetree.cmi \
+ odoc_value.cmo odoc_types.cmi odoc_type.cmo odoc_sig.cmi \
+ odoc_parameter.cmo odoc_name.cmi odoc_module.cmo odoc_messages.cmo \
+ odoc_global.cmi odoc_exception.cmo odoc_env.cmi odoc_class.cmo \
+ ../utils/misc.cmi ../parsing/location.cmi ../typing/ident.cmi \
+ ../parsing/asttypes.cmi odoc_ast.cmi
+odoc_ast.cmx: ../typing/types.cmx ../typing/typedtree.cmx \
+ ../typing/predef.cmx ../typing/path.cmx ../parsing/parsetree.cmi \
+ odoc_value.cmx odoc_types.cmx odoc_type.cmx odoc_sig.cmx \
+ odoc_parameter.cmx odoc_name.cmx odoc_module.cmx odoc_messages.cmx \
+ odoc_global.cmx odoc_exception.cmx odoc_env.cmx odoc_class.cmx \
+ ../utils/misc.cmx ../parsing/location.cmx ../typing/ident.cmx \
+ ../parsing/asttypes.cmi odoc_ast.cmi
+odoc_class.cmo: ../typing/types.cmi odoc_value.cmo odoc_types.cmi \
+ odoc_parameter.cmo odoc_name.cmi
+odoc_class.cmx: ../typing/types.cmx odoc_value.cmx odoc_types.cmx \
+ odoc_parameter.cmx odoc_name.cmx
+odoc_comments.cmo: odoc_types.cmi odoc_text.cmi odoc_see_lexer.cmo \
+ odoc_parser.cmi odoc_misc.cmi odoc_messages.cmo odoc_merge.cmi \
+ odoc_lexer.cmo odoc_global.cmi odoc_cross.cmi odoc_comments_global.cmi \
+ odoc_comments.cmi
+odoc_comments.cmx: odoc_types.cmx odoc_text.cmx odoc_see_lexer.cmx \
+ odoc_parser.cmx odoc_misc.cmx odoc_messages.cmx odoc_merge.cmx \
+ odoc_lexer.cmx odoc_global.cmx odoc_cross.cmx odoc_comments_global.cmx \
+ odoc_comments.cmi
+odoc_comments_global.cmo: odoc_comments_global.cmi
+odoc_comments_global.cmx: odoc_comments_global.cmi
+odoc_config.cmo: ../utils/config.cmi odoc_config.cmi
+odoc_config.cmx: ../utils/config.cmx odoc_config.cmi
+odoc_control.cmo:
+odoc_control.cmx:
+odoc_cross.cmo: odoc_value.cmo odoc_types.cmi odoc_type.cmo odoc_search.cmi \
+ odoc_scan.cmo odoc_parameter.cmo odoc_name.cmi odoc_module.cmo \
+ odoc_misc.cmi odoc_messages.cmo odoc_global.cmi odoc_exception.cmo \
+ odoc_class.cmo odoc_cross.cmi
+odoc_cross.cmx: odoc_value.cmx odoc_types.cmx odoc_type.cmx odoc_search.cmx \
+ odoc_scan.cmx odoc_parameter.cmx odoc_name.cmx odoc_module.cmx \
+ odoc_misc.cmx odoc_messages.cmx odoc_global.cmx odoc_exception.cmx \
+ odoc_class.cmx odoc_cross.cmi
+odoc_dag2html.cmo: odoc_info.cmi odoc_dag2html.cmi
+odoc_dag2html.cmx: odoc_info.cmx odoc_dag2html.cmi
+odoc_dep.cmo: ../parsing/parsetree.cmi odoc_type.cmo odoc_print.cmi \
+ odoc_module.cmo ../tools/depend.cmi
+odoc_dep.cmx: ../parsing/parsetree.cmi odoc_type.cmx odoc_print.cmx \
+ odoc_module.cmx ../tools/depend.cmx
+odoc_dot.cmo: odoc_messages.cmo odoc_info.cmi
+odoc_dot.cmx: odoc_messages.cmx odoc_info.cmx
+odoc_env.cmo: ../typing/types.cmi ../typing/printtyp.cmi ../typing/predef.cmi \
+ ../typing/path.cmi odoc_name.cmi ../typing/btype.cmi odoc_env.cmi
+odoc_env.cmx: ../typing/types.cmx ../typing/printtyp.cmx ../typing/predef.cmx \
+ ../typing/path.cmx odoc_name.cmx ../typing/btype.cmx odoc_env.cmi
+odoc_exception.cmo: ../typing/types.cmi odoc_types.cmi odoc_name.cmi
+odoc_exception.cmx: ../typing/types.cmx odoc_types.cmx odoc_name.cmx
+odoc_gen.cmo: odoc_texi.cmo odoc_module.cmo odoc_man.cmo odoc_latex.cmo \
+ odoc_html.cmo odoc_dot.cmo odoc_gen.cmi
+odoc_gen.cmx: odoc_texi.cmx odoc_module.cmx odoc_man.cmx odoc_latex.cmx \
+ odoc_html.cmx odoc_dot.cmx odoc_gen.cmi
+odoc_global.cmo: odoc_types.cmi odoc_messages.cmo odoc_config.cmi \
+ ../utils/clflags.cmi odoc_global.cmi
+odoc_global.cmx: odoc_types.cmx odoc_messages.cmx odoc_config.cmx \
+ ../utils/clflags.cmx odoc_global.cmi
+odoc_html.cmo: odoc_text.cmi odoc_ocamlhtml.cmo odoc_messages.cmo \
+ odoc_info.cmi odoc_global.cmi odoc_dag2html.cmi ../parsing/asttypes.cmi
+odoc_html.cmx: odoc_text.cmx odoc_ocamlhtml.cmx odoc_messages.cmx \
+ odoc_info.cmx odoc_global.cmx odoc_dag2html.cmx ../parsing/asttypes.cmi
+odoc_info.cmo: ../typing/printtyp.cmi odoc_value.cmo odoc_types.cmi \
+ odoc_type.cmo odoc_text.cmi odoc_str.cmi odoc_search.cmi odoc_scan.cmo \
+ odoc_print.cmi odoc_parameter.cmo odoc_name.cmi odoc_module.cmo \
+ odoc_misc.cmi odoc_global.cmi odoc_exception.cmo odoc_dep.cmo \
+ odoc_config.cmi odoc_comments.cmi odoc_class.cmo odoc_analyse.cmi \
+ odoc_info.cmi
+odoc_info.cmx: ../typing/printtyp.cmx odoc_value.cmx odoc_types.cmx \
+ odoc_type.cmx odoc_text.cmx odoc_str.cmx odoc_search.cmx odoc_scan.cmx \
+ odoc_print.cmx odoc_parameter.cmx odoc_name.cmx odoc_module.cmx \
+ odoc_misc.cmx odoc_global.cmx odoc_exception.cmx odoc_dep.cmx \
+ odoc_config.cmx odoc_comments.cmx odoc_class.cmx odoc_analyse.cmx \
+ odoc_info.cmi
+odoc_inherit.cmo:
+odoc_inherit.cmx:
+odoc_latex.cmo: odoc_to_text.cmo odoc_messages.cmo odoc_latex_style.cmo \
+ odoc_info.cmi ../parsing/asttypes.cmi
+odoc_latex.cmx: odoc_to_text.cmx odoc_messages.cmx odoc_latex_style.cmx \
+ odoc_info.cmx ../parsing/asttypes.cmi
+odoc_latex_style.cmo:
+odoc_latex_style.cmx:
+odoc_lexer.cmo: odoc_parser.cmi odoc_messages.cmo odoc_global.cmi \
+ odoc_comments_global.cmi
+odoc_lexer.cmx: odoc_parser.cmx odoc_messages.cmx odoc_global.cmx \
+ odoc_comments_global.cmx
+odoc_man.cmo: odoc_str.cmi odoc_print.cmi odoc_misc.cmi odoc_messages.cmo \
+ odoc_info.cmi ../parsing/asttypes.cmi
+odoc_man.cmx: odoc_str.cmx odoc_print.cmx odoc_misc.cmx odoc_messages.cmx \
+ odoc_info.cmx ../parsing/asttypes.cmi
+odoc_merge.cmo: odoc_value.cmo odoc_types.cmi odoc_type.cmo \
+ odoc_parameter.cmo odoc_name.cmi odoc_module.cmo odoc_messages.cmo \
+ odoc_global.cmi odoc_exception.cmo odoc_class.cmo odoc_merge.cmi
+odoc_merge.cmx: odoc_value.cmx odoc_types.cmx odoc_type.cmx \
+ odoc_parameter.cmx odoc_name.cmx odoc_module.cmx odoc_messages.cmx \
+ odoc_global.cmx odoc_exception.cmx odoc_class.cmx odoc_merge.cmi
+odoc_messages.cmo: ../utils/config.cmi
+odoc_messages.cmx: ../utils/config.cmx
+odoc_misc.cmo: ../typing/types.cmi ../typing/predef.cmi ../typing/path.cmi \
+ odoc_types.cmi odoc_messages.cmo ../parsing/longident.cmi \
+ ../typing/ctype.cmi ../typing/btype.cmi odoc_misc.cmi
+odoc_misc.cmx: ../typing/types.cmx ../typing/predef.cmx ../typing/path.cmx \
+ odoc_types.cmx odoc_messages.cmx ../parsing/longident.cmx \
+ ../typing/ctype.cmx ../typing/btype.cmx odoc_misc.cmi
+odoc_module.cmo: ../typing/types.cmi odoc_value.cmo odoc_types.cmi \
+ odoc_type.cmo odoc_name.cmi odoc_exception.cmo odoc_class.cmo
+odoc_module.cmx: ../typing/types.cmx odoc_value.cmx odoc_types.cmx \
+ odoc_type.cmx odoc_name.cmx odoc_exception.cmx odoc_class.cmx
+odoc_name.cmo: ../typing/path.cmi odoc_misc.cmi ../typing/ident.cmi \
+ odoc_name.cmi
+odoc_name.cmx: ../typing/path.cmx odoc_misc.cmx ../typing/ident.cmx \
+ odoc_name.cmi
+odoc_ocamlhtml.cmo:
+odoc_ocamlhtml.cmx:
+odoc_parameter.cmo: ../typing/types.cmi odoc_types.cmi
+odoc_parameter.cmx: ../typing/types.cmx odoc_types.cmx
+odoc_parser.cmo: odoc_types.cmi odoc_comments_global.cmi odoc_parser.cmi
+odoc_parser.cmx: odoc_types.cmx odoc_comments_global.cmx odoc_parser.cmi
+odoc_print.cmo: ../typing/types.cmi ../typing/printtyp.cmi odoc_print.cmi
+odoc_print.cmx: ../typing/types.cmx ../typing/printtyp.cmx odoc_print.cmi
+odoc_scan.cmo: odoc_value.cmo odoc_types.cmi odoc_type.cmo odoc_module.cmo \
+ odoc_exception.cmo odoc_class.cmo
+odoc_scan.cmx: odoc_value.cmx odoc_types.cmx odoc_type.cmx odoc_module.cmx \
+ odoc_exception.cmx odoc_class.cmx
+odoc_search.cmo: odoc_value.cmo odoc_types.cmi odoc_type.cmo \
+ odoc_parameter.cmo odoc_name.cmi odoc_module.cmo odoc_exception.cmo \
+ odoc_class.cmo odoc_search.cmi
+odoc_search.cmx: odoc_value.cmx odoc_types.cmx odoc_type.cmx \
+ odoc_parameter.cmx odoc_name.cmx odoc_module.cmx odoc_exception.cmx \
+ odoc_class.cmx odoc_search.cmi
+odoc_see_lexer.cmo: odoc_parser.cmi
+odoc_see_lexer.cmx: odoc_parser.cmx
+odoc_sig.cmo: ../typing/types.cmi ../typing/typedtree.cmi ../typing/path.cmi \
+ ../parsing/parsetree.cmi odoc_value.cmo odoc_types.cmi odoc_type.cmo \
+ odoc_parameter.cmo odoc_name.cmi odoc_module.cmo odoc_misc.cmi \
+ odoc_messages.cmo odoc_merge.cmi odoc_global.cmi odoc_exception.cmo \
+ odoc_env.cmi odoc_class.cmo ../utils/misc.cmi ../parsing/location.cmi \
+ ../typing/btype.cmi ../parsing/asttypes.cmi odoc_sig.cmi
+odoc_sig.cmx: ../typing/types.cmx ../typing/typedtree.cmx ../typing/path.cmx \
+ ../parsing/parsetree.cmi odoc_value.cmx odoc_types.cmx odoc_type.cmx \
+ odoc_parameter.cmx odoc_name.cmx odoc_module.cmx odoc_misc.cmx \
+ odoc_messages.cmx odoc_merge.cmx odoc_global.cmx odoc_exception.cmx \
+ odoc_env.cmx odoc_class.cmx ../utils/misc.cmx ../parsing/location.cmx \
+ ../typing/btype.cmx ../parsing/asttypes.cmi odoc_sig.cmi
+odoc_str.cmo: ../typing/types.cmi ../typing/printtyp.cmi odoc_value.cmo \
+ odoc_type.cmo odoc_print.cmi odoc_name.cmi odoc_misc.cmi \
+ odoc_messages.cmo odoc_exception.cmo odoc_class.cmo \
+ ../parsing/asttypes.cmi odoc_str.cmi
+odoc_str.cmx: ../typing/types.cmx ../typing/printtyp.cmx odoc_value.cmx \
+ odoc_type.cmx odoc_print.cmx odoc_name.cmx odoc_misc.cmx \
+ odoc_messages.cmx odoc_exception.cmx odoc_class.cmx \
+ ../parsing/asttypes.cmi odoc_str.cmi
+odoc_test.cmo: odoc_info.cmi odoc_gen.cmi odoc_args.cmi
+odoc_test.cmx: odoc_info.cmx odoc_gen.cmx odoc_args.cmx
+odoc_texi.cmo: odoc_to_text.cmo odoc_messages.cmo odoc_info.cmi \
+ ../parsing/asttypes.cmi
+odoc_texi.cmx: odoc_to_text.cmx odoc_messages.cmx odoc_info.cmx \
+ ../parsing/asttypes.cmi
+odoc_text.cmo: odoc_types.cmi odoc_text_parser.cmi odoc_text_lexer.cmo \
+ odoc_text.cmi
+odoc_text.cmx: odoc_types.cmx odoc_text_parser.cmx odoc_text_lexer.cmx \
+ odoc_text.cmi
+odoc_text_lexer.cmo: odoc_text_parser.cmi odoc_misc.cmi
+odoc_text_lexer.cmx: odoc_text_parser.cmx odoc_misc.cmx
+odoc_text_parser.cmo: odoc_types.cmi odoc_misc.cmi odoc_text_parser.cmi
+odoc_text_parser.cmx: odoc_types.cmx odoc_misc.cmx odoc_text_parser.cmi
+odoc_to_text.cmo: odoc_module.cmo odoc_messages.cmo odoc_info.cmi
+odoc_to_text.cmx: odoc_module.cmx odoc_messages.cmx odoc_info.cmx
+odoc_type.cmo: ../typing/types.cmi odoc_types.cmi odoc_name.cmi \
+ ../parsing/asttypes.cmi
+odoc_type.cmx: ../typing/types.cmx odoc_types.cmx odoc_name.cmx \
+ ../parsing/asttypes.cmi
+odoc_types.cmo: odoc_messages.cmo odoc_types.cmi
+odoc_types.cmx: odoc_messages.cmx odoc_types.cmi
+odoc_value.cmo: ../typing/types.cmi ../typing/printtyp.cmi odoc_types.cmi \
+ odoc_parameter.cmo odoc_name.cmi
+odoc_value.cmx: ../typing/types.cmx ../typing/printtyp.cmx odoc_types.cmx \
+ odoc_parameter.cmx odoc_name.cmx
+t.cmo:
+t.cmx:
+odoc_analyse.cmi: odoc_module.cmo odoc_global.cmi
+odoc_args.cmi: odoc_gen.cmi
+odoc_ast.cmi: ../typing/types.cmi ../typing/typedtree.cmi ../typing/path.cmi \
+ ../parsing/parsetree.cmi odoc_sig.cmi odoc_name.cmi odoc_module.cmo
+odoc_comments.cmi: odoc_types.cmi odoc_module.cmo
+odoc_comments_global.cmi:
+odoc_config.cmi:
+odoc_cross.cmi: odoc_types.cmi odoc_module.cmo
+odoc_dag2html.cmi: odoc_info.cmi
+odoc_env.cmi: ../typing/types.cmi odoc_name.cmi
+odoc_gen.cmi: odoc_texi.cmo odoc_module.cmo odoc_man.cmo odoc_latex.cmo \
+ odoc_html.cmo odoc_dot.cmo
+odoc_global.cmi: odoc_types.cmi
+odoc_info.cmi: ../typing/types.cmi odoc_value.cmo odoc_types.cmi \
+ odoc_type.cmo odoc_search.cmi odoc_parameter.cmo odoc_module.cmo \
+ odoc_global.cmi odoc_exception.cmo odoc_class.cmo
+odoc_merge.cmi: odoc_types.cmi odoc_module.cmo
+odoc_misc.cmi: ../typing/types.cmi odoc_types.cmi ../parsing/longident.cmi
+odoc_name.cmi: ../typing/path.cmi ../parsing/longident.cmi \
+ ../typing/ident.cmi
+odoc_parser.cmi: odoc_types.cmi
+odoc_print.cmi: ../typing/types.cmi
+odoc_search.cmi: odoc_value.cmo odoc_types.cmi odoc_type.cmo odoc_module.cmo \
+ odoc_exception.cmo odoc_class.cmo
+odoc_sig.cmi: ../typing/types.cmi ../parsing/parsetree.cmi odoc_types.cmi \
+ odoc_type.cmo odoc_name.cmi odoc_module.cmo odoc_env.cmi odoc_class.cmo
+odoc_str.cmi: ../typing/types.cmi odoc_value.cmo odoc_type.cmo \
+ odoc_exception.cmo odoc_class.cmo
+odoc_text.cmi: odoc_types.cmi
+odoc_text_parser.cmi: odoc_types.cmi
+odoc_types.cmi:
diff --git a/ocaml-binary-annot/ocamldoc/Changes.txt b/ocaml-binary-annot/ocamldoc/Changes.txt
new file mode 100644
index 0000000000..3707d265bd
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/Changes.txt
@@ -0,0 +1,209 @@
+TODO:
+ - need to fix display of type parameters for inherited classes/class types
+ - need to add an environment while generating to print correct links:
+ file foo.mli:
+ type u
+ module type M = sig type u end
+ module N : sig include M val f: u -> unit end
+ Here, in html for example, f in displayed being of type Foo.u instead of Foo.M.u
+ - latex: types variant polymorphes dépassent de la page quand ils sont trop longs
+ - utilisation nouvelles infos de Xavier: "début de rec", etc.
+ - xml generator
+
+=====
+Release > 3.11.0:
+- option -g also for native code version (loading custom generators)
+
+=====
+Release 3.09.3:
+- mod: PR#4017 new option -short-functors to use a short form to display
+ functors in html generator
+- fix: PR#4016 (using modtype constraint to filter module elements displayed in doc)
+- fix: PR#4066 (missing crossref in text from intro files)
+- fix: PR#4007 (error in merging of top dependencies of modules)
+- fix: PR#3981 (-dot-colors has no effect)
+- mod: name resolution in cross-referencing: {!name} if name is not
+ found, then it is searched in the parent module/class, and in the parent
+ of the parent, and so on until it is found.
+
+=====
+Release 3.09.1:
+ - fix: remove .TP for generated man pages, use .sp instead
+ (.TP caused a lot of odd margins)
+ - fix: html generator now output DOCTYPE and character encoding information.
+ - add: m_text_only field in Module.t_module, to separate real modules
+ from text files handled as modules.
+ - fix: display only text for "text modules"
+ - extensible {foo } syntax
+ - user can give .txt files on the command line, containing ocamldoc formatted
+ text, to be able to include bigger texts out of source files
+ - -o option is now used by the html generator to indicate the prefix
+ of generated index files (to avoid conflict when a Index module exists
+ on case-insensitive file systems).
+
+=====
+Release 3.08.4:
+ - some improvements in html display
+ - better error messages for misplaced variant constructors comments
+ - some fixes in man page generation (escaping characters)
+
+=====
+Release 3.08.2:
+ - fix: error "Lexing: empty token" (PR#3173)
+
+=====
+Release 3.08.1:
+ - add: new -intf and -impl options supported (PR#3036)
+ - fix: display of class parameters in HTML and LaTeX (PR#2994)
+ - fix: display of link to class page in html (PR#2994)
+
+=====
+Release 3.08.0:
+ - fix: method parameters names in signature are now retrieved correctly
+ (fix of Odoc_value.parameter_list_from_arrows to handle Tpoly for methods)
+ - ajout à la doc de Module_list et Index_list (utilisé dans le html seulement)
+ - ajout à la doc: fichier de l'option -intro utilisé pour l'index en html
+ - fix: create a Module_with instead of a Module_alias when we encounter
+ module A : Foo in a signature
+ - latex: style latex pour indenter dans les module kind et les class kind
+ - latex: il manque la génération des paramètres de classe
+ - parse des {!modules: } et {!indexlist}
+ - gestion des Module_list et Index_list
+ - no need to Dynlink.add_available_units any more
+ - generate html from module_kind rather than from module_type
+ + same for classes and class types
+ - add the kind to module parameters (the way the parameter was build in the parsetree)
+ - fix: the generated ocamldoc.sty is more robust for paragraphs in
+ ocamldocdescription environment
+ - fix: when generating separated files in latex, generate them in
+ the same directory than the main file, (the one specified by -o)
+ - mod: one section per to module in latex output + improve latex output
+ - mod: odoc_latex: use buffers instead of string concatenation
+ - add: new ocamldoc man page, thanks to Samuel Mimram
+ - fix: useless parenthesis around agruments of arguments of a type constructor in
+ type definitions, and aournd arguments of exceptions in exception definitions.
+ - fix: blank lines in verbatim, latex, code pre, code and ele ref modes
+ are now accepted
+ - fix: html generator: included module names were displayed with their simple
+ name rather than their fully qualified name
+ - fix: use a formatter from a buffer rather Format.str_formatter in
+ Odoc_mist.sting_of_module_type, to avoid too much blanks
+ - new module odoc_print, will work when Format.pp_print_flush is fixed
+ - odoc_html: use buffers instead of string concatenation
+ - odoc_man: use buffers instead of string concatenation
+ - odoc_cross.ml: use hash tables modified on the fly to resolve
+ (module | module type | exception) name aliases
+ - odoc_html: replace some calls to Str. by specific functions on strings
+ - odoc_cross.ml: use a Map to associate a complete name to
+ the known elements with this name, instead of searching each time
+ through the whole list of modules -> a gain of more than 90% in speed
+ for cross-referencing (Odoc_cross.associate)
+ - fix: Odoc_name.cut printed a '(' instead of a '.'
+ - add: new option -customdir
+ - add: new option -i (to add a path to the directory where
+ to look for custom generators)
+ - add: add odoc_config.ml{,i}
+ - add: keep_code in Odoc_info.Args interface
+ - add: m_code_intf and m_code fields for modules, fit when the
+ Odoc_args.keep_code option is set, and fit for all modules, not
+ only toplevel ones
+ - fix: bug preventing to get the code in a .mli
+ - fix: missing spaces after carriage return in types (Odoc_misc.string_of_type_expr)
+ - fixes: some bugs in the text parser
+ ( ]} meaning end of code and somehting else instead of end of precode)
+ - add: in Odoc_info: text_of_string, text_string_of_text, info_of_string
+ - fix: better output of titles in html (use more the style)
+ - add: -intro option to use a file content as ocamldoc comment to use as
+ introduction for LaTeX document and HTML index page
+ - add: the HTML generator generates the code of the module if available
+ - add: field m_code for modules, to keep the code of top modules
+ - fix: display "include Foo" instead of "include module Foo" in Latex, Man, Texi
+ - fix: not display comments associated to include directives
+ - fix: bad display of type parameters for class and class types
+
+======
+
+Release 3.05 :
+ - added link tags in html header to reference sections and subsections
+ in each page (for browser which handle those tags)
+ - no titles nor lists in first sentence of text in indexes and latex titles
+ - only one table for the titles in HTML output
+ - fix of bad comment association for types in .ml files
+ - dumps now contain a magic number, checked when dumps are loaded
+ - new option -o to use with texi, latex and dot generators
+ - new .code CSS class used
+ - better output for classes and modules, with their type
+ - added texinfo generator, by Olivier Andrieu
+ - removed iso generator, which became the odoc_check custom generator
+ - link syntax {{:url}text} added to the manual
+ - (** comments in code is colorized in ocaml code html pages
+ - new class .code in style
+ - new generator : -dot . Output dot code to display
+ modules or types dependencies.
+ - new option -inv-merge-ml-mli to inverse the priority of
+ .ml and .mli when merging
+ - option -werr becomes -warn-error
+ - possibility to define and reference section labels
+ Exemple:
+ (** {2:mysectionlabel My title bla bla bla} *)
+ in module Foo
+
+ This section is referenced with {!Foo.mysectionlabel} in
+ a comment.
+
+Pre-release 4 :
+ - new option -werr to treat ocamldoc warnings as errors
+ - new option -hide to remove some modules from complete names,
+ (e.g., print ref instead of Pervasives.ref)
+ - HTML doc in classic style only contain indexes to existing element kinds
+ (i.e. there is no class index if the doc does not contain any class.)
+ - First description sentence now stops at the first period followed by a blank,
+ or at the first blank line.
+ - update of user manual
+ - check report generator added (options -iso and -iso-{val|ty|cl|ex|mod})
+ - Odoc_info.Scan.scanner base class added
+ - support for custom tags (@xxx with xxx not a predefined tag), see manual
+ - new classes info in Odoc_html, Odoc_to_text, Odoc_latex, and Odoc_man, which
+ contains the functions for printing info structures
+ - replacement of modules Odoc_html.Text and Odoc_latex.Text by
+ classes Odoc_html.text and Odoc_latex.text to allow the redefinition
+ of their methods in custom generators
+ - bug fix : a shortcut list can be pu after a blank line
+ - improved display of variant constructors, record fields and
+ their comments in classic HTML
+ - blank lines in comments become <p> in HTML instead of <br>
+ - bug fix : there can be blanks between the last item
+ and the ending } of a list
+ - new option -latextitles
+ - number of errors encountered is displayed
+ - if at least one error occurs, exit code is not 0
+ - more precise error messages
+ - bug fix : \n and other blanks are accepted after, for example, {i
+
+Pre-release 3 :
+ - option -stars
+ - complete paths of executables in the generated Makefile
+ - names of executables changed to ocamldoc and ocamldoc.opt
+ - better LaTeX output
+ - option -sepfiles for LaTeX
+ - ocamldoc.sty used by the generated LaTeX
+ - ocamldoc.hva added to use Hevea on the generated LaTeX
+ - user manual updated
+ - {[ ]} marks to put pre-formatted code on more than one line
+ - {!Toto.tutu} to add cross references between elements
+ - some bug fixes
+
+Rep-release 2 :
+- generator of texinfo files : odoc_texi.cma
+- use of CSS in generated html
+- new option -css-style to provide a different style sheet
+- improved html
+- added more precise titles in generated html pages
+- no more links to unknown elements
+- added indexes
+- simple html : added <LINK ...> in <HEAD> : compliant
+ browsers should display quick access to modules and indexes in
+ their navigation bar (for example, mozilla 0.9.5 is compliant)
+- '{bone}' doesn't work any more ; a space is required as in '{b one}'.
+ Same for {e, {i, and some others marks. Check the manual
+- bug fixes
diff --git a/ocaml-binary-annot/ocamldoc/Makefile b/ocaml-binary-annot/ocamldoc/Makefile
new file mode 100644
index 0000000000..b352aab63d
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/Makefile
@@ -0,0 +1,371 @@
+#(***********************************************************************)
+#(* OCamldoc *)
+#(* *)
+#(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+#(* *)
+#(* Copyright 2001 Institut National de Recherche en Informatique et *)
+#(* en Automatique. All rights reserved. This file is distributed *)
+#(* under the terms of the Q Public License version 1.0. *)
+#(* *)
+#(***********************************************************************)
+
+# $Id$
+
+include ../config/Makefile
+
+# Various commands and dir
+##########################
+CAMLRUN=../boot/ocamlrun
+OCAMLC = ../ocamlcomp.sh
+OCAMLOPT = ../ocamlcompopt.sh
+OCAMLDEP = $(CAMLRUN) ../tools/ocamldep
+OCAMLLEX = $(CAMLRUN) ../boot/ocamllex
+OCAMLYACC= ../boot/ocamlyacc
+OCAMLLIB = $(LIBDIR)
+OCAMLBIN = $(BINDIR)
+
+OCAMLPP=-pp './remove_DEBUG'
+
+# For installation
+##############
+MKDIR=mkdir -p
+CP=cp -f
+OCAMLDOC=ocamldoc
+OCAMLDOC_RUN=./ocamldoc.opt #sh ./runocamldoc $(SUPPORTS_SHARED_LIBRARIES)
+OCAMLDOC_OPT=$(OCAMLDOC).opt
+OCAMLDOC_LIBCMA=odoc_info.cma
+OCAMLDOC_LIBCMI=odoc_info.cmi
+OCAMLDOC_LIBCMXA=odoc_info.cmxa
+OCAMLDOC_LIBA=odoc_info.a
+INSTALL_LIBDIR=$(OCAMLLIB)/ocamldoc
+INSTALL_CUSTOMDIR=$(INSTALL_LIBDIR)/custom
+INSTALL_BINDIR=$(OCAMLBIN)
+INSTALL_MANODIR=$(MANDIR)/man3
+
+INSTALL_MLIS=odoc_info.mli
+INSTALL_CMIS=$(INSTALL_MLIS:.mli=.cmi)
+
+ODOC_TEST=odoc_test.cmo
+
+GENERATORS_CMOS= \
+ generators/odoc_todo.cmo \
+ generators/odoc_literate.cmo
+GENERATORS_CMXS=$(GENERATORS_CMOS:.cmo=.cmxs)
+
+
+# Compilation
+#############
+OCAMLSRCDIR=..
+INCLUDES_DEP=-I $(OCAMLSRCDIR)/parsing \
+ -I $(OCAMLSRCDIR)/utils \
+ -I $(OCAMLSRCDIR)/typing \
+ -I $(OCAMLSRCDIR)/driver \
+ -I $(OCAMLSRCDIR)/bytecomp \
+ -I $(OCAMLSRCDIR)/tools \
+ -I $(OCAMLSRCDIR)/toplevel/
+
+INCLUDES_NODEP= -I $(OCAMLSRCDIR)/stdlib \
+ -I $(OCAMLSRCDIR)/otherlibs/str \
+ -I $(OCAMLSRCDIR)/otherlibs/dynlink \
+ -I $(OCAMLSRCDIR)/otherlibs/unix \
+ -I $(OCAMLSRCDIR)/otherlibs/num \
+ -I $(OCAMLSRCDIR)/otherlibs/graph
+
+INCLUDES=$(INCLUDES_DEP) $(INCLUDES_NODEP)
+
+COMPFLAGS=$(INCLUDES) -warn-error A
+LINKFLAGS=$(INCLUDES) -nostdlib
+
+CMOFILES= odoc_config.cmo \
+ odoc_messages.cmo\
+ odoc_global.cmo\
+ odoc_types.cmo\
+ odoc_misc.cmo\
+ odoc_text_parser.cmo\
+ odoc_text_lexer.cmo\
+ odoc_text.cmo\
+ odoc_name.cmo\
+ odoc_parameter.cmo\
+ odoc_value.cmo\
+ odoc_type.cmo\
+ odoc_exception.cmo\
+ odoc_class.cmo\
+ odoc_module.cmo\
+ odoc_print.cmo \
+ odoc_str.cmo\
+ odoc_comments_global.cmo\
+ odoc_parser.cmo\
+ odoc_lexer.cmo\
+ odoc_see_lexer.cmo\
+ odoc_env.cmo\
+ odoc_merge.cmo\
+ odoc_sig.cmo\
+ odoc_ast.cmo\
+ odoc_control.cmo\
+ odoc_inherit.cmo\
+ odoc_search.cmo\
+ odoc_scan.cmo\
+ odoc_cross.cmo\
+ odoc_comments.cmo\
+ odoc_dep.cmo\
+ odoc_analyse.cmo\
+ odoc_info.cmo
+
+
+CMXFILES= $(CMOFILES:.cmo=.cmx)
+CMIFILES= $(CMOFILES:.cmo=.cmi)
+
+EXECMOFILES=$(CMOFILES) \
+ odoc_dag2html.cmo \
+ odoc_to_text.cmo \
+ odoc_ocamlhtml.cmo \
+ odoc_html.cmo \
+ odoc_man.cmo \
+ odoc_latex_style.cmo \
+ odoc_latex.cmo \
+ odoc_texi.cmo \
+ odoc_dot.cmo \
+ odoc_gen.cmo \
+ odoc_args.cmo\
+ odoc.cmo
+
+EXECMXFILES= $(EXECMOFILES:.cmo=.cmx)
+EXECMIFILES= $(EXECMOFILES:.cmo=.cmi)
+
+LIBCMOFILES=$(CMOFILES)
+LIBCMXFILES= $(LIBCMOFILES:.cmo=.cmx)
+LIBCMIFILES= $(LIBCMOFILES:.cmo=.cmi)
+
+# Les cmo et cmx de la distrib OCAML
+OCAMLCMOFILES=$(OCAMLSRCDIR)/parsing/printast.cmo \
+ $(OCAMLSRCDIR)/typing/ident.cmo \
+ $(OCAMLSRCDIR)/utils/tbl.cmo \
+ $(OCAMLSRCDIR)/utils/misc.cmo \
+ $(OCAMLSRCDIR)/utils/config.cmo \
+ $(OCAMLSRCDIR)/utils/clflags.cmo \
+ $(OCAMLSRCDIR)/utils/warnings.cmo \
+ $(OCAMLSRCDIR)/utils/ccomp.cmo \
+ $(OCAMLSRCDIR)/utils/consistbl.cmo \
+ $(OCAMLSRCDIR)/parsing/linenum.cmo\
+ $(OCAMLSRCDIR)/parsing/location.cmo\
+ $(OCAMLSRCDIR)/parsing/longident.cmo \
+ $(OCAMLSRCDIR)/parsing/syntaxerr.cmo \
+ $(OCAMLSRCDIR)/parsing/parser.cmo \
+ $(OCAMLSRCDIR)/parsing/lexer.cmo \
+ $(OCAMLSRCDIR)/parsing/parse.cmo \
+ $(OCAMLSRCDIR)/typing/types.cmo \
+ $(OCAMLSRCDIR)/typing/path.cmo \
+ $(OCAMLSRCDIR)/typing/btype.cmo \
+ $(OCAMLSRCDIR)/typing/predef.cmo \
+ $(OCAMLSRCDIR)/typing/datarepr.cmo \
+ $(OCAMLSRCDIR)/typing/subst.cmo \
+ $(OCAMLSRCDIR)/typing/env.cmo \
+ $(OCAMLSRCDIR)/typing/ctype.cmo \
+ $(OCAMLSRCDIR)/typing/primitive.cmo \
+ $(OCAMLSRCDIR)/typing/oprint.cmo \
+ $(OCAMLSRCDIR)/typing/printtyp.cmo \
+ $(OCAMLSRCDIR)/typing/includecore.cmo \
+ $(OCAMLSRCDIR)/typing/typetexp.cmo \
+ $(OCAMLSRCDIR)/typing/typedtree.cmo \
+ $(OCAMLSRCDIR)/typing/parmatch.cmo \
+ $(OCAMLSRCDIR)/typing/stypes.cmo \
+ $(OCAMLSRCDIR)/typing/typecore.cmo \
+ $(OCAMLSRCDIR)/typing/includeclass.cmo \
+ $(OCAMLSRCDIR)/typing/typedecl.cmo \
+ $(OCAMLSRCDIR)/typing/typeclass.cmo \
+ $(OCAMLSRCDIR)/typing/mtype.cmo \
+ $(OCAMLSRCDIR)/typing/includemod.cmo \
+ $(OCAMLSRCDIR)/typing/typemod.cmo \
+ $(OCAMLSRCDIR)/bytecomp/lambda.cmo \
+ $(OCAMLSRCDIR)/bytecomp/typeopt.cmo \
+ $(OCAMLSRCDIR)/bytecomp/printlambda.cmo \
+ $(OCAMLSRCDIR)/bytecomp/switch.cmo \
+ $(OCAMLSRCDIR)/bytecomp/matching.cmo \
+ $(OCAMLSRCDIR)/bytecomp/translobj.cmo \
+ $(OCAMLSRCDIR)/bytecomp/translcore.cmo \
+ $(OCAMLSRCDIR)/bytecomp/translclass.cmo \
+ $(OCAMLSRCDIR)/tools/depend.cmo
+
+OCAMLCMXFILES=$(OCAMLCMOFILES:.cmo=.cmx)
+
+STDLIB_MLIS=../stdlib/*.mli \
+ ../otherlibs/unix/unix.mli \
+ ../otherlibs/str/str.mli \
+ ../otherlibs/bigarray/bigarray.mli \
+ ../otherlibs/num/num.mli
+
+all: exe lib generators
+
+exe: $(OCAMLDOC)
+lib: $(OCAMLDOC_LIBCMA) $(OCAMLDOC_LIBCMI) $(ODOC_TEST)
+generators: $(GENERATORS_CMOS)
+
+opt.opt: exeopt libopt generatorsopt
+ $(MAKE) manpages
+exeopt: $(OCAMLDOC_OPT)
+libopt: $(OCAMLDOC_LIBCMXA) $(OCAMLDOC_LIBCMI)
+generatorsopt: $(GENERATORS_CMXS)
+
+debug:
+ make OCAMLPP=""
+
+$(OCAMLDOC): $(EXECMOFILES)
+ $(OCAMLC) -o $@ -linkall unix.cma str.cma dynlink.cma $(LINKFLAGS) $(OCAMLCMOFILES) $(EXECMOFILES)
+$(OCAMLDOC_OPT): $(EXECMXFILES)
+ $(OCAMLOPT) -o $@ unix.cmxa str.cmxa dynlink.cmxa $(LINKFLAGS) $(OCAMLCMXFILES) $(EXECMXFILES)
+
+$(OCAMLDOC_LIBCMA): $(LIBCMOFILES)
+ $(OCAMLC) -a -o $@ $(LINKFLAGS) $(OCAMLCMOFILES) $(LIBCMOFILES)
+$(OCAMLDOC_LIBCMXA): $(LIBCMXFILES)
+ $(OCAMLOPT) -a -o $@ $(LINKFLAGS) $(OCAMLCMXFILES) $(LIBCMXFILES)
+
+manpages: stdlib_man/Pervasives.3o
+
+dot: $(EXECMOFILES)
+ $(OCAMLDOC_RUN) -dot -dot-reduce -o ocamldoc.dot $(INCLUDES) \
+ odoc*.ml
+
+# Parsers and lexers dependencies :
+###################################
+odoc_text_parser.ml: odoc_text_parser.mly
+odoc_text_parser.mli: odoc_text_parser.mly
+
+odoc_parser.ml: odoc_parser.mly
+odoc_parser.mli:odoc_parser.mly
+
+odoc_text_lexer.ml: odoc_text_lexer.mll
+
+odoc_lexer.ml:odoc_lexer.mll
+
+odoc_ocamlhtml.ml: odoc_ocamlhtml.mll
+
+odoc_see_lexer.ml: odoc_see_lexer.mll
+
+
+# generic rules :
+#################
+
+.SUFFIXES: .mll .mly .ml .mli .cmo .cmi .cmx .cmxs
+
+.ml.cmo:
+ $(OCAMLC) $(OCAMLPP) $(COMPFLAGS) -c $<
+
+.mli.cmi:
+ $(OCAMLC) $(OCAMLPP) $(COMPFLAGS) -c $<
+
+.ml.cmx:
+ $(OCAMLOPT) $(OCAMLPP) $(COMPFLAGS) -c $<
+
+.ml.cmxs:
+ $(OCAMLOPT) -shared -o $@ $(OCAMLPP) $(COMPFLAGS) $<
+
+.mll.ml:
+ $(OCAMLLEX) $<
+
+.mly.ml:
+ $(OCAMLYACC) -v $<
+
+.mly.mli:
+ $(OCAMLYACC) -v $<
+
+# Installation targets
+######################
+install: dummy
+ if test -d $(INSTALL_BINDIR); then : ; else $(MKDIR) $(INSTALL_BINDIR); fi
+ if test -d $(INSTALL_LIBDIR); then : ; else $(MKDIR) $(INSTALL_LIBDIR); fi
+ if test -d $(INSTALL_CUSTOMDIR); then : ; else $(MKDIR) $(INSTALL_CUSTOMDIR); fi
+ $(CP) $(OCAMLDOC) $(INSTALL_BINDIR)/$(OCAMLDOC)$(EXE)
+ $(CP) ocamldoc.hva *.cmi $(OCAMLDOC_LIBCMA) $(INSTALL_LIBDIR)
+ $(CP) $(INSTALL_MLIS) $(INSTALL_CMIS) $(INSTALL_LIBDIR)
+ if test -d $(INSTALL_MANODIR); then : ; else $(MKDIR) $(INSTALL_MANODIR); fi
+ if test -d stdlib_man; then $(CP) stdlib_man/* $(INSTALL_MANODIR); else : ; fi
+
+installopt:
+ if test -f $(OCAMLDOC_OPT) ; then $(MAKE) installopt_really ; fi
+
+installopt_really:
+ if test -d $(INSTALL_BINDIR); then : ; else $(MKDIR) $(INSTALL_BINDIR); fi
+ if test -d $(INSTALL_LIBDIR); then : ; else $(MKDIR) $(INSTALL_LIBDIR); fi
+ $(CP) $(OCAMLDOC_OPT) $(INSTALL_BINDIR)/$(OCAMLDOC_OPT)$(EXE)
+ $(CP) ocamldoc.hva $(OCAMLDOC_LIBA) $(OCAMLDOC_LIBCMXA) $(INSTALL_LIBDIR)
+ $(CP) $(INSTALL_MLIS) $(INSTALL_CMIS) $(INSTALL_LIBDIR)
+
+# Testing :
+###########
+test: dummy
+ $(MKDIR) $@
+ $(OCAMLDOC_RUN) -html -colorize-code -sort -d $@ $(INCLUDES) -dump $@/ocamldoc.odoc odoc*.ml odoc*.mli -v
+ $(MKDIR) $@-custom
+ $(OCAMLDOC_RUN) -colorize-code -sort -d $@-custom $(INCLUDES) \
+ -g generators/odoc_literate.cmo -g generators/odoc_todo.cmo \
+ -load $@/ocamldoc.odoc -v
+
+test_stdlib: dummy
+ $(MKDIR) $@
+ $(OCAMLDOC_RUN) -html -colorize-code -sort -d $@ $(INCLUDES) -dump $@/stdlib.odoc -keep-code \
+ ../stdlib/pervasives.ml ../stdlib/*.mli \
+ ../otherlibs/unix/unix.mli \
+ ../otherlibs/str/str.mli
+
+test_framed: dummy
+ $(MKDIR) $@
+ $(OCAMLDOC_RUN) -g odoc_fhtml.cmo -sort -colorize-code -d $@ $(INCLUDES) odoc*.ml odoc*.mli
+
+test_latex: dummy
+ $(MKDIR) $@
+ $(OCAMLDOC_RUN) -latex -sort -o $@/test.tex -d $@ $(INCLUDES) odoc*.ml odoc*.mli test2.txt ../stdlib/*.mli ../otherlibs/unix/unix.mli
+
+test_latex_simple: dummy
+ $(MKDIR) $@
+ $(OCAMLDOC_RUN) -latex -sort -o $@/test.tex -d $@ $(INCLUDES) \
+ -latextitle 6,subsection -latextitle 7,subsubection \
+ ../stdlib/hashtbl.mli \
+ ../stdlib/arg.mli \
+ ../otherlibs/unix/unix.mli \
+ ../stdlib/map.mli
+
+test_man: dummy
+ $(MKDIR) $@
+ $(OCAMLDOC_RUN) -man -sort -d $@ $(INCLUDES) odoc*.ml odoc*.mli
+
+test_texi: dummy
+ $(MKDIR) $@
+ $(OCAMLDOC_RUN) -texi -sort -d $@ $(INCLUDES) odoc*.ml odoc*.mli
+
+stdlib_man/Pervasives.3o: $(STDLIB_MLIS)
+ $(MKDIR) stdlib_man
+ $(OCAMLDOC_RUN) -man -d stdlib_man $(INCLUDES) \
+ -t "OCaml library" -man-mini \
+ $(STDLIB_MLIS)
+
+autotest_stdlib: dummy
+ $(MKDIR) $@
+ $(OCAMLDOC_RUN) -g autotest/odoc_test.cmo\
+ $(INCLUDES) -keep-code \
+ ../stdlib/pervasives.ml ../stdlib/*.mli \
+ ../otherlibs/unix/unix.mli \
+ ../otherlibs/str/str.mli
+
+# backup, clean and depend :
+############################
+
+clean:: dummy
+ @rm -f *~ \#*\#
+ @rm -f $(OCAMLDOC) $(OCAMLDOC_OPT) *.cma *.cmxa *.cmo *.cmi *.cmx *.a *.o
+ @rm -f odoc_parser.output odoc_text_parser.output
+ @rm -f odoc_lexer.ml odoc_text_lexer.ml odoc_see_lexer.ml odoc_ocamlhtml.ml
+ @rm -f odoc_parser.ml odoc_parser.mli odoc_text_parser.ml odoc_text_parser.mli
+ @rm -rf stdlib_man
+
+depend::
+ $(OCAMLYACC) odoc_text_parser.mly
+ $(OCAMLYACC) odoc_parser.mly
+ $(OCAMLLEX) odoc_text_lexer.mll
+ $(OCAMLLEX) odoc_lexer.mll
+ $(OCAMLLEX) odoc_ocamlhtml.mll
+ $(OCAMLLEX) odoc_see_lexer.mll
+ $(OCAMLDEP) $(INCLUDES_DEP) *.mll *.mly *.ml *.mli > .depend
+
+dummy:
+
+include .depend
diff --git a/ocaml-binary-annot/ocamldoc/Makefile.nt b/ocaml-binary-annot/ocamldoc/Makefile.nt
new file mode 100644
index 0000000000..387aec928c
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/Makefile.nt
@@ -0,0 +1,272 @@
+#(***********************************************************************)
+#(* OCamldoc *)
+#(* *)
+#(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+#(* *)
+#(* Copyright 2001 Institut National de Recherche en Informatique et *)
+#(* en Automatique. All rights reserved. This file is distributed *)
+#(* under the terms of the Q Public License version 1.0. *)
+#(* *)
+#(***********************************************************************)
+
+# $Id$
+
+include ../config/Makefile
+
+CAMLRUN =../boot/ocamlrun
+OCAMLC = ../ocamlcomp.sh
+OCAMLOPT = ../ocamlcompopt.sh
+OCAMLLEX =$(CAMLRUN) ../boot/ocamllex
+OCAMLYACC=../boot/ocamlyacc
+
+OCAMLLIB = $(LIBDIR)
+OCAMLBIN = $(BINDIR)
+
+OCAMLPP=-pp "grep -v DEBUG"
+
+# For installation
+##############
+MKDIR=mkdir
+CP=cp
+OCAMLDOC=ocamldoc
+OCAMLDOC_RUN=$(CAMLRUN) $(OCAMLDOC)
+OCAMLDOC_OPT=$(OCAMLDOC).opt
+OCAMLDOC_LIBCMA=odoc_info.cma
+OCAMLDOC_LIBCMI=odoc_info.cmi
+OCAMLDOC_LIBCMXA=odoc_info.cmxa
+OCAMLDOC_LIBA=odoc_info.$(A)
+INSTALL_LIBDIR=$(OCAMLLIB)/ocamldoc
+INSTALL_CUSTOMDIR=$(INSTALL_LIBDIR)/custom
+INSTALL_BINDIR=$(OCAMLBIN)
+
+INSTALL_MLIS=odoc_info.mli
+INSTALL_CMIS=$(INSTALL_MLIS:.mli=.cmi)
+
+# Compilation
+#############
+OCAMLSRCDIR=..
+INCLUDES_DEP=-I $(OCAMLSRCDIR)/parsing \
+ -I $(OCAMLSRCDIR)/utils \
+ -I $(OCAMLSRCDIR)/typing \
+ -I $(OCAMLSRCDIR)/driver \
+ -I $(OCAMLSRCDIR)/bytecomp \
+ -I $(OCAMLSRCDIR)/tools \
+ -I $(OCAMLSRCDIR)/toplevel/
+
+INCLUDES_NODEP= -I $(OCAMLSRCDIR)/stdlib \
+ -I $(OCAMLSRCDIR)/otherlibs/str \
+ -I $(OCAMLSRCDIR)/otherlibs/dynlink \
+ -I $(OCAMLSRCDIR)/otherlibs/win32unix \
+ -I $(OCAMLSRCDIR)/otherlibs/num \
+ -I $(OCAMLSRCDIR)/otherlibs/win32graph
+
+INCLUDES=$(INCLUDES_DEP) $(INCLUDES_NODEP)
+
+COMPFLAGS=$(INCLUDES)
+LINKFLAGS=$(INCLUDES) -nostdlib
+
+CMOFILES= odoc_config.cmo \
+ odoc_global.cmo\
+ odoc_messages.cmo\
+ odoc_types.cmo\
+ odoc_misc.cmo\
+ odoc_text_parser.cmo\
+ odoc_text_lexer.cmo\
+ odoc_text.cmo\
+ odoc_name.cmo\
+ odoc_parameter.cmo\
+ odoc_value.cmo\
+ odoc_type.cmo\
+ odoc_exception.cmo\
+ odoc_class.cmo\
+ odoc_module.cmo\
+ odoc_print.cmo \
+ odoc_str.cmo\
+ odoc_args.cmo\
+ odoc_comments_global.cmo\
+ odoc_parser.cmo\
+ odoc_lexer.cmo\
+ odoc_see_lexer.cmo\
+ odoc_env.cmo\
+ odoc_merge.cmo\
+ odoc_sig.cmo\
+ odoc_ast.cmo\
+ odoc_control.cmo\
+ odoc_inherit.cmo\
+ odoc_search.cmo\
+ odoc_scan.cmo\
+ odoc_cross.cmo\
+ odoc_comments.cmo\
+ odoc_dep.cmo\
+ odoc_analyse.cmo\
+ odoc_info.cmo
+
+
+CMXFILES= $(CMOFILES:.cmo=.cmx)
+CMIFILES= $(CMOFILES:.cmo=.cmi)
+
+EXECMOFILES=$(CMOFILES)\
+ odoc_dag2html.cmo\
+ odoc_to_text.cmo\
+ odoc_ocamlhtml.cmo\
+ odoc_html.cmo\
+ odoc_man.cmo\
+ odoc_latex_style.cmo \
+ odoc_latex.cmo\
+ odoc_texi.cmo\
+ odoc_dot.cmo\
+ odoc.cmo
+
+
+EXECMXFILES= $(EXECMOFILES:.cmo=.cmx)
+EXECMIFILES= $(EXECMOFILES:.cmo=.cmi)
+
+LIBCMOFILES=$(CMOFILES)
+LIBCMXFILES= $(LIBCMOFILES:.cmo=.cmx)
+LIBCMIFILES= $(LIBCMOFILES:.cmo=.cmi)
+
+# Les cmo et cmx de la distrib OCAML
+OCAMLCMOFILES=$(OCAMLSRCDIR)/parsing/printast.cmo \
+ $(OCAMLSRCDIR)/typing/ident.cmo \
+ $(OCAMLSRCDIR)/utils/tbl.cmo \
+ $(OCAMLSRCDIR)/utils/misc.cmo \
+ $(OCAMLSRCDIR)/utils/config.cmo \
+ $(OCAMLSRCDIR)/utils/clflags.cmo \
+ $(OCAMLSRCDIR)/utils/warnings.cmo \
+ $(OCAMLSRCDIR)/utils/ccomp.cmo \
+ $(OCAMLSRCDIR)/utils/consistbl.cmo \
+ $(OCAMLSRCDIR)/parsing/linenum.cmo\
+ $(OCAMLSRCDIR)/parsing/location.cmo\
+ $(OCAMLSRCDIR)/parsing/longident.cmo \
+ $(OCAMLSRCDIR)/parsing/syntaxerr.cmo \
+ $(OCAMLSRCDIR)/parsing/parser.cmo \
+ $(OCAMLSRCDIR)/parsing/lexer.cmo \
+ $(OCAMLSRCDIR)/parsing/parse.cmo \
+ $(OCAMLSRCDIR)/typing/types.cmo \
+ $(OCAMLSRCDIR)/typing/path.cmo \
+ $(OCAMLSRCDIR)/typing/btype.cmo \
+ $(OCAMLSRCDIR)/typing/predef.cmo \
+ $(OCAMLSRCDIR)/typing/datarepr.cmo \
+ $(OCAMLSRCDIR)/typing/subst.cmo \
+ $(OCAMLSRCDIR)/typing/env.cmo \
+ $(OCAMLSRCDIR)/typing/ctype.cmo \
+ $(OCAMLSRCDIR)/typing/primitive.cmo \
+ $(OCAMLSRCDIR)/typing/oprint.cmo \
+ $(OCAMLSRCDIR)/typing/printtyp.cmo \
+ $(OCAMLSRCDIR)/typing/includecore.cmo \
+ $(OCAMLSRCDIR)/typing/typetexp.cmo \
+ $(OCAMLSRCDIR)/typing/parmatch.cmo \
+ $(OCAMLSRCDIR)/typing/typedtree.cmo \
+ $(OCAMLSRCDIR)/typing/stypes.cmo \
+ $(OCAMLSRCDIR)/typing/typecore.cmo \
+ $(OCAMLSRCDIR)/typing/includeclass.cmo \
+ $(OCAMLSRCDIR)/typing/typedecl.cmo \
+ $(OCAMLSRCDIR)/typing/typeclass.cmo \
+ $(OCAMLSRCDIR)/typing/mtype.cmo \
+ $(OCAMLSRCDIR)/typing/includemod.cmo \
+ $(OCAMLSRCDIR)/typing/typemod.cmo \
+ $(OCAMLSRCDIR)/bytecomp/lambda.cmo \
+ $(OCAMLSRCDIR)/bytecomp/typeopt.cmo \
+ $(OCAMLSRCDIR)/bytecomp/printlambda.cmo \
+ $(OCAMLSRCDIR)/bytecomp/switch.cmo \
+ $(OCAMLSRCDIR)/bytecomp/matching.cmo \
+ $(OCAMLSRCDIR)/bytecomp/translobj.cmo \
+ $(OCAMLSRCDIR)/bytecomp/translcore.cmo \
+ $(OCAMLSRCDIR)/bytecomp/translclass.cmo \
+ $(OCAMLSRCDIR)/tools/depend.cmo
+
+OCAMLCMXFILES=$(OCAMLCMOFILES:.cmo=.cmx)
+
+all: exe lib
+exe: $(OCAMLDOC)
+lib: $(OCAMLDOC_LIBCMA) $(OCAMLDOC_LIBCMI)
+
+opt.opt: exeopt libopt
+exeopt: $(OCAMLDOC_OPT)
+libopt: $(OCAMLDOC_LIBCMXA) $(OCAMLDOC_LIBCMI)
+debug:
+ make OCAMLPP=""
+
+$(OCAMLDOC): $(EXECMOFILES)
+ $(OCAMLC) -o $@ -linkall unix.cma str.cma dynlink.cma $(LINKFLAGS) $(OCAMLCMOFILES) $(EXECMOFILES)
+$(OCAMLDOC_OPT): $(EXECMXFILES)
+ $(OCAMLOPT) -o $@ unix.cmxa str.cmxa dynlink.cmxa $(LINKFLAGS) $(OCAMLCMXFILES) $(EXECMXFILES)
+
+$(OCAMLDOC_LIBCMA): $(LIBCMOFILES)
+ $(OCAMLC) -a -o $@ $(LINKFLAGS) $(OCAMLCMOFILES) $(LIBCMOFILES)
+$(OCAMLDOC_LIBCMXA): $(LIBCMXFILES)
+ $(OCAMLOPT) -a -o $@ $(LINKFLAGS) $(OCAMLCMXFILES) $(LIBCMXFILES)
+
+# generic rules :
+#################
+
+.SUFFIXES: .mli .ml .cmi .cmo .cmx
+
+.mli.cmi:
+ $(OCAMLC) $(OCAMLPP) $(COMPFLAGS) -c $<
+
+.ml.cmo:
+ $(OCAMLC) $(OCAMLPP) $(COMPFLAGS) -c $<
+
+.ml.cmx:
+ $(OCAMLOPT) $(OCAMLPP) $(COMPFLAGS) -c $<
+
+odoc_text_parser.ml odoc_text_parser.mli: odoc_text_parser.mly
+ $(OCAMLYACC) odoc_text_parser.mly
+
+odoc_parser.ml odoc_parser.mli: odoc_parser.mly
+ $(OCAMLYACC) odoc_parser.mly
+
+odoc_text_lexer.ml: odoc_text_lexer.mll
+ $(OCAMLLEX) odoc_text_lexer.mll
+
+odoc_lexer.ml: odoc_lexer.mll
+ $(OCAMLLEX) odoc_lexer.mll
+
+odoc_ocamlhtml.ml: odoc_ocamlhtml.mll
+ $(OCAMLLEX) odoc_ocamlhtml.mll
+
+odoc_see_lexer.ml: odoc_see_lexer.mll
+ $(OCAMLLEX) odoc_see_lexer.mll
+
+# Installation targets
+######################
+install: dummy
+ $(MKDIR) -p $(INSTALL_BINDIR)
+ $(MKDIR) -p $(INSTALL_LIBDIR)
+ $(CP) $(OCAMLDOC) $(INSTALL_BINDIR)/$(OCAMLDOC).exe
+ $(CP) ocamldoc.hva *.cmi $(OCAMLDOC_LIBCMA) $(INSTALL_LIBDIR)
+ $(CP) $(INSTALL_MLIS) $(INSTALL_CMIS) $(INSTALL_LIBDIR)
+
+installopt:
+ if test -f $(OCAMLDOC_OPT); then $(MAKEREC) installopt_really; fi
+
+installopt_really:
+ $(MKDIR) -p $(INSTALL_BINDIR)
+ $(MKDIR) -p $(INSTALL_LIBDIR)
+ $(CP) $(OCAMLDOC_OPT) $(INSTALL_BINDIR)/$(OCAMLDOC_OPT).exe
+ $(CP) ocamldoc.hva $(OCAMLDOC_LIBA) $(OCAMLDOC_LIBCMXA) $(INSTALL_LIBDIR)
+ $(CP) $(INSTALL_MLIS) $(INSTALL_CMIS) $(INSTALL_LIBDIR)
+
+
+# backup, clean and depend :
+############################
+
+clean:: dummy
+ @rm -f *~ /#*/#
+ @rm -f $(OCAMLDOC) $(OCAMLDOC_OPT) *.cma *.cmxa *.cmo *.cmi *.cmx *.$(A) *.$(O)
+ @rm -f odoc_parser.output odoc_text_parser.output
+ @rm -f odoc_lexer.ml odoc_text_lexer.ml odoc_see_lexer.ml odoc_ocamlhtml.ml
+ @rm -f odoc_parser.ml odoc_parser.mli odoc_text_parser.ml odoc_text_parser.mli
+
+depend::
+ rm -f .depend
+ $(OCAMLYACC) odoc_text_parser.mly
+ $(OCAMLYACC) odoc_parser.mly
+ $(OCAMLLEX) odoc_text_lexer.mll
+ $(OCAMLLEX) odoc_lexer.mll
+ $(OCAMLDEP) $(INCLUDES_DEP) *.mll *.mly *.ml *.mli > .depend
+
+dummy:
+
+include .depend
diff --git a/ocaml-binary-annot/ocamldoc/generators/odoc_literate.ml b/ocaml-binary-annot/ocamldoc/generators/odoc_literate.ml
new file mode 100644
index 0000000000..e79b4f1a21
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/generators/odoc_literate.ml
@@ -0,0 +1,207 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id: odoc_literate.ml,v 1.1 2008/02/28 11:09:33 guesdon Exp $ *)
+
+open Odoc_info
+module Naming = Odoc_html.Naming
+open Odoc_info.Value
+open Odoc_info.Module
+
+let p = Printf.bprintf
+let bp = Printf.bprintf
+let bs = Buffer.add_string
+
+module Html =
+ (val
+ (
+ match !Odoc_args.current_generator with
+ None -> (module Odoc_html.Generator : Odoc_html.Html_generator)
+ | Some (Odoc_gen.Html m) -> m
+ | _ ->
+ failwith
+ "A non-html generator is already set. Cannot install the Todo-list html generator"
+ ) : Odoc_html.Html_generator)
+;;
+
+module Generator =
+struct
+class html =
+ object (self)
+ inherit Html.html as html
+
+ method private html_of_module_comment b text =
+ let br1, br2 =
+ match text with
+ [(Odoc_info.Title (n, l_opt, t))] -> false, false
+ | (Odoc_info.Title (n, l_opt, t)) :: _ -> false, true
+ | _ -> true, true
+ in
+ if br1 then p b "<br/>";
+ self#html_of_text b text;
+ if br2 then p b "<br/><br/>\n"
+
+ method private html_of_Title b n l_opt t =
+ let label1 = self#create_title_label (n, l_opt, t) in
+ p b "<a name=\"%s\"></a>\n" (Naming.label_target label1);
+ p b "<h%d>" n;
+ self#html_of_text b t;
+ p b "</h%d>" n
+
+ val mutable code_id = 0
+ method private code_block b code =
+ code_id <- code_id + 1;
+ Printf.bprintf b
+ "<span class=\"code_expand\" onclick=\"if(document.getElementById('code%d').style.display=='none') {document.getElementById('code%d').style.display='block';} else {document.getElementById('code%d').style.display='none';}\"><img src=\"expand_collapse.png\" alt=\"+/-\"/></span>" code_id code_id code_id;
+ Printf.bprintf b "<div id=\"code%d\" class=\"codeblock\">" code_id;
+ self#html_of_code b code;
+ Printf.bprintf b "</div>"
+
+ (** Print html code for a value. *)
+ method private html_of_value b v =
+ Odoc_info.reset_type_names ();
+ self#html_of_info b v.val_info;
+ bs b "<pre>";
+ bs b (self#keyword "val");
+ bs b " ";
+ (* html mark *)
+ bp b "<a name=\"%s\"></a>" (Naming.value_target v);
+ bs b (self#escape (Name.simple v.val_name));
+ bs b " : ";
+ self#html_of_type_expr b (Name.father v.val_name) v.val_type;
+ bs b "</pre>";
+ (
+ if !Odoc_html.with_parameter_list then
+ self#html_of_parameter_list b (Name.father v.val_name) v.val_parameters
+ else
+ self#html_of_described_parameter_list b (Name.father v.val_name) v.val_parameters
+ );
+ (
+ match v.val_code with
+ None -> ()
+ | Some code ->
+ self#code_block b code
+ )
+(*
+ (** Print html code for a module. *)
+ method private html_of_module b ?(info=true) ?(complete=true) ?(with_link=true) m =
+ let (html_file, _) = Naming.html_files m.m_name in
+ let father = Name.father m.m_name in
+ bs b "<pre>";
+ bs b ((self#keyword "module")^" ");
+ (
+ if with_link then
+ bp b "<a href=\"%s\">%s</a>" html_file (Name.simple m.m_name)
+ else
+ bs b (Name.simple m.m_name)
+ );
+(* A remettre quand on compilera avec ocaml 3.10
+ (
+ match m.m_kind with
+ Module_functor _ when !Odoc_info.Args.html_short_functors ->
+ ()
+
+ | _ -> *) bs b ": ";
+ (*
+ );
+ *)
+ self#html_of_module_kind b father ~modu: m m.m_kind;
+ bs b "</pre>";
+ if info && complete then
+ self#html_of_info ~indent: false b m.m_info
+
+*)
+ initializer
+ default_style_options <-
+ ["a:visited {color : #416DFF; text-decoration : none; }" ;
+ "a:link {color : #416DFF; text-decoration : none;}" ;
+ "a:hover {color : Red; text-decoration : none; background-color: #5FFF88}" ;
+ "a:active {color : Red; text-decoration : underline; }" ;
+ ".keyword { font-weight : bold ; color : Red }" ;
+ ".keywordsign { color : #C04600 }" ;
+ ".superscript { font-size : 4 }" ;
+ ".subscript { font-size : 4 }" ;
+ ".comment { color : Green }" ;
+ ".constructor { color : Blue }" ;
+ ".type { color : #5C6585 }" ;
+ ".string { color : Maroon }" ;
+ ".warning { color : Red ; font-weight : bold }" ;
+ ".info { margin-top: 8px; }";
+ ".param_info { margin-top: 4px; margin-left : 3em; margin-right : 3em }" ;
+ ".code { color : #465F91 ; }" ;
+ "h1 { font-size : 20pt ; text-align: center; }" ;
+
+ "h2 { font-size : 20pt ; border: 1px solid #000000; "^
+ "margin-top: 5px; margin-bottom: 2px;"^
+ "text-align: center; background-color: #90BDFF ;"^
+ "padding: 2px; }" ;
+
+ "h3 { font-size : 20pt ; border: 1px solid #000000; "^
+ "margin-top: 5px; margin-bottom: 2px;"^
+ "text-align: center; background-color: #90DDFF ;"^
+ "padding: 2px; }" ;
+
+ "h4 { font-size : 20pt ; border: 1px solid #000000; "^
+ "margin-top: 5px; margin-bottom: 2px;"^
+ "text-align: center; background-color: #90EDFF ;"^
+ "padding: 2px; }" ;
+
+ "h5 { font-size : 20pt ; border: 1px solid #000000; "^
+ "margin-top: 5px; margin-bottom: 2px;"^
+ "text-align: center; background-color: #90FDFF ;"^
+ "padding: 2px; }" ;
+
+ "h6 { font-size : 20pt ; border: 1px solid #000000; "^
+ "margin-top: 5px; margin-bottom: 2px;"^
+ "text-align: center; background-color: #C0FFFF ; "^
+ "padding: 2px; }" ;
+
+ "div.h7 { font-size : 20pt ; border: 1px solid #000000; "^
+ "margin-top: 5px; margin-bottom: 2px;"^
+ "text-align: center; background-color: #E0FFFF ; "^
+ "padding: 2px; }" ;
+
+ "div.h8 { font-size : 20pt ; border: 1px solid #000000; "^
+ "margin-top: 5px; margin-bottom: 2px;"^
+ "text-align: center; background-color: #F0FFFF ; "^
+ "padding: 2px; }" ;
+
+ "div.h9 { font-size : 20pt ; border: 1px solid #000000; "^
+ "margin-top: 5px; margin-bottom: 2px;"^
+ "text-align: center; background-color: #FFFFFF ; "^
+ "padding: 2px; }" ;
+
+ ".typetable { border-style : hidden }" ;
+ ".indextable { border-style : hidden }" ;
+ ".paramstable { border-style : hidden ; padding: 5pt 5pt}" ;
+ "body { background-color : White }" ;
+ "tr { background-color : White }" ;
+ "td.typefieldcomment { background-color : #FFFFFF ; font-size: smaller ;}" ;
+ "pre { margin-bottom: 4px ; margin-left: 1em; "^
+ "border-color: #27408b; border-style: solid; "^
+ "border-width: 1px 1px 1px 3px; "^
+ "padding: 4px; }" ;
+ "div.sig_block {margin-left: 2em}" ;
+
+ "div.codeblock { "^
+ "margin-left: 2em; margin-right: 1em; padding: 6px; "^
+ "margin-bottom: 8px; display: none; "^
+ "border-width: 1px 1px 1px 3px; border-style: solid; border-color: grey; }" ;
+
+ "span.code_expand { color: blue; text-decoration: underline; cursor: pointer; "^
+ "margin-left: 1em ; } ";
+ ];
+ end
+end
+
+let _ = Odoc_args.set_generator
+ (Odoc_gen.Html (module Generator : Odoc_html.Html_generator))
+ ;;
diff --git a/ocaml-binary-annot/ocamldoc/generators/odoc_todo.ml b/ocaml-binary-annot/ocamldoc/generators/odoc_todo.ml
new file mode 100644
index 0000000000..23e6c8892d
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/generators/odoc_todo.ml
@@ -0,0 +1,225 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2010 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id: odoc_todo.ml 411 2004-08-03 13:08:20Z guesdon $ *)
+
+(** An OCamldoc generator to retrieve information in "todo" tags and
+ generate an html page with all todo items. *)
+
+open Odoc_info
+module Naming = Odoc_html.Naming
+open Odoc_info.Value
+open Odoc_info.Module
+open Odoc_info.Type
+open Odoc_info.Exception
+open Odoc_info.Class
+
+let p = Printf.bprintf
+
+module Html =
+ (val
+ (
+ match !Odoc_args.current_generator with
+ None -> (module Odoc_html.Generator : Odoc_html.Html_generator)
+ | Some (Odoc_gen.Html m) -> m
+ | _ ->
+ failwith
+ "A non-html generator is already set. Cannot install the Todo-list html generator"
+ ) : Odoc_html.Html_generator)
+;;
+
+module Generator =
+struct
+ class scanner html =
+ object (self)
+ inherit Odoc_info.Scan.scanner
+
+ val b = Buffer.create 256
+ method buffer = b
+
+ method private gen_if_tag name target info_opt =
+ match info_opt with
+ None -> ()
+ | Some i ->
+ let l =
+ List.fold_left
+ (fun acc (t, text) ->
+ match t with
+ "todo" ->
+ begin
+ match text with
+ (Odoc_info.Code s) :: q ->
+ (
+ try
+ let n = int_of_string s in
+ let head =
+ Odoc_info.Code (Printf.sprintf "[%d] " n)
+ in
+ (Some n, head::q) :: acc
+ with _ -> (None, text) :: acc
+ )
+ | _ -> (None, text) :: acc
+
+ end
+ | _ -> acc
+ )
+ []
+ i.i_custom
+ in
+ match l with
+ [] -> ()
+ | _ ->
+ let l = List.sort
+ (fun a b ->
+ match a, b with
+ (None, _), _ -> -1
+ | _, (None, _) -> 1
+ | (Some n1, _), (Some n2, _) -> compare n1 n2
+ )
+ l
+ in
+ p b "<pre><a href=\"%s\">%s</a></pre><div class=\"info\">"
+ target name;
+ let col = function
+ None -> "#000000"
+ | Some 1 -> "#FF0000"
+ | Some 2 -> "#AA5555"
+ | Some 3 -> "#44BB00"
+ | Some n -> Printf.sprintf "#%2x0000" (0xAA - (n * 0x10))
+ in
+ List.iter
+ (fun (n, e) ->
+ Printf.bprintf b "<span style=\"color: %s\">" (col n);
+ html#html_of_text b e;
+ p b "</span><br/>\n";
+ )
+ l;
+ p b "</div>"
+
+ method scan_value v =
+ self#gen_if_tag
+ v.val_name
+ (Odoc_html.Naming.complete_value_target v)
+ v.val_info
+
+ method scan_type t =
+ self#gen_if_tag
+ t.ty_name
+ (Odoc_html.Naming.complete_type_target t)
+ t.ty_info
+
+ method scan_exception e =
+ self#gen_if_tag
+ e.ex_name
+ (Odoc_html.Naming.complete_exception_target e)
+ e.ex_info
+
+ method scan_attribute a =
+ self#gen_if_tag
+ a.att_value.val_name
+ (Odoc_html.Naming.complete_attribute_target a)
+ a.att_value.val_info
+
+ method scan_method m =
+ self#gen_if_tag
+ m.met_value.val_name
+ (Odoc_html.Naming.complete_method_target m)
+ m.met_value.val_info
+
+ (** This method scan the elements of the given module. *)
+ method scan_module_elements m =
+ List.iter
+ (fun ele ->
+ match ele with
+ Odoc_module.Element_module m -> self#scan_module m
+ | Odoc_module.Element_module_type mt -> self#scan_module_type mt
+ | Odoc_module.Element_included_module im -> self#scan_included_module im
+ | Odoc_module.Element_class c -> self#scan_class c
+ | Odoc_module.Element_class_type ct -> self#scan_class_type ct
+ | Odoc_module.Element_value v -> self#scan_value v
+ | Odoc_module.Element_exception e -> self#scan_exception e
+ | Odoc_module.Element_type t -> self#scan_type t
+ | Odoc_module.Element_module_comment t -> self#scan_module_comment t
+ )
+ (Odoc_module.module_elements ~trans: false m)
+
+ method scan_included_module _ = ()
+
+ method scan_class_pre c =
+ self#gen_if_tag
+ c.cl_name
+ (fst (Odoc_html.Naming.html_files c.cl_name))
+ c.cl_info;
+ true
+
+ method scan_class_type_pre ct =
+ self#gen_if_tag
+ ct.clt_name
+ (fst (Odoc_html.Naming.html_files ct.clt_name))
+ ct.clt_info;
+ true
+
+ method scan_module_pre m =
+ self#gen_if_tag
+ m.m_name
+ (fst (Odoc_html.Naming.html_files m.m_name))
+ m.m_info;
+ true
+
+ method scan_module_type_pre mt =
+ self#gen_if_tag
+ mt.mt_name
+ (fst (Odoc_html.Naming.html_files mt.mt_name))
+ mt.mt_info;
+ true
+ end
+
+ class html : Html.html =
+ object (self)
+ inherit Html.html as html
+
+ (** we have to hack a little because we cannot inherit from
+ scanner, since public method cannot be hidden and
+ our html class must respect the type of the default
+ html generator class *)
+ val mutable scanner = new scanner (new Html.html )
+
+ method generate modules =
+ (* prevent having the 'todo' tag signaled as not handled *)
+ tag_functions <- ("todo", (fun _ -> "")) :: tag_functions;
+ (* generate doc as usual *)
+ html#generate modules;
+ (* then retrieve the todo tags and generate the todo.html page *)
+ let title =
+ match !Odoc_info.Global.title with
+ None -> ""
+ | Some s -> s
+ in
+ let b = Buffer.create 512 in
+ p b "<html>";
+ self#print_header b title ;
+ p b "<body><h1>%s</h1>" title;
+ scanner#scan_module_list modules;
+ Buffer.add_buffer b scanner#buffer;
+ let oc = open_out
+ (Filename.concat !Odoc_info.Global.target_dir "todo.html")
+ in
+ Buffer.output_buffer oc b;
+ close_out oc
+
+ initializer
+ scanner <- new scanner self
+ end
+end
+
+let _ = Odoc_args.set_generator
+ (Odoc_gen.Html (module Generator : Odoc_html.Html_generator))
+ ;;
diff --git a/ocaml-binary-annot/ocamldoc/ocamldoc.hva b/ocaml-binary-annot/ocamldoc/ocamldoc.hva
new file mode 100644
index 0000000000..454cee9e7e
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/ocamldoc.hva
@@ -0,0 +1,19 @@
+\usepackage{alltt}
+\newenvironment{ocamldoccode}{\begin{alltt}}{\end{alltt}}
+\newenvironment{ocamldocdescription}{\begin{quote}}{\end{quote}}
+\newenvironment{ocamldoccomment}{\begin{quote}}{\end{quote}}
+\newcommand\textbar{|}
+\newcommand\textbackslash{\begin{rawhtml}\\end{rawhtml}}
+\newcommand\textasciicircum{\^{}}
+\newcommand\sharp{#}
+
+\let\ocamldocvspace\vspace
+\newenvironment{ocamldocindent}{\list{}{}\item\relax}{\endlist}
+\newenvironment{ocamldocsigend}
+ {\noindent\quad\texttt{sig}\ocamldocindent}
+ {\endocamldocindent\vskip -\lastskip
+ \noindent\quad\texttt{end}\medskip}
+\newenvironment{ocamldocobjectend}
+ {\noindent\quad\texttt{object}\ocamldocindent}
+ {\endocamldocindent\vskip -\lastskip
+ \noindent\quad\texttt{end}\medskip}
diff --git a/ocaml-binary-annot/ocamldoc/ocamldoc.sty b/ocaml-binary-annot/ocamldoc/ocamldoc.sty
new file mode 100644
index 0000000000..6a8ef1e959
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/ocamldoc.sty
@@ -0,0 +1,58 @@
+%% Support macros for LaTeX documentation generated by ocamldoc.
+%% This file is in the public domain; do what you want with it.
+
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{ocamldoc}
+ [2001/12/04 v1.0 ocamldoc support]
+
+\newenvironment{ocamldoccode}{%
+ \bgroup
+ \leftskip\@totalleftmargin
+ \rightskip\z@skip
+ \parindent\z@
+ \parfillskip\@flushglue
+ \parskip\z@skip
+ %\noindent
+ \@@par\smallskip
+ \@tempswafalse
+ \def\par{%
+ \if@tempswa
+ \leavevmode\null\@@par\penalty\interlinepenalty
+ \else
+ \@tempswatrue
+ \ifhmode\@@par\penalty\interlinepenalty\fi
+ \fi}
+ \obeylines
+ \verbatim@font
+ \let\org@prime~%
+ \@noligs
+ \let\org@dospecials\dospecials
+ \g@remfrom@specials{\\}
+ \g@remfrom@specials{\{}
+ \g@remfrom@specials{\}}
+ \let\do\@makeother
+ \dospecials
+ \let\dospecials\org@dospecials
+ \frenchspacing\@vobeyspaces
+ \everypar \expandafter{\the\everypar \unpenalty}}
+{\egroup\par}
+
+\def\g@remfrom@specials#1{%
+ \def\@new@specials{}
+ \def\@remove##1{%
+ \ifx##1#1\else
+ \g@addto@macro\@new@specials{\do ##1}\fi}
+ \let\do\@remove\dospecials
+ \let\dospecials\@new@specials
+ }
+
+\newenvironment{ocamldocdescription}
+{\list{}{\rightmargin0pt \topsep0pt}\raggedright\item\relax}
+{\endlist\medskip}
+
+\newenvironment{ocamldoccomment}
+{\list{}{\leftmargin 2\leftmargini \rightmargin0pt \topsep0pt}\raggedright\item\relax}
+{\endlist}
+
+\let\ocamldocvspace\vspace
+\endinput
diff --git a/ocaml-binary-annot/ocamldoc/odoc.ml b/ocaml-binary-annot/ocamldoc/odoc.ml
new file mode 100644
index 0000000000..54b84db93c
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc.ml
@@ -0,0 +1,137 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Main module for bytecode.
+@todo coucou le todo*)
+
+open Config
+open Clflags
+open Misc
+open Format
+open Typedtree
+
+module M = Odoc_messages
+
+let print_DEBUG s = print_string s ; print_newline ()
+
+(* we check if we must load a module given on the command line *)
+let arg_list = Array.to_list Sys.argv
+let (plugins, paths) =
+ let rec iter (files, incs) = function
+ [] | _ :: [] -> (List.rev files, List.rev incs)
+ | "-g" :: file :: q when
+ ((Filename.check_suffix file "cmo") or
+ (Filename.check_suffix file "cma") or
+ (Filename.check_suffix file "cmxs")) ->
+ iter (file :: files, incs) q
+ | "-i" :: dir :: q ->
+ iter (files, dir :: incs) q
+ | _ :: q ->
+ iter (files, incs) q
+ in
+ iter ([], []) arg_list
+
+let _ = print_DEBUG "Fin analyse des arguments pour le dynamic load"
+
+(** Return the real name of the file to load,
+ searching it in the paths if it is
+ a simple name and not in the current directory. *)
+let get_real_filename name =
+ if Filename.basename name <> name then
+ name
+ else
+ (
+ let paths = Filename.current_dir_name :: paths @ [Odoc_config.custom_generators_path] in
+ try
+ let d = List.find
+ (fun d -> Sys.file_exists (Filename.concat d name))
+ paths
+ in
+ Filename.concat d name
+ with
+ Not_found ->
+ failwith (M.file_not_found_in_paths paths name)
+ )
+
+let load_plugin file =
+ let file = Dynlink.adapt_filename file in
+ Dynlink.allow_unsafe_modules true;
+ try
+ let real_file = get_real_filename file in
+ ignore(Dynlink.loadfile real_file)
+ with
+ Dynlink.Error e ->
+ prerr_endline (Odoc_messages.load_file_error file (Dynlink.error_message e)) ;
+ exit 1
+ | Not_found ->
+ prerr_endline (Odoc_messages.load_file_error file "Not_found");
+ exit 1
+ | Sys_error s
+ | Failure s ->
+ prerr_endline (Odoc_messages.load_file_error file s);
+ exit 1
+;;
+List.iter load_plugin plugins;;
+
+let () = print_DEBUG "Fin du chargement dynamique eventuel"
+
+let () = Odoc_args.parse ()
+
+
+let loaded_modules =
+ List.flatten
+ (List.map
+ (fun f ->
+ Odoc_info.verbose (Odoc_messages.loading f);
+ try
+ let l = Odoc_analyse.load_modules f in
+ Odoc_info.verbose Odoc_messages.ok;
+ l
+ with Failure s ->
+ prerr_endline s ;
+ incr Odoc_global.errors ;
+ []
+ )
+ !Odoc_global.load
+ )
+
+let modules = Odoc_analyse.analyse_files ~init: loaded_modules !Odoc_global.files
+
+let _ =
+ match !Odoc_global.dump with
+ None -> ()
+ | Some f ->
+ try Odoc_analyse.dump_modules f modules
+ with Failure s ->
+ prerr_endline s ;
+ incr Odoc_global.errors
+
+
+let _ =
+ match !Odoc_args.current_generator with
+ None ->
+ ()
+ | Some gen ->
+ let generator = Odoc_gen.get_minimal_generator gen in
+ Odoc_info.verbose Odoc_messages.generating_doc;
+ generator#generate modules;
+ Odoc_info.verbose Odoc_messages.ok
+
+let _ =
+ if !Odoc_global.errors > 0 then
+ (
+ prerr_endline (Odoc_messages.errors_occured !Odoc_global.errors) ;
+ exit 1
+ )
+ else
+ exit 0
diff --git a/ocaml-binary-annot/ocamldoc/odoc_analyse.ml b/ocaml-binary-annot/ocamldoc/odoc_analyse.ml
new file mode 100644
index 0000000000..2091dd3967
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_analyse.ml
@@ -0,0 +1,539 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Analysis of source files. This module is strongly inspired from
+ driver/main.ml :-) *)
+
+let print_DEBUG s = print_string s ; print_newline ()
+
+open Config
+open Clflags
+open Misc
+open Format
+open Typedtree
+
+
+(** Initialize the search path.
+ The current directory is always searched first,
+ then the directories specified with the -I option (in command-line order),
+ then the standard library directory. *)
+let init_path () =
+ load_path :=
+ "" :: List.rev (Config.standard_library :: !Clflags.include_dirs);
+ Env.reset_cache ()
+
+(** Return the initial environment in which compilation proceeds. *)
+let initial_env () =
+ try
+ if !Clflags.nopervasives
+ then Env.initial
+ else Env.open_pers_signature "Pervasives" Env.initial
+ with Not_found ->
+ fatal_error "cannot open pervasives.cmi"
+
+(** Optionally preprocess a source file *)
+let preprocess sourcefile =
+ match !Clflags.preprocessor with
+ None -> sourcefile
+ | Some pp ->
+ let tmpfile = Filename.temp_file "camlpp" "" in
+ let comm = Printf.sprintf "%s %s > %s" pp sourcefile tmpfile in
+ if Ccomp.command comm <> 0 then begin
+ remove_file tmpfile;
+ Printf.eprintf "Preprocessing error\n";
+ exit 2
+ end;
+ tmpfile
+
+(** Remove the input file if this file was the result of a preprocessing.*)
+let remove_preprocessed inputfile =
+ match !Clflags.preprocessor with
+ None -> ()
+ | Some _ -> remove_file inputfile
+
+let remove_preprocessed_if_ast inputfile =
+ match !Clflags.preprocessor with
+ None -> ()
+ | Some _ -> if inputfile <> !Location.input_name then remove_file inputfile
+
+exception Outdated_version
+
+(** Parse a file or get a dumped syntax tree in it *)
+let parse_file inputfile parse_fun ast_magic =
+ let ic = open_in_bin inputfile in
+ let is_ast_file =
+ try
+ let buffer = String.create (String.length ast_magic) in
+ really_input ic buffer 0 (String.length ast_magic);
+ if buffer = ast_magic then true
+ else if String.sub buffer 0 9 = String.sub ast_magic 0 9 then
+ raise Outdated_version
+ else false
+ with
+ Outdated_version ->
+ fatal_error "Ocaml and preprocessor have incompatible versions"
+ | _ -> false
+ in
+ let ast =
+ try
+ if is_ast_file then begin
+ Location.input_name := input_value ic;
+ input_value ic
+ end else begin
+ seek_in ic 0;
+ Location.input_name := inputfile;
+ let lexbuf = Lexing.from_channel ic in
+ Location.init lexbuf inputfile;
+ parse_fun lexbuf
+ end
+ with x -> close_in ic; raise x
+ in
+ close_in ic;
+ ast
+
+let (++) x f = f x
+
+(** Analysis of an implementation file. Returns (Some typedtree) if
+ no error occured, else None and an error message is printed.*)
+let process_implementation_file ppf sourcefile =
+ init_path ();
+ let prefixname = Filename.chop_extension sourcefile in
+ let modulename = String.capitalize(Filename.basename prefixname) in
+ Env.set_unit_name modulename;
+ let inputfile = preprocess sourcefile in
+ let env = initial_env () in
+ try
+ let parsetree = parse_file inputfile Parse.implementation ast_impl_magic_number in
+ let typedtree = Typemod.type_implementation sourcefile prefixname modulename env parsetree in
+ (Some (parsetree, typedtree), inputfile)
+ with
+ e ->
+ match e with
+ Syntaxerr.Error err ->
+ fprintf Format.err_formatter "@[%a@]@."
+ Syntaxerr.report_error err;
+ None, inputfile
+ | Failure s ->
+ prerr_endline s;
+ incr Odoc_global.errors ;
+ None, inputfile
+ | e ->
+ raise e
+
+(** Analysis of an interface file. Returns (Some signature) if
+ no error occured, else None and an error message is printed.*)
+let process_interface_file ppf sourcefile =
+ init_path ();
+ let prefixname = Filename.chop_extension sourcefile in
+ let modulename = String.capitalize(Filename.basename prefixname) in
+ Env.set_unit_name modulename;
+ let inputfile = preprocess sourcefile in
+ let ast = parse_file inputfile Parse.interface ast_intf_magic_number in
+ let sg = Typemod.transl_signature (initial_env()) ast in
+ Warnings.check_fatal ();
+ (ast, sg, inputfile)
+
+(** The module used to analyse the parsetree and signature of an implementation file.*)
+module Ast_analyser = Odoc_ast.Analyser (Odoc_comments.Basic_info_retriever)
+
+(** The module used to analyse the parse tree and typed tree of an interface file.*)
+module Sig_analyser = Odoc_sig.Analyser (Odoc_comments.Basic_info_retriever)
+
+(** Handle an error. This is a partial copy of the compiler
+ driver/error.ml file. We do this because there are
+ some differences between the possibly raised exceptions
+ in the bytecode (error.ml) and opt (opterros.ml) compilers
+ and we don't want to take care of this. Besises, these
+ differences only concern code generation (i believe).*)
+let process_error exn =
+ let report ppf = function
+ | Lexer.Error(err, loc) ->
+ Location.print_error ppf loc;
+ Lexer.report_error ppf err
+ | Syntaxerr.Error err ->
+ Syntaxerr.report_error ppf err
+ | Env.Error err ->
+ Location.print_error_cur_file ppf;
+ Env.report_error ppf err
+ | Ctype.Tags(l, l') ->
+ Location.print_error_cur_file ppf;
+ fprintf ppf
+ "In this program,@ variant constructors@ `%s and `%s@ \
+ have the same hash value." l l'
+ | Typecore.Error(loc, err) ->
+ Location.print_error ppf loc; Typecore.report_error ppf err
+ | Typetexp.Error(loc, err) ->
+ Location.print_error ppf loc; Typetexp.report_error ppf err
+ | Typedecl.Error(loc, err) ->
+ Location.print_error ppf loc; Typedecl.report_error ppf err
+ | Includemod.Error err ->
+ Location.print_error_cur_file ppf;
+ Includemod.report_error ppf err
+ | Typemod.Error(loc, err) ->
+ Location.print_error ppf loc; Typemod.report_error ppf err
+ | Translcore.Error(loc, err) ->
+ Location.print_error ppf loc; Translcore.report_error ppf err
+ | Sys_error msg ->
+ Location.print_error_cur_file ppf;
+ fprintf ppf "I/O error: %s" msg
+ | Typeclass.Error(loc, err) ->
+ Location.print_error ppf loc; Typeclass.report_error ppf err
+ | Translclass.Error(loc, err) ->
+ Location.print_error ppf loc; Translclass.report_error ppf err
+ | Warnings.Errors (n) ->
+ Location.print_error_cur_file ppf;
+ fprintf ppf "Error-enabled warnings (%d occurrences)" n
+ | x ->
+ fprintf ppf "@]";
+ fprintf ppf
+ "Compilation error(%s). Use the OCaml compiler to get more details."
+ (Printexc.to_string x)
+ in
+ Format.fprintf Format.err_formatter "@[%a@]@." report exn
+
+(** Process the given file, according to its extension. Return the Module.t created, if any.*)
+let process_file ppf sourcefile =
+ if !Odoc_global.verbose then
+ (
+ let f = match sourcefile with
+ Odoc_global.Impl_file f
+ | Odoc_global.Intf_file f -> f
+ | Odoc_global.Text_file f -> f
+ in
+ print_string (Odoc_messages.analysing f) ;
+ print_newline ();
+ );
+ match sourcefile with
+ Odoc_global.Impl_file file ->
+ (
+ Location.input_name := file;
+ try
+ let (parsetree_typedtree_opt, input_file) = process_implementation_file ppf file in
+ match parsetree_typedtree_opt with
+ None ->
+ None
+ | Some (parsetree, typedtree) ->
+ let file_module = Ast_analyser.analyse_typed_tree file
+ !Location.input_name parsetree typedtree
+ in
+ file_module.Odoc_module.m_top_deps <- Odoc_dep.impl_dependencies parsetree ;
+
+ if !Odoc_global.verbose then
+ (
+ print_string Odoc_messages.ok;
+ print_newline ()
+ );
+ remove_preprocessed input_file;
+ Some file_module
+ with
+ | Sys_error s
+ | Failure s ->
+ prerr_endline s ;
+ incr Odoc_global.errors ;
+ None
+ | e ->
+ process_error e ;
+ incr Odoc_global.errors ;
+ None
+ )
+ | Odoc_global.Intf_file file ->
+ (
+ Location.input_name := file;
+ try
+ let (ast, signat, input_file) = process_interface_file ppf file in
+ let file_module = Sig_analyser.analyse_signature file
+ !Location.input_name ast signat
+ in
+
+ file_module.Odoc_module.m_top_deps <- Odoc_dep.intf_dependencies ast ;
+
+ if !Odoc_global.verbose then
+ (
+ print_string Odoc_messages.ok;
+ print_newline ()
+ );
+ remove_preprocessed input_file;
+ Some file_module
+ with
+ | Sys_error s
+ | Failure s ->
+ prerr_endline s;
+ incr Odoc_global.errors ;
+ None
+ | e ->
+ process_error e ;
+ incr Odoc_global.errors ;
+ None
+ )
+ | Odoc_global.Text_file file ->
+ Location.input_name := file;
+ try
+ let mod_name =
+ String.capitalize (Filename.basename (Filename.chop_extension file))
+ in
+ let txt =
+ try Odoc_text.Texter.text_of_string (Odoc_misc.input_file_as_string file)
+ with Odoc_text.Text_syntax (l, c, s) ->
+ raise (Failure (Odoc_messages.text_parse_error l c s))
+ in
+ let m =
+ {
+ Odoc_module.m_name = mod_name ;
+ Odoc_module.m_type = Types.Tmty_signature [] ;
+ Odoc_module.m_info = None ;
+ Odoc_module.m_is_interface = true ;
+ Odoc_module.m_file = file ;
+ Odoc_module.m_kind = Odoc_module.Module_struct
+ [Odoc_module.Element_module_comment txt] ;
+ Odoc_module.m_loc =
+ { Odoc_types.loc_impl = None ;
+ Odoc_types.loc_inter = Some (file, 0) } ;
+ Odoc_module.m_top_deps = [] ;
+ Odoc_module.m_code = None ;
+ Odoc_module.m_code_intf = None ;
+ Odoc_module.m_text_only = true ;
+ }
+ in
+ Some m
+ with
+ | Sys_error s
+ | Failure s ->
+ prerr_endline s;
+ incr Odoc_global.errors ;
+ None
+ | e ->
+ process_error e ;
+ incr Odoc_global.errors ;
+ None
+
+(** Remove the class elements between the stop special comments. *)
+let rec remove_class_elements_between_stop keep eles =
+ match eles with
+ [] -> []
+ | ele :: q ->
+ match ele with
+ Odoc_class.Class_comment [ Odoc_types.Raw "/*" ] ->
+ remove_class_elements_between_stop (not keep) q
+ | Odoc_class.Class_attribute _
+ | Odoc_class.Class_method _
+ | Odoc_class.Class_comment _ ->
+ if keep then
+ ele :: (remove_class_elements_between_stop keep q)
+ else
+ remove_class_elements_between_stop keep q
+
+(** Remove the class elements between the stop special comments in a class kind. *)
+let rec remove_class_elements_between_stop_in_class_kind k =
+ match k with
+ Odoc_class.Class_structure (inher, l) ->
+ Odoc_class.Class_structure (inher, remove_class_elements_between_stop true l)
+ | Odoc_class.Class_apply _ -> k
+ | Odoc_class.Class_constr _ -> k
+ | Odoc_class.Class_constraint (k1, ctk) ->
+ Odoc_class.Class_constraint (remove_class_elements_between_stop_in_class_kind k1,
+ remove_class_elements_between_stop_in_class_type_kind ctk)
+
+(** Remove the class elements beetween the stop special comments in a class type kind. *)
+and remove_class_elements_between_stop_in_class_type_kind tk =
+ match tk with
+ Odoc_class.Class_signature (inher, l) ->
+ Odoc_class.Class_signature (inher, remove_class_elements_between_stop true l)
+ | Odoc_class.Class_type _ -> tk
+
+
+(** Remove the module elements between the stop special comments. *)
+let rec remove_module_elements_between_stop keep eles =
+ let f = remove_module_elements_between_stop in
+ match eles with
+ [] -> []
+ | ele :: q ->
+ match ele with
+ Odoc_module.Element_module_comment [ Odoc_types.Raw "/*" ] ->
+ f (not keep) q
+ | Odoc_module.Element_module_comment _ ->
+ if keep then
+ ele :: (f keep q)
+ else
+ f keep q
+ | Odoc_module.Element_module m ->
+ if keep then
+ (
+ m.Odoc_module.m_kind <- remove_module_elements_between_stop_in_module_kind m.Odoc_module.m_kind ;
+ (Odoc_module.Element_module m) :: (f keep q)
+ )
+ else
+ f keep q
+ | Odoc_module.Element_module_type mt ->
+ if keep then
+ (
+ mt.Odoc_module.mt_kind <- Odoc_misc.apply_opt
+ remove_module_elements_between_stop_in_module_type_kind mt.Odoc_module.mt_kind ;
+ (Odoc_module.Element_module_type mt) :: (f keep q)
+ )
+ else
+ f keep q
+ | Odoc_module.Element_included_module _ ->
+ if keep then
+ ele :: (f keep q)
+ else
+ f keep q
+ | Odoc_module.Element_class c ->
+ if keep then
+ (
+ c.Odoc_class.cl_kind <- remove_class_elements_between_stop_in_class_kind c.Odoc_class.cl_kind ;
+ (Odoc_module.Element_class c) :: (f keep q)
+ )
+ else
+ f keep q
+ | Odoc_module.Element_class_type ct ->
+ if keep then
+ (
+ ct.Odoc_class.clt_kind <- remove_class_elements_between_stop_in_class_type_kind ct.Odoc_class.clt_kind ;
+ (Odoc_module.Element_class_type ct) :: (f keep q)
+ )
+ else
+ f keep q
+ | Odoc_module.Element_value _
+ | Odoc_module.Element_exception _
+ | Odoc_module.Element_type _ ->
+ if keep then
+ ele :: (f keep q)
+ else
+ f keep q
+
+
+(** Remove the module elements between the stop special comments, in the given module kind. *)
+and remove_module_elements_between_stop_in_module_kind k =
+ match k with
+ | Odoc_module.Module_struct l -> Odoc_module.Module_struct (remove_module_elements_between_stop true l)
+ | Odoc_module.Module_alias _ -> k
+ | Odoc_module.Module_functor (params, k2) ->
+ Odoc_module.Module_functor (params, remove_module_elements_between_stop_in_module_kind k2)
+ | Odoc_module.Module_apply (k1, k2) ->
+ Odoc_module.Module_apply (remove_module_elements_between_stop_in_module_kind k1,
+ remove_module_elements_between_stop_in_module_kind k2)
+ | Odoc_module.Module_with (mtkind, s) ->
+ Odoc_module.Module_with (remove_module_elements_between_stop_in_module_type_kind mtkind, s)
+ | Odoc_module.Module_constraint (k2, mtkind) ->
+ Odoc_module.Module_constraint (remove_module_elements_between_stop_in_module_kind k2,
+ remove_module_elements_between_stop_in_module_type_kind mtkind)
+ | Odoc_module.Module_typeof _ -> k
+ | Odoc_module.Module_unpack _ -> k
+
+(** Remove the module elements between the stop special comment, in the given module type kind. *)
+and remove_module_elements_between_stop_in_module_type_kind tk =
+ match tk with
+ | Odoc_module.Module_type_struct l -> Odoc_module.Module_type_struct (remove_module_elements_between_stop true l)
+ | Odoc_module.Module_type_functor (params, tk2) ->
+ Odoc_module.Module_type_functor (params, remove_module_elements_between_stop_in_module_type_kind tk2)
+ | Odoc_module.Module_type_alias _ -> tk
+ | Odoc_module.Module_type_with (tk2, s) ->
+ Odoc_module.Module_type_with (remove_module_elements_between_stop_in_module_type_kind tk2, s)
+ | Odoc_module.Module_type_typeof _ -> tk
+
+(** Remove elements between the stop special comment. *)
+let remove_elements_between_stop module_list =
+ List.map
+ (fun m ->
+ m.Odoc_module.m_kind <- remove_module_elements_between_stop_in_module_kind m.Odoc_module.m_kind;
+ m
+ )
+ module_list
+
+(** This function builds the modules from the given list of source files. *)
+let analyse_files ?(init=[]) files =
+ let modules_pre =
+ init @
+ (List.fold_left
+ (fun acc -> fun file ->
+ try
+ match process_file Format.err_formatter file with
+ None ->
+ acc
+ | Some m ->
+ acc @ [ m ]
+ with
+ Failure s ->
+ prerr_endline s ;
+ incr Odoc_global.errors ;
+ acc
+ )
+ []
+ files
+ )
+ in
+ (* Remove elements between the stop special comments, if needed. *)
+ let modules =
+ if !Odoc_global.no_stop then
+ modules_pre
+ else
+ remove_elements_between_stop modules_pre
+ in
+
+
+ if !Odoc_global.verbose then
+ (
+ print_string Odoc_messages.merging;
+ print_newline ()
+ );
+ let merged_modules = Odoc_merge.merge !Odoc_global.merge_options modules in
+ if !Odoc_global.verbose then
+ (
+ print_string Odoc_messages.ok;
+ print_newline ();
+ );
+ let modules_list =
+ (List.fold_left
+ (fun acc -> fun m -> acc @ (Odoc_module.module_all_submodules ~trans: false m))
+ merged_modules
+ merged_modules
+ )
+ in
+ if !Odoc_global.verbose then
+ (
+ print_string Odoc_messages.cross_referencing;
+ print_newline ()
+ );
+ let _ = Odoc_cross.associate modules_list in
+
+ if !Odoc_global.verbose then
+ (
+ print_string Odoc_messages.ok;
+ print_newline ();
+ );
+
+ if !Odoc_global.sort_modules then
+ Sort.list (fun m1 -> fun m2 -> m1.Odoc_module.m_name < m2.Odoc_module.m_name) merged_modules
+ else
+ merged_modules
+
+let dump_modules file (modules : Odoc_module.t_module list) =
+ try
+ let chanout = open_out_bin file in
+ let dump = Odoc_types.make_dump modules in
+ output_value chanout dump;
+ close_out chanout
+ with
+ Sys_error s ->
+ raise (Failure s)
+
+let load_modules file =
+ try
+ let chanin = open_in_bin file in
+ let dump = input_value chanin in
+ close_in chanin ;
+ let (l : Odoc_module.t_module list) = Odoc_types.open_dump dump in
+ l
+ with
+ Sys_error s ->
+ raise (Failure s)
diff --git a/ocaml-binary-annot/ocamldoc/odoc_analyse.mli b/ocaml-binary-annot/ocamldoc/odoc_analyse.mli
new file mode 100644
index 0000000000..b927ad4a06
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_analyse.mli
@@ -0,0 +1,31 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Analysis of source files. *)
+
+(** This function builds the top modules from the analysis of the
+ given list of source files.
+ @param init is the list of modules already known from a previous analysis.
+*)
+val analyse_files :
+ ?init: Odoc_module.t_module list ->
+ Odoc_global.source_file list ->
+ Odoc_module.t_module list
+
+(** Dump of a list of modules into a file.
+ @raise Failure if an error occurs.*)
+val dump_modules : string -> Odoc_module.t_module list -> unit
+
+(** Load of a list of modules from a file.
+ @raise Failure if an error occurs.*)
+val load_modules : string -> Odoc_module.t_module list
diff --git a/ocaml-binary-annot/ocamldoc/odoc_args.ml b/ocaml-binary-annot/ocamldoc/odoc_args.ml
new file mode 100644
index 0000000000..f3500f51d3
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_args.ml
@@ -0,0 +1,245 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* cvsid $Id$ *)
+
+(** Command-line arguments. *)
+
+module M = Odoc_messages
+
+let current_generator = ref (None : Odoc_gen.generator option)
+
+(** Analysis of a string defining options. Return the list of
+ options according to the list giving associations between
+ [(character, _)] and a list of options. *)
+let analyse_option_string l s =
+ List.fold_left
+ (fun acc -> fun ((c,_), v) ->
+ if String.contains s c then
+ acc @ v
+ else
+ acc)
+ []
+ l
+
+(** Analysis of a string defining the merge options to be used.
+ Returns the list of options specified.*)
+let analyse_merge_options s =
+ let l = [
+ (M.merge_description, [Odoc_types.Merge_description]) ;
+ (M.merge_author, [Odoc_types.Merge_author]) ;
+ (M.merge_version, [Odoc_types.Merge_version]) ;
+ (M.merge_see, [Odoc_types.Merge_see]) ;
+ (M.merge_since, [Odoc_types.Merge_since]) ;
+ (M.merge_deprecated, [Odoc_types.Merge_deprecated]) ;
+ (M.merge_param, [Odoc_types.Merge_param]) ;
+ (M.merge_raised_exception, [Odoc_types.Merge_raised_exception]) ;
+ (M.merge_return_value, [Odoc_types.Merge_return_value]) ;
+ (M.merge_custom, [Odoc_types.Merge_custom]) ;
+ (M.merge_all, Odoc_types.all_merge_options)
+ ]
+ in
+ analyse_option_string l s
+
+
+let f_latex_title s =
+ try
+ let pos = String.index s ',' in
+ let n = int_of_string (String.sub s 0 pos) in
+ let len = String.length s in
+ let command = String.sub s (pos + 1) (len - pos - 1) in
+ Odoc_latex.latex_titles := List.remove_assoc n !Odoc_latex.latex_titles ;
+ Odoc_latex.latex_titles := (n, command) :: !Odoc_latex.latex_titles
+ with
+ Not_found
+ | Invalid_argument _ ->
+ incr Odoc_global.errors ;
+ prerr_endline (M.wrong_format s)
+
+let add_hidden_modules s =
+ let l = Str.split (Str.regexp ",") s in
+ List.iter
+ (fun n ->
+ let name = Str.global_replace (Str.regexp "[ \n\r\t]+") "" n in
+ match name with
+ "" -> ()
+ | _ ->
+ match name.[0] with
+ 'A'..'Z' -> Odoc_global.hidden_modules := name :: !Odoc_global.hidden_modules
+ | _ ->
+ incr Odoc_global.errors;
+ prerr_endline (M.not_a_module_name name)
+ )
+ l
+
+let set_generator (g : Odoc_gen.generator) = current_generator := Some g
+
+(** The default option list *)
+let options = ref [
+ "-version", Arg.Unit (fun () -> print_string M.message_version ; print_newline () ; exit 0) , M.option_version ;
+ "-vnum", Arg.Unit (fun () -> print_string M.config_version ;
+ print_newline () ; exit 0) , M.option_version ;
+ "-v", Arg.Unit (fun () -> Odoc_global.verbose := true), M.verbose_mode ;
+ "-I", Arg.String (fun s ->
+ Odoc_global.include_dirs :=
+ (Misc.expand_directory Config.standard_library s) :: !Odoc_global.include_dirs),
+ M.include_dirs ;
+ "-pp", Arg.String (fun s -> Odoc_global.preprocessor := Some s), M.preprocess ;
+ "-impl", Arg.String (fun s ->
+ Odoc_global.files := !Odoc_global.files @ [Odoc_global.Impl_file s]),
+ M.option_impl ;
+ "-intf", Arg.String (fun s ->
+ Odoc_global.files := !Odoc_global.files @ [Odoc_global.Intf_file s]),
+ M.option_intf ;
+ "-text", Arg.String (fun s ->
+ Odoc_global.files := !Odoc_global.files @ [Odoc_global.Text_file s]),
+ M.option_text ;
+ "-rectypes", Arg.Set Odoc_global.recursive_types, M.rectypes ;
+ "-nolabels", Arg.Unit (fun () -> Odoc_global.classic := true), M.nolabels ;
+ "-warn-error", Arg.Set Odoc_global.warn_error, M.werr ;
+ "-hide-warnings", Arg.Clear Odoc_config.print_warnings, M.hide_warnings ;
+ "-o", Arg.String (fun s -> Odoc_global.out_file := s), M.out_file ;
+ "-d", Arg.String (fun s -> Odoc_global.target_dir := s), M.target_dir ;
+ "-sort", Arg.Unit (fun () -> Odoc_global.sort_modules := true), M.sort_modules ;
+ "-no-stop", Arg.Set Odoc_global.no_stop, M.no_stop ;
+ "-no-custom-tags", Arg.Set Odoc_global.no_custom_tags, M.no_custom_tags ;
+ "-stars", Arg.Set Odoc_global.remove_stars, M.remove_stars ;
+ "-inv-merge-ml-mli", Arg.Set Odoc_global.inverse_merge_ml_mli, M.inverse_merge_ml_mli ;
+ "-no-module-constraint-filter", Arg.Clear Odoc_global.filter_with_module_constraints,
+ M.no_filter_with_module_constraints ;
+
+ "-keep-code", Arg.Set Odoc_global.keep_code, M.keep_code^"\n" ;
+
+ "-dump", Arg.String (fun s -> Odoc_global.dump := Some s), M.dump ;
+ "-load", Arg.String (fun s -> Odoc_global.load := !Odoc_global.load @ [s]), M.load^"\n" ;
+
+ "-t", Arg.String (fun s -> Odoc_global.title := Some s), M.option_title ;
+ "-intro", Arg.String (fun s -> Odoc_global.intro_file := Some s), M.option_intro ;
+ "-hide", Arg.String add_hidden_modules, M.hide_modules ;
+ "-m", Arg.String (fun s -> Odoc_global.merge_options := !Odoc_global.merge_options @ (analyse_merge_options s)),
+ M.merge_options ^
+ "\n\n *** choosing a generator ***\n";
+
+(* generators *)
+ "-html", Arg.Unit (fun () -> set_generator
+ (Odoc_gen.Html (module Odoc_html.Generator : Odoc_html.Html_generator))),
+ M.generate_html ;
+ "-latex", Arg.Unit (fun () -> set_generator
+ (Odoc_gen.Latex (module Odoc_latex.Generator : Odoc_latex.Latex_generator))),
+ M.generate_latex ;
+ "-texi", Arg.Unit (fun () -> set_generator
+ (Odoc_gen.Texi (module Odoc_texi.Generator : Odoc_texi.Texi_generator))),
+ M.generate_texinfo ;
+ "-man", Arg.Unit (fun () -> set_generator
+ (Odoc_gen.Man (module Odoc_man.Generator : Odoc_man.Man_generator))),
+ M.generate_man ;
+ "-dot", Arg.Unit (fun () -> set_generator
+ (Odoc_gen.Dot (module Odoc_dot.Generator : Odoc_dot.Dot_generator))),
+ M.generate_dot ;
+ "-customdir", Arg.Unit (fun () -> Printf.printf "%s\n" Odoc_config.custom_generators_path; exit 0),
+ M.display_custom_generators_dir ;
+ "-i", Arg.String (fun s -> ()), M.add_load_dir ;
+ "-g", Arg.String (fun s -> ()), M.load_file ^
+ "\n\n *** HTML options ***\n";
+
+(* html only options *)
+ "-all-params", Arg.Set Odoc_html.with_parameter_list, M.with_parameter_list ;
+ "-css-style", Arg.String (fun s -> Odoc_html.css_style := Some s), M.css_style ;
+ "-index-only", Arg.Set Odoc_html.index_only, M.index_only ;
+ "-colorize-code", Arg.Set Odoc_html.colorize_code, M.colorize_code ;
+ "-short-functors", Arg.Set Odoc_html.html_short_functors, M.html_short_functors ^
+ "\n\n *** LaTeX options ***\n";
+
+(* latex only options *)
+ "-noheader", Arg.Unit (fun () -> Odoc_global.with_header := false), M.no_header ;
+ "-notrailer", Arg.Unit (fun () -> Odoc_global.with_trailer := false), M.no_trailer ;
+ "-sepfiles", Arg.Set Odoc_latex.separate_files, M.separate_files ;
+ "-latextitle", Arg.String f_latex_title, M.latex_title Odoc_latex.latex_titles ;
+ "-latex-value-prefix",
+ Arg.String (fun s -> Odoc_latex.latex_value_prefix := s), M.latex_value_prefix ;
+ "-latex-type-prefix",
+ Arg.String (fun s -> Odoc_latex.latex_type_prefix := s), M.latex_type_prefix ;
+ "-latex-exception-prefix",
+ Arg.String (fun s -> Odoc_latex.latex_exception_prefix := s), M.latex_exception_prefix ;
+ "-latex-attribute-prefix",
+ Arg.String (fun s -> Odoc_latex.latex_attribute_prefix := s), M.latex_attribute_prefix ;
+ "-latex-method-prefix",
+ Arg.String (fun s -> Odoc_latex.latex_method_prefix := s), M.latex_method_prefix ;
+ "-latex-module-prefix",
+ Arg.String (fun s -> Odoc_latex.latex_module_prefix := s), M.latex_module_prefix ;
+ "-latex-module-type-prefix",
+ Arg.String (fun s -> Odoc_latex.latex_module_type_prefix := s), M.latex_module_type_prefix ;
+ "-latex-class-prefix",
+ Arg.String (fun s -> Odoc_latex.latex_class_prefix := s), M.latex_class_prefix ;
+ "-latex-class-type-prefix",
+ Arg.String (fun s -> Odoc_latex.latex_class_type_prefix := s), M.latex_class_type_prefix ;
+ "-notoc", Arg.Unit (fun () -> Odoc_global.with_toc := false), M.no_toc ^
+ "\n\n *** texinfo options ***\n";
+
+(* texi only options *)
+ "-noindex", Arg.Clear Odoc_global.with_index, M.no_index ;
+ "-esc8", Arg.Set Odoc_texi.esc_8bits, M.esc_8bits ;
+ "-info-section", Arg.String ((:=) Odoc_texi.info_section), M.info_section ;
+ "-info-entry", Arg.String (fun s -> Odoc_texi.info_entry := !Odoc_texi.info_entry @ [ s ]),
+ M.info_entry ^
+ "\n\n *** dot options ***\n";
+
+(* dot only options *)
+ "-dot-colors", Arg.String (fun s -> Odoc_dot.dot_colors := Str.split (Str.regexp_string ",") s), M.dot_colors ;
+ "-dot-include-all", Arg.Set Odoc_dot.dot_include_all, M.dot_include_all ;
+ "-dot-types", Arg.Set Odoc_dot.dot_types, M.dot_types ;
+ "-dot-reduce", Arg.Set Odoc_dot.dot_reduce, M.dot_reduce^
+ "\n\n *** man pages options ***\n";
+
+(* man only options *)
+ "-man-mini", Arg.Set Odoc_man.man_mini, M.man_mini ;
+ "-man-suffix", Arg.String (fun s -> Odoc_man.man_suffix := s), M.man_suffix ;
+ "-man-section", Arg.String (fun s -> Odoc_man.man_section := s), M.man_section ;
+
+]
+
+let add_option o =
+ let (s,_,_) = o in
+ let rec iter = function
+ [] -> [o]
+ | (s2,f,m) :: q ->
+ if s = s2 then
+ o :: q
+ else
+ (s2,f,m) :: (iter q)
+ in
+ options := iter !options
+
+let parse () =
+ let anonymous f =
+ let sf =
+ if Filename.check_suffix f "ml" then
+ Odoc_global.Impl_file f
+ else
+ if Filename.check_suffix f "mli" then
+ Odoc_global.Intf_file f
+ else
+ if Filename.check_suffix f "txt" then
+ Odoc_global.Text_file f
+ else
+ failwith (Odoc_messages.unknown_extension f)
+ in
+ Odoc_global.files := !Odoc_global.files @ [sf]
+ in
+ let _ = Arg.parse !options
+ anonymous
+ (M.usage^M.options_are)
+ in
+ (* we sort the hidden modules by name, to be sure that for example,
+ A.B is before A, so we will match against A.B before A in
+ Odoc_name.hide_modules.*)
+ Odoc_global.hidden_modules :=
+ List.sort (fun a -> fun b -> - (compare a b)) !Odoc_global.hidden_modules
diff --git a/ocaml-binary-annot/ocamldoc/odoc_args.mli b/ocaml-binary-annot/ocamldoc/odoc_args.mli
new file mode 100644
index 0000000000..2f190ef756
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_args.mli
@@ -0,0 +1,27 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Analysis of the command line arguments. *)
+
+(** The current module defining the generator to use. *)
+val current_generator : Odoc_gen.generator option ref
+
+(** To set the documentation generator. *)
+val set_generator : Odoc_gen.generator -> unit
+
+(** Add an option specification. *)
+val add_option : string * Arg.spec * string -> unit
+
+(** Parse the args.
+ [byte] indicate if we are in bytecode mode (default is [true]).*)
+val parse : unit -> unit
diff --git a/ocaml-binary-annot/ocamldoc/odoc_ast.ml b/ocaml-binary-annot/ocamldoc/odoc_ast.ml
new file mode 100644
index 0000000000..c497794184
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_ast.ml
@@ -0,0 +1,1738 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Analysis of implementation files. *)
+open Misc
+open Asttypes
+open Types
+open Typedtree
+
+let print_DEBUG3 s = print_string s ; print_newline ();;
+let print_DEBUG s = print_string s ; print_newline ();;
+
+type typedtree = (Typedtree.structure * Typedtree.module_coercion)
+
+module Name = Odoc_name
+open Odoc_parameter
+open Odoc_value
+open Odoc_type
+open Odoc_exception
+open Odoc_class
+open Odoc_module
+open Odoc_types
+
+(** This variable contains the regular expression representing a blank.*)
+let blank = "[ \010\013\009\012']"
+
+(** This variable contains the regular expression representing a blank but not a '\n'.*)
+let simple_blank = "[ \013\009\012]"
+
+(** This module is used to search for structure items by name in a Typedtree.structure.
+ One function creates two hash tables, which can then be used to search for elements.
+ Class elements do not use tables.
+*)
+module Typedtree_search =
+ struct
+ type ele =
+ | M of string
+ | MT of string
+ | T of string
+ | C of string
+ | CT of string
+ | E of string
+ | ER of string
+ | P of string
+ | IM of string
+
+ type tab = (ele, Typedtree.structure_item) Hashtbl.t
+ type tab_values = (Odoc_module.Name.t, Typedtree.pattern * Typedtree.expression) Hashtbl.t
+
+ let iter_val_pattern = function
+ | Typedtree.Tpat_any -> None
+ | Typedtree.Tpat_var name -> Some (Name.from_ident name)
+ | Typedtree.Tpat_tuple _ -> None (* A VOIR quand on traitera les tuples *)
+ | _ -> None
+
+ let add_to_hashes table table_values tt =
+ match tt with
+ | Typedtree.Tstr_module (ident, _) ->
+ Hashtbl.add table (M (Name.from_ident ident)) tt
+ | Typedtree.Tstr_recmodule mods ->
+ List.iter
+ (fun (ident,mod_expr) ->
+ Hashtbl.add table (M (Name.from_ident ident))
+ (Typedtree.Tstr_module (ident,mod_expr))
+ )
+ mods
+ | Typedtree.Tstr_modtype (ident, _) ->
+ Hashtbl.add table (MT (Name.from_ident ident)) tt
+ | Typedtree.Tstr_exception (ident, _) ->
+ Hashtbl.add table (E (Name.from_ident ident)) tt
+ | Typedtree.Tstr_exn_rebind (ident, _) ->
+ Hashtbl.add table (ER (Name.from_ident ident)) tt
+ | Typedtree.Tstr_type ident_type_decl_list ->
+ List.iter
+ (fun (id, e) ->
+ Hashtbl.add table (T (Name.from_ident id))
+ (Typedtree.Tstr_type [(id,e)]))
+ ident_type_decl_list
+ | Typedtree.Tstr_class info_list ->
+ List.iter
+ (fun ((id,_,_,_,_) as ci) ->
+ Hashtbl.add table (C (Name.from_ident id))
+ (Typedtree.Tstr_class [ci]))
+ info_list
+ | Typedtree.Tstr_cltype info_list ->
+ List.iter
+ (fun ((id,_) as ci) ->
+ Hashtbl.add table
+ (CT (Name.from_ident id))
+ (Typedtree.Tstr_cltype [ci]))
+ info_list
+ | Typedtree.Tstr_value (_, pat_exp_list) ->
+ List.iter
+ (fun (pat,exp) ->
+ match iter_val_pattern pat.Typedtree.pat_desc with
+ None -> ()
+ | Some n -> Hashtbl.add table_values n (pat,exp)
+ )
+ pat_exp_list
+ | Typedtree.Tstr_primitive (ident, _) ->
+ Hashtbl.add table (P (Name.from_ident ident)) tt
+ | Typedtree.Tstr_open _ -> ()
+ | Typedtree.Tstr_include _ -> ()
+ | Typedtree.Tstr_eval _ -> ()
+
+ let tables typedtree =
+ let t = Hashtbl.create 13 in
+ let t_values = Hashtbl.create 13 in
+ List.iter (add_to_hashes t t_values) typedtree;
+ (t, t_values)
+
+ let search_module table name =
+ match Hashtbl.find table (M name) with
+ (Typedtree.Tstr_module (_, module_expr)) -> module_expr
+ | _ -> assert false
+
+ let search_module_type table name =
+ match Hashtbl.find table (MT name) with
+ | (Typedtree.Tstr_modtype (_, module_type)) -> module_type
+ | _ -> assert false
+
+ let search_exception table name =
+ match Hashtbl.find table (E name) with
+ | (Typedtree.Tstr_exception (_, excep_decl)) -> excep_decl
+ | _ -> assert false
+
+ let search_exception_rebind table name =
+ match Hashtbl.find table (ER name) with
+ | (Typedtree.Tstr_exn_rebind (_, p)) -> p
+ | _ -> assert false
+
+ let search_type_declaration table name =
+ match Hashtbl.find table (T name) with
+ | (Typedtree.Tstr_type [(_,decl)]) -> decl
+ | _ -> assert false
+
+ let search_class_exp table name =
+ match Hashtbl.find table (C name) with
+ | (Typedtree.Tstr_class [(_,_,_,ce,_)]) ->
+ (
+ try
+ let type_decl = search_type_declaration table name in
+ (ce, type_decl.Types.type_params)
+ with
+ Not_found ->
+ (ce, [])
+ )
+ | _ -> assert false
+
+ let search_class_type_declaration table name =
+ match Hashtbl.find table (CT name) with
+ | (Typedtree.Tstr_cltype [(_,cltype_decl)]) -> cltype_decl
+ | _ -> assert false
+
+ let search_value table name = Hashtbl.find table name
+
+ let search_primitive table name =
+ match Hashtbl.find table (P name) with
+ Tstr_primitive (ident, val_desc) -> val_desc.Types.val_type
+ | _ -> assert false
+
+ let get_nth_inherit_class_expr cls n =
+ let rec iter cpt = function
+ | [] ->
+ raise Not_found
+ | Typedtree.Cf_inher (clexp, _, _) :: q ->
+ if n = cpt then clexp else iter (cpt+1) q
+ | _ :: q ->
+ iter cpt q
+ in
+ iter 0 cls.Typedtree.cl_field
+
+ let search_attribute_type cls name =
+ let rec iter = function
+ | [] ->
+ raise Not_found
+ | Typedtree.Cf_val (_, ident, Some exp, _) :: q
+ when Name.from_ident ident = name ->
+ exp.Typedtree.exp_type
+ | _ :: q ->
+ iter q
+ in
+ iter cls.Typedtree.cl_field
+
+ let class_sig_of_cltype_decl =
+ let rec iter = function
+ Types.Tcty_constr (_, _, cty) -> iter cty
+ | Types.Tcty_signature s -> s
+ | Types.Tcty_fun (_,_, cty) -> iter cty
+ in
+ fun ct_decl -> iter ct_decl.Types.clty_type
+
+ let search_virtual_attribute_type table ctname name =
+ let ct_decl = search_class_type_declaration table ctname in
+ let cls_sig = class_sig_of_cltype_decl ct_decl in
+ let (_,_,texp) = Types.Vars.find name cls_sig.cty_vars in
+ texp
+
+ let search_method_expression cls name =
+ let rec iter = function
+ | [] ->
+ raise Not_found
+ | Typedtree.Cf_meth (label, exp) :: q when label = name ->
+ exp
+ | _ :: q ->
+ iter q
+ in
+ iter cls.Typedtree.cl_field
+ end
+
+module Analyser =
+ functor (My_ir : Odoc_sig.Info_retriever) ->
+
+ struct
+ module Sig = Odoc_sig.Analyser (My_ir)
+
+ (** This variable is used to load a file as a string and retrieve characters from it.*)
+ let file = Sig.file
+
+ (** The name of the analysed file. *)
+ let file_name = Sig.file_name
+
+ (** This function takes two indexes (start and end) and return the string
+ corresponding to the indexes in the file global variable. The function
+ prepare_file must have been called to fill the file global variable.*)
+ let get_string_of_file = Sig.get_string_of_file
+
+ (** This function loads the given file in the file global variable.
+ and sets file_name.*)
+ let prepare_file = Sig.prepare_file
+
+ (** The function used to get the comments in a class. *)
+ let get_comments_in_class = Sig.get_comments_in_class
+
+ (** The function used to get the comments in a module. *)
+ let get_comments_in_module = Sig.get_comments_in_module
+
+ (** This function takes a parameter pattern and builds the
+ corresponding [parameter] structure. The f_desc function
+ is used to retrieve a parameter description, if any, from
+ a parameter name.
+ *)
+ let tt_param_info_from_pattern env f_desc pat =
+ let rec iter_pattern pat =
+ match pat.pat_desc with
+ Typedtree.Tpat_var ident ->
+ let name = Name.from_ident ident in
+ Simple_name { sn_name = name ;
+ sn_text = f_desc name ;
+ sn_type = Odoc_env.subst_type env pat.pat_type
+ }
+
+ | Typedtree.Tpat_alias (pat, _) ->
+ iter_pattern pat
+
+ | Typedtree.Tpat_tuple patlist ->
+ Tuple
+ (List.map iter_pattern patlist,
+ Odoc_env.subst_type env pat.pat_type)
+
+ | Typedtree.Tpat_construct (cons_desc, _) when
+ (* we give a name to the parameter only if it unit *)
+ (match cons_desc.cstr_res.desc with
+ Tconstr (p, _, _) ->
+ Path.same p Predef.path_unit
+ | _ ->
+ false)
+ ->
+ (* a () argument, it never has description *)
+ Simple_name { sn_name = "()" ;
+ sn_text = None ;
+ sn_type = Odoc_env.subst_type env pat.pat_type
+ }
+
+ | _ ->
+ (* implicit pattern matching -> anonymous parameter *)
+ Simple_name { sn_name = "()" ;
+ sn_text = None ;
+ sn_type = Odoc_env.subst_type env pat.pat_type
+ }
+ in
+ iter_pattern pat
+
+ (** Analysis of the parameter of a function. Return a list of t_parameter created from
+ the (pattern, expression) structures encountered. *)
+ let rec tt_analyse_function_parameters env current_comment_opt pat_exp_list =
+ match pat_exp_list with
+ [] ->
+ (* This case means we have a 'function' without pattern, that's impossible *)
+ raise (Failure "tt_analyse_function_parameters: 'function' without pattern")
+
+ | (pattern_param, exp) :: second_ele :: q ->
+ (* implicit pattern matching -> anonymous parameter and no more parameter *)
+ (* A VOIR : le label ? *)
+ let parameter = Odoc_parameter.Tuple ([], Odoc_env.subst_type env pattern_param.pat_type) in
+ [ parameter ]
+
+ | (pattern_param, func_body) :: [] ->
+ let parameter =
+ tt_param_info_from_pattern
+ env
+ (Odoc_parameter.desc_from_info_opt current_comment_opt)
+ pattern_param
+
+ in
+ (* For optional parameters with a default value, a special treatment is required *)
+ (* we look if the name of the parameter we just add is "*opt*", which means
+ that there is a let param_name = ... in ... just right now *)
+ let (p, next_exp) =
+ match parameter with
+ Simple_name { sn_name = "*opt*" } ->
+ (
+ (
+ match func_body.exp_desc with
+ Typedtree.Texp_let (_, ({pat_desc = Typedtree.Tpat_var id } , exp) :: _, func_body2) ->
+ let name = Name.from_ident id in
+ let new_param = Simple_name
+ { sn_name = name ;
+ sn_text = Odoc_parameter.desc_from_info_opt current_comment_opt name ;
+ sn_type = Odoc_env.subst_type env exp.exp_type
+ }
+ in
+ (new_param, func_body2)
+ | _ ->
+ print_DEBUG3 "Pas le bon filtre pour le parametre optionnel avec valeur par defaut.";
+ (parameter, func_body)
+ )
+ )
+ | _ ->
+ (parameter, func_body)
+ in
+ (* continue if the body is still a function *)
+ match next_exp.exp_desc with
+ Texp_function (pat_exp_list, _) ->
+ p :: (tt_analyse_function_parameters env current_comment_opt pat_exp_list)
+ | _ ->
+ (* something else ; no more parameter *)
+ [ p ]
+
+ (** Analysis of a Tstr_value from the typedtree. Create and return a list of [t_value].
+ @raise Failure if an error occurs.*)
+ let tt_analyse_value env current_module_name comment_opt loc pat_exp rec_flag =
+ let (pat, exp) = pat_exp in
+ match (pat.pat_desc, exp.exp_desc) with
+ (Typedtree.Tpat_var ident, Typedtree.Texp_function (pat_exp_list2, partial)) ->
+ (* a new function is defined *)
+ let name_pre = Name.from_ident ident in
+ let name = Name.parens_if_infix name_pre in
+ let complete_name = Name.concat current_module_name name in
+ (* create the value *)
+ let new_value = {
+ val_name = complete_name ;
+ val_info = comment_opt ;
+ val_type = Odoc_env.subst_type env pat.Typedtree.pat_type ;
+ val_recursive = rec_flag = Asttypes.Recursive ;
+ val_parameters = tt_analyse_function_parameters env comment_opt pat_exp_list2 ;
+ val_code = Some (get_string_of_file loc.Location.loc_start.Lexing.pos_cnum loc.Location.loc_end.Lexing.pos_cnum) ;
+ val_loc = { loc_impl = Some (!file_name, loc.Location.loc_start.Lexing.pos_cnum) ; loc_inter = None } ;
+ }
+ in
+ [ new_value ]
+
+ | (Typedtree.Tpat_var ident, _) ->
+ (* a new value is defined *)
+ let name_pre = Name.from_ident ident in
+ let name = Name.parens_if_infix name_pre in
+ let complete_name = Name.concat current_module_name name in
+ let new_value = {
+ val_name = complete_name ;
+ val_info = comment_opt ;
+ val_type = Odoc_env.subst_type env pat.Typedtree.pat_type ;
+ val_recursive = rec_flag = Asttypes.Recursive ;
+ val_parameters = [] ;
+ val_code = Some (get_string_of_file loc.Location.loc_start.Lexing.pos_cnum loc.Location.loc_end.Lexing.pos_cnum) ;
+ val_loc = { loc_impl = Some (!file_name, loc.Location.loc_start.Lexing.pos_cnum) ; loc_inter = None } ;
+ }
+ in
+ [ new_value ]
+
+ | (Typedtree.Tpat_tuple lpat, _) ->
+ (* new identifiers are defined *)
+ (* A VOIR : by now we don't accept to have global variables defined in tuples *)
+ []
+
+ | _ ->
+ (* something else, we don't care ? A VOIR *)
+ []
+
+ (** This function takes a Typedtree.class_expr and returns a string which can stand for the class name.
+ The name can be "object ... end" if the class expression is not an ident or a class constraint or a class apply. *)
+ let rec tt_name_of_class_expr clexp =
+(*
+ (
+ match clexp.Typedtree.cl_desc with
+ Tclass_ident _ -> prerr_endline "Tclass_ident"
+ | Tclass_structure _ -> prerr_endline "Tclass_structure"
+ | Tclass_fun _ -> prerr_endline "Tclass_fun"
+ | Tclass_apply _ -> prerr_endline "Tclass_apply"
+ | Tclass_let _ -> prerr_endline "Tclass_let"
+ | Tclass_constraint _ -> prerr_endline "Tclass_constraint"
+ );
+*)
+ match clexp.Typedtree.cl_desc with
+ Typedtree.Tclass_ident p -> Name.from_path p
+ | Typedtree.Tclass_constraint (class_expr, _, _, _)
+ | Typedtree.Tclass_apply (class_expr, _) -> tt_name_of_class_expr class_expr
+(*
+ | Typedtree.Tclass_fun (_, _, class_expr, _) -> tt_name_of_class_expr class_expr
+ | Typedtree.Tclass_let (_,_,_, class_expr) -> tt_name_of_class_expr class_expr
+*)
+ | _ -> Odoc_messages.object_end
+
+ (** Analysis of a method expression to get the method parameters.
+ @param first indicates if we're analysing the method for
+ the first time ; in that case we must not keep the first parameter,
+ which is "self-*", the object itself.
+ *)
+ let rec tt_analyse_method_expression env current_method_name comment_opt ?(first=true) exp =
+ match exp.Typedtree.exp_desc with
+ Typedtree.Texp_function (pat_exp_list, _) ->
+ (
+ match pat_exp_list with
+ [] ->
+ (* it is not a function since there are no parameters *)
+ (* we can't get here normally *)
+ raise (Failure (Odoc_messages.bad_tree^" "^(Odoc_messages.method_without_param current_method_name)))
+ | l ->
+ match l with
+ [] ->
+ (* cas impossible, on l'a filtré avant *)
+ assert false
+ | (pattern_param, exp) :: second_ele :: q ->
+ (* implicit pattern matching -> anonymous parameter *)
+ (* Note : We can't match this pattern if it is the first call to the function. *)
+ let new_param = Simple_name
+ { sn_name = "??" ; sn_text = None;
+ sn_type = Odoc_env.subst_type env pattern_param.Typedtree.pat_type }
+ in
+ [ new_param ]
+
+ | (pattern_param, body) :: [] ->
+ (* if this is the first call to the function, this is the first parameter and we skip it *)
+ if not first then
+ (
+ let parameter =
+ tt_param_info_from_pattern
+ env
+ (Odoc_parameter.desc_from_info_opt comment_opt)
+ pattern_param
+ in
+ (* For optional parameters with a default value, a special treatment is required. *)
+ (* We look if the name of the parameter we just add is "*opt*", which means
+ that there is a let param_name = ... in ... just right now. *)
+ let (current_param, next_exp) =
+ match parameter with
+ Simple_name { sn_name = "*opt*"} ->
+ (
+ (
+ match body.exp_desc with
+ Typedtree.Texp_let (_, ({pat_desc = Typedtree.Tpat_var id } , exp) :: _, body2) ->
+ let name = Name.from_ident id in
+ let new_param = Simple_name
+ { sn_name = name ;
+ sn_text = Odoc_parameter.desc_from_info_opt comment_opt name ;
+ sn_type = Odoc_env.subst_type env exp.Typedtree.exp_type ;
+ }
+ in
+ (new_param, body2)
+ | _ ->
+ print_DEBUG3 "Pas le bon filtre pour le parametre optionnel avec valeur par defaut.";
+ (parameter, body)
+ )
+ )
+ | _ ->
+ (* no *opt* parameter, we add the parameter then continue *)
+ (parameter, body)
+ in
+ current_param :: (tt_analyse_method_expression env current_method_name comment_opt ~first: false next_exp)
+ )
+ else
+ tt_analyse_method_expression env current_method_name comment_opt ~first: false body
+ )
+ | _ ->
+ (* no more parameter *)
+ []
+
+ (** Analysis of a [Parsetree.class_struture] and a [Typedtree.class_structure] to get a couple
+ (inherited classes, class elements). *)
+ let analyse_class_structure env current_class_name tt_class_sig last_pos pos_limit p_cls tt_cls table =
+ let rec iter acc_inher acc_fields last_pos = function
+ | [] ->
+ let s = get_string_of_file last_pos pos_limit in
+ let (_, ele_coms) = My_ir.all_special !file_name s in
+ let ele_comments =
+ List.fold_left
+ (fun acc -> fun sc ->
+ match sc.Odoc_types.i_desc with
+ None ->
+ acc
+ | Some t ->
+ acc @ [Class_comment t])
+ []
+ ele_coms
+ in
+ (acc_inher, acc_fields @ ele_comments)
+
+ | (Parsetree.Pcf_inher (_, p_clexp, _)) :: q ->
+ let tt_clexp =
+ let n = List.length acc_inher in
+ try Typedtree_search.get_nth_inherit_class_expr tt_cls n
+ with Not_found ->
+ raise (Failure (
+ Odoc_messages.inherit_classexp_not_found_in_typedtree n))
+ in
+ let (info_opt, ele_comments) =
+ get_comments_in_class last_pos
+ p_clexp.Parsetree.pcl_loc.Location.loc_start.Lexing.pos_cnum
+ in
+ let text_opt =
+ match info_opt with None -> None
+ | Some i -> i.Odoc_types.i_desc in
+ let name = tt_name_of_class_expr tt_clexp in
+ let inher =
+ {
+ ic_name = Odoc_env.full_class_or_class_type_name env name ;
+ ic_class = None ;
+ ic_text = text_opt ;
+ }
+ in
+ iter (acc_inher @ [ inher ]) (acc_fields @ ele_comments)
+ p_clexp.Parsetree.pcl_loc.Location.loc_end.Lexing.pos_cnum
+ q
+
+ | ((Parsetree.Pcf_val (label, mutable_flag, _, _, loc) |
+ Parsetree.Pcf_valvirt (label, mutable_flag, _, loc) ) as x) :: q ->
+ let virt = match x with Parsetree.Pcf_val _ -> false | _ -> true in
+ let complete_name = Name.concat current_class_name label in
+ let (info_opt, ele_comments) = get_comments_in_class last_pos loc.Location.loc_start.Lexing.pos_cnum in
+ let type_exp =
+ try
+ if virt then
+ Typedtree_search.search_virtual_attribute_type table
+ (Name.simple current_class_name) label
+ else
+ Typedtree_search.search_attribute_type tt_cls label
+ with Not_found ->
+ raise (Failure (Odoc_messages.attribute_not_found_in_typedtree complete_name))
+ in
+ let att =
+ {
+ att_value = { val_name = complete_name ;
+ val_info = info_opt ;
+ val_type = Odoc_env.subst_type env type_exp ;
+ val_recursive = false ;
+ val_parameters = [] ;
+ val_code = Some (get_string_of_file loc.Location.loc_start.Lexing.pos_cnum loc.Location.loc_end.Lexing.pos_cnum) ;
+ val_loc = { loc_impl = Some (!file_name, loc.Location.loc_start.Lexing.pos_cnum) ; loc_inter = None } ;
+ } ;
+ att_mutable = mutable_flag = Asttypes.Mutable ;
+ att_virtual = virt ;
+ }
+ in
+ iter acc_inher (acc_fields @ ele_comments @ [ Class_attribute att ]) loc.Location.loc_end.Lexing.pos_cnum q
+
+ | (Parsetree.Pcf_virt (label, private_flag, _, loc)) :: q ->
+ let complete_name = Name.concat current_class_name label in
+ let (info_opt, ele_comments) = get_comments_in_class last_pos loc.Location.loc_start.Lexing.pos_cnum in
+ let met_type =
+ try Odoc_sig.Signature_search.search_method_type label tt_class_sig
+ with Not_found -> raise (Failure (Odoc_messages.method_type_not_found current_class_name label))
+ in
+ let real_type =
+ match met_type.Types.desc with
+ Tarrow (_, _, t, _) ->
+ t
+ | _ ->
+ (* ?!? : not an arrow type ! return the original type *)
+ met_type
+ in
+ let met =
+ {
+ met_value = { val_name = complete_name ;
+ val_info = info_opt ;
+ val_type = Odoc_env.subst_type env real_type ;
+ val_recursive = false ;
+ val_parameters = [] ;
+ val_code = Some (get_string_of_file loc.Location.loc_start.Lexing.pos_cnum loc.Location.loc_end.Lexing.pos_cnum) ;
+ val_loc = { loc_impl = Some (!file_name, loc.Location.loc_start.Lexing.pos_cnum) ; loc_inter = None } ;
+ } ;
+ met_private = private_flag = Asttypes.Private ;
+ met_virtual = true ;
+ }
+ in
+ (* update the parameter description *)
+ Odoc_value.update_value_parameters_text met.met_value;
+
+ iter acc_inher (acc_fields @ ele_comments @ [ Class_method met ]) loc.Location.loc_end.Lexing.pos_cnum q
+
+ | (Parsetree.Pcf_meth (label, private_flag, _, _, loc)) :: q ->
+ let complete_name = Name.concat current_class_name label in
+ let (info_opt, ele_comments) = get_comments_in_class last_pos loc.Location.loc_start.Lexing.pos_cnum in
+ let exp =
+ try Typedtree_search.search_method_expression tt_cls label
+ with Not_found -> raise (Failure (Odoc_messages.method_not_found_in_typedtree complete_name))
+ in
+ let real_type =
+ match exp.exp_type.desc with
+ Tarrow (_, _, t,_) ->
+ t
+ | _ ->
+ (* ?!? : not an arrow type ! return the original type *)
+ exp.Typedtree.exp_type
+ in
+ let met =
+ {
+ met_value = { val_name = complete_name ;
+ val_info = info_opt ;
+ val_type = Odoc_env.subst_type env real_type ;
+ val_recursive = false ;
+ val_parameters = tt_analyse_method_expression env complete_name info_opt exp ;
+ val_code = Some (get_string_of_file loc.Location.loc_start.Lexing.pos_cnum loc.Location.loc_end.Lexing.pos_cnum) ;
+ val_loc = { loc_impl = Some (!file_name, loc.Location.loc_start.Lexing.pos_cnum) ; loc_inter = None } ;
+ } ;
+ met_private = private_flag = Asttypes.Private ;
+ met_virtual = false ;
+ }
+ in
+ (* update the parameter description *)
+ Odoc_value.update_value_parameters_text met.met_value;
+
+ iter acc_inher (acc_fields @ ele_comments @ [ Class_method met ]) loc.Location.loc_end.Lexing.pos_cnum q
+
+ | Parsetree.Pcf_cstr (_, _, loc) :: q ->
+ (* don't give a $*%@ ! *)
+ iter acc_inher acc_fields loc.Location.loc_end.Lexing.pos_cnum q
+
+ | Parsetree.Pcf_let (_, _, loc) :: q ->
+ (* don't give a $*%@ ! *)
+ iter acc_inher acc_fields loc.Location.loc_end.Lexing.pos_cnum q
+
+ | (Parsetree.Pcf_init exp) :: q ->
+ iter acc_inher acc_fields exp.Parsetree.pexp_loc.Location.loc_end.Lexing.pos_cnum q
+ in
+ iter [] [] last_pos (snd p_cls)
+
+ (** Analysis of a [Parsetree.class_expr] and a [Typedtree.class_expr] to get a a couple (class parameters, class kind). *)
+ let rec analyse_class_kind env current_class_name comment_opt last_pos p_class_expr tt_class_exp table =
+ match (p_class_expr.Parsetree.pcl_desc, tt_class_exp.Typedtree.cl_desc) with
+ (Parsetree.Pcl_constr (lid, _), tt_class_exp_desc ) ->
+ let name =
+ match tt_class_exp_desc with
+ Typedtree.Tclass_ident p -> Name.from_path p
+ | _ ->
+ (* we try to get the name from the environment. *)
+ (* A VOIR : dommage qu'on n'ait pas un Tclass_ident :-( même quand on a class tutu = toto *)
+ Name.from_longident lid
+ in
+ (* On n'a pas ici les paramètres de type sous forme de Types.type_expr,
+ par contre on peut les trouver dans le class_type *)
+ let params =
+ match tt_class_exp.Typedtree.cl_type with
+ Types.Tcty_constr (p2, type_exp_list, cltyp) ->
+ (* cltyp is the class type for [type_exp_list] p *)
+ type_exp_list
+ | _ ->
+ []
+ in
+ ([],
+ Class_constr
+ {
+ cco_name = Odoc_env.full_class_name env name ;
+ cco_class = None ;
+ cco_type_parameters = List.map (Odoc_env.subst_type env) params ;
+ } )
+
+ | (Parsetree.Pcl_structure p_class_structure, Typedtree.Tclass_structure tt_class_structure) ->
+ (* we need the class signature to get the type of methods in analyse_class_structure *)
+ let tt_class_sig =
+ match tt_class_exp.Typedtree.cl_type with
+ Types.Tcty_signature class_sig -> class_sig
+ | _ -> raise (Failure "analyse_class_kind: no class signature for a class structure.")
+ in
+ let (inherited_classes, class_elements) = analyse_class_structure
+ env
+ current_class_name
+ tt_class_sig
+ last_pos
+ p_class_expr.Parsetree.pcl_loc.Location.loc_end.Lexing.pos_cnum
+ p_class_structure
+ tt_class_structure
+ table
+ in
+ ([],
+ Class_structure (inherited_classes, class_elements) )
+
+ | (Parsetree.Pcl_fun (label, expression_opt, pattern, p_class_expr2),
+ Typedtree.Tclass_fun (pat, ident_exp_list, tt_class_expr2, partial)) ->
+ (* we check that this is not an optional parameter with
+ a default value. In this case, we look for the good parameter pattern *)
+ let (parameter, next_tt_class_exp) =
+ match pat.Typedtree.pat_desc with
+ Typedtree.Tpat_var ident when Name.from_ident ident = "*opt*" ->
+ (
+ (* there must be a Tclass_let just after *)
+ match tt_class_expr2.Typedtree.cl_desc with
+ Typedtree.Tclass_let (_, ({pat_desc = Typedtree.Tpat_var id } , exp) :: _, _, tt_class_expr3) ->
+ let name = Name.from_ident id in
+ let new_param = Simple_name
+ { sn_name = name ;
+ sn_text = Odoc_parameter.desc_from_info_opt comment_opt name ;
+ sn_type = Odoc_env.subst_type env exp.exp_type
+ }
+ in
+ (new_param, tt_class_expr3)
+ | _ ->
+ (* strange case *)
+ (* we create the parameter and add it to the class *)
+ raise (Failure "analyse_class_kind: strange case")
+ )
+ | _ ->
+ (* no optional parameter with default value, we create the parameter *)
+ let new_param =
+ tt_param_info_from_pattern
+ env
+ (Odoc_parameter.desc_from_info_opt comment_opt)
+ pat
+ in
+ (new_param, tt_class_expr2)
+ in
+ let (params, k) = analyse_class_kind
+ env current_class_name comment_opt last_pos p_class_expr2
+ next_tt_class_exp table
+ in
+ (parameter :: params, k)
+
+ | (Parsetree.Pcl_apply (p_class_expr2, _), Tclass_apply (tt_class_expr2, exp_opt_optional_list)) ->
+ let applied_name =
+ (* we want an ident, or else the class applied will appear in the form object ... end,
+ because if the class applied has no name, the code is kinda ugly, isn't it ? *)
+ match tt_class_expr2.Typedtree.cl_desc with
+ Typedtree.Tclass_ident p -> Name.from_path p (* A VOIR : obtenir le nom complet *)
+ | _ ->
+ (* A VOIR : dommage qu'on n'ait pas un Tclass_ident :-( même quand on a class tutu = toto *)
+ match p_class_expr2.Parsetree.pcl_desc with
+ Parsetree.Pcl_constr (lid, _) ->
+ (* we try to get the name from the environment. *)
+ Name.from_longident lid
+ | _ ->
+ Odoc_messages.object_end
+ in
+ let param_exps = List.fold_left
+ (fun acc -> fun (exp_opt, _) ->
+ match exp_opt with
+ None -> acc
+ | Some e -> acc @ [e])
+ []
+ exp_opt_optional_list
+ in
+ let param_types = List.map (fun e -> e.Typedtree.exp_type) param_exps in
+ let params_code =
+ List.map
+ (fun e -> get_string_of_file
+ e.exp_loc.Location.loc_start.Lexing.pos_cnum
+ e.exp_loc.Location.loc_end.Lexing.pos_cnum)
+ param_exps
+ in
+ ([],
+ Class_apply
+ { capp_name = Odoc_env.full_class_name env applied_name ;
+ capp_class = None ;
+ capp_params = param_types ;
+ capp_params_code = params_code ;
+ } )
+
+ | (Parsetree.Pcl_let (_, _, p_class_expr2), Typedtree.Tclass_let (_, _, _, tt_class_expr2)) ->
+ (* we don't care about these lets *)
+ analyse_class_kind
+ env current_class_name comment_opt last_pos p_class_expr2
+ tt_class_expr2 table
+
+ | (Parsetree.Pcl_constraint (p_class_expr2, p_class_type2),
+ Typedtree.Tclass_constraint (tt_class_expr2, _, _, _)) ->
+ let (l, class_kind) = analyse_class_kind
+ env current_class_name comment_opt last_pos p_class_expr2
+ tt_class_expr2 table
+ in
+ (* A VOIR : analyse du class type ? on n'a pas toutes les infos. cf. Odoc_sig.analyse_class_type_kind *)
+ let class_type_kind =
+ (*Sig.analyse_class_type_kind
+ env
+ ""
+ p_class_type2.Parsetree.pcty_loc.Location.loc_start.Lexing.pos_cnum
+ p_class_type2
+ tt_class_expr2.Typedtree.cl_type
+ *)
+ Class_type { cta_name = Odoc_messages.object_end ;
+ cta_class = None ; cta_type_parameters = [] }
+ in
+ (l, Class_constraint (class_kind, class_type_kind))
+
+ | _ ->
+ raise (Failure "analyse_class_kind: Parsetree and typedtree don't match.")
+
+ (** Analysis of a [Parsetree.class_declaration] and a [Typedtree.class_expr] to return a [t_class].*)
+ let analyse_class env current_module_name comment_opt p_class_decl tt_type_params tt_class_exp table =
+ let name = p_class_decl.Parsetree.pci_name in
+ let complete_name = Name.concat current_module_name name in
+ let pos_start = p_class_decl.Parsetree.pci_expr.Parsetree.pcl_loc.Location.loc_start.Lexing.pos_cnum in
+ let type_parameters = tt_type_params in
+ let virt = p_class_decl.Parsetree.pci_virt = Asttypes.Virtual in
+ let cltype = Odoc_env.subst_class_type env tt_class_exp.Typedtree.cl_type in
+ let (parameters, kind) = analyse_class_kind
+ env
+ complete_name
+ comment_opt
+ pos_start
+ p_class_decl.Parsetree.pci_expr
+ tt_class_exp
+ table
+ in
+ let cl =
+ {
+ cl_name = complete_name ;
+ cl_info = comment_opt ;
+ cl_type = cltype ;
+ cl_virtual = virt ;
+ cl_type_parameters = type_parameters ;
+ cl_kind = kind ;
+ cl_parameters = parameters ;
+ cl_loc = { loc_impl = Some (!file_name, pos_start) ; loc_inter = None } ;
+ }
+ in
+ cl
+
+ (** Get a name from a module expression, or "struct ... end" if the module expression
+ is not an ident of a constraint on an ident. *)
+ let rec tt_name_from_module_expr mod_expr =
+ match mod_expr.Typedtree.mod_desc with
+ Typedtree.Tmod_ident p -> Name.from_path p
+ | Typedtree.Tmod_constraint (m_exp, _, _) -> tt_name_from_module_expr m_exp
+ | Typedtree.Tmod_structure _
+ | Typedtree.Tmod_functor _
+ | Typedtree.Tmod_apply _
+ | Typedtree.Tmod_unpack _ ->
+ Odoc_messages.struct_end
+
+ (** Get the list of included modules in a module structure of a typed tree. *)
+ let tt_get_included_module_list tt_structure =
+ let f acc item =
+ match item with
+ Typedtree.Tstr_include (mod_expr, _) ->
+ acc @ [
+ { (* A VOIR : chercher dans les modules et les module types, avec quel env ? *)
+ im_name = tt_name_from_module_expr mod_expr ;
+ im_module = None ;
+ im_info = None ;
+ }
+ ]
+ | _ ->
+ acc
+ in
+ List.fold_left f [] tt_structure
+
+ (** This function takes a [module element list] of a module and replaces the "dummy" included modules with
+ the ones found in typed tree structure of the module. *)
+ let replace_dummy_included_modules module_elements included_modules =
+ let rec f = function
+ | ([], _) ->
+ []
+ | ((Element_included_module im) :: q, (im_repl :: im_q)) ->
+ (Element_included_module { im_repl with im_info = im.im_info })
+ :: (f (q, im_q))
+ | ((Element_included_module im) :: q, []) ->
+ (Element_included_module im) :: q
+ | (ele :: q, l) ->
+ ele :: (f (q, l))
+ in
+ f (module_elements, included_modules)
+
+ (** This function removes the elements of the module which does not
+ belong to the given module type, if the module type is expanded
+ and the module has a "structure" kind. *)
+ let rec filter_module_with_module_type_constraint m mt =
+ match m.m_kind, mt with
+ Module_struct l, Types.Tmty_signature lsig ->
+ m.m_kind <- Module_struct (filter_module_elements_with_module_type_constraint l lsig);
+ m.m_type <- mt;
+ | _ -> ()
+
+ (** This function removes the elements of the module type which does not
+ belong to the given module type, if the module type is expanded
+ and the module type has a "structure" kind. *)
+ and filter_module_type_with_module_type_constraint mtyp mt =
+ match mtyp.mt_kind, mt with
+ Some Module_type_struct l, Types.Tmty_signature lsig ->
+ mtyp.mt_kind <- Some (Module_type_struct (filter_module_elements_with_module_type_constraint l lsig));
+ mtyp.mt_type <- Some mt;
+ | _ -> ()
+
+ and filter_module_elements_with_module_type_constraint l lsig =
+ let pred ele =
+ let f = match ele with
+ Element_module m ->
+ (function
+ Types.Tsig_module (ident,t,_) ->
+ let n1 = Name.simple m.m_name
+ and n2 = Ident.name ident in
+ (
+ match n1 = n2 with
+ true -> filter_module_with_module_type_constraint m t; true
+ | false -> false
+ )
+ | _ -> false)
+ | Element_module_type mt ->
+ (function
+ Types.Tsig_modtype (ident,Types.Tmodtype_manifest t) ->
+ let n1 = Name.simple mt.mt_name
+ and n2 = Ident.name ident in
+ (
+ match n1 = n2 with
+ true -> filter_module_type_with_module_type_constraint mt t; true
+ | false -> false
+ )
+ | _ -> false)
+ | Element_value v ->
+ (function
+ Types.Tsig_value (ident,_) ->
+ let n1 = Name.simple v.val_name
+ and n2 = Ident.name ident in
+ n1 = n2
+ | _ -> false)
+ | Element_type t ->
+ (function
+ Types.Tsig_type (ident,_,_) ->
+ (* A VOIR: il est possible que le détail du type soit caché *)
+ let n1 = Name.simple t.ty_name
+ and n2 = Ident.name ident in
+ n1 = n2
+ | _ -> false)
+ | Element_exception e ->
+ (function
+ Types.Tsig_exception (ident,_) ->
+ let n1 = Name.simple e.ex_name
+ and n2 = Ident.name ident in
+ n1 = n2
+ | _ -> false)
+ | Element_class c ->
+ (function
+ Types.Tsig_class (ident,_,_) ->
+ let n1 = Name.simple c.cl_name
+ and n2 = Ident.name ident in
+ n1 = n2
+ | _ -> false)
+ | Element_class_type ct ->
+ (function
+ Types.Tsig_cltype (ident,_,_) ->
+ let n1 = Name.simple ct.clt_name
+ and n2 = Ident.name ident in
+ n1 = n2
+ | _ -> false)
+ | Element_module_comment _ -> fun _ -> true
+ | Element_included_module _ -> fun _ -> true
+ in
+ List.exists f lsig
+ in
+ List.filter pred l
+
+ (** Analysis of a parse tree structure with a typed tree, to return module elements.*)
+ let rec analyse_structure env current_module_name last_pos pos_limit parsetree typedtree =
+ print_DEBUG "Odoc_ast:analyse_struture";
+ let (table, table_values) = Typedtree_search.tables typedtree in
+ let rec iter env last_pos = function
+ [] ->
+ let s = get_string_of_file last_pos pos_limit in
+ let (_, ele_coms) = My_ir.all_special !file_name s in
+ let ele_comments =
+ List.fold_left
+ (fun acc -> fun sc ->
+ match sc.Odoc_types.i_desc with
+ None ->
+ acc
+ | Some t ->
+ acc @ [Element_module_comment t])
+ []
+ ele_coms
+ in
+ ele_comments
+ | item :: q ->
+ let (comment_opt, ele_comments) =
+ get_comments_in_module last_pos item.Parsetree.pstr_loc.Location.loc_start.Lexing.pos_cnum
+ in
+ let pos_limit2 =
+ match q with
+ [] -> pos_limit
+ | item2 :: _ -> item2.Parsetree.pstr_loc.Location.loc_start.Lexing.pos_cnum
+ in
+ let (maybe_more, new_env, elements) = analyse_structure_item
+ env
+ current_module_name
+ item.Parsetree.pstr_loc
+ pos_limit2
+ comment_opt
+ item.Parsetree.pstr_desc
+ typedtree
+ table
+ table_values
+ in
+ ele_comments @ elements @ (iter new_env (item.Parsetree.pstr_loc.Location.loc_end.Lexing.pos_cnum + maybe_more) q)
+ in
+ iter env last_pos parsetree
+
+ (** Analysis of a parse tree structure item to obtain a new environment and a list of elements.*)
+ and analyse_structure_item env current_module_name loc pos_limit comment_opt parsetree_item_desc typedtree
+ table table_values =
+ print_DEBUG "Odoc_ast:analyse_struture_item";
+ match parsetree_item_desc with
+ Parsetree.Pstr_eval _ ->
+ (* don't care *)
+ (0, env, [])
+ | Parsetree.Pstr_value (rec_flag, pat_exp_list) ->
+ (* of rec_flag * (pattern * expression) list *)
+ (* For each value, look for the value name, then look in the
+ typedtree for the corresponding information,
+ at last analyse this information to build the value *)
+ let rec iter_pat = function
+ | Parsetree.Ppat_any -> None
+ | Parsetree.Ppat_var name -> Some name
+ | Parsetree.Ppat_tuple _ -> None (* A VOIR quand on traitera les tuples *)
+ | Parsetree.Ppat_constraint (pat, _) -> iter_pat pat.Parsetree.ppat_desc
+ | _ -> None
+ in
+ let rec iter ?(first=false) last_pos acc_env acc p_e_list =
+ match p_e_list with
+ [] ->
+ (acc_env, acc)
+ | (pat, exp) :: q ->
+ let value_name_opt = iter_pat pat.Parsetree.ppat_desc in
+ let new_last_pos = exp.Parsetree.pexp_loc.Location.loc_end.Lexing.pos_cnum in
+ match value_name_opt with
+ None ->
+ iter new_last_pos acc_env acc q
+ | Some name ->
+ try
+ let pat_exp = Typedtree_search.search_value table_values name in
+ let (info_opt, ele_comments) =
+ (* we already have the optional comment for the first value. *)
+ if first then
+ (comment_opt, [])
+ else
+ get_comments_in_module
+ last_pos
+ pat.Parsetree.ppat_loc.Location.loc_start.Lexing.pos_cnum
+ in
+ let l_values = tt_analyse_value
+ env
+ current_module_name
+ info_opt
+ loc
+ pat_exp
+ rec_flag
+ in
+ let new_env = List.fold_left
+ (fun e -> fun v ->
+ Odoc_env.add_value e v.val_name
+ )
+ acc_env
+ l_values
+ in
+ let l_ele = List.map (fun v -> Element_value v) l_values in
+ iter
+ new_last_pos
+ new_env
+ (acc @ ele_comments @ l_ele)
+ q
+ with
+ Not_found ->
+ iter new_last_pos acc_env acc q
+ in
+ let (new_env, l_ele) = iter ~first: true loc.Location.loc_start.Lexing.pos_cnum env [] pat_exp_list in
+ (0, new_env, l_ele)
+
+ | Parsetree.Pstr_primitive (name_pre, val_desc) ->
+ (* of string * value_description *)
+ print_DEBUG ("Parsetree.Pstr_primitive ("^name_pre^", ["^(String.concat ", " val_desc.Parsetree.pval_prim)^"]");
+ let typ = Typedtree_search.search_primitive table name_pre in
+ let name = Name.parens_if_infix name_pre in
+ let complete_name = Name.concat current_module_name name in
+ let new_value = {
+ val_name = complete_name ;
+ val_info = comment_opt ;
+ val_type = Odoc_env.subst_type env typ ;
+ val_recursive = false ;
+ val_parameters = [] ;
+ val_code = Some (get_string_of_file loc.Location.loc_start.Lexing.pos_cnum loc.Location.loc_end.Lexing.pos_cnum) ;
+ val_loc = { loc_impl = Some (!file_name, loc.Location.loc_start.Lexing.pos_cnum) ; loc_inter = None } ;
+ }
+ in
+ let new_env = Odoc_env.add_value env new_value.val_name in
+ (0, new_env, [Element_value new_value])
+
+ | Parsetree.Pstr_type name_typedecl_list ->
+ (* of (string * type_declaration) list *)
+ (* we start by extending the environment *)
+ let new_env =
+ List.fold_left
+ (fun acc_env -> fun (name, _) ->
+ let complete_name = Name.concat current_module_name name in
+ Odoc_env.add_type acc_env complete_name
+ )
+ env
+ name_typedecl_list
+ in
+ let rec f ?(first=false) maybe_more_acc last_pos name_type_decl_list =
+ match name_type_decl_list with
+ [] -> (maybe_more_acc, [])
+ | (name, type_decl) :: q ->
+ let complete_name = Name.concat current_module_name name in
+ let loc_start = type_decl.Parsetree.ptype_loc.Location.loc_start.Lexing.pos_cnum in
+ let loc_end = type_decl.Parsetree.ptype_loc.Location.loc_end.Lexing.pos_cnum in
+ let pos_limit2 =
+ match q with
+ [] -> pos_limit
+ | (_, td) :: _ -> td.Parsetree.ptype_loc.Location.loc_start.Lexing.pos_cnum
+ in
+ let (maybe_more, name_comment_list) =
+ Sig.name_comment_from_type_kind
+ loc_end
+ pos_limit2
+ type_decl.Parsetree.ptype_kind
+ in
+ let tt_type_decl =
+ try Typedtree_search.search_type_declaration table name
+ with Not_found -> raise (Failure (Odoc_messages.type_not_found_in_typedtree complete_name))
+ in
+ let (com_opt, ele_comments) = (* the comment for the first type was already retrieved *)
+ if first then
+ (comment_opt , [])
+ else
+ get_comments_in_module last_pos loc_start
+ in
+ let kind = Sig.get_type_kind
+ new_env name_comment_list
+ tt_type_decl.Types.type_kind
+ in
+ let new_end = loc_end + maybe_more in
+ let t =
+ {
+ ty_name = complete_name ;
+ ty_info = com_opt ;
+ ty_parameters =
+ List.map2
+ (fun p (co,cn,_) ->
+ (Odoc_env.subst_type new_env p,
+ co, cn)
+ )
+ tt_type_decl.Types.type_params
+ tt_type_decl.Types.type_variance ;
+ ty_kind = kind ;
+ ty_private = tt_type_decl.Types.type_private;
+ ty_manifest =
+ (match tt_type_decl.Types.type_manifest with
+ None -> None
+ | Some t -> Some (Odoc_env.subst_type new_env t));
+ ty_loc = { loc_impl = Some (!file_name, loc_start) ; loc_inter = None } ;
+ ty_code =
+ (
+ if !Odoc_global.keep_code then
+ Some (get_string_of_file loc_start new_end)
+ else
+ None
+ ) ;
+ }
+ in
+ let (maybe_more2, info_after_opt) =
+ My_ir.just_after_special
+ !file_name
+ (get_string_of_file new_end pos_limit2)
+ in
+ t.ty_info <- Sig.merge_infos t.ty_info info_after_opt ;
+ let (maybe_more3, eles) = f (maybe_more + maybe_more2) (new_end + maybe_more2) q in
+ (maybe_more3, ele_comments @ ((Element_type t) :: eles))
+ in
+ let (maybe_more, eles) = f ~first: true 0 loc.Location.loc_start.Lexing.pos_cnum name_typedecl_list in
+ (maybe_more, new_env, eles)
+
+ | Parsetree.Pstr_exception (name, excep_decl) ->
+ (* a new exception is defined *)
+ let complete_name = Name.concat current_module_name name in
+ (* we get the exception declaration in the typed tree *)
+ let tt_excep_decl =
+ try Typedtree_search.search_exception table name
+ with Not_found ->
+ raise (Failure (Odoc_messages.exception_not_found_in_typedtree complete_name))
+ in
+ let new_env = Odoc_env.add_exception env complete_name in
+ let loc_start = loc.Location.loc_start.Lexing.pos_cnum in
+ let loc_end = loc.Location.loc_end.Lexing.pos_cnum in
+ let new_ex =
+ {
+ ex_name = complete_name ;
+ ex_info = comment_opt ;
+ ex_args = List.map (Odoc_env.subst_type new_env) tt_excep_decl ;
+ ex_alias = None ;
+ ex_loc = { loc_impl = Some (!file_name, loc.Location.loc_start.Lexing.pos_cnum) ; loc_inter = None } ;
+ ex_code =
+ (
+ if !Odoc_global.keep_code then
+ Some (get_string_of_file loc_start loc_end)
+ else
+ None
+ ) ;
+ }
+ in
+ (0, new_env, [ Element_exception new_ex ])
+
+ | Parsetree.Pstr_exn_rebind (name, _) ->
+ (* a new exception is defined *)
+ let complete_name = Name.concat current_module_name name in
+ (* we get the exception rebind in the typed tree *)
+ let tt_path =
+ try Typedtree_search.search_exception_rebind table name
+ with Not_found ->
+ raise (Failure (Odoc_messages.exception_not_found_in_typedtree complete_name))
+ in
+ let new_env = Odoc_env.add_exception env complete_name in
+ let new_ex =
+ {
+ ex_name = complete_name ;
+ ex_info = comment_opt ;
+ ex_args = [] ;
+ ex_alias = Some { ea_name = (Odoc_env.full_exception_name env (Name.from_path tt_path)) ;
+ ea_ex = None ; } ;
+ ex_loc = { loc_impl = Some (!file_name, loc.Location.loc_start.Lexing.pos_cnum) ; loc_inter = None } ;
+ ex_code = None ;
+ }
+ in
+ (0, new_env, [ Element_exception new_ex ])
+
+ | Parsetree.Pstr_module (name, module_expr) ->
+ (
+ (* of string * module_expr *)
+ try
+ let tt_module_expr = Typedtree_search.search_module table name in
+ let new_module_pre = analyse_module
+ env
+ current_module_name
+ name
+ comment_opt
+ module_expr
+ tt_module_expr
+ in
+ let code =
+ if !Odoc_global.keep_code then
+ let loc = module_expr.Parsetree.pmod_loc in
+ let st = loc.Location.loc_start.Lexing.pos_cnum in
+ let en = loc.Location.loc_end.Lexing.pos_cnum in
+ Some (get_string_of_file st en)
+ else
+ None
+ in
+ let new_module =
+ { new_module_pre with m_code = code }
+ in
+ let new_env = Odoc_env.add_module env new_module.m_name in
+ let new_env2 =
+ match new_module.m_type with
+ (* A VOIR : cela peut-il être Tmty_ident ? dans ce cas, on aurait pas la signature *)
+ Types.Tmty_signature s ->
+ Odoc_env.add_signature new_env new_module.m_name
+ ~rel: (Name.simple new_module.m_name) s
+ | _ ->
+ new_env
+ in
+ (0, new_env2, [ Element_module new_module ])
+ with
+ Not_found ->
+ let complete_name = Name.concat current_module_name name in
+ raise (Failure (Odoc_messages.module_not_found_in_typedtree complete_name))
+ )
+
+ | Parsetree.Pstr_recmodule mods ->
+ (* A VOIR ICI pb: pas de lien avec les module type
+ dans les contraintes sur les modules *)
+ let new_env =
+ List.fold_left
+ (fun acc_env (name, _, mod_exp) ->
+ let complete_name = Name.concat current_module_name name in
+ let e = Odoc_env.add_module acc_env complete_name in
+ let tt_mod_exp =
+ try Typedtree_search.search_module table name
+ with Not_found -> raise (Failure (Odoc_messages.module_not_found_in_typedtree complete_name))
+ in
+ let new_module = analyse_module
+ e
+ current_module_name
+ name
+ None
+ mod_exp
+ tt_mod_exp
+ in
+ match new_module.m_type with
+ Types.Tmty_signature s ->
+ Odoc_env.add_signature e new_module.m_name
+ ~rel: (Name.simple new_module.m_name) s
+ | _ ->
+ e
+ )
+ env
+ mods
+ in
+ let rec f ?(first=false) last_pos name_mod_exp_list =
+ match name_mod_exp_list with
+ [] -> []
+ | (name, _, mod_exp) :: q ->
+ let complete_name = Name.concat current_module_name name in
+ let loc_start = mod_exp.Parsetree.pmod_loc.Location.loc_start.Lexing.pos_cnum in
+ let loc_end = mod_exp.Parsetree.pmod_loc.Location.loc_end.Lexing.pos_cnum in
+ let tt_mod_exp =
+ try Typedtree_search.search_module table name
+ with Not_found -> raise (Failure (Odoc_messages.module_not_found_in_typedtree complete_name))
+ in
+ let (com_opt, ele_comments) = (* the comment for the first type was already retrieved *)
+ if first then
+ (comment_opt, [])
+ else
+ get_comments_in_module last_pos loc_start
+ in
+ let new_module = analyse_module
+ new_env
+ current_module_name
+ name
+ com_opt
+ mod_exp
+ tt_mod_exp
+ in
+ let eles = f loc_end q in
+ ele_comments @ ((Element_module new_module) :: eles)
+ in
+ let eles = f ~first: true loc.Location.loc_start.Lexing.pos_cnum mods in
+ (0, new_env, eles)
+
+ | Parsetree.Pstr_modtype (name, modtype) ->
+ let complete_name = Name.concat current_module_name name in
+ let tt_module_type =
+ try Typedtree_search.search_module_type table name
+ with Not_found ->
+ raise (Failure (Odoc_messages.module_type_not_found_in_typedtree complete_name))
+ in
+ let kind = Sig.analyse_module_type_kind env complete_name
+ modtype tt_module_type
+ in
+ let mt =
+ {
+ mt_name = complete_name ;
+ mt_info = comment_opt ;
+ mt_type = Some tt_module_type ;
+ mt_is_interface = false ;
+ mt_file = !file_name ;
+ mt_kind = Some kind ;
+ mt_loc = { loc_impl = Some (!file_name, loc.Location.loc_start.Lexing.pos_cnum) ; loc_inter = None } ;
+ }
+ in
+ let new_env = Odoc_env.add_module_type env mt.mt_name in
+ let new_env2 =
+ match tt_module_type with
+ (* A VOIR : cela peut-il être Tmty_ident ? dans ce cas, on n'aurait pas la signature *)
+ Types.Tmty_signature s ->
+ Odoc_env.add_signature new_env mt.mt_name ~rel: (Name.simple mt.mt_name) s
+ | _ ->
+ new_env
+ in
+ (0, new_env2, [ Element_module_type mt ])
+
+ | Parsetree.Pstr_open longident ->
+ (* A VOIR : enrichir l'environnement quand open ? *)
+ let ele_comments = match comment_opt with
+ None -> []
+ | Some i ->
+ match i.i_desc with
+ None -> []
+ | Some t -> [Element_module_comment t]
+ in
+ (0, env, ele_comments)
+
+ | Parsetree.Pstr_class class_decl_list ->
+ (* we start by extending the environment *)
+ let new_env =
+ List.fold_left
+ (fun acc_env -> fun class_decl ->
+ let complete_name = Name.concat current_module_name class_decl.Parsetree.pci_name in
+ Odoc_env.add_class acc_env complete_name
+ )
+ env
+ class_decl_list
+ in
+ let rec f ?(first=false) last_pos class_decl_list =
+ match class_decl_list with
+ [] ->
+ []
+ | class_decl :: q ->
+ let (tt_class_exp, tt_type_params) =
+ try Typedtree_search.search_class_exp table class_decl.Parsetree.pci_name
+ with Not_found ->
+ let complete_name = Name.concat current_module_name class_decl.Parsetree.pci_name in
+ raise (Failure (Odoc_messages.class_not_found_in_typedtree complete_name))
+ in
+ let (com_opt, ele_comments) =
+ if first then
+ (comment_opt, [])
+ else
+ get_comments_in_module last_pos class_decl.Parsetree.pci_loc.Location.loc_start.Lexing.pos_cnum
+ in
+ let last_pos2 = class_decl.Parsetree.pci_loc.Location.loc_end.Lexing.pos_cnum in
+ let new_class = analyse_class
+ new_env
+ current_module_name
+ com_opt
+ class_decl
+ tt_type_params
+ tt_class_exp
+ table
+ in
+ ele_comments @ ((Element_class new_class) :: (f last_pos2 q))
+ in
+ (0, new_env, f ~first: true loc.Location.loc_start.Lexing.pos_cnum class_decl_list)
+
+ | Parsetree.Pstr_class_type class_type_decl_list ->
+ (* we start by extending the environment *)
+ let new_env =
+ List.fold_left
+ (fun acc_env -> fun class_type_decl ->
+ let complete_name = Name.concat current_module_name class_type_decl.Parsetree.pci_name in
+ Odoc_env.add_class_type acc_env complete_name
+ )
+ env
+ class_type_decl_list
+ in
+ let rec f ?(first=false) last_pos class_type_decl_list =
+ match class_type_decl_list with
+ [] ->
+ []
+ | class_type_decl :: q ->
+ let name = class_type_decl.Parsetree.pci_name in
+ let complete_name = Name.concat current_module_name name in
+ let virt = class_type_decl.Parsetree.pci_virt = Asttypes.Virtual in
+ let tt_cltype_declaration =
+ try Typedtree_search.search_class_type_declaration table name
+ with Not_found ->
+ raise (Failure (Odoc_messages.class_type_not_found_in_typedtree complete_name))
+ in
+ let type_params = tt_cltype_declaration.Types.clty_params in
+ let kind = Sig.analyse_class_type_kind
+ new_env
+ complete_name
+ class_type_decl.Parsetree.pci_loc.Location.loc_start.Lexing.pos_cnum
+ class_type_decl.Parsetree.pci_expr
+ tt_cltype_declaration.Types.clty_type
+ in
+ let (com_opt, ele_comments) =
+ if first then
+ (comment_opt, [])
+ else
+ get_comments_in_module last_pos class_type_decl.Parsetree.pci_loc.Location.loc_start.Lexing.pos_cnum
+ in
+ let last_pos2 = class_type_decl.Parsetree.pci_loc.Location.loc_end.Lexing.pos_cnum in
+ let new_ele =
+ Element_class_type
+ {
+ clt_name = complete_name ;
+ clt_info = com_opt ;
+ clt_type = Odoc_env.subst_class_type env tt_cltype_declaration.Types.clty_type ;
+ clt_type_parameters = List.map (Odoc_env.subst_type new_env) type_params ;
+ clt_virtual = virt ;
+ clt_kind = kind ;
+ clt_loc = { loc_impl = Some (!file_name, loc.Location.loc_start.Lexing.pos_cnum) ;
+ loc_inter = None } ;
+ }
+ in
+ ele_comments @ (new_ele :: (f last_pos2 q))
+ in
+ (0, new_env, f ~first: true loc.Location.loc_start.Lexing.pos_cnum class_type_decl_list)
+
+ | Parsetree.Pstr_include module_expr ->
+ (* we add a dummy included module which will be replaced by a correct
+ one at the end of the module analysis,
+ to use the Path.t of the included modules in the typdtree. *)
+ let im =
+ {
+ im_name = "dummy" ;
+ im_module = None ;
+ im_info = comment_opt ;
+ }
+ in
+ (0, env, [ Element_included_module im ]) (* A VOIR : étendre l'environnement ? avec quoi ? *)
+
+ (** Analysis of a [Parsetree.module_expr] and a name to return a [t_module].*)
+ and analyse_module env current_module_name module_name comment_opt p_module_expr tt_module_expr =
+ let complete_name = Name.concat current_module_name module_name in
+ let pos_start = p_module_expr.Parsetree.pmod_loc.Location.loc_start.Lexing.pos_cnum in
+ let pos_end = p_module_expr.Parsetree.pmod_loc.Location.loc_end.Lexing.pos_cnum in
+ let modtype =
+ (* A VOIR : Odoc_env.subst_module_type env ? *)
+ tt_module_expr.Typedtree.mod_type
+ in
+ let m_code_intf =
+ match p_module_expr.Parsetree.pmod_desc with
+ Parsetree.Pmod_constraint (_, pmodule_type) ->
+ let loc_start = pmodule_type.Parsetree.pmty_loc.Location.loc_start.Lexing.pos_cnum in
+ let loc_end = pmodule_type.Parsetree.pmty_loc.Location.loc_end.Lexing.pos_cnum in
+ Some (get_string_of_file loc_start loc_end)
+ | _ ->
+ None
+ in
+ let m_base =
+ {
+ m_name = complete_name ;
+ m_type = modtype ;
+ m_info = comment_opt ;
+ m_is_interface = false ;
+ m_file = !file_name ;
+ m_kind = Module_struct [] ;
+ m_loc = { loc_impl = Some (!file_name, pos_start) ; loc_inter = None } ;
+ m_top_deps = [] ;
+ m_code = None ; (* code is set by the caller, after the module is created *)
+ m_code_intf = m_code_intf ;
+ m_text_only = false ;
+ }
+ in
+ match (p_module_expr.Parsetree.pmod_desc, tt_module_expr.Typedtree.mod_desc) with
+ (Parsetree.Pmod_ident longident, Typedtree.Tmod_ident path) ->
+ let alias_name = Odoc_env.full_module_name env (Name.from_path path) in
+ { m_base with m_kind = Module_alias { ma_name = alias_name ;
+ ma_module = None ; } }
+
+ | (Parsetree.Pmod_structure p_structure, Typedtree.Tmod_structure tt_structure) ->
+ let elements = analyse_structure env complete_name pos_start pos_end p_structure tt_structure in
+ (* we must complete the included modules *)
+ let included_modules_from_tt = tt_get_included_module_list tt_structure in
+ let elements2 = replace_dummy_included_modules elements included_modules_from_tt in
+ { m_base with m_kind = Module_struct elements2 }
+
+ | (Parsetree.Pmod_functor (_, pmodule_type, p_module_expr2),
+ Typedtree.Tmod_functor (ident, mtyp, tt_module_expr2)) ->
+ let loc_start = pmodule_type.Parsetree.pmty_loc.Location.loc_start.Lexing.pos_cnum in
+ let loc_end = pmodule_type.Parsetree.pmty_loc.Location.loc_end.Lexing.pos_cnum in
+ let mp_type_code = get_string_of_file loc_start loc_end in
+ print_DEBUG (Printf.sprintf "mp_type_code=%s" mp_type_code);
+ let mp_name = Name.from_ident ident in
+ let mp_kind = Sig.analyse_module_type_kind env
+ current_module_name pmodule_type mtyp
+ in
+ let param =
+ {
+ mp_name = mp_name ;
+ mp_type = Odoc_env.subst_module_type env mtyp ;
+ mp_type_code = mp_type_code ;
+ mp_kind = mp_kind ;
+ }
+ in
+ let dummy_complete_name = (*Name.concat "__"*) param.mp_name in
+ (* TODO: A VOIR CE __ *)
+ let new_env = Odoc_env.add_module env dummy_complete_name in
+ let m_base2 = analyse_module
+ new_env
+ current_module_name
+ module_name
+ None
+ p_module_expr2
+ tt_module_expr2
+ in
+ let kind = m_base2.m_kind in
+ { m_base with m_kind = Module_functor (param, kind) }
+
+ | (Parsetree.Pmod_apply (p_module_expr1, p_module_expr2),
+ Typedtree.Tmod_apply (tt_module_expr1, tt_module_expr2, _))
+ | (Parsetree.Pmod_apply (p_module_expr1, p_module_expr2),
+ Typedtree.Tmod_constraint
+ ({ Typedtree.mod_desc = Typedtree.Tmod_apply (tt_module_expr1, tt_module_expr2, _)},
+ _, _)
+ ) ->
+ let m1 = analyse_module
+ env
+ current_module_name
+ module_name
+ None
+ p_module_expr1
+ tt_module_expr1
+ in
+ let m2 = analyse_module
+ env
+ current_module_name
+ module_name
+ None
+ p_module_expr2
+ tt_module_expr2
+ in
+ { m_base with m_kind = Module_apply (m1.m_kind, m2.m_kind) }
+
+ | (Parsetree.Pmod_constraint (p_module_expr2, p_modtype),
+ Typedtree.Tmod_constraint (tt_module_expr2, tt_modtype, _)) ->
+ print_DEBUG ("Odoc_ast: case Parsetree.Pmod_constraint + Typedtree.Tmod_constraint "^module_name);
+ let m_base2 = analyse_module
+ env
+ current_module_name
+ module_name
+ None
+ p_module_expr2
+ tt_module_expr2
+ in
+ let mtkind = Sig.analyse_module_type_kind env
+ (Name.concat current_module_name "??")
+ p_modtype tt_modtype
+ in
+ let tt_modtype = Odoc_env.subst_module_type env tt_modtype in
+ if !Odoc_global.filter_with_module_constraints then
+ filter_module_with_module_type_constraint m_base2 tt_modtype;
+ {
+ m_base with
+ m_type = tt_modtype ;
+ m_kind = Module_constraint (m_base2.m_kind, mtkind) ;
+ }
+
+ | (Parsetree.Pmod_structure p_structure,
+ Typedtree.Tmod_constraint
+ ({ Typedtree.mod_desc = Typedtree.Tmod_structure tt_structure},
+ tt_modtype, _)
+ ) ->
+ (* needed for recursive modules *)
+
+ print_DEBUG ("Odoc_ast: case Parsetree.Pmod_structure + Typedtree.Tmod_constraint "^module_name);
+ let elements = analyse_structure env complete_name pos_start pos_end p_structure tt_structure in
+ (* we must complete the included modules *)
+ let included_modules_from_tt = tt_get_included_module_list tt_structure in
+ let elements2 = replace_dummy_included_modules elements included_modules_from_tt in
+ { m_base with
+ m_type = Odoc_env.subst_module_type env tt_modtype ;
+ m_kind = Module_struct elements2 ;
+ }
+
+ | (Parsetree.Pmod_unpack (p_exp),
+ Typedtree.Tmod_unpack (t_exp, tt_modtype)) ->
+ print_DEBUG ("Odoc_ast: case Parsetree.Pmod_unpack + Typedtree.Tmod_unpack "^module_name);
+ let code =
+ let loc = p_module_expr.Parsetree.pmod_loc in
+ let loc_end = loc.Location.loc_end.Lexing.pos_cnum in
+ let exp_loc = p_exp.Parsetree.pexp_loc in
+ let exp_loc_end = exp_loc.Location.loc_end.Lexing.pos_cnum in
+ let s = get_string_of_file exp_loc_end loc_end in
+ Printf.sprintf "(val ...%s" s
+ in
+ (* let name = Odoc_env.full_module_type_name env (Name.from_path (fst pkg_type)) in *)
+ let name =
+ match tt_modtype with
+ | Tmty_ident p ->
+ Odoc_env.full_module_type_name env (Name.from_path p)
+ | _ -> ""
+ in
+ let alias = { mta_name = name ; mta_module = None } in
+ { m_base with
+ m_type = Odoc_env.subst_module_type env tt_modtype ;
+ m_kind = Module_unpack (code, alias) ;
+ }
+
+ | (parsetree, typedtree) ->
+ (*DEBUG*)let s_parse =
+ (*DEBUG*) match parsetree with
+ (*DEBUG*) Parsetree.Pmod_ident _ -> "Pmod_ident"
+ (*DEBUG*) | Parsetree.Pmod_structure _ -> "Pmod_structure"
+ (*DEBUG*) | Parsetree.Pmod_functor _ -> "Pmod_functor"
+ (*DEBUG*) | Parsetree.Pmod_apply _ -> "Pmod_apply"
+ (*DEBUG*) | Parsetree.Pmod_constraint _ -> "Pmod_constraint"
+ (*DEBUG*) | Parsetree.Pmod_unpack _ -> "Pmod_unpack"
+ (*DEBUG*)in
+ (*DEBUG*)let s_typed =
+ (*DEBUG*) match typedtree with
+ (*DEBUG*) Typedtree.Tmod_ident _ -> "Tmod_ident"
+ (*DEBUG*) | Typedtree.Tmod_structure _ -> "Tmod_structure"
+ (*DEBUG*) | Typedtree.Tmod_functor _ -> "Tmod_functor"
+ (*DEBUG*) | Typedtree.Tmod_apply _ -> "Tmod_apply"
+ (*DEBUG*) | Typedtree.Tmod_constraint _ -> "Tmod_constraint"
+ (*DEBUG*) | Typedtree.Tmod_unpack _ -> "Tmod_unpack"
+ (*DEBUG*)in
+ (*DEBUG*)let code = get_string_of_file pos_start pos_end in
+ print_DEBUG (Printf.sprintf "code=%s\ns_parse=%s\ns_typed=%s\n" code s_parse s_typed);
+
+ raise (Failure "analyse_module: parsetree and typedtree don't match.")
+
+ let analyse_typed_tree source_file input_file
+ (parsetree : Parsetree.structure) (typedtree : typedtree) =
+ let (tree_structure, _) = typedtree in
+ let complete_source_file =
+ try
+ let curdir = Sys.getcwd () in
+ let (dirname, basename) = (Filename.dirname source_file, Filename.basename source_file) in
+ Sys.chdir dirname ;
+ let complete = Filename.concat (Sys.getcwd ()) basename in
+ Sys.chdir curdir ;
+ complete
+ with
+ Sys_error s ->
+ prerr_endline s ;
+ incr Odoc_global.errors ;
+ source_file
+ in
+ prepare_file complete_source_file input_file;
+ (* We create the t_module for this file. *)
+ let mod_name = String.capitalize (Filename.basename (Filename.chop_extension source_file)) in
+ let (len,info_opt) = My_ir.first_special !file_name !file in
+
+ (* we must complete the included modules *)
+ let elements = analyse_structure Odoc_env.empty mod_name len (String.length !file) parsetree tree_structure in
+ let included_modules_from_tt = tt_get_included_module_list tree_structure in
+ let elements2 = replace_dummy_included_modules elements included_modules_from_tt in
+ let kind = Module_struct elements2 in
+ {
+ m_name = mod_name ;
+ m_type = Types.Tmty_signature [] ;
+ m_info = info_opt ;
+ m_is_interface = false ;
+ m_file = !file_name ;
+ m_kind = kind ;
+ m_loc = { loc_impl = Some (!file_name, 0) ; loc_inter = None } ;
+ m_top_deps = [] ;
+ m_code = (if !Odoc_global.keep_code then Some !file else None) ;
+ m_code_intf = None ;
+ m_text_only = false ;
+ }
+ end
diff --git a/ocaml-binary-annot/ocamldoc/odoc_ast.mli b/ocaml-binary-annot/ocamldoc/odoc_ast.mli
new file mode 100644
index 0000000000..48ba98bfb3
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_ast.mli
@@ -0,0 +1,104 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** The module for analysing the typed abstract syntax tree and source code and creating modules, classes, ..., elements.*)
+
+type typedtree = Typedtree.structure * Typedtree.module_coercion
+
+(** This module is used to search for structure items by name in a [Typedtree.structure]. *)
+module Typedtree_search :
+ sig
+ type ele
+
+ type tab = (ele, Typedtree.structure_item) Hashtbl.t
+ type tab_values = (Odoc_name.t, Typedtree.pattern * Typedtree.expression) Hashtbl.t
+
+ (** Create hash tables used to search by some of the functions below. *)
+ val tables : Typedtree.structure_item list -> tab * tab_values
+
+ (** This function returns the [Typedtree.module_expr] associated to the given module name,
+ in the given table.
+ @raise Not_found if the module was not found.*)
+ val search_module : tab -> string -> Typedtree.module_expr
+
+ (** This function returns the [Types.module_type] associated to the given module type name,
+ in the given table.
+ @raise Not_found if the module type was not found.*)
+ val search_module_type : tab -> string -> Types.module_type
+
+ (** This function returns the [Types.exception_declaration] associated to the given exception name,
+ in the given table.
+ @raise Not_found if the exception was not found.*)
+ val search_exception : tab -> string -> Types.exception_declaration
+
+ (** This function returns the [Path.t] associated to the given exception rebind name,
+ in the table.
+ @raise Not_found if the exception rebind was not found.*)
+ val search_exception_rebind : tab -> string -> Path.t
+
+ (** This function returns the [Typedtree.type_declaration] associated to the given type name,
+ in the given table.
+ @raise Not_found if the type was not found. *)
+ val search_type_declaration : tab -> string -> Types.type_declaration
+
+ (** This function returns the [Typedtree.class_expr] and type parameters
+ associated to the given class name, in the given table.
+ @raise Not_found if the class was not found. *)
+ val search_class_exp : tab -> string -> (Typedtree.class_expr * (Types.type_expr list))
+
+ (** This function returns the [Types.cltype_declaration] associated to the given class type name,
+ in the given table.
+ @raise Not_found if the class type was not found. *)
+ val search_class_type_declaration : tab -> string -> Types.cltype_declaration
+
+ (** This function returns the couple (pat, exp) for the given value name, in the
+ given table of values.
+ @raise Not found if no value matches the name.*)
+ val search_value : tab_values -> string -> Typedtree.pattern * Typedtree.expression
+
+ (** This function returns the [type_expr] for the given primitive name, in the
+ given table.
+ @raise Not found if no value matches the name.*)
+ val search_primitive : tab -> string -> Types.type_expr
+
+ (** This function returns the [Typedtree.class_expr] associated to
+ the n'th inherit in the given class structure of typed tree.
+ @raise Not_found if the class expression could not be found.*)
+ val get_nth_inherit_class_expr :
+ Typedtree.class_structure -> int -> Typedtree.class_expr
+
+ (** This function returns the [Types.type_expr] of the attribute
+ whose name is given, in a given class structure.
+ @raise Not_found if the class attribute could not be found.*)
+ val search_attribute_type :
+ Typedtree.class_structure -> string -> Types.type_expr
+
+ (** This function returns the [Types.expression] of the method whose name is given, in a given class structure.
+ @raise Not_found if the class method could not be found.*)
+ val search_method_expression :
+ Typedtree.class_structure -> string -> Typedtree.expression
+ end
+
+(** The module which performs the analysis of a typed tree.
+ The module uses the module {!Odoc_sig.Analyser}.
+ @param My_ir The module used to retrieve comments and special comments.*)
+module Analyser :
+ functor (My_ir : Odoc_sig.Info_retriever) ->
+ sig
+ (** This function takes a file name, a file containg the code and
+ the typed tree obtained from the compiler.
+ It goes through the tree, creating values for encountered
+ functions, modules, ..., and looking in the source file for comments.*)
+ val analyse_typed_tree :
+ string -> string -> Parsetree.structure -> typedtree -> Odoc_module.t_module
+ end
diff --git a/ocaml-binary-annot/ocamldoc/odoc_class.ml b/ocaml-binary-annot/ocamldoc/odoc_class.ml
new file mode 100644
index 0000000000..676d0ebc37
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_class.ml
@@ -0,0 +1,253 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Representation and manipulation of classes and class types.*)
+
+module Name = Odoc_name
+
+(** To keep the order of elements in a class *)
+type class_element =
+ Class_attribute of Odoc_value.t_attribute
+ | Class_method of Odoc_value.t_method
+ | Class_comment of Odoc_types.text
+
+(** Used when we can reference t_class or t_class_type. *)
+type cct =
+ Cl of t_class
+ | Cltype of t_class_type * Types.type_expr list (** class type and type parameters *)
+
+and inherited_class = {
+ ic_name : Name.t ; (** Complete name of the inherited class *)
+ mutable ic_class : cct option ; (** The associated t_class or t_class_type *)
+ ic_text : Odoc_types.text option ; (** The inheritance comment, if any *)
+ }
+
+and class_apply = {
+ capp_name : Name.t ; (** The complete name of the applied class *)
+ mutable capp_class : t_class option; (** The associated t_class if we found it *)
+ capp_params : Types.type_expr list; (** The type of expressions the class is applied to *)
+ capp_params_code : string list ; (** The code of these expressions *)
+ }
+
+and class_constr = {
+ cco_name : Name.t ; (** The complete name of the applied class *)
+ mutable cco_class : cct option; (** The associated class ot class type if we found it *)
+ cco_type_parameters : Types.type_expr list; (** The type parameters of the class, if needed *)
+ }
+
+
+and class_kind =
+ Class_structure of inherited_class list * class_element list
+ (** an explicit class structure, used in implementation and interface *)
+ | Class_apply of class_apply (** application/alias of a class, used in implementation only *)
+ | Class_constr of class_constr (** a class used to give the type of the defined class,
+ instead of a structure, used in interface only.
+ For example, it will be used with the name "M1.M2....tutu"
+ when the class to is defined like this :
+ class toto : int -> tutu *)
+ | Class_constraint of class_kind * class_type_kind
+ (** A class definition with a constraint. *)
+
+(** Representation of a class. *)
+and t_class = {
+ cl_name : Name.t ; (** Name of the class *)
+ mutable cl_info : Odoc_types.info option ; (** The optional associated user information *)
+ cl_type : Types.class_type ;
+ cl_type_parameters : Types.type_expr list ; (** Type parameters *)
+ cl_virtual : bool ; (** true = virtual *)
+ mutable cl_kind : class_kind ;
+ mutable cl_parameters : Odoc_parameter.parameter list ;
+ mutable cl_loc : Odoc_types.location ;
+ }
+
+and class_type_alias = {
+ cta_name : Name.t ;
+ mutable cta_class : cct option ; (** we can have a t_class or a t_class_type *)
+ cta_type_parameters : Types.type_expr list ; (** the type parameters *)
+ }
+
+and class_type_kind =
+ Class_signature of inherited_class list * class_element list
+ | Class_type of class_type_alias (** a class type eventually applied to type args *)
+
+(** Representation of a class type. *)
+and t_class_type = {
+ clt_name : Name.t ;
+ mutable clt_info : Odoc_types.info option ; (** The optional associated user information *)
+ clt_type : Types.class_type ;
+ clt_type_parameters : Types.type_expr list ; (** type parameters *)
+ clt_virtual : bool ; (** true = virtual *)
+ mutable clt_kind : class_type_kind ;
+ mutable clt_loc : Odoc_types.location ;
+ }
+
+
+(** {2 Functions} *)
+
+(** Returns the text associated to the given parameter label
+ in the given class, or None. *)
+let class_parameter_text_by_name cl label =
+ match cl.cl_info with
+ None -> None
+ | Some i ->
+ try
+ let t = List.assoc label i.Odoc_types.i_params in
+ Some t
+ with
+ Not_found ->
+ None
+
+(** Returns the list of elements of a t_class. *)
+let rec class_elements ?(trans=true) cl =
+ let rec iter_kind k =
+ match k with
+ Class_structure (_, elements) -> elements
+ | Class_constraint (c_kind, ct_kind) ->
+ iter_kind c_kind
+ (* A VOIR : utiliser le c_kind ou le ct_kind ?
+ Pour l'instant, comme le ct_kind n'est pas analysé,
+ on cherche dans le c_kind
+ class_type_elements ~trans: trans
+ { clt_name = "" ; clt_info = None ;
+ clt_type_parameters = [] ;
+ clt_virtual = false ;
+ clt_kind = ct_kind }
+ *)
+ | Class_apply capp ->
+ (
+ match capp.capp_class with
+ Some c when trans -> class_elements ~trans: trans c
+ | _ -> []
+ )
+ | Class_constr cco ->
+ (
+ match cco.cco_class with
+ Some (Cl c) when trans -> class_elements ~trans: trans c
+ | Some (Cltype (ct,_)) when trans -> class_type_elements ~trans: trans ct
+ | _ -> []
+ )
+ in
+ iter_kind cl.cl_kind
+
+(** Returns the list of elements of a t_class_type. *)
+and class_type_elements ?(trans=true) clt =
+ match clt.clt_kind with
+ Class_signature (_, elements) -> elements
+ | Class_type { cta_class = Some (Cltype (ct, _)) } when trans ->
+ class_type_elements ~trans ct
+ | Class_type { cta_class = Some (Cl c) } when trans ->
+ class_elements ~trans c
+ | Class_type _ ->
+ []
+
+(** Returns the attributes of a t_class. *)
+let class_attributes ?(trans=true) cl =
+ List.fold_left
+ (fun acc -> fun ele ->
+ match ele with
+ Class_attribute a ->
+ acc @ [ a ]
+ | _ ->
+ acc
+ )
+ []
+ (class_elements ~trans cl)
+
+(** Returns the methods of a t_class. *)
+let class_methods ?(trans=true) cl =
+ List.fold_left
+ (fun acc -> fun ele ->
+ match ele with
+ Class_method m ->
+ acc @ [ m ]
+ | _ ->
+ acc
+ )
+ []
+ (class_elements ~trans cl)
+
+(** Returns the comments in a t_class. *)
+let class_comments ?(trans=true) cl =
+ List.fold_left
+ (fun acc -> fun ele ->
+ match ele with
+ Class_comment t ->
+ acc @ [ t ]
+ | _ ->
+ acc
+ )
+ []
+ (class_elements ~trans cl)
+
+
+(** Update the parameters text of a t_class, according to the cl_info field. *)
+let class_update_parameters_text cl =
+ let f p =
+ Odoc_parameter.update_parameter_text (class_parameter_text_by_name cl) p
+ in
+ List.iter f cl.cl_parameters
+
+(** Returns the attributes of a t_class_type. *)
+let class_type_attributes ?(trans=true) clt =
+ List.fold_left
+ (fun acc -> fun ele ->
+ match ele with
+ Class_attribute a ->
+ acc @ [ a ]
+ | _ ->
+ acc
+ )
+ []
+ (class_type_elements ~trans clt)
+
+(** Returns the methods of a t_class_type. *)
+let class_type_methods ?(trans=true) clt =
+ List.fold_left
+ (fun acc -> fun ele ->
+ match ele with
+ Class_method m ->
+ acc @ [ m ]
+ | _ ->
+ acc
+ )
+ []
+ (class_type_elements ~trans clt)
+
+(** Returns the comments in a t_class_type. *)
+let class_type_comments ?(trans=true) clt =
+ List.fold_left
+ (fun acc -> fun ele ->
+ match ele with
+ Class_comment m ->
+ acc @ [ m ]
+ | _ ->
+ acc
+ )
+ []
+ (class_type_elements ~trans clt)
+
+(** Returns the text associated to the given parameter label
+ in the given class type, or None. *)
+let class_type_parameter_text_by_name clt label =
+ match clt.clt_info with
+ None -> None
+ | Some i ->
+ try
+ let t = List.assoc label i.Odoc_types.i_params in
+ Some t
+ with
+ Not_found ->
+ None
+
+
+(* eof $Id$ *)
diff --git a/ocaml-binary-annot/ocamldoc/odoc_comments.ml b/ocaml-binary-annot/ocamldoc/odoc_comments.ml
new file mode 100644
index 0000000000..ea5427e077
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_comments.ml
@@ -0,0 +1,348 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Analysis of comments. *)
+
+open Odoc_types
+
+let print_DEBUG s = print_string s ; print_newline ();;
+
+(** This variable contains the regular expression representing a blank but not a '\n'.*)
+let simple_blank = "[ \013\009\012]"
+
+module type Texter =
+ sig
+ (** Return a text structure from a string. *)
+ val text_of_string : string -> text
+ end
+
+module Info_retriever =
+ functor (MyTexter : Texter) ->
+ struct
+ let create_see s =
+ try
+ let lexbuf = Lexing.from_string s in
+ let (see_ref, s) = Odoc_parser.see_info Odoc_see_lexer.main lexbuf in
+ (see_ref, MyTexter.text_of_string s)
+ with
+ | Odoc_text.Text_syntax (l, c, s) ->
+ raise (Failure (Odoc_messages.text_parse_error l c s))
+ | _ ->
+ raise (Failure ("Erreur inconnue lors du parse de see : "^s))
+
+ let retrieve_info fun_lex file (s : string) =
+ try
+ let _ = Odoc_comments_global.init () in
+ Odoc_lexer.comments_level := 0;
+ let lexbuf = Lexing.from_string s in
+ match Odoc_parser.main fun_lex lexbuf with
+ None ->
+ (0, None)
+ | Some (desc, remain_opt) ->
+ let mem_nb_chars = !Odoc_comments_global.nb_chars in
+ let _ =
+ match remain_opt with
+ None ->
+ ()
+ | Some s ->
+ (*DEBUG*)print_string ("remain: "^s); print_newline();
+ let lexbuf2 = Lexing.from_string s in
+ Odoc_parser.info_part2 Odoc_lexer.elements lexbuf2
+ in
+ (mem_nb_chars,
+ Some
+ {
+ i_desc = (match desc with "" -> None | _ -> Some (MyTexter.text_of_string desc));
+ i_authors = !Odoc_comments_global.authors;
+ i_version = !Odoc_comments_global.version;
+ i_sees = (List.map create_see !Odoc_comments_global.sees) ;
+ i_since = !Odoc_comments_global.since;
+ i_before = Odoc_merge.merge_before_tags
+ (List.map (fun (n, s) ->
+ (n, MyTexter.text_of_string s)) !Odoc_comments_global.before)
+ ;
+ i_deprecated =
+ (match !Odoc_comments_global.deprecated with
+ None -> None | Some s -> Some (MyTexter.text_of_string s));
+ i_params =
+ (List.map (fun (n, s) ->
+ (n, MyTexter.text_of_string s)) !Odoc_comments_global.params);
+ i_raised_exceptions =
+ (List.map (fun (n, s) ->
+ (n, MyTexter.text_of_string s)) !Odoc_comments_global.raised_exceptions);
+ i_return_value =
+ (match !Odoc_comments_global.return_value with
+ None -> None | Some s -> Some (MyTexter.text_of_string s)) ;
+ i_custom = (List.map
+ (fun (tag, s) -> (tag, MyTexter.text_of_string s))
+ !Odoc_comments_global.customs)
+ }
+ )
+ with
+ Failure s ->
+ incr Odoc_global.errors ;
+ prerr_endline (file^" : "^s^"\n");
+ (0, None)
+ | Odoc_text.Text_syntax (l, c, s) ->
+ incr Odoc_global.errors ;
+ prerr_endline (file^" : "^(Odoc_messages.text_parse_error l c s));
+ (0, None)
+ | _ ->
+ incr Odoc_global.errors ;
+ prerr_endline (file^" : "^Odoc_messages.parse_error^"\n");
+ (0, None)
+
+ (** This function takes a string where a simple comment may has been found. It returns
+ false if there is a blank line or the first comment is a special one, or if there is
+ no comment if the string.*)
+ let nothing_before_simple_comment s =
+ (* get the position of the first "(*" *)
+ try
+ print_DEBUG ("comment_is_attached: "^s);
+ let pos = Str.search_forward (Str.regexp "(\\*") s 0 in
+ let next_char = if (String.length s) >= (pos + 1) then s.[pos + 2] else '_' in
+ (next_char <> '*') &&
+ (
+ (* there is no special comment between the constructor and the coment we got *)
+ let s2 = String.sub s 0 pos in
+ print_DEBUG ("s2="^s2);
+ try
+ let _ = Str.search_forward (Str.regexp ("['\n']"^simple_blank^"*['\n']")) s2 0 in
+ (* a blank line was before the comment *)
+ false
+ with
+ Not_found ->
+ true
+ )
+ with
+ Not_found ->
+ false
+
+ (** Return true if the given string contains a blank line. *)
+ let blank_line s =
+ try
+ let _ = Str.search_forward (Str.regexp ("['\n']"^simple_blank^"*['\n']")) s 0 in
+ (* a blank line was before the comment *)
+ true
+ with
+ Not_found ->
+ false
+
+ let retrieve_info_special file (s : string) =
+ retrieve_info Odoc_lexer.main file s
+
+ let retrieve_info_simple file (s : string) =
+ let _ = Odoc_comments_global.init () in
+ Odoc_lexer.comments_level := 0;
+ let lexbuf = Lexing.from_string s in
+ match Odoc_parser.main Odoc_lexer.simple lexbuf with
+ None ->
+ (0, None)
+ | Some (desc, remain_opt) ->
+ (!Odoc_comments_global.nb_chars, Some Odoc_types.dummy_info)
+
+ (** Return true if the given string contains a blank line outside a simple comment. *)
+ let blank_line_outside_simple file s =
+ let rec iter s2 =
+ match retrieve_info_simple file s2 with
+ (_, None) ->
+ blank_line s2
+ | (len, Some _) ->
+ try
+ let pos = Str.search_forward (Str.regexp_string "(*") s2 0 in
+ let s_before = String.sub s2 0 pos in
+ let s_after = String.sub s2 len ((String.length s2) - len) in
+ (blank_line s_before) || (iter s_after)
+ with
+ Not_found ->
+ (* we shouldn't get here *)
+ false
+ in
+ iter s
+
+ (** This function returns the first simple comment in
+ the given string. If strict is [true] then no
+ comment is returned if a blank line or a special
+ comment is found before the simple comment. *)
+ let retrieve_first_info_simple ?(strict=true) file (s : string) =
+ match retrieve_info_simple file s with
+ (_, None) ->
+ (0, None)
+ | (len, Some d) ->
+ (* we check if the comment we got was really attached to the constructor,
+ i.e. that there was no blank line or any special comment "(**" before *)
+ if (not strict) or (nothing_before_simple_comment s) then
+ (* ok, we attach the comment to the constructor *)
+ (len, Some d)
+ else
+ (* a blank line or special comment was before the comment,
+ so we must not attach this comment to the constructor. *)
+ (0, None)
+
+ let retrieve_last_info_simple file (s : string) =
+ print_DEBUG ("retrieve_last_info_simple:"^s);
+ let rec f cur_len cur_d =
+ try
+ let s2 = String.sub s cur_len ((String.length s) - cur_len) in
+ print_DEBUG ("retrieve_last_info_simple.f:"^s2);
+ match retrieve_info_simple file s2 with
+ (len, None) ->
+ print_DEBUG "retrieve_last_info_simple: None";
+ (cur_len + len, cur_d)
+ | (len, Some d) ->
+ print_DEBUG "retrieve_last_info_simple: Some";
+ f (len + cur_len) (Some d)
+ with
+ _ ->
+ print_DEBUG "retrieve_last_info_simple : Erreur String.sub";
+ (cur_len, cur_d)
+ in
+ f 0 None
+
+ let retrieve_last_special_no_blank_after file (s : string) =
+ print_DEBUG ("retrieve_last_special_no_blank_after:"^s);
+ let rec f cur_len cur_d =
+ try
+ let s2 = String.sub s cur_len ((String.length s) - cur_len) in
+ print_DEBUG ("retrieve_last_special_no_blank_after.f:"^s2);
+ match retrieve_info_special file s2 with
+ (len, None) ->
+ print_DEBUG "retrieve_last_special_no_blank_after: None";
+ (cur_len + len, cur_d)
+ | (len, Some d) ->
+ print_DEBUG "retrieve_last_special_no_blank_after: Some";
+ f (len + cur_len) (Some d)
+ with
+ _ ->
+ print_DEBUG "retrieve_last_special_no_blank_after : Erreur String.sub";
+ (cur_len, cur_d)
+ in
+ f 0 None
+
+ let all_special file s =
+ print_DEBUG ("all_special: "^s);
+ let rec iter acc n s2 =
+ match retrieve_info_special file s2 with
+ (_, None) ->
+ (n, acc)
+ | (n2, Some i) ->
+ print_DEBUG ("all_special: avant String.sub new_s="^s2);
+ print_DEBUG ("n2="^(string_of_int n2)) ;
+ print_DEBUG ("len(s2)="^(string_of_int (String.length s2))) ;
+ let new_s = String.sub s2 n2 ((String.length s2) - n2) in
+ print_DEBUG ("all_special: apres String.sub new_s="^new_s);
+ iter (acc @ [i]) (n + n2) new_s
+ in
+ let res = iter [] 0 s in
+ print_DEBUG ("all_special: end");
+ res
+
+ let just_after_special file s =
+ print_DEBUG ("just_after_special: "^s);
+ let res = match retrieve_info_special file s with
+ (_, None) ->
+ (0, None)
+ | (len, Some d) ->
+ (* we must not have a simple comment or a blank line before. *)
+ match retrieve_info_simple file (String.sub s 0 len) with
+ (_, None) ->
+ (
+ try
+ (* if the special comment is the stop comment (**/**),
+ then we must not associate it. *)
+ let pos = Str.search_forward (Str.regexp_string "(**") s 0 in
+ if blank_line (String.sub s 0 pos) or
+ d.Odoc_types.i_desc = Some [Odoc_types.Raw "/*"]
+ then
+ (0, None)
+ else
+ (len, Some d)
+ with
+ Not_found ->
+ (* should not occur *)
+ (0, None)
+ )
+ | (len2, Some d2) ->
+ (0, None)
+ in
+ print_DEBUG ("just_after_special:end");
+ res
+
+ let first_special file s =
+ retrieve_info_special file s
+
+ let get_comments f_create_ele file s =
+ let (assoc_com, ele_coms) =
+ (* get the comments *)
+ let (len, special_coms) = all_special file s in
+ (* if there is no blank line after the special comments, and
+ if the last special comment is not the stop special comment, then the
+ last special comments must be associated to the element. *)
+ match List.rev special_coms with
+ [] ->
+ (None, [])
+ | h :: q ->
+ if (blank_line_outside_simple file
+ (String.sub s len ((String.length s) - len)) )
+ or h.Odoc_types.i_desc = Some [Odoc_types.Raw "/*"]
+ then
+ (None, special_coms)
+ else
+ (Some h, List.rev q)
+ in
+ let ele_comments =
+ List.fold_left
+ (fun acc -> fun sc ->
+ match sc.Odoc_types.i_desc with
+ None ->
+ acc
+ | Some t ->
+ acc @ [f_create_ele t])
+ []
+ ele_coms
+ in
+ (assoc_com, ele_comments)
+ end
+
+module Basic_info_retriever = Info_retriever (Odoc_text.Texter)
+
+let info_of_string s =
+ let dummy =
+ {
+ i_desc = None ;
+ i_authors = [] ;
+ i_version = None ;
+ i_sees = [] ;
+ i_since = None ;
+ i_before = [] ;
+ i_deprecated = None ;
+ i_params = [] ;
+ i_raised_exceptions = [] ;
+ i_return_value = None ;
+ i_custom = [] ;
+ }
+ in
+ let s2 = Printf.sprintf "(** %s *)" s in
+ let (_, i_opt) = Basic_info_retriever.first_special "-" s2 in
+ match i_opt with
+ None -> dummy
+ | Some i -> i
+
+let info_of_comment_file modlist f =
+ try
+ let s = Odoc_misc.input_file_as_string f in
+ let i = info_of_string s in
+ Odoc_cross.assoc_comments_info "" modlist i
+ with
+ Sys_error s ->
+ failwith s
diff --git a/ocaml-binary-annot/ocamldoc/odoc_comments.mli b/ocaml-binary-annot/ocamldoc/odoc_comments.mli
new file mode 100644
index 0000000000..28122cda94
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_comments.mli
@@ -0,0 +1,74 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Analysis of comments. *)
+
+val simple_blank : string
+
+(** The type of modules in argument to Info_retriever *)
+module type Texter =
+ sig
+ (** Return a text structure from a string. *)
+ val text_of_string : string -> Odoc_types.text
+ end
+
+(** The basic module for special comments analysis.*)
+module Basic_info_retriever :
+ sig
+ (** Return true if the given string contains a blank line. *)
+ val blank_line_outside_simple :
+ string -> string -> bool
+
+ (** This function retrieves all the special comments in the given string. *)
+ val all_special : string -> string -> int * Odoc_types.info list
+
+ (** [just_after_special file str] return the pair ([length], [info_opt])
+ where [info_opt] is the first optional special comment found
+ in [str], without any blank line before. [length] is the number
+ of chars from the beginning of [str] to the end of the special comment. *)
+ val just_after_special :
+ string -> string -> int * Odoc_types.info option
+
+ (** [first_special file str] return the pair ([length], [info_opt])
+ where [info_opt] is the first optional special comment found
+ in [str]. [length] is the number of chars from the beginning of
+ [str] to the end of the special comment. *)
+ val first_special :
+ string -> string -> int * Odoc_types.info option
+
+ (** Return a pair [(comment_opt, element_comment_list)], where [comment_opt] is the last special
+ comment found in the given string and not followed by a blank line,
+ and [element_comment_list] the list of values built from the other
+ special comments found and the given function. *)
+ val get_comments :
+ (Odoc_types.text -> 'a) ->
+ string -> string -> Odoc_types.info option * 'a list
+
+ end
+
+(** [info_of_string s] parses the given string
+ like a regular ocamldoc comment and return an
+ {!Odoc_types.info} structure.
+ @return an empty structure if there was a syntax error. TODO: change this
+*)
+val info_of_string : string -> Odoc_types.info
+
+(** [info_of_comment_file file] parses the given file
+ and return an {!Odoc_types.info} structure. The content of the
+ file must have the same syntax as the content of a special comment.
+ The given module list is used for cross reference.
+ @raise Failure is the file could not be opened or there is a
+ syntax error.
+*)
+val info_of_comment_file :
+ Odoc_module.t_module list -> string -> Odoc_types.info
diff --git a/ocaml-binary-annot/ocamldoc/odoc_comments_global.ml b/ocaml-binary-annot/ocamldoc/odoc_comments_global.ml
new file mode 100644
index 0000000000..a4366ceb71
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_comments_global.ml
@@ -0,0 +1,51 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** The global variables used by the special comment parser.*)
+
+let nb_chars = ref 0
+
+let authors = ref ([] : string list)
+
+let version = ref (None : string option)
+
+let sees = ref ([] : string list)
+
+let since = ref (None : string option)
+
+let before = ref []
+
+let deprecated = ref (None : string option)
+
+let params = ref ([] : (string * string) list)
+
+let raised_exceptions = ref ([] : (string * string) list)
+
+let return_value = ref (None : string option)
+
+let customs = ref []
+
+let init () =
+ nb_chars := 0;
+ authors := [];
+ version := None;
+ sees := [];
+ since := None;
+ before := [];
+ deprecated := None;
+ params := [];
+ raised_exceptions := [];
+ return_value := None ;
+ customs := []
+
+(* eof $Id$ *)
diff --git a/ocaml-binary-annot/ocamldoc/odoc_comments_global.mli b/ocaml-binary-annot/ocamldoc/odoc_comments_global.mli
new file mode 100644
index 0000000000..e9efbffc59
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_comments_global.mli
@@ -0,0 +1,50 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** The global variables used by the special comment parser.*)
+
+(** the number of chars used in the lexer. *)
+val nb_chars : int ref
+
+(** the authors list *)
+val authors : string list ref
+
+(** the version string *)
+val version : string option ref
+
+(** the see references *)
+val sees : string list ref
+
+(** the since string *)
+val since : string option ref
+
+(** the before tag information *)
+val before : (string * string) list ref
+
+(** the deprecated flag *)
+val deprecated : string option ref
+
+(** parameters, with name and description *)
+val params : (string * string) list ref
+
+(** the raised exceptions, with name and description *)
+val raised_exceptions : (string * string) list ref
+
+(** the description of the return value *)
+val return_value : string option ref
+
+(** the strings associated to custom tags. *)
+val customs : (string * string) list ref
+
+(** this function inits the variables filled by the parser. *)
+val init : unit -> unit
diff --git a/ocaml-binary-annot/ocamldoc/odoc_config.ml b/ocaml-binary-annot/ocamldoc/odoc_config.ml
new file mode 100644
index 0000000000..71769534dc
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_config.ml
@@ -0,0 +1,18 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+let custom_generators_path =
+ Filename.concat Config.standard_library
+ (Filename.concat "ocamldoc" "custom")
+
+let print_warnings = ref true
diff --git a/ocaml-binary-annot/ocamldoc/odoc_config.mli b/ocaml-binary-annot/ocamldoc/odoc_config.mli
new file mode 100644
index 0000000000..fb356084bb
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_config.mli
@@ -0,0 +1,20 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Ocamldoc configuration contants. *)
+
+(** Default path to search for custom generators and to install them. *)
+val custom_generators_path : string
+
+(** A flag to indicate whether to print ocamldoc warnings or not. *)
+val print_warnings : bool ref
diff --git a/ocaml-binary-annot/ocamldoc/odoc_control.ml b/ocaml-binary-annot/ocamldoc/odoc_control.ml
new file mode 100644
index 0000000000..b73796bf8a
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_control.ml
@@ -0,0 +1,12 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
diff --git a/ocaml-binary-annot/ocamldoc/odoc_cross.ml b/ocaml-binary-annot/ocamldoc/odoc_cross.ml
new file mode 100644
index 0000000000..39965f83b2
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_cross.ml
@@ -0,0 +1,1006 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Cross referencing. *)
+
+module Name = Odoc_name
+open Odoc_module
+open Odoc_class
+open Odoc_exception
+open Odoc_types
+open Odoc_value
+open Odoc_type
+open Odoc_parameter
+
+(*** Replacements of aliases : if e1 = e2 and e2 = e3, then replace e2 by e3 to have e1 = e3,
+ in order to associate the element with complete information. *)
+
+(** The module used to keep what refs were modified. *)
+module S = Set.Make
+ (
+ struct type t = string * ref_kind option
+ let compare = Pervasives.compare
+ end
+ )
+
+let verified_refs = ref S.empty
+
+let add_verified v = verified_refs := S.add v !verified_refs
+let was_verified v = S.mem v !verified_refs
+
+(** The module with the predicates used to get the aliased modules, classes and exceptions. *)
+module P_alias =
+ struct
+ type t = int
+
+ let p_module m _ =
+ (true,
+ match m.m_kind with
+ Module_alias _ -> true
+ | _ -> false
+ )
+ let p_module_type mt _ =
+ (true,
+ match mt.mt_kind with
+ Some (Module_type_alias _) -> true
+ | _ -> false
+ )
+ let p_class c _ = (false, false)
+ let p_class_type ct _ = (false, false)
+ let p_value v _ = false
+ let p_type t _ = false
+ let p_exception e _ = e.ex_alias <> None
+ let p_attribute a _ = false
+ let p_method m _ = false
+ let p_section s _ = false
+ end
+
+(** The module used to get the aliased elements. *)
+module Search_alias = Odoc_search.Search (P_alias)
+
+type alias_state =
+ Alias_resolved
+ | Alias_to_resolve
+
+(** Couples of module name aliases. *)
+let (module_aliases : (Name.t, Name.t * alias_state) Hashtbl.t) = Hashtbl.create 13 ;;
+
+(** Couples of module or module type name aliases. *)
+let module_and_modtype_aliases = Hashtbl.create 13;;
+
+(** Couples of exception name aliases. *)
+let exception_aliases = Hashtbl.create 13;;
+
+let rec build_alias_list = function
+ [] -> ()
+ | (Odoc_search.Res_module m) :: q ->
+ (
+ match m.m_kind with
+ Module_alias ma ->
+ Hashtbl.add module_aliases m.m_name (ma.ma_name, Alias_to_resolve);
+ Hashtbl.add module_and_modtype_aliases m.m_name (ma.ma_name, Alias_to_resolve)
+ | _ -> ()
+ );
+ build_alias_list q
+ | (Odoc_search.Res_module_type mt) :: q ->
+ (
+ match mt.mt_kind with
+ Some (Module_type_alias mta) ->
+ Hashtbl.add module_and_modtype_aliases
+ mt.mt_name (mta.mta_name, Alias_to_resolve)
+ | _ -> ()
+ );
+ build_alias_list q
+ | (Odoc_search.Res_exception e) :: q ->
+ (
+ match e.ex_alias with
+ None -> ()
+ | Some ea ->
+ Hashtbl.add exception_aliases
+ e.ex_name (ea.ea_name,Alias_to_resolve)
+ );
+ build_alias_list q
+ | _ :: q ->
+ build_alias_list q
+
+(** Retrieve the aliases for modules, module types and exceptions
+ and put them in global hash tables. *)
+let get_alias_names module_list =
+ Hashtbl.clear module_aliases;
+ Hashtbl.clear module_and_modtype_aliases;
+ Hashtbl.clear exception_aliases;
+ build_alias_list (Search_alias.search module_list 0)
+
+exception Found of string
+let name_alias =
+ let rec f t name =
+ try
+ match Hashtbl.find t name with
+ (s, Alias_resolved) -> s
+ | (s, Alias_to_resolve) -> f t s
+ with
+ Not_found ->
+ try
+ Hashtbl.iter
+ (fun n2 (n3, _) ->
+ if Name.prefix n2 name then
+ let ln2 = String.length n2 in
+ let s = n3^(String.sub name ln2 ((String.length name) - ln2)) in
+ raise (Found s)
+ )
+ t ;
+ Hashtbl.replace t name (name, Alias_resolved);
+ name
+ with
+ Found s ->
+ let s2 = f t s in
+ Hashtbl.replace t s2 (s2, Alias_resolved);
+ s2
+ in
+ fun name alias_tbl ->
+ f alias_tbl name
+
+
+module Map_ord =
+ struct
+ type t = string
+ let compare = Pervasives.compare
+ end
+
+module Ele_map = Map.Make (Map_ord)
+
+let known_elements = ref Ele_map.empty
+let add_known_element name k =
+ try
+ let l = Ele_map.find name !known_elements in
+ let s = Ele_map.remove name !known_elements in
+ known_elements := Ele_map.add name (k::l) s
+ with
+ Not_found ->
+ known_elements := Ele_map.add name [k] !known_elements
+
+let rec get_known_elements name =
+ try Ele_map.find name !known_elements
+ with Not_found -> []
+
+let kind_name_exists kind =
+ let pred =
+ match kind with
+ RK_module -> (fun e -> match e with Odoc_search.Res_module _ -> true | _ -> false)
+ | RK_module_type -> (fun e -> match e with Odoc_search.Res_module_type _ -> true | _ -> false)
+ | RK_class -> (fun e -> match e with Odoc_search.Res_class_type _ -> true | _ -> false)
+ | RK_class_type -> (fun e -> match e with Odoc_search.Res_class_type _ -> true | _ -> false)
+ | RK_value -> (fun e -> match e with Odoc_search.Res_value _ -> true | _ -> false)
+ | RK_type -> (fun e -> match e with Odoc_search.Res_type _ -> true | _ -> false)
+ | RK_exception -> (fun e -> match e with Odoc_search.Res_exception _ -> true | _ -> false)
+ | RK_attribute -> (fun e -> match e with Odoc_search.Res_attribute _ -> true | _ -> false)
+ | RK_method -> (fun e -> match e with Odoc_search.Res_method _ -> true | _ -> false)
+ | RK_section _ -> assert false
+ in
+ fun name ->
+ try List.exists pred (get_known_elements name)
+ with Not_found -> false
+
+let module_exists = kind_name_exists RK_module
+let module_type_exists = kind_name_exists RK_module_type
+let class_exists = kind_name_exists RK_class
+let class_type_exists = kind_name_exists RK_class_type
+let value_exists = kind_name_exists RK_value
+let type_exists = kind_name_exists RK_type
+let exception_exists = kind_name_exists RK_exception
+let attribute_exists = kind_name_exists RK_attribute
+let method_exists = kind_name_exists RK_method
+
+let lookup_module name =
+ match List.find
+ (fun k -> match k with Odoc_search.Res_module _ -> true | _ -> false)
+ (get_known_elements name)
+ with
+ | Odoc_search.Res_module m -> m
+ | _ -> assert false
+
+let lookup_module_type name =
+ match List.find
+ (fun k -> match k with Odoc_search.Res_module_type _ -> true | _ -> false)
+ (get_known_elements name)
+ with
+ | Odoc_search.Res_module_type m -> m
+ | _ -> assert false
+
+let lookup_class name =
+ match List.find
+ (fun k -> match k with Odoc_search.Res_class _ -> true | _ -> false)
+ (get_known_elements name)
+ with
+ | Odoc_search.Res_class c -> c
+ | _ -> assert false
+
+let lookup_class_type name =
+ match List.find
+ (fun k -> match k with Odoc_search.Res_class_type _ -> true | _ -> false)
+ (get_known_elements name)
+ with
+ | Odoc_search.Res_class_type c -> c
+ | _ -> assert false
+
+let lookup_exception name =
+ match List.find
+ (fun k -> match k with Odoc_search.Res_exception _ -> true | _ -> false)
+ (get_known_elements name)
+ with
+ | Odoc_search.Res_exception e -> e
+ | _ -> assert false
+
+class scan =
+ object
+ inherit Odoc_scan.scanner
+ method! scan_value v =
+ add_known_element v.val_name (Odoc_search.Res_value v)
+ method! scan_type t =
+ add_known_element t.ty_name (Odoc_search.Res_type t)
+ method! scan_exception e =
+ add_known_element e.ex_name (Odoc_search.Res_exception e)
+ method! scan_attribute a =
+ add_known_element a.att_value.val_name
+ (Odoc_search.Res_attribute a)
+ method! scan_method m =
+ add_known_element m.met_value.val_name
+ (Odoc_search.Res_method m)
+ method! scan_class_pre c =
+ add_known_element c.cl_name (Odoc_search.Res_class c);
+ true
+ method! scan_class_type_pre c =
+ add_known_element c.clt_name (Odoc_search.Res_class_type c);
+ true
+ method! scan_module_pre m =
+ add_known_element m.m_name (Odoc_search.Res_module m);
+ true
+ method! scan_module_type_pre m =
+ add_known_element m.mt_name (Odoc_search.Res_module_type m);
+ true
+
+ end
+
+let init_known_elements_map module_list =
+ let c = new scan in
+ c#scan_module_list module_list
+
+
+(** The type to describe the names not found. *)
+type not_found_name =
+ NF_m of Name.t
+ | NF_mt of Name.t
+ | NF_mmt of Name.t
+ | NF_c of Name.t
+ | NF_ct of Name.t
+ | NF_cct of Name.t
+ | NF_ex of Name.t
+
+(** Functions to find and associate aliases elements. *)
+
+let rec associate_in_module module_list (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) m =
+ let rec iter_kind (acc_b, acc_inc, acc_names) k =
+ match k with
+ Module_struct elements ->
+ List.fold_left
+ (associate_in_module_element module_list m.m_name)
+ (acc_b, acc_inc, acc_names)
+ elements
+
+ | Module_alias ma ->
+ (
+ match ma.ma_module with
+ Some _ ->
+ (acc_b, acc_inc, acc_names)
+ | None ->
+ let mmt_opt =
+ try Some (Mod (lookup_module ma.ma_name))
+ with Not_found ->
+ try Some (Modtype (lookup_module_type ma.ma_name))
+ with Not_found -> None
+ in
+ match mmt_opt with
+ None -> (acc_b, (Name.head m.m_name) :: acc_inc,
+ (* we don't want to output warning messages for
+ "sig ... end" or "struct ... end" modules not found *)
+ (if ma.ma_name = Odoc_messages.struct_end or
+ ma.ma_name = Odoc_messages.sig_end then
+ acc_names
+ else
+ (NF_mmt ma.ma_name) :: acc_names)
+ )
+ | Some mmt ->
+ ma.ma_module <- Some mmt ;
+ (true, acc_inc, acc_names)
+ )
+
+ | Module_functor (_, k) ->
+ iter_kind (acc_b, acc_inc, acc_names) k
+
+ | Module_with (tk, _) ->
+ associate_in_module_type module_list (acc_b, acc_inc, acc_names)
+ { mt_name = "" ; mt_info = None ; mt_type = None ;
+ mt_is_interface = false ; mt_file = ""; mt_kind = Some tk ;
+ mt_loc = Odoc_types.dummy_loc }
+
+ | Module_apply (k1, k2) ->
+ let (acc_b2, acc_inc2, acc_names2) = iter_kind (acc_b, acc_inc, acc_names) k1 in
+ iter_kind (acc_b2, acc_inc2, acc_names2) k2
+
+ | Module_constraint (k, tk) ->
+ let (acc_b2, acc_inc2, acc_names2) = iter_kind (acc_b, acc_inc, acc_names) k in
+ associate_in_module_type module_list (acc_b2, acc_inc2, acc_names2)
+ { mt_name = "" ; mt_info = None ; mt_type = None ;
+ mt_is_interface = false ; mt_file = "" ; mt_kind = Some tk ;
+ mt_loc = Odoc_types.dummy_loc }
+
+ | Module_typeof _ ->
+ (acc_b, acc_inc, acc_names)
+
+ | Module_unpack (code, mta) ->
+ begin
+ match mta.mta_module with
+ Some _ ->
+ (acc_b, acc_inc, acc_names)
+ | None ->
+ let mt_opt =
+ try Some (lookup_module_type mta.mta_name)
+ with Not_found -> None
+ in
+ match mt_opt with
+ None -> (acc_b, (Name.head m.m_name) :: acc_inc,
+ (* we don't want to output warning messages for
+ "sig ... end" or "struct ... end" modules not found *)
+ (if mta.mta_name = Odoc_messages.struct_end or
+ mta.mta_name = Odoc_messages.sig_end then
+ acc_names
+ else
+ (NF_mt mta.mta_name) :: acc_names)
+ )
+ | Some mt ->
+ mta.mta_module <- Some mt ;
+ (true, acc_inc, acc_names)
+ end
+ in
+ iter_kind (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) m.m_kind
+
+and associate_in_module_type module_list (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) mt =
+ let rec iter_kind (acc_b, acc_inc, acc_names) k =
+ match k with
+ Module_type_struct elements ->
+ List.fold_left
+ (associate_in_module_element module_list mt.mt_name)
+ (acc_b, acc_inc, acc_names)
+ elements
+
+ | Module_type_functor (_, k) ->
+ iter_kind (acc_b, acc_inc, acc_names) k
+
+ | Module_type_with (k, _) ->
+ iter_kind (acc_b, acc_inc, acc_names) k
+
+ | Module_type_alias mta ->
+ begin
+ match mta.mta_module with
+ Some _ ->
+ (acc_b, acc_inc, acc_names)
+ | None ->
+ let mt_opt =
+ try Some (lookup_module_type mta.mta_name)
+ with Not_found -> None
+ in
+ match mt_opt with
+ None -> (acc_b, (Name.head mt.mt_name) :: acc_inc,
+ (* we don't want to output warning messages for
+ "sig ... end" or "struct ... end" modules not found *)
+ (if mta.mta_name = Odoc_messages.struct_end or
+ mta.mta_name = Odoc_messages.sig_end then
+ acc_names
+ else
+ (NF_mt mta.mta_name) :: acc_names)
+ )
+ | Some mt ->
+ mta.mta_module <- Some mt ;
+ (true, acc_inc, acc_names)
+ end
+ | Module_type_typeof _ ->
+ (acc_b, acc_inc, acc_names)
+ in
+ match mt.mt_kind with
+ None -> (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found)
+ | Some k -> iter_kind (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) k
+
+and associate_in_module_element module_list m_name (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) element =
+ match element with
+ Element_module m -> associate_in_module module_list (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) m
+ | Element_module_type mt -> associate_in_module_type module_list (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) mt
+ | Element_included_module im ->
+ (
+ match im.im_module with
+ Some _ -> (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found)
+ | None ->
+ let mmt_opt =
+ try Some (Mod (lookup_module im.im_name))
+ with Not_found ->
+ try Some (Modtype (lookup_module_type im.im_name))
+ with Not_found -> None
+ in
+ match mmt_opt with
+ None -> (acc_b_modif, (Name.head m_name) :: acc_incomplete_top_module_names,
+ (* we don't want to output warning messages for
+ "sig ... end" or "struct ... end" modules not found *)
+ (if im.im_name = Odoc_messages.struct_end or
+ im.im_name = Odoc_messages.sig_end then
+ acc_names_not_found
+ else
+ (NF_mmt im.im_name) :: acc_names_not_found)
+ )
+ | Some mmt ->
+ im.im_module <- Some mmt ;
+ (true, acc_incomplete_top_module_names, acc_names_not_found)
+ )
+ | Element_class cl -> associate_in_class module_list (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) cl
+ | Element_class_type ct -> associate_in_class_type module_list (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) ct
+ | Element_value _ -> (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found)
+ | Element_exception ex ->
+ (
+ match ex.ex_alias with
+ None -> (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found)
+ | Some ea ->
+ match ea.ea_ex with
+ Some _ ->
+ (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found)
+ | None ->
+ let ex_opt =
+ try Some (lookup_exception ea.ea_name)
+ with Not_found -> None
+ in
+ match ex_opt with
+ None -> (acc_b_modif, (Name.head m_name) :: acc_incomplete_top_module_names, (NF_ex ea.ea_name) :: acc_names_not_found)
+ | Some e ->
+ ea.ea_ex <- Some e ;
+ (true, acc_incomplete_top_module_names, acc_names_not_found)
+ )
+ | Element_type _ -> (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found)
+ | Element_module_comment _ -> (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found)
+
+and associate_in_class module_list (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) c =
+ let rec iter_kind (acc_b, acc_inc, acc_names) k =
+ match k with
+ Class_structure (inher_l, _) ->
+ let f (acc_b2, acc_inc2, acc_names2) ic =
+ match ic.ic_class with
+ Some _ -> (acc_b2, acc_inc2, acc_names2)
+ | None ->
+ let cct_opt =
+ try Some (Cl (lookup_class ic.ic_name))
+ with Not_found ->
+ try Some (Cltype (lookup_class_type ic.ic_name, []))
+ with Not_found -> None
+ in
+ match cct_opt with
+ None -> (acc_b2, (Name.head c.cl_name) :: acc_inc2,
+ (* we don't want to output warning messages for "object ... end" classes not found *)
+ (if ic.ic_name = Odoc_messages.object_end then acc_names2 else (NF_cct ic.ic_name) :: acc_names2))
+ | Some cct ->
+ ic.ic_class <- Some cct ;
+ (true, acc_inc2, acc_names2)
+ in
+ List.fold_left f (acc_b, acc_inc, acc_names) inher_l
+
+ | Class_apply capp ->
+ (
+ match capp.capp_class with
+ Some _ -> (acc_b, acc_inc, acc_names)
+ | None ->
+ let cl_opt =
+ try Some (lookup_class capp.capp_name)
+ with Not_found -> None
+ in
+ match cl_opt with
+ None -> (acc_b, (Name.head c.cl_name) :: acc_inc,
+ (* we don't want to output warning messages for "object ... end" classes not found *)
+ (if capp.capp_name = Odoc_messages.object_end then acc_names else (NF_c capp.capp_name) :: acc_names))
+ | Some c ->
+ capp.capp_class <- Some c ;
+ (true, acc_inc, acc_names)
+ )
+
+ | Class_constr cco ->
+ (
+ match cco.cco_class with
+ Some _ -> (acc_b, acc_inc, acc_names)
+ | None ->
+ let cl_opt =
+ try Some (lookup_class cco.cco_name)
+ with Not_found -> None
+ in
+ match cl_opt with
+ None ->
+ (
+ let clt_opt =
+ try Some (lookup_class_type cco.cco_name)
+ with Not_found -> None
+ in
+ match clt_opt with
+ None ->
+ (acc_b, (Name.head c.cl_name) :: acc_inc,
+ (* we don't want to output warning messages for "object ... end" classes not found *)
+ (if cco.cco_name = Odoc_messages.object_end then acc_names else (NF_cct cco.cco_name) :: acc_names))
+ | Some ct ->
+ cco.cco_class <- Some (Cltype (ct, [])) ;
+ (true, acc_inc, acc_names)
+ )
+ | Some c ->
+ cco.cco_class <- Some (Cl c) ;
+ (true, acc_inc, acc_names)
+ )
+ | Class_constraint (ckind, ctkind) ->
+ let (acc_b2, acc_inc2, acc_names2) = iter_kind (acc_b, acc_inc, acc_names) ckind in
+ associate_in_class_type module_list (acc_b2, acc_inc2, acc_names2)
+ { clt_name = "" ; clt_info = None ;
+ clt_type = c.cl_type ; (* should be ok *)
+ clt_type_parameters = [] ;
+ clt_virtual = false ;
+ clt_kind = ctkind ;
+ clt_loc = Odoc_types.dummy_loc }
+ in
+ iter_kind (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) c.cl_kind
+
+and associate_in_class_type module_list (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) ct =
+ let rec iter_kind (acc_b, acc_inc, acc_names) k =
+ match k with
+ Class_signature (inher_l, _) ->
+ let f (acc_b2, acc_inc2, acc_names2) ic =
+ match ic.ic_class with
+ Some _ -> (acc_b2, acc_inc2, acc_names2)
+ | None ->
+ let cct_opt =
+ try Some (Cltype (lookup_class_type ic.ic_name, []))
+ with Not_found ->
+ try Some (Cl (lookup_class ic.ic_name))
+ with Not_found -> None
+ in
+ match cct_opt with
+ None -> (acc_b2, (Name.head ct.clt_name) :: acc_inc2,
+ (* we don't want to output warning messages for "object ... end" class types not found *)
+ (if ic.ic_name = Odoc_messages.object_end then acc_names2 else (NF_cct ic.ic_name) :: acc_names2))
+ | Some cct ->
+ ic.ic_class <- Some cct ;
+ (true, acc_inc2, acc_names2)
+ in
+ List.fold_left f (acc_b, acc_inc, acc_names) inher_l
+
+ | Class_type cta ->
+ (
+ match cta.cta_class with
+ Some _ -> (acc_b, acc_inc, acc_names)
+ | None ->
+ let cct_opt =
+ try Some (Cltype (lookup_class_type cta.cta_name, []))
+ with Not_found ->
+ try Some (Cl (lookup_class cta.cta_name))
+ with Not_found -> None
+ in
+ match cct_opt with
+ None -> (acc_b, (Name.head ct.clt_name) :: acc_inc,
+ (* we don't want to output warning messages for "object ... end" class types not found *)
+ (if cta.cta_name = Odoc_messages.object_end then acc_names else (NF_cct cta.cta_name) :: acc_names))
+ | Some c ->
+ cta.cta_class <- Some c ;
+ (true, acc_inc, acc_names)
+ )
+ in
+ iter_kind (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) ct.clt_kind
+
+(*************************************************************)
+(** Association of types to elements referenced in comments .*)
+
+let ao = Odoc_misc.apply_opt
+
+let not_found_of_kind kind name =
+ (match kind with
+ RK_module -> Odoc_messages.cross_module_not_found
+ | RK_module_type -> Odoc_messages.cross_module_type_not_found
+ | RK_class -> Odoc_messages.cross_class_not_found
+ | RK_class_type -> Odoc_messages.cross_class_type_not_found
+ | RK_value -> Odoc_messages.cross_value_not_found
+ | RK_type -> Odoc_messages.cross_type_not_found
+ | RK_exception -> Odoc_messages.cross_exception_not_found
+ | RK_attribute -> Odoc_messages.cross_attribute_not_found
+ | RK_method -> Odoc_messages.cross_method_not_found
+ | RK_section _ -> Odoc_messages.cross_section_not_found
+ ) name
+
+let rec assoc_comments_text_elements parent_name module_list t_ele =
+ match t_ele with
+ | Raw _
+ | Code _
+ | CodePre _
+ | Latex _
+ | Verbatim _ -> t_ele
+ | Bold t -> Bold (assoc_comments_text parent_name module_list t)
+ | Italic t -> Italic (assoc_comments_text parent_name module_list t)
+ | Center t -> Center (assoc_comments_text parent_name module_list t)
+ | Left t -> Left (assoc_comments_text parent_name module_list t)
+ | Right t -> Right (assoc_comments_text parent_name module_list t)
+ | Emphasize t -> Emphasize (assoc_comments_text parent_name module_list t)
+ | List l -> List (List.map (assoc_comments_text parent_name module_list) l)
+ | Enum l -> Enum (List.map (assoc_comments_text parent_name module_list) l)
+ | Newline -> Newline
+ | Block t -> Block (assoc_comments_text parent_name module_list t)
+ | Superscript t -> Superscript (assoc_comments_text parent_name module_list t)
+ | Subscript t -> Subscript (assoc_comments_text parent_name module_list t)
+ | Title (n, l_opt, t) -> Title (n, l_opt, (assoc_comments_text parent_name module_list t))
+ | Link (s, t) -> Link (s, (assoc_comments_text parent_name module_list t))
+ | Ref (initial_name, None, text_option) ->
+ (
+ let rec iter_parent ?parent_name name =
+ let name = Odoc_name.normalize_name name in
+ let res =
+ match get_known_elements name with
+ [] ->
+ (
+ try
+ let re = Str.regexp ("^"^(Str.quote name)^"$") in
+ let t = Odoc_search.find_section module_list re in
+ let v2 = (name, Some (RK_section t)) in
+ add_verified v2 ;
+ (name, Some (RK_section t))
+ with
+ Not_found ->
+ (name, None)
+ )
+ | ele :: _ ->
+ (* we look for the first element with this name *)
+ let (name, kind) =
+ match ele with
+ Odoc_search.Res_module m -> (m.m_name, RK_module)
+ | Odoc_search.Res_module_type mt -> (mt.mt_name, RK_module_type)
+ | Odoc_search.Res_class c -> (c.cl_name, RK_class)
+ | Odoc_search.Res_class_type ct -> (ct.clt_name, RK_class_type)
+ | Odoc_search.Res_value v -> (v.val_name, RK_value)
+ | Odoc_search.Res_type t -> (t.ty_name, RK_type)
+ | Odoc_search.Res_exception e -> (e.ex_name, RK_exception)
+ | Odoc_search.Res_attribute a -> (a.att_value.val_name, RK_attribute)
+ | Odoc_search.Res_method m -> (m.met_value.val_name, RK_method)
+ | Odoc_search.Res_section (_ ,t)-> assert false
+ in
+ add_verified (name, Some kind) ;
+ (name, Some kind)
+ in
+ match res with
+ | (name, Some k) -> Ref (name, Some k, text_option)
+ | (_, None) ->
+ match parent_name with
+ None ->
+ Odoc_global.pwarning (Odoc_messages.cross_element_not_found initial_name);
+ Ref (initial_name, None, text_option)
+ | Some p ->
+ let parent_name =
+ match Name.father p with
+ "" -> None
+ | s -> Some s
+ in
+ iter_parent ?parent_name (Name.concat p initial_name)
+ in
+ iter_parent ~parent_name initial_name
+ )
+ | Ref (initial_name, Some kind, text_option) ->
+ (
+ let rec iter_parent ?parent_name name =
+ let v = (name, Some kind) in
+ if was_verified v then
+ Ref (name, Some kind, text_option)
+ else
+ let res =
+ match kind with
+ | RK_section _ ->
+ (
+ (** we just verify that we find an element of this kind with this name *)
+ try
+ let re = Str.regexp ("^"^(Str.quote name)^"$") in
+ let t = Odoc_search.find_section module_list re in
+ let v2 = (name, Some (RK_section t)) in
+ add_verified v2 ;
+ (name, Some (RK_section t))
+ with
+ Not_found ->
+ (name, None)
+ )
+ | _ ->
+ let f =
+ match kind with
+ RK_module -> module_exists
+ | RK_module_type -> module_type_exists
+ | RK_class -> class_exists
+ | RK_class_type -> class_type_exists
+ | RK_value -> value_exists
+ | RK_type -> type_exists
+ | RK_exception -> exception_exists
+ | RK_attribute -> attribute_exists
+ | RK_method -> method_exists
+ | RK_section _ -> assert false
+ in
+ if f name then
+ (
+ add_verified v ;
+ (name, Some kind)
+ )
+ else
+ (name, None)
+ in
+ match res with
+ | (name, Some k) -> Ref (name, Some k, text_option)
+ | (_, None) ->
+ match parent_name with
+ None ->
+ Odoc_global.pwarning (not_found_of_kind kind initial_name);
+ Ref (initial_name, None, text_option)
+ | Some p ->
+ let parent_name =
+ match Name.father p with
+ "" -> None
+ | s -> Some s
+ in
+ iter_parent ?parent_name (Name.concat p initial_name)
+ in
+ iter_parent ~parent_name initial_name
+ )
+ | Module_list l ->
+ Module_list l
+ | Index_list ->
+ Index_list
+ | Custom (s,t) -> Custom (s, (assoc_comments_text parent_name module_list t))
+ | Target (target, code) -> Target (target, code)
+
+and assoc_comments_text parent_name module_list text =
+ List.map (assoc_comments_text_elements parent_name module_list) text
+
+and assoc_comments_info parent_name module_list i =
+ let ft = assoc_comments_text parent_name module_list in
+ {
+ i with
+ i_desc = ao ft i.i_desc ;
+ i_sees = List.map (fun (sr, t) -> (sr, ft t)) i.i_sees;
+ i_deprecated = ao ft i.i_deprecated ;
+ i_params = List.map (fun (name, t) -> (name, ft t)) i.i_params;
+ i_raised_exceptions = List.map (fun (name, t) -> (name, ft t)) i.i_raised_exceptions;
+ i_return_value = ao ft i.i_return_value ;
+ i_custom = List.map (fun (tag, t) -> (tag, ft t)) i.i_custom ;
+ }
+
+
+let rec assoc_comments_module_element parent_name module_list m_ele =
+ match m_ele with
+ Element_module m ->
+ Element_module (assoc_comments_module module_list m)
+ | Element_module_type mt ->
+ Element_module_type (assoc_comments_module_type module_list mt)
+ | Element_included_module _ ->
+ m_ele (* don't go down into the aliases *)
+ | Element_class c ->
+ Element_class (assoc_comments_class module_list c)
+ | Element_class_type ct ->
+ Element_class_type (assoc_comments_class_type module_list ct)
+ | Element_value v ->
+ Element_value (assoc_comments_value module_list v)
+ | Element_exception e ->
+ Element_exception (assoc_comments_exception module_list e)
+ | Element_type t ->
+ Element_type (assoc_comments_type module_list t)
+ | Element_module_comment t ->
+ Element_module_comment (assoc_comments_text parent_name module_list t)
+
+and assoc_comments_class_element parent_name module_list c_ele =
+ match c_ele with
+ Class_attribute a ->
+ Class_attribute (assoc_comments_attribute module_list a)
+ | Class_method m ->
+ Class_method (assoc_comments_method module_list m)
+ | Class_comment t ->
+ Class_comment (assoc_comments_text parent_name module_list t)
+
+and assoc_comments_module_kind parent_name module_list mk =
+ match mk with
+ | Module_struct eles ->
+ Module_struct
+ (List.map (assoc_comments_module_element parent_name module_list) eles)
+ | Module_alias _
+ | Module_functor _ ->
+ mk
+ | Module_apply (mk1, mk2) ->
+ Module_apply (assoc_comments_module_kind parent_name module_list mk1,
+ assoc_comments_module_kind parent_name module_list mk2)
+ | Module_with (mtk, s) ->
+ Module_with (assoc_comments_module_type_kind parent_name module_list mtk, s)
+ | Module_constraint (mk1, mtk) ->
+ Module_constraint
+ (assoc_comments_module_kind parent_name module_list mk1,
+ assoc_comments_module_type_kind parent_name module_list mtk)
+ | Module_typeof _ -> mk
+ | Module_unpack _ -> mk
+
+and assoc_comments_module_type_kind parent_name module_list mtk =
+ match mtk with
+ | Module_type_struct eles ->
+ Module_type_struct
+ (List.map (assoc_comments_module_element parent_name module_list) eles)
+ | Module_type_functor (params, mtk1) ->
+ Module_type_functor
+ (params, assoc_comments_module_type_kind parent_name module_list mtk1)
+ | Module_type_alias _ ->
+ mtk
+ | Module_type_with (mtk1, s) ->
+ Module_type_with
+ (assoc_comments_module_type_kind parent_name module_list mtk1, s)
+ | Module_type_typeof _ -> mtk
+
+and assoc_comments_class_kind parent_name module_list ck =
+ match ck with
+ Class_structure (inher, eles) ->
+ let inher2 =
+ List.map
+ (fun ic ->
+ { ic with
+ ic_text = ao (assoc_comments_text parent_name module_list) ic.ic_text })
+ inher
+ in
+ Class_structure
+ (inher2, List.map (assoc_comments_class_element parent_name module_list) eles)
+
+ | Class_apply _
+ | Class_constr _ -> ck
+ | Class_constraint (ck1, ctk) ->
+ Class_constraint (assoc_comments_class_kind parent_name module_list ck1,
+ assoc_comments_class_type_kind parent_name module_list ctk)
+
+and assoc_comments_class_type_kind parent_name module_list ctk =
+ match ctk with
+ Class_signature (inher, eles) ->
+ let inher2 =
+ List.map
+ (fun ic -> { ic with
+ ic_text = ao (assoc_comments_text parent_name module_list) ic.ic_text })
+ inher
+ in
+ Class_signature (inher2, List.map (assoc_comments_class_element parent_name module_list) eles)
+
+ | Class_type _ -> ctk
+
+
+and assoc_comments_module module_list m =
+ m.m_info <- ao (assoc_comments_info m.m_name module_list) m.m_info ;
+ m.m_kind <- assoc_comments_module_kind m.m_name module_list m.m_kind ;
+ m
+
+and assoc_comments_module_type module_list mt =
+ mt.mt_info <- ao (assoc_comments_info mt.mt_name module_list) mt.mt_info ;
+ mt.mt_kind <- ao (assoc_comments_module_type_kind mt.mt_name module_list) mt.mt_kind ;
+ mt
+
+and assoc_comments_class module_list c =
+ c.cl_info <- ao (assoc_comments_info c.cl_name module_list) c.cl_info ;
+ c.cl_kind <- assoc_comments_class_kind c.cl_name module_list c.cl_kind ;
+ assoc_comments_parameter_list c.cl_name module_list c.cl_parameters;
+ c
+
+and assoc_comments_class_type module_list ct =
+ ct.clt_info <- ao (assoc_comments_info ct.clt_name module_list) ct.clt_info ;
+ ct.clt_kind <- assoc_comments_class_type_kind ct.clt_name module_list ct.clt_kind ;
+ ct
+
+and assoc_comments_parameter parent_name module_list p =
+ match p with
+ Simple_name sn ->
+ sn.sn_text <- ao (assoc_comments_text parent_name module_list) sn.sn_text
+ | Tuple (l, t) ->
+ List.iter (assoc_comments_parameter parent_name module_list) l
+
+and assoc_comments_parameter_list parent_name module_list pl =
+ List.iter (assoc_comments_parameter parent_name module_list) pl
+
+and assoc_comments_value module_list v =
+ let parent = Name.father v.val_name in
+ v.val_info <- ao (assoc_comments_info parent module_list) v.val_info ;
+ assoc_comments_parameter_list parent module_list v.val_parameters;
+ v
+
+and assoc_comments_exception module_list e =
+ let parent = Name.father e.ex_name in
+ e.ex_info <- ao (assoc_comments_info parent module_list) e.ex_info ;
+ e
+
+and assoc_comments_type module_list t =
+ let parent = Name.father t.ty_name in
+ t.ty_info <- ao (assoc_comments_info parent module_list) t.ty_info ;
+ (match t.ty_kind with
+ Type_abstract -> ()
+ | Type_variant vl ->
+ List.iter
+ (fun vc -> vc.vc_text <- ao (assoc_comments_text parent module_list) vc.vc_text)
+ vl
+ | Type_record fl ->
+ List.iter
+ (fun rf -> rf.rf_text <- ao (assoc_comments_text parent module_list) rf.rf_text)
+ fl
+ );
+ t
+
+and assoc_comments_attribute module_list a =
+ let _ = assoc_comments_value module_list a.att_value in
+ a
+
+and assoc_comments_method module_list m =
+ let parent_name = Name.father m.met_value.val_name in
+ let _ = assoc_comments_value module_list m.met_value in
+ assoc_comments_parameter_list parent_name module_list m.met_value.val_parameters;
+ m
+
+
+let associate_type_of_elements_in_comments module_list =
+ List.map (assoc_comments_module module_list) module_list
+
+
+(***********************************************************)
+(** The function which performs all the cross referencing. *)
+let associate module_list =
+ get_alias_names module_list ;
+ init_known_elements_map module_list;
+ let rec remove_doubles acc = function
+ [] -> acc
+ | h :: q ->
+ if List.mem h acc then remove_doubles acc q
+ else remove_doubles (h :: acc) q
+ in
+ let rec iter incomplete_modules =
+ let (b_modif, remaining_inc_modules, acc_names_not_found) =
+ List.fold_left (associate_in_module module_list) (false, [], []) incomplete_modules
+ in
+ let remaining_no_doubles = remove_doubles [] remaining_inc_modules in
+ let remaining_modules = List.filter
+ (fun m -> List.mem m.m_name remaining_no_doubles)
+ incomplete_modules
+ in
+ if b_modif then
+ (* we may be able to associate something else *)
+ iter remaining_modules
+ else
+ (* nothing changed, we won't be able to associate any more *)
+ acc_names_not_found
+ in
+ let names_not_found = iter module_list in
+ (
+ match names_not_found with
+ [] ->
+ ()
+ | l ->
+ List.iter
+ (fun nf ->
+ Odoc_global.pwarning
+ (
+ match nf with
+ NF_m n -> Odoc_messages.cross_module_not_found n
+ | NF_mt n -> Odoc_messages.cross_module_type_not_found n
+ | NF_mmt n -> Odoc_messages.cross_module_or_module_type_not_found n
+ | NF_c n -> Odoc_messages.cross_class_not_found n
+ | NF_ct n -> Odoc_messages.cross_class_type_not_found n
+ | NF_cct n -> Odoc_messages.cross_class_or_class_type_not_found n
+ | NF_ex n -> Odoc_messages.cross_exception_not_found n
+ );
+ )
+ l
+ ) ;
+
+ (* Find a type for each name of element which is referenced in comments. *)
+ ignore (associate_type_of_elements_in_comments module_list)
diff --git a/ocaml-binary-annot/ocamldoc/odoc_cross.mli b/ocaml-binary-annot/ocamldoc/odoc_cross.mli
new file mode 100644
index 0000000000..2fce2c48c1
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_cross.mli
@@ -0,0 +1,20 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Cross-referencing. *)
+
+val associate : Odoc_module.t_module list -> unit
+
+val assoc_comments_info :
+ string -> Odoc_module.t_module list ->
+ Odoc_types.info -> Odoc_types.info
diff --git a/ocaml-binary-annot/ocamldoc/odoc_dag2html.ml b/ocaml-binary-annot/ocamldoc/odoc_dag2html.ml
new file mode 100644
index 0000000000..cfdf9abcb4
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_dag2html.ml
@@ -0,0 +1,1750 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** The types and functions to create a html table representing a dag. Thanks to Daniel De Rauglaudre. *)
+
+type 'a dag = { mutable dag : 'a node array }
+and 'a node =
+ { mutable pare : idag list; valu : 'a; mutable chil : idag list }
+and idag = int
+;;
+
+external int_of_idag : idag -> int = "%identity";;
+external idag_of_int : int -> idag = "%identity";;
+
+type 'a table = { mutable table : 'a data array array }
+and 'a data = { mutable elem : 'a elem; mutable span : span_id }
+and 'a elem = Elem of 'a | Ghost of ghost_id | Nothing
+and span_id
+and ghost_id
+;;
+
+external span_id_of_int : int -> span_id = "%identity";;
+external int_of_span_id : span_id -> int = "%identity";;
+external ghost_id_of_int : int -> ghost_id = "%identity";;
+external int_of_ghost_id : ghost_id -> int = "%identity";;
+
+let new_span_id = let i = ref 0 in fun () -> incr i; span_id_of_int !i;;
+
+let new_ghost_id = let i = ref 0 in fun () -> incr i; ghost_id_of_int !i;;
+
+(** creating the html table structure *)
+
+type align = LeftA | CenterA | RightA;;
+type table_data = TDstring of string | TDhr of align;;
+type html_table = (int * align * table_data) array array;;
+
+let html_table_struct indi_txt phony d t =
+ let phony =
+ function
+ Elem e -> phony d.dag.(int_of_idag e)
+ | Ghost _ -> false
+ | Nothing -> true
+ in
+ let elem_txt =
+ function
+ Elem e -> indi_txt d.dag.(int_of_idag e)
+ | Ghost _ -> "|"
+ | Nothing -> "&nbsp;"
+ in
+ let bar_txt =
+ function
+ Elem _ | Ghost _ -> "|"
+ | Nothing -> "&nbsp;"
+ in
+ let all_empty i =
+ let rec loop j =
+ if j = Array.length t.table.(i) then true
+ else
+ match t.table.(i).(j).elem with
+ Nothing -> loop (j + 1)
+ | e -> if phony e then loop (j + 1) else false
+ in
+ loop 0
+ in
+ let line_elem_txt i =
+ let les =
+ let rec loop les j =
+ if j = Array.length t.table.(i) then les
+ else
+ let x = t.table.(i).(j) in
+ let next_j =
+ let rec loop j =
+ if j = Array.length t.table.(i) then j
+ else if t.table.(i).(j) = x then loop (j + 1)
+ else j
+ in
+ loop (j + 1)
+ in
+ let colspan = 3 * (next_j - j) in
+ let les = (1, LeftA, TDstring "&nbsp;") :: les in
+ let les =
+ let s =
+ if t.table.(i).(j).elem = Nothing then "&nbsp;"
+ else elem_txt t.table.(i).(j).elem
+ in
+ (colspan - 2, CenterA, TDstring s) :: les
+ in
+ let les = (1, LeftA, TDstring "&nbsp;") :: les in loop les next_j
+ in
+ loop [] 0
+ in
+ Array.of_list (List.rev les)
+ in
+ let vbars_txt k i =
+ let les =
+ let rec loop les j =
+ if j = Array.length t.table.(i) then les
+ else
+ let x = t.table.(i).(j) in
+ let next_j =
+ let rec loop j =
+ if j = Array.length t.table.(i) then j
+ else if t.table.(i).(j) = x then loop (j + 1)
+ else j
+ in
+ loop (j + 1)
+ in
+ let colspan = 3 * (next_j - j) in
+ let les = (1, LeftA, TDstring "&nbsp;") :: les in
+ let les =
+ let s =
+ if k > 0 && t.table.(k - 1).(j).elem = Nothing ||
+ t.table.(k).(j).elem = Nothing then
+ "&nbsp;"
+ else if phony t.table.(i).(j).elem then "&nbsp;"
+ else bar_txt t.table.(i).(j).elem
+ in
+ (colspan - 2, CenterA, TDstring s) :: les
+ in
+ let les = (1, LeftA, TDstring "&nbsp;") :: les in loop les next_j
+ in
+ loop [] 0
+ in
+ Array.of_list (List.rev les)
+ in
+ let alone_bar_txt i =
+ let les =
+ let rec loop les j =
+ if j = Array.length t.table.(i) then les
+ else
+ let next_j =
+ let x = t.table.(i).(j).span in
+ let rec loop j =
+ if j = Array.length t.table.(i) then j
+ else if t.table.(i).(j).span = x then loop (j + 1)
+ else j
+ in
+ loop (j + 1)
+ in
+ let colspan = 3 * (next_j - j) - 2 in
+ let les = (1, LeftA, TDstring "&nbsp;") :: les in
+ let les =
+ if t.table.(i).(j).elem = Nothing ||
+ t.table.(i + 1).(j).elem = Nothing then
+ (colspan, LeftA, TDstring "&nbsp;") :: les
+ else
+ let s =
+ let all_ph =
+ let rec loop j =
+ if j = next_j then true
+ else if phony t.table.(i + 1).(j).elem then loop (j + 1)
+ else false
+ in
+ loop j
+ in
+ if all_ph then "&nbsp;" else "|"
+ in
+ (colspan, CenterA, TDstring s) :: les
+ in
+ let les = (1, LeftA, TDstring "&nbsp;") :: les in loop les next_j
+ in
+ loop [] 0
+ in
+ Array.of_list (List.rev les)
+ in
+ let exist_several_branches i k =
+ let rec loop j =
+ if j = Array.length t.table.(i) then false
+ else
+ let x = t.table.(i).(j).span in
+ let e = t.table.(k).(j).elem in
+ let rec loop1 j =
+ if j = Array.length t.table.(i) then false
+ else if t.table.(i).(j).elem = Nothing then loop j
+ else if t.table.(i).(j).span <> x then loop j
+ else if t.table.(k).(j).elem <> e then true
+ else loop1 (j + 1)
+ in
+ loop1 (j + 1)
+ in
+ loop 0
+ in
+ let hbars_txt i k =
+ let les =
+ let rec loop les j =
+ if j = Array.length t.table.(i) then les
+ else
+ let next_j =
+ let e = t.table.(i).(j).elem in
+ let x = t.table.(i).(j).span in
+ let rec loop j =
+ if j = Array.length t.table.(i) then j
+ else if e = Nothing && t.table.(i).(j).elem = Nothing then
+ loop (j + 1)
+ else if t.table.(i).(j).span = x then loop (j + 1)
+ else j
+ in
+ loop (j + 1)
+ in
+ let rec loop1 les l =
+ if l = next_j then loop les next_j
+ else
+ let next_l =
+ let y = t.table.(k).(l) in
+ match y.elem with
+ Elem _ | Ghost _ ->
+ let rec loop l =
+ if l = Array.length t.table.(i) then l
+ else if t.table.(k).(l) = y then loop (l + 1)
+ else l
+ in
+ loop (l + 1)
+ | _ -> l + 1
+ in
+ if next_l > next_j then
+ begin
+ Printf.eprintf
+ "assert false i %d k %d l %d next_l %d next_j %d\n" i k l
+ next_l next_j;
+ flush stderr
+ end;
+ let next_l = min next_l next_j in
+ let colspan = 3 * (next_l - l) - 2 in
+ let les =
+ match t.table.(i).(l).elem, t.table.(i + 1).(l).elem with
+ Nothing, _ | _, Nothing ->
+ (colspan + 2, LeftA, TDstring "&nbsp;") :: les
+ | _ ->
+ let ph s =
+ if phony t.table.(k).(l).elem then TDstring "&nbsp;"
+ else s
+ in
+ if l = j && next_l = next_j then
+ let les = (1, LeftA, TDstring "&nbsp;") :: les in
+ let s = ph (TDstring "|") in
+ let les = (colspan, CenterA, s) :: les in
+ let les = (1, LeftA, TDstring "&nbsp;") :: les in les
+ else if l = j then
+ let les = (1, LeftA, TDstring "&nbsp;") :: les in
+ let s = ph (TDhr RightA) in
+ let les = (colspan, RightA, s) :: les in
+ let s = ph (TDhr CenterA) in
+ let les = (1, LeftA, s) :: les in les
+ else if next_l = next_j then
+ let s = ph (TDhr CenterA) in
+ let les = (1, LeftA, s) :: les in
+ let s = ph (TDhr LeftA) in
+ let les = (colspan, LeftA, s) :: les in
+ let les = (1, LeftA, TDstring "&nbsp;") :: les in les
+ else
+ let s = ph (TDhr CenterA) in
+ (colspan + 2, LeftA, s) :: les
+ in
+ loop1 les next_l
+ in
+ loop1 les j
+ in
+ loop [] 0
+ in
+ Array.of_list (List.rev les)
+ in
+ let hts =
+ let rec loop hts i =
+ if i = Array.length t.table then hts
+ else if i = Array.length t.table - 1 && all_empty i then hts
+ else
+ let hts = line_elem_txt i :: hts in
+ let hts =
+ if i < Array.length t.table - 1 then
+ let hts = vbars_txt (i + 1) i :: hts in
+ let hts =
+ if exist_several_branches i i then
+ alone_bar_txt i :: hbars_txt i i :: hts
+ else hts
+ in
+ let hts =
+ if exist_several_branches i (i + 1) &&
+ (i < Array.length t.table - 2 ||
+ not (all_empty (i + 1))) then
+ vbars_txt (i + 1) (i + 1) :: hbars_txt i (i + 1) :: hts
+ else hts
+ in
+ hts
+ else hts
+ in
+ loop hts (i + 1)
+ in
+ loop [] 0
+ in
+ Array.of_list (List.rev hts)
+;;
+
+(** transforming dag into table *)
+
+let ancestors d =
+ let rec loop i =
+ if i = Array.length d.dag then []
+ else
+ let n = d.dag.(i) in
+ if n.pare = [] then idag_of_int i :: loop (i + 1) else loop (i + 1)
+ in
+ loop 0
+;;
+
+let get_children d parents =
+ let rec merge_children children el =
+ List.fold_right
+ (fun (x, _) children ->
+ match x with
+ Elem e ->
+ let e = d.dag.(int_of_idag e) in
+ List.fold_right
+ (fun c children ->
+ if List.mem c children then children else c :: children)
+ e.chil children
+ | _ -> [])
+ el children
+ in
+ merge_children [] parents
+;;
+
+let rec get_block t i j =
+ if j = Array.length t.table.(i) then None
+ else if j = Array.length t.table.(i) - 1 then
+ let x = t.table.(i).(j) in Some ([x.elem, 1], 1, x.span)
+ else
+ let x = t.table.(i).(j) in
+ let y = t.table.(i).(j + 1) in
+ if y.span = x.span then
+ match get_block t i (j + 1) with
+ Some ((x1, c1) :: list, mpc, span) ->
+ let (list, mpc) =
+ if x1 = x.elem then (x1, c1 + 1) :: list, max mpc (c1 + 1)
+ else (x.elem, 1) :: (x1, c1) :: list, max mpc c1
+ in
+ Some (list, mpc, span)
+ | _ -> assert false
+ else Some ([x.elem, 1], 1, x.span)
+;;
+
+let group_by_common_children d list =
+ let module O = struct type t = idag;; let compare = compare;; end
+ in
+ let module S = Set.Make (O)
+ in
+ let nlcsl =
+ List.map
+ (fun id ->
+ let n = d.dag.(int_of_idag id) in
+ let cs = List.fold_right S.add n.chil S.empty in [id], cs)
+ list
+ in
+ let nlcsl =
+ let rec loop =
+ function
+ [] -> []
+ | (nl, cs) :: rest ->
+ let rec loop1 beg =
+ function
+ (nl1, cs1) :: rest1 ->
+ if S.is_empty (S.inter cs cs1) then
+ loop1 ((nl1, cs1) :: beg) rest1
+ else
+ loop ((nl @ nl1, S.union cs cs1) :: (List.rev beg @ rest1))
+ | [] -> (nl, cs) :: loop rest
+ in
+ loop1 [] rest
+ in
+ loop nlcsl
+ in
+ List.fold_right
+ (fun (nl, _) a ->
+ let span = new_span_id () in
+ List.fold_right (fun n a -> {elem = Elem n; span = span} :: a) nl a)
+ nlcsl []
+;;
+
+let copy_data d = {elem = d.elem; span = d.span};;
+
+let insert_columns t nb j =
+ let t1 = Array.create (Array.length t.table) [| |] in
+ for i = 0 to Array.length t.table - 1 do
+ let line = t.table.(i) in
+ let line1 = Array.create (Array.length line + nb) line.(0) in
+ t1.(i) <- line1;
+ let rec loop k =
+ if k = Array.length line then ()
+ else
+ begin
+ if k < j then line1.(k) <- copy_data line.(k)
+ else if k = j then
+ for r = 0 to nb do line1.(k + r) <- copy_data line.(k) done
+ else line1.(k + nb) <- copy_data line.(k);
+ loop (k + 1)
+ end
+ in
+ loop 0
+ done;
+ {table = t1}
+;;
+
+let rec gcd a b =
+ if a < b then gcd b a else if b = 0 then a else gcd b (a mod b)
+;;
+
+let treat_new_row d t =
+ let i = Array.length t.table - 1 in
+ let rec loop t i j =
+ match get_block t i j with
+ Some (parents, max_parent_colspan, span) ->
+ let children = get_children d parents in
+ let children =
+ if children = [] then [{elem = Nothing; span = new_span_id ()}]
+ else
+ List.map (fun n -> {elem = Elem n; span = new_span_id ()})
+ children
+ in
+ let simple_parents_colspan =
+ List.fold_left (fun x (_, c) -> x + c) 0 parents
+ in
+ if simple_parents_colspan mod List.length children = 0 then
+ let j = j + simple_parents_colspan in
+ let children =
+ let cnt = simple_parents_colspan / List.length children in
+ List.fold_right
+ (fun d list ->
+ let rec loop cnt list =
+ if cnt = 1 then d :: list
+ else copy_data d :: loop (cnt - 1) list
+ in
+ loop cnt list)
+ children []
+ in
+ let (t, children_rest) = loop t i j in t, children @ children_rest
+ else
+ let parent_colspan =
+ List.fold_left
+ (fun scm (_, c) -> let g = gcd scm c in scm / g * c)
+ max_parent_colspan parents
+ in
+ let (t, parents, _) =
+ List.fold_left
+ (fun (t, parents, j) (x, c) ->
+ let to_add = parent_colspan / c - 1 in
+ let t =
+ let rec loop cc t j =
+ if cc = 0 then t
+ else
+ let t = insert_columns t to_add j in
+ loop (cc - 1) t (j + to_add + 1)
+ in
+ loop c t j
+ in
+ t, (x, parent_colspan) :: parents, j + parent_colspan)
+ (t, [], j) parents
+ in
+ let parents = List.rev parents in
+ let parents_colspan = parent_colspan * List.length parents in
+ let children_colspan = List.length children in
+ let g = gcd parents_colspan children_colspan in
+ let (t, j) =
+ let cnt = children_colspan / g in
+ List.fold_left
+ (fun (t, j) (_, c) ->
+ let rec loop cc t j =
+ if cc = 0 then t, j
+ else
+ let t = insert_columns t (cnt - 1) j in
+ let j = j + cnt in loop (cc - 1) t j
+ in
+ loop c t j)
+ (t, j) parents
+ in
+ let children =
+ let cnt = parents_colspan / g in
+ List.fold_right
+ (fun d list ->
+ let rec loop cnt list =
+ if cnt = 0 then list else d :: loop (cnt - 1) list
+ in
+ loop cnt list)
+ children []
+ in
+ let (t, children_rest) = loop t i j in t, children @ children_rest
+ | None -> t, []
+ in
+ loop t i 0
+;;
+
+let down_it t i k y =
+ t.table.(Array.length t.table - 1).(k) <- t.table.(i).(k);
+ for r = i to Array.length t.table - 2 do
+ t.table.(r).(k) <- {elem = Ghost (new_ghost_id ()); span = new_span_id ()}
+ done
+;;
+
+(* equilibrate:
+ in the last line, for all elem A, make fall all As, which are located at
+ its right side above, to its line,
+ A |
+ i.e. transform all . into |
+ A....... A......A
+*)
+
+let equilibrate t =
+ let ilast = Array.length t.table - 1 in
+ let last = t.table.(ilast) in
+ let len = Array.length last in
+ let rec loop j =
+ if j = len then ()
+ else
+ match last.(j).elem with
+ Elem x ->
+ let rec loop1 i =
+ if i = ilast then loop (j + 1)
+ else
+ let rec loop2 k =
+ if k = len then loop1 (i + 1)
+ else
+ match t.table.(i).(k).elem with
+ Elem y when x = y -> down_it t i k y; loop 0
+ | _ -> loop2 (k + 1)
+ in
+ loop2 0
+ in
+ loop1 0
+ | _ -> loop (j + 1)
+ in
+ loop 0
+;;
+
+(* group_elem:
+ transform all x y into x x
+ A A A A *)
+
+let group_elem t =
+ for i = 0 to Array.length t.table - 2 do
+ for j = 1 to Array.length t.table.(0) - 1 do
+ match t.table.(i + 1).(j - 1).elem, t.table.(i + 1).(j).elem with
+ Elem x, Elem y when x = y ->
+ t.table.(i).(j).span <- t.table.(i).(j - 1).span
+ | _ -> ()
+ done
+ done
+;;
+
+(* group_ghost:
+ x x x x |a |a |a |a
+ transform all |a |b into |a |a and all x y into x x
+ y z y y A A A A *)
+
+let group_ghost t =
+ for i = 0 to Array.length t.table - 2 do
+ for j = 1 to Array.length t.table.(0) - 1 do
+ begin match t.table.(i + 1).(j - 1).elem, t.table.(i + 1).(j).elem with
+ Ghost x, Ghost _ ->
+ if t.table.(i).(j - 1).span = t.table.(i).(j).span then
+ t.table.(i + 1).(j) <-
+ {elem = Ghost x; span = t.table.(i + 1).(j - 1).span}
+ | _ -> ()
+ end;
+ match t.table.(i).(j - 1).elem, t.table.(i).(j).elem with
+ Ghost x, Ghost _ ->
+ if t.table.(i + 1).(j - 1).elem = t.table.(i + 1).(j).elem then
+ begin
+ t.table.(i).(j) <-
+ {elem = Ghost x; span = t.table.(i).(j - 1).span};
+ if i > 0 then
+ t.table.(i - 1).(j).span <- t.table.(i - 1).(j - 1).span
+ end
+ | _ -> ()
+ done
+ done
+;;
+
+(* group_children:
+ transform all A A into A A
+ x y x x *)
+
+let group_children t =
+ for i = 0 to Array.length t.table - 1 do
+ let line = t.table.(i) in
+ let len = Array.length line in
+ for j = 1 to len - 1 do
+ if line.(j).elem = line.(j - 1).elem && line.(j).elem <> Nothing then
+ line.(j).span <- line.(j - 1).span
+ done
+ done
+;;
+
+(* group_span_by_common_children:
+ in the last line, transform all
+ A B into A B
+ x y x x
+ if A and B have common children *)
+
+let group_span_by_common_children d t =
+ let module O = struct type t = idag;; let compare = compare;; end
+ in
+ let module S = Set.Make (O)
+ in
+ let i = Array.length t.table - 1 in
+ let line = t.table.(i) in
+ let rec loop j cs =
+ if j = Array.length line then ()
+ else
+ match line.(j).elem with
+ Elem id ->
+ let n = d.dag.(int_of_idag id) in
+ let curr_cs = List.fold_right S.add n.chil S.empty in
+ if S.is_empty (S.inter cs curr_cs) then loop (j + 1) curr_cs
+ else
+ begin
+ line.(j).span <- line.(j - 1).span;
+ loop (j + 1) (S.union cs curr_cs)
+ end
+ | _ -> loop (j + 1) S.empty
+ in
+ loop 0 S.empty
+;;
+
+let find_same_parents t i j1 j2 j3 j4 =
+ let rec loop i j1 j2 j3 j4 =
+ if i = 0 then i, j1, j2, j3, j4
+ else
+ let x1 = t.(i - 1).(j1) in
+ let x2 = t.(i - 1).(j2) in
+ let x3 = t.(i - 1).(j3) in
+ let x4 = t.(i - 1).(j4) in
+ if x1.span = x4.span then i, j1, j2, j3, j4
+ else
+ let j1 =
+ let rec loop j =
+ if j < 0 then 0
+ else if t.(i - 1).(j).span = x1.span then loop (j - 1)
+ else j + 1
+ in
+ loop (j1 - 1)
+ in
+ let j2 =
+ let rec loop j =
+ if j >= Array.length t.(i) then j - 1
+ else if t.(i - 1).(j).span = x2.span then loop (j + 1)
+ else j - 1
+ in
+ loop (j2 + 1)
+ in
+ let j3 =
+ let rec loop j =
+ if j < 0 then 0
+ else if t.(i - 1).(j).span = x3.span then loop (j - 1)
+ else j + 1
+ in
+ loop (j3 - 1)
+ in
+ let j4 =
+ let rec loop j =
+ if j >= Array.length t.(i) then j - 1
+ else if t.(i - 1).(j).span = x4.span then loop (j + 1)
+ else j - 1
+ in
+ loop (j4 + 1)
+ in
+ loop (i - 1) j1 j2 j3 j4
+ in
+ loop i j1 j2 j3 j4
+;;
+
+let find_linked_children t i j1 j2 j3 j4 =
+ let rec loop i j1 j2 j3 j4 =
+ if i = Array.length t - 1 then j1, j2, j3, j4
+ else
+ let x1 = t.(i).(j1) in
+ let x2 = t.(i).(j2) in
+ let x3 = t.(i).(j3) in
+ let x4 = t.(i).(j4) in
+ let j1 =
+ let rec loop j =
+ if j < 0 then 0
+ else if t.(i).(j).span = x1.span then loop (j - 1)
+ else j + 1
+ in
+ loop (j1 - 1)
+ in
+ let j2 =
+ let rec loop j =
+ if j >= Array.length t.(i) then j - 1
+ else if t.(i).(j).span = x2.span then loop (j + 1)
+ else j - 1
+ in
+ loop (j2 + 1)
+ in
+ let j3 =
+ let rec loop j =
+ if j < 0 then 0
+ else if t.(i).(j).span = x3.span then loop (j - 1)
+ else j + 1
+ in
+ loop (j3 - 1)
+ in
+ let j4 =
+ let rec loop j =
+ if j >= Array.length t.(i) then j - 1
+ else if t.(i).(j).span = x4.span then loop (j + 1)
+ else j - 1
+ in
+ loop (j4 + 1)
+ in
+ loop (i + 1) j1 j2 j3 j4
+ in
+ loop i j1 j2 j3 j4
+;;
+
+let mirror_block t i1 i2 j1 j2 =
+ for i = i1 to i2 do
+ let line = t.(i) in
+ let rec loop j1 j2 =
+ if j1 >= j2 then ()
+ else
+ let v = line.(j1) in
+ line.(j1) <- line.(j2); line.(j2) <- v; loop (j1 + 1) (j2 - 1)
+ in
+ loop j1 j2
+ done
+;;
+
+let exch_blocks t i1 i2 j1 j2 j3 j4 =
+ for i = i1 to i2 do
+ let line = t.(i) in
+ let saved = Array.copy line in
+ for j = j1 to j2 do line.(j4 - j2 + j) <- saved.(j) done;
+ for j = j3 to j4 do line.(j1 - j3 + j) <- saved.(j) done
+ done
+;;
+
+let find_block_with_parents t i jj1 jj2 jj3 jj4 =
+ let rec loop ii jj1 jj2 jj3 jj4 =
+ let (nii, njj1, njj2, njj3, njj4) =
+ find_same_parents t i jj1 jj2 jj3 jj4
+ in
+ if nii <> ii || njj1 <> jj1 || njj2 <> jj2 || njj3 <> jj3 ||
+ njj4 <> jj4 then
+ let nii = min ii nii in
+ let (jj1, jj2, jj3, jj4) =
+ find_linked_children t nii njj1 njj2 njj3 njj4
+ in
+ if njj1 <> jj1 || njj2 <> jj2 || njj3 <> jj3 || njj4 <> jj4 then
+ loop nii jj1 jj2 jj3 jj4
+ else nii, jj1, jj2, jj3, jj4
+ else ii, jj1, jj2, jj3, jj4
+ in
+ loop i jj1 jj2 jj3 jj4
+;;
+
+let push_to_right d t i j1 j2 =
+ let line = t.(i) in
+ let rec loop j =
+ if j = j2 then j - 1
+ else
+ let ini_jj1 =
+ match line.(j - 1).elem with
+ Nothing -> j - 1
+ | x ->
+ let rec same_value j =
+ if j < 0 then 0
+ else if line.(j).elem = x then same_value (j - 1)
+ else j + 1
+ in
+ same_value (j - 2)
+ in
+ let jj1 = ini_jj1 in
+ let jj2 = j - 1 in
+ let jj3 = j in
+ let jj4 =
+ match line.(j).elem with
+ Nothing -> j
+ | x ->
+ let rec same_value j =
+ if j >= Array.length line then j - 1
+ else if line.(j).elem = x then same_value (j + 1)
+ else j - 1
+ in
+ same_value (j + 1)
+ in
+ let (ii, jj1, jj2, jj3, jj4) =
+ find_block_with_parents t i jj1 jj2 jj3 jj4
+ in
+ if jj4 < j2 && jj2 < jj3 then
+ begin exch_blocks t ii i jj1 jj2 jj3 jj4; loop (jj4 + 1) end
+ else if jj4 < j2 && jj1 = ini_jj1 && jj2 <= jj4 then
+ begin mirror_block t ii i jj1 jj4; loop (jj4 + 1) end
+ else j - 1
+ in
+ loop (j1 + 1)
+;;
+
+let push_to_left d t i j1 j2 =
+ let line = t.(i) in
+ let rec loop j =
+ if j = j1 then j + 1
+ else
+ let jj1 =
+ match line.(j).elem with
+ Nothing -> j
+ | x ->
+ let rec same_value j =
+ if j < 0 then 0
+ else if line.(j).elem = x then same_value (j - 1)
+ else j + 1
+ in
+ same_value (j - 1)
+ in
+ let jj2 = j in
+ let jj3 = j + 1 in
+ let ini_jj4 =
+ match line.(j + 1).elem with
+ Nothing -> j + 1
+ | x ->
+ let rec same_value j =
+ if j >= Array.length line then j - 1
+ else if line.(j).elem = x then same_value (j + 1)
+ else j - 1
+ in
+ same_value (j + 2)
+ in
+ let jj4 = ini_jj4 in
+ let (ii, jj1, jj2, jj3, jj4) =
+ find_block_with_parents t i jj1 jj2 jj3 jj4
+ in
+ if jj1 > j1 && jj2 < jj3 then
+ begin exch_blocks t ii i jj1 jj2 jj3 jj4; loop (jj1 - 1) end
+ else if jj1 > j1 && jj4 = ini_jj4 && jj3 >= jj1 then
+ begin mirror_block t ii i jj1 jj4; loop (jj1 - 1) end
+ else j + 1
+ in
+ loop (j2 - 1)
+;;
+
+let fill_gap d t i j1 j2 =
+ let t1 =
+ let t1 = Array.copy t.table in
+ for i = 0 to Array.length t.table - 1 do
+ t1.(i) <- Array.copy t.table.(i);
+ for j = 0 to Array.length t1.(i) - 1 do
+ t1.(i).(j) <- copy_data t.table.(i).(j)
+ done
+ done;
+ t1
+ in
+ let j2 = push_to_left d t1 i j1 j2 in
+ let j1 = push_to_right d t1 i j1 j2 in
+ if j1 = j2 - 1 then
+ let line = t1.(i - 1) in
+ let x = line.(j1).span in
+ let y = line.(j2).span in
+ let rec loop y j =
+ if j >= Array.length line then ()
+ else if line.(j).span = y || t1.(i).(j).elem = t1.(i).(j - 1).elem then
+ let y = line.(j).span in
+ line.(j).span <- x;
+ if i > 0 then t1.(i - 1).(j).span <- t1.(i - 1).(j - 1).span;
+ loop y (j + 1)
+ in
+ loop y j2; Some ({table = t1}, true)
+ else None
+;;
+
+let treat_gaps d t =
+ let i = Array.length t.table - 1 in
+ let rec loop t j =
+ let line = t.table.(i) in
+ if j = Array.length line then t
+ else
+ match line.(j).elem with
+ Elem _ as y ->
+ if y = line.(j - 1).elem then loop t (j + 1)
+ else
+ let rec loop1 t j1 =
+ if j1 < 0 then loop t (j + 1)
+ else if y = line.(j1).elem then
+ match fill_gap d t i j1 j with
+ Some (t, ok) -> if ok then loop t 2 else loop t (j + 1)
+ | None -> loop t (j + 1)
+ else loop1 t (j1 - 1)
+ in
+ loop1 t (j - 2)
+ | _ -> loop t (j + 1)
+ in
+ if Array.length t.table.(i) = 1 then t else loop t 2
+;;
+
+let group_span_last_row t =
+ let row = t.table.(Array.length t.table - 1) in
+ let rec loop i =
+ if i >= Array.length row then ()
+ else
+ begin
+ begin match row.(i).elem with
+ Elem _ | Ghost _ as x ->
+ if x = row.(i - 1).elem then row.(i).span <- row.(i - 1).span
+ | _ -> ()
+ end;
+ loop (i + 1)
+ end
+ in
+ loop 1
+;;
+
+let has_phony_children phony d t =
+ let line = t.table.(Array.length t.table - 1) in
+ let rec loop j =
+ if j = Array.length line then false
+ else
+ match line.(j).elem with
+ Elem x -> if phony d.dag.(int_of_idag x) then true else loop (j + 1)
+ | _ -> loop (j + 1)
+ in
+ loop 0
+;;
+
+let tablify phony no_optim no_group d =
+ let a = ancestors d in
+ let r = group_by_common_children d a in
+ let t = {table = [| Array.of_list r |]} in
+ let rec loop t =
+ let (t, new_row) = treat_new_row d t in
+ if List.for_all (fun x -> x.elem = Nothing) new_row then t
+ else
+ let t = {table = Array.append t.table [| Array.of_list new_row |]} in
+ let t =
+ if no_group && not (has_phony_children phony d t) then t
+ else
+ let _ = if no_optim then () else equilibrate t in
+ let _ = group_elem t in
+ let _ = group_ghost t in
+ let _ = group_children t in
+ let _ = group_span_by_common_children d t in
+ let t = if no_optim then t else treat_gaps d t in
+ let _ = group_span_last_row t in t
+ in
+ loop t
+ in
+ loop t
+;;
+
+let fall d t =
+ for i = 1 to Array.length t.table - 1 do
+ let line = t.table.(i) in
+ let rec loop j =
+ if j = Array.length line then ()
+ else
+ match line.(j).elem with
+ Ghost x ->
+ let j2 =
+ let rec loop j =
+ if j = Array.length line then j - 1
+ else
+ match line.(j).elem with
+ Ghost y when y = x -> loop (j + 1)
+ | _ -> j - 1
+ in
+ loop (j + 1)
+ in
+ let i1 =
+ let rec loop i =
+ if i < 0 then i + 1
+ else
+ let line = t.table.(i) in
+ if (j = 0 || line.(j - 1).span <> line.(j).span) &&
+ (j2 = Array.length line - 1 ||
+ line.(j2 + 1).span <> line.(j2).span) then
+ loop (i - 1)
+ else i + 1
+ in
+ loop (i - 1)
+ in
+ let i1 =
+ if i1 = i then i1
+ else if i1 = 0 then i1
+ else if t.table.(i1).(j).elem = Nothing then i1
+ else i
+ in
+ if i1 < i then
+ begin
+ for k = i downto i1 + 1 do
+ for j = j to j2 do
+ t.table.(k).(j).elem <- t.table.(k - 1).(j).elem;
+ if k < i then
+ t.table.(k).(j).span <- t.table.(k - 1).(j).span
+ done
+ done;
+ for l = j to j2 do
+ if i1 = 0 || t.table.(i1 - 1).(l).elem = Nothing then
+ t.table.(i1).(l).elem <- Nothing
+ else
+ t.table.(i1).(l) <-
+ if l = j ||
+ t.table.(i1 - 1).(l - 1).span <>
+ t.table.(i1 - 1).(l).span then
+ {elem = Ghost (new_ghost_id ());
+ span = new_span_id ()}
+ else copy_data t.table.(i1).(l - 1)
+ done
+ end;
+ loop (j2 + 1)
+ | _ -> loop (j + 1)
+ in
+ loop 0
+ done
+;;
+
+let fall2_cool_right t i1 i2 i3 j1 j2 =
+ let span = t.table.(i2 - 1).(j1).span in
+ for i = i2 - 1 downto 0 do
+ for j = j1 to j2 - 1 do
+ t.table.(i).(j) <-
+ if i - i2 + i1 >= 0 then t.table.(i - i2 + i1).(j)
+ else {elem = Nothing; span = new_span_id ()}
+ done
+ done;
+ for i = Array.length t.table - 1 downto 0 do
+ for j = j2 to Array.length t.table.(i) - 1 do
+ t.table.(i).(j) <-
+ if i - i2 + i1 >= 0 then t.table.(i - i2 + i1).(j)
+ else {elem = Nothing; span = new_span_id ()}
+ done
+ done;
+ let old_span = t.table.(i2 - 1).(j1).span in
+ let rec loop j =
+ if j = Array.length t.table.(i2 - 1) then ()
+ else if t.table.(i2 - 1).(j).span = old_span then
+ begin t.table.(i2 - 1).(j).span <- span; loop (j + 1) end
+ in
+ loop j1
+;;
+
+let fall2_cool_left t i1 i2 i3 j1 j2 =
+ let span = t.table.(i2 - 1).(j2).span in
+ for i = i2 - 1 downto 0 do
+ for j = j1 + 1 to j2 do
+ t.table.(i).(j) <-
+ if i - i2 + i1 >= 0 then t.table.(i - i2 + i1).(j)
+ else {elem = Nothing; span = new_span_id ()}
+ done
+ done;
+ for i = Array.length t.table - 1 downto 0 do
+ for j = j1 downto 0 do
+ t.table.(i).(j) <-
+ if i - i2 + i1 >= 0 then t.table.(i - i2 + i1).(j)
+ else {elem = Nothing; span = new_span_id ()}
+ done
+ done;
+ let old_span = t.table.(i2 - 1).(j2).span in
+ let rec loop j =
+ if j < 0 then ()
+ else if t.table.(i2 - 1).(j).span = old_span then
+ begin t.table.(i2 - 1).(j).span <- span; loop (j - 1) end
+ in
+ loop j2
+;;
+
+let do_fall2_right t i1 i2 j1 j2 =
+ let i3 =
+ let rec loop_i i =
+ if i < 0 then 0
+ else
+ let rec loop_j j =
+ if j = Array.length t.table.(i) then loop_i (i - 1)
+ else
+ match t.table.(i).(j).elem with
+ Nothing -> loop_j (j + 1)
+ | _ -> i + 1
+ in
+ loop_j j2
+ in
+ loop_i (Array.length t.table - 1)
+ in
+ let new_height = i3 + i2 - i1 in
+ let t =
+ if new_height > Array.length t.table then
+ let rec loop cnt t =
+ if cnt = 0 then t
+ else
+ let new_line =
+ Array.init (Array.length t.table.(0))
+ (fun i -> {elem = Nothing; span = new_span_id ()})
+ in
+ let t = {table = Array.append t.table [| new_line |]} in
+ loop (cnt - 1) t
+ in
+ loop (new_height - Array.length t.table) t
+ else t
+ in
+ fall2_cool_right t i1 i2 i3 j1 j2; t
+;;
+
+let do_fall2_left t i1 i2 j1 j2 =
+ let i3 =
+ let rec loop_i i =
+ if i < 0 then 0
+ else
+ let rec loop_j j =
+ if j < 0 then loop_i (i - 1)
+ else
+ match t.table.(i).(j).elem with
+ Nothing -> loop_j (j - 1)
+ | _ -> i + 1
+ in
+ loop_j j1
+ in
+ loop_i (Array.length t.table - 1)
+ in
+ let new_height = i3 + i2 - i1 in
+ let t =
+ if new_height > Array.length t.table then
+ let rec loop cnt t =
+ if cnt = 0 then t
+ else
+ let new_line =
+ Array.init (Array.length t.table.(0))
+ (fun i -> {elem = Nothing; span = new_span_id ()})
+ in
+ let t = {table = Array.append t.table [| new_line |]} in
+ loop (cnt - 1) t
+ in
+ loop (new_height - Array.length t.table) t
+ else t
+ in
+ fall2_cool_left t i1 i2 i3 j1 j2; t
+;;
+
+let do_shorten_too_long t i1 j1 j2 =
+ for i = i1 to Array.length t.table - 2 do
+ for j = j1 to j2 - 1 do t.table.(i).(j) <- t.table.(i + 1).(j) done
+ done;
+ let i = Array.length t.table - 1 in
+ for j = j1 to j2 - 1 do
+ t.table.(i).(j) <- {elem = Nothing; span = new_span_id ()}
+ done;
+ t
+;;
+
+let try_fall2_right t i j =
+ match t.table.(i).(j).elem with
+ Ghost _ ->
+ let i1 =
+ let rec loop i =
+ if i < 0 then 0
+ else
+ match t.table.(i).(j).elem with
+ Ghost _ -> loop (i - 1)
+ | _ -> i + 1
+ in
+ loop (i - 1)
+ in
+ let separated1 =
+ let rec loop i =
+ if i < 0 then true
+ else if
+ j > 0 && t.table.(i).(j - 1).span = t.table.(i).(j).span then
+ false
+ else loop (i - 1)
+ in
+ loop (i1 - 1)
+ in
+ let j2 =
+ let x = t.table.(i).(j).span in
+ let rec loop j2 =
+ if j2 = Array.length t.table.(i) then j2
+ else
+ match t.table.(i).(j2) with
+ {elem = Ghost _; span = y} when y = x -> loop (j2 + 1)
+ | _ -> j2
+ in
+ loop (j + 1)
+ in
+ let separated2 =
+ let rec loop i =
+ if i = Array.length t.table then true
+ else if j2 = Array.length t.table.(i) then false
+ else if t.table.(i).(j2 - 1).span = t.table.(i).(j2).span then false
+ else loop (i + 1)
+ in
+ loop (i + 1)
+ in
+ if not separated1 || not separated2 then None
+ else Some (do_fall2_right t i1 (i + 1) j j2)
+ | _ -> None
+;;
+
+let try_fall2_left t i j =
+ match t.table.(i).(j).elem with
+ Ghost _ ->
+ let i1 =
+ let rec loop i =
+ if i < 0 then 0
+ else
+ match t.table.(i).(j).elem with
+ Ghost _ -> loop (i - 1)
+ | _ -> i + 1
+ in
+ loop (i - 1)
+ in
+ let separated1 =
+ let rec loop i =
+ if i < 0 then true
+ else if
+ j < Array.length t.table.(i) - 1 &&
+ t.table.(i).(j).span = t.table.(i).(j + 1).span then
+ false
+ else loop (i - 1)
+ in
+ loop (i1 - 1)
+ in
+ let j1 =
+ let x = t.table.(i).(j).span in
+ let rec loop j1 =
+ if j1 < 0 then j1
+ else
+ match t.table.(i).(j1) with
+ {elem = Ghost _; span = y} when y = x -> loop (j1 - 1)
+ | _ -> j1
+ in
+ loop (j - 1)
+ in
+ let separated2 =
+ let rec loop i =
+ if i = Array.length t.table then true
+ else if j1 < 0 then false
+ else if t.table.(i).(j1).span = t.table.(i).(j1 + 1).span then false
+ else loop (i + 1)
+ in
+ loop (i + 1)
+ in
+ if not separated1 || not separated2 then None
+ else Some (do_fall2_left t i1 (i + 1) j1 j)
+ | _ -> None
+;;
+
+let try_shorten_too_long t i j =
+ match t.table.(i).(j).elem with
+ Ghost _ ->
+ let j2 =
+ let x = t.table.(i).(j).span in
+ let rec loop j2 =
+ if j2 = Array.length t.table.(i) then j2
+ else
+ match t.table.(i).(j2) with
+ {elem = Ghost _; span = y} when y = x -> loop (j2 + 1)
+ | _ -> j2
+ in
+ loop (j + 1)
+ in
+ let i1 =
+ let rec loop i =
+ if i = Array.length t.table then i
+ else
+ match t.table.(i).(j).elem with
+ Elem _ -> loop (i + 1)
+ | _ -> i
+ in
+ loop (i + 1)
+ in
+ let i2 =
+ let rec loop i =
+ if i = Array.length t.table then i
+ else
+ match t.table.(i).(j).elem with
+ Nothing -> loop (i + 1)
+ | _ -> i
+ in
+ loop i1
+ in
+ let separated_left =
+ let rec loop i =
+ if i = i2 then true
+ else if
+ j > 0 && t.table.(i).(j).span = t.table.(i).(j - 1).span then
+ false
+ else loop (i + 1)
+ in
+ loop i
+ in
+ let separated_right =
+ let rec loop i =
+ if i = i2 then true
+ else if
+ j2 < Array.length t.table.(i) &&
+ t.table.(i).(j2 - 1).span = t.table.(i).(j2).span then
+ false
+ else loop (i + 1)
+ in
+ loop i
+ in
+ if not separated_left || not separated_right then None
+ else if i2 < Array.length t.table then None
+ else Some (do_shorten_too_long t i j j2)
+ | _ -> None
+;;
+
+let fall2_right t =
+ let rec loop_i i t =
+ if i <= 0 then t
+ else
+ let rec loop_j j t =
+ if j < 0 then loop_i (i - 1) t
+ else
+ match try_fall2_right t i j with
+ Some t -> loop_i (Array.length t.table - 1) t
+ | None -> loop_j (j - 1) t
+ in
+ loop_j (Array.length t.table.(i) - 2) t
+ in
+ loop_i (Array.length t.table - 1) t
+;;
+
+let fall2_left t =
+ let rec loop_i i t =
+ if i <= 0 then t
+ else
+ let rec loop_j j t =
+ if j >= Array.length t.table.(i) then loop_i (i - 1) t
+ else
+ match try_fall2_left t i j with
+ Some t -> loop_i (Array.length t.table - 1) t
+ | None -> loop_j (j + 1) t
+ in
+ loop_j 1 t
+ in
+ loop_i (Array.length t.table - 1) t
+;;
+
+let shorten_too_long t =
+ let rec loop_i i t =
+ if i <= 0 then t
+ else
+ let rec loop_j j t =
+ if j >= Array.length t.table.(i) then loop_i (i - 1) t
+ else
+ match try_shorten_too_long t i j with
+ Some t -> loop_i (Array.length t.table - 1) t
+ | None -> loop_j (j + 1) t
+ in
+ loop_j 1 t
+ in
+ loop_i (Array.length t.table - 1) t
+;;
+
+(* top_adjust:
+ deletes all empty rows that might have appeared on top of the table
+ after the falls *)
+
+let top_adjust t =
+ let di =
+ let rec loop i =
+ if i = Array.length t.table then i
+ else
+ let rec loop_j j =
+ if j = Array.length t.table.(i) then loop (i + 1)
+ else if t.table.(i).(j).elem <> Nothing then i
+ else loop_j (j + 1)
+ in
+ loop_j 0
+ in
+ loop 0
+ in
+ if di > 0 then
+ begin
+ for i = 0 to Array.length t.table - 1 - di do
+ t.table.(i) <- t.table.(i + di)
+ done;
+ {table = Array.sub t.table 0 (Array.length t.table - di)}
+ end
+ else t
+;;
+
+(* bottom_adjust:
+ deletes all empty rows that might have appeared on bottom of the table
+ after the falls *)
+
+let bottom_adjust t =
+ let last_i =
+ let rec loop i =
+ if i < 0 then i
+ else
+ let rec loop_j j =
+ if j = Array.length t.table.(i) then loop (i - 1)
+ else if t.table.(i).(j).elem <> Nothing then i
+ else loop_j (j + 1)
+ in
+ loop_j 0
+ in
+ loop (Array.length t.table - 1)
+ in
+ if last_i < Array.length t.table - 1 then
+ {table = Array.sub t.table 0 (last_i + 1)}
+ else t
+;;
+
+(* invert *)
+
+let invert_dag d =
+ let d = {dag = Array.copy d.dag} in
+ for i = 0 to Array.length d.dag - 1 do
+ let n = d.dag.(i) in
+ d.dag.(i) <-
+ {pare = List.map (fun x -> x) n.chil; valu = n.valu;
+ chil = List.map (fun x -> x) n.pare}
+ done;
+ d
+;;
+
+let invert_table t =
+ let t' = {table = Array.copy t.table} in
+ let len = Array.length t.table in
+ for i = 0 to len - 1 do
+ t'.table.(i) <-
+ Array.init (Array.length t.table.(0))
+ (fun j ->
+ let d = t.table.(len - 1 - i).(j) in
+ {elem = d.elem; span = d.span});
+ if i < len - 1 then
+ for j = 0 to Array.length t'.table.(i) - 1 do
+ t'.table.(i).(j).span <- t.table.(len - 2 - i).(j).span
+ done
+ done;
+ t'
+;;
+
+(* main *)
+
+let table_of_dag phony no_optim invert no_group d =
+ let d = if invert then invert_dag d else d in
+ let t = tablify phony no_optim no_group d in
+ let t = if invert then invert_table t else t in
+ let _ = fall () t in
+ let t = fall2_right t in
+ let t = fall2_left t in
+ let t = shorten_too_long t in
+ let t = top_adjust t in let t = bottom_adjust t in t
+;;
+
+
+let version = "1.01";;
+
+(* input dag *)
+
+let strip_spaces str =
+ let start =
+ let rec loop i =
+ if i == String.length str then i
+ else
+ match str.[i] with
+ ' ' | '\013' | '\n' | '\t' -> loop (i + 1)
+ | _ -> i
+ in
+ loop 0
+ in
+ let stop =
+ let rec loop i =
+ if i == -1 then i + 1
+ else
+ match str.[i] with
+ ' ' | '\013' | '\n' | '\t' -> loop (i - 1)
+ | _ -> i + 1
+ in
+ loop (String.length str - 1)
+ in
+ if start == 0 && stop == String.length str then str
+ else if start > stop then ""
+ else String.sub str start (stop - start)
+;;
+
+let rec get_line ic =
+ try
+ let line = input_line ic in
+ if String.length line > 0 && line.[0] = '#' then get_line ic
+ else Some (strip_spaces line)
+ with
+ End_of_file -> None
+;;
+
+let input_dag ic =
+ let rec find cnt s =
+ function
+ n :: nl ->
+ if n.valu = s then n, idag_of_int cnt else find (cnt - 1) s nl
+ | [] -> raise Not_found
+ in
+ let add_node pl cl nl cnt =
+ let cl = List.rev cl in
+ let pl = List.rev pl in
+ let (pl, pnl, nl, cnt) =
+ List.fold_left
+ (fun (pl, pnl, nl, cnt) p ->
+ try
+ let (n, p) = find (cnt - 1) p nl in p :: pl, n :: pnl, nl, cnt
+ with
+ Not_found ->
+ let n = {pare = []; valu = p; chil = []} in
+ let p = idag_of_int cnt in p :: pl, n :: pnl, n :: nl, cnt + 1)
+ ([], [], nl, cnt) pl
+ in
+ let pl = List.rev pl in
+ let (cl, nl, cnt) =
+ List.fold_left
+ (fun (cl, nl, cnt) c ->
+ try
+ let (n, c) = find (cnt - 1) c nl in
+ n.pare <- n.pare @ pl; c :: cl, nl, cnt
+ with
+ Not_found ->
+ let n = {pare = pl; valu = c; chil = []} in
+ let c = idag_of_int cnt in c :: cl, n :: nl, cnt + 1)
+ ([], nl, cnt) cl
+ in
+ let cl = List.rev cl in
+ List.iter (fun p -> p.chil <- p.chil @ cl) pnl; nl, cnt
+ in
+ let rec input_parents nl pl cnt =
+ function
+ Some "" -> input_parents nl pl cnt (get_line ic)
+ | Some line ->
+ begin match line.[0] with
+ 'o' ->
+ let p =
+ strip_spaces (String.sub line 1 (String.length line - 1))
+ in
+ if p = "" then failwith line
+ else input_parents nl (p :: pl) cnt (get_line ic)
+ | '-' ->
+ if pl = [] then failwith line
+ else input_children nl pl [] cnt (Some line)
+ | _ -> failwith line
+ end
+ | None -> if pl = [] then nl, cnt else failwith "end of file 1"
+ and input_children nl pl cl cnt =
+ function
+ Some "" -> input_children nl pl cl cnt (get_line ic)
+ | Some line ->
+ begin match line.[0] with
+ 'o' ->
+ if cl = [] then failwith line
+ else
+ let (nl, cnt) = add_node pl cl nl cnt in
+ input_parents nl [] cnt (Some line)
+ | '-' ->
+ let c =
+ strip_spaces (String.sub line 1 (String.length line - 1))
+ in
+ if c = "" then failwith line
+ else input_children nl pl (c :: cl) cnt (get_line ic)
+ | _ -> failwith line
+ end
+ | None ->
+ if cl = [] then failwith "end of file 2" else add_node pl cl nl cnt
+ in
+ let (nl, _) = input_parents [] [] 0 (get_line ic) in
+ {dag = Array.of_list (List.rev nl)}
+;;
+
+(* testing *)
+
+let map_dag f d =
+ let a =
+ Array.map (fun d -> {pare = d.pare; valu = f d.valu; chil = d.chil}) d.dag
+ in
+ {dag = a}
+;;
+
+let tag_dag d =
+ let c = ref 'A' in
+ map_dag
+ (fun v ->
+ let v = !c in
+ c :=
+ if !c = 'Z' then 'a'
+ else if !c = 'z' then '1'
+ else Char.chr (Char.code !c + 1);
+ String.make 1 v)
+ d
+;;
+
+(* *)
+
+let phony _ = false;;
+let indi_txt n = n.valu;;
+
+let string_table border hts =
+ let buf = Buffer.create 30 in
+ Printf.bprintf buf "<center><table border=%d" border;
+ Printf.bprintf buf " cellspacing=0 cellpadding=0>\n";
+ for i = 0 to Array.length hts - 1 do
+ Printf.bprintf buf "<tr>\n";
+ for j = 0 to Array.length hts.(i) - 1 do
+ let (colspan, align, td) = hts.(i).(j) in
+ Printf.bprintf buf "<td";
+ if colspan = 1 && (td = TDstring "&nbsp;" || td = TDhr CenterA) then ()
+ else Printf.bprintf buf " colspan=%d" colspan;
+ begin match align, td with
+ LeftA, TDhr LeftA -> Printf.bprintf buf " align=left"
+ | LeftA, _ -> ()
+ | CenterA, _ -> Printf.bprintf buf " align=center"
+ | RightA, _ -> Printf.bprintf buf " align=right"
+ end;
+ Printf.bprintf buf ">";
+ begin match td with
+ TDstring s -> Printf.bprintf buf "%s" s
+ | TDhr align ->
+ Printf.bprintf buf "<hr noshade size=1";
+ begin match align with
+ LeftA -> Printf.bprintf buf " width=\"50%%\" align=left"
+ | RightA -> Printf.bprintf buf " width=\"50%%\" align=right"
+ | _ -> ()
+ end;
+ Printf.bprintf buf ">";
+ ()
+ end;
+ Printf.bprintf buf "</td>\n";
+ ()
+ done
+ done;
+ Printf.bprintf buf "</table></center>\n";
+ Buffer.contents buf
+;;
+
+let fname = ref "";;
+let invert = ref false;;
+let char = ref false;;
+let border = ref 0;;
+let no_optim = ref false;;
+let no_group = ref false;;
+
+let html_of_dag d =
+ let t = table_of_dag phony !no_optim !invert !no_group d in
+ let hts = html_table_struct indi_txt phony d t in
+ string_table !border hts
+;;
+
+
+(********************************* Max's code **********************************)
+(** This function takes a list of classes and a list of class types
+ and create the associate dag. *)
+let create_class_dag cl_list clt_list =
+ let module M = Odoc_info.Class in
+ (* the list of all the classes concerned *)
+ let cl_list2 = List.map (fun c -> (c.M.cl_name, Some (M.Cl c))) cl_list in
+ let clt_list2 = List.map (fun ct -> (ct.M.clt_name, Some (M.Cltype (ct, [])))) clt_list in
+ let list = cl_list2 @ clt_list2 in
+ let all_classes =
+ let rec iter list2 =
+ List.fold_left
+ (fun acc -> fun (name, cct_opt) ->
+ let l =
+ match cct_opt with
+ None -> []
+ | Some (M.Cl c) ->
+ iter
+ (List.map
+ (fun inh ->(inh.M.ic_name, inh.M.ic_class))
+ (match c.M.cl_kind with
+ M.Class_structure (inher_l, _) ->
+ inher_l
+ | _ ->
+ []
+ )
+ )
+ | Some (M.Cltype (ct, _)) ->
+ iter
+ (List.map
+ (fun inh ->(inh.M.ic_name, inh.M.ic_class))
+ (match ct.M.clt_kind with
+ M.Class_signature (inher_l, _) ->
+ inher_l
+ | _ ->
+ []
+ )
+ )
+ in
+ (name, cct_opt) :: (acc @ l)
+ )
+ []
+ list2
+ in
+ iter list
+ in
+ let rec distinct acc = function
+ [] ->
+ acc
+ | (name, cct_opt) :: q ->
+ if List.exists (fun (name2, _) -> name = name2) acc then
+ distinct acc q
+ else
+ distinct ((name, cct_opt) :: acc) q
+ in
+ let distinct_classes = distinct [] all_classes in
+ let liste_index =
+ let rec f n = function
+ [] -> []
+ | (name, _) :: q -> (name, n) :: (f (n+1) q)
+ in
+ f 0 distinct_classes
+ in
+ let array1 = Array.of_list distinct_classes in
+ (* create the dag array, filling parents and values *)
+ let fmap (name, cct_opt) =
+ { pare = List.map
+ (fun inh -> List.assoc inh.M.ic_name liste_index )
+ (match cct_opt with
+ None -> []
+ | Some (M.Cl c) ->
+ (match c.M.cl_kind with
+ M.Class_structure (inher_l, _) ->
+ inher_l
+ | _ ->
+ []
+ )
+ | Some (M.Cltype (ct, _)) ->
+ (match ct.M.clt_kind with
+ M.Class_signature (inher_l, _) ->
+ inher_l
+ | _ ->
+ []
+ )
+ );
+ valu = (name, cct_opt) ;
+ chil = []
+ }
+ in
+ let dag = { dag = Array.map fmap array1 } in
+ (* fill the children *)
+ let fiter i node =
+ let l = Array.to_list dag.dag in
+ let l2 = List.map (fun n -> n.valu)
+ (List.filter (fun n -> List.mem i n.pare) l)
+ in
+ node.chil <- List.map (fun (name,_) -> List.assoc name liste_index) l2
+ in
+ Array.iteri fiter dag.dag;
+ dag
diff --git a/ocaml-binary-annot/ocamldoc/odoc_dag2html.mli b/ocaml-binary-annot/ocamldoc/odoc_dag2html.mli
new file mode 100644
index 0000000000..d377bce2ee
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_dag2html.mli
@@ -0,0 +1,29 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** The types and functions to create a html table representing a dag.
+ Thanks to Daniel de Rauglaudre. *)
+
+type 'a dag = { mutable dag : 'a node array }
+and 'a node =
+ { mutable pare : idag list; valu : 'a; mutable chil : idag list }
+and idag = int
+
+(** This function returns the html code to represent the given dag. *)
+val html_of_dag : string dag -> string
+
+(** This function takes a list of classes and a list of class types and creates the associate dag. *)
+val create_class_dag :
+ Odoc_info.Class.t_class list ->
+ Odoc_info.Class.t_class_type list ->
+ (Odoc_info.Name.t * Odoc_info.Class.cct option) dag
diff --git a/ocaml-binary-annot/ocamldoc/odoc_dep.ml b/ocaml-binary-annot/ocamldoc/odoc_dep.ml
new file mode 100644
index 0000000000..86a0f247c9
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_dep.ml
@@ -0,0 +1,219 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Top modules dependencies. *)
+
+module StrS = Depend.StringSet
+module Module = Odoc_module
+module Type = Odoc_type
+
+let set_to_list s =
+ let l = ref [] in
+ StrS.iter (fun e -> l := e :: !l) s;
+ !l
+
+let impl_dependencies ast =
+ Depend.free_structure_names := StrS.empty;
+ Depend.add_use_file StrS.empty [Parsetree.Ptop_def ast];
+ set_to_list !Depend.free_structure_names
+
+let intf_dependencies ast =
+ Depend.free_structure_names := StrS.empty;
+ Depend.add_signature StrS.empty ast;
+ set_to_list !Depend.free_structure_names
+
+
+module Dep =
+ struct
+ type id = string
+
+ module S = Set.Make (struct type t = string let compare = compare end)
+
+ let set_to_list s =
+ let l = ref [] in
+ S.iter (fun e -> l := e :: !l) s;
+ !l
+
+ type node = {
+ id : id ;
+ mutable near : S.t ; (** fils directs *)
+ mutable far : (id * S.t) list ; (** fils indirects, par quel fils *)
+ reflex : bool ; (** reflexive or not, we keep
+ information here to remove the node itself from its direct children *)
+ }
+
+ type graph = node list
+
+ let make_node s children =
+ let set = List.fold_right
+ S.add
+ children
+ S.empty
+ in
+ { id = s;
+ near = S.remove s set ;
+ far = [] ;
+ reflex = List.mem s children ;
+ }
+
+ let get_node graph s =
+ try List.find (fun n -> n.id = s) graph
+ with Not_found ->
+ make_node s []
+
+ let rec trans_closure graph acc n =
+ if S.mem n.id acc then
+ acc
+ else
+ (* optimisation plus tard : utiliser le champ far si non vide ? *)
+ S.fold
+ (fun child -> fun acc2 ->
+ trans_closure graph acc2 (get_node graph child))
+ n.near
+ (S.add n.id acc)
+
+ let node_trans_closure graph n =
+ let far = List.map
+ (fun child ->
+ let set = trans_closure graph S.empty (get_node graph child) in
+ (child, set)
+ )
+ (set_to_list n.near)
+ in
+ n.far <- far
+
+ let compute_trans_closure graph =
+ List.iter (node_trans_closure graph) graph
+
+ let prune_node graph node =
+ S.iter
+ (fun child ->
+ let set_reachables = List.fold_left
+ (fun acc -> fun (ch, reachables) ->
+ if child = ch then
+ acc
+ else
+ S.union acc reachables
+ )
+ S.empty
+ node.far
+ in
+ let set = S.remove node.id set_reachables in
+ if S.exists (fun n2 -> S.mem child (get_node graph n2).near) set then
+ (
+ node.near <- S.remove child node.near ;
+ node.far <- List.filter (fun (ch,_) -> ch <> child) node.far
+ )
+ else
+ ()
+ )
+ node.near;
+ if node.reflex then
+ node.near <- S.add node.id node.near
+ else
+ ()
+
+ let kernel graph =
+ (* compute transitive closure *)
+ compute_trans_closure graph ;
+
+ (* remove edges to keep a transitive kernel *)
+ List.iter (prune_node graph) graph;
+
+ graph
+
+ end
+
+(** [type_deps t] returns the list of fully qualified type names
+ [t] depends on. *)
+let type_deps t =
+ let module T = Odoc_type in
+ let l = ref [] in
+ let re = Str.regexp "\\([A-Z]\\([a-zA-Z_'0-9]\\)*\\.\\)+\\([a-z][a-zA-Z_'0-9]*\\)" in
+ let f s =
+ let s2 = Str.matched_string s in
+ l := s2 :: !l ;
+ s2
+ in
+ (match t.T.ty_kind with
+ T.Type_abstract -> ()
+ | T.Type_variant cl ->
+ List.iter
+ (fun c ->
+ List.iter
+ (fun e ->
+ let s = Odoc_print.string_of_type_expr e in
+ ignore (Str.global_substitute re f s)
+ )
+ c.T.vc_args
+ )
+ cl
+ | T.Type_record rl ->
+ List.iter
+ (fun r ->
+ let s = Odoc_print.string_of_type_expr r.T.rf_type in
+ ignore (Str.global_substitute re f s)
+ )
+ rl
+ );
+
+ (match t.T.ty_manifest with
+ None -> ()
+ | Some e ->
+ let s = Odoc_print.string_of_type_expr e in
+ ignore (Str.global_substitute re f s)
+ );
+
+ !l
+
+(** Modify the modules depencies of the given list of modules,
+ to get the minimum transitivity kernel. *)
+let kernel_deps_of_modules modules =
+ let graph = List.map
+ (fun m -> Dep.make_node m.Module.m_name m.Module.m_top_deps)
+ modules
+ in
+ let k = Dep.kernel graph in
+ List.iter
+ (fun m ->
+ let node = Dep.get_node k m.Module.m_name in
+ m.Module.m_top_deps <-
+ List.filter (fun m2 -> Dep.S.mem m2 node.Dep.near) m.Module.m_top_deps)
+ modules
+
+(** Return the list of dependencies between the given types,
+ in the form of a list [(type, names of types it depends on)].
+ @param kernel indicates if we must keep only the transitivity kernel
+ of the dependencies. Default is [false].
+*)
+let deps_of_types ?(kernel=false) types =
+ let deps_pre = List.map (fun t -> (t, type_deps t)) types in
+ let deps =
+ if kernel then
+ (
+ let graph = List.map
+ (fun (t, names) -> Dep.make_node t.Type.ty_name names)
+ deps_pre
+ in
+ let k = Dep.kernel graph in
+ List.map
+ (fun t ->
+ let node = Dep.get_node k t.Type.ty_name in
+ (t, Dep.set_to_list node.Dep.near)
+ )
+ types
+ )
+ else
+ deps_pre
+ in
+ deps
diff --git a/ocaml-binary-annot/ocamldoc/odoc_dot.ml b/ocaml-binary-annot/ocamldoc/odoc_dot.ml
new file mode 100644
index 0000000000..8d4fa2f3c9
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_dot.ml
@@ -0,0 +1,146 @@
+(***********************************************************************)
+(* Ocamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Definition of a class which outputs a dot file showing
+ top modules dependencies.*)
+
+open Odoc_info
+
+module F = Format
+
+let dot_include_all = ref false
+
+let dot_types = ref false
+
+let dot_reduce = ref false
+
+let dot_colors = ref (List.flatten Odoc_messages.default_dot_colors)
+
+module Generator =
+struct
+
+(** This class generates a dot file showing the top modules dependencies. *)
+class dot =
+ object (self)
+
+ (** To store the colors associated to locations of modules. *)
+ val mutable loc_colors = []
+
+ (** the list of modules we know. *)
+ val mutable modules = []
+
+ (** Colors to use when finding new locations of modules. *)
+ val mutable colors = !dot_colors
+
+ (** Graph header. *)
+ method header =
+ "digraph G {\n"^
+ " size=\"10,7.5\";\n"^
+ " ratio=\"fill\";\n"^
+ " rotate=90;\n"^
+ " fontsize=\"12pt\";\n"^
+ " rankdir = TB ;\n"
+
+ method get_one_color =
+ match colors with
+ [] -> None
+ | h :: q ->
+ colors <- q ;
+ Some h
+
+ method node_color s =
+ try Some (List.assoc s loc_colors)
+ with
+ Not_found ->
+ match self#get_one_color with
+ None -> None
+ | Some c ->
+ loc_colors <- (s, c) :: loc_colors ;
+ Some c
+
+ method print_module_atts fmt m =
+ match self#node_color (Filename.dirname m.Module.m_file) with
+ None -> ()
+ | Some col -> F.fprintf fmt "\"%s\" [style=filled, color=%s];\n" m.Module.m_name col
+
+ method print_type_atts fmt t =
+ match self#node_color (Name.father t.Type.ty_name) with
+ None -> ()
+ | Some col -> F.fprintf fmt "\"%s\" [style=filled, color=%s];\n" t.Type.ty_name col
+
+ method print_one_dep fmt src dest =
+ F.fprintf fmt "\"%s\" -> \"%s\";\n" src dest
+
+ method generate_for_module fmt m =
+ let l = List.filter
+ (fun n ->
+ !dot_include_all or
+ (List.exists (fun m -> m.Module.m_name = n) modules))
+ m.Module.m_top_deps
+ in
+ self#print_module_atts fmt m;
+ List.iter (self#print_one_dep fmt m.Module.m_name) l
+
+ method generate_for_type fmt (t, l) =
+ self#print_type_atts fmt t;
+ List.iter
+ (self#print_one_dep fmt t.Type.ty_name)
+ l
+
+ method generate_types types =
+ try
+ let oc = open_out !Global.out_file in
+ let fmt = F.formatter_of_out_channel oc in
+ F.fprintf fmt "%s" self#header;
+ let graph = Odoc_info.Dep.deps_of_types
+ ~kernel: !dot_reduce
+ types
+ in
+ List.iter (self#generate_for_type fmt) graph;
+ F.fprintf fmt "}\n" ;
+ F.pp_print_flush fmt ();
+ close_out oc
+ with
+ Sys_error s ->
+ raise (Failure s)
+
+ method generate_modules modules_list =
+ try
+ modules <- modules_list ;
+ let oc = open_out !Global.out_file in
+ let fmt = F.formatter_of_out_channel oc in
+ F.fprintf fmt "%s" self#header;
+
+ if !dot_reduce then
+ Odoc_info.Dep.kernel_deps_of_modules modules_list;
+
+ List.iter (self#generate_for_module fmt) modules_list;
+ F.fprintf fmt "}\n" ;
+ F.pp_print_flush fmt ();
+ close_out oc
+ with
+ Sys_error s ->
+ raise (Failure s)
+
+ (** Generate the dot code in the file {!Odoc_info.Args.out_file}. *)
+ method generate (modules_list : Odoc_info.Module.t_module list) =
+ colors <- !dot_colors;
+ if !dot_types then
+ self#generate_types (Odoc_info.Search.types modules_list)
+ else
+ self#generate_modules modules_list
+ end
+end
+
+module type Dot_generator = module type of Generator
+
diff --git a/ocaml-binary-annot/ocamldoc/odoc_env.ml b/ocaml-binary-annot/ocamldoc/odoc_env.ml
new file mode 100644
index 0000000000..a108cf416a
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_env.ml
@@ -0,0 +1,249 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Environment for finding complete names from relative names. *)
+
+let print_DEBUG s = print_string s ; print_newline ();;
+
+module Name = Odoc_name
+
+(** relative name * complete name *)
+type env_element = Name.t * Name.t
+
+type env = {
+ env_values : env_element list ;
+ env_types : env_element list ;
+ env_class_types : env_element list ;
+ env_classes : env_element list ;
+ env_modules : env_element list ;
+ env_module_types : env_element list ;
+ env_exceptions : env_element list ;
+ }
+
+let empty = {
+ env_values = [] ;
+ env_types = [] ;
+ env_class_types = [] ;
+ env_classes = [] ;
+ env_modules = [] ;
+ env_module_types = [] ;
+ env_exceptions = [] ;
+ }
+
+(** Add a signature to an environment. *)
+let rec add_signature env root ?rel signat =
+ let qualify id = Name.concat root (Name.from_ident id) in
+ let rel_name id =
+ let n = Name.from_ident id in
+ match rel with
+ None -> n
+ | Some r -> Name.concat r n
+ in
+ let f env item =
+ match item with
+ Types.Tsig_value (ident, _) -> { env with env_values = (rel_name ident, qualify ident) :: env.env_values }
+ | Types.Tsig_type (ident,_,_) -> { env with env_types = (rel_name ident, qualify ident) :: env.env_types }
+ | Types.Tsig_exception (ident, _) -> { env with env_exceptions = (rel_name ident, qualify ident) :: env.env_exceptions }
+ | Types.Tsig_module (ident, modtype, _) ->
+ let env2 =
+ match modtype with (* A VOIR : le cas où c'est un identificateur, dans ce cas on n'a pas de signature *)
+ Types.Tmty_signature s -> add_signature env (qualify ident) ~rel: (rel_name ident) s
+ | _ -> env
+ in
+ { env2 with env_modules = (rel_name ident, qualify ident) :: env2.env_modules }
+ | Types.Tsig_modtype (ident, modtype_decl) ->
+ let env2 =
+ match modtype_decl with
+ Types.Tmodtype_abstract ->
+ env
+ | Types.Tmodtype_manifest modtype ->
+ match modtype with
+ (* A VOIR : le cas où c'est un identificateur, dans ce cas on n'a pas de signature *)
+ Types.Tmty_signature s -> add_signature env (qualify ident) ~rel: (rel_name ident) s
+ | _ -> env
+ in
+ { env2 with env_module_types = (rel_name ident, qualify ident) :: env2.env_module_types }
+ | Types.Tsig_class (ident, _, _) -> { env with env_classes = (rel_name ident, qualify ident) :: env.env_classes }
+ | Types.Tsig_cltype (ident, _, _) -> { env with env_class_types = (rel_name ident, qualify ident) :: env.env_class_types }
+ in
+ List.fold_left f env signat
+
+let add_exception env full_name =
+ let simple_name = Name.simple full_name in
+ { env with env_exceptions = (simple_name, full_name) :: env.env_exceptions }
+
+let add_type env full_name =
+ let simple_name = Name.simple full_name in
+ { env with env_types = (simple_name, full_name) :: env.env_types }
+
+let add_value env full_name =
+ let simple_name = Name.simple full_name in
+ { env with env_values = (simple_name, full_name) :: env.env_values }
+
+let add_module env full_name =
+ let simple_name = Name.simple full_name in
+ { env with env_modules = (simple_name, full_name) :: env.env_modules }
+
+let add_module_type env full_name =
+ let simple_name = Name.simple full_name in
+ { env with env_module_types = (simple_name, full_name) :: env.env_module_types }
+
+let add_class env full_name =
+ let simple_name = Name.simple full_name in
+ { env with
+ env_classes = (simple_name, full_name) :: env.env_classes ;
+ (* we also add a type 'cause the class name may appear as a type *)
+ env_types = (simple_name, full_name) :: env.env_types
+ }
+
+let add_class_type env full_name =
+ let simple_name = Name.simple full_name in
+ { env with
+ env_class_types = (simple_name, full_name) :: env.env_class_types ;
+ (* we also add a type 'cause the class type name may appear as a type *)
+ env_types = (simple_name, full_name) :: env.env_types
+ }
+
+let full_module_name env n =
+ try List.assoc n env.env_modules
+ with Not_found ->
+ print_DEBUG ("Module "^n^" not found with env=");
+ List.iter (fun (sn, fn) -> print_DEBUG ("("^sn^", "^fn^")")) env.env_modules;
+ n
+
+let full_module_type_name env n =
+ try List.assoc n env.env_module_types
+ with Not_found ->
+ print_DEBUG ("Module "^n^" not found with env=");
+ List.iter (fun (sn, fn) -> print_DEBUG ("("^sn^", "^fn^")")) env.env_modules;
+ n
+
+let full_module_or_module_type_name env n =
+ try List.assoc n env.env_modules
+ with Not_found -> full_module_type_name env n
+
+let full_type_name env n =
+ try
+ let full = List.assoc n env.env_types in
+(** print_string ("type "^n^" is "^full);
+ print_newline ();*)
+ full
+ with Not_found ->
+(** print_string ("type "^n^" not found");
+ print_newline ();*)
+ n
+
+let full_value_name env n =
+ try List.assoc n env.env_values
+ with Not_found -> n
+
+let full_exception_name env n =
+ try List.assoc n env.env_exceptions
+ with Not_found ->
+ print_DEBUG ("Exception "^n^" not found with env=");
+ List.iter (fun (sn, fn) -> print_DEBUG ("("^sn^", "^fn^")")) env.env_exceptions;
+ n
+
+let full_class_name env n =
+ try List.assoc n env.env_classes
+ with Not_found ->
+ print_DEBUG ("Class "^n^" not found with env=");
+ List.iter (fun (sn, fn) -> print_DEBUG ("("^sn^", "^fn^")")) env.env_classes;
+ n
+
+let full_class_type_name env n =
+ try List.assoc n env.env_class_types
+ with Not_found ->
+ print_DEBUG ("Class type "^n^" not found with env=");
+ List.iter (fun (sn, fn) -> print_DEBUG ("("^sn^", "^fn^")")) env.env_class_types;
+ n
+
+let full_class_or_class_type_name env n =
+ try List.assoc n env.env_classes
+ with Not_found -> full_class_type_name env n
+
+let print_env_types env =
+ List.iter (fun (s1,s2) -> Printf.printf "%s = %s\n" s1 s2) env.env_types
+
+let subst_type env t =
+(*
+ print_string "Odoc_env.subst_type\n";
+ print_env_types env ;
+ print_newline ();
+*)
+ Printtyp.mark_loops t;
+ let deja_vu = ref [] in
+ let rec iter t =
+ if List.memq t !deja_vu then () else begin
+ deja_vu := t :: !deja_vu;
+ Btype.iter_type_expr iter t;
+ match t.Types.desc with
+ | Types.Tconstr (p, [ty], a) when Path.same p Predef.path_option ->
+ ()
+ | Types.Tconstr (p, l, a) ->
+ let new_p =
+ Odoc_name.to_path (full_type_name env (Odoc_name.from_path p)) in
+ t.Types.desc <- Types.Tconstr (new_p, l, a)
+ | Types.Tpackage (p, n, l) ->
+ let new_p =
+ Odoc_name.to_path (full_module_type_name env (Odoc_name.from_path p)) in
+ t.Types.desc <- Types.Tpackage (new_p, n, l)
+ | Types.Tobject (_, ({contents=Some(p,tyl)} as r)) ->
+ let new_p =
+ Odoc_name.to_path (full_type_name env (Odoc_name.from_path p)) in
+ r := Some (new_p, tyl)
+ | Types.Tvariant ({Types.row_name=Some(p, tyl)} as row) ->
+ let new_p =
+ Odoc_name.to_path (full_type_name env (Odoc_name.from_path p)) in
+ t.Types.desc <-
+ Types.Tvariant {row with Types.row_name=Some(new_p, tyl)}
+ | _ ->
+ ()
+ end
+ in
+ iter t;
+ t
+
+
+let subst_module_type env t =
+ let rec iter t =
+ match t with
+ Types.Tmty_ident p ->
+ let new_p = Odoc_name.to_path (full_module_type_name env (Odoc_name.from_path p)) in
+ Types.Tmty_ident new_p
+ | Types.Tmty_signature _ ->
+ t
+ | Types.Tmty_functor (id, mt1, mt2) ->
+ Types.Tmty_functor (id, iter mt1, iter mt2)
+ in
+ iter t
+
+let subst_class_type env t =
+ let rec iter t =
+ match t with
+ Types.Tcty_constr (p,texp_list,ct) ->
+ let new_p = Odoc_name.to_path (full_type_name env (Odoc_name.from_path p)) in
+ let new_texp_list = List.map (subst_type env) texp_list in
+ let new_ct = iter ct in
+ Types.Tcty_constr (new_p, new_texp_list, new_ct)
+ | Types.Tcty_signature cs ->
+ (* on ne s'occupe pas des vals et methods *)
+ t
+ | Types.Tcty_fun (l, texp, ct) ->
+ let new_texp = subst_type env texp in
+ let new_ct = iter ct in
+ Types.Tcty_fun (l, new_texp, new_ct)
+ in
+ iter t
+
+(* eof $Id$ *)
diff --git a/ocaml-binary-annot/ocamldoc/odoc_env.mli b/ocaml-binary-annot/ocamldoc/odoc_env.mli
new file mode 100644
index 0000000000..75c0b38a4d
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_env.mli
@@ -0,0 +1,76 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Environment for finding complete names from relative names. *)
+
+(** An environment of known names,
+ from simple name to complete name. *)
+type env
+
+(** The empty environment. *)
+val empty : env
+
+(** Extending an environment *)
+
+val add_signature : env -> string -> ?rel:string -> Types.signature -> env
+val add_exception : env -> Odoc_name.t -> env
+val add_type : env -> Odoc_name.t -> env
+val add_value : env -> Odoc_name.t -> env
+val add_module : env -> Odoc_name.t -> env
+val add_module_type : env -> Odoc_name.t -> env
+val add_class : env -> Odoc_name.t -> env
+val add_class_type : env -> Odoc_name.t -> env
+
+(** Retrieving fully qualified names from an environment *)
+
+(** Get the fully qualified module name from a name.*)
+val full_module_name : env -> Odoc_name.t -> Odoc_name.t
+
+(** Get the fully qualified module type name from a name.*)
+val full_module_type_name : env -> Odoc_name.t -> Odoc_name.t
+
+(** Get the fully qualified module or module type name from a name.
+ We look for a module type if we don't find a module.*)
+val full_module_or_module_type_name : env -> Odoc_name.t -> Odoc_name.t
+
+(** Get the fully qualified type name from a name.*)
+val full_type_name : env -> Odoc_name.t -> Odoc_name.t
+
+(** Get the fully qualified value name from a name.*)
+val full_value_name : env -> Odoc_name.t -> Odoc_name.t
+
+(** Get the fully qualified exception name from a name.*)
+val full_exception_name : env -> Odoc_name.t -> Odoc_name.t
+
+(** Get the fully qualified class name from a name.*)
+val full_class_name : env -> Odoc_name.t -> Odoc_name.t
+
+(** Get the fully qualified class type name from a name.*)
+val full_class_type_name : env -> Odoc_name.t -> Odoc_name.t
+
+(** Get the fully qualified class or class type name from a name.*)
+val full_class_or_class_type_name : env -> Odoc_name.t -> Odoc_name.t
+
+(** Substitutions *)
+
+(** Replace the [Path.t] by a complete [Path.t] in a [Types.type_expr].*)
+val subst_type : env -> Types.type_expr -> Types.type_expr
+
+(** Replace the [Path.t] by a complete [Path.t] in a [Types.module_type].*)
+val subst_module_type : env -> Types.module_type -> Types.module_type
+
+(** Replace the [Path.t] by a complete [Path.t] in a [Types.class_type].
+ Also empty the structures to get only [object end] when the type
+ is printed.
+*)
+val subst_class_type : env -> Types.class_type -> Types.class_type
diff --git a/ocaml-binary-annot/ocamldoc/odoc_exception.ml b/ocaml-binary-annot/ocamldoc/odoc_exception.ml
new file mode 100644
index 0000000000..74a2fb5a20
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_exception.ml
@@ -0,0 +1,30 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Representation and manipulation of exceptions. *)
+
+module Name = Odoc_name
+
+type exception_alias = {
+ ea_name : Name.t ;
+ mutable ea_ex : t_exception option ;
+ }
+
+and t_exception = {
+ ex_name : Name.t ;
+ mutable ex_info : Odoc_types.info option ; (** optional user information *)
+ ex_args : Types.type_expr list ; (** the types of the parameters *)
+ ex_alias : exception_alias option ;
+ mutable ex_loc : Odoc_types.location ;
+ mutable ex_code : string option ;
+ }
diff --git a/ocaml-binary-annot/ocamldoc/odoc_gen.ml b/ocaml-binary-annot/ocamldoc/odoc_gen.ml
new file mode 100644
index 0000000000..260aed4df4
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_gen.ml
@@ -0,0 +1,38 @@
+(** *)
+
+class type doc_generator =
+ object method generate : Odoc_module.t_module list -> unit end;;
+
+module type Base = sig
+ class generator : doc_generator
+ end;;
+
+type generator =
+ | Html of (module Odoc_html.Html_generator)
+ | Latex of (module Odoc_latex.Latex_generator)
+ | Texi of (module Odoc_texi.Texi_generator)
+ | Man of (module Odoc_man.Man_generator)
+ | Dot of (module Odoc_dot.Dot_generator)
+ | Other of (module Base)
+;;
+
+let get_minimal_generator = function
+ Html m ->
+ let module M = (val m : Odoc_html.Html_generator) in
+ (new M.html :> doc_generator)
+| Latex m ->
+ let module M = (val m : Odoc_latex.Latex_generator) in
+ (new M.latex :> doc_generator)
+| Man m ->
+ let module M = (val m : Odoc_man.Man_generator) in
+ (new M.man :> doc_generator)
+| Texi m ->
+ let module M = (val m : Odoc_texi.Texi_generator) in
+ (new M.texi :> doc_generator)
+| Dot m ->
+ let module M = (val m : Odoc_dot.Dot_generator) in
+ (new M.dot :> doc_generator)
+| Other m ->
+ let module M = (val m : Base) in
+ new M.generator
+ ;; \ No newline at end of file
diff --git a/ocaml-binary-annot/ocamldoc/odoc_gen.mli b/ocaml-binary-annot/ocamldoc/odoc_gen.mli
new file mode 100644
index 0000000000..1200a7c420
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_gen.mli
@@ -0,0 +1,22 @@
+(** The types of generators. *)
+
+(** The minimal class type of documentation generators. *)
+class type doc_generator =
+ object method generate : Odoc_module.t_module list -> unit end;;
+
+(** The module type of minimal generators. *)
+module type Base = sig
+ class generator : doc_generator
+ end;;
+
+(** Various ways to create a generator. *)
+type generator =
+ | Html of (module Odoc_html.Html_generator)
+ | Latex of (module Odoc_latex.Latex_generator)
+ | Texi of (module Odoc_texi.Texi_generator)
+ | Man of (module Odoc_man.Man_generator)
+ | Dot of (module Odoc_dot.Dot_generator)
+ | Other of (module Base)
+;;
+
+val get_minimal_generator : generator -> doc_generator \ No newline at end of file
diff --git a/ocaml-binary-annot/ocamldoc/odoc_global.ml b/ocaml-binary-annot/ocamldoc/odoc_global.ml
new file mode 100644
index 0000000000..0b2ab6a2bb
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_global.ml
@@ -0,0 +1,89 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Global variables. *)
+
+(* Tell ocaml compiler not to generate files. *)
+let _ = Clflags.dont_write_files := true
+
+open Clflags
+
+type source_file =
+ Impl_file of string
+ | Intf_file of string
+ | Text_file of string
+
+let include_dirs = Clflags.include_dirs
+
+let errors = ref 0
+
+let warn_error = ref false
+
+let pwarning s =
+ if !Odoc_config.print_warnings then prerr_endline (Odoc_messages.warning^": "^s);
+ if !warn_error then incr errors
+
+let merge_options = ref ([] : Odoc_types.merge_option list)
+
+let classic = Clflags.classic
+
+let dump = ref (None : string option)
+
+let load = ref ([] : string list)
+
+(** Allow arbitrary recursive types. *)
+let recursive_types = Clflags.recursive_types
+
+(** Optional preprocessor command. *)
+let preprocessor = Clflags.preprocessor
+
+let sort_modules = ref false
+
+let no_custom_tags = ref false
+
+let no_stop = ref false
+
+let remove_stars = ref false
+
+let keep_code = ref false
+
+let inverse_merge_ml_mli = ref false
+
+let filter_with_module_constraints = ref true
+
+let hidden_modules = ref ([] : string list)
+
+let files = ref []
+
+
+
+let out_file = ref Odoc_messages.default_out_file
+
+let verbose = ref false
+
+let target_dir = ref Filename.current_dir_name
+
+let title = ref (None : string option)
+
+let intro_file = ref (None : string option)
+
+let with_header = ref true
+
+let with_trailer = ref true
+
+let with_toc = ref true
+
+let with_index = ref true
+
+
+
diff --git a/ocaml-binary-annot/ocamldoc/odoc_global.mli b/ocaml-binary-annot/ocamldoc/odoc_global.mli
new file mode 100644
index 0000000000..454bb8535b
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_global.mli
@@ -0,0 +1,104 @@
+(***********************************************************************)
+(* Ocamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Global variables. *)
+
+(** The kind of source file in arguments. *)
+type source_file =
+ Impl_file of string
+ | Intf_file of string
+ | Text_file of string
+
+(** The include_dirs in the OCaml compiler. *)
+val include_dirs : string list ref
+
+(** Optional preprocessor command to pass to ocaml compiler. *)
+val preprocessor : string option ref
+
+(** Recursive types flag to passe to ocaml compiler. *)
+val recursive_types : bool ref
+
+(** The merge options to be used. *)
+val merge_options : Odoc_types.merge_option list ref
+
+(** Classic mode or not. *)
+val classic : bool ref
+
+(** The optional file name to dump the collected information into.*)
+val dump : string option ref
+
+(** The list of information files to load. *)
+val load : string list ref
+
+(** We must sort the list of top modules or not.*)
+val sort_modules : bool ref
+
+(** We must not stop at the stop special comments. Default is false (we stop).*)
+val no_stop : bool ref
+
+(** We must raise an exception when we find an unknown @-tag. *)
+val no_custom_tags : bool ref
+
+(** We must remove the the first characters of each comment line, until the first asterisk '*'. *)
+val remove_stars : bool ref
+
+(** To keep the code while merging, when we have both .ml and .mli files for a module. *)
+val keep_code : bool ref
+
+(** To inverse implementation and interface files when merging. *)
+val inverse_merge_ml_mli : bool ref
+
+(** To filter module elements according to module type constraints. *)
+val filter_with_module_constraints : bool ref
+
+(** The list of module names to hide. *)
+val hidden_modules : string list ref
+
+(** The files to be analysed. *)
+val files : source_file list ref
+(** A counter for errors. *)
+val errors : int ref
+
+(** Indicate if a warning is an error. *)
+val warn_error : bool ref
+
+(** Print the given warning, adding it to the list of {!errors}
+if {!warn_error} is [true]. *)
+val pwarning : string -> unit
+
+(** The file used by the generators outputting only one file. *)
+val out_file : string ref
+
+(** Verbose mode or not. *)
+val verbose : bool ref
+
+(** The optional file whose content can be used as intro text. *)
+val intro_file : string option ref
+
+(** The optional title to use in the generated documentation. *)
+val title : string option ref
+
+(** The directory where files have to be generated. *)
+val target_dir : string ref
+
+(** The flag which indicates if we must generate a table of contents. *)
+val with_toc : bool ref
+
+(** The flag which indicates if we must generate an index. *)
+val with_index : bool ref
+
+(** The flag which indicates if we must generate a header.*)
+val with_header : bool ref
+
+(** The flag which indicates if we must generate a trailer.*)
+val with_trailer : bool ref
diff --git a/ocaml-binary-annot/ocamldoc/odoc_html.ml b/ocaml-binary-annot/ocamldoc/odoc_html.ml
new file mode 100644
index 0000000000..fecef08502
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_html.ml
@@ -0,0 +1,2577 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Generation of html documentation.*)
+
+let print_DEBUG s = print_string s ; print_newline ()
+
+open Odoc_info
+open Parameter
+open Value
+open Type
+open Exception
+open Class
+open Module
+
+let with_parameter_list = ref false
+let css_style = ref None
+let index_only = ref false
+let colorize_code = ref false
+let html_short_functors = ref false
+
+
+(** The functions used for naming files and html marks.*)
+module Naming =
+ struct
+ (** The prefix for types marks. *)
+ let mark_type = "TYPE"
+
+ (** The prefix for functions marks. *)
+ let mark_function = "FUN"
+
+ (** The prefix for exceptions marks. *)
+ let mark_exception = "EXCEPTION"
+
+ (** The prefix for values marks. *)
+ let mark_value = "VAL"
+
+ (** The prefix for attributes marks. *)
+ let mark_attribute = "ATT"
+
+ (** The prefix for methods marks. *)
+ let mark_method = "METHOD"
+
+ (** The prefix for code files.. *)
+ let code_prefix = "code_"
+
+ (** The prefix for type files.. *)
+ let type_prefix = "type_"
+
+ (** Return the two html files names for the given module or class name.*)
+ let html_files name =
+ let qual =
+ try
+ let i = String.rindex name '.' in
+ match name.[i + 1] with
+ | 'A'..'Z' -> ""
+ | _ -> "-c"
+ with Not_found -> ""
+ in
+ let prefix = name^qual in
+ let html_file = prefix^".html" in
+ let html_frame_file = prefix^"-frame.html" in
+ (html_file, html_frame_file)
+
+ (** Return the target for the given prefix and simple name. *)
+ let target pref simple_name = pref^simple_name
+
+ (** Return the complete link target (file#target) for the given prefix string and complete name.*)
+ let complete_target pref complete_name =
+ let simple_name = Name.simple complete_name in
+ let module_name =
+ let s = Name.father complete_name in
+ if s = "" then simple_name else s
+ in
+ let (html_file, _) = html_files module_name in
+ html_file^"#"^(target pref simple_name)
+
+ (** Return the link target for the given type. *)
+ let type_target t = target mark_type (Name.simple t.ty_name)
+
+ (** Return the complete link target for the given type. *)
+ let complete_type_target t = complete_target mark_type t.ty_name
+
+ (** Return the link target for the given exception. *)
+ let exception_target e = target mark_exception (Name.simple e.ex_name)
+
+ (** Return the complete link target for the given exception. *)
+ let complete_exception_target e = complete_target mark_exception e.ex_name
+
+ (** Return the link target for the given value. *)
+ let value_target v = target mark_value (Name.simple v.val_name)
+
+ (** Return the given value name where symbols accepted in infix values
+ are replaced by strings, to avoid clashes with the filesystem.*)
+ let subst_infix_symbols name =
+ let len = String.length name in
+ let buf = Buffer.create len in
+ let ch c = Buffer.add_char buf c in
+ let st s = Buffer.add_string buf s in
+ for i = 0 to len - 1 do
+ match name.[i] with
+ | '|' -> st "_pipe_"
+ | '<' -> st "_lt_"
+ | '>' -> st "_gt_"
+ | '@' -> st "_at_"
+ | '^' -> st "_exp_"
+ | '&' -> st "_amp_"
+ | '+' -> st "_plus_"
+ | '-' -> st "_minus_"
+ | '*' -> st "_star_"
+ | '/' -> st "_slash_"
+ | '$' -> st "_dollar_"
+ | '%' -> st "_percent_"
+ | '=' -> st "_equal_"
+ | ':' -> st "_column_"
+ | '~' -> st "_tilde_"
+ | '!' -> st "_bang_"
+ | '?' -> st "_questionmark_"
+ | c -> ch c
+ done;
+ Buffer.contents buf
+
+ (** Return the complete link target for the given value. *)
+ let complete_value_target v = complete_target mark_value v.val_name
+
+ (** Return the complete filename for the code of the given value. *)
+ let file_code_value_complete_target v =
+ let f = code_prefix^mark_value^(subst_infix_symbols v.val_name)^".html" in
+ f
+
+ (** Return the link target for the given attribute. *)
+ let attribute_target a = target mark_attribute (Name.simple a.att_value.val_name)
+
+ (** Return the complete link target for the given attribute. *)
+ let complete_attribute_target a = complete_target mark_attribute a.att_value.val_name
+
+ (** Return the complete filename for the code of the given attribute. *)
+ let file_code_attribute_complete_target a =
+ let f = code_prefix^mark_attribute^a.att_value.val_name^".html" in
+ f
+
+ (** Return the link target for the given method. *)
+ let method_target m = target mark_method (Name.simple m.met_value.val_name)
+
+ (** Return the complete link target for the given method. *)
+ let complete_method_target m = complete_target mark_method m.met_value.val_name
+
+ (** Return the complete filename for the code of the given method. *)
+ let file_code_method_complete_target m =
+ let f = code_prefix^mark_method^m.met_value.val_name^".html" in
+ f
+
+ (** Return the link target for the given label section. *)
+ let label_target l = target "" l
+
+ (** Return the complete link target for the given section label. *)
+ let complete_label_target l = complete_target "" l
+
+ (** Return the complete filename for the code of the type of the
+ given module or module type name. *)
+ let file_type_module_complete_target name =
+ let f = type_prefix^name^".html" in
+ f
+
+ (** Return the complete filename for the code of the
+ given module name. *)
+ let file_code_module_complete_target name =
+ let f = code_prefix^name^".html" in
+ f
+
+ (** Return the complete filename for the code of the type of the
+ given class or class type name. *)
+ let file_type_class_complete_target name =
+ let f = type_prefix^name^".html" in
+ f
+ end
+
+module StringSet = Set.Make (struct type t = string let compare = compare end)
+
+(** A class with a method to colorize a string which represents OCaml code. *)
+class ocaml_code =
+ object(self)
+ method html_of_code b ?(with_pre=true) code =
+ Odoc_ocamlhtml.html_of_code b ~with_pre: with_pre code
+ end
+
+let new_buf () = Buffer.create 1024
+let bp = Printf.bprintf
+let bs = Buffer.add_string
+
+
+(** Generation of html code from text structures. *)
+class virtual text =
+ object (self)
+ (** We want to display colorized code. *)
+ inherit ocaml_code
+
+ (** Escape the strings which would clash with html syntax, and
+ make some replacements (double newlines replaced by <br>). *)
+ method escape s = Odoc_ocamlhtml.escape_base s
+
+ method keep_alpha_num s =
+ let len = String.length s in
+ let buf = Buffer.create len in
+ for i = 0 to len - 1 do
+ match s.[i] with
+ 'a'..'z' | 'A'..'Z' | '0'..'9' -> Buffer.add_char buf s.[i]
+ | _ -> ()
+ done;
+ Buffer.contents buf
+
+ (** Return a label created from the first sentence of a text. *)
+ method label_of_text t=
+ let t2 = Odoc_info.first_sentence_of_text t in
+ let s = Odoc_info.string_of_text t2 in
+ let s2 = self#keep_alpha_num s in
+ s2
+
+ (** Create a label for the associated title.
+ Return the label specified by the user or a label created
+ from the title level and the first sentence of the title. *)
+ method create_title_label (n,label_opt,t) =
+ match label_opt with
+ Some s -> s
+ | None -> Printf.sprintf "%d_%s" n (self#label_of_text t)
+
+ (** Print the html code corresponding to the [text] parameter. *)
+ method html_of_text b t =
+ List.iter (self#html_of_text_element b) t
+
+ (** Print the html code for the [text_element] in parameter. *)
+ method html_of_text_element b te =
+ print_DEBUG "text::html_of_text_element";
+ match te with
+ | Odoc_info.Raw s -> self#html_of_Raw b s
+ | Odoc_info.Code s -> self#html_of_Code b s
+ | Odoc_info.CodePre s -> self#html_of_CodePre b s
+ | Odoc_info.Verbatim s -> self#html_of_Verbatim b s
+ | Odoc_info.Bold t -> self#html_of_Bold b t
+ | Odoc_info.Italic t -> self#html_of_Italic b t
+ | Odoc_info.Emphasize t -> self#html_of_Emphasize b t
+ | Odoc_info.Center t -> self#html_of_Center b t
+ | Odoc_info.Left t -> self#html_of_Left b t
+ | Odoc_info.Right t -> self#html_of_Right b t
+ | Odoc_info.List tl -> self#html_of_List b tl
+ | Odoc_info.Enum tl -> self#html_of_Enum b tl
+ | Odoc_info.Newline -> self#html_of_Newline b
+ | Odoc_info.Block t -> self#html_of_Block b t
+ | Odoc_info.Title (n, l_opt, t) -> self#html_of_Title b n l_opt t
+ | Odoc_info.Latex s -> self#html_of_Latex b s
+ | Odoc_info.Link (s, t) -> self#html_of_Link b s t
+ | Odoc_info.Ref (name, ref_opt, text_opt) ->
+ self#html_of_Ref b name ref_opt text_opt
+ | Odoc_info.Superscript t -> self#html_of_Superscript b t
+ | Odoc_info.Subscript t -> self#html_of_Subscript b t
+ | Odoc_info.Module_list l -> self#html_of_Module_list b l
+ | Odoc_info.Index_list -> self#html_of_Index_list b
+ | Odoc_info.Custom (s,t) -> self#html_of_custom_text b s t
+ | Odoc_info.Target (target, code) -> self#html_of_Target b ~target ~code
+
+ method html_of_custom_text b s t = ()
+
+ method html_of_Target b ~target ~code =
+ if String.lowercase target = "html" then bs b code else ()
+
+ method html_of_Raw b s = bs b (self#escape s)
+
+ method html_of_Code b s =
+ if !colorize_code then
+ self#html_of_code b ~with_pre: false s
+ else
+ (
+ bs b "<code class=\"";
+ bs b Odoc_ocamlhtml.code_class ;
+ bs b "\">";
+ bs b (self#escape s);
+ bs b "</code>"
+ )
+
+ method html_of_CodePre =
+ let remove_useless_newlines s =
+ let len = String.length s in
+ let rec iter_first n =
+ if n >= len then
+ None
+ else
+ match s.[n] with
+ | '\n' -> iter_first (n+1)
+ | _ -> Some n
+ in
+ match iter_first 0 with
+ None -> ""
+ | Some first ->
+ let rec iter_last n =
+ if n <= first then
+ None
+ else
+ match s.[n] with
+ '\t' -> iter_last (n-1)
+ | _ -> Some n
+ in
+ match iter_last (len-1) with
+ None -> String.sub s first 1
+ | Some last -> String.sub s first ((last-first)+1)
+ in
+ fun b s ->
+ if !colorize_code then
+ (
+ bs b "<pre></pre>";
+ self#html_of_code b (remove_useless_newlines s);
+ bs b "<pre></pre>"
+ )
+ else
+ (
+ bs b "<pre><code class=\"";
+ bs b Odoc_ocamlhtml.code_class;
+ bs b "\">" ;
+ bs b (self#escape (remove_useless_newlines s));
+ bs b "</code></pre>"
+ )
+
+ method html_of_Verbatim b s =
+ bs b "<pre>";
+ bs b (self#escape s);
+ bs b "</pre>"
+
+ method html_of_Bold b t =
+ bs b "<b>";
+ self#html_of_text b t;
+ bs b "</b>"
+
+ method html_of_Italic b t =
+ bs b "<i>" ;
+ self#html_of_text b t;
+ bs b "</i>"
+
+ method html_of_Emphasize b t =
+ bs b "<em>" ;
+ self#html_of_text b t ;
+ bs b "</em>"
+
+ method html_of_Center b t =
+ bs b "<center>";
+ self#html_of_text b t;
+ bs b "</center>"
+
+ method html_of_Left b t =
+ bs b "<div align=left>";
+ self#html_of_text b t;
+ bs b "</div>"
+
+ method html_of_Right b t =
+ bs b "<div align=right>";
+ self#html_of_text b t;
+ bs b "</div>"
+
+ method html_of_List b tl =
+ bs b "<ul>\n";
+ List.iter
+ (fun t -> bs b "<li>"; self#html_of_text b t; bs b "</li>\n")
+ tl;
+ bs b "</ul>\n"
+
+ method html_of_Enum b tl =
+ bs b "<OL>\n";
+ List.iter
+ (fun t -> bs b "<li>"; self#html_of_text b t; bs b"</li>\n")
+ tl;
+ bs b "</OL>\n"
+
+ method html_of_Newline b = bs b "\n<p>\n"
+
+ method html_of_Block b t =
+ bs b "<blockquote>\n";
+ self#html_of_text b t;
+ bs b "</blockquote>\n"
+
+ method html_of_Title b n label_opt t =
+ let label1 = self#create_title_label (n, label_opt, t) in
+ bp b "<span id=\"%s\">" (Naming.label_target label1);
+ let (tag_o, tag_c) =
+ if n > 6 then
+ (Printf.sprintf "div class=\"h%d\"" n, "div")
+ else
+ let t = Printf.sprintf "h%d" n in (t, t)
+ in
+ bs b "<";
+ bs b tag_o;
+ bs b ">";
+ self#html_of_text b t;
+ bs b "</";
+ bs b tag_c;
+ bs b ">";
+ bs b "</span>"
+
+ method html_of_Latex b _ = ()
+ (* don't care about LaTeX stuff in HTML. *)
+
+ method html_of_Link b s t =
+ bs b "<a href=\"";
+ bs b s ;
+ bs b "\">";
+ self#html_of_text b t;
+ bs b "</a>"
+
+ method html_of_Ref b name ref_opt text_opt =
+ match ref_opt with
+ None ->
+ let text =
+ match text_opt with
+ None -> [Odoc_info.Code name]
+ | Some t -> t
+ in
+ self#html_of_text b text
+ | Some kind ->
+ let h name = Odoc_info.Code (Odoc_info.use_hidden_modules name) in
+ let (target, text) =
+ match kind with
+ Odoc_info.RK_module
+ | Odoc_info.RK_module_type
+ | Odoc_info.RK_class
+ | Odoc_info.RK_class_type ->
+ let (html_file, _) = Naming.html_files name in
+ (html_file, h name)
+ | Odoc_info.RK_value -> (Naming.complete_target Naming.mark_value name, h name)
+ | Odoc_info.RK_type -> (Naming.complete_target Naming.mark_type name, h name)
+ | Odoc_info.RK_exception -> (Naming.complete_target Naming.mark_exception name, h name)
+ | Odoc_info.RK_attribute -> (Naming.complete_target Naming.mark_attribute name, h name)
+ | Odoc_info.RK_method -> (Naming.complete_target Naming.mark_method name, h name)
+ | Odoc_info.RK_section t -> (Naming.complete_label_target name,
+ Odoc_info.Italic [Raw (Odoc_info.string_of_text t)])
+ in
+ let text =
+ match text_opt with
+ None -> [text]
+ | Some text -> text
+ in
+ bs b ("<a href=\""^target^"\">");
+ self#html_of_text b text;
+ bs b "</a>"
+
+ method html_of_Superscript b t =
+ bs b "<sup class=\"superscript\">";
+ self#html_of_text b t;
+ bs b "</sup>"
+
+ method html_of_Subscript b t =
+ bs b "<sub class=\"subscript\">";
+ self#html_of_text b t;
+ bs b "</sub>"
+
+ method virtual html_of_info_first_sentence : _
+
+ method html_of_Module_list b l =
+ bs b "<br>\n<table class=\"indextable\">\n";
+ List.iter
+ (fun name ->
+ bs b "<tr><td>";
+ (
+ try
+ let m =
+ List.find (fun m -> m.m_name = name) self#list_modules
+ in
+ let (html, _) = Naming.html_files m.m_name in
+ bp b "<a href=\"%s\">%s</a></td>" html m.m_name;
+ bs b "<td>";
+ self#html_of_info_first_sentence b m.m_info;
+ with
+ Not_found ->
+ Odoc_global.pwarning (Odoc_messages.cross_module_not_found name);
+ bp b "%s</td><td>" name
+ );
+ bs b "</td></tr>\n"
+ )
+ l;
+ bs b "</table>\n"
+
+ method html_of_Index_list b =
+ let index_if_not_empty l url m =
+ match l with
+ [] -> ()
+ | _ -> bp b "<a href=\"%s\">%s</a><br>\n" url m
+ in
+ index_if_not_empty self#list_types self#index_types Odoc_messages.index_of_types;
+ index_if_not_empty self#list_exceptions self#index_exceptions Odoc_messages.index_of_exceptions;
+ index_if_not_empty self#list_values self#index_values Odoc_messages.index_of_values;
+ index_if_not_empty self#list_attributes self#index_attributes Odoc_messages.index_of_attributes;
+ index_if_not_empty self#list_methods self#index_methods Odoc_messages.index_of_methods;
+ index_if_not_empty self#list_classes self#index_classes Odoc_messages.index_of_classes;
+ index_if_not_empty self#list_class_types self#index_class_types Odoc_messages.index_of_class_types;
+ index_if_not_empty self#list_modules self#index_modules Odoc_messages.index_of_modules;
+ index_if_not_empty self#list_module_types self#index_module_types Odoc_messages.index_of_module_types
+
+ method virtual list_types : Odoc_info.Type.t_type list
+ method virtual index_types : string
+ method virtual list_exceptions : Odoc_info.Exception.t_exception list
+ method virtual index_exceptions : string
+ method virtual list_values : Odoc_info.Value.t_value list
+ method virtual index_values : string
+ method virtual list_attributes : Odoc_info.Value.t_attribute list
+ method virtual index_attributes : string
+ method virtual list_methods : Odoc_info.Value.t_method list
+ method virtual index_methods : string
+ method virtual list_classes : Odoc_info.Class.t_class list
+ method virtual index_classes : string
+ method virtual list_class_types : Odoc_info.Class.t_class_type list
+ method virtual index_class_types : string
+ method virtual list_modules : Odoc_info.Module.t_module list
+ method virtual index_modules : string
+ method virtual list_module_types : Odoc_info.Module.t_module_type list
+ method virtual index_module_types : string
+
+ end
+
+(** A class used to generate html code for info structures. *)
+class virtual info =
+ object (self)
+ (** The list of pairs [(tag, f)] where [f] is a function taking
+ the [text] associated to [tag] and returning html code.
+ Add a pair here to handle a tag.*)
+ val mutable tag_functions = ([] : (string * (Odoc_info.text -> string)) list)
+
+ (** The method used to get html code from a [text]. *)
+ method virtual html_of_text : Buffer.t -> Odoc_info.text -> unit
+
+ (** Print html for an author list. *)
+ method html_of_author_list b l =
+ match l with
+ [] -> ()
+ | _ ->
+ bp b "<b>%s:</b> %s<br>\n"
+ Odoc_messages.authors
+ (String.concat ", " l)
+
+ (** Print html code for the given optional version information.*)
+ method html_of_version_opt b v_opt =
+ match v_opt with
+ None -> ()
+ | Some v ->
+ bp b "<b>%s:</b> %s<br>\n" Odoc_messages.version v
+
+ (** Print html code for the given optional since information.*)
+ method html_of_since_opt b s_opt =
+ match s_opt with
+ None -> ()
+ | Some s ->
+ bp b "<b>%s</b> %s<br>\n" Odoc_messages.since s
+
+ (** Print html code for the given "before" information.*)
+ method html_of_before b l =
+ let f (v, text) =
+ bp b "<b>%s %s </b> " Odoc_messages.before v;
+ self#html_of_text b text;
+ bs b "<br>\n"
+ in
+ List.iter f l
+
+ (** Print html code for the given list of raised exceptions.*)
+ method html_of_raised_exceptions b l =
+ match l with
+ [] -> ()
+ | (s, t) :: [] ->
+ bp b "<b>%s</b> <code>%s</code> "
+ Odoc_messages.raises
+ s;
+ self#html_of_text b t;
+ bs b "<br>\n"
+ | _ ->
+ bp b "<b>%s</b><ul>" Odoc_messages.raises;
+ List.iter
+ (fun (ex, desc) ->
+ bp b "<li><code>%s</code> " ex ;
+ self#html_of_text b desc;
+ bs b "</li>\n"
+ )
+ l;
+ bs b "</ul>\n"
+
+ (** Print html code for the given "see also" reference. *)
+ method html_of_see b (see_ref, t) =
+ let t_ref =
+ match see_ref with
+ Odoc_info.See_url s -> [ Odoc_info.Link (s, t) ]
+ | Odoc_info.See_file s -> (Odoc_info.Code s) :: (Odoc_info.Raw " ") :: t
+ | Odoc_info.See_doc s -> (Odoc_info.Italic [Odoc_info.Raw s]) :: (Odoc_info.Raw " ") :: t
+ in
+ self#html_of_text b t_ref
+
+ (** Print html code for the given list of "see also" references.*)
+ method html_of_sees b l =
+ match l with
+ [] -> ()
+ | see :: [] ->
+ bp b "<b>%s</b> " Odoc_messages.see_also;
+ self#html_of_see b see;
+ bs b "<br>\n"
+ | _ ->
+ bp b "<b>%s</b><ul>" Odoc_messages.see_also;
+ List.iter
+ (fun see ->
+ bs b "<li>" ;
+ self#html_of_see b see;
+ bs b "</li>\n"
+ )
+ l;
+ bs b "</ul>\n"
+
+ (** Print html code for the given optional return information.*)
+ method html_of_return_opt b return_opt =
+ match return_opt with
+ None -> ()
+ | Some s ->
+ bp b "<b>%s</b> " Odoc_messages.returns;
+ self#html_of_text b s;
+ bs b "<br>\n"
+
+ (** Print html code for the given list of custom tagged texts. *)
+ method html_of_custom b l =
+ List.iter
+ (fun (tag, text) ->
+ try
+ let f = List.assoc tag tag_functions in
+ Buffer.add_string b (f text)
+ with
+ Not_found ->
+ Odoc_info.warning (Odoc_messages.tag_not_handled tag)
+ )
+ l
+
+ (** Print html code for a description, except for the [i_params] field.
+ @param indent can be specified not to use the style of info comments;
+ default is [true].
+ *)
+ method html_of_info ?(indent=true) b info_opt =
+ match info_opt with
+ None ->
+ ()
+ | Some info ->
+ let module M = Odoc_info in
+ if indent then bs b "<div class=\"info\">\n";
+ (
+ match info.M.i_deprecated with
+ None -> ()
+ | Some d ->
+ bs b "<span class=\"warning\">";
+ bs b Odoc_messages.deprecated ;
+ bs b "</span>" ;
+ self#html_of_text b d;
+ bs b "<br>\n"
+ );
+ (
+ match info.M.i_desc with
+ None -> ()
+ | Some d when d = [Odoc_info.Raw ""] -> ()
+ | Some d -> self#html_of_text b d; bs b "<br>\n"
+ );
+ self#html_of_author_list b info.M.i_authors;
+ self#html_of_version_opt b info.M.i_version;
+ self#html_of_before b info.M.i_before;
+ self#html_of_since_opt b info.M.i_since;
+ self#html_of_raised_exceptions b info.M.i_raised_exceptions;
+ self#html_of_return_opt b info.M.i_return_value;
+ self#html_of_sees b info.M.i_sees;
+ self#html_of_custom b info.M.i_custom;
+ if indent then bs b "</div>\n"
+
+ (** Print html code for the first sentence of a description.
+ The titles and lists in this first sentence has been removed.*)
+ method html_of_info_first_sentence b info_opt =
+ match info_opt with
+ None -> ()
+ | Some info ->
+ let module M = Odoc_info in
+ let dep = info.M.i_deprecated <> None in
+ bs b "<div class=\"info\">\n";
+ if dep then bs b "<font color=\"#CCCCCC\">";
+ (
+ match info.M.i_desc with
+ None -> ()
+ | Some d when d = [Odoc_info.Raw ""] -> ()
+ | Some d ->
+ self#html_of_text b
+ (Odoc_info.text_no_title_no_list
+ (Odoc_info.first_sentence_of_text d));
+ bs b "\n"
+ );
+ if dep then bs b "</font>";
+ bs b "</div>\n"
+
+ end
+
+
+
+let opt = Odoc_info.apply_opt
+
+let print_concat b sep f =
+ let rec iter = function
+ [] -> ()
+ | [c] -> f c
+ | c :: q ->
+ f c;
+ bs b sep;
+ iter q
+ in
+ iter
+
+let newline_to_indented_br s =
+ let len = String.length s in
+ let b = Buffer.create len in
+ for i = 0 to len - 1 do
+ match s.[i] with
+ '\n' -> Buffer.add_string b "<br> "
+ | c -> Buffer.add_char b c
+ done;
+ Buffer.contents b
+
+module Generator =
+ struct
+(** This class is used to create objects which can generate a simple html documentation. *)
+class html =
+ object (self)
+ inherit text
+ inherit info
+
+ val mutable doctype =
+ "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n"
+ val mutable character_encoding =
+ "<meta content=\"text/html; charset=iso-8859-1\" http-equiv=\"Content-Type\">\n"
+
+ (** The default style options. *)
+ val mutable default_style_options =
+ ["a:visited {color : #416DFF; text-decoration : none; }" ;
+ "a:link {color : #416DFF; text-decoration : none;}" ;
+ "a:hover {color : Red; text-decoration : none; background-color: #5FFF88}" ;
+ "a:active {color : Red; text-decoration : underline; }" ;
+ ".keyword { font-weight : bold ; color : Red }" ;
+ ".keywordsign { color : #C04600 }" ;
+ ".superscript { font-size : 4 }" ;
+ ".subscript { font-size : 4 }" ;
+ ".comment { color : Green }" ;
+ ".constructor { color : Blue }" ;
+ ".type { color : #5C6585 }" ;
+ ".string { color : Maroon }" ;
+ ".warning { color : Red ; font-weight : bold }" ;
+ ".info { margin-left : 3em; margin-right : 3em }" ;
+ ".param_info { margin-top: 4px; margin-left : 3em; margin-right : 3em }" ;
+ ".code { color : #465F91 ; }" ;
+ "h1 { font-size : 20pt ; text-align: center; }" ;
+
+ "h2 { font-size : 20pt ; border: 1px solid #000000; "^
+ "margin-top: 5px; margin-bottom: 2px;"^
+ "text-align: center; background-color: #90BDFF ;"^
+ "padding: 2px; }" ;
+
+ "h3 { font-size : 20pt ; border: 1px solid #000000; "^
+ "margin-top: 5px; margin-bottom: 2px;"^
+ "text-align: center; background-color: #90DDFF ;"^
+ "padding: 2px; }" ;
+
+ "h4 { font-size : 20pt ; border: 1px solid #000000; "^
+ "margin-top: 5px; margin-bottom: 2px;"^
+ "text-align: center; background-color: #90EDFF ;"^
+ "padding: 2px; }" ;
+
+ "h5 { font-size : 20pt ; border: 1px solid #000000; "^
+ "margin-top: 5px; margin-bottom: 2px;"^
+ "text-align: center; background-color: #90FDFF ;"^
+ "padding: 2px; }" ;
+
+ "h6 { font-size : 20pt ; border: 1px solid #000000; "^
+ "margin-top: 5px; margin-bottom: 2px;"^
+ "text-align: center; background-color: #C0FFFF ; "^
+ "padding: 2px; }" ;
+
+ "div.h7 { font-size : 20pt ; border: 1px solid #000000; "^
+ "margin-top: 5px; margin-bottom: 2px;"^
+ "text-align: center; background-color: #E0FFFF ; "^
+ "padding: 2px; }" ;
+
+ "div.h8 { font-size : 20pt ; border: 1px solid #000000; "^
+ "margin-top: 5px; margin-bottom: 2px;"^
+ "text-align: center; background-color: #F0FFFF ; "^
+ "padding: 2px; }" ;
+
+ "div.h9 { font-size : 20pt ; border: 1px solid #000000; "^
+ "margin-top: 5px; margin-bottom: 2px;"^
+ "text-align: center; background-color: #FFFFFF ; "^
+ "padding: 2px; }" ;
+
+ ".typetable { border-style : hidden }" ;
+ ".indextable { border-style : hidden }" ;
+ ".paramstable { border-style : hidden ; padding: 5pt 5pt}" ;
+ "body { background-color : White }" ;
+ "tr { background-color : White }" ;
+ "td.typefieldcomment { background-color : #FFFFFF ; font-size: smaller ;}" ;
+ "pre { margin-bottom: 4px }" ;
+
+ "div.sig_block {margin-left: 2em}" ;
+
+ "*:target { background: yellow; } " ;
+ ]
+
+ (** The style file for all pages. *)
+ val mutable style_file = "style.css"
+
+ (** The code to import the style. Initialized in [init_style]. *)
+ val mutable style = ""
+
+ (** The known types names.
+ Used to know if we must create a link to a type
+ when printing a type. *)
+ val mutable known_types_names = StringSet.empty
+
+ (** The known class and class type names.
+ Used to know if we must create a link to a class
+ or class type or not when printing a type. *)
+ val mutable known_classes_names = StringSet.empty
+
+ (** The known modules and module types names.
+ Used to know if we must create a link to a type or not
+ when printing a module type. *)
+ val mutable known_modules_names = StringSet.empty
+
+ method index_prefix =
+ if !Odoc_global.out_file = Odoc_messages.default_out_file then
+ "index"
+ else
+ Filename.basename !Odoc_global.out_file
+
+ (** The main file. *)
+ method index =
+ let p = self#index_prefix in
+ Printf.sprintf "%s.html" p
+
+ (** The file for the index of values. *)
+ method index_values = Printf.sprintf "%s_values.html" self#index_prefix
+ (** The file for the index of types. *)
+ method index_types = Printf.sprintf "%s_types.html" self#index_prefix
+ (** The file for the index of exceptions. *)
+ method index_exceptions = Printf.sprintf "%s_exceptions.html" self#index_prefix
+ (** The file for the index of attributes. *)
+ method index_attributes = Printf.sprintf "%s_attributes.html" self#index_prefix
+ (** The file for the index of methods. *)
+ method index_methods = Printf.sprintf "%s_methods.html" self#index_prefix
+ (** The file for the index of classes. *)
+ method index_classes = Printf.sprintf "%s_classes.html" self#index_prefix
+ (** The file for the index of class types. *)
+ method index_class_types = Printf.sprintf "%s_class_types.html" self#index_prefix
+ (** The file for the index of modules. *)
+ method index_modules = Printf.sprintf "%s_modules.html" self#index_prefix
+ (** The file for the index of module types. *)
+ method index_module_types = Printf.sprintf "%s_module_types.html" self#index_prefix
+
+
+ (** The list of attributes. Filled in the [generate] method. *)
+ val mutable list_attributes = []
+ method list_attributes = list_attributes
+ (** The list of methods. Filled in the [generate] method. *)
+ val mutable list_methods = []
+ method list_methods = list_methods
+ (** The list of values. Filled in the [generate] method. *)
+ val mutable list_values = []
+ method list_values = list_values
+ (** The list of exceptions. Filled in the [generate] method. *)
+ val mutable list_exceptions = []
+ method list_exceptions = list_exceptions
+ (** The list of types. Filled in the [generate] method. *)
+ val mutable list_types = []
+ method list_types = list_types
+ (** The list of modules. Filled in the [generate] method. *)
+ val mutable list_modules = []
+ method list_modules = list_modules
+ (** The list of module types. Filled in the [generate] method. *)
+ val mutable list_module_types = []
+ method list_module_types = list_module_types
+ (** The list of classes. Filled in the [generate] method. *)
+ val mutable list_classes = []
+ method list_classes = list_classes
+ (** The list of class types. Filled in the [generate] method. *)
+ val mutable list_class_types = []
+ method list_class_types = list_class_types
+
+ (** The header of pages. Must be prepared by the [prepare_header] method.*)
+ val mutable header = fun b -> fun ?(nav=None) -> fun ?(comments=[]) -> fun _ -> ()
+
+ (** Init the style. *)
+ method init_style =
+ (match !css_style with
+ None ->
+ let default_style = String.concat "\n" default_style_options in
+ (
+ try
+ let file = Filename.concat !Global.target_dir style_file in
+ if Sys.file_exists file then
+ Odoc_info.verbose (Odoc_messages.file_exists_dont_generate file)
+ else
+ (
+ let chanout = open_out file in
+ output_string chanout default_style ;
+ flush chanout ;
+ close_out chanout;
+ Odoc_info.verbose (Odoc_messages.file_generated file)
+ )
+ with
+ Sys_error s ->
+ prerr_endline s ;
+ incr Odoc_info.errors ;
+ )
+ | Some f ->
+ style_file <- f
+ );
+ style <- "<link rel=\"stylesheet\" href=\""^style_file^"\" type=\"text/css\">\n"
+
+ (** Get the title given by the user *)
+ method title = match !Global.title with None -> "" | Some t -> self#escape t
+
+ (** Get the title given by the user completed with the given subtitle. *)
+ method inner_title s =
+ (match self#title with "" -> "" | t -> t^" : ")^
+ (self#escape s)
+
+ (** Get the page header. *)
+ method print_header b ?nav ?comments title = header b ?nav ?comments title
+
+ (** A function to build the header of pages. *)
+ method prepare_header module_list =
+ let f b ?(nav=None) ?(comments=[]) t =
+ let link_if_not_empty l m url =
+ match l with
+ [] -> ()
+ | _ ->
+ bp b "<link title=\"%s\" rel=Appendix href=\"%s\">\n" m url
+ in
+ bs b "<head>\n";
+ bs b style;
+ bs b character_encoding ;
+ bs b "<link rel=\"Start\" href=\"";
+ bs b self#index;
+ bs b "\">\n" ;
+ (
+ match nav with
+ None -> ()
+ | Some (pre_opt, post_opt, name) ->
+ (match pre_opt with
+ None -> ()
+ | Some name ->
+ bp b "<link rel=\"previous\" href=\"%s\">\n"
+ (fst (Naming.html_files name));
+ );
+ (match post_opt with
+ None -> ()
+ | Some name ->
+ bp b "<link rel=\"next\" href=\"%s\">\n"
+ (fst (Naming.html_files name));
+ );
+ (
+ let father = Name.father name in
+ let href = if father = "" then self#index else fst (Naming.html_files father) in
+ bp b "<link rel=\"Up\" href=\"%s\">\n" href
+ )
+ );
+ link_if_not_empty self#list_types Odoc_messages.index_of_types self#index_types;
+ link_if_not_empty self#list_exceptions Odoc_messages.index_of_exceptions self#index_exceptions;
+ link_if_not_empty self#list_values Odoc_messages.index_of_values self#index_values;
+ link_if_not_empty self#list_attributes Odoc_messages.index_of_attributes self#index_attributes;
+ link_if_not_empty self#list_methods Odoc_messages.index_of_methods self#index_methods;
+ link_if_not_empty self#list_classes Odoc_messages.index_of_classes self#index_classes;
+ link_if_not_empty self#list_class_types Odoc_messages.index_of_class_types self#index_class_types;
+ link_if_not_empty self#list_modules Odoc_messages.index_of_modules self#index_modules;
+ link_if_not_empty self#list_module_types Odoc_messages.index_of_module_types self#index_module_types;
+ let print_one m =
+ let html_file = fst (Naming.html_files m.m_name) in
+ bp b "<link title=\"%s\" rel=\"Chapter\" href=\"%s\">"
+ m.m_name html_file
+ in
+ print_concat b "\n" print_one module_list;
+ self#html_sections_links b comments;
+ bs b "<title>";
+ bs b t ;
+ bs b "</title>\n</head>\n"
+ in
+ header <- f
+
+ (** Build the html code for the link tags in the header, defining section and
+ subsections for the titles found in the given comments.*)
+ method html_sections_links b comments =
+ let titles = List.flatten (List.map Odoc_info.get_titles_in_text comments) in
+ let levels =
+ let rec iter acc l =
+ match l with
+ [] -> acc
+ | (n,_,_) :: q ->
+ if List.mem n acc
+ then iter acc q
+ else iter (n::acc) q
+ in
+ iter [] titles
+ in
+ let sorted_levels = List.sort compare levels in
+ let (section_level, subsection_level) =
+ match sorted_levels with
+ [] -> (None, None)
+ | [n] -> (Some n, None)
+ | n :: m :: _ -> (Some n, Some m)
+ in
+ let titles_per_level level_opt =
+ match level_opt with
+ None -> []
+ | Some n -> List.filter (fun (m,_,_) -> m = n) titles
+ in
+ let section_titles = titles_per_level section_level in
+ let subsection_titles = titles_per_level subsection_level in
+ let print_lines s_rel titles =
+ List.iter
+ (fun (n,lopt,t) ->
+ let s = Odoc_info.string_of_text t in
+ let label = self#create_title_label (n,lopt,t) in
+ bp b "<link title=\"%s\" rel=\"%s\" href=\"#%s\">\n" s s_rel label
+ )
+ titles
+ in
+ print_lines "Section" section_titles ;
+ print_lines "Subsection" subsection_titles
+
+
+ (** Html code for navigation bar.
+ @param pre optional name for optional previous module/class
+ @param post optional name for optional next module/class
+ @param name name of current module/class *)
+ method print_navbar b pre post name =
+ bs b "<div class=\"navbar\">";
+ (
+ match pre with
+ None -> ()
+ | Some name ->
+ bp b "<a href=\"%s\">%s</a>\n"
+ (fst (Naming.html_files name))
+ Odoc_messages.previous
+ );
+ bs b "&nbsp;";
+ let father = Name.father name in
+ let href = if father = "" then self#index else fst (Naming.html_files father) in
+ bp b "<a href=\"%s\">%s</a>\n" href Odoc_messages.up;
+ bs b "&nbsp;";
+ (
+ match post with
+ None -> ()
+ | Some name ->
+ bp b "<a href=\"%s\">%s</a>\n"
+ (fst (Naming.html_files name))
+ Odoc_messages.next
+ );
+ bs b "</div>\n"
+
+ (** Return html code with the given string in the keyword style.*)
+ method keyword s =
+ "<span class=\"keyword\">"^s^"</span>"
+
+ (** Return html code with the given string in the constructor style. *)
+ method constructor s = "<span class=\"constructor\">"^s^"</span>"
+
+ (** Output the given ocaml code to the given file name. *)
+ method private output_code in_title file code =
+ try
+ let chanout = open_out file in
+ let b = new_buf () in
+ bs b "<html>";
+ self#print_header b (self#inner_title in_title);
+ bs b"<body>\n";
+ self#html_of_code b code;
+ bs b "</body></html>";
+ Buffer.output_buffer chanout b;
+ close_out chanout
+ with
+ Sys_error s ->
+ incr Odoc_info.errors ;
+ prerr_endline s
+
+ (** Take a string and return the string where fully qualified
+ type (or class or class type) idents
+ have been replaced by links to the type referenced by the ident.*)
+ method create_fully_qualified_idents_links m_name s =
+ let f str_t =
+ let match_s = Str.matched_string str_t in
+ let rel = Name.get_relative m_name match_s in
+ let s_final = Odoc_info.apply_if_equal
+ Odoc_info.use_hidden_modules
+ match_s
+ rel
+ in
+ if StringSet.mem match_s known_types_names then
+ "<a href=\""^(Naming.complete_target Naming.mark_type match_s)^"\">"^
+ s_final^
+ "</a>"
+ else
+ if StringSet.mem match_s known_classes_names then
+ let (html_file, _) = Naming.html_files match_s in
+ "<a href=\""^html_file^"\">"^s_final^"</a>"
+ else
+ s_final
+ in
+ let s2 = Str.global_substitute
+ (Str.regexp "\\([A-Z]\\([a-zA-Z_'0-9]\\)*\\.\\)+\\([a-z][a-zA-Z_'0-9]*\\)")
+ f
+ s
+ in
+ s2
+
+ (** Take a string and return the string where fully qualified module idents
+ have been replaced by links to the module referenced by the ident.*)
+ method create_fully_qualified_module_idents_links m_name s =
+ let f str_t =
+ let match_s = Str.matched_string str_t in
+ let rel = Name.get_relative m_name match_s in
+ let s_final = Odoc_info.apply_if_equal
+ Odoc_info.use_hidden_modules
+ match_s
+ rel
+ in
+ if StringSet.mem match_s known_modules_names then
+ let (html_file, _) = Naming.html_files match_s in
+ "<a href=\""^html_file^"\">"^s_final^"</a>"
+ else
+ s_final
+ in
+ let s2 = Str.global_substitute
+ (Str.regexp "\\([A-Z]\\([a-zA-Z_'0-9]\\)*\\.\\)+\\([A-Z][a-zA-Z_'0-9]*\\)")
+ f
+ s
+ in
+ s2
+
+ (** Print html code to display a [Types.type_expr]. *)
+ method html_of_type_expr b m_name t =
+ let s = Odoc_info.remove_ending_newline (Odoc_info.string_of_type_expr t) in
+ let s2 = newline_to_indented_br s in
+ bs b "<code class=\"type\">";
+ bs b (self#create_fully_qualified_idents_links m_name s2);
+ bs b "</code>"
+
+ (** Print html code to display a [Types.type_expr list]. *)
+ method html_of_type_expr_list ?par b m_name sep l =
+ print_DEBUG "html#html_of_type_expr_list";
+ let s = Odoc_info.string_of_type_list ?par sep l in
+ print_DEBUG "html#html_of_type_expr_list: 1";
+ let s2 = newline_to_indented_br s in
+ print_DEBUG "html#html_of_type_expr_list: 2";
+ bs b "<code class=\"type\">";
+ bs b (self#create_fully_qualified_idents_links m_name s2);
+ bs b "</code>"
+
+ (** Print html code to display a [Types.type_expr list] as type parameters
+ of a class of class type. *)
+ method html_of_class_type_param_expr_list b m_name l =
+ let s = Odoc_info.string_of_class_type_param_list l in
+ let s2 = newline_to_indented_br s in
+ bs b "<code class=\"type\">[";
+ bs b (self#create_fully_qualified_idents_links m_name s2);
+ bs b "]</code>"
+
+ method html_of_class_parameter_list b father c =
+ let s = Odoc_info.string_of_class_params c in
+ let s = Odoc_info.remove_ending_newline s in
+ let s2 = newline_to_indented_br s in
+ bs b "<code class=\"type\">";
+ bs b (self#create_fully_qualified_idents_links father s2);
+ bs b "</code>"
+
+ (** Print html code to display a list of type parameters for the given type.*)
+ method html_of_type_expr_param_list b m_name t =
+ let s = Odoc_info.string_of_type_param_list t in
+ let s2 = newline_to_indented_br s in
+ bs b "<code class=\"type\">";
+ bs b (self#create_fully_qualified_idents_links m_name s2);
+ bs b "</code>"
+
+ (** Print html code to display a [Types.module_type]. *)
+ method html_of_module_type b ?code m_name t =
+ let s = Odoc_info.remove_ending_newline (Odoc_info.string_of_module_type ?code t) in
+ bs b "<code class=\"type\">";
+ bs b (self#create_fully_qualified_module_idents_links m_name s);
+ bs b "</code>"
+
+ (** Print html code to display the given module kind. *)
+ method html_of_module_kind b father ?modu kind =
+ match kind with
+ Module_struct eles ->
+ self#html_of_text b [Code "sig"];
+ (
+ match modu with
+ None ->
+ bs b "<div class=\"sig_block\">";
+ List.iter (self#html_of_module_element b father) eles;
+ bs b "</div>"
+ | Some m ->
+ let (html_file, _) = Naming.html_files m.m_name in
+ bp b " <a href=\"%s\">..</a> " html_file
+ );
+ self#html_of_text b [Code "end"]
+ | Module_alias a ->
+ bs b "<code class=\"type\">";
+ bs b (self#create_fully_qualified_module_idents_links father a.ma_name);
+ bs b "</code>"
+ | Module_functor (p, k) ->
+ if !html_short_functors then
+ bs b " "
+ else
+ bs b "<div class=\"sig_block\">";
+ self#html_of_module_parameter b father p;
+ (
+ match k with
+ Module_functor _ -> ()
+ | _ when !html_short_functors ->
+ bs b ": "
+ | _ -> ()
+ );
+ self#html_of_module_kind b father ?modu k;
+ if not !html_short_functors then
+ bs b "</div>"
+ | Module_apply (k1, k2) ->
+ (* TODO: l'application n'est pas correcte dans un .mli.
+ Que faire ? -> afficher le module_type du typedtree *)
+ self#html_of_module_kind b father k1;
+ self#html_of_text b [Code "("];
+ self#html_of_module_kind b father k2;
+ self#html_of_text b [Code ")"]
+ | Module_with (k, s) ->
+ (* TODO: à modifier quand Module_with sera plus détaillé *)
+ self#html_of_module_type_kind b father ?modu k;
+ bs b "<code class=\"type\"> ";
+ bs b (self#create_fully_qualified_module_idents_links father s);
+ bs b "</code>"
+ | Module_constraint (k, tk) ->
+ (* TODO: on affiche quoi ? *)
+ self#html_of_module_kind b father ?modu k
+ | Module_typeof s ->
+ bs b "<code class=\"type\">module type of ";
+ bs b (self#create_fully_qualified_module_idents_links father s);
+ bs b "</code>"
+ | Module_unpack (code, mta) ->
+ bs b "<code class=\"type\">";
+ begin
+ match mta.mta_module with
+ None ->
+ bs b (self#create_fully_qualified_module_idents_links father (self#escape code))
+ | Some mt ->
+ let (html_file, _) = Naming.html_files mt.mt_name in
+ bp b " <a href=\"%s\">%s</a> " html_file (self#escape code)
+ end;
+ bs b "</code>"
+
+
+ method html_of_module_parameter b father p =
+ let (s_functor,s_arrow) =
+ if !html_short_functors then
+ "", ""
+ else
+ "functor ", "-> "
+ in
+ self#html_of_text b
+ [
+ Code (s_functor^"(");
+ Code p.mp_name ;
+ Code " : ";
+ ] ;
+ self#html_of_module_type_kind b father p.mp_kind;
+ self#html_of_text b [ Code (") "^s_arrow)]
+
+ method html_of_module_element b father ele =
+ match ele with
+ Element_module m ->
+ self#html_of_module b ~complete: false m
+ | Element_module_type mt ->
+ self#html_of_modtype b ~complete: false mt
+ | Element_included_module im ->
+ self#html_of_included_module b im
+ | Element_class c ->
+ self#html_of_class b ~complete: false c
+ | Element_class_type ct ->
+ self#html_of_class_type b ~complete: false ct
+ | Element_value v ->
+ self#html_of_value b v
+ | Element_exception e ->
+ self#html_of_exception b e
+ | Element_type t ->
+ self#html_of_type b t
+ | Element_module_comment text ->
+ self#html_of_module_comment b text
+
+ (** Print html code to display the given module type kind. *)
+ method html_of_module_type_kind b father ?modu ?mt kind =
+ match kind with
+ Module_type_struct eles ->
+ self#html_of_text b [Code "sig"];
+ (
+ match mt with
+ None ->
+ (
+ match modu with
+ None ->
+ bs b "<div class=\"sig_block\">";
+ List.iter (self#html_of_module_element b father) eles;
+ bs b "</div>"
+ | Some m ->
+ let (html_file, _) = Naming.html_files m.m_name in
+ bp b " <a href=\"%s\">..</a> " html_file
+ )
+ | Some mt ->
+ let (html_file, _) = Naming.html_files mt.mt_name in
+ bp b " <a href=\"%s\">..</a> " html_file
+ );
+ self#html_of_text b [Code "end"]
+ | Module_type_functor (p, k) ->
+ self#html_of_module_parameter b father p;
+ self#html_of_module_type_kind b father ?modu ?mt k
+ | Module_type_alias a ->
+ bs b "<code class=\"type\">";
+ bs b (self#create_fully_qualified_module_idents_links father a.mta_name);
+ bs b "</code>"
+ | Module_type_with (k, s) ->
+ self#html_of_module_type_kind b father ?modu ?mt k;
+ bs b "<code class=\"type\"> ";
+ bs b (self#create_fully_qualified_module_idents_links father s);
+ bs b "</code>"
+ | Module_type_typeof s ->
+ bs b "<code class=\"type\">module type of ";
+ bs b (self#create_fully_qualified_module_idents_links father s);
+ bs b "</code>"
+
+ (** Print html code to display the type of a module parameter.. *)
+ method html_of_module_parameter_type b m_name p =
+ self#html_of_module_type b m_name ~code: p.mp_type_code p.mp_type
+
+ (** Generate a file containing the module type in the given file name. *)
+ method output_module_type in_title file mtyp =
+ let s = Odoc_info.remove_ending_newline (Odoc_info.string_of_module_type ~complete: true mtyp) in
+ self#output_code in_title file s
+
+ (** Generate a file containing the class type in the given file name. *)
+ method output_class_type in_title file ctyp =
+ let s = Odoc_info.remove_ending_newline (Odoc_info.string_of_class_type ~complete: true ctyp) in
+ self#output_code in_title file s
+
+ (** Print html code for a value. *)
+ method html_of_value b v =
+ Odoc_info.reset_type_names ();
+ bs b "<pre>" ;
+ bp b "<span id=\"%s\">" (Naming.value_target v);
+ bs b (self#keyword "val");
+ bs b " ";
+ (
+ match v.val_code with
+ None -> bs b (self#escape (Name.simple v.val_name))
+ | Some c ->
+ let file = Naming.file_code_value_complete_target v in
+ self#output_code v.val_name (Filename.concat !Global.target_dir file) c;
+ bp b "<a href=\"%s\">%s</a>" file (self#escape (Name.simple v.val_name))
+ );
+ bs b "</span>";
+ bs b " : ";
+ self#html_of_type_expr b (Name.father v.val_name) v.val_type;
+ bs b "</pre>";
+ self#html_of_info b v.val_info;
+ (
+ if !with_parameter_list then
+ self#html_of_parameter_list b (Name.father v.val_name) v.val_parameters
+ else
+ self#html_of_described_parameter_list b (Name.father v.val_name) v.val_parameters
+ )
+
+ (** Print html code for an exception. *)
+ method html_of_exception b e =
+ Odoc_info.reset_type_names ();
+ bs b "<pre>";
+ bp b "<span id=\"%s\">" (Naming.exception_target e);
+ bs b (self#keyword "exception");
+ bs b " ";
+ bs b (Name.simple e.ex_name);
+ bs b "</span>";
+ (
+ match e.ex_args with
+ [] -> ()
+ | _ ->
+ bs b (" "^(self#keyword "of")^" ");
+ self#html_of_type_expr_list
+ ~par: false b (Name.father e.ex_name) " * " e.ex_args
+ );
+ (
+ match e.ex_alias with
+ None -> ()
+ | Some ea ->
+ bs b " = ";
+ (
+ match ea.ea_ex with
+ None -> bs b ea.ea_name
+ | Some e ->
+ bp b "<a href=\"%s\">%s</a>" (Naming.complete_exception_target e) e.ex_name
+ )
+ );
+ bs b "</pre>\n";
+ self#html_of_info b e.ex_info
+
+ (** Print html code for a type. *)
+ method html_of_type b t =
+ Odoc_info.reset_type_names ();
+ let father = Name.father t.ty_name in
+ bs b
+ (match t.ty_manifest, t.ty_kind with
+ None, Type_abstract -> "<pre>"
+ | None, Type_variant _
+ | None, Type_record _ -> "<br><code>"
+ | Some _, Type_abstract -> "<pre>"
+ | Some _, Type_variant _
+ | Some _, Type_record _ -> "<pre>"
+ );
+ bp b "<span id=\"%s\">" (Naming.type_target t);
+ bs b ((self#keyword "type")^" ");
+ self#html_of_type_expr_param_list b father t;
+ (match t.ty_parameters with [] -> () | _ -> bs b " ");
+ bs b (Name.simple t.ty_name);
+ bs b "</span> ";
+ let priv = t.ty_private = Asttypes.Private in
+ (
+ match t.ty_manifest with
+ None -> ()
+ | Some typ ->
+ bs b "= ";
+ if priv then bs b "private ";
+ self#html_of_type_expr b father typ;
+ bs b " "
+ );
+ (match t.ty_kind with
+ Type_abstract -> bs b "</pre>"
+ | Type_variant l ->
+ bs b "= ";
+ if priv then bs b "private ";
+ bs b
+ (
+ match t.ty_manifest with
+ None -> "</code>"
+ | Some _ -> "</pre>"
+ );
+ bs b "<table class=\"typetable\">\n";
+ let print_one constr =
+ bs b "<tr>\n<td align=\"left\" valign=\"top\" >\n";
+ bs b "<code>";
+ bs b (self#keyword "|");
+ bs b "</code></td>\n<td align=\"left\" valign=\"top\" >\n";
+ bs b "<code>";
+ bs b (self#constructor constr.vc_name);
+ (
+ match constr.vc_args with
+ [] -> ()
+ | l ->
+ bs b (" " ^ (self#keyword "of") ^ " ");
+ self#html_of_type_expr_list ~par: false b father " * " l;
+ );
+ bs b "</code></td>\n";
+ (
+ match constr.vc_text with
+ None -> ()
+ | Some t ->
+ bs b "<td class=\"typefieldcomment\" align=\"left\" valign=\"top\" >";
+ bs b "<code>";
+ bs b "(*";
+ bs b "</code></td>";
+ bs b "<td class=\"typefieldcomment\" align=\"left\" valign=\"top\" >";
+ self#html_of_text b t;
+ bs b "</td>";
+ bs b "<td class=\"typefieldcomment\" align=\"left\" valign=\"bottom\" >";
+ bs b "<code>";
+ bs b "*)";
+ bs b "</code></td>";
+ );
+ bs b "\n</tr>"
+ in
+ print_concat b "\n" print_one l;
+ bs b "</table>\n"
+
+ | Type_record l ->
+ bs b "= ";
+ if priv then bs b "private " ;
+ bs b "{";
+ bs b
+ (
+ match t.ty_manifest with
+ None -> "</code>"
+ | Some _ -> "</pre>"
+ );
+ bs b "<table class=\"typetable\">\n" ;
+ let print_one r =
+ bs b "<tr>\n<td align=\"left\" valign=\"top\" >\n";
+ bs b "<code>&nbsp;&nbsp;</code>";
+ bs b "</td>\n<td align=\"left\" valign=\"top\" >\n";
+ bs b "<code>";
+ if r.rf_mutable then bs b (self#keyword "mutable&nbsp;") ;
+ bs b (r.rf_name ^ "&nbsp;: ") ;
+ self#html_of_type_expr b father r.rf_type;
+ bs b ";</code></td>\n";
+ (
+ match r.rf_text with
+ None -> ()
+ | Some t ->
+ bs b "<td class=\"typefieldcomment\" align=\"left\" valign=\"top\" >";
+ bs b "<code>";
+ bs b "(*";
+ bs b "</code></td>";
+ bs b "<td class=\"typefieldcomment\" align=\"left\" valign=\"top\" >";
+ self#html_of_text b t;
+ bs b "</td><td class=\"typefieldcomment\" align=\"left\" valign=\"bottom\" >";
+ bs b "<code>*)</code></td>";
+ );
+ bs b "\n</tr>"
+ in
+ print_concat b "\n" print_one l;
+ bs b "</table>\n}\n"
+ );
+ bs b "\n";
+ self#html_of_info b t.ty_info;
+ bs b "\n"
+
+ (** Print html code for a class attribute. *)
+ method html_of_attribute b a =
+ let module_name = Name.father (Name.father a.att_value.val_name) in
+ bs b "<pre>" ;
+ bp b "<span id=\"%s\">" (Naming.attribute_target a);
+ bs b (self#keyword "val");
+ bs b " ";
+ (
+ if a.att_virtual then
+ bs b ((self#keyword "virtual")^ " ")
+ else
+ ()
+ );
+ (
+ if a.att_mutable then
+ bs b ((self#keyword Odoc_messages.mutab)^ " ")
+ else
+ ()
+ );(
+ match a.att_value.val_code with
+ None -> bs b (Name.simple a.att_value.val_name)
+ | Some c ->
+ let file = Naming.file_code_attribute_complete_target a in
+ self#output_code a.att_value.val_name (Filename.concat !Global.target_dir file) c;
+ bp b "<a href=\"%s\">%s</a>" file (Name.simple a.att_value.val_name);
+ );
+ bs b "</span>";
+ bs b " : ";
+ self#html_of_type_expr b module_name a.att_value.val_type;
+ bs b "</pre>";
+ self#html_of_info b a.att_value.val_info
+
+ (** Print html code for a class method. *)
+ method html_of_method b m =
+ let module_name = Name.father (Name.father m.met_value.val_name) in
+ bs b "<pre>";
+ (* html mark *)
+ bp b "<span id=\"%s\">" (Naming.method_target m);
+ bs b ((self#keyword "method")^" ");
+ if m.met_private then bs b ((self#keyword "private")^" ");
+ if m.met_virtual then bs b ((self#keyword "virtual")^" ");
+ (
+ match m.met_value.val_code with
+ None -> bs b (Name.simple m.met_value.val_name)
+ | Some c ->
+ let file = Naming.file_code_method_complete_target m in
+ self#output_code m.met_value.val_name (Filename.concat !Global.target_dir file) c;
+ bp b "<a href=\"%s\">%s</a>" file (Name.simple m.met_value.val_name);
+ );
+ bs b "</span>";
+ bs b " : ";
+ self#html_of_type_expr b module_name m.met_value.val_type;
+ bs b "</pre>";
+ self#html_of_info b m.met_value.val_info;
+ (
+ if !with_parameter_list then
+ self#html_of_parameter_list b
+ module_name m.met_value.val_parameters
+ else
+ self#html_of_described_parameter_list b
+ module_name m.met_value.val_parameters
+ )
+
+ (** Print html code for the description of a function parameter. *)
+ method html_of_parameter_description b p =
+ match Parameter.names p with
+ [] ->
+ ()
+ | name :: [] ->
+ (
+ (* Only one name, no need for label for the description. *)
+ match Parameter.desc_by_name p name with
+ None -> ()
+ | Some t -> self#html_of_text b t
+ )
+ | l ->
+ (* A list of names, we display those with a description. *)
+ let l2 = List.filter
+ (fun n -> (Parameter.desc_by_name p n) <> None)
+ l
+ in
+ let print_one n =
+ match Parameter.desc_by_name p n with
+ None -> ()
+ | Some t ->
+ bs b "<code>";
+ bs b n;
+ bs b "</code> : ";
+ self#html_of_text b t
+ in
+ print_concat b "<br>\n" print_one l2
+
+ (** Print html code for a list of parameters. *)
+ method html_of_parameter_list b m_name l =
+ match l with
+ [] -> ()
+ | _ ->
+ bs b "<div class=\"param_info\">";
+ bs b "<table border=\"0\" cellpadding=\"3\" width=\"100%\">\n";
+ bs b "<tr>\n<td align=\"left\" valign=\"top\" width=\"1%\">";
+ bs b "<b>";
+ bs b Odoc_messages.parameters;
+ bs b ": </b></td>\n" ;
+ bs b "<td>\n<table class=\"paramstable\">\n";
+ let print_one p =
+ bs b "<tr>\n<td align=\"center\" valign=\"top\" width=\"15%\" class=\"code\">\n";
+ bs b
+ (
+ match Parameter.complete_name p with
+ "" -> "?"
+ | s -> s
+ );
+ bs b "</td>\n<td align=\"center\" valign=\"top\">:</td>\n";
+ bs b "<td>";
+ self#html_of_type_expr b m_name (Parameter.typ p);
+ bs b "<br>\n";
+ self#html_of_parameter_description b p;
+ bs b "\n</tr>\n";
+ in
+ List.iter print_one l;
+ bs b "</table>\n</td>\n</tr>\n</table></div>\n"
+
+ (** Print html code for the parameters which have a name and description. *)
+ method html_of_described_parameter_list b m_name l =
+ (* get the params which have a name, and at least one name described. *)
+ let l2 = List.filter
+ (fun p ->
+ List.exists
+ (fun n -> (Parameter.desc_by_name p n) <> None)
+ (Parameter.names p))
+ l
+ in
+ let f p =
+ bs b "<div class=\"param_info\"><code class=\"code\">";
+ bs b (Parameter.complete_name p);
+ bs b "</code> : " ;
+ self#html_of_parameter_description b p;
+ bs b "</div>\n"
+ in
+ List.iter f l2
+
+ (** Print html code for a list of module parameters. *)
+ method html_of_module_parameter_list b m_name l =
+ match l with
+ [] ->
+ ()
+ | _ ->
+ bs b "<table border=\"0\" cellpadding=\"3\" width=\"100%\">\n";
+ bs b "<tr>\n";
+ bs b "<td align=\"left\" valign=\"top\" width=\"1%%\"><b>";
+ bs b Odoc_messages.parameters ;
+ bs b ": </b></td>\n<td>\n";
+ bs b "<table class=\"paramstable\">\n";
+ List.iter
+ (fun (p, desc_opt) ->
+ bs b "<tr>\n";
+ bs b "<td align=\"center\" valign=\"top\" width=\"15%\">\n<code>" ;
+ bs b p.mp_name;
+ bs b "</code></td>\n" ;
+ bs b "<td align=\"center\" valign=\"top\">:</td>\n";
+ bs b "<td>" ;
+ self#html_of_module_parameter_type b m_name p;
+ bs b "\n";
+ (
+ match desc_opt with
+ None -> ()
+ | Some t ->
+ bs b "<br>";
+ self#html_of_text b t;
+ bs b "\n</tr>\n" ;
+ )
+ )
+ l;
+ bs b "</table>\n</td>\n</tr>\n</table>\n"
+
+ (** Print html code for a module. *)
+ method html_of_module b ?(info=true) ?(complete=true) ?(with_link=true) m =
+ let (html_file, _) = Naming.html_files m.m_name in
+ let father = Name.father m.m_name in
+ bs b "<pre>";
+ bs b ((self#keyword "module")^" ");
+ (
+ if with_link then
+ bp b "<a href=\"%s\">%s</a>" html_file (Name.simple m.m_name)
+ else
+ bs b (Name.simple m.m_name)
+ );
+ (
+ match m.m_kind with
+ Module_functor _ when !html_short_functors ->
+ ()
+ | _ -> bs b ": "
+ );
+ self#html_of_module_kind b father ~modu: m m.m_kind;
+ bs b "</pre>";
+ if info then
+ (
+ if complete then
+ self#html_of_info ~indent: false
+ else
+ self#html_of_info_first_sentence
+ ) b m.m_info
+ else
+ ()
+
+ (** Print html code for a module type. *)
+ method html_of_modtype b ?(info=true) ?(complete=true) ?(with_link=true) mt =
+ let (html_file, _) = Naming.html_files mt.mt_name in
+ let father = Name.father mt.mt_name in
+ bs b "<pre>";
+ bs b ((self#keyword "module type")^" ");
+ (
+ if with_link then
+ bp b "<a href=\"%s\">%s</a>" html_file (Name.simple mt.mt_name)
+ else
+ bs b (Name.simple mt.mt_name)
+ );
+ (match mt.mt_kind with
+ None -> ()
+ | Some k ->
+ bs b " = ";
+ self#html_of_module_type_kind b father ~mt k
+ );
+ bs b "</pre>";
+ if info then
+ (
+ if complete then
+ self#html_of_info ~indent: false
+ else
+ self#html_of_info_first_sentence
+ ) b mt.mt_info
+ else
+ ()
+
+ (** Print html code for an included module. *)
+ method html_of_included_module b im =
+ bs b "<pre>";
+ bs b ((self#keyword "include")^" ");
+ (
+ match im.im_module with
+ None ->
+ bs b im.im_name
+ | Some mmt ->
+ let (file, name) =
+ match mmt with
+ Mod m ->
+ let (html_file, _) = Naming.html_files m.m_name in
+ (html_file, m.m_name)
+ | Modtype mt ->
+ let (html_file, _) = Naming.html_files mt.mt_name in
+ (html_file, mt.mt_name)
+ in
+ bp b "<a href=\"%s\">%s</a>" file name
+ );
+ bs b "</pre>\n";
+ self#html_of_info b im.im_info
+
+ method html_of_class_element b element =
+ match element with
+ Class_attribute a ->
+ self#html_of_attribute b a
+ | Class_method m ->
+ self#html_of_method b m
+ | Class_comment t ->
+ self#html_of_class_comment b t
+
+ method html_of_class_kind b father ?cl kind =
+ match kind with
+ Class_structure (inh, eles) ->
+ self#html_of_text b [Code "object"];
+ (
+ match cl with
+ None ->
+ bs b "\n";
+ (
+ match inh with
+ [] -> ()
+ | _ ->
+ self#generate_inheritance_info b inh
+ );
+ List.iter (self#html_of_class_element b) eles;
+ | Some cl ->
+ let (html_file, _) = Naming.html_files cl.cl_name in
+ bp b " <a href=\"%s\">..</a> " html_file
+ );
+ self#html_of_text b [Code "end"]
+
+ | Class_apply capp ->
+ (* TODO: afficher le type final à partir du typedtree *)
+ self#html_of_text b [Raw "class application not handled yet"]
+
+ | Class_constr cco ->
+ (
+ match cco.cco_type_parameters with
+ [] -> ()
+ | l ->
+ self#html_of_class_type_param_expr_list b father l;
+ bs b " "
+ );
+ bs b "<code class=\"type\">";
+ bs b (self#create_fully_qualified_idents_links father cco.cco_name);
+ bs b "</code>"
+
+ | Class_constraint (ck, ctk) ->
+ self#html_of_text b [Code "( "] ;
+ self#html_of_class_kind b father ck;
+ self#html_of_text b [Code " : "] ;
+ self#html_of_class_type_kind b father ctk;
+ self#html_of_text b [Code " )"]
+
+ method html_of_class_type_kind b father ?ct kind =
+ match kind with
+ Class_type cta ->
+ (
+ match cta.cta_type_parameters with
+ [] -> ()
+ | l ->
+ self#html_of_class_type_param_expr_list b father l;
+ bs b " "
+ );
+ bs b "<code class=\"type\">";
+ bs b (self#create_fully_qualified_idents_links father cta.cta_name);
+ bs b "</code>"
+
+ | Class_signature (inh, eles) ->
+ self#html_of_text b [Code "object"];
+ (
+ match ct with
+ None ->
+ bs b "\n";
+ (
+ match inh with
+ [] -> ()
+ | _ -> self#generate_inheritance_info b inh
+ );
+ List.iter (self#html_of_class_element b) eles
+ | Some ct ->
+ let (html_file, _) = Naming.html_files ct.clt_name in
+ bp b " <a href=\"%s\">..</a> " html_file
+ );
+ self#html_of_text b [Code "end"]
+
+ (** Print html code for a class. *)
+ method html_of_class b ?(complete=true) ?(with_link=true) c =
+ let father = Name.father c.cl_name in
+ Odoc_info.reset_type_names ();
+ let (html_file, _) = Naming.html_files c.cl_name in
+ bs b "<pre>";
+ (* we add a html id, the same as for a type so we can
+ go directly here when the class name is used as a type name *)
+ bp b "<span name=\"%s\">"
+ (Naming.type_target
+ { ty_name = c.cl_name ;
+ ty_info = None ; ty_parameters = [] ;
+ ty_kind = Type_abstract ; ty_private = Asttypes.Public; ty_manifest = None ;
+ ty_loc = Odoc_info.dummy_loc ;
+ ty_code = None ;
+ }
+ );
+ bs b ((self#keyword "class")^" ");
+ print_DEBUG "html#html_of_class : virtual or not" ;
+ if c.cl_virtual then bs b ((self#keyword "virtual")^" ");
+ (
+ match c.cl_type_parameters with
+ [] -> ()
+ | l ->
+ self#html_of_class_type_param_expr_list b father l;
+ bs b " "
+ );
+ print_DEBUG "html#html_of_class : with link or not" ;
+ (
+ if with_link then
+ bp b "<a href=\"%s\">%s</a>" html_file (Name.simple c.cl_name)
+ else
+ bs b (Name.simple c.cl_name)
+ );
+ bs b "</span>";
+ bs b " : " ;
+ self#html_of_class_parameter_list b father c ;
+ self#html_of_class_kind b father ~cl: c c.cl_kind;
+ bs b "</pre>" ;
+ print_DEBUG "html#html_of_class : info" ;
+ (
+ if complete then
+ self#html_of_info ~indent: false
+ else
+ self#html_of_info_first_sentence
+ ) b c.cl_info
+
+ (** Print html code for a class type. *)
+ method html_of_class_type b ?(complete=true) ?(with_link=true) ct =
+ Odoc_info.reset_type_names ();
+ let father = Name.father ct.clt_name in
+ let (html_file, _) = Naming.html_files ct.clt_name in
+ bs b "<pre>";
+ (* we add a html id, the same as for a type so we can
+ go directly here when the class type name is used as a type name *)
+ bp b "<span id=\"%s\">"
+ (Naming.type_target
+ { ty_name = ct.clt_name ;
+ ty_info = None ; ty_parameters = [] ;
+ ty_kind = Type_abstract ; ty_private = Asttypes.Public; ty_manifest = None ;
+ ty_loc = Odoc_info.dummy_loc ;
+ ty_code = None ;
+ }
+ );
+ bs b ((self#keyword "class type")^" ");
+ if ct.clt_virtual then bs b ((self#keyword "virtual")^" ");
+ (
+ match ct.clt_type_parameters with
+ [] -> ()
+ | l ->
+ self#html_of_class_type_param_expr_list b father l;
+ bs b " "
+ );
+
+ if with_link then
+ bp b "<a href=\"%s\">%s</a>" html_file (Name.simple ct.clt_name)
+ else
+ bs b (Name.simple ct.clt_name);
+
+ bs b "</span>";
+ bs b " = ";
+ self#html_of_class_type_kind b father ~ct ct.clt_kind;
+ bs b "</pre>";
+ (
+ if complete then
+ self#html_of_info ~indent: false
+ else
+ self#html_of_info_first_sentence
+ ) b ct.clt_info
+
+ (** Return html code to represent a dag, represented as in Odoc_dag2html. *)
+ method html_of_dag dag =
+ let f n =
+ let (name, cct_opt) = n.Odoc_dag2html.valu in
+ (* if we have a c_opt = Some class then we take its information
+ because we are sure the name is complete. *)
+ let (name2, html_file) =
+ match cct_opt with
+ None -> (name, fst (Naming.html_files name))
+ | Some (Cl c) -> (c.cl_name, fst (Naming.html_files c.cl_name))
+ | Some (Cltype (ct, _)) -> (ct.clt_name, fst (Naming.html_files ct.clt_name))
+ in
+ let new_v =
+ "<table border=1>\n<tr><td>"^
+ "<a href=\""^html_file^"\">"^name2^"</a>"^
+ "</td></tr>\n</table>\n"
+ in
+ { n with Odoc_dag2html.valu = new_v }
+ in
+ let a = Array.map f dag.Odoc_dag2html.dag in
+ Odoc_dag2html.html_of_dag { Odoc_dag2html.dag = a }
+
+ (** Print html code for a module comment.*)
+ method html_of_module_comment b text =
+ bs b "<br>\n";
+ self#html_of_text b text;
+ bs b "<br>\n"
+
+ (** Print html code for a class comment.*)
+ method html_of_class_comment b text =
+ (* Add some style if there is no style for the first part of the text. *)
+ let text2 =
+ match text with
+ | (Odoc_info.Raw s) :: q ->
+ (Odoc_info.Title (2, None, [Odoc_info.Raw s])) :: q
+ | _ -> text
+ in
+ self#html_of_text b text2
+
+ (** Generate html code for the given list of inherited classes.*)
+ method generate_inheritance_info b inher_l =
+ let f inh =
+ match inh.ic_class with
+ None -> (* we can't make the link. *)
+ (Odoc_info.Code inh.ic_name) ::
+ (match inh.ic_text with
+ None -> []
+ | Some t -> (Odoc_info.Raw " ") :: t)
+ | Some cct ->
+ (* we can create the link. *)
+ let real_name = (* even if it should be the same *)
+ match cct with
+ Cl c -> c.cl_name
+ | Cltype (ct, _) -> ct.clt_name
+ in
+ let (class_file, _) = Naming.html_files real_name in
+ (Odoc_info.Link (class_file, [Odoc_info.Code real_name])) ::
+ (match inh.ic_text with
+ None -> []
+ | Some t -> (Odoc_info.Raw " ") :: t)
+ in
+ let text = [
+ Odoc_info.Bold [Odoc_info.Raw Odoc_messages.inherits] ;
+ Odoc_info.List (List.map f inher_l)
+ ]
+ in
+ self#html_of_text b text
+
+ (** Generate html code for the inherited classes of the given class. *)
+ method generate_class_inheritance_info b cl =
+ let rec iter_kind k =
+ match k with
+ Class_structure ([], _) ->
+ ()
+ | Class_structure (l, _) ->
+ self#generate_inheritance_info b l
+ | Class_constraint (k, ct) ->
+ iter_kind k
+ | Class_apply _
+ | Class_constr _ ->
+ ()
+ in
+ iter_kind cl.cl_kind
+
+ (** Generate html code for the inherited classes of the given class type. *)
+ method generate_class_type_inheritance_info b clt =
+ match clt.clt_kind with
+ Class_signature ([], _) ->
+ ()
+ | Class_signature (l, _) ->
+ self#generate_inheritance_info b l
+ | Class_type _ ->
+ ()
+
+ (** A method to create index files. *)
+ method generate_elements_index :
+ 'a.
+ 'a list ->
+ ('a -> Odoc_info.Name.t) ->
+ ('a -> Odoc_info.info option) ->
+ ('a -> string) -> string -> string -> unit =
+ fun elements name info target title simple_file ->
+ try
+ let chanout = open_out (Filename.concat !Global.target_dir simple_file) in
+ let b = new_buf () in
+ bs b "<html>\n";
+ self#print_header b (self#inner_title title);
+ bs b "<body>\n<center><h1>";
+ bs b title;
+ bs b "</h1></center>\n" ;
+
+ let sorted_elements = List.sort
+ (fun e1 e2 -> compare (Name.simple (name e1)) (Name.simple (name e2)))
+ elements
+ in
+ let groups = Odoc_info.create_index_lists sorted_elements (fun e -> Name.simple (name e)) in
+ let f_ele e =
+ let simple_name = Name.simple (name e) in
+ let father_name = Name.father (name e) in
+ bp b "<tr><td><a href=\"%s\">%s</a> " (target e) (self#escape simple_name);
+ if simple_name <> father_name && father_name <> "" then
+ bp b "[<a href=\"%s\">%s</a>]" (fst (Naming.html_files father_name)) father_name;
+ bs b "</td>\n<td>";
+ self#html_of_info_first_sentence b (info e);
+ bs b "</td></tr>\n";
+ in
+ let f_group l =
+ match l with
+ [] -> ()
+ | e :: _ ->
+ let s =
+ match (Char.uppercase (Name.simple (name e)).[0]) with
+ 'A'..'Z' as c -> String.make 1 c
+ | _ -> ""
+ in
+ bs b "<tr><td align=\"left\"><br>";
+ bs b s ;
+ bs b "</td></tr>\n" ;
+ List.iter f_ele l
+ in
+ bs b "<table>\n";
+ List.iter f_group groups ;
+ bs b "</table><br>\n" ;
+ bs b "</body>\n</html>";
+ Buffer.output_buffer chanout b;
+ close_out chanout
+ with
+ Sys_error s ->
+ raise (Failure s)
+
+ (** A method to generate a list of module/class files. *)
+ method generate_elements :
+ 'a. ('a option -> 'a option -> 'a -> unit) -> 'a list -> unit =
+ fun f_generate l ->
+ let rec iter pre_opt = function
+ [] -> ()
+ | ele :: [] -> f_generate pre_opt None ele
+ | ele1 :: ele2 :: q ->
+ f_generate pre_opt (Some ele2) ele1 ;
+ iter (Some ele1) (ele2 :: q)
+ in
+ iter None l
+
+ (** Generate the code of the html page for the given class.*)
+ method generate_for_class pre post cl =
+ Odoc_info.reset_type_names ();
+ let (html_file, _) = Naming.html_files cl.cl_name in
+ let type_file = Naming.file_type_class_complete_target cl.cl_name in
+ try
+ let chanout = open_out (Filename.concat !Global.target_dir html_file) in
+ let b = new_buf () in
+ let pre_name = opt (fun c -> c.cl_name) pre in
+ let post_name = opt (fun c -> c.cl_name) post in
+ bs b doctype ;
+ bs b "<html>\n";
+ self#print_header b
+ ~nav: (Some (pre_name, post_name, cl.cl_name))
+ ~comments: (Class.class_comments cl)
+ (self#inner_title cl.cl_name);
+ bs b "<body>\n";
+ self#print_navbar b pre_name post_name cl.cl_name;
+ bs b "<center><h1>";
+ bs b (Odoc_messages.clas^" ");
+ if cl.cl_virtual then bs b "virtual " ;
+ bp b "<a href=\"%s\">%s</a>" type_file cl.cl_name;
+ bs b "</h1></center>\n<br>\n";
+ self#html_of_class b ~with_link: false cl;
+ (* parameters *)
+ self#html_of_described_parameter_list b
+ (Name.father cl.cl_name) cl.cl_parameters;
+ (* class inheritance *)
+ self#generate_class_inheritance_info b cl;
+ (* a horizontal line *)
+ bs b "<hr width=\"100%\">\n";
+ (* the various elements *)
+ List.iter (self#html_of_class_element b)
+ (Class.class_elements ~trans:false cl);
+ bs b "</body></html>";
+ Buffer.output_buffer chanout b;
+ close_out chanout;
+
+ (* generate the file with the complete class type *)
+ self#output_class_type
+ cl.cl_name
+ (Filename.concat !Global.target_dir type_file)
+ cl.cl_type
+ with
+ Sys_error s ->
+ raise (Failure s)
+
+ (** Generate the code of the html page for the given class type.*)
+ method generate_for_class_type pre post clt =
+ Odoc_info.reset_type_names ();
+ let (html_file, _) = Naming.html_files clt.clt_name in
+ let type_file = Naming.file_type_class_complete_target clt.clt_name in
+ try
+ let chanout = open_out (Filename.concat !Global.target_dir html_file) in
+ let b = new_buf () in
+ let pre_name = opt (fun ct -> ct.clt_name) pre in
+ let post_name = opt (fun ct -> ct.clt_name) post in
+ bs b doctype ;
+ bs b "<html>\n";
+ self#print_header b
+ ~nav: (Some (pre_name, post_name, clt.clt_name))
+ ~comments: (Class.class_type_comments clt)
+ (self#inner_title clt.clt_name);
+
+ bs b "<body>\n";
+ self#print_navbar b pre_name post_name clt.clt_name;
+ bs b "<center><h1>";
+ bs b (Odoc_messages.class_type^" ");
+ if clt.clt_virtual then bs b "virtual ";
+ bp b "<a href=\"%s\">%s</a>" type_file clt.clt_name;
+ bs b "</h1></center>\n<br>\n";
+ self#html_of_class_type b ~with_link: false clt;
+
+ (* class inheritance *)
+ self#generate_class_type_inheritance_info b clt;
+ (* a horizontal line *)
+ bs b "<hr width=\"100%\">\n";
+ (* the various elements *)
+ List.iter (self#html_of_class_element b)
+ (Class.class_type_elements ~trans: false clt);
+ bs b "</body></html>";
+ Buffer.output_buffer chanout b;
+ close_out chanout;
+
+ (* generate the file with the complete class type *)
+ self#output_class_type
+ clt.clt_name
+ (Filename.concat !Global.target_dir type_file)
+ clt.clt_type
+ with
+ Sys_error s ->
+ raise (Failure s)
+
+ (** Generate the html file for the given module type.
+ @raise Failure if an error occurs.*)
+ method generate_for_module_type pre post mt =
+ try
+ let (html_file, _) = Naming.html_files mt.mt_name in
+ let type_file = Naming.file_type_module_complete_target mt.mt_name in
+ let chanout = open_out (Filename.concat !Global.target_dir html_file) in
+ let b = new_buf () in
+ let pre_name = opt (fun mt -> mt.mt_name) pre in
+ let post_name = opt (fun mt -> mt.mt_name) post in
+ bs b doctype ;
+ bs b "<html>\n";
+ self#print_header b
+ ~nav: (Some (pre_name, post_name, mt.mt_name))
+ ~comments: (Module.module_type_comments mt)
+ (self#inner_title mt.mt_name);
+ bs b "<body>\n";
+ self#print_navbar b pre_name post_name mt.mt_name;
+ bp b "<center><h1>";
+ bs b (Odoc_messages.module_type^" ");
+ (
+ match mt.mt_type with
+ Some _ -> bp b "<a href=\"%s\">%s</a>" type_file mt.mt_name
+ | None-> bs b mt.mt_name
+ );
+ bs b "</h1></center>\n<br>\n" ;
+ self#html_of_modtype b ~with_link: false mt;
+
+ (* parameters for functors *)
+ self#html_of_module_parameter_list b
+ (Name.father mt.mt_name)
+ (Module.module_type_parameters mt);
+ (* a horizontal line *)
+ bs b "<hr width=\"100%\">\n";
+ (* module elements *)
+ List.iter
+ (self#html_of_module_element b (Name.father mt.mt_name))
+ (Module.module_type_elements mt);
+
+ bs b "</body></html>";
+ Buffer.output_buffer chanout b;
+ close_out chanout;
+
+ (* generate html files for submodules *)
+ self#generate_elements self#generate_for_module (Module.module_type_modules mt);
+ (* generate html files for module types *)
+ self#generate_elements self#generate_for_module_type (Module.module_type_module_types mt);
+ (* generate html files for classes *)
+ self#generate_elements self#generate_for_class (Module.module_type_classes mt);
+ (* generate html files for class types *)
+ self#generate_elements self#generate_for_class_type (Module.module_type_class_types mt);
+
+ (* generate the file with the complete module type *)
+ (
+ match mt.mt_type with
+ None -> ()
+ | Some mty ->
+ self#output_module_type
+ mt.mt_name
+ (Filename.concat !Global.target_dir type_file)
+ mty
+ )
+ with
+ Sys_error s ->
+ raise (Failure s)
+
+ (** Generate the html file for the given module.
+ @raise Failure if an error occurs.*)
+ method generate_for_module pre post modu =
+ try
+ Odoc_info.verbose ("Generate for module "^modu.m_name);
+ let (html_file, _) = Naming.html_files modu.m_name in
+ let type_file = Naming.file_type_module_complete_target modu.m_name in
+ let code_file = Naming.file_code_module_complete_target modu.m_name in
+ let chanout = open_out (Filename.concat !Global.target_dir html_file) in
+ let b = new_buf () in
+ let pre_name = opt (fun m -> m.m_name) pre in
+ let post_name = opt (fun m -> m.m_name) post in
+ bs b doctype ;
+ bs b "<html>\n";
+ self#print_header b
+ ~nav: (Some (pre_name, post_name, modu.m_name))
+ ~comments: (Module.module_comments modu)
+ (self#inner_title modu.m_name);
+ bs b "<body>\n" ;
+ self#print_navbar b pre_name post_name modu.m_name ;
+ bs b "<center><h1>";
+ if modu.m_text_only then
+ bs b modu.m_name
+ else
+ (
+ bs b
+ (
+ if Module.module_is_functor modu then
+ Odoc_messages.functo
+ else
+ Odoc_messages.modul
+ );
+ bp b " <a href=\"%s\">%s</a>" type_file modu.m_name;
+ (
+ match modu.m_code with
+ None -> ()
+ | Some _ -> bp b " (<a href=\"%s\">.ml</a>)" code_file
+ )
+ );
+ bs b "</h1></center>\n<br>\n";
+
+ if not modu.m_text_only then self#html_of_module b ~with_link: false modu;
+
+ (* parameters for functors *)
+ self#html_of_module_parameter_list b
+ (Name.father modu.m_name)
+ (Module.module_parameters modu);
+
+ (* a horizontal line *)
+ if not modu.m_text_only then bs b "<hr width=\"100%\">\n";
+
+ (* module elements *)
+ List.iter
+ (self#html_of_module_element b (Name.father modu.m_name))
+ (Module.module_elements modu);
+
+ bs b "</body></html>";
+ Buffer.output_buffer chanout b;
+ close_out chanout;
+
+ (* generate html files for submodules *)
+ self#generate_elements self#generate_for_module (Module.module_modules modu);
+ (* generate html files for module types *)
+ self#generate_elements self#generate_for_module_type (Module.module_module_types modu);
+ (* generate html files for classes *)
+ self#generate_elements self#generate_for_class (Module.module_classes modu);
+ (* generate html files for class types *)
+ self#generate_elements self#generate_for_class_type (Module.module_class_types modu);
+
+ (* generate the file with the complete module type *)
+ self#output_module_type
+ modu.m_name
+ (Filename.concat !Global.target_dir type_file)
+ modu.m_type;
+
+ match modu.m_code with
+ None -> ()
+ | Some code ->
+ self#output_code
+ modu.m_name
+ (Filename.concat !Global.target_dir code_file)
+ code
+ with
+ Sys_error s ->
+ raise (Failure s)
+
+ (** Generate the [<index_prefix>.html] file corresponding to the given module list.
+ @raise Failure if an error occurs.*)
+ method generate_index module_list =
+ try
+ let chanout = open_out (Filename.concat !Global.target_dir self#index) in
+ let b = new_buf () in
+ let title = match !Global.title with None -> "" | Some t -> self#escape t in
+ bs b doctype ;
+ bs b "<html>\n";
+ self#print_header b self#title;
+ bs b "<body>\n";
+ bs b "<center><h1>";
+ bs b title;
+ bs b "</h1></center>\n" ;
+ let info = Odoc_info.apply_opt
+ (Odoc_info.info_of_comment_file module_list)
+ !Odoc_info.Global.intro_file
+ in
+ (
+ match info with
+ None ->
+ self#html_of_Index_list b;
+ bs b "<br/>";
+ self#html_of_Module_list b
+ (List.map (fun m -> m.m_name) module_list);
+ | Some i -> self#html_of_info ~indent: false b info
+ );
+ bs b "</body>\n</html>";
+ Buffer.output_buffer chanout b;
+ close_out chanout
+ with
+ Sys_error s ->
+ raise (Failure s)
+
+ (** Generate the values index in the file [index_values.html]. *)
+ method generate_values_index module_list =
+ self#generate_elements_index
+ self#list_values
+ (fun v -> v.val_name)
+ (fun v -> v.val_info)
+ Naming.complete_value_target
+ Odoc_messages.index_of_values
+ self#index_values
+
+ (** Generate the exceptions index in the file [index_exceptions.html]. *)
+ method generate_exceptions_index module_list =
+ self#generate_elements_index
+ self#list_exceptions
+ (fun e -> e.ex_name)
+ (fun e -> e.ex_info)
+ Naming.complete_exception_target
+ Odoc_messages.index_of_exceptions
+ self#index_exceptions
+
+ (** Generate the types index in the file [index_types.html]. *)
+ method generate_types_index module_list =
+ self#generate_elements_index
+ self#list_types
+ (fun t -> t.ty_name)
+ (fun t -> t.ty_info)
+ Naming.complete_type_target
+ Odoc_messages.index_of_types
+ self#index_types
+
+ (** Generate the attributes index in the file [index_attributes.html]. *)
+ method generate_attributes_index module_list =
+ self#generate_elements_index
+ self#list_attributes
+ (fun a -> a.att_value.val_name)
+ (fun a -> a.att_value.val_info)
+ Naming.complete_attribute_target
+ Odoc_messages.index_of_attributes
+ self#index_attributes
+
+ (** Generate the methods index in the file [index_methods.html]. *)
+ method generate_methods_index module_list =
+ self#generate_elements_index
+ self#list_methods
+ (fun m -> m.met_value.val_name)
+ (fun m -> m.met_value.val_info)
+ Naming.complete_method_target
+ Odoc_messages.index_of_methods
+ self#index_methods
+
+ (** Generate the classes index in the file [index_classes.html]. *)
+ method generate_classes_index module_list =
+ self#generate_elements_index
+ self#list_classes
+ (fun c -> c.cl_name)
+ (fun c -> c.cl_info)
+ (fun c -> fst (Naming.html_files c.cl_name))
+ Odoc_messages.index_of_classes
+ self#index_classes
+
+ (** Generate the class types index in the file [index_class_types.html]. *)
+ method generate_class_types_index module_list =
+ self#generate_elements_index
+ self#list_class_types
+ (fun ct -> ct.clt_name)
+ (fun ct -> ct.clt_info)
+ (fun ct -> fst (Naming.html_files ct.clt_name))
+ Odoc_messages.index_of_class_types
+ self#index_class_types
+
+ (** Generate the modules index in the file [index_modules.html]. *)
+ method generate_modules_index module_list =
+ self#generate_elements_index
+ self#list_modules
+ (fun m -> m.m_name)
+ (fun m -> m.m_info)
+ (fun m -> fst (Naming.html_files m.m_name))
+ Odoc_messages.index_of_modules
+ self#index_modules
+
+ (** Generate the module types index in the file [index_module_types.html]. *)
+ method generate_module_types_index module_list =
+ self#generate_elements_index
+ self#list_module_types
+ (fun mt -> mt.mt_name)
+ (fun mt -> mt.mt_info)
+ (fun mt -> fst (Naming.html_files mt.mt_name))
+ Odoc_messages.index_of_module_types
+ self#index_module_types
+
+ (** Generate all the html files from a module list. The main
+ file is [<index_prefix>.html]. *)
+ method generate module_list =
+ (* init the style *)
+ self#init_style ;
+ (* init the lists of elements *)
+ list_values <- Odoc_info.Search.values module_list ;
+ list_exceptions <- Odoc_info.Search.exceptions module_list ;
+ list_types <- Odoc_info.Search.types module_list ;
+ list_attributes <- Odoc_info.Search.attributes module_list ;
+ list_methods <- Odoc_info.Search.methods module_list ;
+ list_classes <- Odoc_info.Search.classes module_list ;
+ list_class_types <- Odoc_info.Search.class_types module_list ;
+ list_modules <- Odoc_info.Search.modules module_list ;
+ list_module_types <- Odoc_info.Search.module_types module_list ;
+
+ (* prepare the page header *)
+ self#prepare_header module_list ;
+ (* Get the names of all known types. *)
+ let types = Odoc_info.Search.types module_list in
+ known_types_names <-
+ List.fold_left
+ (fun acc t -> StringSet.add t.ty_name acc)
+ known_types_names
+ types ;
+ (* Get the names of all class and class types. *)
+ let classes = Odoc_info.Search.classes module_list in
+ let class_types = Odoc_info.Search.class_types module_list in
+ known_classes_names <-
+ List.fold_left
+ (fun acc c -> StringSet.add c.cl_name acc)
+ known_classes_names
+ classes ;
+ known_classes_names <-
+ List.fold_left
+ (fun acc ct -> StringSet.add ct.clt_name acc)
+ known_classes_names
+ class_types ;
+ (* Get the names of all known modules and module types. *)
+ let module_types = Odoc_info.Search.module_types module_list in
+ let modules = Odoc_info.Search.modules module_list in
+ known_modules_names <-
+ List.fold_left
+ (fun acc m -> StringSet.add m.m_name acc)
+ known_modules_names
+ modules ;
+ known_modules_names <-
+ List.fold_left
+ (fun acc mt -> StringSet.add mt.mt_name acc)
+ known_modules_names
+ module_types ;
+ (* generate html for each module *)
+ if not !index_only then
+ self#generate_elements self#generate_for_module module_list ;
+
+ try
+ self#generate_index module_list;
+ self#generate_values_index module_list ;
+ self#generate_exceptions_index module_list ;
+ self#generate_types_index module_list ;
+ self#generate_attributes_index module_list ;
+ self#generate_methods_index module_list ;
+ self#generate_classes_index module_list ;
+ self#generate_class_types_index module_list ;
+ self#generate_modules_index module_list ;
+ self#generate_module_types_index module_list ;
+ with
+ Failure s ->
+ prerr_endline s ;
+ incr Odoc_info.errors
+
+ initializer
+ Odoc_ocamlhtml.html_of_comment :=
+ (fun s ->
+ let b = new_buf () in
+ self#html_of_text b (Odoc_text.Texter.text_of_string s);
+ Buffer.contents b
+ )
+ end
+end
+
+module type Html_generator = module type of Generator
diff --git a/ocaml-binary-annot/ocamldoc/odoc_info.ml b/ocaml-binary-annot/ocamldoc/odoc_info.ml
new file mode 100644
index 0000000000..061d091f53
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_info.ml
@@ -0,0 +1,323 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Interface for analysing documented OCaml source files and to the collected information. *)
+
+type ref_kind = Odoc_types.ref_kind =
+ RK_module
+ | RK_module_type
+ | RK_class
+ | RK_class_type
+ | RK_value
+ | RK_type
+ | RK_exception
+ | RK_attribute
+ | RK_method
+ | RK_section of text
+
+and text_element = Odoc_types.text_element =
+ | Raw of string
+ | Code of string
+ | CodePre of string
+ | Verbatim of string
+ | Bold of text
+ | Italic of text
+ | Emphasize of text
+ | Center of text
+ | Left of text
+ | Right of text
+ | List of text list
+ | Enum of text list
+ | Newline
+ | Block of text
+ | Title of int * string option * text
+ | Latex of string
+ | Link of string * text
+ | Ref of string * ref_kind option * text option
+ | Superscript of text
+ | Subscript of text
+ | Module_list of string list
+ | Index_list
+ | Custom of string * text
+ | Target of string * string
+
+and text = text_element list
+
+exception Text_syntax = Odoc_text.Text_syntax
+
+type see_ref = Odoc_types.see_ref =
+ See_url of string
+ | See_file of string
+ | See_doc of string
+
+type see = see_ref * text
+
+type param = (string * text)
+
+type raised_exception = (string * text)
+
+type info = Odoc_types.info = {
+ i_desc : text option;
+ i_authors : string list;
+ i_version : string option;
+ i_sees : see list;
+ i_since : string option;
+ i_before : (string * text) list ;
+ i_deprecated : text option;
+ i_params : param list;
+ i_raised_exceptions : raised_exception list;
+ i_return_value : text option ;
+ i_custom : (string * text) list ;
+ }
+
+type location = Odoc_types.location = {
+ loc_impl : (string * int) option ;
+ loc_inter : (string * int) option ;
+ }
+
+let dummy_loc = { loc_impl = None ; loc_inter = None }
+
+module Name = Odoc_name
+module Parameter = Odoc_parameter
+module Exception = Odoc_exception
+module Type = Odoc_type
+module Value = Odoc_value
+module Class = Odoc_class
+module Module = Odoc_module
+
+
+let analyse_files
+ ?(merge_options=([] : Odoc_types.merge_option list))
+ ?(include_dirs=([] : string list))
+ ?(labels=false)
+ ?(sort_modules=false)
+ ?(no_stop=false)
+ ?(init=[])
+ files =
+ Odoc_global.merge_options := merge_options;
+ Odoc_global.include_dirs := include_dirs;
+ Odoc_global.classic := not labels;
+ Odoc_global.sort_modules := sort_modules;
+ Odoc_global.no_stop := no_stop;
+ Odoc_analyse.analyse_files ~init: init files
+
+let dump_modules = Odoc_analyse.dump_modules
+
+let load_modules = Odoc_analyse.load_modules
+
+let reset_type_names = Printtyp.reset
+
+let string_of_variance t (co,cn) = Odoc_str.string_of_variance t (co, cn)
+
+let string_of_type_expr t = Odoc_print.string_of_type_expr t
+
+let string_of_class_params = Odoc_str.string_of_class_params
+
+let string_of_type_list ?par sep type_list = Odoc_str.string_of_type_list ?par sep type_list
+
+let string_of_type_param_list t = Odoc_str.string_of_type_param_list t
+
+let string_of_class_type_param_list l = Odoc_str.string_of_class_type_param_list l
+
+let string_of_module_type = Odoc_print.string_of_module_type
+
+let string_of_class_type = Odoc_print.string_of_class_type
+
+let string_of_text t = Odoc_misc.string_of_text t
+
+let string_of_info i = Odoc_misc.string_of_info i
+
+let string_of_type t = Odoc_str.string_of_type t
+
+let string_of_exception e = Odoc_str.string_of_exception e
+
+let string_of_value v = Odoc_str.string_of_value v
+
+let string_of_attribute att = Odoc_str.string_of_attribute att
+
+let string_of_method m = Odoc_str.string_of_method m
+
+let first_sentence_of_text = Odoc_misc.first_sentence_of_text
+
+let first_sentence_and_rest_of_text = Odoc_misc.first_sentence_and_rest_of_text
+
+let text_no_title_no_list = Odoc_misc.text_no_title_no_list
+
+let text_concat = Odoc_misc.text_concat
+
+let get_titles_in_text = Odoc_misc.get_titles_in_text
+
+let create_index_lists = Odoc_misc.create_index_lists
+
+let remove_ending_newline = Odoc_misc.remove_ending_newline
+
+let remove_option = Odoc_misc.remove_option
+
+let is_optional = Odoc_misc.is_optional
+
+let label_name = Odoc_misc.label_name
+
+let use_hidden_modules n =
+ Odoc_name.hide_given_modules !Odoc_global.hidden_modules n
+
+let verbose s =
+ if !Odoc_global.verbose then
+ (print_string s ; print_newline ())
+ else
+ ()
+
+let warning s = Odoc_global.pwarning s
+let print_warnings = Odoc_config.print_warnings
+
+let errors = Odoc_global.errors
+
+let apply_opt = Odoc_misc.apply_opt
+
+let apply_if_equal f v1 v2 =
+ if v1 = v2 then
+ f v1
+ else
+ v2
+
+let text_of_string = Odoc_text.Texter.text_of_string
+
+let text_string_of_text = Odoc_text.Texter.string_of_text
+
+
+let escape_arobas s =
+ let len = String.length s in
+ let b = Buffer.create len in
+ for i = 0 to len - 1 do
+ match s.[i] with
+ '@' -> Buffer.add_string b "\\@"
+ | c -> Buffer.add_char b c
+ done;
+ Buffer.contents b
+
+let info_string_of_info i =
+ let b = Buffer.create 256 in
+ let p = Printf.bprintf in
+ (
+ match i.i_desc with
+ None -> ()
+ | Some t -> p b "%s" (escape_arobas (text_string_of_text t))
+ );
+ List.iter
+ (fun s -> p b "\n@author %s" (escape_arobas s))
+ i.i_authors;
+ (
+ match i.i_version with
+ None -> ()
+ | Some s -> p b "\n@version %s" (escape_arobas s)
+ );
+ (
+ (* TODO: escape characters ? *)
+ let f_see_ref = function
+ See_url s -> Printf.sprintf "<%s>" s
+ | See_file s -> Printf.sprintf "'%s'" s
+ | See_doc s -> Printf.sprintf "\"%s\"" s
+ in
+ List.iter
+ (fun (sref, t) ->
+ p b "\n@see %s %s"
+ (escape_arobas (f_see_ref sref))
+ (escape_arobas (text_string_of_text t))
+ )
+ i.i_sees
+ );
+ (
+ match i.i_since with
+ None -> ()
+ | Some s -> p b "\n@since %s" (escape_arobas s)
+ );
+ (
+ match i.i_deprecated with
+ None -> ()
+ | Some t ->
+ p b "\n@deprecated %s"
+ (escape_arobas (text_string_of_text t))
+ );
+ List.iter
+ (fun (s, t) ->
+ p b "\n@param %s %s"
+ (escape_arobas s)
+ (escape_arobas (text_string_of_text t))
+ )
+ i.i_params;
+ List.iter
+ (fun (s, t) ->
+ p b "\n@raise %s %s"
+ (escape_arobas s)
+ (escape_arobas (text_string_of_text t))
+ )
+ i.i_raised_exceptions;
+ (
+ match i.i_return_value with
+ None -> ()
+ | Some t ->
+ p b "\n@return %s"
+ (escape_arobas (text_string_of_text t))
+ );
+ List.iter
+ (fun (s, t) ->
+ p b "\n@%s %s" s
+ (escape_arobas (text_string_of_text t))
+ )
+ i.i_custom;
+
+ Buffer.contents b
+
+let info_of_string = Odoc_comments.info_of_string
+let info_of_comment_file = Odoc_comments.info_of_comment_file
+
+module Search =
+ struct
+ type result_element = Odoc_search.result_element =
+ Res_module of Module.t_module
+ | Res_module_type of Module.t_module_type
+ | Res_class of Class.t_class
+ | Res_class_type of Class.t_class_type
+ | Res_value of Value.t_value
+ | Res_type of Type.t_type
+ | Res_exception of Exception.t_exception
+ | Res_attribute of Value.t_attribute
+ | Res_method of Value.t_method
+ | Res_section of string * text
+
+ type search_result = result_element list
+
+ let search_by_name = Odoc_search.Search_by_name.search
+
+ let values = Odoc_search.values
+ let exceptions = Odoc_search.exceptions
+ let types = Odoc_search.types
+ let attributes = Odoc_search.attributes
+ let methods = Odoc_search.methods
+ let classes = Odoc_search.classes
+ let class_types = Odoc_search.class_types
+ let modules = Odoc_search.modules
+ let module_types = Odoc_search.module_types
+ end
+
+module Scan =
+ struct
+ class scanner = Odoc_scan.scanner
+ end
+
+module Dep =
+ struct
+ let kernel_deps_of_modules = Odoc_dep.kernel_deps_of_modules
+ let deps_of_types = Odoc_dep.deps_of_types
+ end
+
+module Global = Odoc_global
diff --git a/ocaml-binary-annot/ocamldoc/odoc_info.mli b/ocaml-binary-annot/ocamldoc/odoc_info.mli
new file mode 100644
index 0000000000..c106b040b7
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_info.mli
@@ -0,0 +1,988 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Interface to the information collected in source files. *)
+
+(** The differents kinds of element references. *)
+type ref_kind = Odoc_types.ref_kind =
+ RK_module
+ | RK_module_type
+ | RK_class
+ | RK_class_type
+ | RK_value
+ | RK_type
+ | RK_exception
+ | RK_attribute
+ | RK_method
+ | RK_section of text
+
+and text_element = Odoc_types.text_element =
+ | Raw of string (** Raw text. *)
+ | Code of string (** The string is source code. *)
+ | CodePre of string (** The string is pre-formatted source code. *)
+ | Verbatim of string (** String 'as is'. *)
+ | Bold of text (** Text in bold style. *)
+ | Italic of text (** Text in italic. *)
+ | Emphasize of text (** Emphasized text. *)
+ | Center of text (** Centered text. *)
+ | Left of text (** Left alignment. *)
+ | Right of text (** Right alignment. *)
+ | List of text list (** A list. *)
+ | Enum of text list (** An enumerated list. *)
+ | Newline (** To force a line break. *)
+ | Block of text (** Like html's block quote. *)
+ | Title of int * string option * text
+ (** Style number, optional label, and text. *)
+ | Latex of string (** A string for latex. *)
+ | Link of string * text (** A reference string and the link text. *)
+ | Ref of string * ref_kind option * text option
+ (** A reference to an element. Complete name and kind.
+ An optional text can be given to display this text instead
+ of the element name.*)
+ | Superscript of text (** Superscripts. *)
+ | Subscript of text (** Subscripts. *)
+ | Module_list of string list
+ (** The table of the given modules with their abstract. *)
+ | Index_list (** The links to the various indexes (values, types, ...) *)
+ | Custom of string * text (** to extend \{foo syntax *)
+ | Target of string * string (** (target, code) : to specify code specific to a target format *)
+
+(** A text is a list of [text_element]. The order matters. *)
+and text = text_element list
+
+(** The different forms of references in \@see tags. *)
+type see_ref = Odoc_types.see_ref =
+ See_url of string
+ | See_file of string
+ | See_doc of string
+
+(** Raised when parsing string to build a {!Odoc_info.text}
+ structure. [(line, char, string)] *)
+exception Text_syntax of int * int * string
+
+(** The information in a \@see tag. *)
+type see = see_ref * text
+
+(** Parameter name and description. *)
+type param = (string * text)
+
+(** Raised exception name and description. *)
+type raised_exception = (string * text)
+
+(** Information in a special comment
+@before 3.12.0 \@before information was not present.
+*)
+type info = Odoc_types.info = {
+ i_desc : text option; (** The description text. *)
+ i_authors : string list; (** The list of authors in \@author tags. *)
+ i_version : string option; (** The string in the \@version tag. *)
+ i_sees : see list; (** The list of \@see tags. *)
+ i_since : string option; (** The string in the \@since tag. *)
+ i_before : (string * text) list ; (** the version number and text in \@before tag *)
+ i_deprecated : text option; (** The of the \@deprecated tag. *)
+ i_params : param list; (** The list of parameter descriptions. *)
+ i_raised_exceptions : raised_exception list; (** The list of raised exceptions. *)
+ i_return_value : text option; (** The description text of the return value. *)
+ i_custom : (string * text) list ; (** A text associated to a custom @-tag. *)
+ }
+
+(** Location of elements in implementation and interface files. *)
+type location = Odoc_types.location = {
+ loc_impl : (string * int) option ; (** implementation file name and position *)
+ loc_inter : (string * int) option ; (** interface file name and position *)
+ }
+
+(** A dummy location. *)
+val dummy_loc : location
+
+(** Representation of element names. *)
+module Name :
+ sig
+ type t = string
+
+ (** Access to the simple name. *)
+ val simple : t -> t
+
+ (** [concat t1 t2] returns the concatenation of [t1] and [t2].*)
+ val concat : t -> t -> t
+
+ (** Return the depth of the name, i.e. the numer of levels to the root.
+ Example : [depth "Toto.Tutu.name"] = [3]. *)
+ val depth : t -> int
+
+ (** Take two names n1 and n2 = n3.n4 and return n4 if n3=n1 or else n2. *)
+ val get_relative : t -> t -> t
+
+ (** Return the name of the 'father' (like [dirname] for a file name).*)
+ val father : t -> t
+ end
+
+(** Representation and manipulation of method / function / class / module parameters.*)
+module Parameter :
+ sig
+ (** {3 Types} *)
+ (** Representation of a simple parameter name *)
+ type simple_name = Odoc_parameter.simple_name =
+ {
+ sn_name : string ;
+ sn_type : Types.type_expr ;
+ mutable sn_text : text option ;
+ }
+
+ (** Representation of parameter names. We need it to represent parameter names in tuples.
+ The value [Tuple ([], t)] stands for an anonymous parameter.*)
+ type param_info = Odoc_parameter.param_info =
+ Simple_name of simple_name
+ | Tuple of param_info list * Types.type_expr
+
+ (** A parameter is just a param_info.*)
+ type parameter = param_info
+
+ (** {3 Functions} *)
+ (** Acces to the name as a string. For tuples, parenthesis and commas are added. *)
+ val complete_name : parameter -> string
+
+ (** Access to the complete type. *)
+ val typ : parameter -> Types.type_expr
+
+ (** Access to the list of names ; only one for a simple parameter, or
+ a list for a tuple. *)
+ val names : parameter -> string list
+
+ (** Access to the description of a specific name.
+ @raise Not_found if no description is associated to the given name. *)
+ val desc_by_name : parameter -> string -> text option
+
+ (** Access to the type of a specific name.
+ @raise Not_found if no type is associated to the given name. *)
+ val type_by_name : parameter -> string -> Types.type_expr
+ end
+
+(** Representation and manipulation of exceptions. *)
+module Exception :
+ sig
+ (** Used when the exception is a rebind of another exception,
+ when we have [exception Ex = Target_ex].*)
+ type exception_alias = Odoc_exception.exception_alias =
+ {
+ ea_name : Name.t ; (** The complete name of the target exception. *)
+ mutable ea_ex : t_exception option ; (** The target exception, if we found it.*)
+ }
+
+ and t_exception = Odoc_exception.t_exception =
+ {
+ ex_name : Name.t ;
+ mutable ex_info : info option ; (** Information found in the optional associated comment. *)
+ ex_args : Types.type_expr list ; (** The types of the parameters. *)
+ ex_alias : exception_alias option ; (** [None] when the exception is not a rebind. *)
+ mutable ex_loc : location ;
+ mutable ex_code : string option ;
+ }
+ end
+
+(** Representation and manipulation of types.*)
+module Type :
+ sig
+ type private_flag = Odoc_type.private_flag =
+ Private | Public
+
+ (** Description of a variant type constructor. *)
+ type variant_constructor = Odoc_type.variant_constructor =
+ {
+ vc_name : string ; (** Name of the constructor. *)
+ vc_args : Types.type_expr list ; (** Arguments of the constructor. *)
+ mutable vc_text : text option ; (** Optional description in the associated comment. *)
+ }
+
+ (** Description of a record type field. *)
+ type record_field = Odoc_type.record_field =
+ {
+ rf_name : string ; (** Name of the field. *)
+ rf_mutable : bool ; (** [true] if mutable. *)
+ rf_type : Types.type_expr ; (** Type of the field. *)
+ mutable rf_text : text option ; (** Optional description in the associated comment.*)
+ }
+
+ (** The various kinds of a type. *)
+ type type_kind = Odoc_type.type_kind =
+ Type_abstract (** Type is abstract, for example [type t]. *)
+ | Type_variant of variant_constructor list
+ (** constructors *)
+ | Type_record of record_field list
+ (** fields *)
+
+ (** Representation of a type. *)
+ type t_type = Odoc_type.t_type =
+ {
+ ty_name : Name.t ; (** Complete name of the type. *)
+ mutable ty_info : info option ; (** Information found in the optional associated comment. *)
+ ty_parameters : (Types.type_expr * bool * bool) list ;
+ (** type parameters: (type, covariant, contravariant) *)
+ ty_kind : type_kind; (** Type kind. *)
+ ty_private : private_flag; (** Private or public type. *)
+ ty_manifest : Types.type_expr option; (** Type manifest. *)
+ mutable ty_loc : location ;
+ mutable ty_code : string option;
+ }
+
+ end
+
+(** Representation and manipulation of values, class attributes and class methods. *)
+module Value :
+ sig
+ (** Representation of a value. *)
+ type t_value = Odoc_value.t_value =
+ {
+ val_name : Name.t ; (** Complete name of the value. *)
+ mutable val_info : info option ; (** Information found in the optional associated comment. *)
+ val_type : Types.type_expr ; (** Type of the value. *)
+ val_recursive : bool ; (** [true] if the value is recursive. *)
+ mutable val_parameters : Odoc_parameter.parameter list ; (** The parameters, if any. *)
+ mutable val_code : string option ; (** The code of the value, if we had the only the implementation file. *)
+ mutable val_loc : location ;
+ }
+
+ (** Representation of a class attribute. *)
+ type t_attribute = Odoc_value.t_attribute =
+ {
+ att_value : t_value ; (** an attribute has almost all the same information as a value *)
+ att_mutable : bool ; (** [true] if the attribute is mutable. *)
+ att_virtual : bool ; (** [true] if the attribute is virtual. *)
+ }
+
+ (** Representation of a class method. *)
+ type t_method = Odoc_value.t_method =
+ {
+ met_value : t_value ; (** a method has almost all the same information as a value *)
+ met_private : bool ; (** [true] if the method is private.*)
+ met_virtual : bool ; (** [true] if the method is virtual. *)
+ }
+
+ (** Return [true] if the value is a function, i.e. it has a functional type. *)
+ val is_function : t_value -> bool
+
+ (** Access to the description associated to the given parameter name.*)
+ val value_parameter_text_by_name : t_value -> string -> text option
+ end
+
+(** Representation and manipulation of classes and class types.*)
+module Class :
+ sig
+ (** {3 Types} *)
+ (** To keep the order of elements in a class. *)
+ type class_element = Odoc_class.class_element =
+ Class_attribute of Value.t_attribute
+ | Class_method of Value.t_method
+ | Class_comment of text
+
+ (** Used when we can reference a t_class or a t_class_type. *)
+ type cct = Odoc_class.cct =
+ Cl of t_class
+ | Cltype of t_class_type * Types.type_expr list (** Class type and type parameters. *)
+
+ and inherited_class = Odoc_class.inherited_class =
+ {
+ ic_name : Name.t ; (** Complete name of the inherited class. *)
+ mutable ic_class : cct option ; (** The associated t_class or t_class_type. *)
+ ic_text : text option ; (** The inheritance description, if any. *)
+ }
+
+ and class_apply = Odoc_class.class_apply =
+ {
+ capp_name : Name.t ; (** The complete name of the applied class. *)
+ mutable capp_class : t_class option; (** The associated t_class if we found it. *)
+ capp_params : Types.type_expr list; (** The type of expressions the class is applied to. *)
+ capp_params_code : string list ; (** The code of these exprssions. *)
+ }
+
+ and class_constr = Odoc_class.class_constr =
+ {
+ cco_name : Name.t ; (** The complete name of the applied class. *)
+ mutable cco_class : cct option;
+ (** The associated class or class type if we found it. *)
+ cco_type_parameters : Types.type_expr list; (** The type parameters of the class, if needed. *)
+ }
+
+ and class_kind = Odoc_class.class_kind =
+ Class_structure of inherited_class list * class_element list
+ (** An explicit class structure, used in implementation and interface. *)
+ | Class_apply of class_apply
+ (** Application/alias of a class, used in implementation only. *)
+ | Class_constr of class_constr
+ (** A class used to give the type of the defined class,
+ instead of a structure, used in interface only.
+ For example, it will be used with the name [M1.M2....bar]
+ when the class foo is defined like this :
+ [class foo : int -> bar] *)
+ | Class_constraint of class_kind * class_type_kind
+ (** A class definition with a constraint. *)
+
+ (** Representation of a class. *)
+ and t_class = Odoc_class.t_class =
+ {
+ cl_name : Name.t ; (** Complete name of the class. *)
+ mutable cl_info : info option ; (** Information found in the optional associated comment. *)
+ cl_type : Types.class_type ; (** Type of the class. *)
+ cl_type_parameters : Types.type_expr list ; (** Type parameters. *)
+ cl_virtual : bool ; (** [true] when the class is virtual. *)
+ mutable cl_kind : class_kind ; (** The way the class is defined. *)
+ mutable cl_parameters : Parameter.parameter list ; (** The parameters of the class. *)
+ mutable cl_loc : location ;
+ }
+
+ and class_type_alias = Odoc_class.class_type_alias =
+ {
+ cta_name : Name.t ; (** Complete name of the target class type. *)
+ mutable cta_class : cct option ; (** The target t_class or t_class_type, if we found it.*)
+ cta_type_parameters : Types.type_expr list ; (** The type parameters. A VOIR : mettre des string ? *)
+ }
+
+ and class_type_kind = Odoc_class.class_type_kind =
+ Class_signature of inherited_class list * class_element list
+ | Class_type of class_type_alias (** A class type eventually applied to type args. *)
+
+ (** Representation of a class type. *)
+ and t_class_type = Odoc_class.t_class_type =
+ {
+ clt_name : Name.t ; (** Complete name of the type. *)
+ mutable clt_info : info option ; (** Information found in the optional associated comment. *)
+ clt_type : Types.class_type ;
+ clt_type_parameters : Types.type_expr list ; (** Type parameters. *)
+ clt_virtual : bool ; (** [true] if the class type is virtual *)
+ mutable clt_kind : class_type_kind ; (** The way the class type is defined. *)
+ mutable clt_loc : location ;
+ }
+
+ (** {3 Functions} *)
+
+ (** Access to the elements of a class. *)
+ val class_elements : ?trans:bool -> t_class -> class_element list
+
+ (** Access to the list of class attributes. *)
+ val class_attributes : ?trans:bool -> t_class -> Value.t_attribute list
+
+ (** Access to the description associated to the given class parameter name. *)
+ val class_parameter_text_by_name : t_class -> string -> text option
+
+ (** Access to the methods of a class. *)
+ val class_methods : ?trans:bool -> t_class -> Value.t_method list
+
+ (** Access to the comments of a class. *)
+ val class_comments : ?trans:bool -> t_class -> text list
+
+ (** Access to the elements of a class type. *)
+ val class_type_elements : ?trans:bool -> t_class_type -> class_element list
+
+ (** Access to the list of class type attributes. *)
+ val class_type_attributes : ?trans:bool -> t_class_type -> Value.t_attribute list
+
+ (** Access to the description associated to the given class type parameter name. *)
+ val class_type_parameter_text_by_name : t_class_type -> string -> text option
+
+ (** Access to the methods of a class type. *)
+ val class_type_methods : ?trans:bool -> t_class_type -> Value.t_method list
+
+ (** Access to the comments of a class type. *)
+ val class_type_comments : ?trans:bool -> t_class_type -> text list
+ end
+
+(** Representation and manipulation of modules and module types. *)
+module Module :
+ sig
+ (** {3 Types} *)
+ (** To keep the order of elements in a module. *)
+ type module_element = Odoc_module.module_element =
+ Element_module of t_module
+ | Element_module_type of t_module_type
+ | Element_included_module of included_module
+ | Element_class of Class.t_class
+ | Element_class_type of Class.t_class_type
+ | Element_value of Value.t_value
+ | Element_exception of Exception.t_exception
+ | Element_type of Type.t_type
+ | Element_module_comment of text
+
+ (** Used where we can reference t_module or t_module_type. *)
+ and mmt = Odoc_module.mmt =
+ | Mod of t_module
+ | Modtype of t_module_type
+
+ and included_module = Odoc_module.included_module =
+ {
+ im_name : Name.t ; (** Complete name of the included module. *)
+ mutable im_module : mmt option ; (** The included module or module type, if we found it. *)
+ mutable im_info : Odoc_types.info option ; (** comment associated to the includ directive *)
+ }
+
+ and module_alias = Odoc_module.module_alias =
+ {
+ ma_name : Name.t ; (** Complete name of the target module. *)
+ mutable ma_module : mmt option ; (** The real module or module type if we could associate it. *)
+ }
+
+ and module_parameter = Odoc_module.module_parameter = {
+ mp_name : string ; (** the name *)
+ mp_type : Types.module_type ; (** the type *)
+ mp_type_code : string ; (** the original code *)
+ mp_kind : module_type_kind ; (** the way the parameter was built *)
+ }
+
+ (** Different kinds of a module. *)
+ and module_kind = Odoc_module.module_kind =
+ | Module_struct of module_element list (** A complete module structure. *)
+ | Module_alias of module_alias (** Complete name and corresponding module if we found it *)
+ | Module_functor of module_parameter * module_kind
+ (** A functor, with its parameter and the rest of its definition *)
+ | Module_apply of module_kind * module_kind
+ (** A module defined by application of a functor. *)
+ | Module_with of module_type_kind * string
+ (** A module whose type is a with ... constraint.
+ Should appear in interface files only. *)
+ | Module_constraint of module_kind * module_type_kind
+ (** A module constraint by a module type. *)
+ | Module_typeof of string (** by now only the code of the module expression *)
+ | Module_unpack of string * module_type_alias (** code of the expression and module type alias *)
+
+ (** Representation of a module. *)
+ and t_module = Odoc_module.t_module =
+ {
+ m_name : Name.t ; (** Complete name of the module. *)
+ mutable m_type : Types.module_type ; (** The type of the module. *)
+ mutable m_info : info option ; (** Information found in the optional associated comment. *)
+ m_is_interface : bool ; (** [true] for modules read from interface files *)
+ m_file : string ; (** The file the module is defined in. *)
+ mutable m_kind : module_kind ; (** The way the module is defined. *)
+ mutable m_loc : location ;
+ mutable m_top_deps : Name.t list ; (** The toplevels module names this module depends on. *)
+ mutable m_code : string option ; (** The whole code of the module *)
+ mutable m_code_intf : string option ; (** The whole code of the interface of the module *)
+ m_text_only : bool ; (** [true] if the module comes from a text file *)
+ }
+
+ and module_type_alias = Odoc_module.module_type_alias =
+ {
+ mta_name : Name.t ; (** Complete name of the target module type. *)
+ mutable mta_module : t_module_type option ; (** The real module type if we could associate it. *)
+ }
+
+ (** Different kinds of module type. *)
+ and module_type_kind = Odoc_module.module_type_kind =
+ | Module_type_struct of module_element list (** A complete module signature. *)
+ | Module_type_functor of module_parameter * module_type_kind
+ (** A functor, with its parameter and the rest of its definition *)
+ | Module_type_alias of module_type_alias
+ (** Complete alias name and corresponding module type if we found it. *)
+ | Module_type_with of module_type_kind * string
+ (** The module type kind and the code of the with constraint. *)
+ | Module_type_typeof of string
+ (** by now only the code of the module expression *)
+
+ (** Representation of a module type. *)
+ and t_module_type = Odoc_module.t_module_type =
+ {
+ mt_name : Name.t ; (** Complete name of the module type. *)
+ mutable mt_info : info option ; (** Information found in the optional associated comment. *)
+ mutable mt_type : Types.module_type option ; (** [None] means that the module type is abstract. *)
+ mt_is_interface : bool ; (** [true] for modules read from interface files. *)
+ mt_file : string ; (** The file the module type is defined in. *)
+ mutable mt_kind : module_type_kind option ;
+ (** The way the module is defined. [None] means that module type is abstract.
+ It is always [None] when the module type was extracted from the implementation file.
+ That means module types are only analysed in interface files. *)
+ mutable mt_loc : location ;
+ }
+
+ (** {3 Functions for modules} *)
+
+ (** Access to the elements of a module. *)
+ val module_elements : ?trans:bool -> t_module -> module_element list
+
+ (** Access to the submodules of a module. *)
+ val module_modules : ?trans:bool -> t_module -> t_module list
+
+ (** Access to the module types of a module. *)
+ val module_module_types : ?trans:bool -> t_module -> t_module_type list
+
+ (** Access to the included modules of a module. *)
+ val module_included_modules : ?trans:bool-> t_module -> included_module list
+
+ (** Access to the exceptions of a module. *)
+ val module_exceptions : ?trans:bool-> t_module -> Exception.t_exception list
+
+ (** Access to the types of a module. *)
+ val module_types : ?trans:bool-> t_module -> Type.t_type list
+
+ (** Access to the values of a module. *)
+ val module_values : ?trans:bool -> t_module -> Value.t_value list
+
+ (** Access to functional values of a module. *)
+ val module_functions : ?trans:bool-> t_module -> Value.t_value list
+
+ (** Access to non-functional values of a module. *)
+ val module_simple_values : ?trans:bool-> t_module -> Value.t_value list
+
+ (** Access to the classes of a module. *)
+ val module_classes : ?trans:bool-> t_module -> Class.t_class list
+
+ (** Access to the class types of a module. *)
+ val module_class_types : ?trans:bool-> t_module -> Class.t_class_type list
+
+ (** The list of classes defined in this module and all its submodules and functors. *)
+ val module_all_classes : ?trans:bool-> t_module -> Class.t_class list
+
+ (** [true] if the module is functor. *)
+ val module_is_functor : t_module -> bool
+
+ (** The list of couples (module parameter, optional description). *)
+ val module_parameters : ?trans:bool-> t_module -> (module_parameter * text option) list
+
+ (** The list of module comments. *)
+ val module_comments : ?trans:bool-> t_module -> text list
+
+ (** {3 Functions for module types} *)
+
+ (** Access to the elements of a module type. *)
+ val module_type_elements : ?trans:bool-> t_module_type -> module_element list
+
+ (** Access to the submodules of a module type. *)
+ val module_type_modules : ?trans:bool-> t_module_type -> t_module list
+
+ (** Access to the module types of a module type. *)
+ val module_type_module_types : ?trans:bool-> t_module_type -> t_module_type list
+
+ (** Access to the included modules of a module type. *)
+ val module_type_included_modules : ?trans:bool-> t_module_type -> included_module list
+
+ (** Access to the exceptions of a module type. *)
+ val module_type_exceptions : ?trans:bool-> t_module_type -> Exception.t_exception list
+
+ (** Access to the types of a module type. *)
+ val module_type_types : ?trans:bool-> t_module_type -> Type.t_type list
+
+ (** Access to the values of a module type. *)
+ val module_type_values : ?trans:bool-> t_module_type -> Value.t_value list
+
+ (** Access to functional values of a module type. *)
+ val module_type_functions : ?trans:bool-> t_module_type -> Value.t_value list
+
+ (** Access to non-functional values of a module type. *)
+ val module_type_simple_values : ?trans:bool-> t_module_type -> Value.t_value list
+
+ (** Access to the classes of a module type. *)
+ val module_type_classes : ?trans:bool-> t_module_type -> Class.t_class list
+
+ (** Access to the class types of a module type. *)
+ val module_type_class_types : ?trans:bool-> t_module_type -> Class.t_class_type list
+
+ (** The list of classes defined in this module type and all its submodules and functors. *)
+ val module_type_all_classes : ?trans:bool-> t_module_type -> Class.t_class list
+
+ (** [true] if the module type is functor. *)
+ val module_type_is_functor : t_module_type -> bool
+
+ (** The list of couples (module parameter, optional description). *)
+ val module_type_parameters : ?trans:bool-> t_module_type -> (module_parameter * text option) list
+
+ (** The list of module comments. *)
+ val module_type_comments : ?trans:bool-> t_module_type -> text list
+ end
+
+
+(** {3 Getting strings from values} *)
+
+(** This function is used to reset the names of type variables.
+ It must be called when printing the whole type of a function,
+ but not when printing the type of its parameters. Same for
+ classes (call it) and methods and attributes (don't call it).*)
+val reset_type_names : unit -> unit
+
+(** [string_of_variance t (covariant, invariant)] returns ["+"] if
+ the given information means "covariant", ["-"] if the it means
+ "contravariant", orelse [""], and always [""] if the given
+ type is not an abstract type with no manifest (i.e. no need
+ for the variance to be printed.*)
+val string_of_variance : Type.t_type -> (bool * bool) -> string
+
+(** This function returns a string representing a Types.type_expr. *)
+val string_of_type_expr : Types.type_expr -> string
+
+(** @return a string to display the parameters of the given class,
+ in the same form as the compiler. *)
+val string_of_class_params : Class.t_class -> string
+
+(** This function returns a string to represent the given list of types,
+ with a given separator. *)
+val string_of_type_list : ?par: bool -> string -> Types.type_expr list -> string
+
+(** This function returns a string to represent the list of type parameters
+ for the given type. *)
+val string_of_type_param_list : Type.t_type -> string
+
+(** This function returns a string to represent the given list of
+ type parameters of a class or class type,
+ with a given separator. *)
+val string_of_class_type_param_list : Types.type_expr list -> string
+
+(** This function returns a string representing a [Types.module_type].
+ @param complete indicates if we must print complete signatures
+ or just [sig end]. Default if [false].
+ @param code if [complete = false] and the type contains something else
+ than identificators and functors, then the given code is used.
+*)
+val string_of_module_type : ?code: string -> ?complete: bool -> Types.module_type -> string
+
+(** This function returns a string representing a [Types.class_type].
+ @param complete indicates if we must print complete signatures
+ or just [object end]. Default if [false].
+*)
+val string_of_class_type : ?complete: bool -> Types.class_type -> string
+
+
+(** Get a string from a text. *)
+val string_of_text : text -> string
+
+(** Get a string from an info structure. *)
+val string_of_info : info -> string
+
+(** @return a string to describe the given type. *)
+val string_of_type : Type.t_type -> string
+
+(** @return a string to describe the given exception. *)
+val string_of_exception : Exception.t_exception -> string
+
+(** @return a string to describe the given value. *)
+val string_of_value : Value.t_value -> string
+
+(** @return a string to describe the given attribute. *)
+val string_of_attribute : Value.t_attribute -> string
+
+(** @return a string to describe the given method. *)
+val string_of_method : Value.t_method -> string
+
+(** {3 Miscelaneous functions} *)
+
+(** Return the first sentence (until the first dot followed by a blank
+ or the first blank line) of a text.
+ Don't stop in the middle of [Code], [CodePre], [Verbatim], [List], [Enum],
+ [Latex], [Link], [Ref], [Subscript] or [Superscript]. *)
+val first_sentence_of_text : text -> text
+
+(** Return the first sentence (until the first dot followed by a blank
+ or the first blank line) of a text, and the remaining text after.
+ Don't stop in the middle of [Code], [CodePre], [Verbatim], [List], [Enum],
+ [Latex], [Link], [Ref], [Subscript] or [Superscript].*)
+val first_sentence_and_rest_of_text : text -> text * text
+
+(** Return the given [text] without any title or list. *)
+val text_no_title_no_list : text -> text
+
+(** [concat sep l] concats the given list of text [l], each separated with
+ the text [sep]. *)
+val text_concat : Odoc_types.text -> Odoc_types.text list -> Odoc_types.text
+
+(** Return the list of titles in a [text].
+ A title is a title level, an optional label and a text.*)
+val get_titles_in_text : text -> (int * string option * text) list
+
+(** Take a sorted list of elements, a function to get the name
+ of an element and return the list of list of elements,
+ where each list group elements beginning by the same letter.
+ Since the original list is sorted, elements whose name does not
+ begin with a letter should be in the first returned list.*)
+val create_index_lists : 'a list -> ('a -> string) -> 'a list list
+
+(** Take a type and remove the option top constructor. This is
+ useful when printing labels, we we then remove the top option contructor
+ for optional labels.*)
+val remove_option : Types.type_expr -> Types.type_expr
+
+(** Return [true] if the given label is optional.*)
+val is_optional : string -> bool
+
+(** Return the label name for the given label,
+ i.e. removes the beginning '?' if present.*)
+val label_name : string -> string
+
+(** Return the given name where the module name or
+ part of it was removed, according to the list of modules
+ which must be hidden (cf {!Odoc_args.hidden_modules})*)
+val use_hidden_modules : Name.t -> Name.t
+
+(** Print the given string if the verbose mode is activated. *)
+val verbose : string -> unit
+
+(** Print a warning message to stderr.
+ If warnings must be treated as errors, then the
+ error counter is incremented. *)
+val warning : string -> unit
+
+(** A flag to indicate whether ocamldoc warnings must be printed or not. *)
+val print_warnings : bool ref
+
+(** Increment this counter when an error is encountered.
+ The ocamldoc tool will print the number of errors
+ encountered exit with code 1 if this number is greater
+ than 0. *)
+val errors : int ref
+
+(** Apply a function to an optional value. *)
+val apply_opt : ('a -> 'b) -> 'a option -> 'b option
+
+(** Apply a function to a first value if it is
+ not different from a second value. If the two values
+ are different, return the second one.*)
+val apply_if_equal : ('a -> 'a) -> 'a -> 'a -> 'a
+
+(** [text_of_string s] returns the text structure from the
+ given string.
+ @raise Text_syntax if a syntax error is encountered. *)
+val text_of_string : string -> text
+
+(** [text_string_of_text text] returns the string representing
+ the given [text]. This string can then be parsed again
+ by {!Odoc_info.text_of_string}.*)
+val text_string_of_text : text -> string
+
+(** [info_of_string s] parses the given string
+ like a regular ocamldoc comment and return an
+ {!Odoc_info.info} structure.
+ @return an empty structure if there was a syntax error. TODO: change this
+*)
+val info_of_string : string -> info
+
+(** [info_string_of_info info] returns the string representing
+ the given [info]. This string can then be parsed again
+ by {!Odoc_info.info_of_string}.*)
+val info_string_of_info : info -> string
+
+(** [info_of_comment_file file] parses the given file
+ and return an {!Odoc_info.info} structure. The content of the
+ file must have the same syntax as the content of a special comment.
+ The given module list is used for cross reference.
+ @raise Failure is the file could not be opened or there is a
+ syntax error.
+*)
+val info_of_comment_file : Module.t_module list -> string -> info
+
+(** [remove_ending_newline s] returns [s] without the optional ending newline. *)
+val remove_ending_newline : string -> string
+
+(** Research in elements *)
+module Search :
+ sig
+ type result_element = Odoc_search.result_element =
+ Res_module of Module.t_module
+ | Res_module_type of Module.t_module_type
+ | Res_class of Class.t_class
+ | Res_class_type of Class.t_class_type
+ | Res_value of Value.t_value
+ | Res_type of Type.t_type
+ | Res_exception of Exception.t_exception
+ | Res_attribute of Value.t_attribute
+ | Res_method of Value.t_method
+ | Res_section of string * text
+
+ (** The type representing a research result.*)
+ type search_result = result_element list
+
+ (** Research of the elements whose name matches the given regular expression.*)
+ val search_by_name : Module.t_module list -> Str.regexp -> search_result
+
+ (** A function to search all the values in a list of modules. *)
+ val values : Module.t_module list -> Value.t_value list
+
+ (** A function to search all the exceptions in a list of modules. *)
+ val exceptions : Module.t_module list -> Exception.t_exception list
+
+ (** A function to search all the types in a list of modules. *)
+ val types : Module.t_module list -> Type.t_type list
+
+ (** A function to search all the class attributes in a list of modules. *)
+ val attributes : Module.t_module list -> Value.t_attribute list
+
+ (** A function to search all the class methods in a list of modules. *)
+ val methods : Module.t_module list -> Value.t_method list
+
+ (** A function to search all the classes in a list of modules. *)
+ val classes : Module.t_module list -> Class.t_class list
+
+ (** A function to search all the class types in a list of modules. *)
+ val class_types : Module.t_module list -> Class.t_class_type list
+
+ (** A function to search all the modules in a list of modules. *)
+ val modules : Module.t_module list -> Module.t_module list
+
+ (** A function to search all the module types in a list of modules. *)
+ val module_types : Module.t_module list -> Module.t_module_type list
+
+ end
+
+(** Scanning of collected information *)
+module Scan :
+ sig
+ class scanner :
+ object
+ (** Scan of 'leaf elements'. *)
+
+ method scan_value : Value.t_value -> unit
+ method scan_type : Type.t_type -> unit
+ method scan_exception : Exception.t_exception -> unit
+ method scan_attribute : Value.t_attribute -> unit
+ method scan_method : Value.t_method -> unit
+ method scan_included_module : Module.included_module -> unit
+
+ (** Scan of a class. *)
+
+ (** Scan of a comment inside a class. *)
+ method scan_class_comment : text -> unit
+
+ (** Override this method to perform controls on the class comment
+ and params. This method is called before scanning the class elements.
+ @return true if the class elements must be scanned.*)
+ method scan_class_pre : Class.t_class -> bool
+
+ (** This method scan the elements of the given class. *)
+ method scan_class_elements : Class.t_class -> unit
+
+ (** Scan of a class. Should not be overridden. It calls [scan_class_pre]
+ and if [scan_class_pre] returns [true], then it calls scan_class_elements.*)
+ method scan_class : Class.t_class -> unit
+
+ (** Scan of a class type. *)
+
+ (** Scan of a comment inside a class type. *)
+ method scan_class_type_comment : text -> unit
+
+ (** Override this method to perform controls on the class type comment
+ and form. This method is called before scanning the class type elements.
+ @return true if the class type elements must be scanned.*)
+ method scan_class_type_pre : Class.t_class_type -> bool
+
+ (** This method scan the elements of the given class type. *)
+ method scan_class_type_elements : Class.t_class_type -> unit
+
+ (** Scan of a class type. Should not be overridden. It calls [scan_class_type_pre]
+ and if [scan_class_type_pre] returns [true], then it calls scan_class_type_elements.*)
+ method scan_class_type : Class.t_class_type -> unit
+
+ (** Scan of modules. *)
+
+ (** Scan of a comment inside a module. *)
+ method scan_module_comment : text -> unit
+
+ (** Override this method to perform controls on the module comment
+ and form. This method is called before scanning the module elements.
+ @return true if the module elements must be scanned.*)
+ method scan_module_pre : Module.t_module -> bool
+
+ (** This method scan the elements of the given module. *)
+ method scan_module_elements : Module.t_module -> unit
+
+ (** Scan of a module. Should not be overridden. It calls [scan_module_pre]
+ and if [scan_module_pre] returns [true], then it calls scan_module_elements.*)
+ method scan_module : Module.t_module -> unit
+
+ (** Scan of module types. *)
+
+ (** Scan of a comment inside a module type. *)
+ method scan_module_type_comment : text -> unit
+
+ (** Override this method to perform controls on the module type comment
+ and form. This method is called before scanning the module type elements.
+ @return true if the module type elements must be scanned. *)
+ method scan_module_type_pre : Module.t_module_type -> bool
+
+ (** This method scan the elements of the given module type. *)
+ method scan_module_type_elements : Module.t_module_type -> unit
+
+ (** Scan of a module type. Should not be overridden. It calls [scan_module_type_pre]
+ and if [scan_module_type_pre] returns [true], then it calls scan_module_type_elements.*)
+ method scan_module_type : Module.t_module_type -> unit
+
+ (** Main scanning method. *)
+
+ (** Scan a list of modules. *)
+ method scan_module_list : Module.t_module list -> unit
+ end
+ end
+
+(** Computation of dependencies. *)
+module Dep :
+ sig
+ (** Modify the modules depencies of the given list of modules,
+ to get the minimum transitivity kernel. *)
+ val kernel_deps_of_modules : Module.t_module list -> unit
+
+ (** Return the list of dependencies between the given types,
+ in the form of a list [(type name, names of types it depends on)].
+ @param kernel indicates if we must keep only the transitivity kernel
+ of the dependencies. Default is [false].
+ *)
+ val deps_of_types : ?kernel: bool -> Type.t_type list -> (Type.t_type * (Name.t list)) list
+ end
+
+(** {2 Some global variables} *)
+
+module Global :
+ sig
+ val errors : int ref
+ val warn_error : bool ref
+
+ (** The file used by the generators outputting only one file. *)
+ val out_file : string ref
+
+ (** Verbose mode or not. *)
+ val verbose : bool ref
+
+ (** The directory where files have to be generated. *)
+ val target_dir : string ref
+
+ (** The optional title to use in the generated documentation. *)
+ val title : string option ref
+
+ (** The optional file whose content can be used as intro text. *)
+ val intro_file : string option ref
+
+ (** The flag which indicates if we must generate a table of contents. *)
+ val with_toc : bool ref
+
+ (** The flag which indicates if we must generate an index. *)
+ val with_index : bool ref
+
+ (** The flag which indicates if we must generate a header.*)
+ val with_header : bool ref
+
+ (** The flag which indicates if we must generate a trailer.*)
+ val with_trailer : bool ref
+end
+
+(** Analysis of the given source files.
+ @param init is the list of modules already known from a previous analysis.
+ @return the list of analysed top modules. *)
+val analyse_files :
+ ?merge_options:Odoc_types.merge_option list ->
+ ?include_dirs:string list ->
+ ?labels:bool ->
+ ?sort_modules:bool ->
+ ?no_stop:bool ->
+ ?init: Odoc_module.t_module list ->
+ Odoc_global.source_file list ->
+ Module.t_module list
+
+(** Dump of a list of modules into a file.
+ @raise Failure if an error occurs.*)
+val dump_modules : string -> Odoc_module.t_module list -> unit
+
+(** Load of a list of modules from a file.
+ @raise Failure if an error occurs.*)
+val load_modules : string -> Odoc_module.t_module list
diff --git a/ocaml-binary-annot/ocamldoc/odoc_inherit.ml b/ocaml-binary-annot/ocamldoc/odoc_inherit.ml
new file mode 100644
index 0000000000..b73796bf8a
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_inherit.ml
@@ -0,0 +1,12 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
diff --git a/ocaml-binary-annot/ocamldoc/odoc_latex.ml b/ocaml-binary-annot/ocamldoc/odoc_latex.ml
new file mode 100644
index 0000000000..c20c344b51
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_latex.ml
@@ -0,0 +1,1201 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Generation of LaTeX documentation. *)
+
+let print_DEBUG s = print_string s ; print_newline ()
+
+open Odoc_info
+open Parameter
+open Value
+open Type
+open Exception
+open Class
+open Module
+
+
+
+let separate_files = ref false
+
+let latex_titles = ref [
+ 1, "section" ;
+ 2, "subsection" ;
+ 3, "subsubsection" ;
+ 4, "paragraph" ;
+ 5, "subparagraph" ;
+]
+
+let latex_value_prefix = ref Odoc_messages.default_latex_value_prefix
+let latex_type_prefix = ref Odoc_messages.default_latex_type_prefix
+let latex_exception_prefix = ref Odoc_messages.default_latex_exception_prefix
+let latex_module_prefix = ref Odoc_messages.default_latex_module_prefix
+let latex_module_type_prefix = ref Odoc_messages.default_latex_module_type_prefix
+let latex_class_prefix = ref Odoc_messages.default_latex_class_prefix
+let latex_class_type_prefix = ref Odoc_messages.default_latex_class_type_prefix
+let latex_attribute_prefix = ref Odoc_messages.default_latex_attribute_prefix
+let latex_method_prefix = ref Odoc_messages.default_latex_method_prefix
+
+let new_buf () = Buffer.create 1024
+let new_fmt () =
+ let b = new_buf () in
+ let fmt = Format.formatter_of_buffer b in
+ (fmt,
+ fun () ->
+ Format.pp_print_flush fmt ();
+ let s = Buffer.contents b in
+ Buffer.reset b;
+ s
+ )
+
+let p = Format.fprintf
+let ps f s = Format.fprintf f "%s" s
+
+
+let bp = Printf.bprintf
+let bs = Buffer.add_string
+
+let print_concat fmt sep f =
+ let rec iter = function
+ [] -> ()
+ | [c] -> f c
+ | c :: q ->
+ f c;
+ ps fmt sep;
+ iter q
+ in
+ iter
+
+(** Generation of LaTeX code from text structures. *)
+class text =
+ object (self)
+ (** Return latex code to make a sectionning according to the given level,
+ and with the given latex code. *)
+ method section_style level s =
+ try
+ let sec = List.assoc level !latex_titles in
+ "\\"^sec^"{"^s^"}\n"
+ with Not_found -> s
+
+ (** Associations of strings to subsitute in latex code. *)
+ val mutable subst_strings = [
+ ("MAXENCE"^"ZZZ", "\\$");
+ ("MAXENCE"^"YYY", "\\&");
+ ("MAXENCE"^"XXX", "{\\textbackslash}") ;
+ ("à", "\\`a") ;
+ ("â", "\\^a") ;
+ ("é", "\\'e") ;
+ ("è", "\\`e") ;
+ ("ê", "\\^e") ;
+ ("ë", "\\\"e") ;
+ ("ç", "\\c{c}") ;
+ ("ô", "\\^o") ;
+ ("ö", "\\\"o") ;
+ ("î", "\\^i") ;
+ ("ï", "\\\"i") ;
+ ("ù", "\\`u") ;
+ ("û", "\\^u") ;
+ ("%", "\\%") ;
+ ("_", "\\_");
+ ("\\.\\.\\.", "$\\ldots$");
+ ("~", "\\~{}");
+ ("#", "\\verb`#`");
+ ("}", "\\}");
+ ("{", "\\{");
+ ("&", "\\&");
+ (">", "$>$");
+ ("<", "$<$");
+ ("=", "$=$");
+ (">=", "$\\geq$");
+ ("<=", "$\\leq$");
+ ("->", "$\\rightarrow$") ;
+ ("<-", "$\\leftarrow$");
+ ("|", "\\textbar ");
+ ("\\^", "\\textasciicircum ") ;
+ ("\\.\\.\\.", "$\\ldots$");
+ ("\\\\", "MAXENCE"^"XXX") ;
+ ("&", "MAXENCE"^"YYY") ;
+ ("\\$", "MAXENCE"^"ZZZ");
+ ]
+
+ val mutable subst_strings_simple =
+ [
+ ("MAXENCE"^"XXX", "{\\textbackslash}") ;
+ "}", "\\}" ;
+ "{", "\\{" ;
+ ("\\\\", "MAXENCE"^"XXX") ;
+ ]
+
+ val mutable subst_strings_code = [
+ ("MAXENCE"^"ZZZ", "\\$");
+ ("MAXENCE"^"YYY", "\\&");
+ ("MAXENCE"^"XXX", "{\\textbackslash}") ;
+ ("%", "\\%") ;
+ ("_", "\\_");
+ ("~", "\\~{}");
+ ("#", "\\verb`#`");
+ ("}", "\\}");
+ ("{", "\\{");
+ ("&", "\\&");
+ ("\\^", "\\textasciicircum ") ;
+ ("&", "MAXENCE"^"YYY") ;
+ ("\\$", "MAXENCE"^"ZZZ") ;
+ ("\\\\", "MAXENCE"^"XXX") ;
+ ]
+
+ method subst l s =
+ List.fold_right
+ (fun (s, s2) -> fun acc -> Str.global_replace (Str.regexp s) s2 acc)
+ l
+ s
+
+ (** Escape the strings which would clash with LaTeX syntax. *)
+ method escape s = self#subst subst_strings s
+
+ (** Escape the ['\'], ['{'] and ['}'] characters. *)
+ method escape_simple s = self#subst subst_strings_simple s
+
+ (** Escape some characters for the code style. *)
+ method escape_code s = self#subst subst_strings_code s
+
+ (** Make a correct latex label from a name. *)
+ (* The following characters are forbidden in LaTeX \index:
+ \ { } $ & # ^ _ % ~ ! " @ | (" to close the double quote)
+ The following characters are forbidden in LaTeX \label:
+ \ { } $ & # ^ _ % ~
+ So we will use characters not forbidden in \index if no_ = true.
+ *)
+ method label ?(no_=true) name =
+ let len = String.length name in
+ let buf = Buffer.create len in
+ for i = 0 to len - 1 do
+ let (s_no_, s) =
+ match name.[i] with
+ '_' -> ("-underscore", "_")
+ | '~' -> ("-tilde", "~")
+ | '%' -> ("-percent", "%")
+ | '@' -> ("-at", "\"@")
+ | '!' -> ("-bang", "\"!")
+ | '|' -> ("-pipe", "\"|")
+ | '<' -> ("-lt", "<")
+ | '>' -> ("-gt", ">")
+ | '^' -> ("-exp", "^")
+ | '&' -> ("-ampersand", "&")
+ | '+' -> ("-plus", "+")
+ | '-' -> ("-minus", "-")
+ | '*' -> ("-star", "*")
+ | '/' -> ("-slash", "/")
+ | '$' -> ("-dollar", "$")
+ | '=' -> ("-equal", "=")
+ | ':' -> ("-colon", ":")
+ | c -> (String.make 1 c, String.make 1 c)
+ in
+ Buffer.add_string buf (if no_ then s_no_ else s)
+ done;
+ Buffer.contents buf
+
+ (** Make a correct label from a value name. *)
+ method value_label ?no_ name = !latex_value_prefix^(self#label ?no_ name)
+
+ (** Make a correct label from an attribute name. *)
+ method attribute_label ?no_ name = !latex_attribute_prefix^(self#label ?no_ name)
+
+ (** Make a correct label from a method name. *)
+ method method_label ?no_ name = !latex_method_prefix^(self#label ?no_ name)
+
+ (** Make a correct label from a class name. *)
+ method class_label ?no_ name = !latex_class_prefix^(self#label ?no_ name)
+
+ (** Make a correct label from a class type name. *)
+ method class_type_label ?no_ name = !latex_class_type_prefix^(self#label ?no_ name)
+
+ (** Make a correct label from a module name. *)
+ method module_label ?no_ name = !latex_module_prefix^(self#label ?no_ name)
+
+ (** Make a correct label from a module type name. *)
+ method module_type_label ?no_ name = !latex_module_type_prefix^(self#label ?no_ name)
+
+ (** Make a correct label from an exception name. *)
+ method exception_label ?no_ name = !latex_exception_prefix^(self#label ?no_ name)
+
+ (** Make a correct label from a type name. *)
+ method type_label ?no_ name = !latex_type_prefix^(self#label ?no_ name)
+
+ (** Return latex code for the label of a given label. *)
+ method make_label label = "\\label{"^label^"}"
+
+ (** Return latex code for the ref to a given label. *)
+ method make_ref label = "\\ref{"^label^"}"
+
+ (** Print the LaTeX code corresponding to the [text] parameter.*)
+ method latex_of_text fmt t =
+ List.iter (self#latex_of_text_element fmt) t
+
+ (** Print the LaTeX code for the [text_element] in parameter. *)
+ method latex_of_text_element fmt te =
+ match te with
+ | Odoc_info.Raw s -> self#latex_of_Raw fmt s
+ | Odoc_info.Code s -> self#latex_of_Code fmt s
+ | Odoc_info.CodePre s -> self#latex_of_CodePre fmt s
+ | Odoc_info.Verbatim s -> self#latex_of_Verbatim fmt s
+ | Odoc_info.Bold t -> self#latex_of_Bold fmt t
+ | Odoc_info.Italic t -> self#latex_of_Italic fmt t
+ | Odoc_info.Emphasize t -> self#latex_of_Emphasize fmt t
+ | Odoc_info.Center t -> self#latex_of_Center fmt t
+ | Odoc_info.Left t -> self#latex_of_Left fmt t
+ | Odoc_info.Right t -> self#latex_of_Right fmt t
+ | Odoc_info.List tl -> self#latex_of_List fmt tl
+ | Odoc_info.Enum tl -> self#latex_of_Enum fmt tl
+ | Odoc_info.Newline -> self#latex_of_Newline fmt
+ | Odoc_info.Block t -> self#latex_of_Block fmt t
+ | Odoc_info.Title (n, l_opt, t) -> self#latex_of_Title fmt n l_opt t
+ | Odoc_info.Latex s -> self#latex_of_Latex fmt s
+ | Odoc_info.Link (s, t) -> self#latex_of_Link fmt s t
+ | Odoc_info.Ref (name, ref_opt, text_opt) ->
+ self#latex_of_Ref fmt name ref_opt text_opt
+ | Odoc_info.Superscript t -> self#latex_of_Superscript fmt t
+ | Odoc_info.Subscript t -> self#latex_of_Subscript fmt t
+ | Odoc_info.Module_list _ -> ()
+ | Odoc_info.Index_list -> ()
+ | Odoc_info.Custom (s,t) -> self#latex_of_custom_text fmt s t
+ | Odoc_info.Target (target, code) -> self#latex_of_Target fmt ~target ~code
+
+ method latex_of_custom_text fmt s t = ()
+
+ method latex_of_Target fmt ~target ~code =
+ if String.lowercase target = "latex" then
+ self#latex_of_Latex fmt code
+ else
+ ()
+
+ method latex_of_Raw fmt s =
+ ps fmt (self#escape s)
+
+ method latex_of_Code fmt s =
+ let s2 = self#escape_code s in
+ let s3 = Str.global_replace (Str.regexp "\n") ("\\\\\n") s2 in
+ p fmt "{\\tt{%s}}" s3
+
+ method latex_of_CodePre fmt s =
+ ps fmt "\\begin{ocamldoccode}\n";
+ ps fmt (self#escape_simple s);
+ ps fmt "\n\\end{ocamldoccode}\n"
+
+ method latex_of_Verbatim fmt s =
+ ps fmt "\\begin{verbatim}";
+ ps fmt s;
+ ps fmt "\\end{verbatim}"
+
+ method latex_of_Bold fmt t =
+ ps fmt "{\\bf ";
+ self#latex_of_text fmt t;
+ ps fmt "}"
+
+ method latex_of_Italic fmt t =
+ ps fmt "{\\it ";
+ self#latex_of_text fmt t;
+ ps fmt "}"
+
+ method latex_of_Emphasize fmt t =
+ ps fmt "{\\em ";
+ self#latex_of_text fmt t;
+ ps fmt "}"
+
+ method latex_of_Center fmt t =
+ ps fmt "\\begin{center}\n";
+ self#latex_of_text fmt t;
+ ps fmt "\\end{center}\n"
+
+ method latex_of_Left fmt t =
+ ps fmt "\\begin{flushleft}\n";
+ self#latex_of_text fmt t;
+ ps fmt "\\end{flushleft}\n"
+
+ method latex_of_Right fmt t =
+ ps fmt "\\begin{flushright}\n";
+ self#latex_of_text fmt t;
+ ps fmt "\\end{flushright}\n"
+
+ method latex_of_List fmt tl =
+ ps fmt "\\begin{itemize}\n";
+ List.iter
+ (fun t ->
+ ps fmt "\\item ";
+ self#latex_of_text fmt t;
+ ps fmt "\n"
+ )
+ tl;
+ ps fmt "\\end{itemize}\n"
+
+ method latex_of_Enum fmt tl =
+ ps fmt "\\begin{enumerate}\n";
+ List.iter
+ (fun t ->
+ ps fmt "\\item ";
+ self#latex_of_text fmt t;
+ ps fmt "\n"
+ )
+ tl;
+ ps fmt "\\end{enumerate}\n"
+
+ method latex_of_Newline fmt = ps fmt "\n\n"
+
+ method latex_of_Block fmt t =
+ ps fmt "\\begin{ocamldocdescription}\n";
+ self#latex_of_text fmt t;
+ ps fmt "\n\\end{ocamldocdescription}\n"
+
+ method latex_of_Title fmt n label_opt t =
+ let (fmt2, flush) = new_fmt () in
+ self#latex_of_text fmt2 t;
+ let s_title2 = self#section_style n (flush ()) in
+ ps fmt s_title2;
+ (
+ match label_opt with
+ None -> ()
+ | Some l ->
+ ps fmt (self#make_label (self#label ~no_: false l))
+ )
+
+ method latex_of_Latex fmt s = ps fmt s
+
+ method latex_of_Link fmt s t =
+ self#latex_of_text fmt t ;
+ ps fmt "[\\url{";
+ ps fmt s ;
+ ps fmt "}]"
+
+ method latex_of_Ref fmt name ref_opt text_opt =
+ match ref_opt with
+ None ->
+ self#latex_of_text fmt
+ (match text_opt with
+ None ->
+ [Odoc_info.Code (Odoc_info.use_hidden_modules name)]
+ | Some t -> t
+ )
+ | Some (RK_section _) ->
+ self#latex_of_text_element fmt
+ (Latex ("["^(self#make_ref (self#label ~no_:false (Name.simple name)))^"]"))
+ | Some kind ->
+ let f_label =
+ match kind with
+ Odoc_info.RK_module -> self#module_label
+ | Odoc_info.RK_module_type -> self#module_type_label
+ | Odoc_info.RK_class -> self#class_label
+ | Odoc_info.RK_class_type -> self#class_type_label
+ | Odoc_info.RK_value -> self#value_label
+ | Odoc_info.RK_type -> self#type_label
+ | Odoc_info.RK_exception -> self#exception_label
+ | Odoc_info.RK_attribute -> self#attribute_label
+ | Odoc_info.RK_method -> self#method_label
+ | Odoc_info.RK_section _ -> assert false
+ in
+ let text =
+ match text_opt with
+ None -> [Odoc_info.Code (Odoc_info.use_hidden_modules name)]
+ | Some t -> t
+ in
+ self#latex_of_text fmt
+ (text @ [Latex ("["^(self#make_ref (f_label name))^"]")])
+
+ method latex_of_Superscript fmt t =
+ ps fmt "$^{";
+ self#latex_of_text fmt t;
+ ps fmt "}$"
+
+ method latex_of_Subscript fmt t =
+ ps fmt "$_{";
+ self#latex_of_text fmt t;
+ ps fmt "}$"
+
+ end
+
+(** A class used to generate LaTeX code for info structures. *)
+class virtual info =
+ object (self)
+ (** The method used to get LaTeX code from a [text]. *)
+ method virtual latex_of_text : Format.formatter -> Odoc_info.text -> unit
+
+ (** The method used to get a [text] from an optionel info structure. *)
+ method virtual text_of_info : ?block: bool -> Odoc_info.info option -> Odoc_info.text
+
+ (** Print LaTeX code for a description, except for the [i_params] field. *)
+ method latex_of_info fmt ?(block=false) info_opt =
+ self#latex_of_text fmt
+ (self#text_of_info ~block info_opt)
+ end
+
+module Generator =
+struct
+(** This class is used to create objects which can generate a simple LaTeX documentation. *)
+class latex =
+ object (self)
+ inherit text
+ inherit Odoc_to_text.to_text as to_text
+ inherit info
+
+ (** Get the first sentence and the rest of a description,
+ from an optional [info] structure. The first sentence
+ can be empty if it would not appear right in a title.
+ In the first sentence, the titles and lists has been removed,
+ since it is used in LaTeX titles and would make LaTeX complain
+ if we has two nested \section commands.
+ *)
+ method first_and_rest_of_info i_opt =
+ match i_opt with
+ None -> ([], [])
+ | Some i ->
+ match i.Odoc_info.i_desc with
+ None -> ([], self#text_of_info ~block: true i_opt)
+ | Some t ->
+ let (first,_) = Odoc_info.first_sentence_and_rest_of_text t in
+ let (_, rest) = Odoc_info.first_sentence_and_rest_of_text (self#text_of_info ~block: false i_opt) in
+ (Odoc_info.text_no_title_no_list first, rest)
+
+ (** Print LaTeX code for a value. *)
+ method latex_of_value fmt v =
+ Odoc_info.reset_type_names () ;
+ let label = self#value_label v.val_name in
+ let latex = self#make_label label in
+ self#latex_of_text fmt
+ ((Latex latex) ::
+ (to_text#text_of_value v))
+
+ (** Print LaTeX code for a class attribute. *)
+ method latex_of_attribute fmt a =
+ self#latex_of_text fmt
+ ((Latex (self#make_label (self#attribute_label a.att_value.val_name))) ::
+ (to_text#text_of_attribute a))
+
+ (** Print LaTeX code for a class method. *)
+ method latex_of_method fmt m =
+ self#latex_of_text fmt
+ ((Latex (self#make_label (self#method_label m.met_value.val_name))) ::
+ (to_text#text_of_method m))
+
+ (** Print LaTeX code for the parameters of a type. *)
+ method latex_of_type_params fmt m_name t =
+ let print_one (p, co, cn) =
+ ps fmt (Odoc_info.string_of_variance t (co,cn));
+ ps fmt (self#normal_type m_name p)
+ in
+ match t.ty_parameters with
+ [] -> ()
+ | [(p,co,cn)] -> print_one (p, co, cn)
+ | l ->
+ ps fmt "(";
+ print_concat fmt ", " print_one t.ty_parameters;
+ ps fmt ")"
+
+ method latex_of_class_parameter_list fmt father c =
+ self#latex_of_text fmt
+ (self#text_of_class_params father c)
+
+ (** Print LaTeX code for a type. *)
+ method latex_of_type fmt t =
+ let s_name = Name.simple t.ty_name in
+ let text =
+ let (fmt2, flush2) = new_fmt () in
+ Odoc_info.reset_type_names () ;
+ let mod_name = Name.father t.ty_name in
+ Format.fprintf fmt2 "@[<h 2>type ";
+ self#latex_of_type_params fmt2 mod_name t;
+ (match t.ty_parameters with [] -> () | _ -> ps fmt2 " ");
+ ps fmt2 s_name;
+ let priv = t.ty_private = Asttypes.Private in
+ (
+ match t.ty_manifest with
+ None -> ()
+ | Some typ ->
+ p fmt2 " = %s%s" (if priv then "private " else "") (self#normal_type mod_name typ)
+ );
+ let s_type3 =
+ p fmt2
+ " %s"
+ (
+ match t.ty_kind with
+ Type_abstract -> ""
+ | Type_variant _ -> "="^(if priv then " private" else "")
+ | Type_record _ -> "= "^(if priv then "private " else "")^"{"
+ ) ;
+ flush2 ()
+ in
+
+ let defs =
+ match t.ty_kind with
+ Type_abstract -> []
+ | Type_variant l ->
+ (List.flatten
+ (List.map
+ (fun constr ->
+ let s_cons =
+ p fmt2 "@[<h 6> | %s" constr.vc_name;
+ (
+ match constr.vc_args with
+ [] -> ()
+ | l ->
+ p fmt2 " %s@ %s"
+ "of"
+ (self#normal_type_list ~par: false mod_name " * " l)
+ );
+ flush2 ()
+ in
+ [ CodePre s_cons ] @
+ (match constr.vc_text with
+ None -> []
+ | Some t ->
+ let s =
+ ps fmt2 "\\begin{ocamldoccomment}\n";
+ self#latex_of_text fmt2 t;
+ ps fmt2 "\n\\end{ocamldoccomment}\n";
+ flush2 ()
+ in
+ [ Latex s]
+ )
+ )
+ l
+ )
+ )
+ | Type_record l ->
+ (List.flatten
+ (List.map
+ (fun r ->
+ let s_field =
+ p fmt2
+ "@[<h 6> %s%s :@ %s ;"
+ (if r.rf_mutable then "mutable " else "")
+ r.rf_name
+ (self#normal_type mod_name r.rf_type);
+ flush2 ()
+ in
+ [ CodePre s_field ] @
+ (match r.rf_text with
+ None -> []
+ | Some t ->
+ let s =
+ ps fmt2 "\\begin{ocamldoccomment}\n";
+ self#latex_of_text fmt2 t;
+ ps fmt2 "\n\\end{ocamldoccomment}\n";
+ flush2 ()
+ in
+ [ Latex s]
+ )
+ )
+ l
+ )
+ ) @
+ [ CodePre "}" ]
+ in
+ let defs2 = (CodePre s_type3) :: defs in
+ let rec iter = function
+ [] -> []
+ | [e] -> [e]
+ | (CodePre s1) :: (CodePre s2) :: q ->
+ iter ((CodePre (s1^"\n"^s2)) :: q)
+ | e :: q ->
+ e :: (iter q)
+ in
+ (iter defs2) @
+ [Latex ("\\index{"^(self#label s_name)^"@\\verb`"^(self#label ~no_:false s_name)^"`}\n")] @
+ (self#text_of_info t.ty_info)
+ in
+ self#latex_of_text fmt
+ ((Latex (self#make_label (self#type_label t.ty_name))) :: text)
+
+ (** Print LaTeX code for an exception. *)
+ method latex_of_exception fmt e =
+ Odoc_info.reset_type_names () ;
+ self#latex_of_text fmt
+ ((Latex (self#make_label (self#exception_label e.ex_name))) ::
+ (to_text#text_of_exception e))
+
+ method latex_of_module_parameter fmt m_name p =
+ self#latex_of_text fmt
+ [
+ Code "functor (";
+ Code p.mp_name ;
+ Code " : ";
+ ] ;
+ self#latex_of_module_type_kind fmt m_name p.mp_kind;
+ self#latex_of_text fmt [ Code ") -> "]
+
+
+ method latex_of_module_type_kind fmt father kind =
+ match kind with
+ Module_type_struct eles ->
+ self#latex_of_text fmt [Latex "\\begin{ocamldocsigend}\n"];
+ List.iter (self#latex_of_module_element fmt father) eles;
+ self#latex_of_text fmt [Latex "\\end{ocamldocsigend}\n"]
+ | Module_type_functor (p, k) ->
+ self#latex_of_module_parameter fmt father p;
+ self#latex_of_module_type_kind fmt father k
+ | Module_type_alias a ->
+ self#latex_of_text fmt
+ [Code (self#relative_module_idents father a.mta_name)]
+ | Module_type_with (k, s) ->
+ self#latex_of_module_type_kind fmt father k;
+ self#latex_of_text fmt
+ [ Code " ";
+ Code (self#relative_idents father s);
+ ]
+ | Module_type_typeof s ->
+ self#latex_of_text fmt
+ [ Code "module type of ";
+ Code (self#relative_idents father s);
+ ]
+
+ method latex_of_module_kind fmt father kind =
+ match kind with
+ Module_struct eles ->
+ self#latex_of_text fmt [Latex "\\begin{ocamldocsigend}\n"];
+ List.iter (self#latex_of_module_element fmt father) eles;
+ self#latex_of_text fmt [Latex "\\end{ocamldocsigend}\n"]
+ | Module_alias a ->
+ self#latex_of_text fmt
+ [Code (self#relative_module_idents father a.ma_name)]
+ | Module_functor (p, k) ->
+ self#latex_of_module_parameter fmt father p;
+ self#latex_of_module_kind fmt father k
+ | Module_apply (k1, k2) ->
+ (* TODO: l'application n'est pas correcte dans un .mli.
+ Que faire ? -> afficher le module_type du typedtree *)
+ self#latex_of_module_kind fmt father k1;
+ self#latex_of_text fmt [Code "("];
+ self#latex_of_module_kind fmt father k2;
+ self#latex_of_text fmt [Code ")"]
+ | Module_with (k, s) ->
+ (* TODO: à modifier quand Module_with sera plus détaillé *)
+ self#latex_of_module_type_kind fmt father k;
+ self#latex_of_text fmt
+ [ Code " ";
+ Code (self#relative_idents father s) ;
+ ]
+ | Module_constraint (k, tk) ->
+ (* TODO: on affiche quoi ? *)
+ self#latex_of_module_kind fmt father k
+ | Module_typeof s ->
+ self#latex_of_text fmt
+ [ Code "module type of ";
+ Code (self#relative_idents father s);
+ ]
+ | Module_unpack (s, _) ->
+ self#latex_of_text fmt
+ [
+ Code (self#relative_idents father s);
+ ]
+
+ method latex_of_class_kind fmt father kind =
+ match kind with
+ Class_structure (inh, eles) ->
+ self#latex_of_text fmt [Latex "\\begin{ocamldocobjectend}\n"];
+ self#generate_inheritance_info fmt inh;
+ List.iter (self#latex_of_class_element fmt father) eles;
+ self#latex_of_text fmt [Latex "\\end{ocamldocobjectend}\n"]
+
+ | Class_apply capp ->
+ (* TODO: afficher le type final à partir du typedtree *)
+ self#latex_of_text fmt [Raw "class application not handled yet"]
+
+ | Class_constr cco ->
+ (
+ match cco.cco_type_parameters with
+ [] -> ()
+ | l ->
+ self#latex_of_text fmt
+ (
+ Code "[" ::
+ (self#text_of_class_type_param_expr_list father l) @
+ [Code "] "]
+ )
+ );
+ self#latex_of_text fmt
+ [Code (self#relative_idents father cco.cco_name)]
+
+ | Class_constraint (ck, ctk) ->
+ self#latex_of_text fmt [Code "( "] ;
+ self#latex_of_class_kind fmt father ck;
+ self#latex_of_text fmt [Code " : "] ;
+ self#latex_of_class_type_kind fmt father ctk;
+ self#latex_of_text fmt [Code " )"]
+
+ method latex_of_class_type_kind fmt father kind =
+ match kind with
+ Class_type cta ->
+ (
+ match cta.cta_type_parameters with
+ [] -> ()
+ | l ->
+ self#latex_of_text fmt
+ (Code "[" ::
+ (self#text_of_class_type_param_expr_list father l) @
+ [Code "] "]
+ )
+ );
+ self#latex_of_text fmt
+ [Code (self#relative_idents father cta.cta_name)]
+
+ | Class_signature (inh, eles) ->
+ self#latex_of_text fmt [Latex "\\begin{ocamldocobjectend}\n"];
+ self#generate_inheritance_info fmt inh;
+ List.iter (self#latex_of_class_element fmt father) eles;
+ self#latex_of_text fmt [Latex "\\end{ocamldocobjectend}\n"]
+
+ method latex_for_module_index fmt m =
+ let s_name = Name.simple m.m_name in
+ self#latex_of_text fmt
+ [Latex ("\\index{"^(self#label s_name)^"@\\verb`"^
+ (self#label ~no_:false s_name)^"`}\n"
+ )
+ ]
+
+ method latex_for_module_type_index fmt mt =
+ let s_name = Name.simple mt.mt_name in
+ self#latex_of_text fmt
+ [Latex ("\\index{"^(self#label s_name)^"@\\verb`"^
+ (self#label ~no_:false (Name.simple s_name))^"`}\n"
+ )
+ ]
+
+ method latex_for_module_label fmt m =
+ ps fmt (self#make_label (self#module_label m.m_name))
+
+ method latex_for_module_type_label fmt mt =
+ ps fmt (self#make_label (self#module_type_label mt.mt_name))
+
+
+ method latex_for_class_index fmt c =
+ let s_name = Name.simple c.cl_name in
+ self#latex_of_text fmt
+ [Latex ("\\index{"^(self#label s_name)^"@\\verb`"^
+ (self#label ~no_:false s_name)^"`}\n"
+ )
+ ]
+
+ method latex_for_class_type_index fmt ct =
+ let s_name = Name.simple ct.clt_name in
+ self#latex_of_text fmt
+ [Latex ("\\index{"^(self#label s_name)^"@\\verb`"^
+ (self#label ~no_:false s_name)^"`}\n"
+ )
+ ]
+
+ method latex_for_class_label fmt c =
+ ps fmt (self#make_label (self#class_label c.cl_name))
+
+ method latex_for_class_type_label fmt ct =
+ ps fmt (self#make_label (self#class_type_label ct.clt_name))
+
+ (** Print the LaTeX code for the given module. *)
+ method latex_of_module fmt m =
+ let father = Name.father m.m_name in
+ let t =
+ [
+ Latex "\\begin{ocamldoccode}\n" ;
+ Code "module ";
+ Code (Name.simple m.m_name);
+ Code " : ";
+ ]
+ in
+ self#latex_of_text fmt t;
+ self#latex_of_text fmt [ Latex "\\end{ocamldoccode}\n" ];
+ self#latex_for_module_label fmt m;
+ self#latex_for_module_index fmt m;
+ p fmt "@[<h 4>";
+ self#latex_of_module_kind fmt father m.m_kind;
+ (
+ match Module.module_is_functor m with
+ false -> ()
+ | true ->
+ self#latex_of_text fmt [Newline];
+ (
+ match List.filter (fun (_,d) -> d <> None)
+ (module_parameters ~trans: false m)
+ with
+ [] -> ()
+ | l ->
+ let t =
+ [ Bold [Raw "Parameters: "];
+ List
+ (List.map
+ (fun (p,text_opt) ->
+ let t = match text_opt with None -> [] | Some t -> t in
+ ( Raw p.mp_name :: Raw ": " :: t)
+ )
+ l
+ )
+ ]
+ in
+ self#latex_of_text fmt t
+ );
+ );
+ self#latex_of_text fmt [Newline];
+ self#latex_of_info fmt ~block: true m.m_info;
+ p fmt "@]";
+
+
+ (** Print the LaTeX code for the given module type. *)
+ method latex_of_module_type fmt mt =
+ let father = Name.father mt.mt_name in
+ let t =
+ [
+ Latex "\\begin{ocamldoccode}\n" ;
+ Code "module type " ;
+ Code (Name.simple mt.mt_name);
+ ]
+ in
+ self#latex_of_text fmt t;
+ (
+ match mt.mt_type, mt.mt_kind with
+ | Some mtyp, Some kind ->
+ self#latex_of_text fmt [ Code " = " ];
+ self#latex_of_text fmt [ Latex "\\end{ocamldoccode}\n" ];
+ self#latex_for_module_type_label fmt mt;
+ self#latex_for_module_type_index fmt mt;
+ p fmt "@[<h 4>";
+ self#latex_of_module_type_kind fmt father kind
+ | _ ->
+ self#latex_of_text fmt [ Latex "\\end{ocamldoccode}\n" ];
+ self#latex_for_module_type_index fmt mt;
+ p fmt "@[<h 4>";
+ );
+ (
+ match Module.module_type_is_functor mt with
+ false -> ()
+ | true ->
+ self#latex_of_text fmt [Newline];
+ (
+ match List.filter (fun (_,d) -> d <> None)
+ (module_type_parameters ~trans: false mt)
+ with
+ [] -> ()
+ | l ->
+ let t =
+ [ Bold [Raw "Parameters: "];
+ List
+ (List.map
+ (fun (p,text_opt) ->
+ let t = match text_opt with None -> [] | Some t -> t in
+ ( Raw p.mp_name :: Raw ": " :: t)
+ )
+ l
+ )
+ ]
+ in
+ self#latex_of_text fmt t
+ );
+ );
+ self#latex_of_text fmt [Newline];
+ self#latex_of_info fmt ~block: true mt.mt_info;
+ p fmt "@]";
+
+ (** Print the LaTeX code for the given included module. *)
+ method latex_of_included_module fmt im =
+ self#latex_of_text fmt
+ ((Code "include ") ::
+ (Code
+ (match im.im_module with
+ None -> im.im_name
+ | Some (Mod m) -> m.m_name
+ | Some (Modtype mt) -> mt.mt_name)
+ ) ::
+ (self#text_of_info im.im_info)
+ )
+
+ (** Print the LaTeX code for the given class. *)
+ method latex_of_class fmt c =
+ Odoc_info.reset_type_names () ;
+ let father = Name.father c.cl_name in
+ let type_params =
+ match c.cl_type_parameters with
+ [] -> ""
+ | l -> (self#normal_class_type_param_list father l)^" "
+ in
+ let t =
+ [
+ Latex "\\begin{ocamldoccode}\n" ;
+ Code (Printf.sprintf
+ "class %s%s%s : "
+ (if c.cl_virtual then "virtual " else "")
+ type_params
+ (Name.simple c.cl_name)
+ )
+ ]
+ in
+ self#latex_of_text fmt t;
+ self#latex_of_class_parameter_list fmt father c;
+ (* avoid a big gap if the kind is a consrt *)
+ (
+ match c.cl_kind with
+ Class.Class_constr _ ->
+ self#latex_of_class_kind fmt father c.cl_kind
+ | _ ->
+ ()
+ );
+ self#latex_of_text fmt [ Latex "\\end{ocamldoccode}\n" ];
+ self#latex_for_class_label fmt c;
+ self#latex_for_class_index fmt c;
+ p fmt "@[<h 4>";
+ (match c.cl_kind with
+ Class.Class_constr _ -> ()
+ | _ -> self#latex_of_class_kind fmt father c.cl_kind
+ );
+ self#latex_of_text fmt [Newline];
+ self#latex_of_info fmt ~block: true c.cl_info;
+ p fmt "@]"
+
+ (** Print the LaTeX code for the given class type. *)
+ method latex_of_class_type fmt ct =
+ Odoc_info.reset_type_names () ;
+ let father = Name.father ct.clt_name in
+ let type_params =
+ match ct.clt_type_parameters with
+ [] -> ""
+ | l -> (self#normal_class_type_param_list father l)^" "
+ in
+ let t =
+ [
+ Latex "\\begin{ocamldoccode}\n" ;
+ Code (Printf.sprintf
+ "class type %s%s%s = "
+ (if ct.clt_virtual then "virtual " else "")
+ type_params
+ (Name.simple ct.clt_name)
+ )
+ ]
+ in
+ self#latex_of_text fmt t;
+
+ self#latex_of_text fmt [ Latex "\\end{ocamldoccode}\n" ];
+ self#latex_for_class_type_label fmt ct;
+ self#latex_for_class_type_index fmt ct;
+ p fmt "@[<h 4>";
+ self#latex_of_class_type_kind fmt father ct.clt_kind;
+ self#latex_of_text fmt [Newline];
+ self#latex_of_info fmt ~block: true ct.clt_info;
+ p fmt "@]"
+
+ (** Print the LaTeX code for the given class element. *)
+ method latex_of_class_element fmt class_name class_ele =
+ self#latex_of_text fmt [Newline];
+ match class_ele with
+ Class_attribute att -> self#latex_of_attribute fmt att
+ | Class_method met -> self#latex_of_method fmt met
+ | Class_comment t ->
+ match t with
+ | [] -> ()
+ | (Title (_,_,_)) :: _ -> self#latex_of_text fmt t
+ | _ -> self#latex_of_text fmt [ Title ((Name.depth class_name) + 2, None, t) ]
+
+ (** Print the LaTeX code for the given module element. *)
+ method latex_of_module_element fmt module_name module_ele =
+ self#latex_of_text fmt [Newline];
+ match module_ele with
+ Element_module m -> self#latex_of_module fmt m
+ | Element_module_type mt -> self#latex_of_module_type fmt mt
+ | Element_included_module im -> self#latex_of_included_module fmt im
+ | Element_class c -> self#latex_of_class fmt c
+ | Element_class_type ct -> self#latex_of_class_type fmt ct
+ | Element_value v -> self#latex_of_value fmt v
+ | Element_exception e -> self#latex_of_exception fmt e
+ | Element_type t -> self#latex_of_type fmt t
+ | Element_module_comment t -> self#latex_of_text fmt t
+
+ (** Generate the LaTeX code for the given list of inherited classes.*)
+ method generate_inheritance_info fmt inher_l =
+ let f inh =
+ match inh.ic_class with
+ None -> (* we can't make the reference *)
+ Newline ::
+ Code ("inherit "^inh.ic_name) ::
+ (match inh.ic_text with
+ None -> []
+ | Some t -> Newline :: t
+ )
+ | Some cct ->
+ let label =
+ match cct with
+ Cl _ -> self#class_label inh.ic_name
+ | Cltype _ -> self#class_type_label inh.ic_name
+ in
+ (* we can create the reference *)
+ Newline ::
+ Odoc_info.Code ("inherit "^inh.ic_name) ::
+ (Odoc_info.Latex (" ["^(self#make_ref label)^"]")) ::
+ (match inh.ic_text with
+ None -> []
+ | Some t -> Newline :: t
+ )
+ in
+ List.iter (self#latex_of_text fmt) (List.map f inher_l)
+
+ (** Generate the LaTeX code for the inherited classes of the given class. *)
+ method generate_class_inheritance_info fmt cl =
+ let rec iter_kind k =
+ match k with
+ Class_structure ([], _) ->
+ ()
+ | Class_structure (l, _) ->
+ self#generate_inheritance_info fmt l
+ | Class_constraint (k, _) ->
+ iter_kind k
+ | Class_apply _
+ | Class_constr _ ->
+ ()
+ in
+ iter_kind cl.cl_kind
+
+ (** Generate the LaTeX code for the inherited classes of the given class type. *)
+ method generate_class_type_inheritance_info fmt clt =
+ match clt.clt_kind with
+ Class_signature ([], _) ->
+ ()
+ | Class_signature (l, _) ->
+ self#generate_inheritance_info fmt l
+ | Class_type _ ->
+ ()
+
+ (** Generate the LaTeX code for the given top module, in the given buffer. *)
+ method generate_for_top_module fmt m =
+ let (first_t, rest_t) = self#first_and_rest_of_info m.m_info in
+ let text =
+ if m.m_text_only then
+ [ Title (1, None, [Raw m.m_name] @
+ (match first_t with
+ [] -> []
+ | t -> (Raw " : ") :: t)
+ ) ;
+ ]
+ else
+ [ Title (1, None,
+ [ Raw (Odoc_messages.modul^" ") ; Code m.m_name ] @
+ (match first_t with
+ [] -> []
+ | t -> (Raw " : ") :: t)) ;
+ ]
+ in
+ self#latex_of_text fmt text;
+ self#latex_for_module_label fmt m;
+ self#latex_for_module_index fmt m;
+ self#latex_of_text fmt rest_t ;
+
+ self#latex_of_text fmt [ Newline ] ;
+ if not m.m_text_only then ps fmt "\\ocamldocvspace{0.5cm}\n\n";
+ List.iter
+ (fun ele ->
+ self#latex_of_module_element fmt m.m_name ele;
+ ps fmt "\n\n"
+ )
+ (Module.module_elements ~trans: false m)
+
+ (** Print the header of the TeX document. *)
+ method latex_header fmt module_list =
+ ps fmt "\\documentclass[11pt]{article} \n";
+ ps fmt "\\usepackage[latin1]{inputenc} \n";
+ ps fmt "\\usepackage[T1]{fontenc} \n";
+ ps fmt "\\usepackage{fullpage} \n";
+ ps fmt "\\usepackage{url} \n";
+ ps fmt "\\usepackage{ocamldoc}\n";
+ (
+ match !Global.title with
+ None -> ()
+ | Some s ->
+ ps fmt "\\title{";
+ ps fmt (self#escape s);
+ ps fmt "}\n"
+ );
+ ps fmt "\\begin{document}\n";
+ (match !Global.title with
+ None -> () |
+ Some _ -> ps fmt "\\maketitle\n"
+ );
+ if !Global.with_toc then ps fmt "\\tableofcontents\n";
+ (
+ let info = Odoc_info.apply_opt
+ (Odoc_info.info_of_comment_file module_list)
+ !Odoc_info.Global.intro_file
+ in
+ (match info with None -> () | Some _ -> ps fmt "\\vspace{0.2cm}");
+ self#latex_of_info fmt info;
+ (match info with None -> () | Some _ -> ps fmt "\n\n")
+ )
+
+
+ (** Generate the LaTeX style file, if it does not exists. *)
+ method generate_style_file =
+ try
+ let dir = Filename.dirname !Global.out_file in
+ let file = Filename.concat dir "ocamldoc.sty" in
+ if Sys.file_exists file then
+ Odoc_info.verbose (Odoc_messages.file_exists_dont_generate file)
+ else
+ (
+ let chanout = open_out file in
+ output_string chanout Odoc_latex_style.content ;
+ flush chanout ;
+ close_out chanout;
+ Odoc_info.verbose (Odoc_messages.file_generated file)
+ )
+ with
+ Sys_error s ->
+ prerr_endline s ;
+ incr Odoc_info.errors ;
+
+ (** Generate the LaTeX file from a module list, in the {!Odoc_info.Global.out_file} file. *)
+ method generate module_list =
+ self#generate_style_file ;
+ let main_file = !Global.out_file in
+ let dir = Filename.dirname main_file in
+ if !separate_files then
+ (
+ let f m =
+ try
+ let chanout =
+ open_out ((Filename.concat dir (Name.simple m.m_name))^".tex")
+ in
+ let fmt = Format.formatter_of_out_channel chanout in
+ self#generate_for_top_module fmt m ;
+ Format.pp_print_flush fmt ();
+ close_out chanout
+ with
+ Failure s
+ | Sys_error s ->
+ prerr_endline s ;
+ incr Odoc_info.errors
+ in
+ List.iter f module_list
+ );
+
+ try
+ let chanout = open_out main_file in
+ let fmt = Format.formatter_of_out_channel chanout in
+ if !Global.with_header then self#latex_header fmt module_list;
+ List.iter
+ (fun m ->
+ if !separate_files then
+ ps fmt ("\\input{"^((Name.simple m.m_name))^".tex}\n")
+ else
+ self#generate_for_top_module fmt m
+ )
+ module_list ;
+ if !Global.with_trailer then ps fmt "\\end{document}";
+ Format.pp_print_flush fmt ();
+ close_out chanout
+ with
+ Failure s
+ | Sys_error s ->
+ prerr_endline s ;
+ incr Odoc_info.errors
+ end
+end
+
+module type Latex_generator = module type of Generator
diff --git a/ocaml-binary-annot/ocamldoc/odoc_latex_style.ml b/ocaml-binary-annot/ocamldoc/odoc_latex_style.ml
new file mode 100644
index 0000000000..a689b26866
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_latex_style.ml
@@ -0,0 +1,91 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(** The content of the LaTeX style to generate when generating LaTeX code. *)
+
+(* $Id$ *)
+
+let content ="\n\
+%% Support macros for LaTeX documentation generated by ocamldoc.\n\
+%% This file is in the public domain; do what you want with it.\n\
+\n\
+\\NeedsTeXFormat{LaTeX2e}\n\
+\\ProvidesPackage{ocamldoc}\n\
+ [2001/12/04 v1.0 ocamldoc support]\n\
+\n\
+\\newenvironment{ocamldoccode}{%\n\
+ \\bgroup\n\
+ \\leftskip\\@totalleftmargin\n\
+ \\rightskip\\z@skip\n\
+ \\parindent\\z@\n\
+ \\parfillskip\\@flushglue\n\
+ \\parskip\\z@skip\n\
+ %\\noindent\n\
+ \\@@par\\smallskip\n\
+ \\@tempswafalse\n\
+ \\def\\par{%\n\
+ \\if@tempswa\n\
+ \\leavevmode\\null\\@@par\\penalty\\interlinepenalty\n\
+ \\else\n\
+ \\@tempswatrue\n\
+ \\ifhmode\\@@par\\penalty\\interlinepenalty\\fi\n\
+ \\fi}\n\
+ \\obeylines\n\
+ \\verbatim@font\n\
+ \\let\\org@prime~%\n\
+ \\@noligs\n\
+ \\let\\org@dospecials\\dospecials\n\
+ \\g@remfrom@specials{\\\\}\n\
+ \\g@remfrom@specials{\\{}\n\
+ \\g@remfrom@specials{\\}}\n\
+ \\let\\do\\@makeother\n\
+ \\dospecials\n\
+ \\let\\dospecials\\org@dospecials\n\
+ \\frenchspacing\\@vobeyspaces\n\
+ \\everypar \\expandafter{\\the\\everypar \\unpenalty}}\n\
+{\\egroup\\par}\n\
+\n\
+\\def\\g@remfrom@specials#1{%\n\
+ \\def\\@new@specials{}\n\
+ \\def\\@remove##1{%\n\
+ \\ifx##1#1\\else\n\
+ \\g@addto@macro\\@new@specials{\\do ##1}\\fi}\n\
+ \\let\\do\\@remove\\dospecials\n\
+ \\let\\dospecials\\@new@specials\n\
+ }\n\
+\n\
+\\newenvironment{ocamldocdescription}\n\
+{\\list{}{\\rightmargin0pt \\topsep0pt}\\raggedright\\item\\noindent\\relax\\ignorespaces}\n\
+{\\endlist\\medskip}\n\
+\n\
+\\newenvironment{ocamldoccomment}\n\
+{\\list{}{\\leftmargin 2\\leftmargini \\rightmargin0pt \\topsep0pt}\\raggedright\\item\\noindent\\relax}\n\
+{\\endlist}\n\
+\n\
+\\let \\ocamldocparagraph \\paragraph\n\
+\\def \\paragraph #1{\\ocamldocparagraph {#1}\\noindent}\n\
+\\let \\ocamldocsubparagraph \\subparagraph\n\
+\\def \\subparagraph #1{\\ocamldocsubparagraph {#1}\\noindent}\n\
+\n\
+\\let\\ocamldocvspace\\vspace\n\
+\n\
+\\newenvironment{ocamldocindent}{\\list{}{}\\item\\relax}{\\endlist}\n\
+\\newenvironment{ocamldocsigend}\n\
+ {\\noindent\\quad\\texttt{sig}\\ocamldocindent}\n\
+ {\\endocamldocindent\\vskip -\\lastskip\n\
+ \\noindent\\quad\\texttt{end}\\medskip}\n\
+\\newenvironment{ocamldocobjectend}\n\
+ {\\noindent\\quad\\texttt{object}\\ocamldocindent}\n\
+ {\\endocamldocindent\\vskip -\\lastskip\n\
+ \\noindent\\quad\\texttt{end}\\medskip}\n\
+\n\
+\\endinput\n\
+"
diff --git a/ocaml-binary-annot/ocamldoc/odoc_lexer.mll b/ocaml-binary-annot/ocamldoc/odoc_lexer.mll
new file mode 100644
index 0000000000..318a839fff
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_lexer.mll
@@ -0,0 +1,413 @@
+{
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** The lexer for special comments. *)
+
+open Lexing
+open Odoc_parser
+
+let line_number = ref 0
+
+
+let string_buffer = Buffer.create 32
+
+(** Fonction de remise à zéro de la chaine de caractères tampon *)
+let reset_string_buffer () = Buffer.reset string_buffer
+
+(** Fonction d'ajout d'un caractère dans la chaine de caractères tampon *)
+let ajout_char_string = Buffer.add_char string_buffer
+
+(** Add a string to the buffer. *)
+let ajout_string = Buffer.add_string string_buffer
+
+let lecture_string () = Buffer.contents string_buffer
+
+(** The variable which will contain the description string.
+ Is initialized when we encounter the start of a special comment. *)
+let description = ref ""
+
+let blank = "[ \013\009\012]"
+
+(** The nested comments level. *)
+let comments_level = ref 0
+
+let print_DEBUG2 s = print_string s; print_newline ()
+
+(** This function returns the given string without the leading and trailing blanks.*)
+let remove_blanks s =
+ print_DEBUG2 ("remove_blanks "^s);
+ let l = Str.split_delim (Str.regexp "\n") s in
+ let l2 =
+ let rec iter liste =
+ match liste with
+ h :: q ->
+ let h2 = Str.global_replace (Str.regexp ("^"^blank^"+")) "" h in
+ if h2 = "" then
+ (
+ print_DEBUG2 (h^" n'a que des blancs");
+ (* we remove this line and must remove leading blanks of the next one *)
+ iter q
+ )
+ else
+ (* we don't remove leading blanks in the remaining lines *)
+ h2 :: q
+ | _ ->
+ []
+ in iter l
+ in
+ let l3 =
+ let rec iter liste =
+ match liste with
+ h :: q ->
+ let h2 = Str.global_replace (Str.regexp (blank^"+$")) "" h in
+ if h2 = "" then
+ (
+ print_DEBUG2 (h^" n'a que des blancs");
+ (* we remove this line and must remove trailing blanks of the next one *)
+ iter q
+ )
+ else
+ (* we don't remove trailing blanks in the remaining lines *)
+ h2 :: q
+ | _ ->
+ []
+ in
+ List.rev (iter (List.rev l2))
+ in
+ String.concat "\n" l3
+
+(** Remove first blank characters of each line of a string, until the first '*' *)
+let remove_stars s =
+ let s2 = Str.global_replace (Str.regexp ("^"^blank^"*\\*")) "" s in
+ s2
+}
+
+let lowercase = ['a'-'z' '\223'-'\246' '\248'-'\255' '_']
+let uppercase = ['A'-'Z' '\192'-'\214' '\216'-'\222']
+let identchar =
+ ['A'-'Z' 'a'-'z' '_' '\192'-'\214' '\216'-'\246' '\248'-'\255' '\'' '0'-'9']
+
+rule main = parse
+ [' ' '\013' '\009' '\012'] +
+ {
+ Odoc_comments_global.nb_chars := !Odoc_comments_global.nb_chars + (String.length (Lexing.lexeme lexbuf));
+ main lexbuf
+ }
+
+ | [ '\010' ]
+ {
+ incr line_number;
+ incr Odoc_comments_global.nb_chars;
+ main lexbuf
+ }
+ | "(**)"
+ {
+ Odoc_comments_global.nb_chars := !Odoc_comments_global.nb_chars + (String.length (Lexing.lexeme lexbuf));
+ Description ("", None)
+ }
+
+ | "(**"("*"+)")"
+ {
+ Odoc_comments_global.nb_chars := !Odoc_comments_global.nb_chars + (String.length (Lexing.lexeme lexbuf));
+ main lexbuf
+ }
+
+ | "(***"
+ {
+ Odoc_comments_global.nb_chars := !Odoc_comments_global.nb_chars + (String.length (Lexing.lexeme lexbuf));
+ incr comments_level;
+ main lexbuf
+ }
+
+ | "(**"
+ {
+ Odoc_comments_global.nb_chars := !Odoc_comments_global.nb_chars + (String.length (Lexing.lexeme lexbuf));
+ incr comments_level;
+ if !comments_level = 1 then
+ (
+ reset_string_buffer ();
+ description := "";
+ special_comment lexbuf
+ )
+ else
+ main lexbuf
+ }
+
+ | eof
+ { EOF }
+
+ | "*)"
+ {
+ Odoc_comments_global.nb_chars := !Odoc_comments_global.nb_chars + (String.length (Lexing.lexeme lexbuf));
+ decr comments_level ;
+ main lexbuf
+ }
+
+ | "(*"
+ {
+ Odoc_comments_global.nb_chars := !Odoc_comments_global.nb_chars + (String.length (Lexing.lexeme lexbuf));
+ incr comments_level ;
+ main lexbuf
+ }
+
+ | _
+ {
+ incr Odoc_comments_global.nb_chars;
+ main lexbuf
+ }
+
+and special_comment = parse
+ | "*)"
+ {
+ let s = Lexing.lexeme lexbuf in
+ Odoc_comments_global.nb_chars := !Odoc_comments_global.nb_chars + (String.length s);
+ if !comments_level = 1 then
+ (
+ (* there is just a description *)
+ let s2 = lecture_string () in
+ let s3 = remove_blanks s2 in
+ let s4 =
+ if !Odoc_global.remove_stars then
+ remove_stars s3
+ else
+ s3
+ in
+ Description (s4, None)
+ )
+ else
+ (
+ ajout_string s;
+ decr comments_level;
+ special_comment lexbuf
+ )
+ }
+
+ | "(*"
+ {
+ let s = Lexing.lexeme lexbuf in
+ Odoc_comments_global.nb_chars := !Odoc_comments_global.nb_chars + (String.length s);
+ incr comments_level ;
+ ajout_string s;
+ special_comment lexbuf
+ }
+
+ | "\\@"
+ {
+ let s = Lexing.lexeme lexbuf in
+ let c = (Lexing.lexeme_char lexbuf 1) in
+ ajout_char_string c;
+ Odoc_comments_global.nb_chars := !Odoc_comments_global.nb_chars + (String.length s);
+ special_comment lexbuf
+ }
+
+ | "@"lowercase+
+ {
+ (* we keep the description before we go further *)
+ let s = lecture_string () in
+ description := remove_blanks s;
+ reset_string_buffer ();
+ let len = String.length (Lexing.lexeme lexbuf) in
+ lexbuf.Lexing.lex_curr_pos <- lexbuf.Lexing.lex_curr_pos - len;
+ lexbuf.Lexing.lex_curr_p <-
+ { lexbuf.Lexing.lex_curr_p with
+ pos_cnum = lexbuf.Lexing.lex_curr_p.pos_cnum - len
+ } ;
+ (* we don't increment the Odoc_comments_global.nb_chars *)
+ special_comment_part2 lexbuf
+ }
+
+ | _
+ {
+ let c = (Lexing.lexeme_char lexbuf 0) in
+ ajout_char_string c;
+ if c = '\010' then incr line_number;
+ incr Odoc_comments_global.nb_chars;
+ special_comment lexbuf
+ }
+
+and special_comment_part2 = parse
+ | "*)"
+ {
+ let s = Lexing.lexeme lexbuf in
+ Odoc_comments_global.nb_chars := !Odoc_comments_global.nb_chars + (String.length s);
+ if !comments_level = 1 then
+ (* finally we return the description we kept *)
+ let desc =
+ if !Odoc_global.remove_stars then
+ remove_stars !description
+ else
+ !description
+ in
+ let remain = lecture_string () in
+ let remain2 =
+ if !Odoc_global.remove_stars then
+ remove_stars remain
+ else
+ remain
+ in
+ Description (desc, Some remain2)
+ else
+ (
+ ajout_string s ;
+ decr comments_level ;
+ special_comment_part2 lexbuf
+ )
+ }
+
+ | "(*"
+ {
+ let s = Lexing.lexeme lexbuf in
+ Odoc_comments_global.nb_chars := !Odoc_comments_global.nb_chars + (String.length s);
+ ajout_string s;
+ incr comments_level ;
+ special_comment_part2 lexbuf
+ }
+
+ | _
+ {
+ let c = (Lexing.lexeme_char lexbuf 0) in
+ ajout_char_string c;
+ if c = '\010' then incr line_number;
+ incr Odoc_comments_global.nb_chars;
+ special_comment_part2 lexbuf
+ }
+
+and elements = parse
+ | [' ' '\013' '\009' '\012'] +
+ {
+ Odoc_comments_global.nb_chars := !Odoc_comments_global.nb_chars + (String.length (Lexing.lexeme lexbuf));
+ elements lexbuf
+ }
+
+ | [ '\010' ]
+ { incr line_number;
+ incr Odoc_comments_global.nb_chars;
+ print_DEBUG2 "newline";
+ elements lexbuf }
+
+ | "@"lowercase+
+ {
+ let s = Lexing.lexeme lexbuf in
+ Odoc_comments_global.nb_chars := !Odoc_comments_global.nb_chars + (String.length s);
+ let s2 = String.sub s 1 ((String.length s) - 1) in
+ print_DEBUG2 s2;
+ match s2 with
+ "param" ->
+ T_PARAM
+ | "author" ->
+ T_AUTHOR
+ | "version" ->
+ T_VERSION
+ | "see" ->
+ T_SEE
+ | "since" ->
+ T_SINCE
+ | "before" ->
+ T_BEFORE
+ | "deprecated" ->
+ T_DEPRECATED
+ | "raise" ->
+ T_RAISES
+ | "return" ->
+ T_RETURN
+ | s ->
+ if !Odoc_global.no_custom_tags then
+ raise (Failure (Odoc_messages.not_a_valid_tag s))
+ else
+ T_CUSTOM s
+ }
+
+ | ("\\@" | [^'@'])+
+ {
+ Odoc_comments_global.nb_chars := !Odoc_comments_global.nb_chars + (String.length (Lexing.lexeme lexbuf));
+ let s = Lexing.lexeme lexbuf in
+ let s = Str.global_replace (Str.regexp_string "\\@") "@" s in
+ let s = remove_blanks s in
+ print_DEBUG2 ("Desc "^s);
+ Desc s
+ }
+ | eof
+ {
+ EOF
+ }
+
+
+and simple = parse
+ [' ' '\013' '\009' '\012'] +
+ {
+ Odoc_comments_global.nb_chars := !Odoc_comments_global.nb_chars + (String.length (Lexing.lexeme lexbuf));
+ simple lexbuf
+ }
+
+ | [ '\010' ]
+ { incr line_number;
+ incr Odoc_comments_global.nb_chars;
+ simple lexbuf
+ }
+
+ | "(**"("*"+)
+ {
+ Odoc_comments_global.nb_chars := !Odoc_comments_global.nb_chars + (String.length (Lexing.lexeme lexbuf));
+ incr comments_level;
+ simple lexbuf
+ }
+
+ | "(*"("*"+)")"
+ {
+ let s = Lexing.lexeme lexbuf in
+ Odoc_comments_global.nb_chars := !Odoc_comments_global.nb_chars + (String.length s);
+ simple lexbuf
+ }
+ | "(**"
+ {
+ let s = Lexing.lexeme lexbuf in
+ Odoc_comments_global.nb_chars := !Odoc_comments_global.nb_chars + (String.length s);
+ incr comments_level;
+ simple lexbuf
+ }
+
+ | "(*"
+ {
+ let s = Lexing.lexeme lexbuf in
+ Odoc_comments_global.nb_chars := !Odoc_comments_global.nb_chars + (String.length s);
+ incr comments_level;
+ if !comments_level = 1 then
+ (
+ reset_string_buffer ();
+ description := "";
+ special_comment lexbuf
+ )
+ else
+ (
+ ajout_string s;
+ simple lexbuf
+ )
+ }
+
+ | eof
+ { EOF }
+
+ | "*)"
+ {
+ let s = Lexing.lexeme lexbuf in
+ Odoc_comments_global.nb_chars := !Odoc_comments_global.nb_chars + (String.length s);
+ decr comments_level ;
+ simple lexbuf
+ }
+
+ | _
+ {
+ incr Odoc_comments_global.nb_chars;
+ simple lexbuf
+ }
diff --git a/ocaml-binary-annot/ocamldoc/odoc_man.ml b/ocaml-binary-annot/ocamldoc/odoc_man.ml
new file mode 100644
index 0000000000..612bc11a02
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_man.ml
@@ -0,0 +1,1089 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** The man pages generator. *)
+open Odoc_info
+open Parameter
+open Value
+open Type
+open Exception
+open Class
+open Module
+open Search
+
+let man_suffix = ref Odoc_messages.default_man_suffix
+let man_section = ref Odoc_messages.default_man_section
+
+let man_mini = ref false
+
+let new_buf () = Buffer.create 1024
+let bp = Printf.bprintf
+let bs = Buffer.add_string
+
+(** A class used to get a [text] for info structures. *)
+class virtual info =
+ object (self)
+ (** The list of pairs [(tag, f)] where [f] is a function taking
+ the [text] associated to [tag] and returning man code.
+ Add a pair here to handle a tag.*)
+ val mutable tag_functions = ([] : (string * (Odoc_info.text -> string)) list)
+
+ (** Return man code for a [text]. *)
+ method virtual man_of_text : Buffer.t -> Odoc_info.text -> unit
+
+ (** Print groff string for an author list. *)
+ method man_of_author_list b l =
+ match l with
+ [] -> ()
+ | _ ->
+ bs b ".B \"";
+ bs b Odoc_messages.authors;
+ bs b "\"\n:\n";
+ bs b (String.concat ", " l);
+ bs b "\n.sp\n"
+
+ (** Print groff string for the given optional version information.*)
+ method man_of_version_opt b v_opt =
+ match v_opt with
+ None -> ()
+ | Some v ->
+ bs b ".B \"";
+ bs b Odoc_messages.version;
+ bs b "\"\n:\n";
+ bs b v;
+ bs b "\n.sp\n"
+
+ (** Printf groff string for the \@before information. *)
+ method man_of_before b = function
+ [] -> ()
+ | l ->
+ List.iter
+ (fun (v, text) ->
+ bp b ".B \"%s" Odoc_messages.before;
+ bs b v;
+ bs b "\"\n";
+ self#man_of_text b text;
+ bs b "\n";
+ bs b "\n.sp\n"
+ )
+ l
+
+
+ (** Print groff string for the given optional since information.*)
+ method man_of_since_opt b s_opt =
+ match s_opt with
+ None -> ()
+ | Some s ->
+ bs b ".B \"";
+ bs b Odoc_messages.since;
+ bs b "\"\n";
+ bs b s;
+ bs b "\n.sp\n"
+
+ (** Print groff string for the given list of raised exceptions.*)
+ method man_of_raised_exceptions b l =
+ match l with
+ [] -> ()
+ | (s, t) :: [] ->
+ bs b ".B \"";
+ bs b Odoc_messages.raises;
+ bs b (" "^s^"\"\n");
+ self#man_of_text b t;
+ bs b "\n.sp\n"
+ | _ ->
+ bs b ".B \"";
+ bs b Odoc_messages.raises;
+ bs b "\"\n";
+ List.iter
+ (fun (ex, desc) ->
+ bs b ".sp\n.B \"";
+ bs b ex;
+ bs b "\"\n";
+ self#man_of_text b desc;
+ bs b "\n"
+ )
+ l;
+ bs b "\n.sp\n"
+
+ (** Print groff string for the given "see also" reference. *)
+ method man_of_see b (see_ref, t) =
+ let t_ref =
+ match see_ref with
+ Odoc_info.See_url s -> [ Odoc_info.Link (s, t) ]
+ | Odoc_info.See_file s -> (Odoc_info.Code s) :: (Odoc_info.Raw " ") :: t
+ | Odoc_info.See_doc s -> (Odoc_info.Italic [Odoc_info.Raw s]) :: (Odoc_info.Raw " ") :: t
+ in
+ self#man_of_text b t_ref
+
+ (** Print groff string for the given list of "see also" references.*)
+ method man_of_sees b l =
+ match l with
+ [] -> ()
+ | see :: [] ->
+ bs b ".B \"";
+ bs b Odoc_messages.see_also;
+ bs b "\"\n";
+ self#man_of_see b see;
+ bs b "\n.sp\n"
+ | _ ->
+ bs b ".B \"";
+ bs b Odoc_messages.see_also;
+ bs b "\"\n";
+ List.iter
+ (fun see ->
+ bs b ".sp\n";
+ self#man_of_see b see;
+ bs b "\n"
+ )
+ l;
+ bs b "\n.sp\n"
+
+ (** Print groff string for the given optional return information.*)
+ method man_of_return_opt b return_opt =
+ match return_opt with
+ None -> ()
+ | Some s ->
+ bs b ".B ";
+ bs b Odoc_messages.returns;
+ bs b "\n";
+ self#man_of_text b s;
+ bs b "\n.sp\n"
+
+ (** Print man code for the given list of custom tagged texts. *)
+ method man_of_custom b l =
+ let buf = Buffer.create 50 in
+ List.iter
+ (fun (tag, text) ->
+ try
+ let f = List.assoc tag tag_functions in
+ Buffer.add_string buf (f text)
+ with
+ Not_found ->
+ Odoc_info.warning (Odoc_messages.tag_not_handled tag)
+ )
+ l
+
+ (** Print the groff string to display an optional info structure. *)
+ method man_of_info b info_opt =
+ match info_opt with
+ None -> ()
+ | Some info ->
+ let module M = Odoc_info in
+ (
+ match info.M.i_deprecated with
+ None -> ()
+ | Some d ->
+ bs b ".B \"";
+ bs b Odoc_messages.deprecated;
+ bs b "\"\n";
+ self#man_of_text b d;
+ bs b "\n.sp\n"
+ );
+ (
+ match info.M.i_desc with
+ None -> ()
+ | Some d when d = [Odoc_info.Raw ""] -> ()
+ | Some d ->
+ self#man_of_text b d;
+ bs b "\n.sp\n"
+ );
+ self#man_of_author_list b info.M.i_authors;
+ self#man_of_version_opt b info.M.i_version;
+ self#man_of_before b info.M.i_before;
+ self#man_of_since_opt b info.M.i_since;
+ self#man_of_raised_exceptions b info.M.i_raised_exceptions;
+ self#man_of_return_opt b info.M.i_return_value;
+ self#man_of_sees b info.M.i_sees;
+ self#man_of_custom b info.M.i_custom
+ end
+
+module Generator =
+struct
+
+(** This class is used to create objects which can generate a simple html documentation. *)
+class man =
+ let re_slash = Str.regexp_string "/" in
+ object (self)
+ inherit info
+
+ (** Get a file name from a complete name. *)
+ method file_name name =
+ let s = Printf.sprintf "%s.%s" name !man_suffix in
+ Str.global_replace re_slash "slash" s
+
+ (** Escape special sequences of characters in a string. *)
+ method escape (s : string) =
+ let len = String.length s in
+ let b = Buffer.create len in
+ for i = 0 to len - 1 do
+ match s.[i] with
+ '\\' -> Buffer.add_string b "\\(rs"
+ | '.' -> Buffer.add_string b "\\&."
+ | '\'' -> Buffer.add_string b "\\&'"
+ | '-' -> Buffer.add_string b "\\-"
+ | c -> Buffer.add_char b c
+ done;
+ Buffer.contents b
+
+ (** Open a file for output. Add the target directory.*)
+ method open_out file =
+ let f = Filename.concat !Global.target_dir file in
+ open_out f
+
+ (** Print groff string for a text, without correction of blanks. *)
+ method private man_of_text2 b t =
+ List.iter (self#man_of_text_element b) t
+
+ (** Print the groff string for a text, with blanks corrected. *)
+ method man_of_text b t =
+ let b2 = new_buf () in
+ self#man_of_text2 b2 t ;
+ let s = Buffer.contents b2 in
+ let s2 = Str.global_replace (Str.regexp "\n[ ]*") "\n" s in
+ bs b (Str.global_replace (Str.regexp "\n\n") "\n" s2)
+
+ (** Return the given string without no newlines. *)
+ method remove_newlines s =
+ Str.global_replace (Str.regexp "[ ]*\n[ ]*") " " s
+
+ (** Print the groff string for a text element. *)
+ method man_of_text_element b te =
+ match te with
+ | Odoc_info.Raw s -> bs b (self#escape s)
+ | Odoc_info.Code s ->
+ bs b "\n.B ";
+ bs b ((Str.global_replace (Str.regexp "\n") "\n.B " (self#escape s))^"\n")
+ | Odoc_info.CodePre s ->
+ bs b "\n.B ";
+ bs b ((Str.global_replace (Str.regexp "\n") "\n.B " (self#escape s))^"\n")
+ | Odoc_info.Verbatim s ->
+ bs b (self#escape s)
+ | Odoc_info.Bold t
+ | Odoc_info.Italic t
+ | Odoc_info.Emphasize t
+ | Odoc_info.Center t
+ | Odoc_info.Left t
+ | Odoc_info.Right t ->
+ self#man_of_text2 b t
+ | Odoc_info.List tl ->
+ List.iter
+ (fun t -> bs b "\n.sp\n \\-"; self#man_of_text2 b t; bs b "\n")
+ tl;
+ bs b "\n"
+ | Odoc_info.Enum tl ->
+ List.iter
+ (fun t -> bs b "\n.sp\n \\-"; self#man_of_text2 b t; bs b "\n")
+ tl;
+ bs b "\n"
+ | Odoc_info.Newline ->
+ bs b "\n.sp\n"
+ | Odoc_info.Block t ->
+ bs b "\n.sp\n";
+ self#man_of_text2 b t;
+ bs b "\n.sp\n"
+ | Odoc_info.Title (n, l_opt, t) ->
+ self#man_of_text2 b [Odoc_info.Code (Odoc_info.string_of_text t)]
+ | Odoc_info.Latex _ ->
+ (* don't care about LaTeX stuff in HTML. *)
+ ()
+ | Odoc_info.Link (s, t) ->
+ self#man_of_text2 b t
+ | Odoc_info.Ref (name, _, _) ->
+ self#man_of_text_element b
+ (Odoc_info.Code (Odoc_info.use_hidden_modules name))
+ | Odoc_info.Superscript t ->
+ bs b "^{"; self#man_of_text2 b t
+ | Odoc_info.Subscript t ->
+ bs b "_{"; self#man_of_text2 b t
+ | Odoc_info.Module_list _ ->
+ ()
+ | Odoc_info.Index_list ->
+ ()
+ | Odoc_info.Custom (s,t) -> self#man_of_custom_text b s t
+ | Odoc_info.Target (target, code) -> self#man_of_Target b ~target ~code
+
+ method man_of_custom_text b s t = ()
+
+ method man_of_Target b ~target ~code =
+ if String.lowercase target = "man" then bs b code else ()
+
+ (** Print groff string to display code. *)
+ method man_of_code b s = self#man_of_text b [ Code s ]
+
+ (** Take a string and return the string where fully qualified idents
+ have been replaced by idents relative to the given module name.*)
+ method relative_idents m_name s =
+ let f str_t =
+ let match_s = Str.matched_string str_t in
+ Odoc_info.apply_if_equal
+ Odoc_info.use_hidden_modules
+ match_s
+ (Name.get_relative m_name match_s)
+ in
+ let s2 = Str.global_substitute
+ (Str.regexp "\\([A-Z]\\([a-zA-Z_'0-9]\\)*\\.\\)+\\([a-z][a-zA-Z_'0-9]*\\)")
+ f
+ s
+ in
+ s2
+
+ (** Print groff string to display a [Types.type_expr].*)
+ method man_of_type_expr b m_name t =
+ let s = String.concat "\n"
+ (Str.split (Str.regexp "\n") (Odoc_print.string_of_type_expr t))
+ in
+ let s2 = Str.global_replace (Str.regexp "\n") "\n.B " s in
+ bs b "\n.B ";
+ bs b (self#relative_idents m_name s2);
+ bs b "\n"
+
+ (** Print groff string to display a [Types.class_type].*)
+ method man_of_class_type_expr b m_name t =
+ let s = String.concat "\n"
+ (Str.split (Str.regexp "\n") (Odoc_print.string_of_class_type t))
+ in
+ let s2 = Str.global_replace (Str.regexp "\n") "\n.B " s in
+ bs b "\n.B ";
+ bs b (self#relative_idents m_name s2);
+ bs b "\n"
+
+ (** Print groff string to display a [Types.type_expr list].*)
+ method man_of_type_expr_list ?par b m_name sep l =
+ let s = Odoc_str.string_of_type_list ?par sep l in
+ let s2 = Str.global_replace (Str.regexp "\n") "\n.B " s in
+ bs b "\n.B ";
+ bs b (self#relative_idents m_name s2);
+ bs b "\n"
+
+ (** Print groff string to display the parameters of a type.*)
+ method man_of_type_expr_param_list b m_name t =
+ match t.ty_parameters with
+ [] -> ()
+ | l ->
+ let s = Odoc_str.string_of_type_param_list t in
+ let s2 = Str.global_replace (Str.regexp "\n") "\n.B " s in
+ bs b "\n.B ";
+ bs b (self#relative_idents m_name s2);
+ bs b "\n"
+
+ (** Print groff string to display a [Types.module_type]. *)
+ method man_of_module_type b m_name t =
+ let s = String.concat "\n"
+ (Str.split (Str.regexp "\n") (Odoc_print.string_of_module_type t))
+ in
+ let s2 = Str.global_replace (Str.regexp "\n") "\n.B " s in
+ bs b "\n.B ";
+ bs b (self#relative_idents m_name s2);
+ bs b "\n"
+
+ (** Print groff string code for a value. *)
+ method man_of_value b v =
+ Odoc_info.reset_type_names () ;
+ bs b "\n.I val ";
+ bs b (Name.simple v.val_name);
+ bs b " \n: ";
+ self#man_of_type_expr b (Name.father v.val_name) v.val_type;
+ bs b ".sp\n";
+ self#man_of_info b v.val_info;
+ bs b "\n.sp\n"
+
+ (** Print groff string code for an exception. *)
+ method man_of_exception b e =
+ Odoc_info.reset_type_names () ;
+ bs b "\n.I exception ";
+ bs b (Name.simple e.ex_name);
+ bs b " \n";
+ (
+ match e.ex_args with
+ [] -> ()
+ | _ ->
+ bs b ".B of ";
+ self#man_of_type_expr_list
+ ~par: false
+ b (Name.father e.ex_name) " * " e.ex_args
+ );
+ (
+ match e.ex_alias with
+ None -> ()
+ | Some ea ->
+ bs b " = ";
+ bs b
+ (
+ match ea.ea_ex with
+ None -> ea.ea_name
+ | Some e -> e.ex_name
+ )
+ );
+ bs b "\n.sp\n";
+ self#man_of_info b e.ex_info;
+ bs b "\n.sp\n"
+
+ (** Print groff string for a type. *)
+ method man_of_type b t =
+ Odoc_info.reset_type_names () ;
+ let father = Name.father t.ty_name in
+ bs b ".I type ";
+ self#man_of_type_expr_param_list b father t;
+ (
+ match t.ty_parameters with
+ [] -> ()
+ | _ -> bs b ".I "
+ );
+ bs b (Name.simple t.ty_name);
+ bs b " \n";
+ let priv = t.ty_private = Asttypes.Private in
+ (
+ match t.ty_manifest with
+ None -> ()
+ | Some typ ->
+ bs b "= ";
+ if priv then bs b "private ";
+ self#man_of_type_expr b father typ
+ );
+ (
+ match t.ty_kind with
+ Type_abstract -> ()
+ | Type_variant l ->
+ bs b "=";
+ if priv then bs b " private";
+ bs b "\n ";
+ List.iter
+ (fun constr ->
+ bs b ("| "^constr.vc_name);
+ (
+ match constr.vc_args, constr.vc_text with
+ [], None -> bs b "\n "
+ | [], (Some t) ->
+ bs b " (* ";
+ self#man_of_text b t;
+ bs b " *)\n "
+ | l, None ->
+ bs b "\n.B of ";
+ self#man_of_type_expr_list ~par: false b father " * " l;
+ bs b " "
+ | l, (Some t) ->
+ bs b "\n.B of ";
+ self#man_of_type_expr_list ~par: false b father " * " l;
+ bs b ".I \" \"\n";
+ bs b "(* ";
+ self#man_of_text b t;
+ bs b " *)\n "
+ )
+ )
+ l
+ | Type_record l ->
+ bs b "= ";
+ if priv then bs b "private ";
+ bs b "{";
+ List.iter
+ (fun r ->
+ bs b (if r.rf_mutable then "\n\n.B mutable \n" else "\n ");
+ bs b (r.rf_name^" : ");
+ self#man_of_type_expr b father r.rf_type;
+ bs b ";";
+ (
+ match r.rf_text with
+ None -> ()
+ | Some t ->
+ bs b " (* ";
+ self#man_of_text b t;
+ bs b " *) "
+ );
+ )
+ l;
+ bs b "\n }\n"
+ );
+ bs b "\n.sp\n";
+ self#man_of_info b t.ty_info;
+ bs b "\n.sp\n"
+
+ (** Print groff string for a class attribute. *)
+ method man_of_attribute b a =
+ bs b ".I val ";
+ if a.att_virtual then bs b ("virtual ");
+ if a.att_mutable then bs b (Odoc_messages.mutab^" ");
+ bs b ((Name.simple a.att_value.val_name)^" : ");
+ self#man_of_type_expr b (Name.father a.att_value.val_name) a.att_value.val_type;
+ bs b "\n.sp\n";
+ self#man_of_info b a.att_value.val_info;
+ bs b "\n.sp\n"
+
+ (** Print groff string for a class method. *)
+ method man_of_method b m =
+ bs b ".I method ";
+ if m.met_private then bs b "private ";
+ if m.met_virtual then bs b "virtual ";
+ bs b ((Name.simple m.met_value.val_name)^" : ");
+ self#man_of_type_expr b
+ (Name.father m.met_value.val_name) m.met_value.val_type;
+ bs b "\n.sp\n";
+ self#man_of_info b m.met_value.val_info;
+ bs b "\n.sp\n"
+
+ (** Groff for a list of parameters. *)
+ method man_of_parameter_list b m_name l =
+ match l with
+ [] -> ()
+ | _ ->
+ bs b "\n.B ";
+ bs b Odoc_messages.parameters;
+ bs b ": \n";
+ List.iter
+ (fun p ->
+ bs b ".sp\n";
+ bs b "\"";
+ bs b (Parameter.complete_name p);
+ bs b "\"\n";
+ self#man_of_type_expr b m_name (Parameter.typ p);
+ bs b "\n";
+ self#man_of_parameter_description b p;
+ bs b "\n"
+ )
+ l;
+ bs b "\n"
+
+ (** Groff for the description of a function parameter. *)
+ method man_of_parameter_description b p =
+ match Parameter.names p with
+ [] -> ()
+ | name :: [] ->
+ (
+ (* Only one name, no need for label for the description. *)
+ match Parameter.desc_by_name p name with
+ None -> ()
+ | Some t -> bs b "\n "; self#man_of_text b t
+ )
+ | l ->
+ (* A list of names, we display those with a description. *)
+ List.iter
+ (fun n ->
+ match Parameter.desc_by_name p n with
+ None -> ()
+ | Some t ->
+ self#man_of_code b (n^" : ");
+ self#man_of_text b t
+ )
+ l
+
+ (** Print groff string for a list of module parameters. *)
+ method man_of_module_parameter_list b m_name l =
+ match l with
+ [] -> ()
+ | _ ->
+ bs b ".B \"";
+ bs b Odoc_messages.parameters;
+ bs b ":\"\n";
+ List.iter
+ (fun (p, desc_opt) ->
+ bs b ".sp\n";
+ bs b ("\""^p.mp_name^"\"\n");
+ self#man_of_module_type b m_name p.mp_type;
+ bs b "\n";
+ (
+ match desc_opt with
+ None -> ()
+ | Some t -> self#man_of_text b t
+ );
+ bs b "\n"
+ )
+ l;
+ bs b "\n\n"
+
+ (** Print groff string for a class. *)
+ method man_of_class b c =
+ Odoc_info.reset_type_names () ;
+ let father = Name.father c.cl_name in
+ bs b ".I class ";
+ if c.cl_virtual then bs b "virtual ";
+ (
+ match c.cl_type_parameters with
+ [] -> ()
+ | l ->
+ bs b (Odoc_str.string_of_class_type_param_list l);
+ bs b " "
+ );
+ bs b (Name.simple c.cl_name);
+ bs b " : " ;
+ self#man_of_class_type_expr b father c.cl_type;
+ bs b "\n.sp\n";
+ self#man_of_info b c.cl_info;
+ bs b "\n.sp\n"
+
+ (** Print groff string for a class type. *)
+ method man_of_class_type b ct =
+ Odoc_info.reset_type_names () ;
+ bs b ".I class type ";
+ if ct.clt_virtual then bs b "virtual " ;
+ (
+ match ct.clt_type_parameters with
+ [] -> ()
+ | l ->
+ bs b (Odoc_str.string_of_class_type_param_list l);
+ bs b " "
+ );
+ bs b (Name.simple ct.clt_name);
+ bs b " = " ;
+ self#man_of_class_type_expr b (Name.father ct.clt_name) ct.clt_type;
+ bs b "\n.sp\n";
+ self#man_of_info b ct.clt_info;
+ bs b "\n.sp\n"
+
+ (** Print groff string for a module. *)
+ method man_of_module b m =
+ bs b ".I module ";
+ bs b (Name.simple m.m_name);
+ bs b " : ";
+ self#man_of_module_type b (Name.father m.m_name) m.m_type;
+ bs b "\n.sp\n";
+ self#man_of_info b m.m_info;
+ bs b "\n.sp\n"
+
+ (** Print groff string for a module type. *)
+ method man_of_modtype b mt =
+ bs b ".I module type ";
+ bs b (Name.simple mt.mt_name);
+ bs b " = ";
+ (match mt.mt_type with
+ None -> ()
+ | Some t ->
+ self#man_of_module_type b (Name.father mt.mt_name) t
+ );
+ bs b "\n.sp\n";
+ self#man_of_info b mt.mt_info;
+ bs b "\n.sp\n"
+
+ (** Print groff string for a module comment.*)
+ method man_of_module_comment b text =
+ bs b "\n.PP\n";
+ self#man_of_text b [Code ("=== "^(Odoc_misc.string_of_text text)^" ===")];
+ bs b "\n.PP\n"
+
+ (** Print groff string for a class comment.*)
+ method man_of_class_comment b text =
+ bs b "\n.PP\n";
+ self#man_of_text b [Code ("=== "^(Odoc_misc.string_of_text text)^" ===")];
+ bs b "\n.PP\n"
+
+ (** Print groff string for an included module. *)
+ method man_of_included_module b m_name im =
+ bs b ".I include ";
+ (
+ match im.im_module with
+ None -> bs b im.im_name
+ | Some mmt ->
+ let name =
+ match mmt with
+ Mod m -> m.m_name
+ | Modtype mt -> mt.mt_name
+ in
+ bs b (self#relative_idents m_name name)
+ );
+ bs b "\n.sp\n";
+ self#man_of_info b im.im_info;
+ bs b "\n.sp\n"
+
+ (** Generate the man page for the given class.*)
+ method generate_for_class cl =
+ Odoc_info.reset_type_names () ;
+ let date = Unix.time () in
+ let file = self#file_name cl.cl_name in
+ try
+ let chanout = self#open_out file in
+ let b = new_buf () in
+ bs b (".TH \""^cl.cl_name^"\" ");
+ bs b !man_section ;
+ bs b (" "^(Odoc_misc.string_of_date ~hour: false date)^" ");
+ bs b "OCamldoc ";
+ bs b ("\""^(match !Global.title with Some t -> t | None -> "")^"\"\n");
+
+ let abstract =
+ match cl.cl_info with
+ None | Some { i_desc = None } -> "no description"
+ | Some { i_desc = Some t } ->
+ let s = Odoc_info.string_of_text (Odoc_info.first_sentence_of_text t) in
+ self#remove_newlines s
+ in
+
+ bs b ".SH NAME\n";
+ bs b (cl.cl_name^" \\- "^abstract^"\n");
+ bs b (".SH "^Odoc_messages.clas^"\n");
+ bs b (Odoc_messages.clas^" "^cl.cl_name^"\n");
+ bs b (".SH "^Odoc_messages.documentation^"\n");
+ bs b ".sp\n";
+ self#man_of_class b cl;
+
+ (* parameters *)
+ self#man_of_parameter_list b "" cl.cl_parameters;
+ (* a large blank *)
+ bs b "\n.sp\n.sp\n";
+
+(*
+ (* class inheritance *)
+ self#generate_class_inheritance_info chanout cl;
+*)
+ (* the various elements *)
+ List.iter
+ (fun element ->
+ match element with
+ Class_attribute a ->
+ self#man_of_attribute b a
+ | Class_method m ->
+ self#man_of_method b m
+ | Class_comment t ->
+ self#man_of_class_comment b t
+ )
+ (Class.class_elements cl);
+
+ Buffer.output_buffer chanout b;
+ close_out chanout
+ with
+ Sys_error s ->
+ incr Odoc_info.errors ;
+ prerr_endline s
+
+ (** Generate the man page for the given class type.*)
+ method generate_for_class_type ct =
+ Odoc_info.reset_type_names () ;
+ let date = Unix.time () in
+ let file = self#file_name ct.clt_name in
+ try
+ let chanout = self#open_out file in
+ let b = new_buf () in
+ bs b (".TH \""^ct.clt_name^"\" ");
+ bs b !man_section ;
+ bs b (" "^(Odoc_misc.string_of_date ~hour: false date)^" ");
+ bs b "OCamldoc ";
+ bs b ("\""^(match !Global.title with Some t -> t | None -> "")^"\"\n");
+
+ let abstract =
+ match ct.clt_info with
+ None | Some { i_desc = None } -> "no description"
+ | Some { i_desc = Some t } ->
+ let s = Odoc_info.string_of_text (Odoc_info.first_sentence_of_text t) in
+ self#remove_newlines s
+ in
+
+ bs b ".SH NAME\n";
+ bs b (ct.clt_name^" \\- "^abstract^"\n");
+ bs b (".SH "^Odoc_messages.class_type^"\n");
+ bs b (Odoc_messages.class_type^" "^ct.clt_name^"\n");
+ bs b (".SH "^Odoc_messages.documentation^"\n");
+ bs b ".sp\n";
+
+ self#man_of_class_type b ct;
+
+ (* a large blank *)
+ bs b "\n.sp\n.sp\n";
+(*
+ (* class inheritance *)
+ self#generate_class_inheritance_info chanout cl;
+*)
+ (* the various elements *)
+ List.iter
+ (fun element ->
+ match element with
+ Class_attribute a ->
+ self#man_of_attribute b a
+ | Class_method m ->
+ self#man_of_method b m
+ | Class_comment t ->
+ self#man_of_class_comment b t
+ )
+ (Class.class_type_elements ct);
+
+ Buffer.output_buffer chanout b;
+ close_out chanout
+ with
+ Sys_error s ->
+ incr Odoc_info.errors ;
+ prerr_endline s
+
+ (** Generate the man file for the given module type.
+ @raise Failure if an error occurs.*)
+ method generate_for_module_type mt =
+ let date = Unix.time () in
+ let file = self#file_name mt.mt_name in
+ try
+ let chanout = self#open_out file in
+ let b = new_buf () in
+ bs b (".TH \""^mt.mt_name^"\" ");
+ bs b !man_section ;
+ bs b (" "^(Odoc_misc.string_of_date ~hour: false date)^" ");
+ bs b "OCamldoc ";
+ bs b ("\""^(match !Global.title with Some t -> t | None -> "")^"\"\n");
+
+ let abstract =
+ match mt.mt_info with
+ None | Some { i_desc = None } -> "no description"
+ | Some { i_desc = Some t } ->
+ let s = Odoc_info.string_of_text (Odoc_info.first_sentence_of_text t) in
+ self#remove_newlines s
+ in
+ bs b ".SH NAME\n";
+ bs b (mt.mt_name^" \\- "^abstract^"\n");
+ bs b (".SH "^Odoc_messages.module_type^"\n");
+ bs b (Odoc_messages.module_type^" "^mt.mt_name^"\n");
+ bs b (".SH "^Odoc_messages.documentation^"\n");
+ bs b ".sp\n";
+ bs b (Odoc_messages.module_type^"\n");
+ bs b (".BI \""^(Name.simple mt.mt_name)^"\"\n");
+ bs b " = ";
+ (
+ match mt.mt_type with
+ None -> ()
+ | Some t ->
+ self#man_of_module_type b (Name.father mt.mt_name) t
+ );
+ bs b "\n.sp\n";
+ self#man_of_info b mt.mt_info;
+ bs b "\n.sp\n";
+
+ (* parameters for functors *)
+ self#man_of_module_parameter_list b "" (Module.module_type_parameters mt);
+ (* a large blank *)
+ bs b "\n.sp\n.sp\n";
+
+ (* module elements *)
+ List.iter
+ (fun ele ->
+ match ele with
+ Element_module m ->
+ self#man_of_module b m
+ | Element_module_type mt ->
+ self#man_of_modtype b mt
+ | Element_included_module im ->
+ self#man_of_included_module b mt.mt_name im
+ | Element_class c ->
+ self#man_of_class b c
+ | Element_class_type ct ->
+ self#man_of_class_type b ct
+ | Element_value v ->
+ self#man_of_value b v
+ | Element_exception e ->
+ self#man_of_exception b e
+ | Element_type t ->
+ self#man_of_type b t
+ | Element_module_comment text ->
+ self#man_of_module_comment b text
+ )
+ (Module.module_type_elements mt);
+
+ Buffer.output_buffer chanout b;
+ close_out chanout
+
+ with
+ Sys_error s ->
+ incr Odoc_info.errors ;
+ prerr_endline s
+
+ (** Generate the man file for the given module.
+ @raise Failure if an error occurs.*)
+ method generate_for_module m =
+ let date = Unix.time () in
+ let file = self#file_name m.m_name in
+ try
+ let chanout = self#open_out file in
+ let b = new_buf () in
+ bs b (".TH \""^m.m_name^"\" ");
+ bs b !man_section ;
+ bs b (" "^(Odoc_misc.string_of_date ~hour: false date)^" ");
+ bs b "OCamldoc ";
+ bs b ("\""^(match !Global.title with Some t -> t | None -> "")^"\"\n");
+
+ let abstract =
+ match m.m_info with
+ None | Some { i_desc = None } -> "no description"
+ | Some { i_desc = Some t } ->
+ let s = Odoc_info.string_of_text (Odoc_info.first_sentence_of_text t) in
+ self#remove_newlines s
+ in
+
+ bs b ".SH NAME\n";
+ bs b (m.m_name^" \\- "^abstract^"\n");
+ bs b (".SH "^Odoc_messages.modul^"\n");
+ bs b (Odoc_messages.modul^" "^m.m_name^"\n");
+ bs b (".SH "^Odoc_messages.documentation^"\n");
+ bs b ".sp\n";
+ bs b (Odoc_messages.modul^"\n");
+ bs b (".BI \""^(Name.simple m.m_name)^"\"\n");
+ bs b " : ";
+ self#man_of_module_type b (Name.father m.m_name) m.m_type;
+ bs b "\n.sp\n";
+ self#man_of_info b m.m_info;
+ bs b "\n.sp\n";
+
+ (* parameters for functors *)
+ self#man_of_module_parameter_list b "" (Module.module_parameters m);
+ (* a large blank *)
+ bs b "\n.sp\n.sp\n";
+
+ (* module elements *)
+ List.iter
+ (fun ele ->
+ match ele with
+ Element_module m ->
+ self#man_of_module b m
+ | Element_module_type mt ->
+ self#man_of_modtype b mt
+ | Element_included_module im ->
+ self#man_of_included_module b m.m_name im
+ | Element_class c ->
+ self#man_of_class b c
+ | Element_class_type ct ->
+ self#man_of_class_type b ct
+ | Element_value v ->
+ self#man_of_value b v
+ | Element_exception e ->
+ self#man_of_exception b e
+ | Element_type t ->
+ self#man_of_type b t
+ | Element_module_comment text ->
+ self#man_of_module_comment b text
+ )
+ (Module.module_elements m);
+
+ Buffer.output_buffer chanout b;
+ close_out chanout
+
+ with
+ Sys_error s ->
+ raise (Failure s)
+
+ (** Create the groups of elements to generate pages for. *)
+ method create_groups module_list =
+ let name res_ele =
+ match res_ele with
+ Res_module m -> m.m_name
+ | Res_module_type mt -> mt.mt_name
+ | Res_class c -> c.cl_name
+ | Res_class_type ct -> ct.clt_name
+ | Res_value v -> Name.simple v.val_name
+ | Res_type t -> Name.simple t.ty_name
+ | Res_exception e -> Name.simple e.ex_name
+ | Res_attribute a -> Name.simple a.att_value.val_name
+ | Res_method m -> Name.simple m.met_value.val_name
+ | Res_section _ -> assert false
+ in
+ let all_items_pre = Odoc_info.Search.search_by_name module_list (Str.regexp ".*") in
+ let all_items = List.filter
+ (fun r -> match r with Res_section _ -> false | _ -> true)
+ all_items_pre
+ in
+ let sorted_items = List.sort (fun e1 -> fun e2 -> compare (name e1) (name e2)) all_items in
+ let rec f acc1 acc2 l =
+ match l with
+ [] -> acc2 :: acc1
+ | h :: q ->
+ match acc2 with
+ [] -> f acc1 [h] q
+ | h2 :: q2 ->
+ if (name h) = (name h2) then
+ if List.mem h acc2 then
+ f acc1 acc2 q
+ else
+ f acc1 (acc2 @ [h]) q
+ else
+ f (acc2 :: acc1) [h] q
+ in
+ f [] [] sorted_items
+
+ (** Generate a man page for a group of elements with the same name.
+ A group must not be empty.*)
+ method generate_for_group l =
+ let name =
+ Name.simple
+ (
+ match List.hd l with
+ Res_module m -> m.m_name
+ | Res_module_type mt -> mt.mt_name
+ | Res_class c -> c.cl_name
+ | Res_class_type ct -> ct.clt_name
+ | Res_value v -> v.val_name
+ | Res_type t -> t.ty_name
+ | Res_exception e -> e.ex_name
+ | Res_attribute a -> a.att_value.val_name
+ | Res_method m -> m.met_value.val_name
+ | Res_section (s,_) -> s
+ )
+ in
+ let date = Unix.time () in
+ let file = self#file_name name in
+ try
+ let chanout = self#open_out file in
+ let b = new_buf () in
+ bs b (".TH \""^name^"\" ");
+ bs b !man_section ;
+ bs b (" "^(Odoc_misc.string_of_date ~hour: false date)^" ");
+ bs b "OCamldoc ";
+ bs b ("\""^(match !Global.title with Some t -> t | None -> "")^"\"\n");
+ bs b ".SH NAME\n";
+ bs b (name^" \\- all "^name^" elements\n\n");
+
+ let f ele =
+ match ele with
+ Res_value v ->
+ bs b ("\n.SH "^Odoc_messages.modul^" "^(Name.father v.val_name)^"\n");
+ self#man_of_value b v
+ | Res_type t ->
+ bs b ("\n.SH "^Odoc_messages.modul^" "^(Name.father t.ty_name)^"\n");
+ self#man_of_type b t
+ | Res_exception e ->
+ bs b ("\n.SH "^Odoc_messages.modul^" "^(Name.father e.ex_name)^"\n");
+ self#man_of_exception b e
+ | Res_attribute a ->
+ bs b ("\n.SH "^Odoc_messages.clas^" "^(Name.father a.att_value.val_name)^"\n");
+ self#man_of_attribute b a
+ | Res_method m ->
+ bs b ("\n.SH "^Odoc_messages.clas^" "^(Name.father m.met_value.val_name)^"\n");
+ self#man_of_method b m
+ | Res_class c ->
+ bs b ("\n.SH "^Odoc_messages.modul^" "^(Name.father c.cl_name)^"\n");
+ self#man_of_class b c
+ | Res_class_type ct ->
+ bs b ("\n.SH "^Odoc_messages.modul^" "^(Name.father ct.clt_name)^"\n");
+ self#man_of_class_type b ct
+ | _ ->
+ (* normalement on ne peut pas avoir de module ici. *)
+ ()
+ in
+ List.iter f l;
+ Buffer.output_buffer chanout b;
+ close_out chanout
+ with
+ Sys_error s ->
+ incr Odoc_info.errors ;
+ prerr_endline s
+
+ (** Generate all the man pages from a module list. *)
+ method generate module_list =
+ let sorted_module_list = Sort.list (fun m1 -> fun m2 -> m1.m_name < m2.m_name) module_list in
+ let groups = self#create_groups sorted_module_list in
+ let f group =
+ match group with
+ [] ->
+ ()
+ | [Res_module m] -> self#generate_for_module m
+ | [Res_module_type mt] -> self#generate_for_module_type mt
+ | [Res_class cl] -> self#generate_for_class cl
+ | [Res_class_type ct] -> self#generate_for_class_type ct
+ | l ->
+ if !man_mini then
+ ()
+ else
+ self#generate_for_group l
+ in
+ List.iter f groups
+ end
+end
+
+module type Man_generator = module type of Generator
diff --git a/ocaml-binary-annot/ocamldoc/odoc_merge.ml b/ocaml-binary-annot/ocamldoc/odoc_merge.ml
new file mode 100644
index 0000000000..8d062f9e02
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_merge.ml
@@ -0,0 +1,988 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Merge of information from [.ml] and [.mli] for a module.*)
+
+open Odoc_types
+
+module Name = Odoc_name
+open Odoc_parameter
+open Odoc_value
+open Odoc_type
+open Odoc_exception
+open Odoc_class
+open Odoc_module
+
+let merge_before_tags l =
+ let rec iter acc = function
+ [] -> List.rev acc
+ | (v, text) :: q ->
+ let (l1, l2) = List.partition
+ (fun (v2,_) -> v = v2) q
+ in
+ let acc =
+ let text =
+ List.fold_left
+ (fun acc t -> acc @ [Raw " "] @ t)
+ text (List.map snd l1)
+ in
+ (v, text) :: acc
+ in
+ iter acc l2
+ in
+ iter [] l
+;;
+
+(** Merge two Odoctypes.info struture, completing the information of
+ the first one with the information in the second one.
+ The merge treatment depends on a given merge_option list.
+ @return the new info structure.*)
+let merge_info merge_options (m1 : info) (m2 : info) =
+ let new_desc_opt =
+ match m1.i_desc, m2.i_desc with
+ None, None -> None
+ | None, Some d
+ | Some d, None -> Some d
+ | Some d1, Some d2 ->
+ if List.mem Merge_description merge_options then
+ Some (d1 @ (Newline :: d2))
+ else
+ Some d1
+ in
+ let new_authors =
+ match m1.i_authors, m2.i_authors with
+ [], [] -> []
+ | l, []
+ | [], l -> l
+ | l1, l2 ->
+ if List.mem Merge_author merge_options then
+ l1 @ l2
+ else
+ l1
+ in
+ let new_version =
+ match m1.i_version , m2.i_version with
+ None, None -> None
+ | Some v, None
+ | None, Some v -> Some v
+ | Some v1, Some v2 ->
+ if List.mem Merge_version merge_options then
+ Some (v1^" "^v2)
+ else
+ Some v1
+ in
+ let new_sees =
+ match m1.i_sees, m2.i_sees with
+ [], [] -> []
+ | l, []
+ | [], l -> l
+ | l1, l2 ->
+ if List.mem Merge_see merge_options then
+ l1 @ l2
+ else
+ l1
+ in
+ let new_since =
+ match m1.i_since, m2.i_since with
+ None, None -> None
+ | Some v, None
+ | None, Some v -> Some v
+ | Some v1, Some v2 ->
+ if List.mem Merge_since merge_options then
+ Some (v1^" "^v2)
+ else
+ Some v1
+ in
+ let new_before = merge_before_tags (m1.i_before @ m2.i_before) in
+ let new_dep =
+ match m1.i_deprecated, m2.i_deprecated with
+ None, None -> None
+ | None, Some t
+ | Some t, None -> Some t
+ | Some t1, Some t2 ->
+ if List.mem Merge_deprecated merge_options then
+ Some (t1 @ (Newline :: t2))
+ else
+ Some t1
+ in
+ let new_params =
+ match m1.i_params, m2.i_params with
+ [], [] -> []
+ | l, []
+ | [], l -> l
+ | l1, l2 ->
+ if List.mem Merge_param merge_options then
+ (
+ let l_in_m1_and_m2, l_in_m2_only = List.partition
+ (fun (param2, _) -> List.mem_assoc param2 l1)
+ l2
+ in
+ let rec iter = function
+ [] -> []
+ | (param2, desc2) :: q ->
+ let desc1 = List.assoc param2 l1 in
+ (param2, desc1 @ (Newline :: desc2)) :: (iter q)
+ in
+ let l1_completed = iter l_in_m1_and_m2 in
+ l1_completed @ l_in_m2_only
+ )
+ else
+ l1
+ in
+ let new_raised_exceptions =
+ match m1.i_raised_exceptions, m2.i_raised_exceptions with
+ [], [] -> []
+ | l, []
+ | [], l -> l
+ | l1, l2 ->
+ if List.mem Merge_raised_exception merge_options then
+ (
+ let l_in_m1_and_m2, l_in_m2_only = List.partition
+ (fun (exc2, _) -> List.mem_assoc exc2 l1)
+ l2
+ in
+ let rec iter = function
+ [] -> []
+ | (exc2, desc2) :: q ->
+ let desc1 = List.assoc exc2 l1 in
+ (exc2, desc1 @ (Newline :: desc2)) :: (iter q)
+ in
+ let l1_completed = iter l_in_m1_and_m2 in
+ l1_completed @ l_in_m2_only
+ )
+ else
+ l1
+ in
+ let new_rv =
+ match m1.i_return_value, m2.i_return_value with
+ None, None -> None
+ | None, Some t
+ | Some t, None -> Some t
+ | Some t1, Some t2 ->
+ if List.mem Merge_return_value merge_options then
+ Some (t1 @ (Newline :: t2))
+ else
+ Some t1
+ in
+ let new_custom =
+ match m1.i_custom, m2.i_custom with
+ [], [] -> []
+ | [], l
+ | l, [] -> l
+ | l1, l2 ->
+ if List.mem Merge_custom merge_options then
+ l1 @ l2
+ else
+ l1
+ in
+ {
+ Odoc_types.i_desc = new_desc_opt ;
+ Odoc_types.i_authors = new_authors ;
+ Odoc_types.i_version = new_version ;
+ Odoc_types.i_sees = new_sees ;
+ Odoc_types.i_since = new_since ;
+ Odoc_types.i_before = new_before ;
+ Odoc_types.i_deprecated = new_dep ;
+ Odoc_types.i_params = new_params ;
+ Odoc_types.i_raised_exceptions = new_raised_exceptions ;
+ Odoc_types.i_return_value = new_rv ;
+ Odoc_types.i_custom = new_custom ;
+ }
+
+(** Merge of two optional info structures. *)
+let merge_info_opt merge_options mli_opt ml_opt =
+ match mli_opt, ml_opt with
+ None, Some i -> Some i
+ | Some i, None -> Some i
+ | None, None -> None
+ | Some i1, Some i2 -> Some (merge_info merge_options i1 i2)
+
+(** merge of two t_type, one for a .mli, another for the .ml.
+ The .mli type is completed with the information in the .ml type. *)
+let merge_types merge_options mli ml =
+ mli.ty_info <- merge_info_opt merge_options mli.ty_info ml.ty_info;
+ mli.ty_loc <- { mli.ty_loc with loc_impl = ml.ty_loc.loc_impl } ;
+ mli.ty_code <- (match mli.ty_code with None -> ml.ty_code | _ -> mli.ty_code) ;
+
+ match mli.ty_kind, ml.ty_kind with
+ Type_abstract, _ ->
+ ()
+
+ | Type_variant l1, Type_variant l2 ->
+ let f cons =
+ try
+ let cons2 = List.find
+ (fun c2 -> c2.vc_name = cons.vc_name)
+ l2
+ in
+ let new_desc =
+ match cons.vc_text, cons2.vc_text with
+ None, None -> None
+ | Some d, None
+ | None, Some d -> Some d
+ | Some d1, Some d2 ->
+ if List.mem Merge_description merge_options then
+ Some (d1 @ d2)
+ else
+ Some d1
+ in
+ cons.vc_text <- new_desc
+ with
+ Not_found ->
+ if !Odoc_global.inverse_merge_ml_mli then
+ ()
+ else
+ raise (Failure (Odoc_messages.different_types mli.ty_name))
+ in
+ List.iter f l1
+
+ | Type_record l1, Type_record l2 ->
+ let f record =
+ try
+ let record2= List.find
+ (fun r -> r.rf_name = record.rf_name)
+ l2
+ in
+ let new_desc =
+ match record.rf_text, record2.rf_text with
+ None, None -> None
+ | Some d, None
+ | None, Some d -> Some d
+ | Some d1, Some d2 ->
+ if List.mem Merge_description merge_options then
+ Some (d1 @ d2)
+ else
+ Some d1
+ in
+ record.rf_text <- new_desc
+ with
+ Not_found ->
+ if !Odoc_global.inverse_merge_ml_mli then
+ ()
+ else
+ raise (Failure (Odoc_messages.different_types mli.ty_name))
+ in
+ List.iter f l1
+
+ | _ ->
+ if !Odoc_global.inverse_merge_ml_mli then
+ ()
+ else
+ raise (Failure (Odoc_messages.different_types mli.ty_name))
+
+(** Merge of two param_info, one from a .mli, one from a .ml.
+ The text fields are not handled but will be recreated from the
+ i_params field of the info structure.
+ Here, if a parameter in the .mli has no name, we take the one
+ from the .ml. When two parameters have two different forms,
+ we take the one from the .mli. *)
+let rec merge_param_info pi_mli pi_ml =
+ match (pi_mli, pi_ml) with
+ (Simple_name sn_mli, Simple_name sn_ml) ->
+ if sn_mli.sn_name = "" then
+ Simple_name { sn_mli with sn_name = sn_ml.sn_name }
+ else
+ pi_mli
+ | (Simple_name _, Tuple _) ->
+ pi_mli
+ | (Tuple (_, t_mli), Simple_name sn_ml) ->
+ (* if we're here, then the tuple in the .mli has no parameter names ;
+ then we take the name of the parameter of the .ml and the type of the .mli. *)
+ Simple_name { sn_ml with sn_type = t_mli }
+
+ | (Tuple (l_mli, t_mli), Tuple (l_ml, _)) ->
+ (* if the two tuples have different lengths
+ (which should not occurs), we return the pi_mli,
+ without further investigation.*)
+ if (List.length l_mli) <> (List.length l_ml) then
+ pi_mli
+ else
+ let new_l = List.map2 merge_param_info l_mli l_ml in
+ Tuple (new_l, t_mli)
+
+(** Merge of the parameters of two functions/methods/classes, one for a .mli, another for a .ml.
+ The prameters in the .mli are completed by the name in the .ml.*)
+let rec merge_parameters param_mli param_ml =
+ match (param_mli, param_ml) with
+ ([], []) -> []
+ | (l, []) | ([], l) -> l
+ | ((pi_mli :: li), (pi_ml :: l)) ->
+ (merge_param_info pi_mli pi_ml) :: merge_parameters li l
+
+(** Merge of two t_class, one for a .mli, another for the .ml.
+ The .mli class is completed with the information in the .ml class. *)
+let merge_classes merge_options mli ml =
+ mli.cl_info <- merge_info_opt merge_options mli.cl_info ml.cl_info;
+ mli.cl_loc <- { mli.cl_loc with loc_impl = ml.cl_loc.loc_impl } ;
+ mli.cl_parameters <- merge_parameters mli.cl_parameters ml.cl_parameters;
+
+ (* we must reassociate comments in @param to the the corresponding
+ parameters because the associated comment of a parameter may have been changed y the merge.*)
+ Odoc_class.class_update_parameters_text mli;
+
+ (* merge values *)
+ List.iter
+ (fun a ->
+ try
+ let _ = List.find
+ (fun ele ->
+ match ele with
+ Class_attribute a2 ->
+ if a2.att_value.val_name = a.att_value.val_name then
+ (
+ a.att_value.val_info <- merge_info_opt merge_options
+ a.att_value.val_info a2.att_value.val_info;
+ a.att_value.val_loc <- { a.att_value.val_loc with loc_impl = a2.att_value.val_loc.loc_impl } ;
+ if !Odoc_global.keep_code then
+ a.att_value.val_code <- a2.att_value.val_code;
+ true
+ )
+ else
+ false
+ | _ ->
+ false
+ )
+ (* we look for the last attribute with this name defined in the implementation *)
+ (List.rev (Odoc_class.class_elements ml))
+ in
+ ()
+ with
+ Not_found ->
+ ()
+ )
+ (Odoc_class.class_attributes mli);
+ (* merge methods *)
+ List.iter
+ (fun m ->
+ try
+ let _ = List.find
+ (fun ele ->
+ match ele with
+ Class_method m2 ->
+ if m2.met_value.val_name = m.met_value.val_name then
+ (
+ m.met_value.val_info <- merge_info_opt
+ merge_options m.met_value.val_info m2.met_value.val_info;
+ m.met_value.val_loc <- { m.met_value.val_loc with loc_impl = m2.met_value.val_loc.loc_impl } ;
+ (* merge the parameter names *)
+ m.met_value.val_parameters <- (merge_parameters
+ m.met_value.val_parameters
+ m2.met_value.val_parameters) ;
+ (* we must reassociate comments in @param to the corresponding
+ parameters because the associated comment of a parameter may have been changed by the merge.*)
+ Odoc_value.update_value_parameters_text m.met_value;
+
+ if !Odoc_global.keep_code then
+ m.met_value.val_code <- m2.met_value.val_code;
+
+ true
+ )
+ else
+ false
+ | _ ->
+ false
+ )
+ (* we look for the last method with this name defined in the implementation *)
+ (List.rev (Odoc_class.class_elements ml))
+ in
+ ()
+ with
+ Not_found ->
+ ()
+ )
+ (Odoc_class.class_methods mli)
+
+(** merge of two t_class_type, one for a .mli, another for the .ml.
+ The .mli class is completed with the information in the .ml class. *)
+let merge_class_types merge_options mli ml =
+ mli.clt_info <- merge_info_opt merge_options mli.clt_info ml.clt_info;
+ mli.clt_loc <- { mli.clt_loc with loc_impl = ml.clt_loc.loc_impl } ;
+ (* merge values *)
+ List.iter
+ (fun a ->
+ try
+ let _ = List.find
+ (fun ele ->
+ match ele with
+ Class_attribute a2 ->
+ if a2.att_value.val_name = a.att_value.val_name then
+ (
+ a.att_value.val_info <- merge_info_opt merge_options
+ a.att_value.val_info a2.att_value.val_info;
+ a.att_value.val_loc <- { a.att_value.val_loc with loc_impl = a2.att_value.val_loc.loc_impl } ;
+ if !Odoc_global.keep_code then
+ a.att_value.val_code <- a2.att_value.val_code;
+
+ true
+ )
+ else
+ false
+ | _ ->
+ false
+ )
+ (* we look for the last attribute with this name defined in the implementation *)
+ (List.rev (Odoc_class.class_type_elements ml))
+ in
+ ()
+ with
+ Not_found ->
+ ()
+ )
+ (Odoc_class.class_type_attributes mli);
+ (* merge methods *)
+ List.iter
+ (fun m ->
+ try
+ let _ = List.find
+ (fun ele ->
+ match ele with
+ Class_method m2 ->
+ if m2.met_value.val_name = m.met_value.val_name then
+ (
+ m.met_value.val_info <- merge_info_opt
+ merge_options m.met_value.val_info m2.met_value.val_info;
+ m.met_value.val_loc <- { m.met_value.val_loc with loc_impl = m2.met_value.val_loc.loc_impl } ;
+ m.met_value.val_parameters <- (merge_parameters
+ m.met_value.val_parameters
+ m2.met_value.val_parameters) ;
+ (* we must reassociate comments in @param to the the corresponding
+ parameters because the associated comment of a parameter may have been changed y the merge.*)
+ Odoc_value.update_value_parameters_text m.met_value;
+
+ if !Odoc_global.keep_code then
+ m.met_value.val_code <- m2.met_value.val_code;
+
+ true
+ )
+ else
+ false
+ | _ ->
+ false
+ )
+ (* we look for the last method with this name defined in the implementation *)
+ (List.rev (Odoc_class.class_type_elements ml))
+ in
+ ()
+ with
+ Not_found ->
+ ()
+ )
+ (Odoc_class.class_type_methods mli)
+
+
+(** merge of two t_module_type, one for a .mli, another for the .ml.
+ The .mli module is completed with the information in the .ml module. *)
+let rec merge_module_types merge_options mli ml =
+ mli.mt_info <- merge_info_opt merge_options mli.mt_info ml.mt_info;
+ mli.mt_loc <- { mli.mt_loc with loc_impl = ml.mt_loc.loc_impl } ;
+ (* merge exceptions *)
+ List.iter
+ (fun ex ->
+ try
+ let _ = List.find
+ (fun ele ->
+ match ele with
+ Element_exception ex2 ->
+ if ex2.ex_name = ex.ex_name then
+ (
+ ex.ex_info <- merge_info_opt merge_options ex.ex_info ex2.ex_info;
+ ex.ex_loc <- { ex.ex_loc with loc_impl = ex2.ex_loc.loc_impl } ;
+ ex.ex_code <- (match ex.ex_code with None -> ex2.ex_code | _ -> ex.ex_code) ;
+ true
+ )
+ else
+ false
+ | _ ->
+ false
+ )
+ (* we look for the last exception with this name defined in the implementation *)
+ (List.rev (Odoc_module.module_type_elements ml))
+ in
+ ()
+ with
+ Not_found ->
+ ()
+ )
+ (Odoc_module.module_type_exceptions mli);
+ (* merge types *)
+ List.iter
+ (fun ty ->
+ try
+ let _ = List.find
+ (fun ele ->
+ match ele with
+ Element_type ty2 ->
+ if ty2.ty_name = ty.ty_name then
+ (
+ merge_types merge_options ty ty2;
+ true
+ )
+ else
+ false
+ | _ ->
+ false
+ )
+ (* we look for the last type with this name defined in the implementation *)
+ (List.rev (Odoc_module.module_type_elements ml))
+ in
+ ()
+ with
+ Not_found ->
+ ()
+ )
+ (Odoc_module.module_type_types mli);
+ (* merge submodules *)
+ List.iter
+ (fun m ->
+ try
+ let _ = List.find
+ (fun ele ->
+ match ele with
+ Element_module m2 ->
+ if m2.m_name = m.m_name then
+ (
+ ignore (merge_modules merge_options m m2);
+(*
+ m.m_info <- merge_info_opt merge_options m.m_info m2.m_info;
+ m.m_loc <- { m.m_loc with loc_impl = m2.m_loc.loc_impl } ;
+*)
+ true
+ )
+ else
+ false
+ | _ ->
+ false
+ )
+ (* we look for the last module with this name defined in the implementation *)
+ (List.rev (Odoc_module.module_type_elements ml))
+ in
+ ()
+ with
+ Not_found ->
+ ()
+ )
+ (Odoc_module.module_type_modules mli);
+
+ (* merge module types *)
+ List.iter
+ (fun m ->
+ try
+ let _ = List.find
+ (fun ele ->
+ match ele with
+ Element_module_type m2 ->
+ if m2.mt_name = m.mt_name then
+ (
+ merge_module_types merge_options m m2;
+ true
+ )
+ else
+ false
+ | _ ->
+ false
+ )
+ (* we look for the last module with this name defined in the implementation *)
+ (List.rev (Odoc_module.module_type_elements ml))
+ in
+ ()
+ with
+ Not_found ->
+ ()
+ )
+ (Odoc_module.module_type_module_types mli);
+
+ (* A VOIR : merge included modules ? *)
+
+ (* merge values *)
+ List.iter
+ (fun v ->
+ try
+ let _ = List.find
+ (fun ele ->
+ match ele with
+ Element_value v2 ->
+ if v2.val_name = v.val_name then
+ (
+ v.val_info <- merge_info_opt merge_options v.val_info v2.val_info ;
+ v.val_loc <- { v.val_loc with loc_impl = v2.val_loc.loc_impl } ;
+ (* in the .mli we don't know any parameters so we add the ones in the .ml *)
+ v.val_parameters <- (merge_parameters
+ v.val_parameters
+ v2.val_parameters) ;
+ (* we must reassociate comments in @param to the the corresponding
+ parameters because the associated comment of a parameter may have been changed y the merge.*)
+ Odoc_value.update_value_parameters_text v;
+
+ if !Odoc_global.keep_code then
+ v.val_code <- v2.val_code;
+
+ true
+ )
+ else
+ false
+ | _ ->
+ false
+ )
+ (* we look for the last value with this name defined in the implementation *)
+ (List.rev (Odoc_module.module_type_elements ml))
+ in
+ ()
+ with
+ Not_found ->
+ ()
+ )
+ (Odoc_module.module_type_values mli);
+
+ (* merge classes *)
+ List.iter
+ (fun c ->
+ try
+ let _ = List.find
+ (fun ele ->
+ match ele with
+ Element_class c2 ->
+ if c2.cl_name = c.cl_name then
+ (
+ merge_classes merge_options c c2;
+ true
+ )
+ else
+ false
+ | _ ->
+ false
+ )
+ (* we look for the last value with this name defined in the implementation *)
+ (List.rev (Odoc_module.module_type_elements ml))
+ in
+ ()
+ with
+ Not_found ->
+ ()
+ )
+ (Odoc_module.module_type_classes mli);
+
+ (* merge class types *)
+ List.iter
+ (fun c ->
+ try
+ let _ = List.find
+ (fun ele ->
+ match ele with
+ Element_class_type c2 ->
+ if c2.clt_name = c.clt_name then
+ (
+ merge_class_types merge_options c c2;
+ true
+ )
+ else
+ false
+ | _ ->
+ false
+ )
+ (* we look for the last value with this name defined in the implementation *)
+ (List.rev (Odoc_module.module_type_elements ml))
+ in
+ ()
+ with
+ Not_found ->
+ ()
+ )
+ (Odoc_module.module_type_class_types mli)
+
+(** merge of two t_module, one for a .mli, another for the .ml.
+ The .mli module is completed with the information in the .ml module. *)
+and merge_modules merge_options mli ml =
+ mli.m_info <- merge_info_opt merge_options mli.m_info ml.m_info;
+ mli.m_loc <- { mli.m_loc with loc_impl = ml.m_loc.loc_impl } ;
+ let rec remove_doubles acc = function
+ [] -> acc
+ | h :: q ->
+ if List.mem h acc then remove_doubles acc q
+ else remove_doubles (h :: acc) q
+ in
+ mli.m_top_deps <- remove_doubles mli.m_top_deps ml.m_top_deps ;
+
+ let code =
+ if !Odoc_global.keep_code then
+ match mli.m_code, ml.m_code with
+ Some s, _ -> Some s
+ | _, Some s -> Some s
+ | _ -> None
+ else
+ None
+ in
+ let code_intf =
+ if !Odoc_global.keep_code then
+ match mli.m_code_intf, ml.m_code_intf with
+ Some s, _ -> Some s
+ | _, Some s -> Some s
+ | _ -> None
+ else
+ None
+ in
+ mli.m_code <- code;
+ mli.m_code_intf <- code_intf;
+
+ (* merge exceptions *)
+ List.iter
+ (fun ex ->
+ try
+ let _ = List.find
+ (fun ele ->
+ match ele with
+ Element_exception ex2 ->
+ if ex2.ex_name = ex.ex_name then
+ (
+ ex.ex_info <- merge_info_opt merge_options ex.ex_info ex2.ex_info;
+ ex.ex_loc <- { ex.ex_loc with loc_impl = ex.ex_loc.loc_impl } ;
+ ex.ex_code <- (match ex.ex_code with None -> ex2.ex_code | _ -> ex.ex_code) ;
+ true
+ )
+ else
+ false
+ | _ ->
+ false
+ )
+ (* we look for the last exception with this name defined in the implementation *)
+ (List.rev (Odoc_module.module_elements ml))
+ in
+ ()
+ with
+ Not_found ->
+ ()
+ )
+ (Odoc_module.module_exceptions mli);
+ (* merge types *)
+ List.iter
+ (fun ty ->
+ try
+ let _ = List.find
+ (fun ele ->
+ match ele with
+ Element_type ty2 ->
+ if ty2.ty_name = ty.ty_name then
+ (
+ merge_types merge_options ty ty2;
+ true
+ )
+ else
+ false
+ | _ ->
+ false
+ )
+ (* we look for the last type with this name defined in the implementation *)
+ (List.rev (Odoc_module.module_elements ml))
+ in
+ ()
+ with
+ Not_found ->
+ ()
+ )
+ (Odoc_module.module_types mli);
+ (* merge submodules *)
+ List.iter
+ (fun m ->
+ try
+ let _ = List.find
+ (fun ele ->
+ match ele with
+ Element_module m2 ->
+ if m2.m_name = m.m_name then
+ (
+ ignore (merge_modules merge_options m m2);
+(*
+ m.m_info <- merge_info_opt merge_options m.m_info m2.m_info;
+ m.m_loc <- { m.m_loc with loc_impl = m2.m_loc.loc_impl } ;
+*)
+ true
+ )
+ else
+ false
+ | _ ->
+ false
+ )
+ (* we look for the last module with this name defined in the implementation *)
+ (List.rev (Odoc_module.module_elements ml))
+ in
+ ()
+ with
+ Not_found ->
+ ()
+ )
+ (Odoc_module.module_modules mli);
+
+ (* merge module types *)
+ List.iter
+ (fun m ->
+ try
+ let _ = List.find
+ (fun ele ->
+ match ele with
+ Element_module_type m2 ->
+ if m2.mt_name = m.mt_name then
+ (
+ merge_module_types merge_options m m2;
+ true
+ )
+ else
+ false
+ | _ ->
+ false
+ )
+ (* we look for the last module with this name defined in the implementation *)
+ (List.rev (Odoc_module.module_elements ml))
+ in
+ ()
+ with
+ Not_found ->
+ ()
+ )
+ (Odoc_module.module_module_types mli);
+
+ (* A VOIR : merge included modules ? *)
+
+ (* merge values *)
+ List.iter
+ (fun v ->
+ try
+ let _ = List.find
+ (fun v2 ->
+ if v2.val_name = v.val_name then
+ (
+ v.val_info <- merge_info_opt merge_options v.val_info v2.val_info ;
+ v.val_loc <- { v.val_loc with loc_impl = v2.val_loc.loc_impl } ;
+ (* in the .mli we don't know any parameters so we add the ones in the .ml *)
+ v.val_parameters <- (merge_parameters
+ v.val_parameters
+ v2.val_parameters) ;
+ (* we must reassociate comments in @param to the the corresponding
+ parameters because the associated comment of a parameter may have been changed y the merge.*)
+ Odoc_value.update_value_parameters_text v;
+
+ if !Odoc_global.keep_code then
+ v.val_code <- v2.val_code;
+ true
+ )
+ else
+ false
+ )
+ (* we look for the last value with this name defined in the implementation *)
+ (List.rev (Odoc_module.module_values ml))
+ in
+ ()
+ with
+ Not_found ->
+ ()
+ )
+ (Odoc_module.module_values mli);
+
+ (* merge classes *)
+ List.iter
+ (fun c ->
+ try
+ let _ = List.find
+ (fun ele ->
+ match ele with
+ Element_class c2 ->
+ if c2.cl_name = c.cl_name then
+ (
+ merge_classes merge_options c c2;
+ true
+ )
+ else
+ false
+ | _ ->
+ false
+ )
+ (* we look for the last value with this name defined in the implementation *)
+ (List.rev (Odoc_module.module_elements ml))
+ in
+ ()
+ with
+ Not_found ->
+ ()
+ )
+ (Odoc_module.module_classes mli);
+
+ (* merge class types *)
+ List.iter
+ (fun c ->
+ try
+ let _ = List.find
+ (fun ele ->
+ match ele with
+ Element_class_type c2 ->
+ if c2.clt_name = c.clt_name then
+ (
+ merge_class_types merge_options c c2;
+ true
+ )
+ else
+ false
+ | _ ->
+ false
+ )
+ (* we look for the last value with this name defined in the implementation *)
+ (List.rev (Odoc_module.module_elements ml))
+ in
+ ()
+ with
+ Not_found ->
+ ()
+ )
+ (Odoc_module.module_class_types mli);
+
+ mli
+
+let merge merge_options modules_list =
+ let rec iter = function
+ [] -> []
+ | m :: q ->
+ (* look for another module with the same name *)
+ let (l_same, l_others) = List.partition
+ (fun m2 -> m.m_name = m2.m_name)
+ q
+ in
+ match l_same with
+ [] ->
+ (* no other module to merge with *)
+ m :: (iter l_others)
+ | m2 :: [] ->
+ (
+ (* we can merge m with m2 if there is an implementation
+ and an interface.*)
+ let f b = if !Odoc_global.inverse_merge_ml_mli then not b else b in
+ match f m.m_is_interface, f m2.m_is_interface with
+ true, false -> (merge_modules merge_options m m2) :: (iter l_others)
+ | false, true -> (merge_modules merge_options m2 m) :: (iter l_others)
+ | false, false ->
+ if !Odoc_global.inverse_merge_ml_mli then
+ (* two Module.ts for the .mli ! *)
+ raise (Failure (Odoc_messages.two_interfaces m.m_name))
+ else
+ (* two Module.t for the .ml ! *)
+ raise (Failure (Odoc_messages.two_implementations m.m_name))
+ | true, true ->
+ if !Odoc_global.inverse_merge_ml_mli then
+ (* two Module.t for the .ml ! *)
+ raise (Failure (Odoc_messages.two_implementations m.m_name))
+ else
+ (* two Module.ts for the .mli ! *)
+ raise (Failure (Odoc_messages.two_interfaces m.m_name))
+ )
+ | _ ->
+ (* two many Module.t ! *)
+ raise (Failure (Odoc_messages.too_many_module_objects m.m_name))
+
+ in
+ iter modules_list
diff --git a/ocaml-binary-annot/ocamldoc/odoc_merge.mli b/ocaml-binary-annot/ocamldoc/odoc_merge.mli
new file mode 100644
index 0000000000..4f580ee899
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_merge.mli
@@ -0,0 +1,35 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Merge of information from [.ml] and [.mli] for a module.*)
+
+(** Merging \@before tags. *)
+val merge_before_tags :
+ (string * Odoc_types.text) list -> (string * Odoc_types.text) list
+
+(** Merge of two optional info structures.
+ Used to merge a comment before and a comment after
+ an element in [Odoc_sig.Analyser.analyse_signature_item_desc]. *)
+val merge_info_opt :
+ Odoc_types.merge_option list ->
+ Odoc_types.info option ->
+ Odoc_types.info option ->
+ Odoc_types.info option
+
+(** Merge of modules which represent the same OCaml module, in a list of t_module.
+ There must be at most two t_module for the same OCaml module, one for a .mli, another for the .ml.
+ The function returns the list of t_module where same modules have been merged, according
+ to the given merge_option list.*)
+val merge :
+ Odoc_types.merge_option list ->
+ Odoc_module.t_module list -> Odoc_module.t_module list
diff --git a/ocaml-binary-annot/ocamldoc/odoc_messages.ml b/ocaml-binary-annot/ocamldoc/odoc_messages.ml
new file mode 100644
index 0000000000..4d92c5d24f
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_messages.ml
@@ -0,0 +1,357 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** The messages of the application. *)
+
+let ok = "Ok"
+let software = "OCamldoc"
+let config_version = Config.version
+let magic = config_version^""
+let message_version = software^" "^config_version
+
+(** Messages for command line *)
+
+let usage = "Usage : "^(Sys.argv.(0))^" [options] <files>\n"
+let options_are = "Options are :"
+let option_version = "\tPrint version and exit"
+let latex_only = "(LaTeX only)"
+let texi_only = "(TeXinfo only)"
+let latex_texi_only = "(LaTeX and TeXinfo only)"
+let html_only = "(HTML only)"
+let html_latex_only = "(HTML and LaTeX only)"
+let html_latex_texi_only = "(HTML, LaTeX and TeXinfo only)"
+let man_only = "(man only)"
+let verbose_mode = "\t\tverbose mode"
+let include_dirs = "<dir>\tAdd <dir> to the list of include directories"
+let rectypes = "\tAllow arbitrary recursive types"
+let preprocess = "<command>\tPipe sources through preprocessor <command>"
+let option_impl ="<file>\tConsider <file> as a .ml file"
+let option_intf ="<file>\tConsider <file> as a .mli file"
+let option_text ="<file>\tConsider <file> as a .txt file"
+let display_custom_generators_dir = "\tDisplay custom generators standard directory and exit"
+let add_load_dir = "<dir>\tAdd the given directory to the search path for custom\n"^
+ "\t\tgenerators"
+let load_file = "<file.cm[o|a|xs]>\n\t\tLoad file defining a new documentation generator"
+let nolabels = "\tIgnore non-optional labels in types"
+let werr = "\tTreat ocamldoc warnings as errors"
+let hide_warnings = "\n\t\tdo not print ocamldoc warnings"
+let target_dir = "<dir>\tGenerate files in directory <dir>, rather than in current\n"^
+ "\t\tdirectory (for man and HTML generators)"
+let dump = "<file>\tDump collected information into <file>"
+let load = "<file>\tLoad information from <file> ; may be used several times"
+let css_style = "<file>\n\t\tUse content of <file> as CSS style definition "^html_only
+let index_only = "\tGenerate index files only "^html_only
+let colorize_code = "\n\t\tColorize code even in documentation pages "^html_only
+let html_short_functors = "\n\t\tUse short form to display functor types "^html_only
+let generate_html = "\tGenerate HTML documentation"
+let generate_latex = "\tGenerate LaTeX documentation"
+let generate_texinfo = "\tGenerate TeXinfo documentation"
+let generate_man = "\t\tGenerate man pages"
+let generate_dot = "\t\tGenerate dot code of top modules dependencies"
+
+let option_not_in_native_code op = "Option "^op^" not available in native code version."
+
+let default_out_file = "ocamldoc.out"
+let out_file =
+ "<file>\tSet the ouput file name, used by texi, latex and dot generators\n"^
+ "\t\t(default is "^default_out_file^")\n"^
+ "\t\tor the prefix of index files for the HTML generator\n"^
+ "\t\t(default is index)"
+
+let dot_include_all =
+ "\n\t\tInclude all modules in the dot output, not only the\n"^
+ "\t\tmodules given on the command line"
+let dot_types = "\tGenerate dependency graph for types instead of modules"
+let default_dot_colors =
+ [ [ "darkturquoise" ; "darkgoldenrod2" ; "cyan" ; "green" ; ] ;
+ [ "magenta" ; "yellow" ; "burlywood1" ; "aquamarine" ; "floralwhite" ; "lightpink" ] ;
+ [ "lightblue" ; "mediumturquoise" ; "salmon" ; "slategray3"] ;
+ ]
+
+let dot_colors =
+ "<c1,c2,...,cn>\n\t\tUse colors c1,c1,...,cn in the dot output\n"^
+ "\t\t(default list is "^
+ (String.concat ",\n\t\t" (List.map (String.concat ",") default_dot_colors))^")"
+
+let dot_reduce =
+ "\tPerform a transitive reduction on the selected dependency graph\n"^
+ "\t\tbefore the dot output"
+
+let man_mini = "\tGenerate man pages only for modules, module types, classes\n"^
+ "\t\tand class types "^man_only
+let default_man_section = "3"
+let man_section = "<section>\n\t\tUse <section> in man page files "^
+ "(default is "^default_man_section^") "^man_only^"\n"
+
+let default_man_suffix = default_man_section^"o"
+let man_suffix = "<suffix>\n\t\tUse <suffix> for man page files "^
+ "(default is "^default_man_suffix^") "^man_only^"\n"
+
+let option_title = "<title>\tUse <title> as title for the generated documentation"
+let option_intro =
+ "<file>\tUse content of <file> as ocamldoc text to use as introduction\n"^
+ "\t\t"^(html_latex_texi_only)
+let with_parameter_list = "\tDisplay the complete list of parameters for functions and\n"^
+ "\t\tmethods "^html_only
+let hide_modules = "<M1,M2.M3,...>\n\t\tHide the given complete module names in generated doc"
+let no_header = "\tSuppress header in generated documentation\n\t\t"^latex_texi_only
+let no_trailer = "\tSuppress trailer in generated documentation\n\t\t"^latex_texi_only
+let separate_files = "\tGenerate one file per toplevel module "^latex_only
+let latex_title ref_titles =
+ "n,style\n\t\tAssociate {n } to the given sectionning style\n"^
+ "\t\t(e.g. 'section') in the latex output "^latex_only^"\n"^
+ "\t\tDefault sectionning is:\n\t\t"^
+ (String.concat "\n\t\t"
+ (List.map (fun (n,t) -> Printf.sprintf " %d -> %s" n t) !ref_titles))
+
+let default_latex_value_prefix = "val:"
+let latex_value_prefix =
+ "<string>\n\t\tUse <string> as prefix for the LaTeX labels of values.\n"^
+ "\t\t(default is \""^default_latex_value_prefix^"\")"
+
+let default_latex_type_prefix = "type:"
+let latex_type_prefix =
+ "<string>\n\t\tUse <string> as prefix for the LaTeX labels of types.\n"^
+ "\t\t(default is \""^default_latex_type_prefix^"\")"
+
+let default_latex_exception_prefix = "exception:"
+let latex_exception_prefix =
+ "<string>\n\t\tUse <string> as prefix for the LaTeX labels of exceptions.\n"^
+ "\t\t(default is \""^default_latex_exception_prefix^"\")"
+
+let default_latex_module_prefix = "module:"
+let latex_module_prefix =
+ "<string>\n\t\tUse <string> as prefix for the LaTeX labels of modules.\n"^
+ "\t\t(default is \""^default_latex_module_prefix^"\")"
+
+let default_latex_module_type_prefix = "moduletype:"
+let latex_module_type_prefix =
+ "<string>\n\t\tUse <string> as prefix for the LaTeX labels of module types.\n"^
+ "\t\t(default is \""^default_latex_module_type_prefix^"\")"
+
+let default_latex_class_prefix = "class:"
+let latex_class_prefix =
+ "<string>\n\t\tUse <string> as prefix for the LaTeX labels of classes.\n"^
+ "\t\t(default is \""^default_latex_class_prefix^"\")"
+
+let default_latex_class_type_prefix = "classtype:"
+let latex_class_type_prefix =
+ "<string>\n\t\tUse <string> as prefix for the LaTeX labels of class types.\n"^
+ "\t\t(default is \""^default_latex_class_type_prefix^"\")"
+
+let default_latex_attribute_prefix = "val:"
+let latex_attribute_prefix =
+ "<string>\n\t\tUse <string> as prefix for the LaTeX labels of attributes.\n"^
+ "\t\t(default is \""^default_latex_attribute_prefix^"\")"
+
+let default_latex_method_prefix = "method:"
+let latex_method_prefix =
+ "<string>\n\t\tUse <string> as prefix for the LaTeX labels of methods.\n"^
+ "\t\t(default is \""^default_latex_method_prefix^"\")"
+
+let no_toc = "\tDo not generate table of contents "^latex_only
+let sort_modules = "\tSort the list of top modules before generating the documentation"
+let no_stop = "\tDo not stop at (**/**) comments"
+let no_custom_tags = "\n\t\tDo not allow custom @-tags"
+let remove_stars = "\tRemove beginning blanks of comment lines, until the first '*'"
+let keep_code = "\tAlways keep code when available"
+let inverse_merge_ml_mli = "\n\t\tInverse implementations and interfaces when merging"
+let no_filter_with_module_constraints = "\n\t\tDo not filter module elements using module type constraints"
+let merge_description = ('d', "merge description")
+let merge_author = ('a', "merge @author")
+let merge_version = ('v', "merge @version")
+let merge_see = ('l', "merge @see")
+let merge_since = ('s', "merge @since")
+let merge_deprecated = ('o', "merge @deprecated")
+let merge_param = ('p', "merge @param")
+let merge_raised_exception = ('e', "merge @raise")
+let merge_return_value = ('r', "merge @return")
+let merge_custom = ('c', "merge custom @-tags")
+let merge_all = ('A', "merge all")
+
+let no_index = "\tDo not build index for Info files "^texi_only
+let esc_8bits = "\tEscape accentuated characters in Info files "^texi_only
+let info_section = "Specify section of Info directory "^texi_only
+let info_entry = "\tSpecify Info directory entry "^texi_only
+
+let options_can_be = "<options> can be one or more of the following characters:"
+let string_of_options_list l =
+ List.fold_left (fun acc -> fun (c, m) -> acc^"\n\t\t"^(String.make 1 c)^" "^m)
+ ""
+ l
+
+let merge_options =
+ "<options>\tspecify merge options between .mli and .ml\n\t\t"^
+ options_can_be^
+ (string_of_options_list
+ [ merge_description ;
+ merge_author ;
+ merge_version ;
+ merge_see ;
+ merge_since ;
+ merge_deprecated ;
+ merge_param ;
+ merge_raised_exception ;
+ merge_return_value ;
+ merge_custom ;
+ merge_all ]
+ )
+
+
+(** Error and warning messages *)
+
+let warning = "Warning"
+
+let bad_magic_number =
+ "Bad magic number for this ocamldoc dump!\n"^
+ "This dump was not created by this version of OCamldoc."
+
+let not_a_module_name s = s^" is not a valid module name"
+let load_file_error f e = "Error while loading file "^f^":\n"^e
+let wrong_format s = "Wrong format for \""^s^"\""
+let errors_occured n = (string_of_int n)^" error(s) encountered"
+let parse_error = "Parse error"
+let text_parse_error l c s =
+ let lines = Str.split (Str.regexp_string "\n") s in
+ "Syntax error in text:\n"^s^"\n"^
+ "line "^(string_of_int l)^", character "^(string_of_int c)^":\n"^
+ (List.nth lines l)^"\n"^
+ (String.make c ' ')^"^"
+
+let file_not_found_in_paths paths name =
+ Printf.sprintf "No file %s found in the load paths: \n%s"
+ name
+ (String.concat "\n" paths)
+
+let tag_not_handled tag = "Tag @"^tag^" not handled by this generator"
+let bad_tree = "Incorrect tree structure."
+let not_a_valid_tag s = s^" is not a valid tag."
+let fun_without_param f = "Function "^f^" has no parameter.";;
+let method_without_param f = "Méthode "^f^" has no parameter.";;
+let anonymous_parameters f = "Function "^f^" has anonymous parameters."
+let function_colon f = "Function "^f^": "
+let implicit_match_in_parameter = "Parameters contain implicit pattern matching."
+let unknown_extension f = "Unknown extension for file "^f^"."
+let two_implementations name = "There are two implementations of module "^name^"."
+let two_interfaces name = "There are two interfaces of module "^name^"."
+let too_many_module_objects name = "There are two many interfaces/implementation of module "^name^"."
+let exception_not_found_in_implementation exc m = "Exception "^exc^" was not found in implementation of module "^m^"."
+let type_not_found_in_implementation exc m = "Type "^exc^" was not found in implementation of module "^m^"."
+let module_not_found_in_implementation m m2 = "Module "^m^" was not found in implementation of module "^m2^"."
+let value_not_found_in_implementation v m = "Value "^v^" was not found in implementation of module "^m^"."
+let class_not_found_in_implementation c m = "Class "^c^" was not found in implementation of module "^m^"."
+let attribute_not_found_in_implementation a c = "Attribute "^a^" was not found in implementation of class "^c^"."
+let method_not_found_in_implementation m c = "Method "^m^" was not found in implementation of class "^c^"."
+let different_types t = "Definition of type "^t^" doesn't match from interface to implementation."
+let attribute_type_not_found cl att = "The type of the attribute "^att^" could not be found in the signature of class "^cl^"."
+let method_type_not_found cl met = "The type of the method "^met^" could not be found in the signature of class "^cl^"."
+let module_not_found m m2 = "The module "^m2^" could not be found in the signature of module "^m^"."
+let module_type_not_found m mt = "The module type "^mt^" could not be found in the signature of module "^m^"."
+let value_not_found m v = "The value "^v^" could not be found in the signature of module "^m^"."
+let exception_not_found m e = "The exception "^e^" could not be found in the signature of module "^m^"."
+let type_not_found m t = "The type "^t^" could not be found in the signature of module "^m^"."
+let class_not_found m c = "The class "^c^" could not be found in the signature of module "^m^"."
+let class_type_not_found m c = "The class type "^c^" could not be found in the signature of module "^m^"."
+let type_not_found_in_typedtree t = "Type "^t^" was not found in typed tree."
+let exception_not_found_in_typedtree e = "Exception "^e^" was not found in typed tree."
+let module_type_not_found_in_typedtree mt = "Module type "^mt^" was not found in typed tree."
+let module_not_found_in_typedtree m = "Module "^m^" was not found in typed tree."
+let class_not_found_in_typedtree c = "Class "^c^" was not found in typed tree."
+let class_type_not_found_in_typedtree ct = "Class type "^ct^" was not found in typed tree."
+let inherit_classexp_not_found_in_typedtree n = "Inheritance class expression number "^(string_of_int n)^" was not found in typed tree."
+let attribute_not_found_in_typedtree att = "Class attribute "^att^" was not found in typed tree."
+let method_not_found_in_typedtree met = "Class method "^met^" was not found in typed tree."
+let misplaced_comment file pos =
+ Printf.sprintf "Misplaced special comment in file %s, character %d." file pos
+
+let cross_module_not_found n = "Module "^n^" not found"
+let cross_module_type_not_found n = "Module type "^n^" not found"
+let cross_module_or_module_type_not_found n = "Module or module type "^n^" not found"
+let cross_class_not_found n = "Class "^n^" not found"
+let cross_class_type_not_found n = "class type "^n^" not found"
+let cross_class_or_class_type_not_found n = "Class or class type "^n^" not found"
+let cross_exception_not_found n = "Exception "^n^" not found"
+let cross_element_not_found n = "Element "^n^" not found"
+let cross_method_not_found n = "Method "^n^" not found"
+let cross_attribute_not_found n = "Attribute "^n^" not found"
+let cross_section_not_found n = "Section "^n^" not found"
+let cross_value_not_found n = "Value "^n^" not found"
+let cross_type_not_found n = "Type "^n^" not found"
+
+let object_end = "object ... end"
+let struct_end = "struct ... end"
+let sig_end = "sig ... end"
+
+(** Messages for verbose mode. *)
+
+let analysing f = "Analysing file "^f^"..."
+let merging = "Merging..."
+let cross_referencing = "Cross referencing..."
+let generating_doc = "Generating documentation..."
+let loading f = "Loading "^f^"..."
+let file_generated f = "File "^f^" generated."
+let file_exists_dont_generate f =
+ "File "^f^" exists, we don't generate it."
+
+(** Messages for documentation generation.*)
+
+let modul = "Module"
+let modules = "Modules"
+let functors = "Functors"
+let values = "Simple values"
+let types = "Types"
+let exceptions = "Exceptions"
+let record = "Record"
+let variant = "Variant"
+let mutab = "mutable"
+let functions = "Functions"
+let parameters = "Parameters"
+let abstract = "Abstract"
+let functo = "Functor"
+let clas = "Class"
+let classes = "Classes"
+let attributes = "Attributes"
+let methods = "Methods"
+let authors = "Author(s)"
+let version = "Version"
+let since = "Since"
+let before = "Before"
+let deprecated = "Deprecated."
+let raises = "Raises"
+let returns = "Returns"
+let inherits = "Inherits"
+let inheritance = "Inheritance"
+let privat = "private"
+let module_type = "Module type"
+let class_type = "Class type"
+let description = "Description"
+let interface = "Interface"
+let type_parameters = "Type parameters"
+let class_types = "Class types"
+let module_types = "Module types"
+let see_also = "See also"
+let documentation = "Documentation"
+let index_of = "Index of"
+let top = "Top"
+let index_of_values = index_of^" values"
+let index_of_exceptions = index_of^" exceptions"
+let index_of_types = index_of^" types"
+let index_of_attributes = index_of^" class attributes"
+let index_of_methods = index_of^" class methods"
+let index_of_classes = index_of^" classes"
+let index_of_class_types = index_of^" class types"
+let index_of_modules = index_of^" modules"
+let index_of_module_types = index_of^" module types"
+let previous = "Previous"
+let next = "Next"
+let up = "Up"
diff --git a/ocaml-binary-annot/ocamldoc/odoc_misc.ml b/ocaml-binary-annot/ocamldoc/odoc_misc.ml
new file mode 100644
index 0000000000..c439ef3163
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_misc.ml
@@ -0,0 +1,494 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+let no_blanks s =
+ let len = String.length s in
+ let buf = Buffer.create len in
+ for i = 0 to len - 1 do
+ match s.[i] with
+ ' ' | '\n' | '\t' | '\r' -> ()
+ | c -> Buffer.add_char buf c
+ done;
+ Buffer.contents buf
+
+let input_file_as_string nom =
+ let chanin = open_in_bin nom in
+ let len = 1024 in
+ let s = String.create len in
+ let buf = Buffer.create len in
+ let rec iter () =
+ try
+ let n = input chanin s 0 len in
+ if n = 0 then
+ ()
+ else
+ (
+ Buffer.add_substring buf s 0 n;
+ iter ()
+ )
+ with
+ End_of_file -> ()
+ in
+ iter ();
+ close_in chanin;
+ Buffer.contents buf
+
+let split_string s chars =
+ let len = String.length s in
+ let rec iter acc pos =
+ if pos >= len then
+ match acc with
+ "" -> []
+ | _ -> [acc]
+ else
+ if List.mem s.[pos] chars then
+ match acc with
+ "" -> iter "" (pos + 1)
+ | _ -> acc :: (iter "" (pos + 1))
+ else
+ iter (Printf.sprintf "%s%c" acc s.[pos]) (pos + 1)
+ in
+ iter "" 0
+
+let split_with_blanks s = split_string s [' ' ; '\n' ; '\r' ; '\t' ]
+
+let list_concat sep =
+ let rec iter = function
+ [] -> []
+ | [h] -> [h]
+ | h :: q -> h :: sep :: q
+ in
+ iter
+
+let rec string_of_longident li =
+ match li with
+ | Longident.Lident s -> s
+ | Longident.Ldot(li, s) -> string_of_longident li ^ "." ^ s
+ | Longident.Lapply(l1, l2) ->
+ string_of_longident l1 ^ "(" ^ string_of_longident l2 ^ ")"
+
+let get_fields type_expr =
+ let (fields, _) = Ctype.flatten_fields (Ctype.object_fields type_expr) in
+ List.fold_left
+ (fun acc -> fun (label, field_kind, typ) ->
+ match field_kind with
+ Types.Fabsent ->
+ acc
+ | _ ->
+ if label = "*dummy method*" then
+ acc
+ else
+ acc @ [label, typ]
+ )
+ []
+ fields
+
+let rec string_of_text t =
+ let rec iter t_ele =
+ match t_ele with
+ | Odoc_types.Raw s
+ | Odoc_types.Code s
+ | Odoc_types.CodePre s
+ | Odoc_types.Verbatim s -> s
+ | Odoc_types.Bold t
+ | Odoc_types.Italic t
+ | Odoc_types.Center t
+ | Odoc_types.Left t
+ | Odoc_types.Right t
+ | Odoc_types.Emphasize t -> string_of_text t
+ | Odoc_types.List l ->
+ (String.concat ""
+ (List.map (fun t -> "\n- "^(string_of_text t)) l))^
+ "\n"
+ | Odoc_types.Enum l ->
+ let rec f n = function
+ [] -> "\n"
+ | t :: q ->
+ "\n"^(string_of_int n)^". "^(string_of_text t)^
+ (f (n + 1) q)
+ in
+ f 1 l
+ | Odoc_types.Newline -> "\n"
+ | Odoc_types.Block t -> "\t"^(string_of_text t)^"\n"
+ | Odoc_types.Title (_, _, t) -> "\n"^(string_of_text t)^"\n"
+ | Odoc_types.Latex s -> "{% "^s^" %}"
+ | Odoc_types.Link (s, t) ->
+ "["^s^"]"^(string_of_text t)
+ | Odoc_types.Ref (name, _, Some text) ->
+ Printf.sprintf "[%s]" (string_of_text text)
+ | Odoc_types.Ref (name, _, None) ->
+ iter (Odoc_types.Code name)
+ | Odoc_types.Superscript t ->
+ "^{"^(string_of_text t)^"}"
+ | Odoc_types.Subscript t ->
+ "^{"^(string_of_text t)^"}"
+ | Odoc_types.Module_list l ->
+ string_of_text
+ (list_concat (Odoc_types.Raw ", ")
+ (List.map (fun s -> Odoc_types.Code s) l)
+ )
+ | Odoc_types.Index_list ->
+ ""
+ | Odoc_types.Custom (_, t) -> string_of_text t
+ | Odoc_types.Target _ -> ""
+ in
+ String.concat "" (List.map iter t)
+
+let string_of_author_list l =
+ match l with
+ [] ->
+ ""
+ | _ ->
+ "* "^Odoc_messages.authors^":\n"^
+ (String.concat ", " l)^
+ "\n"
+
+let string_of_version_opt v_opt =
+ match v_opt with
+ None -> ""
+ | Some v -> Odoc_messages.version^": "^v^"\n"
+
+let string_of_since_opt s_opt =
+ match s_opt with
+ None -> ""
+ | Some s -> Odoc_messages.since^" "^s^"\n"
+
+let string_of_raised_exceptions l =
+ match l with
+ [] -> ""
+ | (s, t) :: [] -> Odoc_messages.raises^" "^s^" "^(string_of_text t)^"\n"
+ | _ ->
+ Odoc_messages.raises^"\n"^
+ (String.concat ""
+ (List.map
+ (fun (ex, desc) -> "- "^ex^" "^(string_of_text desc)^"\n")
+ l
+ )
+ )^"\n"
+
+let string_of_see (see_ref, t) =
+ let t_ref =
+ match see_ref with
+ Odoc_types.See_url s -> [ Odoc_types.Link (s, t) ]
+ | Odoc_types.See_file s -> (Odoc_types.Code s) :: (Odoc_types.Raw " ") :: t
+ | Odoc_types.See_doc s -> (Odoc_types.Italic [Odoc_types.Raw s]) :: (Odoc_types.Raw " ") :: t
+ in
+ string_of_text t_ref
+
+let string_of_sees l =
+ match l with
+ [] -> ""
+ | see :: [] -> Odoc_messages.see_also^" "^(string_of_see see)^" \n"
+ | _ ->
+ Odoc_messages.see_also^"\n"^
+ (String.concat ""
+ (List.map
+ (fun see -> "- "^(string_of_see see)^"\n")
+ l
+ )
+ )^"\n"
+
+let string_of_return_opt return_opt =
+ match return_opt with
+ None -> ""
+ | Some s -> Odoc_messages.returns^" "^(string_of_text s)^"\n"
+
+let string_of_info i =
+ let module M = Odoc_types in
+ (match i.M.i_deprecated with
+ None -> ""
+ | Some d -> Odoc_messages.deprecated^"! "^(string_of_text d)^"\n")^
+ (match i.M.i_desc with
+ None -> ""
+ | Some d when d = [Odoc_types.Raw ""] -> ""
+ | Some d -> (string_of_text d)^"\n"
+ )^
+ (string_of_author_list i.M.i_authors)^
+ (string_of_version_opt i.M.i_version)^
+ (string_of_since_opt i.M.i_since)^
+ (string_of_raised_exceptions i.M.i_raised_exceptions)^
+ (string_of_return_opt i.M.i_return_value)
+
+let apply_opt f v_opt =
+ match v_opt with
+ None -> None
+ | Some v -> Some (f v)
+
+let string_of_date ?(hour=true) d =
+ let add_0 s = if String.length s < 2 then "0"^s else s in
+ let t = Unix.localtime d in
+ (string_of_int (t.Unix.tm_year + 1900))^"-"^
+ (add_0 (string_of_int (t.Unix.tm_mon + 1)))^"-"^
+ (add_0 (string_of_int t.Unix.tm_mday))^
+ (
+ if hour then
+ " "^
+ (add_0 (string_of_int t.Unix.tm_hour))^":"^
+ (add_0 (string_of_int t.Unix.tm_min))
+ else
+ ""
+ )
+
+
+let rec text_list_concat sep l =
+ match l with
+ [] -> []
+ | [t] -> t
+ | t :: q ->
+ t @ (sep :: (text_list_concat sep q))
+
+let rec text_no_title_no_list t =
+ let rec iter t_ele =
+ match t_ele with
+ | Odoc_types.Title (_,_,t) -> text_no_title_no_list t
+ | Odoc_types.List l
+ | Odoc_types.Enum l ->
+ (Odoc_types.Raw " ") ::
+ (text_list_concat
+ (Odoc_types.Raw ", ")
+ (List.map text_no_title_no_list l))
+ | Odoc_types.Raw _
+ | Odoc_types.Code _
+ | Odoc_types.CodePre _
+ | Odoc_types.Verbatim _
+ | Odoc_types.Ref _
+ | Odoc_types.Target _ -> [t_ele]
+ | Odoc_types.Newline -> [Odoc_types.Newline]
+ | Odoc_types.Block t -> [Odoc_types.Block (text_no_title_no_list t)]
+ | Odoc_types.Bold t -> [Odoc_types.Bold (text_no_title_no_list t)]
+ | Odoc_types.Italic t -> [Odoc_types.Italic (text_no_title_no_list t)]
+ | Odoc_types.Center t -> [Odoc_types.Center (text_no_title_no_list t)]
+ | Odoc_types.Left t -> [Odoc_types.Left (text_no_title_no_list t)]
+ | Odoc_types.Right t -> [Odoc_types.Right (text_no_title_no_list t)]
+ | Odoc_types.Emphasize t -> [Odoc_types.Emphasize (text_no_title_no_list t)]
+ | Odoc_types.Latex s -> [Odoc_types.Latex s]
+ | Odoc_types.Link (s, t) -> [Odoc_types.Link (s, (text_no_title_no_list t))]
+ | Odoc_types.Superscript t -> [Odoc_types.Superscript (text_no_title_no_list t)]
+ | Odoc_types.Subscript t -> [Odoc_types.Subscript (text_no_title_no_list t)]
+ | Odoc_types.Module_list l ->
+ list_concat (Odoc_types.Raw ", ")
+ (List.map
+ (fun s -> Odoc_types.Ref (s, Some Odoc_types.RK_module, None))
+ l
+ )
+ | Odoc_types.Index_list -> []
+ | Odoc_types.Custom (s,t) -> [Odoc_types.Custom (s, text_no_title_no_list t)]
+ in
+ List.flatten (List.map iter t)
+
+let get_titles_in_text t =
+ let l = ref [] in
+ let rec iter_ele ele =
+ match ele with
+ | Odoc_types.Title (n,lopt,t) -> l := (n,lopt,t) :: !l
+ | Odoc_types.List l
+ | Odoc_types.Enum l -> List.iter iter_text l
+ | Odoc_types.Raw _
+ | Odoc_types.Code _
+ | Odoc_types.CodePre _
+ | Odoc_types.Verbatim _
+ | Odoc_types.Ref _ -> ()
+ | Odoc_types.Newline -> ()
+ | Odoc_types.Block t
+ | Odoc_types.Bold t
+ | Odoc_types.Italic t
+ | Odoc_types.Center t
+ | Odoc_types.Left t
+ | Odoc_types.Right t
+ | Odoc_types.Emphasize t -> iter_text t
+ | Odoc_types.Latex s -> ()
+ | Odoc_types.Link (_, t)
+ | Odoc_types.Superscript t
+ | Odoc_types.Subscript t -> iter_text t
+ | Odoc_types.Module_list _ -> ()
+ | Odoc_types.Index_list -> ()
+ | Odoc_types.Custom (_, t) -> iter_text t
+ | Odoc_types.Target _ -> ()
+ and iter_text te =
+ List.iter iter_ele te
+ in
+ iter_text t;
+ List.rev !l
+
+let text_concat (sep : Odoc_types.text) l =
+ let rec iter = function
+ [] -> []
+ | [last] -> last
+ | h :: q -> h @ sep @ (iter q)
+ in
+ iter l
+
+(*********************************************************)
+let rec get_before_dot s =
+ try
+ let len = String.length s in
+ let n = String.index s '.' in
+ if n + 1 >= len then
+ (* le point est le dernier caractère *)
+ (true, s, "")
+ else
+ match s.[n+1] with
+ ' ' | '\n' | '\r' | '\t' ->
+ (true, String.sub s 0 (n+1),
+ String.sub s (n+1) (len - n - 1))
+ | _ ->
+ let b, s2, s_after = get_before_dot (String.sub s (n + 1) (len - n - 1)) in
+ (b, (String.sub s 0 (n+1))^s2, s_after)
+ with
+ Not_found -> (false, s, "")
+
+let rec first_sentence_text t =
+ match t with
+ [] -> (false, [], [])
+ | ele :: q ->
+ let (stop, ele2, ele3_opt) = first_sentence_text_ele ele in
+ if stop then
+ (stop, [ele2],
+ match ele3_opt with None -> q | Some e -> e :: q)
+ else
+ let (stop2, q2, rest) = first_sentence_text q in
+ (stop2, ele2 :: q2, rest)
+
+
+and first_sentence_text_ele text_ele =
+ match text_ele with
+ | Odoc_types.Raw s ->
+ let b, s2, s_after = get_before_dot s in
+ (b, Odoc_types.Raw s2, Some (Odoc_types.Raw s_after))
+ | Odoc_types.Code _
+ | Odoc_types.CodePre _
+ | Odoc_types.Verbatim _ -> (false, text_ele, None)
+ | Odoc_types.Bold t ->
+ let (b, t2, t3) = first_sentence_text t in
+ (b, Odoc_types.Bold t2, Some (Odoc_types.Bold t3))
+ | Odoc_types.Italic t ->
+ let (b, t2, t3) = first_sentence_text t in
+ (b, Odoc_types.Italic t2, Some (Odoc_types.Italic t3))
+ | Odoc_types.Center t ->
+ let (b, t2, t3) = first_sentence_text t in
+ (b, Odoc_types.Center t2, Some (Odoc_types.Center t3))
+ | Odoc_types.Left t ->
+ let (b, t2, t3) = first_sentence_text t in
+ (b, Odoc_types.Left t2, Some (Odoc_types.Left t3))
+ | Odoc_types.Right t ->
+ let (b, t2, t3) = first_sentence_text t in
+ (b, Odoc_types.Right t2, Some (Odoc_types.Right t3))
+ | Odoc_types.Emphasize t ->
+ let (b, t2, t3) = first_sentence_text t in
+ (b, Odoc_types.Emphasize t2, Some (Odoc_types.Emphasize t3))
+ | Odoc_types.Block t ->
+ let (b, t2, t3) = first_sentence_text t in
+ (b, Odoc_types.Block t2, Some (Odoc_types.Block t3))
+ | Odoc_types.Title (n, l_opt, t) ->
+ let (b, t2, t3) = first_sentence_text t in
+ (b,
+ Odoc_types.Title (n, l_opt, t2),
+ Some (Odoc_types.Title (n, l_opt, t3)))
+ | Odoc_types.Newline ->
+ (true, Odoc_types.Raw "", Some Odoc_types.Newline)
+ | Odoc_types.List _
+ | Odoc_types.Enum _
+ | Odoc_types.Latex _
+ | Odoc_types.Link _
+ | Odoc_types.Ref _
+ | Odoc_types.Superscript _
+ | Odoc_types.Subscript _
+ | Odoc_types.Module_list _
+ | Odoc_types.Index_list -> (false, text_ele, None)
+ | Odoc_types.Custom _
+ | Odoc_types.Target _ -> (false, text_ele, None)
+
+
+let first_sentence_of_text t =
+ let (_,t2,_) = first_sentence_text t in
+ t2
+
+let first_sentence_and_rest_of_text t =
+ let (_,t1, t2) = first_sentence_text t in
+ (t1, t2)
+
+let remove_ending_newline s =
+ let len = String.length s in
+ if len <= 0 then
+ s
+ else
+ match s.[len-1] with
+ '\n' -> String.sub s 0 (len-1)
+ | _ -> s
+
+let search_string_backward ~pat =
+ let lenp = String.length pat in
+ let rec iter s =
+ let len = String.length s in
+ match compare len lenp with
+ -1 -> raise Not_found
+ | 0 -> if pat = s then 0 else raise Not_found
+ | _ ->
+ let pos = len - lenp in
+ let s2 = String.sub s pos lenp in
+ if s2 = pat then
+ pos
+ else
+ iter (String.sub s 0 pos)
+ in
+ fun ~s -> iter s
+
+
+
+(*********************************************************)
+
+let create_index_lists elements string_of_ele =
+ let rec f current acc0 acc1 acc2 = function
+ [] -> (acc0 :: acc1) @ [acc2]
+ | ele :: q ->
+ let s = string_of_ele ele in
+ match s with
+ "" -> f current acc0 acc1 (acc2 @ [ele]) q
+ | _ ->
+ let first = Char.uppercase s.[0] in
+ match first with
+ 'A' .. 'Z' ->
+ if current = first then
+ f current acc0 acc1 (acc2 @ [ele]) q
+ else
+ f first acc0 (acc1 @ [acc2]) [ele] q
+ | _ ->
+ f current (acc0 @ [ele]) acc1 acc2 q
+ in
+ f '_' [] [] [] elements
+
+
+(*** for labels *)
+
+let is_optional = Btype.is_optional
+let label_name = Btype.label_name
+
+let remove_option typ =
+ let rec iter t =
+ match t with
+ | Types.Tconstr(path, [ty], _) when Path.same path Predef.path_option -> ty.Types.desc
+ | Types.Tconstr _
+ | Types.Tvar
+ | Types.Tunivar
+ | Types.Tpoly _
+ | Types.Tarrow _
+ | Types.Ttuple _
+ | Types.Tobject _
+ | Types.Tfield _
+ | Types.Tnil
+ | Types.Tvariant _
+ | Types.Tpackage _ -> t
+ | Types.Tlink t2
+ | Types.Tsubst t2 -> iter t2.Types.desc
+ in
+ { typ with Types.desc = iter typ.Types.desc }
diff --git a/ocaml-binary-annot/ocamldoc/odoc_misc.mli b/ocaml-binary-annot/ocamldoc/odoc_misc.mli
new file mode 100644
index 0000000000..4fc83fe89b
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_misc.mli
@@ -0,0 +1,115 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Miscelaneous functions *)
+
+(** [no_blanks s] returns the given string without any blank
+ characters, i.e. '\n' '\r' ' ' '\t'.
+*)
+val no_blanks : string -> string
+
+(** This function returns a file in the form of one string.*)
+val input_file_as_string : string -> string
+
+(** [split_with_blanks s] splits the given string [s] according to blanks. *)
+val split_with_blanks : string -> string list
+
+(** This function creates a string from a Longident.t .*)
+val string_of_longident : Longident.t -> string
+
+(** This function returns the list of (label, type_expr) describing
+ the methods of a type_expr in a Tobject.*)
+val get_fields : Types.type_expr -> (string * Types.type_expr) list
+
+(** get a string from a text *)
+val string_of_text : Odoc_types.text -> string
+
+(** @return a string for an authors list. *)
+val string_of_author_list : string list -> string
+
+(** @return a string for the given optional version information.*)
+val string_of_version_opt : string option -> string
+
+(** @return a string for the given optional since information.*)
+val string_of_since_opt : string option -> string
+
+(** @return a string for the given list of raised exceptions.*)
+val string_of_raised_exceptions : (string * Odoc_types.text) list -> string
+
+(** @return a string for the given "see also" reference.*)
+val string_of_see : Odoc_types.see_ref * Odoc_types.text -> string
+
+(** @return a string for the given list of "see also" references.*)
+val string_of_sees : (Odoc_types.see_ref * Odoc_types.text) list -> string
+
+(** @return a string for the given optional return information.*)
+val string_of_return_opt : Odoc_types.text option -> string
+
+(** get a string from a Odoc_info.info structure *)
+val string_of_info : Odoc_types.info -> string
+
+(** Apply a function to an optional value. *)
+val apply_opt : ('a -> 'b) -> 'a option -> 'b option
+
+(** Return a string representing a date given as a number of seconds
+ since 1970. The hour is optionnaly displayed. *)
+val string_of_date : ?hour:bool -> float -> string
+
+(** Return the first sentence (until the first dot) of a text.
+ Don't stop in the middle of [Code], [Verbatim], [List], [Lnum],
+ [Latex], [Link], or [Ref]. *)
+val first_sentence_of_text : Odoc_types.text -> Odoc_types.text
+
+(** Return the first sentence (until the first dot) of a text,
+ and the remaining text after.
+ Don't stop in the middle of [Code], [Verbatim], [List], [Lnum],
+ [Latex], [Link], or [Ref]. *)
+val first_sentence_and_rest_of_text :
+ Odoc_types.text -> Odoc_types.text * Odoc_types.text
+
+(** Return the given [text] without any title or list. *)
+val text_no_title_no_list : Odoc_types.text -> Odoc_types.text
+
+(** [concat sep l] concats the given list of text [l], each separated with
+ the text [sep]. *)
+val text_concat : Odoc_types.text -> Odoc_types.text list -> Odoc_types.text
+
+(** Return the list of titles in a [text].
+ A title is a title level, an optional label and a text.*)
+val get_titles_in_text : Odoc_types.text -> (int * string option * Odoc_types.text) list
+
+(** Take a sorted list of elements, a function to get the name
+ of an element and return the list of list of elements,
+ where each list group elements beginning by the same letter.
+ Since the original list is sorted, elements whose name does not
+ begin with a letter should be in the first returned list.*)
+val create_index_lists : 'a list -> ('a -> string) -> 'a list list
+
+(** [remove_ending_newline s] returns [s] without the optional ending newline. *)
+val remove_ending_newline : string -> string
+
+(** [search_string_backward pat s] searches backward string [pat] in string [s].
+ Return position in string [s] where [pat] appears, orelse raise [Not_found]. *)
+val search_string_backward : pat: string -> s: string -> int
+
+(** Take a type and remove the option top constructor. This is
+ useful when printing labels, we we then remove the top option contructor
+ for optional labels.*)
+val remove_option : Types.type_expr -> Types.type_expr
+
+(** Return [true] if the given label is optional.*)
+val is_optional : string -> bool
+
+(** Return the label name for the given label,
+ i.e. removes the beginning '?' if present.*)
+val label_name : string -> string
diff --git a/ocaml-binary-annot/ocamldoc/odoc_module.ml b/ocaml-binary-annot/ocamldoc/odoc_module.ml
new file mode 100644
index 0000000000..cc1fe02ca8
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_module.ml
@@ -0,0 +1,535 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Representation and manipulation of modules and module types. *)
+
+let print_DEBUG s = print_string s ; print_newline ()
+
+module Name = Odoc_name
+
+(** To keep the order of elements in a module. *)
+type module_element =
+ Element_module of t_module
+ | Element_module_type of t_module_type
+ | Element_included_module of included_module
+ | Element_class of Odoc_class.t_class
+ | Element_class_type of Odoc_class.t_class_type
+ | Element_value of Odoc_value.t_value
+ | Element_exception of Odoc_exception.t_exception
+ | Element_type of Odoc_type.t_type
+ | Element_module_comment of Odoc_types.text
+
+(** Used where we can reference t_module or t_module_type *)
+and mmt =
+ | Mod of t_module
+ | Modtype of t_module_type
+
+and included_module = {
+ im_name : Name.t ; (** the name of the included module *)
+ mutable im_module : mmt option ; (** the included module or module type *)
+ mutable im_info : Odoc_types.info option ; (** comment associated to the includ directive *)
+ }
+
+and module_alias = {
+ ma_name : Name.t ;
+ mutable ma_module : mmt option ; (** the real module or module type if we could associate it *)
+ }
+
+and module_parameter = {
+ mp_name : string ; (** the name *)
+ mp_type : Types.module_type ; (** the type *)
+ mp_type_code : string ; (** the original code *)
+ mp_kind : module_type_kind ; (** the way the parameter was built *)
+ }
+
+(** Different kinds of module. *)
+and module_kind =
+ | Module_struct of module_element list
+ | Module_alias of module_alias (** complete name and corresponding module if we found it *)
+ | Module_functor of module_parameter * module_kind
+ | Module_apply of module_kind * module_kind
+ | Module_with of module_type_kind * string
+ | Module_constraint of module_kind * module_type_kind
+ | Module_typeof of string (** by now only the code of the module expression *)
+ | Module_unpack of string * module_type_alias (** code of the expression and module type alias *)
+
+(** Representation of a module. *)
+and t_module = {
+ m_name : Name.t ;
+ mutable m_type : Types.module_type ;
+ mutable m_info : Odoc_types.info option ;
+ m_is_interface : bool ; (** true for modules read from interface files *)
+ m_file : string ; (** the file the module is defined in. *)
+ mutable m_kind : module_kind ;
+ mutable m_loc : Odoc_types.location ;
+ mutable m_top_deps : Name.t list ; (** The toplevels module names this module depends on. *)
+ mutable m_code : string option ; (** The whole code of the module *)
+ mutable m_code_intf : string option ; (** The whole code of the interface of the module *)
+ m_text_only : bool ; (** [true] if the module comes from a text file *)
+ }
+
+and module_type_alias = {
+ mta_name : Name.t ;
+ mutable mta_module : t_module_type option ; (** the real module type if we could associate it *)
+ }
+
+(** Different kinds of module type. *)
+and module_type_kind =
+ | Module_type_struct of module_element list
+ | Module_type_functor of module_parameter * module_type_kind
+ | Module_type_alias of module_type_alias (** complete name and corresponding module type if we found it *)
+ | Module_type_with of module_type_kind * string (** the module type kind and the code of the with constraint *)
+ | Module_type_typeof of string (** by now only the code of the module expression *)
+
+(** Representation of a module type. *)
+and t_module_type = {
+ mt_name : Name.t ;
+ mutable mt_info : Odoc_types.info option ;
+ mutable mt_type : Types.module_type option ; (** [None] = abstract module type *)
+ mt_is_interface : bool ; (** true for modules read from interface files *)
+ mt_file : string ; (** the file the module type is defined in. *)
+ mutable mt_kind : module_type_kind option ; (** [None] = abstract module type if mt_type = None ;
+ Always [None] when the module type was extracted from the implementation file. *)
+ mutable mt_loc : Odoc_types.location ;
+ }
+
+
+(** {2 Functions} *)
+
+(** Returns the list of values from a list of module_element. *)
+let values l =
+ List.fold_left
+ (fun acc -> fun ele ->
+ match ele with
+ Element_value v -> acc @ [v]
+ | _ -> acc
+ )
+ []
+ l
+
+(** Returns the list of types from a list of module_element. *)
+let types l =
+ List.fold_left
+ (fun acc -> fun ele ->
+ match ele with
+ Element_type t -> acc @ [t]
+ | _ -> acc
+ )
+ []
+ l
+
+(** Returns the list of exceptions from a list of module_element. *)
+let exceptions l =
+ List.fold_left
+ (fun acc -> fun ele ->
+ match ele with
+ Element_exception e -> acc @ [e]
+ | _ -> acc
+ )
+ []
+ l
+
+(** Returns the list of classes from a list of module_element. *)
+let classes l =
+ List.fold_left
+ (fun acc -> fun ele ->
+ match ele with
+ Element_class c -> acc @ [c]
+ | _ -> acc
+ )
+ []
+ l
+
+(** Returns the list of class types from a list of module_element. *)
+let class_types l =
+ List.fold_left
+ (fun acc -> fun ele ->
+ match ele with
+ Element_class_type ct -> acc @ [ct]
+ | _ -> acc
+ )
+ []
+ l
+
+(** Returns the list of modules from a list of module_element. *)
+let modules l =
+ List.fold_left
+ (fun acc -> fun ele ->
+ match ele with
+ Element_module m -> acc @ [m]
+ | _ -> acc
+ )
+ []
+ l
+
+(** Returns the list of module types from a list of module_element. *)
+let mod_types l =
+ List.fold_left
+ (fun acc -> fun ele ->
+ match ele with
+ Element_module_type mt -> acc @ [mt]
+ | _ -> acc
+ )
+ []
+ l
+
+(** Returns the list of module comment from a list of module_element. *)
+let comments l =
+ List.fold_left
+ (fun acc -> fun ele ->
+ match ele with
+ Element_module_comment t -> acc @ [t]
+ | _ -> acc
+ )
+ []
+ l
+
+(** Returns the list of included modules from a list of module_element. *)
+let included_modules l =
+ List.fold_left
+ (fun acc -> fun ele ->
+ match ele with
+ Element_included_module m -> acc @ [m]
+ | _ -> acc
+ )
+ []
+ l
+
+(** Returns the list of elements of a module.
+ @param trans indicates if, for aliased modules, we must perform a transitive search.*)
+let rec module_elements ?(trans=true) m =
+ let rec iter_kind = function
+ Module_struct l ->
+ print_DEBUG "Odoc_module.module_element: Module_struct";
+ l
+ | Module_alias ma ->
+ print_DEBUG "Odoc_module.module_element: Module_alias";
+ if trans then
+ match ma.ma_module with
+ None -> []
+ | Some (Mod m) -> module_elements m
+ | Some (Modtype mt) -> module_type_elements mt
+ else
+ []
+ | Module_functor (_, k)
+ | Module_apply (k, _) ->
+ print_DEBUG "Odoc_module.module_element: Module_functor ou Module_apply";
+ iter_kind k
+ | Module_with (tk,_) ->
+ print_DEBUG "Odoc_module.module_element: Module_with";
+ module_type_elements ~trans: trans
+ { mt_name = "" ; mt_info = None ; mt_type = None ;
+ mt_is_interface = false ; mt_file = "" ; mt_kind = Some tk ;
+ mt_loc = Odoc_types.dummy_loc ;
+ }
+ | Module_constraint (k, tk) ->
+ print_DEBUG "Odoc_module.module_element: Module_constraint";
+ (* A VOIR : utiliser k ou tk ? *)
+ module_elements ~trans: trans
+ { m_name = "" ;
+ m_info = None ;
+ m_type = Types.Tmty_signature [] ;
+ m_is_interface = false ; m_file = "" ; m_kind = k ;
+ m_loc = Odoc_types.dummy_loc ;
+ m_top_deps = [] ;
+ m_code = None ;
+ m_code_intf = None ;
+ m_text_only = false ;
+ }
+ | Module_typeof _ -> []
+ | Module_unpack _ -> []
+(*
+ module_type_elements ~trans: trans
+ { mt_name = "" ; mt_info = None ; mt_type = None ;
+ mt_is_interface = false ; mt_file = "" ; mt_kind = Some tk ;
+ mt_loc = Odoc_types.dummy_loc }
+*)
+ in
+ iter_kind m.m_kind
+
+(** Returns the list of elements of a module type.
+ @param trans indicates if, for aliased modules, we must perform a transitive search.*)
+and module_type_elements ?(trans=true) mt =
+ let rec iter_kind = function
+ | None -> []
+ | Some (Module_type_struct l) -> l
+ | Some (Module_type_functor (_, k)) -> iter_kind (Some k)
+ | Some (Module_type_with (k, _)) ->
+ if trans then
+ iter_kind (Some k)
+ else
+ []
+ | Some (Module_type_alias mta) ->
+ if trans then
+ match mta.mta_module with
+ None -> []
+ | Some mt -> module_type_elements mt
+ else
+ []
+ | Some (Module_type_typeof _) -> []
+ in
+ iter_kind mt.mt_kind
+
+(** Returns the list of values of a module.
+ @param trans indicates if, for aliased modules, we must perform a transitive search.*)
+let module_values ?(trans=true) m = values (module_elements ~trans m)
+
+(** Returns the list of functional values of a module.
+ @param trans indicates if, for aliased modules, we must perform a transitive search.*)
+let module_functions ?(trans=true) m =
+ List.filter
+ (fun v -> Odoc_value.is_function v)
+ (values (module_elements ~trans m))
+
+(** Returns the list of non-functional values of a module.
+ @param trans indicates if, for aliased modules, we must perform a transitive search.*)
+let module_simple_values ?(trans=true) m =
+ List.filter
+ (fun v -> not (Odoc_value.is_function v))
+ (values (module_elements ~trans m))
+
+(** Returns the list of types of a module.
+ @param trans indicates if, for aliased modules, we must perform a transitive search.*)
+let module_types ?(trans=true) m = types (module_elements ~trans m)
+
+(** Returns the list of excptions of a module.
+ @param trans indicates if, for aliased modules, we must perform a transitive search.*)
+let module_exceptions ?(trans=true) m = exceptions (module_elements ~trans m)
+
+(** Returns the list of classes of a module.
+ @param trans indicates if, for aliased modules, we must perform a transitive search.*)
+let module_classes ?(trans=true) m = classes (module_elements ~trans m)
+
+(** Returns the list of class types of a module.
+ @param trans indicates if, for aliased modules, we must perform a transitive search.*)
+let module_class_types ?(trans=true) m = class_types (module_elements ~trans m)
+
+(** Returns the list of modules of a module.
+ @param trans indicates if, for aliased modules, we must perform a transitive search.*)
+let module_modules ?(trans=true) m = modules (module_elements ~trans m)
+
+(** Returns the list of module types of a module.
+ @param trans indicates if, for aliased modules, we must perform a transitive search.*)
+let module_module_types ?(trans=true) m = mod_types (module_elements ~trans m)
+
+(** Returns the list of included module of a module.
+ @param trans indicates if, for aliased modules, we must perform a transitive search.*)
+let module_included_modules ?(trans=true) m = included_modules (module_elements ~trans m)
+
+(** Returns the list of comments of a module.
+ @param trans indicates if, for aliased modules, we must perform a transitive search.*)
+let module_comments ?(trans=true) m = comments (module_elements ~trans m)
+
+(** Access to the parameters, for a functor type.
+ @param trans indicates if, for aliased modules, we must perform a transitive search.*)
+let rec module_type_parameters ?(trans=true) mt =
+ let rec iter k =
+ match k with
+ Some (Module_type_functor (p, k2)) ->
+ let param =
+ (* we create the couple (parameter, description opt), using
+ the description of the parameter if we can find it in the comment.*)
+ match mt.mt_info with
+ None -> (p, None)
+ | Some i ->
+ try
+ let d = List.assoc p.mp_name i.Odoc_types.i_params in
+ (p, Some d)
+ with
+ Not_found ->
+ (p, None)
+ in
+ param :: (iter (Some k2))
+ | Some (Module_type_alias mta) ->
+ if trans then
+ match mta.mta_module with
+ None -> []
+ | Some mt2 -> module_type_parameters ~trans mt2
+ else
+ []
+ | Some (Module_type_with (k, _)) ->
+ if trans then
+ iter (Some k)
+ else
+ []
+ | Some (Module_type_struct _) ->
+ []
+ | Some (Module_type_typeof _) -> []
+ | None ->
+ []
+ in
+ iter mt.mt_kind
+
+(** Access to the parameters, for a functor.
+ @param trans indicates if, for aliased modules, we must perform a transitive search.*)
+and module_parameters ?(trans=true) m =
+ let rec iter = function
+ Module_functor (p, k) ->
+ let param =
+ (* we create the couple (parameter, description opt), using
+ the description of the parameter if we can find it in the comment.*)
+ match m.m_info with
+ None ->(p, None)
+ | Some i ->
+ try
+ let d = List.assoc p.mp_name i.Odoc_types.i_params in
+ (p, Some d)
+ with
+ Not_found ->
+ (p, None)
+ in
+ param :: (iter k)
+
+ | Module_alias ma ->
+ if trans then
+ match ma.ma_module with
+ None -> []
+ | Some (Mod m) -> module_parameters ~trans m
+ | Some (Modtype mt) -> module_type_parameters ~trans mt
+ else
+ []
+ | Module_constraint (k, tk) ->
+ module_type_parameters ~trans: trans
+ { mt_name = "" ; mt_info = None ; mt_type = None ;
+ mt_is_interface = false ; mt_file = "" ; mt_kind = Some tk ;
+ mt_loc = Odoc_types.dummy_loc }
+ | Module_struct _
+ | Module_apply _
+ | Module_with _
+ | Module_typeof _
+ | Module_unpack _ -> []
+ in
+ iter m.m_kind
+
+(** access to all submodules and sudmobules of submodules ... of the given module.
+ @param trans indicates if, for aliased modules, we must perform a transitive search.*)
+let rec module_all_submodules ?(trans=true) m =
+ let l = module_modules ~trans m in
+ List.fold_left
+ (fun acc -> fun m -> acc @ (module_all_submodules ~trans m))
+ l
+ l
+
+(** The module type is a functor if is defined as a functor or if it is an alias for a functor. *)
+let rec module_type_is_functor mt =
+ let rec iter k =
+ match k with
+ Some (Module_type_functor _) -> true
+ | Some (Module_type_alias mta) ->
+ (
+ match mta.mta_module with
+ None -> false
+ | Some mtyp -> module_type_is_functor mtyp
+ )
+ | Some (Module_type_with (k, _)) ->
+ iter (Some k)
+ | Some (Module_type_struct _)
+ | Some (Module_type_typeof _)
+ | None -> false
+ in
+ iter mt.mt_kind
+
+(** The module is a functor if is defined as a functor or if it is an alias for a functor. *)
+let module_is_functor m =
+ let rec iter = function
+ Module_functor _ -> true
+ | Module_alias ma ->
+ (
+ match ma.ma_module with
+ None -> false
+ | Some (Mod mo) -> iter mo.m_kind
+ | Some (Modtype mt) -> module_type_is_functor mt
+ )
+ | Module_constraint (k, _) ->
+ iter k
+ | _ -> false
+ in
+ iter m.m_kind
+
+(** Returns the list of values of a module type.
+ @param trans indicates if, for aliased modules, we must perform a transitive search.*)
+let module_type_values ?(trans=true) m = values (module_type_elements ~trans m)
+
+(** Returns the list of types of a module.
+ @param trans indicates if, for aliased modules, we must perform a transitive search.*)
+let module_type_types ?(trans=true) m = types (module_type_elements ~trans m)
+
+(** Returns the list of excptions of a module.
+ @param trans indicates if, for aliased modules, we must perform a transitive search.*)
+let module_type_exceptions ?(trans=true) m = exceptions (module_type_elements ~trans m)
+
+(** Returns the list of classes of a module.
+ @param trans indicates if, for aliased modules, we must perform a transitive search.*)
+let module_type_classes ?(trans=true) m = classes (module_type_elements ~trans m)
+
+(** Returns the list of class types of a module.
+ @param trans indicates if, for aliased modules, we must perform a transitive search.*)
+let module_type_class_types ?(trans=true) m = class_types (module_type_elements ~trans m)
+
+(** Returns the list of modules of a module.
+ @param trans indicates if, for aliased modules, we must perform a transitive search.*)
+let module_type_modules ?(trans=true) m = modules (module_type_elements ~trans m)
+
+(** Returns the list of module types of a module.
+ @param trans indicates if, for aliased modules, we must perform a transitive search.*)
+let module_type_module_types ?(trans=true) m = mod_types (module_type_elements ~trans m)
+
+(** Returns the list of included module of a module.
+ @param trans indicates if, for aliased modules, we must perform a transitive search.*)
+let module_type_included_modules ?(trans=true) m = included_modules (module_type_elements ~trans m)
+
+(** Returns the list of comments of a module.
+ @param trans indicates if, for aliased modules, we must perform a transitive search.*)
+let module_type_comments ?(trans=true) m = comments (module_type_elements ~trans m)
+
+(** Returns the list of functional values of a module type.
+ @param trans indicates if, for aliased modules, we must perform a transitive search.*)
+let module_type_functions ?(trans=true) mt =
+ List.filter
+ (fun v -> Odoc_value.is_function v)
+ (values (module_type_elements ~trans mt))
+
+(** Returns the list of non-functional values of a module type.
+ @param trans indicates if, for aliased modules, we must perform a transitive search.*)
+let module_type_simple_values ?(trans=true) mt =
+ List.filter
+ (fun v -> not (Odoc_value.is_function v))
+ (values (module_type_elements ~trans mt))
+
+(** {2 Functions for modules and module types} *)
+
+(** The list of classes defined in this module and all its modules, functors, ....
+ @param trans indicates if, for aliased modules, we must perform a transitive search.*)
+let rec module_all_classes ?(trans=true) m =
+ List.fold_left
+ (fun acc -> fun m -> acc @ (module_all_classes ~trans m))
+ (
+ List.fold_left
+ (fun acc -> fun mtyp -> acc @ (module_type_all_classes ~trans mtyp))
+ (module_classes ~trans m)
+ (module_module_types ~trans m)
+ )
+ (module_modules ~trans m)
+
+(** The list of classes defined in this module type and all its modules, functors, ....
+ @param trans indicates if, for aliased modules, we must perform a transitive search.*)
+and module_type_all_classes ?(trans=true) mt =
+ List.fold_left
+ (fun acc -> fun m -> acc @ (module_all_classes ~trans m))
+ (
+ List.fold_left
+ (fun acc -> fun mtyp -> acc @ (module_type_all_classes ~trans mtyp))
+ (module_type_classes ~trans mt)
+ (module_type_module_types ~trans mt)
+ )
+ (module_type_modules ~trans mt)
diff --git a/ocaml-binary-annot/ocamldoc/odoc_name.ml b/ocaml-binary-annot/ocamldoc/odoc_name.ml
new file mode 100644
index 0000000000..b82cf87458
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_name.ml
@@ -0,0 +1,217 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Representation of element names. *)
+
+let infix_chars = [ '|' ;
+ '<' ;
+ '>' ;
+ '@' ;
+ '^' ;
+ '&' ;
+ '+' ;
+ '-' ;
+ '*' ;
+ '/' ;
+ '$' ;
+ '%' ;
+ '=' ;
+ ':' ;
+ '~' ;
+ '!' ;
+ ]
+
+type t = string
+
+let strip_string s =
+ let len = String.length s in
+ let rec iter_first n =
+ if n >= len then
+ None
+ else
+ match s.[n] with
+ ' ' | '\t' | '\n' | '\r' -> iter_first (n+1)
+ | _ -> Some n
+ in
+ match iter_first 0 with
+ None -> ""
+ | Some first ->
+ let rec iter_last n =
+ if n <= first then
+ None
+ else
+ match s.[n] with
+ ' ' | '\t' | '\n' | '\r' -> iter_last (n-1)
+ | _ -> Some n
+ in
+ match iter_last (len-1) with
+ None -> String.sub s first 1
+ | Some last -> String.sub s first ((last-first)+1)
+
+let parens_if_infix name =
+ match strip_string name with
+ | "" -> ""
+ | s when s.[0] = '*' || s.[String.length s - 1] = '*' -> "( " ^ s ^ " )"
+ | s when List.mem s.[0] infix_chars -> "(" ^ s ^ ")"
+ | "or" | "mod" | "land" | "lor" | "lxor" | "lsl" | "lsr" | "asr" ->
+ "(" ^ name ^ ")"
+ | name -> name
+;;
+
+let cut name =
+ match name with
+ "" -> ("", "")
+ | s ->
+ let len = String.length s in
+ match s.[len-1] with
+ ')' ->
+ (
+ let j = ref 0 in
+ let buf = [|Buffer.create len ; Buffer.create len |] in
+ for i = 0 to len - 1 do
+ match s.[i] with
+ '.' when !j = 0 ->
+ if i < len - 1 then
+ match s.[i+1] with
+ '(' ->
+ j := 1
+ | _ ->
+ Buffer.add_char buf.(!j) '.'
+ else
+ Buffer.add_char buf.(!j) s.[i]
+ | c ->
+ Buffer.add_char buf.(!j) c
+ done;
+ (Buffer.contents buf.(0), Buffer.contents buf.(1))
+ )
+ | _ ->
+ match List.rev (Str.split (Str.regexp_string ".") s) with
+ [] -> ("", "")
+ | h :: q ->
+ (String.concat "." (List.rev q), h)
+
+let simple name = snd (cut name)
+let father name = fst (cut name)
+
+let concat n1 n2 = n1^"."^n2
+
+let normalize_name name =
+ let (p,s) = cut name in
+ let len = String.length s in
+ let s =
+ if len >= 2 &&
+ s.[0] = '(' && s.[len - 1] = ')'
+ then
+ parens_if_infix (strip_string (String.sub s 1 (len - 2)))
+ else
+ s
+ in
+ match p with
+ "" -> s
+ | p -> concat p s
+ ;;
+
+let head_and_tail n =
+ try
+ let pos = String.index n '.' in
+ if pos > 0 then
+ let h = String.sub n 0 pos in
+ try
+ ignore (String.index h '(');
+ (n, "")
+ with
+ Not_found ->
+ let len = String.length n in
+ if pos >= (len - 1) then
+ (h, "")
+ else
+ (h, String.sub n (pos + 1) (len - pos - 1))
+ else
+ (n, "")
+ with
+ Not_found -> (n, "")
+
+let head n = fst (head_and_tail n)
+let tail n = snd (head_and_tail n)
+
+let depth name =
+ try
+ List.length (Str.split (Str.regexp "\\.") name)
+ with
+ _ -> 1
+
+let prefix n1 n2 =
+ (n1 <> n2) &
+ (try
+ let len1 = String.length n1 in
+ ((String.sub n2 0 len1) = n1) &
+ (n2.[len1] = '.')
+ with _ -> false)
+
+let rec get_relative_raw n1 n2 =
+ let (f1,s1) = head_and_tail n1 in
+ let (f2,s2) = head_and_tail n2 in
+ if f1 = f2 then
+ if f2 = s2 or s2 = "" then
+ s2
+ else
+ if f1 = s1 or s1 = "" then
+ s2
+ else
+ get_relative_raw s1 s2
+ else
+ n2
+
+let get_relative n1 n2 =
+ if prefix n1 n2 then
+ let len1 = String.length n1 in
+ try
+ String.sub n2 (len1+1) ((String.length n2) - len1 - 1)
+ with
+ _ -> n2
+ else
+ n2
+
+let hide_given_modules l s =
+ let rec iter = function
+ [] -> s
+ | h :: q ->
+ let s2 = get_relative h s in
+ if s = s2 then
+ iter q
+ else
+ s2
+ in
+ iter l
+
+let qualified name = String.contains name '.'
+
+let from_ident ident = Ident.name ident
+
+
+let from_path path = Path.name path
+
+let to_path n =
+ match
+ List.fold_left
+ (fun acc_opt -> fun s ->
+ match acc_opt with
+ None -> Some (Path.Pident (Ident.create s))
+ | Some acc -> Some (Path.Pdot (acc, s, 0)))
+ None
+ (Str.split (Str.regexp "\\.") n)
+ with
+ None -> raise (Failure "to_path")
+ | Some p -> p
+
+let from_longident = Odoc_misc.string_of_longident
diff --git a/ocaml-binary-annot/ocamldoc/odoc_name.mli b/ocaml-binary-annot/ocamldoc/odoc_name.mli
new file mode 100644
index 0000000000..e3b43a7867
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_name.mli
@@ -0,0 +1,69 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Representation of element names. *)
+
+type t = string
+
+(** Add parenthesis to the given simple name if needed. *)
+val parens_if_infix : t -> t
+
+(** Return a simple name from a name.*)
+val simple : t -> t
+
+(** Return the name of the 'father' (like dirname for a file name).*)
+val father : t -> t
+
+(** Concatenates two names. *)
+val concat : t -> t -> t
+
+(** Normalize the given name by removing the beginning and ending spaces
+ of the simple name and adding parenthesis if needed. *)
+val normalize_name : t -> t
+
+(** Returns the head of a name. *)
+val head : t -> t
+
+(** Returns the depth of the name, i.e. the numer of levels to the root.
+ Example : [Toto.Tutu.name] has depth 3. *)
+val depth : t -> int
+
+(** Returns true if the first name is a prefix of the second name.
+ If the two names are equals, then if is false (strict prefix).*)
+val prefix : t -> t -> bool
+
+(** Take two names n1 and n2 = n3.n4 and return n4 if n3=n1 or else n2. *)
+val get_relative : t -> t -> t
+
+(** Take two names n1=n3.n4 and n2 = n5.n6 and return n6 if n3=n5 or else n2. *)
+val get_relative_raw : t -> t -> t
+
+(** Take a list of module names to hide and a name,
+ and return the name when the module name (or part of it)
+ was removed, according to the list of module names to hide.*)
+val hide_given_modules : t list -> t -> t
+
+(** Indicate if a name if qualified or not. *)
+val qualified : t -> bool
+
+(** Get a name from an [Ident.t]. *)
+val from_ident : Ident.t -> t
+
+(** Get a name from a [Path.t]. *)
+val from_path : Path.t -> t
+
+(** Get a [Path.t] from a name.*)
+val to_path : t -> Path.t
+
+(** Get a name from a [Longident.t].*)
+val from_longident : Longident.t -> t
diff --git a/ocaml-binary-annot/ocamldoc/odoc_ocamlhtml.mll b/ocaml-binary-annot/ocamldoc/odoc_ocamlhtml.mll
new file mode 100644
index 0000000000..6364a900f6
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_ocamlhtml.mll
@@ -0,0 +1,545 @@
+
+{
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Generation of html code to display OCaml code. *)
+open Lexing
+
+exception Fatal_error
+
+let fatal_error msg =
+ prerr_string ">> Fatal error: "; prerr_endline msg; raise Fatal_error
+
+type error =
+ | Illegal_character of char
+ | Unterminated_comment
+ | Unterminated_string
+ | Unterminated_string_in_comment
+ | Keyword_as_label of string
+;;
+
+exception Error of error * int * int
+
+let base_escape_strings = [
+ ("&", "&amp;") ;
+ ("<", "&lt;") ;
+ (">", "&gt;") ;
+]
+
+let pre_escape_strings = [
+ (" ", "&nbsp;") ;
+ ("\n", "<br>\n") ;
+ ("\t", "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;") ;
+ ]
+
+
+let pre = ref false
+let fmt = ref Format.str_formatter
+
+(** Escape the strings which would clash with html syntax,
+ and some other strings if we want to get a PRE style.*)
+let escape s =
+ List.fold_left
+ (fun acc -> fun (s, s2) -> Str.global_replace (Str.regexp s) s2 acc)
+ s
+ (if !pre then base_escape_strings @ pre_escape_strings else base_escape_strings)
+
+(** Escape the strings which would clash with html syntax. *)
+let escape_base s =
+ List.fold_left
+ (fun acc -> fun (s, s2) -> Str.global_replace (Str.regexp s) s2 acc)
+ s
+ base_escape_strings
+
+(** The output functions *)
+
+let print ?(esc=true) s =
+ Format.pp_print_string !fmt (if esc then escape s else s)
+;;
+
+let print_class ?(esc=true) cl s =
+ print ~esc: false ("<span class=\""^cl^"\">"^
+ (if esc then escape s else s)^
+ "</span>")
+;;
+
+(** The table of keywords with colors *)
+let create_hashtable size init =
+ let tbl = Hashtbl.create size in
+ List.iter (fun (key, data) -> Hashtbl.add tbl key data) init;
+ tbl
+
+(** The function used to return html code for the given comment body. *)
+let html_of_comment = ref
+ (fun (s : string) -> "<b>Odoc_ocamlhtml.html_of_comment not initialized</b>")
+
+let keyword_table =
+ create_hashtable 149 [
+ "and", "keyword" ;
+ "as", "keyword" ;
+ "assert", "keyword" ;
+ "begin", "keyword" ;
+ "class", "keyword" ;
+ "constraint", "keyword" ;
+ "do", "keyword" ;
+ "done", "keyword" ;
+ "downto", "keyword" ;
+ "else", "keyword" ;
+ "end", "keyword" ;
+ "exception", "keyword" ;
+ "external", "keyword" ;
+ "false", "keyword" ;
+ "for", "keyword" ;
+ "fun", "keyword" ;
+ "function", "keyword" ;
+ "functor", "keyword" ;
+ "if", "keyword" ;
+ "in", "keyword" ;
+ "include", "keyword" ;
+ "inherit", "keyword" ;
+ "initializer", "keyword" ;
+ "lazy", "keyword" ;
+ "let", "keyword" ;
+ "match", "keyword" ;
+ "method", "keyword" ;
+ "module", "keyword" ;
+ "mutable", "keyword" ;
+ "new", "keyword" ;
+ "object", "keyword" ;
+ "of", "keyword" ;
+ "open", "keyword" ;
+ "or", "keyword" ;
+ "parser", "keyword" ;
+ "private", "keyword" ;
+ "rec", "keyword" ;
+ "sig", "keyword" ;
+ "struct", "keyword" ;
+ "then", "keyword" ;
+ "to", "keyword" ;
+ "true", "keyword" ;
+ "try", "keyword" ;
+ "type", "keyword" ;
+ "val", "keyword" ;
+ "virtual", "keyword" ;
+ "when", "keyword" ;
+ "while", "keyword" ;
+ "with", "keyword" ;
+
+ "mod", "keyword" ;
+ "land", "keyword" ;
+ "lor", "keyword" ;
+ "lxor", "keyword" ;
+ "lsl", "keyword" ;
+ "lsr", "keyword" ;
+ "asr", "keyword" ;
+]
+
+let kwsign_class = "keywordsign"
+let constructor_class = "constructor"
+let comment_class = "comment"
+let string_class = "string"
+let code_class = "code"
+
+
+(** To buffer and print comments *)
+
+
+let margin = ref 0
+
+let comment_buffer = Buffer.create 32
+let reset_comment_buffer () = Buffer.reset comment_buffer
+let store_comment_char = Buffer.add_char comment_buffer
+let add_comment_string = Buffer.add_string comment_buffer
+
+let make_margin () =
+ let rec iter n =
+ if n <= 0 then ""
+ else "&nbsp;"^(iter (n-1))
+ in
+ iter !margin
+
+let print_comment () =
+ let s = Buffer.contents comment_buffer in
+ let len = String.length s in
+ let code =
+ if len < 1 then
+ "<span class=\""^comment_class^"\">(*"^(escape s)^"*)</span>"
+ else
+ match s.[0] with
+ '*' ->
+ (
+ try
+ let html = !html_of_comment (String.sub s 1 (len-1)) in
+ "</code><table><tr><td>"^(make_margin ())^"</td><td>"^
+ "<span class=\""^comment_class^"\">"^
+ "(**"^html^"*)"^
+ "</span></td></tr></table><code class=\""^code_class^"\">"
+ with
+ e ->
+ prerr_endline (Printexc.to_string e);
+ "<span class=\""^comment_class^"\">(*"^(escape s)^"*)</span>"
+ )
+ | _ ->
+ "<span class=\""^comment_class^"\">(*"^(escape s)^"*)</span>"
+ in
+ print ~esc: false code
+
+(** To buffer string literals *)
+
+let string_buffer = Buffer.create 32
+let reset_string_buffer () = Buffer.reset string_buffer
+let store_string_char = Buffer.add_char string_buffer
+let get_stored_string () =
+ let s = Buffer.contents string_buffer in
+ s
+
+(** To translate escape sequences *)
+
+let char_for_backslash = function
+ | 'n' -> '\010'
+ | 'r' -> '\013'
+ | 'b' -> '\008'
+ | 't' -> '\009'
+ | c -> c
+
+let char_for_decimal_code lexbuf i =
+ let c = 100 * (Char.code(Lexing.lexeme_char lexbuf i) - 48) +
+ 10 * (Char.code(Lexing.lexeme_char lexbuf (i+1)) - 48) +
+ (Char.code(Lexing.lexeme_char lexbuf (i+2)) - 48) in
+ Char.chr(c land 0xFF)
+
+let char_for_hexa_code lexbuf i =
+ let c = 16 * (Char.code(Lexing.lexeme_char lexbuf i) - 48) +
+ (Char.code(Lexing.lexeme_char lexbuf (i+1)) - 48) in
+ Char.chr(c land 0xFF)
+
+(** To store the position of the beginning of a string and comment *)
+let string_start_pos = ref 0;;
+let comment_start_pos = ref [];;
+let in_comment () = !comment_start_pos <> [];;
+
+(** Error report *)
+
+open Format
+
+let report_error ppf = function
+ | Illegal_character c ->
+ fprintf ppf "Illegal character (%s)" (Char.escaped c)
+ | Unterminated_comment ->
+ fprintf ppf "Comment not terminated"
+ | Unterminated_string ->
+ fprintf ppf "String literal not terminated"
+ | Unterminated_string_in_comment ->
+ fprintf ppf "This comment contains an unterminated string literal"
+ | Keyword_as_label kwd ->
+ fprintf ppf "`%s' is a keyword, it cannot be used as label name" kwd
+;;
+
+}
+
+let blank = [' ' '\010' '\013' '\009' '\012']
+let lowercase = ['a'-'z' '\223'-'\246' '\248'-'\255' '_']
+let uppercase = ['A'-'Z' '\192'-'\214' '\216'-'\222']
+let identchar =
+ ['A'-'Z' 'a'-'z' '_' '\192'-'\214' '\216'-'\246' '\248'-'\255' '\'' '0'-'9']
+let symbolchar =
+ ['!' '$' '%' '&' '*' '+' '-' '.' '/' ':' '<' '=' '>' '?' '@' '^' '|' '~']
+let decimal_literal = ['0'-'9']+
+let hex_literal = '0' ['x' 'X'] ['0'-'9' 'A'-'F' 'a'-'f']+
+let oct_literal = '0' ['o' 'O'] ['0'-'7']+
+let bin_literal = '0' ['b' 'B'] ['0'-'1']+
+let float_literal =
+ ['0'-'9']+ ('.' ['0'-'9']* )? (['e' 'E'] ['+' '-']? ['0'-'9']+)?
+
+rule token = parse
+ blank
+ {
+ let s = Lexing.lexeme lexbuf in
+ (
+ match s with
+ " " -> incr margin
+ | "\t" -> margin := !margin + 8
+ | "\n" -> margin := 0
+ | _ -> ()
+ );
+ print s;
+ token lexbuf
+ }
+ | "_"
+ { print "_" ; token lexbuf }
+ | "~" { print "~" ; token lexbuf }
+ | "~" lowercase identchar * ':'
+ { let s = Lexing.lexeme lexbuf in
+ let name = String.sub s 1 (String.length s - 2) in
+ if Hashtbl.mem keyword_table name then
+ raise (Error(Keyword_as_label name, Lexing.lexeme_start lexbuf,
+ Lexing.lexeme_end lexbuf));
+ print s ; token lexbuf }
+ | "?" { print "?" ; token lexbuf }
+ | "?" lowercase identchar * ':'
+ { let s = Lexing.lexeme lexbuf in
+ let name = String.sub s 1 (String.length s - 2) in
+ if Hashtbl.mem keyword_table name then
+ raise (Error(Keyword_as_label name, Lexing.lexeme_start lexbuf,
+ Lexing.lexeme_end lexbuf));
+ print s ; token lexbuf }
+ | lowercase identchar *
+ { let s = Lexing.lexeme lexbuf in
+ try
+ let cl = Hashtbl.find keyword_table s in
+ (print_class cl s ; token lexbuf )
+ with Not_found ->
+ (print s ; token lexbuf )}
+ | uppercase identchar *
+ { print_class constructor_class (Lexing.lexeme lexbuf) ; token lexbuf } (* No capitalized keywords *)
+ | decimal_literal | hex_literal | oct_literal | bin_literal
+ { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | float_literal
+ { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | "\""
+ { reset_string_buffer();
+ let string_start = Lexing.lexeme_start lexbuf in
+ string_start_pos := string_start;
+ string lexbuf;
+ lexbuf.Lexing.lex_start_pos <-
+ string_start - lexbuf.Lexing.lex_abs_pos;
+ print_class string_class ("\""^(get_stored_string())^"\"") ;
+ token lexbuf }
+ | "'" [^ '\\' '\''] "'"
+ { print_class string_class (Lexing.lexeme lexbuf) ;
+ token lexbuf }
+ | "'" '\\' ['\\' '\'' 'n' 't' 'b' 'r'] "'"
+ { print_class string_class (Lexing.lexeme lexbuf ) ;
+ token lexbuf }
+ | "'" '\\' ['0'-'9'] ['0'-'9'] ['0'-'9'] "'"
+ { print_class string_class (Lexing.lexeme lexbuf ) ;
+ token lexbuf }
+ | "(*"
+ {
+ reset_comment_buffer ();
+ comment_start_pos := [Lexing.lexeme_start lexbuf];
+ comment lexbuf ;
+ print_comment ();
+ token lexbuf }
+ | "(*)"
+ { reset_comment_buffer ();
+ comment_start_pos := [Lexing.lexeme_start lexbuf];
+ comment lexbuf ;
+ print_comment ();
+ token lexbuf
+ }
+ | "*)"
+ { lexbuf.Lexing.lex_curr_pos <- lexbuf.Lexing.lex_curr_pos - 1;
+ lexbuf.Lexing.lex_curr_p <-
+ { lexbuf.Lexing.lex_curr_p with
+ pos_cnum = lexbuf.Lexing.lex_curr_p.pos_cnum - 1
+ } ;
+ print (Lexing.lexeme lexbuf) ;
+ token lexbuf
+ }
+ | "#" [' ' '\t']* ['0'-'9']+ [^ '\n' '\r'] * ('\n' | '\r' | "\r\n")
+ (* # linenum ... *)
+ {
+ print (Lexing.lexeme lexbuf);
+ token lexbuf
+ }
+ | "#" { print_class kwsign_class (Lexing.lexeme lexbuf) ; token lexbuf }
+ | "&" { print_class kwsign_class (Lexing.lexeme lexbuf) ; token lexbuf }
+ | "&&" { print_class kwsign_class (Lexing.lexeme lexbuf) ; token lexbuf }
+ | "`" { print_class kwsign_class (Lexing.lexeme lexbuf) ; token lexbuf }
+ | "'" { print_class kwsign_class (Lexing.lexeme lexbuf) ; token lexbuf }
+ | "(" { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | ")" { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | "*" { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | "," { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | "??" { print_class kwsign_class (Lexing.lexeme lexbuf) ; token lexbuf }
+ | "->" { print_class kwsign_class (Lexing.lexeme lexbuf) ; token lexbuf }
+ | "." { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | ".." { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | ":" { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | "::" { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | ":=" { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | ":>" { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | ";" { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | ";;" { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | "<" { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | "<-" { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | "=" { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | "[" { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | "[|" { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | "[<" { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | "]" { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | "{" { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | "{<" { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | "|" { print_class kwsign_class (Lexing.lexeme lexbuf) ; token lexbuf }
+ | "||" { print_class kwsign_class (Lexing.lexeme lexbuf) ; token lexbuf }
+ | "|]" { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | ">" { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | ">]" { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | "}" { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | ">}" { print (Lexing.lexeme lexbuf) ; token lexbuf }
+
+ | "!=" { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | "+" { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | "-" { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | "-." { print (Lexing.lexeme lexbuf) ; token lexbuf }
+
+ | "!" symbolchar *
+ { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | ['~' '?'] symbolchar +
+ { print_class kwsign_class (Lexing.lexeme lexbuf) ; token lexbuf }
+ | ['=' '<' '>' '|' '&' '$'] symbolchar *
+ { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | ['@' '^'] symbolchar *
+ { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | ['+' '-'] symbolchar *
+ { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | "**" symbolchar *
+ { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | ['*' '/' '%'] symbolchar *
+ { print (Lexing.lexeme lexbuf) ; token lexbuf }
+ | eof { () }
+ | _
+ { raise (Error(Illegal_character ((Lexing.lexeme lexbuf).[0]),
+ Lexing.lexeme_start lexbuf, Lexing.lexeme_end lexbuf)) }
+
+and comment = parse
+ "(*"
+ { comment_start_pos := Lexing.lexeme_start lexbuf :: !comment_start_pos;
+ store_comment_char '(';
+ store_comment_char '*';
+ comment lexbuf;
+ }
+ | "*)"
+ { match !comment_start_pos with
+ | [] -> assert false
+ | [x] -> comment_start_pos := []
+ | _ :: l ->
+ store_comment_char '*';
+ store_comment_char ')';
+ comment_start_pos := l;
+ comment lexbuf;
+ }
+(* These filters are useless
+ | "\""
+ { reset_string_buffer();
+ string_start_pos := Lexing.lexeme_start lexbuf;
+ store_comment_char '"';
+ begin
+ try string lexbuf; add_comment_string ((get_stored_string()^"\""))
+ with Error (Unterminated_string, _, _) ->
+ let st = List.hd !comment_start_pos in
+ raise (Error (Unterminated_string_in_comment, st, st + 2))
+ end;
+ comment lexbuf }
+ | "'" [^ '\\' '\''] "'"
+ {
+ store_comment_char '\'';
+ store_comment_char (Lexing.lexeme_char lexbuf 1);
+ store_comment_char '\'';
+ comment lexbuf }
+ | "'\\" ['\\' '\'' 'n' 't' 'b' 'r'] "'"
+ {
+ store_comment_char '\'';
+ store_comment_char '\\';
+ store_comment_char(char_for_backslash(Lexing.lexeme_char lexbuf 1)) ;
+ store_comment_char '\'';
+ comment lexbuf }
+ | "\\" ['0'-'9'] ['0'-'9'] ['0'-'9']
+ {
+ store_comment_char(char_for_decimal_code lexbuf 1);
+ comment lexbuf }
+ | "\\x" ['0'-'9' 'A'-'Z' 'a'-'z' ] ['0'-'9' 'A'-'Z' 'a'-'z']
+ {
+ store_comment_char(char_for_hexa_code lexbuf 2);
+ string lexbuf }
+ | "''"
+ {
+ store_comment_char '\'';
+ store_comment_char '\'';
+ comment lexbuf }
+*)
+ | eof
+ { let st = List.hd !comment_start_pos in
+ raise (Error (Unterminated_comment, st, st + 2));
+ }
+ | _
+ { store_comment_char(Lexing.lexeme_char lexbuf 0);
+ comment lexbuf }
+
+and string = parse
+ '"'
+ { () }
+ | '\\' ("\010" | "\013" | "\013\010") [' ' '\009'] *
+ { string lexbuf }
+ | '\\' ['\\' '"' 'n' 't' 'b' 'r' ]
+ { Buffer.add_string string_buffer (Lexing.lexeme lexbuf) ;
+ string lexbuf }
+ | '\\' ['0'-'9'] ['0'-'9'] ['0'-'9']
+ {
+ Buffer.add_string string_buffer (Lexing.lexeme lexbuf) ;
+ string lexbuf
+ }
+ | '\\' 'x' ['0'-'9' 'A'-'Z' 'a'-'z' ] ['0'-'9' 'A'-'Z' 'a'-'z']
+ { Buffer.add_string string_buffer (Lexing.lexeme lexbuf) ;
+ string lexbuf }
+ | eof
+ { raise (Error (Unterminated_string,
+ !string_start_pos, !string_start_pos+1)) }
+ | _
+ { store_string_char(Lexing.lexeme_char lexbuf 0);
+ string lexbuf }
+{
+
+let html_of_code b ?(with_pre=true) code =
+ let old_pre = !pre in
+ let old_margin = !margin in
+ let old_comment_buffer = Buffer.contents comment_buffer in
+ let old_string_buffer = Buffer.contents string_buffer in
+ let buf = Buffer.create 256 in
+ let old_fmt = !fmt in
+ fmt := Format.formatter_of_buffer buf ;
+ pre := with_pre;
+ margin := 0;
+
+ let start = "<code class=\""^code_class^"\">" in
+ let ending = "</code>" in
+ let html =
+ (
+ try
+ print ~esc: false start ;
+ let lexbuf = Lexing.from_string code in
+ let _ = token lexbuf in
+ print ~esc: false ending ;
+ Format.pp_print_flush !fmt () ;
+ Buffer.contents buf
+ with
+ _ ->
+ (* flush str_formatter because we already output
+ something in it *)
+ Format.pp_print_flush !fmt () ;
+ start^code^ending
+ )
+ in
+ pre := old_pre;
+ margin := old_margin ;
+ Buffer.reset comment_buffer;
+ Buffer.add_string comment_buffer old_comment_buffer ;
+ Buffer.reset string_buffer;
+ Buffer.add_string string_buffer old_string_buffer ;
+ fmt := old_fmt ;
+
+ Buffer.add_string b html
+
+}
diff --git a/ocaml-binary-annot/ocamldoc/odoc_parameter.ml b/ocaml-binary-annot/ocamldoc/odoc_parameter.ml
new file mode 100644
index 0000000000..56f175ecd4
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_parameter.ml
@@ -0,0 +1,123 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Representation and manipulation of method / function / class parameters. *)
+
+let print_DEBUG s = print_string s ; print_newline ()
+
+(** Types *)
+
+(** Representation of a simple parameter name *)
+type simple_name = {
+ sn_name : string ;
+ sn_type : Types.type_expr ;
+ mutable sn_text : Odoc_types.text option ;
+ }
+
+(** Representation of parameter names. We need it to represent parameter names in tuples.
+ The value [Tuple ([], t)] stands for an anonymous parameter.*)
+type param_info =
+ | Simple_name of simple_name
+ | Tuple of param_info list * Types.type_expr
+
+(** A parameter is just a param_info.*)
+type parameter = param_info
+
+(** Functions *)
+
+(** acces to the name as a string. For tuples, parenthesis and commas are added. *)
+let complete_name p =
+ let rec iter pi =
+ match pi with
+ Simple_name sn ->
+ sn.sn_name
+ | Tuple ([], _) -> (* anonymous parameter *)
+ "??"
+ | Tuple (pi_list, _) ->
+ "("^(String.concat "," (List.map iter pi_list))^")"
+ in
+ iter p
+
+(** access to the complete type *)
+let typ pi =
+ match pi with
+ Simple_name sn -> sn.sn_type
+ | Tuple (_, typ) -> typ
+
+(** Update the text of a parameter using a function returning
+ the optional text associated to a parameter name.*)
+let update_parameter_text f p =
+ let rec iter pi =
+ match pi with
+ Simple_name sn ->
+ sn.sn_text <- f sn.sn_name
+ | Tuple (l, _) ->
+ List.iter iter l
+ in
+ iter p
+
+(** access to the description of a specific name.
+ @raise Not_found if no description is associated to the given name. *)
+let desc_by_name pi name =
+ let rec iter acc pi =
+ match pi with
+ Simple_name sn ->
+ (sn.sn_name, sn.sn_text) :: acc
+ | Tuple (pi_list, _) ->
+ List.fold_left iter acc pi_list
+ in
+ let l = iter [] pi in
+ List.assoc name l
+
+
+(** acces to the list of names ; only one for a simple parameter, or
+ a list for tuples. *)
+let names pi =
+ let rec iter acc pi =
+ match pi with
+ Simple_name sn ->
+ sn.sn_name :: acc
+ | Tuple (pi_list, _) ->
+ List.fold_left iter acc pi_list
+ in
+ iter [] pi
+
+(** access to the type of a specific name.
+ @raise Not_found if no type is associated to the given name. *)
+let type_by_name pi name =
+ let rec iter acc pi =
+ match pi with
+ Simple_name sn ->
+ (sn.sn_name, sn.sn_type) :: acc
+ | Tuple (pi_list, _) ->
+ List.fold_left iter acc pi_list
+ in
+ let l = iter [] pi in
+ List.assoc name l
+
+(** access to the optional description of a parameter name from an optional info structure.*)
+let desc_from_info_opt info_opt s =
+ print_DEBUG "desc_from_info_opt";
+ match info_opt with
+ None -> None
+ | Some i ->
+ match s with
+ "" -> None
+ | _ ->
+ try
+ Some (List.assoc s i.Odoc_types.i_params)
+ with
+ Not_found ->
+ print_DEBUG ("desc_from_info_opt "^s^" not found in\n");
+ List.iter (fun (s, _) -> print_DEBUG s) i.Odoc_types.i_params;
+ None
diff --git a/ocaml-binary-annot/ocamldoc/odoc_parser.mly b/ocaml-binary-annot/ocamldoc/odoc_parser.mly
new file mode 100644
index 0000000000..e62dcc5515
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_parser.mly
@@ -0,0 +1,176 @@
+%{
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+open Odoc_types
+open Odoc_comments_global
+
+let uppercase = "[A-Z\192-\214\216-\222]"
+let identchar =
+ "[A-Za-z_\192-\214\216-\246\248-\255'0-9]"
+let blank = "[ \010\013\009\012]"
+
+let print_DEBUG s = print_string s; print_newline ()
+%}
+
+%token <string * (string option)> Description
+
+%token <string> See_url
+%token <string> See_file
+%token <string> See_doc
+
+%token T_PARAM
+%token T_AUTHOR
+%token T_VERSION
+%token T_SEE
+%token T_SINCE
+%token T_BEFORE
+%token T_DEPRECATED
+%token T_RAISES
+%token T_RETURN
+%token <string> T_CUSTOM
+
+%token EOF
+
+%token <string> Desc
+
+/* Start Symbols */
+%start main info_part2 see_info
+%type <(string * (string option)) option> main
+%type <unit> info_part2
+%type <Odoc_types.see_ref * string> see_info
+
+
+%%
+see_info:
+ see_ref Desc { ($1, $2) }
+;
+
+see_ref:
+ See_url { Odoc_types.See_url $1 }
+| See_file { Odoc_types.See_file $1 }
+| See_doc { Odoc_types.See_doc $1 }
+;
+
+main:
+ Description { Some $1 }
+| EOF { None }
+;
+
+info_part2:
+ element_list EOF { () }
+;
+
+element_list:
+ element { () }
+| element element_list { () }
+;
+
+element:
+| param { () }
+| author { () }
+| version { () }
+| see { () }
+| since { () }
+| before { () }
+| deprecated { () }
+| raise_exc { () }
+| return { () }
+| custom { () }
+;
+
+param:
+ T_PARAM Desc
+ {
+ (* isolate the identificator *)
+ (* we only look for simple id, no pattern nor tuples *)
+ let s = $2 in
+ match Str.split (Str.regexp (blank^"+")) s with
+ []
+ | _ :: [] ->
+ raise (Failure "usage: @param id description")
+ | id :: _ ->
+ print_DEBUG ("Identificator "^id);
+ let reg = identchar^"+" in
+ print_DEBUG ("reg="^reg);
+ if Str.string_match (Str.regexp reg) id 0 then
+ let remain = String.sub s (String.length id) ((String.length s) - (String.length id)) in
+ print_DEBUG ("T_PARAM Desc remain="^remain);
+ let remain2 = Str.replace_first (Str.regexp ("^"^blank^"+")) "" remain in
+ params := !params @ [(id, remain2)]
+ else
+ raise (Failure (id^" is not a valid parameter identificator in \"@param "^s^"\""))
+ }
+;
+author:
+ T_AUTHOR Desc { authors := !authors @ [ $2 ] }
+;
+version:
+ T_VERSION Desc { version := Some $2 }
+;
+see:
+ T_SEE Desc { sees := !sees @ [$2] }
+;
+since:
+ T_SINCE Desc { since := Some $2 }
+;
+before:
+ T_BEFORE Desc
+ {
+ (* isolate the version name *)
+ let s = $2 in
+ match Str.split (Str.regexp (blank^"+")) s with
+ []
+ | _ :: [] ->
+ raise (Failure "usage: @before version description")
+ | id :: _ ->
+ print_DEBUG ("version "^id);
+ let remain = String.sub s (String.length id) ((String.length s) - (String.length id)) in
+ let remain2 = Str.replace_first (Str.regexp ("^"^blank^"+")) "" remain in
+ before := !before @ [(id, remain2)]
+ }
+;
+deprecated:
+ T_DEPRECATED Desc { deprecated := Some $2 }
+;
+raise_exc:
+ T_RAISES Desc
+ {
+ (* isolate the exception construtor name *)
+ let s = $2 in
+ match Str.split (Str.regexp (blank^"+")) s with
+ []
+ | _ :: [] ->
+ raise (Failure "usage: @raise Exception description")
+ | id :: _ ->
+ print_DEBUG ("exception "^id);
+ let reg = uppercase^identchar^"*"^"\\(\\."^uppercase^identchar^"*\\)*" in
+ print_DEBUG ("reg="^reg);
+ if Str.string_match (Str.regexp reg) id 0 then
+ let remain = String.sub s (String.length id) ((String.length s) - (String.length id)) in
+ let remain2 = Str.replace_first (Str.regexp ("^"^blank^"+")) "" remain in
+ raised_exceptions := !raised_exceptions @ [(id, remain2)]
+ else
+ raise (Failure (id^" is not a valid exception constructor in \"@raise "^s^"\""))
+ }
+;
+return:
+ T_RETURN Desc { return_value := Some $2 }
+;
+
+custom:
+ T_CUSTOM Desc { customs := !customs @ [($1, $2)] }
+;
+
+
+%%
diff --git a/ocaml-binary-annot/ocamldoc/odoc_print.ml b/ocaml-binary-annot/ocamldoc/odoc_print.ml
new file mode 100644
index 0000000000..5cc8e038c7
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_print.ml
@@ -0,0 +1,104 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+open Format
+
+let new_fmt () =
+ let buf = Buffer.create 512 in
+ let fmt = formatter_of_buffer buf in
+ let flush () =
+ pp_print_flush fmt ();
+ let s = Buffer.contents buf in
+ Buffer.reset buf ;
+ s
+ in
+ (fmt, flush)
+
+let (type_fmt, flush_type_fmt) = new_fmt ()
+let _ =
+ let (out, flush, outnewline, outspace) =
+ pp_get_all_formatter_output_functions type_fmt ()
+ in
+ pp_set_all_formatter_output_functions type_fmt
+ ~out ~flush
+ ~newline: (fun () -> out "\n " 0 3)
+ ~spaces: outspace
+
+let (modtype_fmt, flush_modtype_fmt) = new_fmt ()
+
+
+
+
+let string_of_type_expr t =
+ Printtyp.mark_loops t;
+ Printtyp.type_scheme_max ~b_reset_names: false type_fmt t;
+ flush_type_fmt ()
+
+exception Use_code of string
+
+(** Return the given module type where methods and vals have been removed
+ from the signatures. Used when we don't want to print a too long module type.
+ @param code when the code is given, we raise the [Use_code] exception is we
+ encouter a signature, to that the calling function can use the code rather
+ than the "emptied" type.
+*)
+let simpl_module_type ?code t =
+ let rec iter t =
+ match t with
+ Types.Tmty_ident p -> t
+ | Types.Tmty_signature _ ->
+ (
+ match code with
+ None -> Types.Tmty_signature []
+ | Some s -> raise (Use_code s)
+ )
+ | Types.Tmty_functor (id, mt1, mt2) ->
+ Types.Tmty_functor (id, iter mt1, iter mt2)
+ in
+ iter t
+
+let string_of_module_type ?code ?(complete=false) t =
+ try
+ let t2 = if complete then t else simpl_module_type ?code t in
+ Printtyp.modtype modtype_fmt t2;
+ flush_modtype_fmt ()
+ with
+ Use_code s -> s
+
+(** Return the given class type where methods and vals have been removed
+ from the signatures. Used when we don't want to print a too long class type.*)
+let simpl_class_type t =
+ let rec iter t =
+ match t with
+ Types.Tcty_constr (p,texp_list,ct) -> t
+ | Types.Tcty_signature cs ->
+ (* on vire les vals et methods pour ne pas qu'elles soient imprimées
+ quand on affichera le type *)
+ let tnil = { Types.desc = Types.Tnil ; Types.level = 0; Types.id = 0 } in
+ Types.Tcty_signature { Types.cty_self = { cs.Types.cty_self with
+ Types.desc = Types.Tobject (tnil, ref None) };
+ Types.cty_vars = Types.Vars.empty ;
+ Types.cty_concr = Types.Concr.empty ;
+ Types.cty_inher = []
+ }
+ | Types.Tcty_fun (l, texp, ct) ->
+ let new_ct = iter ct in
+ Types.Tcty_fun (l, texp, new_ct)
+ in
+ iter t
+
+let string_of_class_type ?(complete=false) t =
+ let t2 = if complete then t else simpl_class_type t in
+ (* A VOIR : ma propre version de Printtyp.class_type pour ne pas faire reset_names *)
+ Printtyp.class_type modtype_fmt t2;
+ flush_modtype_fmt ()
diff --git a/ocaml-binary-annot/ocamldoc/odoc_print.mli b/ocaml-binary-annot/ocamldoc/odoc_print.mli
new file mode 100644
index 0000000000..01b319c35b
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_print.mli
@@ -0,0 +1,32 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Printing functions. *)
+
+(** This function takes a Types.type_expr and returns a string.
+ It writes in and flushes [Format.str_formatter].*)
+val string_of_type_expr : Types.type_expr -> string
+
+(** This function returns a string representing a [Types.module_type].
+ @param complete indicates if we must print complete signatures
+ or just [sig end]. Default if [false].
+ @param code if [complete = false] and the type contains something else
+ than identificators and functors, then the given code is used.
+*)
+val string_of_module_type : ?code: string -> ?complete: bool -> Types.module_type -> string
+
+(** This function returns a string representing a [Types.class_type].
+ @param complete indicates if we must print complete signatures
+ or just [object end]. Default if [false].
+*)
+val string_of_class_type : ?complete: bool -> Types.class_type -> string
diff --git a/ocaml-binary-annot/ocamldoc/odoc_scan.ml b/ocaml-binary-annot/ocamldoc/odoc_scan.ml
new file mode 100644
index 0000000000..29e1ca2724
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_scan.ml
@@ -0,0 +1,156 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Scanning of modules and elements.
+
+ The class scanner defined in this module can be used to
+ develop generators which perform controls on the elements
+ and their comments.
+*)
+
+open Odoc_types
+
+(** Class which defines the scanning of a list of modules and their
+ elements. Inherit this class to develop your own scanner, by
+ overriding some methods.*)
+class scanner =
+ object (self)
+ (** Scan of 'leaf elements'. *)
+
+ method scan_value (v : Odoc_value.t_value) = ()
+ method scan_type (t : Odoc_type.t_type) = ()
+ method scan_exception (e : Odoc_exception.t_exception) = ()
+ method scan_attribute (a : Odoc_value.t_attribute) = ()
+ method scan_method (m : Odoc_value.t_method) = ()
+ method scan_included_module (im : Odoc_module.included_module) = ()
+
+ (** Scan of a class. *)
+
+ (** Scan of a comment inside a class. *)
+ method scan_class_comment (t : text) = ()
+
+ (** Override this method to perform controls on the class comment
+ and params. This method is called before scanning the class elements.
+ @return true if the class elements must be scanned.*)
+ method scan_class_pre (c : Odoc_class.t_class) = true
+
+ (** This method scan the elements of the given class.
+ A VOIR : scan des classes héritées.*)
+ method scan_class_elements c =
+ List.iter
+ (fun ele ->
+ match ele with
+ Odoc_class.Class_attribute a -> self#scan_attribute a
+ | Odoc_class.Class_method m -> self#scan_method m
+ | Odoc_class.Class_comment t -> self#scan_class_comment t
+ )
+ (Odoc_class.class_elements c)
+
+ (** Scan of a class. Should not be overridden. It calls [scan_class_pre]
+ and if [scan_class_pre] returns [true], then it calls scan_class_elements.*)
+ method scan_class c = if self#scan_class_pre c then self#scan_class_elements c
+
+ (** Scan of a class type. *)
+
+ (** Scan of a comment inside a class type. *)
+ method scan_class_type_comment (t : text) = ()
+
+ (** Override this method to perform controls on the class type comment
+ and form. This method is called before scanning the class type elements.
+ @return true if the class type elements must be scanned.*)
+ method scan_class_type_pre (ct : Odoc_class.t_class_type) = true
+
+ (** This method scan the elements of the given class type.
+ A VOIR : scan des classes héritées.*)
+ method scan_class_type_elements ct =
+ List.iter
+ (fun ele ->
+ match ele with
+ Odoc_class.Class_attribute a -> self#scan_attribute a
+ | Odoc_class.Class_method m -> self#scan_method m
+ | Odoc_class.Class_comment t -> self#scan_class_type_comment t
+ )
+ (Odoc_class.class_type_elements ct)
+
+ (** Scan of a class type. Should not be overridden. It calls [scan_class_type_pre]
+ and if [scan_class_type_pre] returns [true], then it calls scan_class_type_elements.*)
+ method scan_class_type ct = if self#scan_class_type_pre ct then self#scan_class_type_elements ct
+
+ (** Scan of modules. *)
+
+ (** Scan of a comment inside a module. *)
+ method scan_module_comment (t : text) = ()
+
+ (** Override this method to perform controls on the module comment
+ and form. This method is called before scanning the module elements.
+ @return true if the module elements must be scanned.*)
+ method scan_module_pre (m : Odoc_module.t_module) = true
+
+ (** This method scan the elements of the given module. *)
+ method scan_module_elements m =
+ List.iter
+ (fun ele ->
+ match ele with
+ Odoc_module.Element_module m -> self#scan_module m
+ | Odoc_module.Element_module_type mt -> self#scan_module_type mt
+ | Odoc_module.Element_included_module im -> self#scan_included_module im
+ | Odoc_module.Element_class c -> self#scan_class c
+ | Odoc_module.Element_class_type ct -> self#scan_class_type ct
+ | Odoc_module.Element_value v -> self#scan_value v
+ | Odoc_module.Element_exception e -> self#scan_exception e
+ | Odoc_module.Element_type t -> self#scan_type t
+ | Odoc_module.Element_module_comment t -> self#scan_module_comment t
+ )
+ (Odoc_module.module_elements m)
+
+ (** Scan of a module. Should not be overridden. It calls [scan_module_pre]
+ and if [scan_module_pre] returns [true], then it calls scan_module_elements.*)
+ method scan_module m = if self#scan_module_pre m then self#scan_module_elements m
+
+ (** Scan of module types. *)
+
+ (** Scan of a comment inside a module type. *)
+ method scan_module_type_comment (t : text) = ()
+
+ (** Override this method to perform controls on the module type comment
+ and form. This method is called before scanning the module type elements.
+ @return true if the module type elements must be scanned. *)
+ method scan_module_type_pre (mt : Odoc_module.t_module_type) = true
+
+ (** This method scan the elements of the given module type. *)
+ method scan_module_type_elements mt =
+ List.iter
+ (fun ele ->
+ match ele with
+ Odoc_module.Element_module m -> self#scan_module m
+ | Odoc_module.Element_module_type mt -> self#scan_module_type mt
+ | Odoc_module.Element_included_module im -> self#scan_included_module im
+ | Odoc_module.Element_class c -> self#scan_class c
+ | Odoc_module.Element_class_type ct -> self#scan_class_type ct
+ | Odoc_module.Element_value v -> self#scan_value v
+ | Odoc_module.Element_exception e -> self#scan_exception e
+ | Odoc_module.Element_type t -> self#scan_type t
+ | Odoc_module.Element_module_comment t -> self#scan_module_comment t
+ )
+ (Odoc_module.module_type_elements mt)
+
+ (** Scan of a module type. Should not be overridden. It calls [scan_module_type_pre]
+ and if [scan_module_type_pre] returns [true], then it calls scan_module_type_elements.*)
+ method scan_module_type mt =
+ if self#scan_module_type_pre mt then self#scan_module_type_elements mt
+
+ (** Main scanning method. *)
+
+ (** Scan a list of modules. *)
+ method scan_module_list l = List.iter self#scan_module l
+ end
diff --git a/ocaml-binary-annot/ocamldoc/odoc_search.ml b/ocaml-binary-annot/ocamldoc/odoc_search.ml
new file mode 100644
index 0000000000..65d602d3b9
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_search.ml
@@ -0,0 +1,636 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Research of elements through modules. *)
+
+module Name = Odoc_name
+open Odoc_parameter
+open Odoc_value
+open Odoc_type
+open Odoc_exception
+open Odoc_class
+open Odoc_module
+
+type result_element =
+ Res_module of t_module
+ | Res_module_type of t_module_type
+ | Res_class of t_class
+ | Res_class_type of t_class_type
+ | Res_value of t_value
+ | Res_type of t_type
+ | Res_exception of t_exception
+ | Res_attribute of t_attribute
+ | Res_method of t_method
+ | Res_section of string * Odoc_types.text
+
+type result = result_element list
+
+module type Predicates =
+ sig
+ type t
+ val p_module : t_module -> t -> bool * bool
+ val p_module_type : t_module_type -> t -> bool * bool
+ val p_class : t_class -> t -> bool * bool
+ val p_class_type : t_class_type -> t -> bool * bool
+ val p_value : t_value -> t -> bool
+ val p_type : t_type -> t -> bool
+ val p_exception : t_exception -> t -> bool
+ val p_attribute : t_attribute -> t -> bool
+ val p_method : t_method -> t -> bool
+ val p_section : string -> t -> bool
+ end
+
+module Search =
+ functor (P : Predicates) ->
+ struct
+ let search_section t s v = if P.p_section s v then [Res_section (s,t)] else []
+
+ let rec search_text root t v =
+ List.flatten (List.map (fun e -> search_text_ele root e v) t)
+
+ and search_text_ele root e v =
+ let module T = Odoc_types in
+ match e with
+ | T.Raw _
+ | T.Code _
+ | T.CodePre _
+ | T.Latex _
+ | T.Verbatim _
+ | T.Ref (_, _, _) -> []
+ | T.Bold t
+ | T.Italic t
+ | T.Center t
+ | T.Left t
+ | T.Right t
+ | T.Emphasize t
+ | T.Block t
+ | T.Superscript t
+ | T.Subscript t
+ | T.Custom (_,t)
+ | T.Link (_, t) -> search_text root t v
+ | T.List l
+ | T.Enum l -> List.flatten (List.map (fun t -> search_text root t v) l)
+ | T.Newline
+ | T.Module_list _
+ | T.Index_list -> []
+ | T.Target _ -> []
+ | T.Title (n, l_opt, t) ->
+ (match l_opt with
+ None -> []
+ | Some s -> search_section t (Name.concat root s) v) @
+ (search_text root t v)
+
+ let search_value va v = if P.p_value va v then [Res_value va] else []
+
+ let search_type t v = if P.p_type t v then [Res_type t] else []
+
+ let search_exception e v = if P.p_exception e v then [Res_exception e] else []
+
+ let search_attribute a v = if P.p_attribute a v then [Res_attribute a] else []
+
+ let search_method m v = if P.p_method m v then [Res_method m] else []
+
+ let search_class c v =
+ let (go_deeper, ok) = P.p_class c v in
+ let l =
+ if go_deeper then
+ let res_att =
+ List.fold_left
+ (fun acc -> fun att -> acc @ (search_attribute att v))
+ []
+ (Odoc_class.class_attributes c)
+ in
+ let res_met =
+ List.fold_left
+ (fun acc -> fun m -> acc @ (search_method m v))
+ []
+ (Odoc_class.class_methods c)
+ in
+ let res_sec =
+ List.fold_left
+ (fun acc -> fun t -> acc @ (search_text c.cl_name t v))
+ []
+ (Odoc_class.class_comments c)
+ in
+ let l = res_att @ res_met @ res_sec in
+ l
+ else
+ []
+ in
+ if ok then
+ (Res_class c) :: l
+ else
+ l
+
+ let search_class_type ct v =
+ let (go_deeper, ok) = P.p_class_type ct v in
+ let l =
+ if go_deeper then
+ let res_att =
+ List.fold_left
+ (fun acc -> fun att -> acc @ (search_attribute att v))
+ []
+ (Odoc_class.class_type_attributes ct)
+ in
+ let res_met =
+ List.fold_left
+ (fun acc -> fun m -> acc @ (search_method m v))
+ []
+ (Odoc_class.class_type_methods ct)
+ in
+ let res_sec =
+ List.fold_left
+ (fun acc -> fun t -> acc @ (search_text ct.clt_name t v))
+ []
+ (Odoc_class.class_type_comments ct)
+ in
+ let l = res_att @ res_met @ res_sec in
+ l
+ else
+ []
+ in
+ if ok then
+ (Res_class_type ct) :: l
+ else
+ l
+
+ let rec search_module_type mt v =
+ let (go_deeper, ok) = P.p_module_type mt v in
+ let l =
+ if go_deeper then
+ let res_val =
+ List.fold_left
+ (fun acc -> fun va -> acc @ (search_value va v))
+ []
+ (Odoc_module.module_type_values mt)
+ in
+ let res_typ =
+ List.fold_left
+ (fun acc -> fun t -> acc @ (search_type t v))
+ []
+ (Odoc_module.module_type_types mt)
+ in
+ let res_exc =
+ List.fold_left
+ (fun acc -> fun e -> acc @ (search_exception e v))
+ []
+ (Odoc_module.module_type_exceptions mt)
+ in
+ let res_mod = search (Odoc_module.module_type_modules mt) v in
+ let res_modtyp =
+ List.fold_left
+ (fun acc -> fun mt -> acc @ (search_module_type mt v))
+ []
+ (Odoc_module.module_type_module_types mt)
+ in
+ let res_cl =
+ List.fold_left
+ (fun acc -> fun cl -> acc @ (search_class cl v))
+ []
+ (Odoc_module.module_type_classes mt)
+ in
+ let res_cltyp =
+ List.fold_left
+ (fun acc -> fun clt -> acc @ (search_class_type clt v))
+ []
+ (Odoc_module.module_type_class_types mt)
+ in
+ let res_sec =
+ List.fold_left
+ (fun acc -> fun t -> acc @ (search_text mt.mt_name t v))
+ []
+ (Odoc_module.module_type_comments mt)
+ in
+ let l = res_val @ res_typ @ res_exc @ res_mod @
+ res_modtyp @ res_cl @ res_cltyp @ res_sec
+ in
+ l
+ else
+ []
+ in
+ if ok then
+ (Res_module_type mt) :: l
+ else
+ l
+
+ and search_module m v =
+ let (go_deeper, ok) = P.p_module m v in
+ let l =
+ if go_deeper then
+ let res_val =
+ List.fold_left
+ (fun acc -> fun va -> acc @ (search_value va v))
+ []
+ (Odoc_module.module_values m)
+ in
+ let res_typ =
+ List.fold_left
+ (fun acc -> fun t -> acc @ (search_type t v))
+ []
+ (Odoc_module.module_types m)
+ in
+ let res_exc =
+ List.fold_left
+ (fun acc -> fun e -> acc @ (search_exception e v))
+ []
+ (Odoc_module.module_exceptions m)
+ in
+ let res_mod = search (Odoc_module.module_modules m) v in
+ let res_modtyp =
+ List.fold_left
+ (fun acc -> fun mt -> acc @ (search_module_type mt v))
+ []
+ (Odoc_module.module_module_types m)
+ in
+ let res_cl =
+ List.fold_left
+ (fun acc -> fun cl -> acc @ (search_class cl v))
+ []
+ (Odoc_module.module_classes m)
+ in
+ let res_cltyp =
+ List.fold_left
+ (fun acc -> fun clt -> acc @ (search_class_type clt v))
+ []
+ (Odoc_module.module_class_types m)
+ in
+ let res_sec =
+ List.fold_left
+ (fun acc -> fun t -> acc @ (search_text m.m_name t v))
+ []
+ (Odoc_module.module_comments m)
+ in
+ let l = res_val @ res_typ @ res_exc @ res_mod @
+ res_modtyp @ res_cl @ res_cltyp @ res_sec
+ in
+ l
+ else
+ []
+ in
+ if ok then
+ (Res_module m) :: l
+ else
+ l
+
+ and search module_list v =
+ List.fold_left
+ (fun acc -> fun m ->
+ List.fold_left
+ (fun acc2 -> fun ele ->
+ if List.mem ele acc2 then acc2 else acc2 @ [ele]
+ )
+ acc
+ (search_module m v)
+ )
+ []
+ module_list
+ end
+
+module P_name =
+ struct
+ type t = Str.regexp
+ let (=~) name regexp = Str.string_match regexp name 0
+ let p_module m r = (true, m.m_name =~ r)
+ let p_module_type mt r = (true, mt.mt_name =~ r)
+ let p_class c r = (true, c.cl_name =~ r)
+ let p_class_type ct r = (true, ct.clt_name =~ r)
+ let p_value v r = v.val_name =~ r
+ let p_type t r = t.ty_name =~ r
+ let p_exception e r = e.ex_name =~ r
+ let p_attribute a r = a.att_value.val_name =~ r
+ let p_method m r = m.met_value.val_name =~ r
+ let p_section s r = s =~ r
+ end
+
+module Search_by_name = Search ( P_name )
+
+module P_values =
+ struct
+ type t = unit
+ let p_module _ _ = (true, false)
+ let p_module_type _ _ = (true, false)
+ let p_class _ _ = (false, false)
+ let p_class_type _ _ = (false, false)
+ let p_value _ _ = true
+ let p_type _ _ = false
+ let p_exception _ _ = false
+ let p_attribute _ _ = false
+ let p_method _ _ = false
+ let p_section _ _ = false
+ end
+module Search_values = Search ( P_values )
+let values l =
+ let l_ele = Search_values.search l () in
+ let p v1 v2 = v1.val_name = v2.val_name in
+ let rec iter acc = function
+ (Res_value v) :: q -> if List.exists (p v) acc then iter acc q else iter (v :: acc) q
+ | _ :: q -> iter acc q
+ | [] -> acc
+ in
+ iter [] l_ele
+
+module P_exceptions =
+ struct
+ type t = unit
+ let p_module _ _ = (true, false)
+ let p_module_type _ _ = (true, false)
+ let p_class _ _ = (false, false)
+ let p_class_type _ _ = (false, false)
+ let p_value _ _ = false
+ let p_type _ _ = false
+ let p_exception _ _ = true
+ let p_attribute _ _ = false
+ let p_method _ _ = false
+ let p_section _ _ = false
+ end
+module Search_exceptions = Search ( P_exceptions )
+let exceptions l =
+ let l_ele = Search_exceptions.search l () in
+ let p e1 e2 = e1.ex_name = e2.ex_name in
+ let rec iter acc = function
+ (Res_exception t) :: q -> if List.exists (p t) acc then iter acc q else iter (t :: acc) q
+ | _ :: q -> iter acc q
+ | [] -> acc
+ in
+ iter [] l_ele
+
+module P_types =
+ struct
+ type t = unit
+ let p_module _ _ = (true, false)
+ let p_module_type _ _ = (true, false)
+ let p_class _ _ = (false, false)
+ let p_class_type _ _ = (false, false)
+ let p_value _ _ = false
+ let p_type _ _ = true
+ let p_exception _ _ = false
+ let p_attribute _ _ = false
+ let p_method _ _ = false
+ let p_section _ _ = false
+ end
+module Search_types = Search ( P_types )
+let types l =
+ let l_ele = Search_types.search l () in
+ let p t1 t2 = t1.ty_name = t2.ty_name in
+ let rec iter acc = function
+ (Res_type t) :: q -> if List.exists (p t) acc then iter acc q else iter (t :: acc) q
+ | _ :: q -> iter acc q
+ | [] -> acc
+ in
+ iter [] l_ele
+
+module P_attributes =
+ struct
+ type t = unit
+ let p_module _ _ = (true, false)
+ let p_module_type _ _ = (true, false)
+ let p_class _ _ = (true, false)
+ let p_class_type _ _ = (true, false)
+ let p_value _ _ = false
+ let p_type _ _ = false
+ let p_exception _ _ = false
+ let p_attribute _ _ = true
+ let p_method _ _ = false
+ let p_section _ _ = false
+ end
+module Search_attributes = Search ( P_attributes )
+let attributes l =
+ let l_ele = Search_attributes.search l () in
+ let p a1 a2 = a1.att_value.val_name = a2.att_value.val_name in
+ let rec iter acc = function
+ (Res_attribute t) :: q -> if List.exists (p t) acc then iter acc q else iter (t :: acc) q
+ | _ :: q -> iter acc q
+ | [] -> acc
+ in
+ iter [] l_ele
+
+module P_methods =
+ struct
+ type t = unit
+ let p_module _ _ = (true, false)
+ let p_module_type _ _ = (true, false)
+ let p_class _ _ = (true, false)
+ let p_class_type _ _ = (true, false)
+ let p_value _ _ = false
+ let p_type _ _ = false
+ let p_exception _ _ = false
+ let p_attribute _ _ = false
+ let p_method _ _ = true
+ let p_section _ _ = true
+ end
+module Search_methods = Search ( P_methods )
+let methods l =
+ let l_ele = Search_methods.search l () in
+ let p m1 m2 = m1.met_value.val_name = m2.met_value.val_name in
+ let rec iter acc = function
+ (Res_method t) :: q -> if List.exists (p t) acc then iter acc q else iter (t :: acc) q
+ | _ :: q -> iter acc q
+ | [] -> acc
+ in
+ iter [] l_ele
+
+module P_classes =
+ struct
+ type t = unit
+ let p_module _ _ = (true, false)
+ let p_module_type _ _ = (true, false)
+ let p_class _ _ = (false, true)
+ let p_class_type _ _ = (false, false)
+ let p_value _ _ = false
+ let p_type _ _ = false
+ let p_exception _ _ = false
+ let p_attribute _ _ = false
+ let p_method _ _ = false
+ let p_section _ _ = false
+ end
+module Search_classes = Search ( P_classes )
+let classes l =
+ let l_ele = Search_classes.search l () in
+ let p c1 c2 = c1.cl_name = c2.cl_name in
+ let rec iter acc = function
+ (Res_class c) :: q -> if List.exists (p c) acc then iter acc q else iter (c :: acc) q
+ | _ :: q -> iter acc q
+ | [] -> acc
+ in
+ iter [] l_ele
+
+module P_class_types =
+ struct
+ type t = unit
+ let p_module _ _ = (true, false)
+ let p_module_type _ _ = (true, false)
+ let p_class _ _ = (false, false)
+ let p_class_type _ _ = (false, true)
+ let p_value _ _ = false
+ let p_type _ _ = false
+ let p_exception _ _ = false
+ let p_attribute _ _ = false
+ let p_method _ _ = false
+ let p_section _ _ = false
+ end
+module Search_class_types = Search ( P_class_types )
+let class_types l =
+ let l_ele = Search_class_types.search l () in
+ let p c1 c2 = c1.clt_name = c2.clt_name in
+ let rec iter acc = function
+ (Res_class_type c) :: q -> if List.exists (p c) acc then iter acc q else iter (c :: acc) q
+ | _ :: q -> iter acc q
+ | [] -> acc
+ in
+ iter [] l_ele
+
+module P_modules =
+ struct
+ type t = unit
+ let p_module _ _ = (true, true)
+ let p_module_type _ _ = (true, false)
+ let p_class _ _ = (false, false)
+ let p_class_type _ _ = (false, false)
+ let p_value _ _ = false
+ let p_type _ _ = false
+ let p_exception _ _ = false
+ let p_attribute _ _ = false
+ let p_method _ _ = false
+ let p_section _ _ = false
+ end
+module Search_modules = Search ( P_modules )
+let modules l =
+ let l_ele = Search_modules.search l () in
+ let p m1 m2 = m1.m_name = m2.m_name in
+ let rec iter acc = function
+ (Res_module m) :: q -> if List.exists (p m) acc then iter acc q else iter (m :: acc) q
+ | _ :: q -> iter acc q
+ | [] -> acc
+ in
+ iter [] l_ele
+
+module P_module_types =
+ struct
+ type t = unit
+ let p_module _ _ = (true, false)
+ let p_module_type _ _ = (true, true)
+ let p_class _ _ = (false, false)
+ let p_class_type _ _ = (false, false)
+ let p_value _ _ = false
+ let p_type _ _ = false
+ let p_exception _ _ = false
+ let p_attribute _ _ = false
+ let p_method _ _ = false
+ let p_section _ _ = false
+ end
+module Search_module_types = Search ( P_module_types )
+let module_types l =
+ let l_ele = Search_module_types.search l () in
+ let p m1 m2 = m1.mt_name = m2.mt_name in
+ let rec iter acc = function
+ (Res_module_type m) :: q -> if List.exists (p m) acc then iter acc q else iter (m :: acc) q
+ | _ :: q -> iter acc q
+ | [] -> acc
+ in
+ iter [] l_ele
+
+let type_exists mods regexp =
+ let l = Search_by_name.search mods regexp in
+ List.exists
+ (function
+ Res_type _ -> true
+ | _ -> false
+ )
+ l
+
+let value_exists mods regexp =
+ let l = Search_by_name.search mods regexp in
+ List.exists
+ (function
+ Res_value _ -> true
+ | _ -> false
+ )
+ l
+
+let class_exists mods regexp =
+ let l = Search_by_name.search mods regexp in
+ List.exists
+ (function
+ Res_class _ -> true
+ | _ -> false
+ )
+ l
+
+let class_type_exists mods regexp =
+ let l = Search_by_name.search mods regexp in
+ List.exists
+ (function
+ Res_class_type _ -> true
+ | _ -> false
+ )
+ l
+
+let module_exists mods regexp =
+ let l = Search_by_name.search mods regexp in
+ List.exists
+ (function
+ Res_module _ -> true
+ | _ -> false
+ )
+ l
+
+let module_type_exists mods regexp =
+ let l = Search_by_name.search mods regexp in
+ List.exists
+ (function
+ Res_module_type _ -> true
+ | _ -> false
+ )
+ l
+
+let exception_exists mods regexp =
+ let l = Search_by_name.search mods regexp in
+ List.exists
+ (function
+ Res_exception _ -> true
+ | _ -> false
+ )
+ l
+
+let attribute_exists mods regexp =
+ let l = Search_by_name.search mods regexp in
+ List.exists
+ (function
+ Res_attribute _ -> true
+ | _ -> false
+ )
+ l
+
+let method_exists mods regexp =
+ let l = Search_by_name.search mods regexp in
+ List.exists
+ (function
+ Res_method _ -> true
+ | _ -> false
+ )
+ l
+
+let find_section mods regexp =
+ let l = Search_by_name.search mods regexp in
+ match
+ List.find
+ (function
+ Res_section _ -> true
+ | _ -> false
+ )
+ l
+ with
+ Res_section (_,t) -> t
+ | _ -> assert false
+
+(* eof $Id$ *)
diff --git a/ocaml-binary-annot/ocamldoc/odoc_search.mli b/ocaml-binary-annot/ocamldoc/odoc_search.mli
new file mode 100644
index 0000000000..d7ace5831a
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_search.mli
@@ -0,0 +1,199 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Research of elements through modules. *)
+
+(** The type for an element of the result of a research. *)
+type result_element =
+ Res_module of Odoc_module.t_module
+ | Res_module_type of Odoc_module.t_module_type
+ | Res_class of Odoc_class.t_class
+ | Res_class_type of Odoc_class.t_class_type
+ | Res_value of Odoc_value.t_value
+ | Res_type of Odoc_type.t_type
+ | Res_exception of Odoc_exception.t_exception
+ | Res_attribute of Odoc_value.t_attribute
+ | Res_method of Odoc_value.t_method
+ | Res_section of string * Odoc_types.text
+
+(** The type representing a research result.*)
+type result = result_element list
+
+(** The type of modules which contain the predicates used during the research.
+ Some functions return a couple of booleans ; the first indicates if we
+ must go deeper in the analysed element, the second if the element satisfies
+ the predicate.
+*)
+module type Predicates =
+ sig
+ type t
+ val p_module : Odoc_module.t_module -> t -> bool * bool
+ val p_module_type : Odoc_module.t_module_type -> t -> bool * bool
+ val p_class : Odoc_class.t_class -> t -> bool * bool
+ val p_class_type : Odoc_class.t_class_type -> t -> bool * bool
+ val p_value : Odoc_value.t_value -> t -> bool
+ val p_type : Odoc_type.t_type -> t -> bool
+ val p_exception : Odoc_exception.t_exception -> t -> bool
+ val p_attribute : Odoc_value.t_attribute -> t -> bool
+ val p_method : Odoc_value.t_method -> t -> bool
+ val p_section : string -> t -> bool
+ end
+
+(** Search for elements verifying the predicates in the module in parameter.*)
+module Search :
+ functor (P : Predicates) ->
+ sig
+ (** search in a section title *)
+ val search_section : Odoc_types.text -> string -> P.t -> result_element list
+
+ (** search in a value *)
+ val search_value : Odoc_value.t_value -> P.t -> result_element list
+
+ (** search in a type *)
+ val search_type : Odoc_type.t_type -> P.t -> result_element list
+
+ (** search in an exception *)
+ val search_exception :
+ Odoc_exception.t_exception -> P.t -> result_element list
+
+ (** search in an attribute *)
+ val search_attribute :
+ Odoc_value.t_attribute -> P.t -> result_element list
+
+ (** search in a method *)
+ val search_method : Odoc_value.t_method -> P.t -> result_element list
+
+ (** search in a class *)
+ val search_class : Odoc_class.t_class -> P.t -> result_element list
+
+ (** search in a class type *)
+ val search_class_type :
+ Odoc_class.t_class_type -> P.t -> result_element list
+
+ (** search in a module type *)
+ val search_module_type :
+ Odoc_module.t_module_type -> P.t -> result_element list
+
+ (** search in a module *)
+ val search_module : Odoc_module.t_module -> P.t -> result_element list
+
+ (** search in a list of modules *)
+ val search : Odoc_module.t_module list -> P.t -> result_element list
+ end
+
+(** A module of predicates to search elements by name (and accepting regexps).*)
+module P_name :
+ sig
+ type t = Str.regexp
+ val ( =~ ) : string -> Str.regexp -> bool
+ val p_module : Odoc_module.t_module -> Str.regexp -> bool * bool
+ val p_module_type :
+ Odoc_module.t_module_type -> Str.regexp -> bool * bool
+ val p_class : Odoc_class.t_class -> Str.regexp -> bool * bool
+ val p_class_type : Odoc_class.t_class_type -> Str.regexp -> bool * bool
+ val p_value : Odoc_value.t_value -> Str.regexp -> bool
+ val p_type : Odoc_type.t_type -> Str.regexp -> bool
+ val p_exception : Odoc_exception.t_exception -> Str.regexp -> bool
+ val p_attribute : Odoc_value.t_attribute -> Str.regexp -> bool
+ val p_method : Odoc_value.t_method -> Str.regexp -> bool
+ end
+
+(** A module to search elements by name. *)
+module Search_by_name :
+ sig
+ val search_section : Odoc_types.text -> string -> P_name.t -> result_element list
+ val search_value : Odoc_value.t_value -> P_name.t -> result_element list
+ val search_type : Odoc_type.t_type -> P_name.t -> result_element list
+ val search_exception :
+ Odoc_exception.t_exception -> P_name.t -> result_element list
+ val search_attribute :
+ Odoc_value.t_attribute -> P_name.t -> result_element list
+ val search_method :
+ Odoc_value.t_method -> P_name.t -> result_element list
+ val search_class : Odoc_class.t_class -> P_name.t -> result_element list
+ val search_class_type :
+ Odoc_class.t_class_type -> P_name.t -> result_element list
+ val search_module_type :
+ Odoc_module.t_module_type -> P_name.t -> result_element list
+ val search_module :
+ Odoc_module.t_module -> P_name.t -> result_element list
+ val search : Odoc_module.t_module list -> P_name.t -> result_element list
+ end
+
+(** A function to search all the values in a list of modules. *)
+val values : Odoc_module.t_module list -> Odoc_value.t_value list
+
+(** A function to search all the exceptions in a list of modules. *)
+val exceptions : Odoc_module.t_module list -> Odoc_exception.t_exception list
+
+(** A function to search all the types in a list of modules. *)
+val types : Odoc_module.t_module list -> Odoc_type.t_type list
+
+(** A function to search all the class attributes in a list of modules. *)
+val attributes : Odoc_module.t_module list -> Odoc_value.t_attribute list
+
+(** A function to search all the class methods in a list of modules. *)
+val methods : Odoc_module.t_module list -> Odoc_value.t_method list
+
+(** A function to search all the classes in a list of modules. *)
+val classes : Odoc_module.t_module list -> Odoc_class.t_class list
+
+(** A function to search all the class types in a list of modules. *)
+val class_types : Odoc_module.t_module list -> Odoc_class.t_class_type list
+
+(** A function to search all the modules in a list of modules. *)
+val modules : Odoc_module.t_module list -> Odoc_module.t_module list
+
+(** A function to search all the module types in a list of modules. *)
+val module_types : Odoc_module.t_module list -> Odoc_module.t_module_type list
+
+(** Return [true] if a type with the given complete name (regexp) exists
+ in the given module list.*)
+val type_exists : Odoc_module.t_module list -> Str.regexp -> bool
+
+(** Return [true] if a value with the given complete name (regexp) exists
+ in the given module list.*)
+val value_exists : Odoc_module.t_module list -> Str.regexp -> bool
+
+(** Return [true] if a module with the given complete name (regexp) exists
+ in the given module list.*)
+val module_exists : Odoc_module.t_module list -> Str.regexp -> bool
+
+(** Return [true] if a module type with the given complete name (regexp) exists
+ in the given module list.*)
+val module_type_exists : Odoc_module.t_module list -> Str.regexp -> bool
+
+(** Return [true] if a class with the given complete name (regexp) exists
+ in the given module list.*)
+val class_exists : Odoc_module.t_module list -> Str.regexp -> bool
+
+(** Return [true] if a class type with the given complete name (regexp) exists
+ in the given module list.*)
+val class_type_exists : Odoc_module.t_module list -> Str.regexp -> bool
+
+(** Return [true] if a exception with the given complete name (regexp) exists
+ in the given module list.*)
+val exception_exists : Odoc_module.t_module list -> Str.regexp -> bool
+
+(** Return [true] if an attribute with the given complete name (regexp) exists
+ in the given module list.*)
+val attribute_exists : Odoc_module.t_module list -> Str.regexp -> bool
+
+(** Return [true] if a method with the given complete name (regexp) exists
+ in the given module list.*)
+val method_exists : Odoc_module.t_module list -> Str.regexp -> bool
+
+(** Return the [text] of the section with the given complete name (regexp)
+ in the given module list.
+ @raise Not_found if the section was not found.*)
+val find_section : Odoc_module.t_module list -> Str.regexp -> Odoc_types.text
diff --git a/ocaml-binary-annot/ocamldoc/odoc_see_lexer.mll b/ocaml-binary-annot/ocamldoc/odoc_see_lexer.mll
new file mode 100644
index 0000000000..b0570f7832
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_see_lexer.mll
@@ -0,0 +1,102 @@
+{
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+let print_DEBUG2 s = print_string s ; print_newline ()
+
+(** the lexer for special comments. *)
+
+open Lexing
+open Odoc_parser
+
+let buf = Buffer.create 32
+
+}
+
+rule main = parse
+ [' ' '\013' '\009' '\012'] +
+ {
+ print_DEBUG2 "[' ' '\013' '\009' '\012'] +";
+ main lexbuf
+ }
+
+ | [ '\010' ]
+ {
+ print_DEBUG2 " [ '\010' ] ";
+ main lexbuf
+ }
+
+ | "<"
+ {
+ print_DEBUG2 "call url lexbuf" ;
+ url lexbuf
+ }
+
+ | "\""
+ {
+ print_DEBUG2 "call doc lexbuf" ;
+ doc lexbuf
+ }
+
+
+ | '\''
+ {
+ print_DEBUG2 "call file lexbuf" ;
+ file lexbuf
+ }
+
+ | eof
+ {
+ print_DEBUG2 "EOF";
+ EOF
+ }
+
+ | _
+ {
+ Buffer.reset buf ;
+ Buffer.add_string buf (Lexing.lexeme lexbuf);
+ desc lexbuf
+ }
+
+and url = parse
+ | ([^'>'] | '\n')+">"
+ {
+ let s = Lexing.lexeme lexbuf in
+ print_DEBUG2 ("([^'>'] | '\n')+ \">\" with "^s) ;
+ See_url (String.sub s 0 ((String.length s) -1))
+ }
+
+
+and doc = parse
+ | ([^'"'] | '\n' | "\\'")* "\""
+ {
+ let s = Lexing.lexeme lexbuf in
+ See_doc (String.sub s 0 ((String.length s) -1))
+ }
+
+and file = parse
+ | ([^'\''] | '\n' | "\\\"")* "'"
+ {
+ let s = Lexing.lexeme lexbuf in
+ See_file (String.sub s 0 ((String.length s) -1))
+ }
+
+
+and desc = parse
+ eof
+ { Desc (Buffer.contents buf) }
+ | _
+ {
+ Buffer.add_string buf (Lexing.lexeme lexbuf);
+ desc lexbuf
+ }
diff --git a/ocaml-binary-annot/ocamldoc/odoc_sig.ml b/ocaml-binary-annot/ocamldoc/odoc_sig.ml
new file mode 100644
index 0000000000..f8308d6c67
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_sig.ml
@@ -0,0 +1,1305 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Analysis of interface files. *)
+
+open Misc
+open Asttypes
+open Types
+open Typedtree
+open Path
+
+let print_DEBUG s = print_string s ; print_newline ();;
+
+module Name = Odoc_name
+open Odoc_parameter
+open Odoc_value
+open Odoc_type
+open Odoc_exception
+open Odoc_class
+open Odoc_module
+open Odoc_types
+
+module Signature_search =
+ struct
+ type ele =
+ | M of string
+ | MT of string
+ | V of string
+ | T of string
+ | C of string
+ | CT of string
+ | E of string
+ | ER of string
+ | P of string
+
+ type tab = (ele, Types.signature_item) Hashtbl.t
+
+ let add_to_hash table signat =
+ match signat with
+ Types.Tsig_value (ident, _) ->
+ Hashtbl.add table (V (Name.from_ident ident)) signat
+ | Types.Tsig_exception (ident, _) ->
+ Hashtbl.add table (E (Name.from_ident ident)) signat
+ | Types.Tsig_type (ident, _, _) ->
+ Hashtbl.add table (T (Name.from_ident ident)) signat
+ | Types.Tsig_class (ident, _, _) ->
+ Hashtbl.add table (C (Name.from_ident ident)) signat
+ | Types.Tsig_cltype (ident, _, _) ->
+ Hashtbl.add table (CT (Name.from_ident ident)) signat
+ | Types.Tsig_module (ident, _, _) ->
+ Hashtbl.add table (M (Name.from_ident ident)) signat
+ | Types.Tsig_modtype (ident,_) ->
+ Hashtbl.add table (MT (Name.from_ident ident)) signat
+
+ let table signat =
+ let t = Hashtbl.create 13 in
+ List.iter (add_to_hash t) signat;
+ t
+
+ let search_value table name =
+ match Hashtbl.find table (V name) with
+ | (Types.Tsig_value (_, val_desc)) -> val_desc.Types.val_type
+ | _ -> assert false
+
+ let search_exception table name =
+ match Hashtbl.find table (E name) with
+ | (Types.Tsig_exception (_, type_expr_list)) ->
+ type_expr_list
+ | _ -> assert false
+
+ let search_type table name =
+ match Hashtbl.find table (T name) with
+ | (Types.Tsig_type (_, type_decl, _)) -> type_decl
+ | _ -> assert false
+
+ let search_class table name =
+ match Hashtbl.find table (C name) with
+ | (Types.Tsig_class (_, class_decl, _)) -> class_decl
+ | _ -> assert false
+
+ let search_class_type table name =
+ match Hashtbl.find table (CT name) with
+ | (Types.Tsig_cltype (_, cltype_decl, _)) -> cltype_decl
+ | _ -> assert false
+
+ let search_module table name =
+ match Hashtbl.find table (M name) with
+ | (Types.Tsig_module (ident, module_type, _)) -> module_type
+ | _ -> assert false
+
+ let search_module_type table name =
+ match Hashtbl.find table (MT name) with
+ | (Types.Tsig_modtype (_, Types.Tmodtype_manifest module_type)) ->
+ Some module_type
+ | (Types.Tsig_modtype (_, Types.Tmodtype_abstract)) ->
+ None
+ | _ -> assert false
+
+ let search_attribute_type name class_sig =
+ let (_, _, type_expr) = Types.Vars.find name class_sig.Types.cty_vars in
+ type_expr
+
+ let search_method_type name class_sig =
+ let fields = Odoc_misc.get_fields class_sig.Types.cty_self in
+ List.assoc name fields
+ end
+
+module type Info_retriever =
+ sig
+ val all_special : string -> string -> int * (Odoc_types.info list)
+ val blank_line_outside_simple : string -> string -> bool
+ val just_after_special : string -> string -> (int * Odoc_types.info option)
+ val first_special : string -> string -> (int * Odoc_types.info option)
+ val get_comments :
+ (Odoc_types.text -> 'a) -> string -> string -> (Odoc_types.info option * 'a list)
+ end
+
+module Analyser =
+ functor (My_ir : Info_retriever) ->
+ struct
+ (** This variable is used to load a file as a string and retrieve characters from it.*)
+ let file = ref ""
+ (** The name of the analysed file. *)
+ let file_name = ref ""
+
+ (** This function takes two indexes (start and end) and return the string
+ corresponding to the indexes in the file global variable. The function
+ prepare_file must have been called to fill the file global variable.*)
+ let get_string_of_file the_start the_end =
+ try
+ let s = String.sub !file the_start (the_end-the_start) in
+ s
+ with
+ Invalid_argument _ ->
+ ""
+
+ (** This function loads the given file in the file global variable,
+ and sets file_name.*)
+ let prepare_file f input_f =
+ try
+ let s = Odoc_misc.input_file_as_string input_f in
+ file := s;
+ file_name := f
+ with
+ e ->
+ file := "";
+ raise e
+
+ (** The function used to get the comments in a class. *)
+ let get_comments_in_class pos_start pos_end =
+ My_ir.get_comments (fun t -> Class_comment t)
+ !file_name
+ (get_string_of_file pos_start pos_end)
+
+ (** The function used to get the comments in a module. *)
+ let get_comments_in_module pos_start pos_end =
+ My_ir.get_comments (fun t -> Element_module_comment t)
+ !file_name
+ (get_string_of_file pos_start pos_end)
+
+ let merge_infos = Odoc_merge.merge_info_opt Odoc_types.all_merge_options
+
+ let name_comment_from_type_kind pos_end pos_limit tk =
+ match tk with
+ Parsetree.Ptype_abstract ->
+ (0, [])
+ | Parsetree.Ptype_variant cons_core_type_list_list ->
+ let rec f acc cons_core_type_list_list =
+ match cons_core_type_list_list with
+ [] ->
+ (0, acc)
+ | (name, core_type_list, loc) :: [] ->
+ let s = get_string_of_file
+ loc.Location.loc_end.Lexing.pos_cnum
+ pos_limit
+ in
+ let (len, comment_opt) = My_ir.just_after_special !file_name s in
+ (len, acc @ [ (name, comment_opt) ])
+ | (name, core_type_list, loc) :: (name2, core_type_list2, loc2)
+ :: q ->
+ let pos_end_first = loc.Location.loc_end.Lexing.pos_cnum in
+ let pos_start_second = loc2.Location.loc_start.Lexing.pos_cnum in
+ let s = get_string_of_file pos_end_first pos_start_second in
+ let (_,comment_opt) = My_ir.just_after_special !file_name s in
+ f (acc @ [name, comment_opt])
+ ((name2, core_type_list2, loc2) :: q)
+ in
+ f [] cons_core_type_list_list
+
+ | Parsetree.Ptype_record name_mutable_type_list (* of (string * mutable_flag * core_type) list*) ->
+ let rec f = function
+ [] ->
+ []
+ | (name, _, ct, xxloc) :: [] ->
+ let pos = ct.Parsetree.ptyp_loc.Location.loc_end.Lexing.pos_cnum in
+ let s = get_string_of_file pos pos_end in
+ let (_,comment_opt) = My_ir.just_after_special !file_name s in
+ [name, comment_opt]
+ | (name,_,ct,xxloc) :: ((name2,_,ct2,xxloc2) as ele2) :: q ->
+ let pos = ct.Parsetree.ptyp_loc.Location.loc_end.Lexing.pos_cnum in
+ let pos2 = ct2.Parsetree.ptyp_loc.Location.loc_start.Lexing.pos_cnum in
+ let s = get_string_of_file pos pos2 in
+ let (_,comment_opt) = My_ir.just_after_special !file_name s in
+ (name, comment_opt) :: (f (ele2 :: q))
+ in
+ (0, f name_mutable_type_list)
+
+ let get_type_kind env name_comment_list type_kind =
+ match type_kind with
+ Types.Type_abstract ->
+ Odoc_type.Type_abstract
+
+ | Types.Type_variant l ->
+ let f (constructor_name, type_expr_list) =
+ let comment_opt =
+ try
+ match List.assoc constructor_name name_comment_list with
+ None -> None
+ | Some d -> d.Odoc_types.i_desc
+ with Not_found -> None
+ in
+ {
+ vc_name = constructor_name ;
+ vc_args = List.map (Odoc_env.subst_type env) type_expr_list ;
+ vc_text = comment_opt
+ }
+ in
+ Odoc_type.Type_variant (List.map f l)
+
+ | Types.Type_record (l, _) ->
+ let f (field_name, mutable_flag, type_expr) =
+ let comment_opt =
+ try
+ match List.assoc field_name name_comment_list with
+ None -> None
+ | Some d -> d.Odoc_types.i_desc
+ with Not_found -> None
+ in
+ {
+ rf_name = field_name ;
+ rf_mutable = mutable_flag = Mutable ;
+ rf_type = Odoc_env.subst_type env type_expr ;
+ rf_text = comment_opt
+ }
+ in
+ Odoc_type.Type_record (List.map f l)
+
+ (** Analysis of the elements of a class, from the information in the parsetree and in the class
+ signature. @return the couple (inherited_class list, elements).*)
+ let analyse_class_elements env current_class_name last_pos pos_limit
+ class_type_field_list class_signature =
+ let get_pos_limit2 q =
+ match q with
+ [] -> pos_limit
+ | ele2 :: _ ->
+ match ele2 with
+ Parsetree.Pctf_val (_, _, _, _, loc)
+ | Parsetree.Pctf_virt (_, _, _, loc)
+ | Parsetree.Pctf_meth (_, _, _, loc)
+ | Parsetree.Pctf_cstr (_, _, loc) -> loc.Location.loc_start.Lexing.pos_cnum
+ | Parsetree.Pctf_inher class_type ->
+ class_type.Parsetree.pcty_loc.Location.loc_start.Lexing.pos_cnum
+ in
+ let get_method name comment_opt private_flag loc q =
+ let complete_name = Name.concat current_class_name name in
+ let typ =
+ try Signature_search.search_method_type name class_signature
+ with Not_found ->
+ raise (Failure (Odoc_messages.method_type_not_found current_class_name name))
+ in
+ let subst_typ = Odoc_env.subst_type env typ in
+ let met =
+ {
+ met_value =
+ {
+ val_name = complete_name ;
+ val_info = comment_opt ;
+ val_type = subst_typ ;
+ val_recursive = false ;
+ val_parameters = Odoc_value.dummy_parameter_list subst_typ ;
+ val_code = None ;
+ val_loc = { loc_impl = None ; loc_inter = Some (!file_name, loc.Location.loc_start.Lexing.pos_cnum) };
+ } ;
+ met_private = private_flag = Asttypes.Private ;
+ met_virtual = false ;
+ }
+ in
+ let pos_limit2 = get_pos_limit2 q in
+ let pos_end = loc.Location.loc_end.Lexing.pos_cnum in
+ let (maybe_more, info_after_opt) =
+ My_ir.just_after_special
+ !file_name
+ (get_string_of_file pos_end pos_limit2)
+ in
+ met.met_value.val_info <- merge_infos met.met_value.val_info info_after_opt ;
+ (* update the parameter description *)
+ Odoc_value.update_value_parameters_text met.met_value;
+ (met, maybe_more)
+ in
+ let rec f last_pos class_type_field_list =
+ match class_type_field_list with
+ [] ->
+ let s = get_string_of_file last_pos pos_limit in
+ let (_, ele_coms) = My_ir.all_special !file_name s in
+ let ele_comments =
+ List.fold_left
+ (fun acc -> fun sc ->
+ match sc.Odoc_types.i_desc with
+ None ->
+ acc
+ | Some t ->
+ acc @ [Class_comment t])
+ []
+ ele_coms
+ in
+ ([], ele_comments)
+
+ | Parsetree.Pctf_val (name, mutable_flag, virtual_flag, _, loc) :: q ->
+ (* of (string * mutable_flag * core_type option * Location.t)*)
+ let (comment_opt, eles_comments) = get_comments_in_class last_pos loc.Location.loc_start.Lexing.pos_cnum in
+ let complete_name = Name.concat current_class_name name in
+ let typ =
+ try Signature_search.search_attribute_type name class_signature
+ with Not_found ->
+ raise (Failure (Odoc_messages.attribute_type_not_found current_class_name name))
+ in
+ let subst_typ = Odoc_env.subst_type env typ in
+ let att =
+ {
+ att_value =
+ {
+ val_name = complete_name ;
+ val_info = comment_opt ;
+ val_type = subst_typ;
+ val_recursive = false ;
+ val_parameters = [] ;
+ val_code = None ;
+ val_loc = { loc_impl = None ; loc_inter = Some (!file_name, loc.Location.loc_start.Lexing.pos_cnum)} ;
+ } ;
+ att_mutable = mutable_flag = Asttypes.Mutable ;
+ att_virtual = virtual_flag = Asttypes.Virtual ;
+ }
+ in
+ let pos_limit2 = get_pos_limit2 q in
+ let pos_end = loc.Location.loc_end.Lexing.pos_cnum in
+ let (maybe_more, info_after_opt) =
+ My_ir.just_after_special
+ !file_name
+ (get_string_of_file pos_end pos_limit2)
+ in
+ att.att_value.val_info <- merge_infos att.att_value.val_info info_after_opt ;
+ let (inher_l, eles) = f (pos_end + maybe_more) q in
+ (inher_l, eles_comments @ ((Class_attribute att) :: eles))
+
+ | Parsetree.Pctf_virt (name, private_flag, _, loc) :: q ->
+ (* of (string * private_flag * core_type * Location.t) *)
+ let (comment_opt, eles_comments) = get_comments_in_class last_pos loc.Location.loc_start.Lexing.pos_cnum in
+ let (met, maybe_more) = get_method name comment_opt private_flag loc q in
+ let met2 = { met with met_virtual = true } in
+ let (inher_l, eles) = f (loc.Location.loc_end.Lexing.pos_cnum + maybe_more) q in
+ (inher_l, eles_comments @ ((Class_method met2) :: eles))
+
+ | Parsetree.Pctf_meth (name, private_flag, _, loc) :: q ->
+ (* of (string * private_flag * core_type * Location.t) *)
+ let (comment_opt, eles_comments) = get_comments_in_class last_pos loc.Location.loc_start.Lexing.pos_cnum in
+ let (met, maybe_more) = get_method name comment_opt private_flag loc q in
+ let (inher_l, eles) = f (loc.Location.loc_end.Lexing.pos_cnum + maybe_more) q in
+ (inher_l, eles_comments @ ((Class_method met) :: eles))
+
+ | (Parsetree.Pctf_cstr (_, _, loc)) :: q ->
+ (* of (core_type * core_type * Location.t) *)
+ (* A VOIR : cela correspond aux contraintes, non ? on ne les garde pas pour l'instant *)
+ let (comment_opt, eles_comments) = get_comments_in_class last_pos loc.Location.loc_start.Lexing.pos_cnum in
+ let (inher_l, eles) = f loc.Location.loc_end.Lexing.pos_cnum q in
+ (inher_l, eles_comments @ eles)
+
+ | Parsetree.Pctf_inher class_type :: q ->
+ let loc = class_type.Parsetree.pcty_loc in
+ let (comment_opt, eles_comments) =
+ get_comments_in_class last_pos loc.Location.loc_start.Lexing.pos_cnum
+ in
+ let pos_limit2 = get_pos_limit2 q in
+ let pos_end = loc.Location.loc_end.Lexing.pos_cnum in
+ let (maybe_more, info_after_opt) =
+ My_ir.just_after_special
+ !file_name
+ (get_string_of_file pos_end pos_limit2)
+ in
+ let comment_opt2 = merge_infos comment_opt info_after_opt in
+ let text_opt = match comment_opt2 with None -> None | Some i -> i.Odoc_types.i_desc in
+ let inh =
+ match class_type.Parsetree.pcty_desc with
+ Parsetree.Pcty_constr (longident, _) ->
+ (*of Longident.t * core_type list*)
+ let name = Name.from_longident longident in
+ let ic =
+ {
+ ic_name = Odoc_env.full_class_or_class_type_name env name ;
+ ic_class = None ;
+ ic_text = text_opt ;
+ }
+ in
+ ic
+
+ | Parsetree.Pcty_signature _
+ | Parsetree.Pcty_fun _ ->
+ (* we don't have a name for the class signature, so we call it "object ... end" *)
+ {
+ ic_name = Odoc_messages.object_end ;
+ ic_class = None ;
+ ic_text = text_opt ;
+ }
+ in
+ let (inher_l, eles) = f (pos_end + maybe_more) q in
+ (inh :: inher_l , eles_comments @ eles)
+ in
+ f last_pos class_type_field_list
+
+ (** Analyse of a .mli parse tree, to get the corresponding elements.
+ last_pos is the position of the first character which may be used to look for special comments.
+ *)
+ let rec analyse_parsetree env signat current_module_name last_pos pos_limit sig_item_list =
+ let table = Signature_search.table signat in
+ (* we look for the comment of each item then analyse the item *)
+ let rec f acc_eles acc_env last_pos = function
+ [] ->
+ let s = get_string_of_file last_pos pos_limit in
+ let (_, ele_coms) = My_ir.all_special !file_name s in
+ let ele_comments =
+ List.fold_left
+ (fun acc -> fun sc ->
+ match sc.Odoc_types.i_desc with
+ None ->
+ acc
+ | Some t ->
+ acc @ [Element_module_comment t])
+ []
+ ele_coms
+ in
+ acc_eles @ ele_comments
+
+ | ele :: q ->
+ let (assoc_com, ele_comments) = get_comments_in_module
+ last_pos
+ ele.Parsetree.psig_loc.Location.loc_start.Lexing.pos_cnum
+ in
+ let (maybe_more, new_env, elements) = analyse_signature_item_desc
+ acc_env
+ signat
+ table
+ current_module_name
+ ele.Parsetree.psig_loc.Location.loc_start.Lexing.pos_cnum
+ ele.Parsetree.psig_loc.Location.loc_end.Lexing.pos_cnum
+ (match q with
+ [] -> pos_limit
+ | ele2 :: _ -> ele2.Parsetree.psig_loc.Location.loc_start.Lexing.pos_cnum
+ )
+ assoc_com
+ ele.Parsetree.psig_desc
+ in
+ f (acc_eles @ (ele_comments @ elements))
+ new_env
+ (ele.Parsetree.psig_loc.Location.loc_end.Lexing.pos_cnum + maybe_more)
+ (* for the comments of constructors in types,
+ which are after the constructor definition and can
+ go beyond ele.Parsetree.psig_loc.Location.loc_end.Lexing.pos_cnum *)
+ q
+ in
+ f [] env last_pos sig_item_list
+
+ (** Analyse the given signature_item_desc to create the corresponding module element
+ (with the given attached comment).*)
+ and analyse_signature_item_desc env signat table current_module_name
+ pos_start_ele pos_end_ele pos_limit comment_opt sig_item_desc =
+ match sig_item_desc with
+ Parsetree.Psig_value (name_pre, value_desc) ->
+ let type_expr =
+ try Signature_search.search_value table name_pre
+ with Not_found ->
+ raise (Failure (Odoc_messages.value_not_found current_module_name name_pre))
+ in
+ let name = Name.parens_if_infix name_pre in
+ let subst_typ = Odoc_env.subst_type env type_expr in
+ let v =
+ {
+ val_name = Name.concat current_module_name name ;
+ val_info = comment_opt ;
+ val_type = subst_typ ;
+ val_recursive = false ;
+ val_parameters = Odoc_value.dummy_parameter_list subst_typ ;
+ val_code = None ;
+ val_loc = { loc_impl = None ; loc_inter = Some (!file_name, pos_start_ele)}
+ }
+ in
+ let (maybe_more, info_after_opt) =
+ My_ir.just_after_special
+ !file_name
+ (get_string_of_file pos_end_ele pos_limit)
+ in
+ v.val_info <- merge_infos v.val_info info_after_opt ;
+ (* update the parameter description *)
+ Odoc_value.update_value_parameters_text v;
+
+ let new_env = Odoc_env.add_value env v.val_name in
+ (maybe_more, new_env, [ Element_value v ])
+
+ | Parsetree.Psig_exception (name, exception_decl) ->
+ let types_excep_decl =
+ try Signature_search.search_exception table name
+ with Not_found ->
+ raise (Failure (Odoc_messages.exception_not_found current_module_name name))
+ in
+ let e =
+ {
+ ex_name = Name.concat current_module_name name ;
+ ex_info = comment_opt ;
+ ex_args = List.map (Odoc_env.subst_type env) types_excep_decl ;
+ ex_alias = None ;
+ ex_loc = { loc_impl = None ; loc_inter = Some (!file_name, pos_start_ele) } ;
+ ex_code =
+ (
+ if !Odoc_global.keep_code then
+ Some (get_string_of_file pos_start_ele pos_end_ele)
+ else
+ None
+ ) ;
+ }
+ in
+ let (maybe_more, info_after_opt) =
+ My_ir.just_after_special
+ !file_name
+ (get_string_of_file pos_end_ele pos_limit)
+ in
+ e.ex_info <- merge_infos e.ex_info info_after_opt ;
+ let new_env = Odoc_env.add_exception env e.ex_name in
+ (maybe_more, new_env, [ Element_exception e ])
+
+ | Parsetree.Psig_type name_type_decl_list ->
+ (* we start by extending the environment *)
+ let new_env =
+ List.fold_left
+ (fun acc_env -> fun (name, _) ->
+ let complete_name = Name.concat current_module_name name in
+ Odoc_env.add_type acc_env complete_name
+ )
+ env
+ name_type_decl_list
+ in
+ let rec f ?(first=false) acc_maybe_more last_pos name_type_decl_list =
+ match name_type_decl_list with
+ [] ->
+ (acc_maybe_more, [])
+ | (name, type_decl) :: q ->
+ let (assoc_com, ele_comments) =
+ if first then
+ (comment_opt, [])
+ else
+ get_comments_in_module
+ last_pos
+ type_decl.Parsetree.ptype_loc.Location.loc_start.Lexing.pos_cnum
+ in
+ let pos_limit2 =
+ match q with
+ [] -> pos_limit
+ | (_, td) :: _ -> td.Parsetree.ptype_loc.Location.loc_start.Lexing.pos_cnum
+ in
+ let (maybe_more, name_comment_list) =
+ name_comment_from_type_kind
+ type_decl.Parsetree.ptype_loc.Location.loc_end.Lexing.pos_cnum
+ pos_limit2
+ type_decl.Parsetree.ptype_kind
+ in
+ print_DEBUG ("Type "^name^" : "^(match assoc_com with None -> "sans commentaire" | Some c -> Odoc_misc.string_of_info c));
+ let f_DEBUG (name, c_opt) = print_DEBUG ("constructor/field "^name^": "^(match c_opt with None -> "sans commentaire" | Some c -> Odoc_misc.string_of_info c)) in
+ List.iter f_DEBUG name_comment_list;
+ (* get the information for the type in the signature *)
+ let sig_type_decl =
+ try Signature_search.search_type table name
+ with Not_found ->
+ raise (Failure (Odoc_messages.type_not_found current_module_name name))
+ in
+ (* get the type kind with the associated comments *)
+ let type_kind = get_type_kind new_env name_comment_list sig_type_decl.Types.type_kind in
+ let loc_start = type_decl.Parsetree.ptype_loc.Location.loc_start.Lexing.pos_cnum in
+ let new_end = type_decl.Parsetree.ptype_loc.Location.loc_end.Lexing.pos_cnum + maybe_more in
+ (* associate the comments to each constructor and build the [Type.t_type] *)
+ let new_type =
+ {
+ ty_name = Name.concat current_module_name name ;
+ ty_info = assoc_com ;
+ ty_parameters =
+ List.map2 (fun p (co,cn,_) ->
+ (Odoc_env.subst_type new_env p,
+ co, cn)
+ )
+ sig_type_decl.Types.type_params
+ sig_type_decl.Types.type_variance;
+ ty_kind = type_kind;
+ ty_private = sig_type_decl.Types.type_private;
+ ty_manifest =
+ (match sig_type_decl.Types.type_manifest with
+ None -> None
+ | Some t -> Some (Odoc_env.subst_type new_env t));
+ ty_loc =
+ { loc_impl = None ;
+ loc_inter = Some (!file_name,loc_start) ;
+ };
+ ty_code =
+ (
+ if !Odoc_global.keep_code then
+ Some (get_string_of_file loc_start new_end)
+ else
+ None
+ ) ;
+ }
+ in
+ let (maybe_more2, info_after_opt) =
+ My_ir.just_after_special
+ !file_name
+ (get_string_of_file new_end pos_limit2)
+ in
+ new_type.ty_info <- merge_infos new_type.ty_info info_after_opt ;
+ let (new_maybe_more, eles) = f
+ (maybe_more + maybe_more2)
+ (new_end + maybe_more2)
+ q
+ in
+ (new_maybe_more, (ele_comments @ [Element_type new_type]) @ eles)
+ in
+ let (maybe_more, types) = f ~first: true 0 pos_start_ele name_type_decl_list in
+ (maybe_more, new_env, types)
+
+ | Parsetree.Psig_open _ -> (* A VOIR *)
+ let ele_comments = match comment_opt with
+ None -> []
+ | Some i ->
+ match i.i_desc with
+ None -> []
+ | Some t -> [Element_module_comment t]
+ in
+ (0, env, ele_comments)
+
+ | Parsetree.Psig_module (name, module_type) ->
+ let complete_name = Name.concat current_module_name name in
+ (* get the the module type in the signature by the module name *)
+ let sig_module_type =
+ try Signature_search.search_module table name
+ with Not_found ->
+ raise (Failure (Odoc_messages.module_not_found current_module_name name))
+ in
+ let module_kind = analyse_module_kind env complete_name module_type sig_module_type in
+ let code_intf =
+ if !Odoc_global.keep_code then
+ let loc = module_type.Parsetree.pmty_loc in
+ let st = loc.Location.loc_start.Lexing.pos_cnum in
+ let en = loc.Location.loc_end.Lexing.pos_cnum in
+ Some (get_string_of_file st en)
+ else
+ None
+ in
+ let new_module =
+ {
+ m_name = complete_name ;
+ m_type = sig_module_type;
+ m_info = comment_opt ;
+ m_is_interface = true ;
+ m_file = !file_name ;
+ m_kind = module_kind ;
+ m_loc = { loc_impl = None ; loc_inter = Some (!file_name, pos_start_ele) } ;
+ m_top_deps = [] ;
+ m_code = None ;
+ m_code_intf = code_intf ;
+ m_text_only = false ;
+ }
+ in
+ let (maybe_more, info_after_opt) =
+ My_ir.just_after_special
+ !file_name
+ (get_string_of_file pos_end_ele pos_limit)
+ in
+ new_module.m_info <- merge_infos new_module.m_info info_after_opt ;
+ let new_env = Odoc_env.add_module env new_module.m_name in
+ let new_env2 =
+ match new_module.m_type with (* A VOIR : cela peut-il être Tmty_ident ? dans ce cas, on aurait pas la signature *)
+ Types.Tmty_signature s -> Odoc_env.add_signature new_env new_module.m_name ~rel: (Name.simple new_module.m_name) s
+ | _ -> new_env
+ in
+ (maybe_more, new_env2, [ Element_module new_module ])
+
+ | Parsetree.Psig_recmodule decls ->
+ (* we start by extending the environment *)
+ let new_env =
+ List.fold_left
+ (fun acc_env -> fun (name, _) ->
+ let complete_name = Name.concat current_module_name name in
+ let e = Odoc_env.add_module acc_env complete_name in
+ (* get the information for the module in the signature *)
+ let sig_module_type =
+ try Signature_search.search_module table name
+ with Not_found ->
+ raise (Failure (Odoc_messages.module_not_found current_module_name name))
+ in
+ match sig_module_type with
+ (* A VOIR : cela peut-il être Tmty_ident ? dans ce cas, on aurait pas la signature *)
+ Types.Tmty_signature s ->
+ Odoc_env.add_signature e complete_name ~rel: name s
+ | _ ->
+ print_DEBUG "not a Tmty_signature";
+ e
+ )
+ env
+ decls
+ in
+ let rec f ?(first=false) acc_maybe_more last_pos name_mtype_list =
+ match name_mtype_list with
+ [] ->
+ (acc_maybe_more, [])
+ | (name, modtype) :: q ->
+ let complete_name = Name.concat current_module_name name in
+ let loc_start = modtype.Parsetree.pmty_loc.Location.loc_start.Lexing.pos_cnum in
+ let loc_end = modtype.Parsetree.pmty_loc.Location.loc_end.Lexing.pos_cnum in
+ let (assoc_com, ele_comments) =
+ if first then
+ (comment_opt, [])
+ else
+ get_comments_in_module
+ last_pos
+ loc_start
+ in
+ let pos_limit2 =
+ match q with
+ [] -> pos_limit
+ | (_, mty) :: _ -> mty.Parsetree.pmty_loc.Location.loc_start.Lexing.pos_cnum
+ in
+ (* get the information for the module in the signature *)
+ let sig_module_type =
+ try Signature_search.search_module table name
+ with Not_found ->
+ raise (Failure (Odoc_messages.module_not_found current_module_name name))
+ in
+ (* associate the comments to each constructor and build the [Type.t_type] *)
+ let module_kind = analyse_module_kind new_env complete_name modtype sig_module_type in
+ let code_intf =
+ if !Odoc_global.keep_code then
+ let loc = modtype.Parsetree.pmty_loc in
+ let st = loc.Location.loc_start.Lexing.pos_cnum in
+ let en = loc.Location.loc_end.Lexing.pos_cnum in
+ Some (get_string_of_file st en)
+ else
+ None
+ in
+ let new_module =
+ {
+ m_name = complete_name ;
+ m_type = sig_module_type;
+ m_info = assoc_com ;
+ m_is_interface = true ;
+ m_file = !file_name ;
+ m_kind = module_kind ;
+ m_loc = { loc_impl = None ; loc_inter = Some (!file_name, pos_start_ele) } ;
+ m_top_deps = [] ;
+ m_code = None ;
+ m_code_intf = code_intf ;
+ m_text_only = false ;
+ }
+ in
+ let (maybe_more, info_after_opt) =
+ My_ir.just_after_special
+ !file_name
+ (get_string_of_file loc_end pos_limit2)
+ in
+ new_module.m_info <- merge_infos new_module.m_info info_after_opt ;
+
+ let (maybe_more2, eles) = f
+ maybe_more
+ (loc_end + maybe_more)
+ q
+ in
+ (maybe_more2, (ele_comments @ [Element_module new_module]) @ eles)
+ in
+ let (maybe_more, mods) = f ~first: true 0 pos_start_ele decls in
+ (maybe_more, new_env, mods)
+
+ | Parsetree.Psig_modtype (name, pmodtype_decl) ->
+ let complete_name = Name.concat current_module_name name in
+ let sig_mtype =
+ try Signature_search.search_module_type table name
+ with Not_found ->
+ raise (Failure (Odoc_messages.module_type_not_found current_module_name name))
+ in
+ let module_type_kind =
+ match pmodtype_decl with
+ Parsetree.Pmodtype_abstract -> None
+ | Parsetree.Pmodtype_manifest module_type ->
+ match sig_mtype with
+ | Some sig_mtype -> Some (analyse_module_type_kind env complete_name module_type sig_mtype)
+ | None -> None
+ in
+
+ let mt =
+ {
+ mt_name = complete_name ;
+ mt_info = comment_opt ;
+ mt_type = sig_mtype ;
+ mt_is_interface = true ;
+ mt_file = !file_name ;
+ mt_kind = module_type_kind ;
+ mt_loc = { loc_impl = None ; loc_inter = Some (!file_name, pos_start_ele) } ;
+ }
+ in
+ let (maybe_more, info_after_opt) =
+ My_ir.just_after_special
+ !file_name
+ (get_string_of_file pos_end_ele pos_limit)
+ in
+ mt.mt_info <- merge_infos mt.mt_info info_after_opt ;
+ let new_env = Odoc_env.add_module_type env mt.mt_name in
+ let new_env2 =
+ match sig_mtype with (* A VOIR : cela peut-il être Tmty_ident ? dans ce cas, on aurait pas la signature *)
+ Some (Types.Tmty_signature s) -> Odoc_env.add_signature new_env mt.mt_name ~rel: (Name.simple mt.mt_name) s
+ | _ -> new_env
+ in
+ (maybe_more, new_env2, [ Element_module_type mt ])
+
+ | Parsetree.Psig_include module_type ->
+ let rec f = function
+ Parsetree.Pmty_ident longident ->
+ Name.from_longident longident
+ | Parsetree.Pmty_signature _ ->
+ "??"
+ | Parsetree.Pmty_functor _ ->
+ "??"
+ | Parsetree.Pmty_with (mt, _) ->
+ f mt.Parsetree.pmty_desc
+ | Parsetree.Pmty_typeof mexpr ->
+ match mexpr.Parsetree.pmod_desc with
+ Parsetree.Pmod_ident longident -> Name.from_longident longident
+ | _ -> "??"
+ in
+ let name = f module_type.Parsetree.pmty_desc in
+ let full_name = Odoc_env.full_module_or_module_type_name env name in
+ let im =
+ {
+ im_name = full_name ;
+ im_module = None ;
+ im_info = comment_opt;
+ }
+ in
+ (0, env, [ Element_included_module im ]) (* A VOIR : étendre l'environnement ? avec quoi ? *)
+
+ | Parsetree.Psig_class class_description_list ->
+ (* we start by extending the environment *)
+ let new_env =
+ List.fold_left
+ (fun acc_env -> fun class_desc ->
+ let complete_name = Name.concat current_module_name class_desc.Parsetree.pci_name in
+ Odoc_env.add_class acc_env complete_name
+ )
+ env
+ class_description_list
+ in
+ let rec f ?(first=false) acc_maybe_more last_pos class_description_list =
+ match class_description_list with
+ [] ->
+ (acc_maybe_more, [])
+ | class_desc :: q ->
+ let (assoc_com, ele_comments) =
+ if first then
+ (comment_opt, [])
+ else
+ get_comments_in_module
+ last_pos
+ class_desc.Parsetree.pci_loc.Location.loc_start.Lexing.pos_cnum
+ in
+ let pos_end = class_desc.Parsetree.pci_loc.Location.loc_end.Lexing.pos_cnum in
+ let pos_limit2 =
+ match q with
+ [] -> pos_limit
+ | cd :: _ -> cd.Parsetree.pci_loc.Location.loc_start.Lexing.pos_cnum
+ in
+ let name = class_desc.Parsetree.pci_name in
+ let complete_name = Name.concat current_module_name name in
+ let sig_class_decl =
+ try Signature_search.search_class table name
+ with Not_found ->
+ raise (Failure (Odoc_messages.class_not_found current_module_name name))
+ in
+ let sig_class_type = sig_class_decl.Types.cty_type in
+ let (parameters, class_kind) =
+ analyse_class_kind
+ new_env
+ complete_name
+ class_desc.Parsetree.pci_loc.Location.loc_start.Lexing.pos_cnum
+ class_desc.Parsetree.pci_expr
+ sig_class_type
+ in
+ let new_class =
+ {
+ cl_name = complete_name ;
+ cl_info = assoc_com ;
+ cl_type = Odoc_env.subst_class_type env sig_class_type ;
+ cl_type_parameters = sig_class_decl.Types.cty_params;
+ cl_virtual = class_desc.Parsetree.pci_virt = Asttypes.Virtual ;
+ cl_kind = class_kind ;
+ cl_parameters = parameters ;
+ cl_loc = { loc_impl = None ; loc_inter = Some (!file_name, pos_start_ele) } ;
+ }
+ in
+ let (maybe_more, info_after_opt) =
+ My_ir.just_after_special
+ !file_name
+ (get_string_of_file pos_end pos_limit2)
+ in
+ new_class.cl_info <- merge_infos new_class.cl_info info_after_opt ;
+ Odoc_class.class_update_parameters_text new_class ;
+ let (new_maybe_more, eles) =
+ f maybe_more (pos_end + maybe_more) q
+ in
+ (new_maybe_more,
+ ele_comments @ (( Element_class new_class ) :: eles))
+ in
+ let (maybe_more, eles) =
+ f ~first: true 0 pos_start_ele class_description_list
+ in
+ (maybe_more, new_env, eles)
+
+ | Parsetree.Psig_class_type class_type_declaration_list ->
+ (* we start by extending the environment *)
+ let new_env =
+ List.fold_left
+ (fun acc_env -> fun class_type_decl ->
+ let complete_name = Name.concat current_module_name class_type_decl.Parsetree.pci_name in
+ Odoc_env.add_class_type acc_env complete_name
+ )
+ env
+ class_type_declaration_list
+ in
+ let rec f ?(first=false) acc_maybe_more last_pos class_type_description_list =
+ match class_type_description_list with
+ [] ->
+ (acc_maybe_more, [])
+ | ct_decl :: q ->
+ let (assoc_com, ele_comments) =
+ if first then
+ (comment_opt, [])
+ else
+ get_comments_in_module
+ last_pos
+ ct_decl.Parsetree.pci_loc.Location.loc_start.Lexing.pos_cnum
+ in
+ let pos_end = ct_decl.Parsetree.pci_loc.Location.loc_end.Lexing.pos_cnum in
+ let pos_limit2 =
+ match q with
+ [] -> pos_limit
+ | ct_decl2 :: _ -> ct_decl2.Parsetree.pci_loc.Location.loc_start.Lexing.pos_cnum
+ in
+ let name = ct_decl.Parsetree.pci_name in
+ let complete_name = Name.concat current_module_name name in
+ let sig_cltype_decl =
+ try Signature_search.search_class_type table name
+ with Not_found ->
+ raise (Failure (Odoc_messages.class_type_not_found current_module_name name))
+ in
+ let sig_class_type = sig_cltype_decl.Types.clty_type in
+ let kind = analyse_class_type_kind
+ new_env
+ complete_name
+ ct_decl.Parsetree.pci_loc.Location.loc_start.Lexing.pos_cnum
+ ct_decl.Parsetree.pci_expr
+ sig_class_type
+ in
+ let ct =
+ {
+ clt_name = complete_name ;
+ clt_info = assoc_com ;
+ clt_type = Odoc_env.subst_class_type env sig_class_type ;
+ clt_type_parameters = sig_cltype_decl.clty_params ;
+ clt_virtual = ct_decl.Parsetree.pci_virt = Asttypes.Virtual ;
+ clt_kind = kind ;
+ clt_loc = { loc_impl = None ; loc_inter = Some (!file_name, pos_start_ele) } ;
+ }
+ in
+ let (maybe_more, info_after_opt) =
+ My_ir.just_after_special
+ !file_name
+ (get_string_of_file pos_end pos_limit2)
+ in
+ ct.clt_info <- merge_infos ct.clt_info info_after_opt ;
+ let (new_maybe_more, eles) =
+ f maybe_more (pos_end + maybe_more) q
+ in
+ (new_maybe_more,
+ ele_comments @ (( Element_class_type ct) :: eles))
+ in
+ let (maybe_more, eles) =
+ f ~first: true 0 pos_start_ele class_type_declaration_list
+ in
+ (maybe_more, new_env, eles)
+
+ (** Return a module_type_kind from a Parsetree.module_type and a Types.module_type *)
+ and analyse_module_type_kind env current_module_name module_type sig_module_type =
+ match module_type.Parsetree.pmty_desc with
+ Parsetree.Pmty_ident longident ->
+ let name =
+ match sig_module_type with
+ Types.Tmty_ident path -> Name.from_path path
+ | _ -> Name.from_longident longident
+ (* A VOIR cela arrive quand on fait module type F : functor ... -> Toto, Toto n'est pas un ident mais une structure *)
+ in
+ Module_type_alias { mta_name = Odoc_env.full_module_type_name env name ;
+ mta_module = None }
+
+ | Parsetree.Pmty_signature ast ->
+ (
+ (* we must have a signature in the module type *)
+ match sig_module_type with
+ Types.Tmty_signature signat ->
+ let pos_start = module_type.Parsetree.pmty_loc.Location.loc_start.Lexing.pos_cnum in
+ let pos_end = module_type.Parsetree.pmty_loc.Location.loc_end.Lexing.pos_cnum in
+ let elements = analyse_parsetree env signat current_module_name pos_start pos_end ast in
+ Module_type_struct elements
+ | _ ->
+ raise (Failure "Parsetree.Pmty_signature signature but not Types.Tmty_signature signat")
+ )
+
+ | Parsetree.Pmty_functor (_,pmodule_type2, module_type2) ->
+ (
+ let loc_start = pmodule_type2.Parsetree.pmty_loc.Location.loc_start.Lexing.pos_cnum in
+ let loc_end = pmodule_type2.Parsetree.pmty_loc.Location.loc_end.Lexing.pos_cnum in
+ let mp_type_code = get_string_of_file loc_start loc_end in
+ print_DEBUG (Printf.sprintf "mp_type_code=%s" mp_type_code);
+ match sig_module_type with
+ Types.Tmty_functor (ident, param_module_type, body_module_type) ->
+ let mp_kind = analyse_module_type_kind env
+ current_module_name pmodule_type2 param_module_type
+ in
+ let param =
+ {
+ mp_name = Name.from_ident ident ;
+ mp_type = Odoc_env.subst_module_type env param_module_type ;
+ mp_type_code = mp_type_code ;
+ mp_kind = mp_kind ;
+ }
+ in
+ let k = analyse_module_type_kind env
+ current_module_name
+ module_type2
+ body_module_type
+ in
+ Module_type_functor (param, k)
+
+ | _ ->
+ (* if we're here something's wrong *)
+ raise (Failure "Parsetree.Pmty_functor _ but not Types.Tmty_functor _")
+ )
+
+ | Parsetree.Pmty_with (module_type2, _) ->
+ (* of module_type * (Longident.t * with_constraint) list *)
+ (
+ let loc_start = module_type2.Parsetree.pmty_loc.Location.loc_end.Lexing.pos_cnum in
+ let loc_end = module_type.Parsetree.pmty_loc.Location.loc_end.Lexing.pos_cnum in
+ let s = get_string_of_file loc_start loc_end in
+ let k = analyse_module_type_kind env current_module_name module_type2 sig_module_type in
+ Module_type_with (k, s)
+ )
+
+ | Parsetree.Pmty_typeof module_expr ->
+ let loc_start = module_expr.Parsetree.pmod_loc.Location.loc_start.Lexing.pos_cnum in
+ let loc_end = module_expr.Parsetree.pmod_loc.Location.loc_end.Lexing.pos_cnum in
+ let s = get_string_of_file loc_start loc_end in
+ Module_type_typeof s
+
+ (** analyse of a Parsetree.module_type and a Types.module_type.*)
+ and analyse_module_kind env current_module_name module_type sig_module_type =
+ match module_type.Parsetree.pmty_desc with
+ Parsetree.Pmty_ident longident ->
+ let k = analyse_module_type_kind env current_module_name module_type sig_module_type in
+ Module_with ( k, "" )
+
+ | Parsetree.Pmty_signature signature ->
+ (
+ match sig_module_type with
+ Types.Tmty_signature signat ->
+ Module_struct
+ (analyse_parsetree
+ env
+ signat
+ current_module_name
+ module_type.Parsetree.pmty_loc.Location.loc_start.Lexing.pos_cnum
+ module_type.Parsetree.pmty_loc.Location.loc_end.Lexing.pos_cnum
+ signature
+ )
+ | _ ->
+ (* if we're here something's wrong *)
+ raise (Failure "Parsetree.Pmty_signature signature but not Types.Tmty_signature signat")
+ )
+ | Parsetree.Pmty_functor (_,pmodule_type2,module_type2) (* of string * module_type * module_type *) ->
+ (
+ match sig_module_type with
+ Types.Tmty_functor (ident, param_module_type, body_module_type) ->
+ let loc_start = pmodule_type2.Parsetree.pmty_loc.Location.loc_start.Lexing.pos_cnum in
+ let loc_end = pmodule_type2.Parsetree.pmty_loc.Location.loc_end.Lexing.pos_cnum in
+ let mp_type_code = get_string_of_file loc_start loc_end in
+ print_DEBUG (Printf.sprintf "mp_type_code=%s" mp_type_code);
+ let mp_kind = analyse_module_type_kind env
+ current_module_name pmodule_type2 param_module_type
+ in
+ let param =
+ {
+ mp_name = Name.from_ident ident ;
+ mp_type = Odoc_env.subst_module_type env param_module_type ;
+ mp_type_code = mp_type_code ;
+ mp_kind = mp_kind ;
+ }
+ in
+ let k = analyse_module_kind env
+ current_module_name
+ module_type2
+ body_module_type
+ in
+ Module_functor (param, k)
+
+ | _ ->
+ (* if we're here something's wrong *)
+ raise (Failure "Parsetree.Pmty_functor _ but not Types.Tmty_functor _")
+ )
+ | Parsetree.Pmty_with (module_type2, _) ->
+ (*of module_type * (Longident.t * with_constraint) list*)
+ (
+ let loc_start = module_type2.Parsetree.pmty_loc.Location.loc_end.Lexing.pos_cnum in
+ let loc_end = module_type.Parsetree.pmty_loc.Location.loc_end.Lexing.pos_cnum in
+ let s = get_string_of_file loc_start loc_end in
+ let k = analyse_module_type_kind env current_module_name module_type2 sig_module_type in
+ Module_with (k, s)
+ )
+ | Parsetree.Pmty_typeof module_expr ->
+ let loc_start = module_expr.Parsetree.pmod_loc.Location.loc_start.Lexing.pos_cnum in
+ let loc_end = module_expr.Parsetree.pmod_loc.Location.loc_end.Lexing.pos_cnum in
+ let s = get_string_of_file loc_start loc_end in
+ Module_typeof s
+
+ (** Analyse of a Parsetree.class_type and a Types.class_type to return a couple
+ (class parameters, class_kind).*)
+ and analyse_class_kind env current_class_name last_pos parse_class_type sig_class_type =
+ match parse_class_type.Parsetree.pcty_desc, sig_class_type with
+ (Parsetree.Pcty_constr (_, _) (*of Longident.t * core_type list *),
+ Types.Tcty_constr (p, typ_list, _) (*of Path.t * type_expr list * class_type*)) ->
+ print_DEBUG "Tcty_constr _";
+ let path_name = Name.from_path p in
+ let name = Odoc_env.full_class_or_class_type_name env path_name in
+ let k =
+ Class_constr
+ {
+ cco_name = name ;
+ cco_class = None ;
+ cco_type_parameters = List.map (Odoc_env.subst_type env) typ_list
+ }
+ in
+ ([], k)
+
+ | (Parsetree.Pcty_signature (_, class_type_field_list), Types.Tcty_signature class_signature) ->
+ (* we get the elements of the class in class_type_field_list *)
+ let (inher_l, ele) = analyse_class_elements env current_class_name
+ last_pos
+ parse_class_type.Parsetree.pcty_loc.Location.loc_end.Lexing.pos_cnum
+ class_type_field_list
+ class_signature
+ in
+ ([], Class_structure (inher_l, ele))
+
+ | (Parsetree.Pcty_fun (parse_label, _, pclass_type), Types.Tcty_fun (label, type_expr, class_type)) ->
+ (* label = string. Dans les signatures, pas de nom de paramètres à l'intérieur des tuples *)
+ (* si label = "", pas de label. ici on a l'information pour savoir si on a un label explicite. *)
+ if parse_label = label then
+ (
+ let new_param = Simple_name
+ {
+ sn_name = Btype.label_name label ;
+ sn_type = Odoc_env.subst_type env type_expr ;
+ sn_text = None ; (* will be updated when the class will be created *)
+ }
+ in
+ let (l, k) = analyse_class_kind env current_class_name last_pos pclass_type class_type in
+ ( (new_param :: l), k )
+ )
+ else
+ (
+ raise (Failure "Parsetree.Pcty_fun (parse_label, _, pclass_type), labels différents")
+ )
+
+ | _ ->
+ raise (Failure "analyse_class_kind pas de correspondance dans le match")
+
+ (** Analyse of a Parsetree.class_type and a Types.class_type to return a class_type_kind.*)
+ and analyse_class_type_kind env current_class_name last_pos parse_class_type sig_class_type =
+ match parse_class_type.Parsetree.pcty_desc, sig_class_type with
+ (Parsetree.Pcty_constr (_, _) (*of Longident.t * core_type list *),
+ Types.Tcty_constr (p, typ_list, _) (*of Path.t * type_expr list * class_type*)) ->
+ print_DEBUG "Tcty_constr _";
+ let k =
+ Class_type
+ {
+ cta_name = Odoc_env.full_class_or_class_type_name env (Name.from_path p) ;
+ cta_class = None ;
+ cta_type_parameters = List.map (Odoc_env.subst_type env) typ_list
+ }
+ in
+ k
+
+ | (Parsetree.Pcty_signature (_, class_type_field_list), Types.Tcty_signature class_signature) ->
+ (* we get the elements of the class in class_type_field_list *)
+ let (inher_l, ele) = analyse_class_elements env current_class_name
+ last_pos
+ parse_class_type.Parsetree.pcty_loc.Location.loc_end.Lexing.pos_cnum
+ class_type_field_list
+ class_signature
+ in
+ Class_signature (inher_l, ele)
+
+ | (Parsetree.Pcty_fun (parse_label, _, pclass_type), Types.Tcty_fun (label, type_expr, class_type)) ->
+ raise (Failure "analyse_class_type_kind : Parsetree.Pcty_fun (...) with Types.Tcty_fun (...)")
+(*
+ | (Parsetree.Pcty_constr (longident, _) (*of Longident.t * core_type list *),
+ Types.Tcty_signature class_signature) ->
+ (* A VOIR : c'est pour le cas des contraintes de classes :
+ class type cons = object
+ method m : int
+ end
+
+ class ['a] maxou x =
+ (object
+ val a = (x : 'a)
+ method m = a
+ end : cons )
+ ^^^^^^
+ *)
+ let k =
+ Class_type
+ {
+ cta_name = Odoc_env.full_class_name env (Name.from_longident longident) ;
+ cta_class = None ;
+ cta_type_parameters = List.map (Odoc_env.subst_type env) typ_list (* ?? *)
+ }
+ in
+ ([], k)
+*)
+ | _ ->
+ raise (Failure "analyse_class_type_kind pas de correspondance dans le match")
+
+ let analyse_signature source_file input_file
+ (ast : Parsetree.signature) (signat : Types.signature) =
+ let complete_source_file =
+ try
+ let curdir = Sys.getcwd () in
+ let (dirname, basename) = (Filename.dirname source_file, Filename.basename source_file) in
+ Sys.chdir dirname ;
+ let complete = Filename.concat (Sys.getcwd ()) basename in
+ Sys.chdir curdir ;
+ complete
+ with
+ Sys_error s ->
+ prerr_endline s ;
+ incr Odoc_global.errors ;
+ source_file
+ in
+ prepare_file complete_source_file input_file;
+ (* We create the t_module for this file. *)
+ let mod_name = String.capitalize
+ (Filename.basename (try Filename.chop_extension source_file with _ -> source_file))
+ in
+ let (len,info_opt) = My_ir.first_special !file_name !file in
+ let elements =
+ analyse_parsetree Odoc_env.empty signat mod_name len (String.length !file) ast
+ in
+ let code_intf =
+ if !Odoc_global.keep_code then
+ Some !file
+ else
+ None
+ in
+ {
+ m_name = mod_name ;
+ m_type = Types.Tmty_signature signat ;
+ m_info = info_opt ;
+ m_is_interface = true ;
+ m_file = !file_name ;
+ m_kind = Module_struct elements ;
+ m_loc = { loc_impl = None ; loc_inter = Some (!file_name, 0) } ;
+ m_top_deps = [] ;
+ m_code = None ;
+ m_code_intf = code_intf ;
+ m_text_only = false ;
+ }
+
+ end
diff --git a/ocaml-binary-annot/ocamldoc/odoc_sig.mli b/ocaml-binary-annot/ocamldoc/odoc_sig.mli
new file mode 100644
index 0000000000..65ee128fc5
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_sig.mli
@@ -0,0 +1,177 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** The module for analysing a signature and source code and creating modules, classes, ..., elements.*)
+
+(** The functions used to retrieve information from a signature. *)
+module Signature_search :
+ sig
+ type ele
+ type tab = (ele, Types.signature_item) Hashtbl.t
+
+ (** Create a table from a signature. This table is used by some
+ of the search functions below. *)
+ val table : Types.signature -> tab
+
+ (** This function returns the type expression for the value whose name is given,
+ in the given signature.
+ @raise Not_found if error.*)
+ val search_value : tab -> string -> Types.type_expr
+
+ (** This function returns the type expression list for the exception whose name is given,
+ in the given table.
+ @raise Not_found if error.*)
+ val search_exception : tab -> string -> Types.exception_declaration
+
+ (** This function returns the Types.type_declaration for the type whose name is given,
+ in the given table.
+ @raise Not_found if error.*)
+ val search_type : tab -> string -> Types.type_declaration
+
+ (** This function returns the Types.class_declaration for the class whose name is given,
+ in the given table.
+ @raise Not_found if error.*)
+ val search_class : tab -> string -> Types.class_declaration
+
+ (** This function returns the Types.cltype_declaration for the class type whose name is given,
+ in the given table.
+ @raise Not_found if error.*)
+ val search_class_type : tab -> string -> Types.cltype_declaration
+
+ (** This function returns the Types.module_type for the module whose name is given,
+ in the given table.
+ @raise Not_found if error.*)
+ val search_module : tab -> string -> Types.module_type
+
+ (** This function returns the optional Types.module_type for the module type whose name is given,
+ in the given table.
+ @raise Not_found if error.*)
+ val search_module_type : tab -> string -> Types.module_type option
+
+ (** This function returns the Types.type_expr for the given val name
+ in the given class signature.
+ @raise Not_found if error.*)
+ val search_attribute_type :
+ Types.Vars.key -> Types.class_signature -> Types.type_expr
+
+ (** This function returns the Types.type_expr for the given method name
+ in the given class signature.
+ @raise Not_found if error.*)
+ val search_method_type :
+ string -> Types.class_signature -> Types.type_expr
+ end
+
+(** Functions to retrieve simple and special comments from strings. *)
+module type Info_retriever =
+ sig
+ (** Return the couple [(n, list)] where [n] is the number of
+ characters read to retrieve [list], which is the list
+ of special comments found in the string. *)
+ val all_special :
+ string -> string -> int * Odoc_types.info list
+
+ (** Return true if the given string contains a blank line. *)
+ val blank_line_outside_simple :
+ string -> string -> bool
+
+ (** [just_after_special file str] return the pair ([length], [info_opt])
+ where [info_opt] is the first optional special comment found
+ in [str], without any blank line before. [length] is the number
+ of chars from the beginning of [str] to the end of the special comment. *)
+ val just_after_special :
+ string -> string -> (int * Odoc_types.info option)
+
+ (** [first_special file str] return the pair ([length], [info_opt])
+ where [info_opt] is the first optional special comment found
+ in [str]. [length] is the number of chars from the beginning of [str]
+ to the end of the special comment. *)
+ val first_special :
+ string -> string -> (int * Odoc_types.info option)
+
+ (** Return a pair [(comment_opt, element_comment_list)], where [comment_opt] is the last special
+ comment found in the given string and not followed by a blank line,
+ and [element_comment_list] the list of values built from the other
+ special comments found and the given function. *)
+ val get_comments :
+ (Odoc_types.text -> 'a) -> string -> string -> (Odoc_types.info option * 'a list)
+
+ end
+
+module Analyser :
+ functor (My_ir : Info_retriever) ->
+ sig
+ (** This variable is used to load a file as a string and retrieve characters from it.*)
+ val file : string ref
+
+ (** The name of the analysed file. *)
+ val file_name : string ref
+
+ (** This function takes two indexes (start and end) and return the string
+ corresponding to the indexes in the file global variable. The function
+ prepare_file must have been called to fill the file global variable.*)
+ val get_string_of_file : int -> int -> string
+
+ (** [prepare_file f input_f] sets [file_name] with [f] and loads the file
+ [input_f] into [file].*)
+ val prepare_file : string -> string -> unit
+
+ (** The function used to get the comments in a class. *)
+ val get_comments_in_class : int -> int ->
+ (Odoc_types.info option * Odoc_class.class_element list)
+
+ (** The function used to get the comments in a module. *)
+ val get_comments_in_module : int -> int ->
+ (Odoc_types.info option * Odoc_module.module_element list)
+
+ (** [name_comment_from_type_kind pos_end pos_limit type_kind].
+ This function takes a [Parsetree.type_kind] and returns the list of
+ (name, optional comment) for the various fields/constructors of the type,
+ or an empty list for an abstract type.
+ [pos_end] is last char of the complete type definition.
+ [pos_limit] is the position of the last char we could use to look for a comment,
+ i.e. usually the beginning on the next element.*)
+ val name_comment_from_type_kind :
+ int -> int -> Parsetree.type_kind -> int * (string * Odoc_types.info option) list
+
+ (** This function converts a [Types.type_kind] into a [Odoc_type.type_kind],
+ by associating the comment found in the parsetree of each constructor/field, if any.*)
+ val get_type_kind :
+ Odoc_env.env -> (string * Odoc_types.info option) list ->
+ Types.type_kind -> Odoc_type.type_kind
+
+ (** This function merge two optional info structures. *)
+ val merge_infos :
+ Odoc_types.info option -> Odoc_types.info option ->
+ Odoc_types.info option
+
+ (** Return a module_type_kind from a Parsetree.module_type and a Types.module_type *)
+ val analyse_module_type_kind :
+ Odoc_env.env -> Odoc_name.t ->
+ Parsetree.module_type -> Types.module_type ->
+ Odoc_module.module_type_kind
+
+ (** Analysis of a Parsetree.class_type and a Types.class_type to
+ return a class_type_kind.*)
+ val analyse_class_type_kind : Odoc_env.env ->
+ Odoc_name.t -> int -> Parsetree.class_type -> Types.class_type ->
+ Odoc_class.class_type_kind
+
+ (** This function takes an interface file name, a file containg the code, a parse tree
+ and the signature obtained from the compiler.
+ It goes through the parse tree, creating values for encountered
+ functions, modules, ..., looking in the source file for comments,
+ and in the signature for types information. *)
+ val analyse_signature :
+ string -> string ->
+ Parsetree.signature -> Types.signature -> Odoc_module.t_module
+ end
diff --git a/ocaml-binary-annot/ocamldoc/odoc_str.ml b/ocaml-binary-annot/ocamldoc/odoc_str.ml
new file mode 100644
index 0000000000..b20cd8b4bc
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_str.ml
@@ -0,0 +1,277 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** The functions to get a string from different kinds of elements (types, modules, ...). *)
+
+module Name = Odoc_name
+
+let string_of_variance t (co,cn) =
+ if t.Odoc_type.ty_kind = Odoc_type.Type_abstract &&
+ t.Odoc_type.ty_manifest = None
+ then
+ match (co, cn) with
+ (true, false) -> "+"
+ | (false, true) -> "-"
+ | _ -> ""
+ else
+ ""
+let rec is_arrow_type t =
+ match t.Types.desc with
+ Types.Tarrow _ -> true
+ | Types.Tlink t2 | Types.Tsubst t2 -> is_arrow_type t2
+ | Types.Ttuple _
+ | Types.Tconstr _
+ | Types.Tvar | Types.Tunivar | Types.Tobject _ | Types.Tpoly _
+ | Types.Tfield _ | Types.Tnil | Types.Tvariant _ | Types.Tpackage _ -> false
+
+let raw_string_of_type_list sep type_list =
+ let buf = Buffer.create 256 in
+ let fmt = Format.formatter_of_buffer buf in
+ let rec need_parent t =
+ match t.Types.desc with
+ Types.Tarrow _ | Types.Ttuple _ -> true
+ | Types.Tlink t2 | Types.Tsubst t2 -> need_parent t2
+ | Types.Tconstr _ ->
+ false
+ | Types.Tvar | Types.Tunivar | Types.Tobject _ | Types.Tpoly _
+ | Types.Tfield _ | Types.Tnil | Types.Tvariant _ | Types.Tpackage _ -> false
+ in
+ let print_one_type variance t =
+ Printtyp.mark_loops t;
+ if need_parent t then
+ (
+ Format.fprintf fmt "(%s" variance;
+ Printtyp.type_scheme_max ~b_reset_names: false fmt t;
+ Format.fprintf fmt ")"
+ )
+ else
+ (
+ Format.fprintf fmt "%s" variance;
+ Printtyp.type_scheme_max ~b_reset_names: false fmt t
+ )
+ in
+ begin match type_list with
+ [] -> ()
+ | [(variance, ty)] -> print_one_type variance ty
+ | (variance, ty) :: tyl ->
+ Format.fprintf fmt "@[<hov 2>";
+ print_one_type variance ty;
+ List.iter
+ (fun (variance, t) ->
+ Format.fprintf fmt "@,%s" sep;
+ print_one_type variance t
+ )
+ tyl;
+ Format.fprintf fmt "@]"
+ end;
+ Format.pp_print_flush fmt ();
+ Buffer.contents buf
+
+let string_of_type_list ?par sep type_list =
+ let par =
+ match par with
+ | Some b -> b
+ | None ->
+ match type_list with
+ [] | [_] -> false
+ | _ -> true
+ in
+ Printf.sprintf "%s%s%s"
+ (if par then "(" else "")
+ (raw_string_of_type_list sep (List.map (fun t -> ("", t)) type_list))
+ (if par then ")" else "")
+
+let string_of_type_param_list t =
+ let par =
+ match t.Odoc_type.ty_parameters with
+ [] | [_] -> false
+ | _ -> true
+ in
+ Printf.sprintf "%s%s%s"
+ (if par then "(" else "")
+ (raw_string_of_type_list ", "
+ (List.map
+ (fun (typ, co, cn) -> (string_of_variance t (co, cn), typ))
+ t.Odoc_type.ty_parameters
+ )
+ )
+ (if par then ")" else "")
+
+let string_of_class_type_param_list l =
+ let par =
+ match l with
+ [] | [_] -> false
+ | _ -> true
+ in
+ Printf.sprintf "%s%s%s"
+ (if par then "[" else "")
+ (raw_string_of_type_list ", "
+ (List.map
+ (fun typ -> ("", typ))
+ l
+ )
+ )
+ (if par then "]" else "")
+
+let string_of_class_params c =
+ let b = Buffer.create 256 in
+ let rec iter = function
+ Types.Tcty_fun (label, t, ctype) ->
+ let parent = is_arrow_type t in
+ Printf.bprintf b "%s%s%s%s -> "
+ (
+ match label with
+ "" -> ""
+ | s -> s^":"
+ )
+ (if parent then "(" else "")
+ (Odoc_print.string_of_type_expr
+ (if Odoc_misc.is_optional label then
+ Odoc_misc.remove_option t
+ else
+ t
+ )
+ )
+ (if parent then ")" else "");
+ iter ctype
+ | Types.Tcty_signature _
+ | Types.Tcty_constr _ -> ()
+ in
+ iter c.Odoc_class.cl_type;
+ Buffer.contents b
+
+let bool_of_private = function
+ | Asttypes.Private -> true
+ | _ -> false
+
+let string_of_type t =
+ let module M = Odoc_type in
+ "type "^
+ (String.concat ""
+ (List.map
+ (fun (p, co, cn) ->
+ (string_of_variance t (co, cn))^
+ (Odoc_print.string_of_type_expr p)^" "
+ )
+ t.M.ty_parameters
+ )
+ )^
+ let priv = bool_of_private (t.M.ty_private) in
+ (Name.simple t.M.ty_name)^" "^
+ (match t.M.ty_manifest with
+ None -> ""
+ | Some typ ->
+ "= " ^ (if priv then "private " else "" ) ^
+ (Odoc_print.string_of_type_expr typ)^" "
+ )^
+ (match t.M.ty_kind with
+ M.Type_abstract ->
+ ""
+ | M.Type_variant l ->
+ "="^(if priv then " private" else "")^"\n"^
+ (String.concat ""
+ (List.map
+ (fun cons ->
+ " | "^cons.M.vc_name^
+ (match cons.M.vc_args with
+ [] -> ""
+ | l ->
+ " of "^(String.concat " * "
+ (List.map (fun t -> "("^(Odoc_print.string_of_type_expr t)^")") l))
+ )^
+ (match cons.M.vc_text with
+ None ->
+ ""
+ | Some t ->
+ "(* "^(Odoc_misc.string_of_text t)^" *)"
+ )^"\n"
+ )
+ l
+ )
+ )
+ | M.Type_record l ->
+ "= "^(if priv then "private " else "")^"{\n"^
+ (String.concat ""
+ (List.map
+ (fun record ->
+ " "^(if record.M.rf_mutable then "mutable " else "")^
+ record.M.rf_name^" : "^(Odoc_print.string_of_type_expr record.M.rf_type)^";"^
+ (match record.M.rf_text with
+ None ->
+ ""
+ | Some t ->
+ "(* "^(Odoc_misc.string_of_text t)^" *)"
+ )^"\n"
+ )
+ l
+ )
+ )^
+ "}\n"
+ )^
+ (match t.M.ty_info with
+ None -> ""
+ | Some info -> Odoc_misc.string_of_info info)
+
+let string_of_exception e =
+ let module M = Odoc_exception in
+ "exception "^(Name.simple e.M.ex_name)^
+ (match e.M.ex_args with
+ [] -> ""
+ | _ ->" : "^
+ (String.concat " -> "
+ (List.map (fun t -> "("^(Odoc_print.string_of_type_expr t)^")") e.M.ex_args)
+ )
+ )^
+ (match e.M.ex_alias with
+ None -> ""
+ | Some ea ->
+ " = "^
+ (match ea.M.ea_ex with
+ None -> ea.M.ea_name
+ | Some e2 -> e2.M.ex_name
+ )
+ )^"\n"^
+ (match e.M.ex_info with
+ None -> ""
+ | Some i -> Odoc_misc.string_of_info i)
+
+let string_of_value v =
+ let module M = Odoc_value in
+ "val "^(Name.simple v.M.val_name)^" : "^
+ (Odoc_print.string_of_type_expr v.M.val_type)^"\n"^
+ (match v.M.val_info with
+ None -> ""
+ | Some i -> Odoc_misc.string_of_info i)
+
+let string_of_attribute a =
+ let module M = Odoc_value in
+ "val "^
+ (if a.M.att_virtual then "virtual " else "")^
+ (if a.M.att_mutable then Odoc_messages.mutab^" " else "")^
+ (Name.simple a.M.att_value.M.val_name)^" : "^
+ (Odoc_print.string_of_type_expr a.M.att_value.M.val_type)^"\n"^
+ (match a.M.att_value.M.val_info with
+ None -> ""
+ | Some i -> Odoc_misc.string_of_info i)
+
+let string_of_method m =
+ let module M = Odoc_value in
+ "method "^
+ (if m.M.met_private then Odoc_messages.privat^" " else "")^
+ (Name.simple m.M.met_value.M.val_name)^" : "^
+ (Odoc_print.string_of_type_expr m.M.met_value.M.val_type)^"\n"^
+ (match m.M.met_value.M.val_info with
+ None -> ""
+ | Some i -> Odoc_misc.string_of_info i)
+
+(* eof $Id$ *)
diff --git a/ocaml-binary-annot/ocamldoc/odoc_str.mli b/ocaml-binary-annot/ocamldoc/odoc_str.mli
new file mode 100644
index 0000000000..5d68c6d234
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_str.mli
@@ -0,0 +1,51 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** The functions to get a string from different kinds of elements (types, modules, ...). *)
+
+(** @return the variance string for the given type and (covariant, contravariant) information. *)
+val string_of_variance : Odoc_type.t_type -> (bool * bool) -> string
+
+(** This function returns a string to represent the given list of types,
+ with a given separator.
+ @param par can be used to force the addition or not of parentheses around the returned string.
+*)
+val string_of_type_list : ?par: bool -> string -> Types.type_expr list -> string
+
+(** This function returns a string to represent the list of type parameters
+ for the given type. *)
+val string_of_type_param_list : Odoc_type.t_type -> string
+
+(** This function returns a string to represent the given list of
+ type parameters of a class or class type,
+ with a given separator. *)
+val string_of_class_type_param_list : Types.type_expr list -> string
+
+(** @return a string to describe the given type. *)
+val string_of_type : Odoc_type.t_type -> string
+
+(** @return a string to display the parameters of the given class,
+ in the same form as the compiler. *)
+val string_of_class_params : Odoc_class.t_class -> string
+
+(** @return a string to describe the given exception. *)
+val string_of_exception : Odoc_exception.t_exception -> string
+
+(** @return a string to describe the given value. *)
+val string_of_value : Odoc_value.t_value -> string
+
+(** @return a string to describe the given attribute. *)
+val string_of_attribute : Odoc_value.t_attribute -> string
+
+(** @return a string to describe the given method. *)
+val string_of_method : Odoc_value.t_method -> string
diff --git a/ocaml-binary-annot/ocamldoc/odoc_test.ml b/ocaml-binary-annot/ocamldoc/odoc_test.ml
new file mode 100644
index 0000000000..7b455f45bf
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_test.ml
@@ -0,0 +1,118 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2004 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Custom generator to perform test on ocamldoc. *)
+
+open Odoc_info
+open Odoc_info.Module
+open Odoc_info.Type
+
+type test_kind =
+ Types_display
+
+let p = Format.fprintf
+
+module Generator =
+struct
+class string_gen =
+ object(self)
+ inherit Odoc_info.Scan.scanner
+
+ val mutable test_kinds = []
+ val mutable fmt = Format.str_formatter
+
+ method must_display_types = List.mem Types_display test_kinds
+
+ method set_test_kinds_from_module m =
+ test_kinds <- List.fold_left
+ (fun acc (s, _) ->
+ match s with
+ "test_types_display" -> Types_display :: acc
+ | _ -> acc
+ )
+ []
+ (
+ match m.m_info with
+ None -> []
+ | Some i -> i.i_custom
+ )
+ method! scan_type t =
+ match test_kinds with
+ [] -> ()
+ | _ ->
+ p fmt "# type %s:\n" t.ty_name;
+ if self#must_display_types then
+ (
+ p fmt "# manifest (Odoc_info.string_of_type_expr):\n<[%s]>\n"
+ (match t.ty_manifest with
+ None -> "None"
+ | Some e -> Odoc_info.string_of_type_expr e
+ );
+ );
+
+
+ method! scan_module_pre m =
+ p fmt "#\n# module %s:\n" m.m_name ;
+ if self#must_display_types then
+ (
+ p fmt "# Odoc_info.string_of_module_type:\n<[%s]>\n"
+ (Odoc_info.string_of_module_type m.m_type);
+ p fmt "# Odoc_info.string_of_module_type ~complete: true :\n<[%s]>\n"
+ (Odoc_info.string_of_module_type ~complete: true m.m_type);
+ );
+ true
+
+ method! scan_module_type_pre m =
+ p fmt "#\n# module type %s:\n" m.mt_name ;
+ if self#must_display_types then
+ (
+ p fmt "# Odoc_info.string_of_module_type:\n<[%s]>\n"
+ (match m.mt_type with
+ None -> "None"
+ | Some t -> Odoc_info.string_of_module_type t
+ );
+ p fmt "# Odoc_info.string_of_module_type ~complete: true :\n<[%s]>\n"
+ (match m.mt_type with
+ None -> "None"
+ | Some t -> Odoc_info.string_of_module_type ~complete: true t
+ );
+ );
+ true
+
+ method generate (module_list: Odoc_info.Module.t_module list) =
+ let oc = open_out !Odoc_info.Global.out_file in
+ fmt <- Format.formatter_of_out_channel oc;
+ (
+ try
+ List.iter
+ (fun m ->
+ self#set_test_kinds_from_module m;
+ self#scan_module_list [m];
+ )
+ module_list
+ with
+ e ->
+ prerr_endline (Printexc.to_string e)
+ );
+ Format.pp_print_flush fmt ();
+ close_out oc
+ end
+
+ class generator =
+ let g = new string_gen in
+ object
+ method generate = g#generate
+ end
+end;;
+
+let _ = Odoc_args.set_generator (Odoc_gen.Other (module Generator : Odoc_gen.Base))
diff --git a/ocaml-binary-annot/ocamldoc/odoc_texi.ml b/ocaml-binary-annot/ocamldoc/odoc_texi.ml
new file mode 100644
index 0000000000..30ac53ce77
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_texi.ml
@@ -0,0 +1,1244 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Olivier Andrieu, base sur du code de Maxence Guesdon *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Generation of Texinfo documentation. *)
+
+open Odoc_info
+open Parameter
+open Value
+open Type
+open Exception
+open Class
+open Module
+
+let esc_8bits = ref false
+
+let info_section = ref "Objective Caml"
+
+let info_entry = ref []
+
+(** {2 Some small helper functions} *)
+
+let puts_nl chan s =
+ output_string chan s ;
+ output_char chan '\n'
+let puts chan s =
+ output_string chan s
+let nl chan =
+ output_char chan '\n'
+
+let is = function
+ | None -> false
+ | Some _ -> true
+
+let pad_to n s =
+ let len = String.length s in
+ if len < n
+ then
+ let s' = String.make n ' ' in
+ String.blit s 0 s' 0 len ; s'
+ else s
+
+let indent nb_sp s =
+ let c = ref 0 in
+ let len = pred (String.length s) in
+ for i = 0 to len do if s.[i] = '\n' then incr c done ;
+ let s' = String.make (succ len + (succ !c) * nb_sp ) ' ' in
+ c := nb_sp ;
+ for i = 0 to len do
+ s'.[!c] <- s.[i] ;
+ if s.[i] = '\n' then c := !c + nb_sp ;
+ incr c
+ done ;
+ s'
+
+type subparts = [
+ | `Module of Odoc_info.Module.t_module
+ | `Module_type of Odoc_info.Module.t_module_type
+ | `Class of Odoc_info.Class.t_class
+ | `Class_type of Odoc_info.Class.t_class_type
+ ]
+
+type menu_data = [
+ | subparts
+ | `Blank
+ | `Comment of string
+ | `Texi of string
+ | `Index of string
+] list
+
+let nothing = Verbatim ""
+
+let module_subparts =
+ let rec iter acc = function
+ | [] -> List.rev acc
+ (* skip aliases *)
+ | Element_module { m_kind = Module_alias _ } :: n ->
+ iter acc n
+ | Element_module_type { mt_kind = Some (Module_type_alias _) } :: n ->
+ iter acc n
+ (* keep modules, module types, classes and class types *)
+ | Element_module m :: n ->
+ iter (`Module m :: acc) n
+ | Element_module_type mt :: n ->
+ iter (`Module_type mt :: acc) n
+ | Element_class c :: n ->
+ iter (`Class c :: acc) n
+ | Element_class_type ct :: n ->
+ iter (`Class_type ct :: acc) n
+ (* forget the rest *)
+ | _ :: n -> iter acc n
+ in
+ iter []
+
+type indices = [
+ | `Type
+ | `Exception
+ | `Value
+ | `Class_att
+ | `Method
+ | `Class
+ | `Class_type
+ | `Module
+ | `Module_type
+]
+
+let indices = function
+ | `Type -> "ty"
+ | `Exception -> "ex"
+ | `Value -> "va"
+ | `Class_att -> "ca"
+ | `Method -> "me"
+ | `Class -> "cl"
+ | `Class_type -> "ct"
+ | `Module -> "mo"
+ | `Module_type -> "mt"
+
+let indices_names = [
+ "Types" , "ty" ;
+ "Exceptions" , "ex" ;
+ "Values" , "va" ;
+ "Class attributes", "ca" ;
+ "Methods" , "me" ;
+ "Classes" , "cl" ;
+ "Class types" , "ct" ;
+ "Modules" , "mo" ;
+ "Module types" , "mt" ; ]
+
+
+
+(** Module for generating various Texinfo things (menus, xrefs, ...) *)
+module Texi =
+struct
+ (** Associations of strings to subsitute in Texinfo code. *)
+ let subst_strings = [
+ (Str.regexp "@", "@@") ;
+ (Str.regexp "{", "@{") ;
+ (Str.regexp "}", "@}") ;
+ (Str.regexp "\\.\\.\\.", "@dots{}") ;
+ ] @
+ (if !esc_8bits
+ then [
+ (Str.regexp "à", "@`a") ;
+ (Str.regexp "â", "@^a") ;
+ (Str.regexp "é", "@'e") ;
+ (Str.regexp "è", "@`e") ;
+ (Str.regexp "ê", "@^e") ;
+ (Str.regexp "ë", "@\"e") ;
+ (Str.regexp "ç", "@,{c}") ;
+ (Str.regexp "ô", "@^o") ;
+ (Str.regexp "ö", "@\"o") ;
+ (Str.regexp "î", "@^i") ;
+ (Str.regexp "ï", "@\"i") ;
+ (Str.regexp "ù", "@`u") ;
+ (Str.regexp "û", "@^u") ;
+ (Str.regexp "æ", "@ae{}" ) ;
+ (Str.regexp "Æ", "@AE{}" ) ;
+ (Str.regexp "ß", "@ss{}" ) ;
+ (Str.regexp "©", "@copyright{}" ) ;
+ ]
+ else [])
+
+ (** Escape the strings which would clash with Texinfo syntax. *)
+ let escape s =
+ List.fold_left
+ (fun acc (p, r) -> Str.global_replace p r acc)
+ s subst_strings
+
+ (** Removes dots (no good for a node name). *)
+ let fix_nodename s =
+ Str.global_replace (Str.regexp "\\.") "/" (escape s)
+
+ (** Generates a Texinfo menu. *)
+ let generate_menu chan subpart_list =
+ if subpart_list <> []
+ then begin
+ let menu_line part_qual name =
+ let sname = Name.simple name in
+ if sname = name
+ then (
+ puts chan (pad_to 35
+ ("* " ^ sname ^ ":: ")) ;
+ puts_nl chan part_qual )
+ else (
+ puts chan (pad_to 35
+ ("* " ^ sname ^ ": " ^ (fix_nodename name) ^ ". " )) ;
+ puts_nl chan part_qual )
+ in
+ puts_nl chan "@menu" ;
+ List.iter
+ (function
+ | `Module { m_name = name } ->
+ menu_line Odoc_messages.modul name
+ | `Module_type { mt_name = name } ->
+ menu_line Odoc_messages.module_type name
+ | `Class { cl_name = name } ->
+ menu_line Odoc_messages.clas name
+ | `Class_type { clt_name = name } ->
+ menu_line Odoc_messages.class_type name
+ | `Blank -> nl chan
+ | `Comment c -> puts_nl chan (escape c)
+ | `Texi t -> puts_nl chan t
+ | `Index ind -> Printf.fprintf chan "* %s::\n" ind)
+ subpart_list ;
+ puts_nl chan "@end menu"
+ end
+
+ (** cross reference to node [name] *)
+ let xref ?xname name =
+ "@xref{" ^ (fix_nodename name) ^
+ (match xname with | None -> "" | Some s -> "," ^ s) ^
+ "}."
+
+ (** enclose the string between [\@ifinfo] tags *)
+ let ifinfo s =
+ String.concat "\n"
+ [ "@ifinfo" ; s ; "@end ifinfo" ; "" ]
+
+ (** [install-info] information *)
+ let dirsection sec =
+ "@dircategory " ^ (escape sec)
+
+ let direntry ent =
+ [ "@direntry" ] @
+ (List.map escape ent) @
+ [ "@end direntry" ]
+end
+
+
+
+
+
+(** {2 Generation of Texinfo code} *)
+
+(** This class generates Texinfo code from text structures *)
+class text =
+ object(self)
+
+ (** Associations between a title number and texinfo code. *)
+ val titles = [
+ 1, "@chapter " ;
+ 2, "@section " ;
+ 3, "@subsection " ;
+ 4, "@subsubsection " ;
+ ]
+
+ val fallback_title =
+ "@unnumberedsubsubsec "
+
+ val headings = [
+ 1, "@majorheading " ;
+ 2, "@heading " ;
+ 3, "@subheading " ;
+ 4, "@subsubheading " ;
+ ]
+
+ val fallback_heading =
+ "@subsubheading "
+
+ method escape =
+ Texi.escape
+
+ (** this method is not used here but is virtual
+ in a class we will inherit later *)
+ method label ?(no_ : bool option) (_ : string) : string =
+ failwith "gni"
+
+ (** Return the Texinfo code corresponding to the [text] parameter.*)
+ method texi_of_text t =
+ String.concat ""
+ (List.map self#texi_of_text_element t)
+
+
+ (** {3 Conversion methods}
+ [texi_of_????] converts a [text_element] to a Texinfo string. *)
+
+ (** Return the Texinfo code for the [text_element] in parameter. *)
+ method texi_of_text_element = function
+ | Verbatim s | Latex s -> self#texi_of_Verbatim s
+ | Raw s -> self#texi_of_Raw s
+ | Code s -> self#texi_of_Code s
+ | CodePre s -> self#texi_of_CodePre s
+ | Bold t -> self#texi_of_Bold t
+ | Italic t -> self#texi_of_Italic t
+ | Emphasize t -> self#texi_of_Emphasize t
+ | Center t -> self#texi_of_Center t
+ | Left t -> self#texi_of_Left t
+ | Right t -> self#texi_of_Right t
+ | List tl -> self#texi_of_List tl
+ | Enum tl -> self#texi_of_Enum tl
+ | Newline -> self#texi_of_Newline
+ | Block t -> self#texi_of_Block t
+ | Title (n, _, t) -> self#texi_of_Title n t
+ | Link (s, t) -> self#texi_of_Link s t
+ | Ref (name, kind, _) ->self#texi_of_Ref name kind
+ | Superscript t -> self#texi_of_Superscript t
+ | Subscript t -> self#texi_of_Subscript t
+ | Odoc_info.Module_list _ -> ""
+ | Odoc_info.Index_list -> ""
+ | Odoc_info.Custom (s,t) -> self#texi_of_custom_text s t
+ | Odoc_info.Target (target, code) -> self#texi_of_Target ~target ~code
+
+ method texi_of_custom_text s t = ""
+
+ method texi_of_Target ~target ~code =
+ if String.lowercase target = "texi" then code else ""
+
+ method texi_of_Verbatim s = s
+ method texi_of_Raw s = self#escape s
+ method texi_of_Code s = "@code{" ^ (self#escape s) ^ "}"
+ method texi_of_CodePre s =
+ String.concat "\n"
+ [ "" ; "@example" ; self#escape s ; "@end example" ; "" ]
+ method texi_of_Bold t = "@strong{" ^ (self#texi_of_text t) ^ "}"
+ method texi_of_Italic t = "@i{" ^ (self#texi_of_text t) ^ "}"
+ method texi_of_Emphasize t = "@emph{" ^ (self#texi_of_text t) ^ "}"
+ method texi_of_Center t =
+ let sl = Str.split (Str.regexp "\n") (self#texi_of_text t) in
+ String.concat ""
+ ((List.map (fun s -> "\n@center "^s) sl) @ [ "\n" ])
+ method texi_of_Left t =
+ String.concat "\n"
+ [ "" ; "@flushleft" ; self#texi_of_text t ; "@end flushleft" ; "" ]
+ method texi_of_Right t =
+ String.concat "\n"
+ [ "" ; "@flushright" ; self#texi_of_text t ; "@end flushright"; "" ]
+ method texi_of_List tl =
+ String.concat "\n"
+ ( [ "" ; "@itemize" ] @
+ (List.map (fun t -> "@item\n" ^ (self#texi_of_text t)) tl) @
+ [ "@end itemize"; "" ] )
+ method texi_of_Enum tl =
+ String.concat "\n"
+ ( [ "" ; "@enumerate" ] @
+ (List.map (fun t -> "@item\n" ^ (self#texi_of_text t)) tl) @
+ [ "@end enumerate"; "" ] )
+ method texi_of_Newline = "\n"
+ method texi_of_Block t =
+ String.concat "\n"
+ [ "@format" ; self#texi_of_text t ; "@end format" ; "" ]
+ method texi_of_Title n t =
+ let t_begin =
+ try List.assoc n titles
+ with Not_found -> fallback_title in
+ t_begin ^ (self#texi_of_text t) ^ "\n"
+ method texi_of_Link s t =
+ String.concat ""
+ [ "@uref{" ; s ; "," ; self#texi_of_text t ; "}" ]
+ method texi_of_Ref name kind =
+ let xname =
+ match kind with
+ | Some RK_module ->
+ Odoc_messages.modul ^ " " ^ (Name.simple name)
+ | Some RK_module_type ->
+ Odoc_messages.module_type ^ " " ^ (Name.simple name)
+ | Some RK_class ->
+ Odoc_messages.clas ^ " " ^ (Name.simple name)
+ | Some RK_class_type ->
+ Odoc_messages.class_type ^ " " ^ (Name.simple name)
+ | _ -> ""
+ in
+ if xname = "" then self#escape name else Texi.xref ~xname name
+ method texi_of_Superscript t =
+ "^@{" ^ (self#texi_of_text t) ^ "@}"
+ method texi_of_Subscript t =
+ "_@{" ^ (self#texi_of_text t) ^ "@}"
+
+ method heading n t =
+ let f =
+ try List.assoc n headings
+ with Not_found -> fallback_heading
+ in
+ f ^ (self#texi_of_text t) ^ "\n"
+
+ method fixedblock t =
+ Block ( ( Verbatim "@t{" :: t ) @ [ Verbatim "}" ] )
+
+ end
+
+exception Aliased_node
+
+module Generator =
+struct
+
+(** This class is used to create objects which can generate a simple
+ Texinfo documentation. *)
+class texi =
+ object (self)
+ inherit text as to_texi
+ inherit Odoc_to_text.to_text as to_text
+
+ (** {3 Small helper stuff.} *)
+
+ val maxdepth = 4
+
+ val bullet = Verbatim " @bullet{} "
+ val minus = Verbatim " @minus{} "
+ val linebreak = Verbatim "@*\n"
+
+ val mutable indices_to_build = [ `Module ]
+
+ (** Keep a set of nodes we create. If we try to create one
+ a second time, that means it is some kind of alias, so
+ don't do it, just link to the previous one *)
+ val node_tbl = Hashtbl.create 37
+
+ method node depth name =
+ if Hashtbl.mem node_tbl name
+ then raise Aliased_node ;
+ Hashtbl.add node_tbl name () ;
+ if depth <= maxdepth
+ then Verbatim ("@node " ^ (Texi.fix_nodename name) ^ ",\n")
+ else nothing
+
+ method index (ind : indices) ent =
+ Verbatim
+ (if !Global.with_index
+ then (assert(List.mem ind indices_to_build) ;
+ String.concat ""
+ [ "@" ; indices ind ; "index " ;
+ Texi.escape (Name.simple ent) ; "\n" ])
+ else "")
+
+
+ (** Two hacks to fix linebreaks in the descriptions.*)
+ method private fix_linebreaks =
+ let re = Str.regexp "\n[ \t]*" in
+ fun t ->
+ List.map
+ (function
+ | Newline -> Raw "\n"
+ | Raw s -> Raw (Str.global_replace re "\n" s)
+ | List tel -> List (List.map self#fix_linebreaks tel)
+ | Enum tel -> Enum (List.map self#fix_linebreaks tel)
+ | te -> te) t
+
+ method private soft_fix_linebreaks =
+ let re = Str.regexp "\n[ \t]*" in
+ fun ind t ->
+ let rep = String.make (succ ind) ' ' in
+ rep.[0] <- '\n' ;
+ List.map
+ (function
+ | Raw s -> Raw (Str.global_replace re rep s)
+ | te -> te) t
+
+ (** {3 [text] values generation}
+ Generates [text] values out of description parts.
+ Redefines some of methods of {! Odoc_to_text.to_text}. *)
+
+ method text_of_desc = function
+ | None -> []
+ | Some [ Raw "" ] -> []
+ | Some t -> (self#fix_linebreaks t) @ [ Newline ]
+
+ method text_of_sees_opt see_l =
+ List.concat
+ (List.map
+ (function
+ | (See_url s, t) ->
+ [ linebreak ; Bold [ Raw Odoc_messages.see_also ] ;
+ Raw " " ; Link (s, t) ; Newline ]
+ | (See_file s, t)
+ | (See_doc s, t) ->
+ [ linebreak ; Bold [ Raw Odoc_messages.see_also ] ;
+ Raw " " ; Raw s ] @ t @ [ Newline ])
+ see_l)
+
+ method text_of_before l =
+ List.flatten
+ (List.map
+ (fun x -> linebreak :: (to_text#text_of_before [x])) l)
+
+ method text_of_params params_list =
+ List.concat
+ (List.map
+ (fun (s, t) ->
+ [ linebreak ;
+ Bold [ Raw Odoc_messages.parameters ] ;
+ Raw " " ; Raw s ; Raw ": " ] @ t @ [ Newline ] )
+ params_list)
+
+ method! text_of_raised_exceptions = function
+ | [] -> []
+ | (s, t) :: [] ->
+ [ linebreak ;
+ Bold [ Raw Odoc_messages.raises ] ;
+ Raw " " ; Code s ; Raw " " ]
+ @ t @ [ Newline ]
+ | l ->
+ [ linebreak ;
+ Bold [ Raw Odoc_messages.raises ] ;
+ Raw " :" ;
+ List
+ (List.map
+ (fun (ex, desc) ->(Code ex) :: (Raw " ") :: desc ) l ) ;
+ Newline ]
+
+ method! text_of_return_opt = function
+ | None -> []
+ | Some t ->
+ (Bold [Raw Odoc_messages.returns ]) :: Raw " " :: t @ [ Newline ]
+
+ method! text_of_custom c_l =
+ List.flatten
+ (List.rev
+ (List.fold_left
+ (fun acc -> fun (tag, text) ->
+ try
+ let f = List.assoc tag tag_functions in
+ ( linebreak :: (f text) @ [ Newline ] ) :: acc
+ with
+ Not_found ->
+ Odoc_info.warning (Odoc_messages.tag_not_handled tag) ;
+ acc
+ ) [] c_l))
+
+ method! text_of_info ?(block=false) = function
+ | None -> []
+ | Some info ->
+ let t =
+ List.concat
+ [ ( match info.i_deprecated with
+ | None -> []
+ | Some t ->
+ (Raw (Odoc_messages.deprecated ^ " ")) ::
+ (self#fix_linebreaks t)
+ @ [ Newline ; Newline ] ) ;
+ self#text_of_desc info.i_desc ;
+ if info.i_authors <> []
+ then ( linebreak ::
+ self#text_of_author_list info.i_authors )
+ else [] ;
+ if is info.i_version
+ then ( linebreak ::
+ self#text_of_version_opt info.i_version )
+ else [] ;
+ self#text_of_sees_opt info.i_sees ;
+ self#text_of_before info.i_before ;
+ if is info.i_since
+ then ( linebreak ::
+ self#text_of_since_opt info.i_since )
+ else [] ;
+ self#text_of_params info.i_params ;
+ self#text_of_raised_exceptions info.i_raised_exceptions ;
+ if is info.i_return_value
+ then ( linebreak ::
+ self#text_of_return_opt info.i_return_value )
+ else [] ;
+ self#text_of_custom info.i_custom ;
+ ] in
+ if block
+ then [ Block t ]
+ else (t @ [ Newline ] )
+
+ method texi_of_info i =
+ self#texi_of_text (self#text_of_info i)
+
+ (** {3 Conversion of [module_elements] into Texinfo strings}
+ The following functions convert [module_elements] and their
+ description to [text] values then to Texinfo strings using the
+ functions above. *)
+
+ method text_el_of_type_expr m_name typ =
+ Raw (indent 5
+ (self#relative_idents m_name
+ (Odoc_info.string_of_type_expr typ)))
+
+ method! text_of_short_type_expr m_name typ =
+ [ Raw (self#normal_type m_name typ) ]
+
+ (** Return Texinfo code for a value. *)
+ method texi_of_value v =
+ Odoc_info.reset_type_names () ;
+ let t = [ self#fixedblock
+ [ Newline ; minus ;
+ Raw ("val " ^ (Name.simple v.val_name) ^ " :\n") ;
+ self#text_el_of_type_expr
+ (Name.father v.val_name) v.val_type ] ;
+ self#index `Value v.val_name ; Newline ] @
+ (self#text_of_info v.val_info) in
+ self#texi_of_text t
+
+
+ (** Return Texinfo code for a class attribute. *)
+ method texi_of_attribute a =
+ Odoc_info.reset_type_names () ;
+ let t = [ self#fixedblock
+ [ Newline ; minus ;
+ Raw "val " ;
+ Raw (if a.att_virtual then "virtual " else "") ;
+ Raw (if a.att_mutable then "mutable " else "") ;
+ Raw (Name.simple a.att_value.val_name) ;
+ Raw " :\n" ;
+ self#text_el_of_type_expr
+ (Name.father a.att_value.val_name)
+ a.att_value.val_type ] ;
+ self#index `Class_att a.att_value.val_name ; Newline ] @
+ (self#text_of_info a.att_value.val_info) in
+ self#texi_of_text t
+
+
+ (** Return Texinfo code for a class method. *)
+ method texi_of_method m =
+ Odoc_info.reset_type_names () ;
+ let t = [ self#fixedblock
+ [ Newline ; minus ; Raw "method " ;
+ Raw (if m.met_private then "private " else "") ;
+ Raw (if m.met_virtual then "virtual " else "") ;
+ Raw (Name.simple m.met_value.val_name) ;
+ Raw " :\n" ;
+ self#text_el_of_type_expr
+ (Name.father m.met_value.val_name)
+ m.met_value.val_type ] ;
+ self#index `Method m.met_value.val_name ; Newline ] @
+ (self#text_of_info m.met_value.val_info) in
+ self#texi_of_text t
+
+
+ method string_of_type_parameters t =
+ let f (tp, co, cn) =
+ Printf.sprintf "%s%s"
+ (Odoc_info.string_of_variance t (co, cn))
+ (Odoc_info.string_of_type_expr tp)
+ in
+ match t.ty_parameters with
+ | [] -> ""
+ | [ (tp, co, cn) ] ->
+ (f (tp, co, cn))^" "
+ | l ->
+ Printf.sprintf "(%s) "
+ (String.concat ", " (List.map f l))
+
+ method string_of_type_args = function
+ | [] -> ""
+ | args -> " of " ^ (Odoc_info.string_of_type_list " * " args)
+
+ (** Return Texinfo code for a type. *)
+ method texi_of_type ty =
+ Odoc_info.reset_type_names () ;
+ let t =
+ [ self#fixedblock (
+ [ Newline ; minus ; Raw "type " ;
+ Raw (self#string_of_type_parameters ty) ;
+ Raw (Name.simple ty.ty_name) ] @
+ let priv = ty.ty_private = Asttypes.Private in
+ ( match ty.ty_manifest with
+ | None -> []
+ | Some typ ->
+ (Raw " = ") ::
+ (Raw (if priv then "private " else "")) ::
+ (self#text_of_short_type_expr (Name.father ty.ty_name) typ) ) @
+ (
+ match ty.ty_kind with
+ | Type_abstract -> [ Newline ]
+ | Type_variant l ->
+ (Raw (" ="^(if priv then " private" else "")^"\n")) ::
+ (List.flatten
+ (List.map
+ (fun constr ->
+ (Raw (" | " ^ constr.vc_name)) ::
+ (Raw (self#string_of_type_args constr.vc_args)) ::
+ (match constr.vc_text with
+ | None -> [ Newline ]
+ | Some t ->
+ ((Raw (indent 5 "\n(* ")) :: (self#soft_fix_linebreaks 8 t)) @
+ [ Raw " *)" ; Newline ]
+ ) ) l ) )
+ | Type_record l ->
+ (Raw (" = "^(if priv then "private " else "")^"{\n")) ::
+ (List.flatten
+ (List.map
+ (fun r ->
+ [ Raw (" " ^ r.rf_name ^ " : ") ] @
+ (self#text_of_short_type_expr
+ (Name.father r.rf_name)
+ r.rf_type) @
+ [ Raw " ;" ] @
+ (match r.rf_text with
+ | None -> [ Newline ]
+ | Some t ->
+ ((Raw (indent 5 "\n(* ")) :: (self#soft_fix_linebreaks 8 t)) @
+ [ Raw " *)" ; Newline ] ) )
+ l ) )
+ @ [ Raw " }" ]
+ ) ) ;
+ self#index `Type ty.ty_name ; Newline ] @
+ (self#text_of_info ty.ty_info) in
+ self#texi_of_text t
+
+ (** Return Texinfo code for an exception. *)
+ method texi_of_exception e =
+ Odoc_info.reset_type_names () ;
+ let t =
+ [ self#fixedblock
+ ( [ Newline ; minus ; Raw "exception " ;
+ Raw (Name.simple e.ex_name) ;
+ Raw (self#string_of_type_args e.ex_args) ] @
+ (match e.ex_alias with
+ | None -> []
+ | Some ea -> [ Raw " = " ; Raw
+ ( match ea.ea_ex with
+ | None -> ea.ea_name
+ | Some e -> e.ex_name ) ; ]
+ ) ) ;
+ self#index `Exception e.ex_name ; Newline ] @
+ (self#text_of_info e.ex_info) in
+ self#texi_of_text t
+
+
+ (** Return the Texinfo code for the given module. *)
+ method texi_of_module m =
+ let is_alias = function
+ | { m_kind = Module_alias _ } -> true
+ | _ -> false in
+ let is_alias_there = function
+ | { m_kind = Module_alias { ma_module = None } } -> false
+ | _ -> true in
+ let resolve_alias_name = function
+ | { m_kind = Module_alias { ma_name = name } } -> name
+ | { m_name = name } -> name in
+ let t =
+ [ [ self#fixedblock
+ [ Newline ; minus ; Raw "module " ;
+ Raw (Name.simple m.m_name) ;
+ Raw (if is_alias m
+ then " = " ^ (resolve_alias_name m)
+ else "" ) ] ] ;
+ ( if is_alias_there m
+ then [ Ref (resolve_alias_name m, Some RK_module, None) ;
+ Newline ; ]
+ else [] ) ;
+ ( if is_alias m
+ then [ self#index `Module m.m_name ; Newline ]
+ else [ Newline ] ) ;
+ self#text_of_info m.m_info ]
+ in
+ self#texi_of_text (List.flatten t)
+
+ (** Return the Texinfo code for the given module type. *)
+ method texi_of_module_type mt =
+ let is_alias = function
+ | { mt_kind = Some (Module_type_alias _) } -> true
+ | _ -> false in
+ let is_alias_there = function
+ | { mt_kind = Some (Module_type_alias { mta_module = None }) } -> false
+ | _ -> true in
+ let resolve_alias_name = function
+ | { mt_kind = Some (Module_type_alias { mta_name = name }) } -> name
+ | { mt_name = name } -> name in
+ let t =
+ [ [ self#fixedblock
+ [ Newline ; minus ; Raw "module type " ;
+ Raw (Name.simple mt.mt_name) ;
+ Raw (if is_alias mt
+ then " = " ^ (resolve_alias_name mt)
+ else "" ) ] ] ;
+ ( if is_alias_there mt
+ then [ Ref (resolve_alias_name mt, Some RK_module_type, None) ;
+ Newline ; ]
+ else [] ) ;
+ ( if is_alias mt
+ then [ self#index `Module_type mt.mt_name ; Newline ]
+ else [ Newline ] ) ;
+ self#text_of_info mt.mt_info ]
+ in
+ self#texi_of_text (List.flatten t)
+
+ (** Return the Texinfo code for the given included module. *)
+ method texi_of_included_module im =
+ let t = [ self#fixedblock
+ ( Newline :: minus :: (Raw "include ") ::
+ ( match im.im_module with
+ | None ->
+ [ Raw im.im_name ]
+ | Some (Mod { m_name = name }) ->
+ [ Raw name ; Raw "\n " ;
+ Ref (name, Some RK_module, None) ]
+ | Some (Modtype { mt_name = name }) ->
+ [ Raw name ; Raw "\n " ;
+ Ref (name, Some RK_module_type, None) ]
+ ) @
+ [ Newline ] @
+ (self#text_of_info im.im_info)
+ )
+ ]
+ in
+ self#texi_of_text t
+
+ (** Return the Texinfo code for the given class. *)
+ method texi_of_class c =
+ Odoc_info.reset_type_names () ;
+ let t = [ self#fixedblock
+ [ Newline ; minus ; Raw "class " ;
+ Raw (Name.simple c.cl_name) ] ;
+ Ref (c.cl_name, Some RK_class, None) ; Newline ;
+ Newline ] @ (self#text_of_info c.cl_info) in
+ self#texi_of_text t
+
+ (** Return the Texinfo code for the given class type. *)
+ method texi_of_class_type ct =
+ Odoc_info.reset_type_names () ;
+ let t = [ self#fixedblock
+ [ Newline ; minus ; Raw "class type " ;
+ Raw (Name.simple ct.clt_name) ] ;
+ Ref (ct.clt_name, Some RK_class_type, None) ; Newline ;
+ Newline ] @ (self#text_of_info ct.clt_info) in
+ self#texi_of_text t
+
+ (** Return the Texinfo code for the given class element. *)
+ method texi_of_class_element class_name class_ele =
+ match class_ele with
+ | Class_attribute att -> self#texi_of_attribute att
+ | Class_method met -> self#texi_of_method met
+ | Class_comment t -> self#texi_of_text t
+
+ (** Return the Texinfo code for the given module element. *)
+ method texi_of_module_element module_name module_ele =
+ (match module_ele with
+ | Element_module m -> self#texi_of_module m
+ | Element_module_type mt -> self#texi_of_module_type mt
+ | Element_included_module im -> self#texi_of_included_module im
+ | Element_class c -> self#texi_of_class c
+ | Element_class_type ct -> self#texi_of_class_type ct
+ | Element_value v -> self#texi_of_value v
+ | Element_exception e -> self#texi_of_exception e
+ | Element_type t -> self#texi_of_type t
+ | Element_module_comment t ->
+ self#texi_of_text (Newline :: t @ [Newline])
+ )
+
+ (** {3 Generating methods }
+ These methods write Texinfo code to an [out_channel] *)
+
+ (** Generate the Texinfo code for the given list of inherited classes.*)
+ method generate_inheritance_info chanout inher_l =
+ let f inh =
+ match inh.ic_class with
+ | None -> (* we can't make the reference *)
+ (Code inh.ic_name) ::
+ (match inh.ic_text with
+ | None -> []
+ | Some t -> Newline :: t)
+ | Some cct -> (* we can create the reference *)
+ let kind =
+ match cct with
+ | Cl _ -> Some RK_class
+ | Cltype _ -> Some RK_class_type in
+ (Code inh.ic_name) ::
+ (Ref (inh.ic_name, kind, None)) ::
+ ( match inh.ic_text with
+ | None -> []
+ | Some t -> Newline :: t)
+ in
+ let text = [
+ Bold [ Raw Odoc_messages.inherits ] ;
+ List (List.map f inher_l) ; Newline ]
+ in
+ puts chanout (self#texi_of_text text)
+
+
+
+ (** Generate the Texinfo code for the inherited classes
+ of the given class. *)
+ method generate_class_inheritance_info chanout cl =
+ let rec iter_kind = function
+ | Class_structure ([], _) -> ()
+ | Class_structure (l, _) ->
+ self#generate_inheritance_info chanout l
+ | Class_constraint (k, _) -> iter_kind k
+ | Class_apply _
+ | Class_constr _ -> ()
+ in
+ iter_kind cl.cl_kind
+
+
+
+ (** Generate the Texinfo code for the inherited classes
+ of the given class type. *)
+ method generate_class_type_inheritance_info chanout clt =
+ match clt.clt_kind with
+ | Class_signature ([], _) ->
+ ()
+ | Class_signature (l, _) ->
+ self#generate_inheritance_info chanout l
+ | Class_type _ ->
+ ()
+
+ (** Generate the Texinfo code for the given class,
+ in the given out channel. *)
+ method generate_for_class chanout c =
+ try
+ Odoc_info.reset_type_names () ;
+ let depth = Name.depth c.cl_name in
+ let title = [
+ self#node depth c.cl_name ;
+ Title (depth, None, [ Raw (Odoc_messages.clas ^ " ") ;
+ Code c.cl_name ]) ;
+ self#index `Class c.cl_name ] in
+ puts chanout (self#texi_of_text title) ;
+
+ if is c.cl_info
+ then begin
+ let descr = [ Title (succ depth, None,
+ [ Raw Odoc_messages.description ]) ] in
+ puts chanout (self#texi_of_text descr) ;
+ puts chanout (self#texi_of_info c.cl_info)
+ end ;
+
+ let intf = [ Title (succ depth, None,
+ [ Raw Odoc_messages.interface]) ] in
+ puts chanout (self#texi_of_text intf);
+ self#generate_class_inheritance_info chanout c ;
+ List.iter
+ (fun ele -> puts chanout
+ (self#texi_of_class_element c.cl_name ele))
+ (Class.class_elements ~trans:false c)
+ with Aliased_node -> ()
+
+
+ (** Generate the Texinfo code for the given class type,
+ in the given out channel. *)
+ method generate_for_class_type chanout ct =
+ try
+ Odoc_info.reset_type_names () ;
+ let depth = Name.depth ct.clt_name in
+ let title = [
+ self#node depth ct.clt_name ;
+ Title (depth, None, [ Raw (Odoc_messages.class_type ^ " ") ;
+ Code ct.clt_name ]) ;
+ self#index `Class_type ct.clt_name ] in
+ puts chanout (self#texi_of_text title) ;
+
+ if is ct.clt_info
+ then begin
+ let descr = [ Title (succ depth, None,
+ [ Raw Odoc_messages.description ]) ] in
+ puts chanout (self#texi_of_text descr) ;
+ puts chanout (self#texi_of_info ct.clt_info)
+ end ;
+
+ let intf = [ Title (succ depth, None,
+ [ Raw Odoc_messages.interface ]) ] in
+ puts chanout (self#texi_of_text intf) ;
+ self#generate_class_type_inheritance_info chanout ct;
+ List.iter
+ (fun ele -> puts chanout
+ (self#texi_of_class_element ct.clt_name ele))
+ (Class.class_type_elements ~trans:false ct)
+ with Aliased_node -> ()
+
+
+ (** Generate the Texinfo code for the given module type,
+ in the given out channel. *)
+ method generate_for_module_type chanout mt =
+ try
+ let depth = Name.depth mt.mt_name in
+ let title = [
+ self#node depth mt.mt_name ;
+ Title (depth, None, [ Raw (Odoc_messages.module_type ^ " ") ;
+ Code mt.mt_name ]) ;
+ self#index `Module_type mt.mt_name ; Newline ] in
+ puts chanout (self#texi_of_text title) ;
+
+ if is mt.mt_info
+ then begin
+ let descr = [ Title (succ depth, None,
+ [ Raw Odoc_messages.description ]) ] in
+ puts chanout (self#texi_of_text descr) ;
+ puts chanout (self#texi_of_info mt.mt_info)
+ end ;
+
+ let mt_ele = Module.module_type_elements ~trans:true mt in
+ let subparts = module_subparts mt_ele in
+ if depth < maxdepth && subparts <> []
+ then begin
+ let menu = Texi.ifinfo
+ ( self#heading (succ depth) [ Raw "Subparts" ]) in
+ puts chanout menu ;
+ Texi.generate_menu chanout (subparts :> menu_data)
+ end ;
+
+ let intf = [ Title (succ depth, None,
+ [ Raw Odoc_messages.interface ]) ] in
+ puts chanout (self#texi_of_text intf) ;
+ List.iter
+ (fun ele -> puts chanout
+ (self#texi_of_module_element mt.mt_name ele))
+ mt_ele ;
+
+ (* create sub parts for modules, module types, classes and class types *)
+ List.iter
+ (function
+ | `Module m -> self#generate_for_module chanout m
+ | `Module_type mt -> self#generate_for_module_type chanout mt
+ | `Class c -> self#generate_for_class chanout c
+ | `Class_type ct -> self#generate_for_class_type chanout ct)
+ subparts
+ with Aliased_node -> ()
+
+ (** Generate the Texinfo code for the given module,
+ in the given out channel. *)
+ method generate_for_module chanout m =
+ try
+ Odoc_info.verbose ("Generate for module " ^ m.m_name) ;
+ let depth = Name.depth m.m_name in
+ let title = [
+ self#node depth m.m_name ;
+ Title (depth, None,
+ if m.m_text_only then
+ [ Raw m.m_name ]
+ else
+ [ Raw (Odoc_messages.modul ^ " ") ;
+ Code m.m_name ]
+ ) ;
+ self#index `Module m.m_name ; Newline ] in
+ puts chanout (self#texi_of_text title) ;
+
+ if is m.m_info
+ then begin
+ let descr = [ Title (succ depth, None,
+ [ Raw Odoc_messages.description ]) ] in
+ puts chanout (self#texi_of_text descr) ;
+ puts chanout (self#texi_of_info m.m_info)
+ end ;
+
+ let m_ele = Module.module_elements ~trans:true m in
+ let subparts = module_subparts m_ele in
+ if depth < maxdepth && subparts <> []
+ then begin
+ let menu = Texi.ifinfo
+ ( self#heading (succ depth) [ Raw "Subparts" ]) in
+ puts chanout menu ;
+ Texi.generate_menu chanout (subparts :> menu_data)
+ end ;
+
+ let intf = [ Title (succ depth, None,
+ [ Raw Odoc_messages.interface]) ] in
+ puts chanout (self#texi_of_text intf) ;
+
+ List.iter
+ (fun ele -> puts chanout
+ (self#texi_of_module_element m.m_name ele))
+ m_ele ;
+
+ (* create sub nodes for modules, module types, classes and class types *)
+ List.iter
+ (function
+ | `Module m -> self#generate_for_module chanout m
+ | `Module_type mt -> self#generate_for_module_type chanout mt
+ | `Class c -> self#generate_for_class chanout c
+ | `Class_type ct -> self#generate_for_class_type chanout ct )
+ subparts
+ with Aliased_node -> ()
+
+
+ (** Writes the header of the TeXinfo document. *)
+ method generate_texi_header chan texi_filename m_list =
+ let title = match !Global.title with
+ | None -> ""
+ | Some s -> self#escape s in
+ let filename =
+ if texi_filename <> "ocamldoc.texi"
+ then
+ let fn = Filename.basename texi_filename in
+ (if Filename.check_suffix fn ".texi"
+ then Filename.chop_suffix fn ".texi"
+ else fn) ^ ".info"
+ else
+ if title <> ""
+ then title ^ ".info"
+ else "doc.info"
+ in
+ (* write a standard Texinfo header *)
+ List.iter
+ (puts_nl chan)
+ (List.flatten
+ [ [ "\\input texinfo @c -*-texinfo-*-" ;
+ "@c %**start of header" ;
+ "@setfilename " ^ filename ;
+ "@settitle " ^ title ;
+ "@c %**end of header" ; ] ;
+
+ (if !Global.with_index then
+ List.map
+ (fun ind ->
+ "@defcodeindex " ^ (indices ind))
+ indices_to_build
+ else []) ;
+
+ [ Texi.dirsection !info_section ] ;
+
+ Texi.direntry
+ (if !info_entry <> []
+ then !info_entry
+ else [ Printf.sprintf "* %s: (%s)."
+ title
+ (Filename.chop_suffix filename ".info") ]) ;
+
+ [ "@ifinfo" ;
+ "This file was generated by Ocamldoc using the Texinfo generator." ;
+ "@end ifinfo" ;
+
+ "@c no titlepage." ;
+
+ "@node Top, , , (dir)" ;
+ "@top "^ title ; ]
+ ] ) ;
+
+ (* insert the intro file *)
+ begin
+ match !Odoc_info.Global.intro_file with
+ | None when title <> "" ->
+ puts_nl chan "@ifinfo" ;
+ puts_nl chan ("Documentation for " ^ title) ;
+ puts_nl chan "@end ifinfo"
+ | None ->
+ puts_nl chan "@c no title given"
+ | Some f ->
+ nl chan ;
+ puts_nl chan
+ (self#texi_of_info
+ (Some (Odoc_info.info_of_comment_file m_list f)))
+ end ;
+
+ (* write a top menu *)
+ Texi.generate_menu chan
+ ((List.map (fun m -> `Module m) m_list) @
+ (if !Global.with_index then
+ let indices_names_to_build = List.map indices indices_to_build in
+ List.rev
+ (List.fold_left
+ (fun acc ->
+ function (longname, shortname)
+ when List.mem shortname indices_names_to_build ->
+ (`Index (longname ^ " index")) :: acc
+ | _ -> acc)
+ [ `Comment "Indices :" ; `Blank ]
+ indices_names )
+ else [] ))
+
+
+ (** Writes the trailer of the TeXinfo document. *)
+ method generate_texi_trailer chan =
+ nl chan ;
+ if !Global.with_index
+ then
+ let indices_names_to_build = List.map indices indices_to_build in
+ List.iter (puts_nl chan)
+ (List.flatten
+ (List.map
+ (fun (longname, shortname) ->
+ if List.mem shortname indices_names_to_build
+ then [ "@node " ^ longname ^ " index," ;
+ "@unnumbered " ^ longname ^ " index" ;
+ "@printindex " ^ shortname ; ]
+ else [])
+ indices_names )) ;
+ if !Global.with_toc
+ then puts_nl chan "@contents" ;
+ puts_nl chan "@bye"
+
+
+ method do_index it =
+ if not (List.mem it indices_to_build)
+ then indices_to_build <- it :: indices_to_build
+
+ (** Scan the whole module information to know which indices need to be build *)
+ method scan_for_index : subparts -> unit = function
+ | `Module m ->
+ let m_ele = Module.module_elements ~trans:true m in
+ List.iter self#scan_for_index_in_mod m_ele
+ | `Module_type mt ->
+ let m_ele = Module.module_type_elements ~trans:true mt in
+ List.iter self#scan_for_index_in_mod m_ele
+ | `Class c ->
+ let c_ele = Class.class_elements ~trans:true c in
+ List.iter self#scan_for_index_in_class c_ele
+ | `Class_type ct ->
+ let c_ele = Class.class_type_elements ~trans:true ct in
+ List.iter self#scan_for_index_in_class c_ele
+
+ method scan_for_index_in_mod = function
+ (* no recursion *)
+ | Element_value _ -> self#do_index `Value
+ | Element_exception _ -> self#do_index `Exception
+ | Element_type _ -> self#do_index `Type
+ | Element_included_module _
+ | Element_module_comment _ -> ()
+ (* recursion *)
+ | Element_module m -> self#do_index `Module ;
+ self#scan_for_index (`Module m)
+ | Element_module_type mt -> self#do_index `Module_type ;
+ self#scan_for_index (`Module_type mt)
+ | Element_class c -> self#do_index `Class ;
+ self#scan_for_index (`Class c)
+ | Element_class_type ct -> self#do_index `Class_type ;
+ self#scan_for_index (`Class_type ct)
+
+ method scan_for_index_in_class = function
+ | Class_attribute _ -> self#do_index `Class_att
+ | Class_method _ -> self#do_index `Method
+ | Class_comment _ -> ()
+
+
+ (** Generate the Texinfo file from a module list,
+ in the {!Odoc_info.Global.out_file} file. *)
+ method generate module_list =
+ Hashtbl.clear node_tbl ;
+ let filename =
+ if !Global.out_file = Odoc_messages.default_out_file
+ then "ocamldoc.texi"
+ else !Global.out_file in
+ if !Global.with_index
+ then List.iter self#scan_for_index
+ (List.map (fun m -> `Module m) module_list) ;
+ try
+ let chanout = open_out
+ (Filename.concat !Global.target_dir filename) in
+ if !Global.with_header
+ then self#generate_texi_header chanout filename module_list ;
+ List.iter
+ (self#generate_for_module chanout)
+ module_list ;
+ if !Global.with_trailer
+ then self#generate_texi_trailer chanout ;
+ close_out chanout
+ with
+ | Failure s
+ | Sys_error s ->
+ prerr_endline s ;
+ incr Odoc_info.errors
+ end
+end
+
+module type Texi_generator = module type of Generator
diff --git a/ocaml-binary-annot/ocamldoc/odoc_text.ml b/ocaml-binary-annot/ocamldoc/odoc_text.ml
new file mode 100644
index 0000000000..b50a2dbd17
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_text.ml
@@ -0,0 +1,164 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+exception Text_syntax of int * int * string (* line, char, string *)
+
+open Odoc_types
+
+module Texter =
+ struct
+ (* builds a text structure from a string. *)
+ let text_of_string s =
+ let lexbuf = Lexing.from_string s in
+ try
+ Odoc_text_lexer.init ();
+ Odoc_text_parser.main Odoc_text_lexer.main lexbuf
+ with
+ _ ->
+ raise (Text_syntax (!Odoc_text_lexer.line_number,
+ !Odoc_text_lexer.char_number,
+ s)
+ )
+
+ let count s c =
+ let count = ref 0 in
+ for i = 0 to String.length s - 1 do
+ if s.[i] = c then incr count
+ done;
+ !count
+
+ let escape_n s c n =
+ let remain = ref n in
+ let len = String.length s in
+ let b = Buffer.create (len + n) in
+ for i = 0 to len - 1 do
+ if s.[i] = c && !remain > 0 then
+ (
+ Printf.bprintf b "\\%c" c;
+ decr remain
+ )
+ else
+ Buffer.add_char b s.[i]
+ done;
+ Buffer.contents b
+
+ let escape_code s =
+ let open_brackets = count s '[' in
+ let close_brackets = count s ']' in
+ if open_brackets > close_brackets then
+ escape_n s '[' (open_brackets - close_brackets)
+ else
+ if close_brackets > open_brackets then
+ escape_n s ']' (close_brackets - open_brackets)
+ else
+ s
+
+ let escape_raw s =
+ let len = String.length s in
+ let b = Buffer.create len in
+ for i = 0 to len - 1 do
+ match s.[i] with
+ '[' | ']' | '{' | '}' ->
+ Printf.bprintf b "\\%c" s.[i]
+ | c ->
+ Buffer.add_char b c
+ done;
+ Buffer.contents b
+
+ let p = Printf.bprintf
+
+ let rec p_text b t =
+ List.iter (p_text_element b) t
+
+ and p_list b l =
+ List.iter
+ (fun t -> p b "{- " ; p_text b t ; p b "}\n")
+ l
+
+ and p_text_element b = function
+ | Raw s -> p b "%s" (escape_raw s)
+ | Code s -> p b "[%s]" (escape_code s)
+ | CodePre s -> p b "{[%s]}" s
+ | Verbatim s -> p b "{v %s v}" s
+ | Bold t -> p b "{b " ; p_text b t ; p b "}"
+ | Italic t -> p b "{i " ; p_text b t ; p b "}"
+ | Emphasize t -> p b "{e " ; p_text b t ; p b "}"
+ | Center t -> p b "{C " ; p_text b t ; p b "}"
+ | Left t -> p b "{L " ; p_text b t ; p b "}"
+ | Right t -> p b "{R " ; p_text b t ; p b "}"
+ | List l -> p b "{ul\n"; p_list b l; p b "}"
+ | Enum l -> p b "{ol\n"; p_list b l; p b "}"
+ | Newline -> p b "\n"
+ | Block t -> p_text b t
+ | Title (n, l_opt, t) ->
+ p b "{%d%s "
+ n
+ (match l_opt with
+ None -> ""
+ | Some s -> ":"^s
+ );
+ p_text b t ;
+ p b "}"
+ | Latex s -> p b "{%% %s%%}" s
+ | Link (s,t) ->
+ p b "{{:%s}" s;
+ p_text b t ;
+ p b "}"
+ | Ref (name, kind_opt, text_opt) ->
+ begin
+ p b "%s{!%s%s}"
+ (match text_opt with None -> "" | Some _ -> "{")
+ (match kind_opt with
+ None -> ""
+ | Some k ->
+ let s =
+ match k with
+ RK_module -> "module"
+ | RK_module_type -> "modtype"
+ | RK_class -> "class"
+ | RK_class_type -> "classtype"
+ | RK_value -> "val"
+ | RK_type -> "type"
+ | RK_exception -> "exception"
+ | RK_attribute -> "attribute"
+ | RK_method -> "method"
+ | RK_section _ -> "section"
+ in
+ s^":"
+ )
+ name;
+ match text_opt with
+ None -> ()
+ | Some t -> p_text b t; p b "}"
+ end
+ | Superscript t -> p b "{^" ; p_text b t ; p b "}"
+ | Subscript t -> p b "{_" ; p_text b t ; p b "}"
+ | Module_list l ->
+ p b "{!modules:";
+ List.iter (fun s -> p b " %s" s) l;
+ p b "}"
+ | Index_list ->
+ p b "{!indexlist}"
+ | Custom (s,t) ->
+ p b "{%s " s;
+ p_text b t;
+ p b "}"
+ | Target (target, code) ->
+ p b "{%%%s: %s}" target (escape_raw code)
+
+ let string_of_text s =
+ let b = Buffer.create 256 in
+ p_text b s;
+ Buffer.contents b
+
+ end
diff --git a/ocaml-binary-annot/ocamldoc/odoc_text.mli b/ocaml-binary-annot/ocamldoc/odoc_text.mli
new file mode 100644
index 0000000000..f4f8e911e4
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_text.mli
@@ -0,0 +1,24 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** A module with a function to parse strings to obtain a [Odoc_types.text] value. *)
+
+(** Syntax error in a text. *)
+exception Text_syntax of int * int * string (* line, char, string *)
+
+(** Transformation of strings to text structures. *)
+module Texter :
+ sig
+ val text_of_string : string -> Odoc_types.text
+ val string_of_text : Odoc_types.text -> string
+ end
diff --git a/ocaml-binary-annot/ocamldoc/odoc_text_lexer.mll b/ocaml-binary-annot/ocamldoc/odoc_text_lexer.mll
new file mode 100644
index 0000000000..f229f08a66
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_text_lexer.mll
@@ -0,0 +1,798 @@
+{
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** The lexer for string to build text structures. *)
+
+open Lexing
+open Odoc_text_parser
+
+let line_number = ref 0
+let char_number = ref 0
+
+let string_buffer = Buffer.create 32
+
+(** Fonction de remise à zéro de la chaine de caractères tampon *)
+let reset_string_buffer () = Buffer.reset string_buffer
+
+(** Fonction d'ajout d'un caractère dans la chaine de caractères tampon *)
+let ajout_char_string = Buffer.add_char string_buffer
+
+(** Add a string to the buffer. *)
+let ajout_string = Buffer.add_string string_buffer
+
+let lecture_string () = Buffer.contents string_buffer
+
+
+(** the variable which will contain the description string.
+ Is initialized when we encounter the start of a special comment. *)
+
+let description = ref ""
+
+let blank = "[ \013\009\012]"
+
+
+let print_DEBUG s = print_string s; print_newline ()
+
+(** this flag indicates whether we're in a string between begin_code and end_code tokens, to
+ remember the number of open '[' and handle ']' correctly. *)
+let open_brackets = ref 0
+
+(** this flag indicates if we're in verbatim mode or not, to handle any special expression
+ like a string when we're in verbatim mode.*)
+let verb_mode = ref false
+
+(** this flag indicates if we're in "target format" mode or not, to handle any special expression
+ like a string when we're in this mode.*)
+let target_mode = ref false
+
+(** this flag indicates if we're in shortcut list mode or not, to handle end_shortcut_list correctly.*)
+let shortcut_list_mode = ref false
+
+(** this flag indicates if we're in an element reference. *)
+let ele_ref_mode = ref false
+
+(** this flag indicates if we're in a preformatted code string. *)
+let code_pre_mode = ref false
+
+let init () =
+ open_brackets := 0;
+ verb_mode := false;
+ target_mode := false;
+ shortcut_list_mode := false;
+ ele_ref_mode := false ;
+ code_pre_mode := false ;
+ line_number := 0 ;
+ char_number := 0
+
+let incr_cpts lexbuf =
+ let s = Lexing.lexeme lexbuf in
+ let l = Str.split_delim (Str.regexp_string "\n") s in
+ match List.rev l with
+ [] -> () (* should not occur *)
+ | [s2] -> (* no newline *)
+ char_number := !char_number + (String.length s2)
+ | s2 :: _ ->
+ line_number := !line_number + ((List.length l) - 1) ;
+ char_number := String.length s2
+
+}
+
+(** html marks, to use as alternative possible special strings *)
+
+let html_bold = "<"('b'|'B')">"
+let html_end_bold = "</"('b'|'B')">"
+let html_italic = "<"('i'|'I')">"
+let html_end_italic = "</"('i'|'I')">"
+let html_title = "<"('h'|'H')(['0'-'9'])+">"
+let html_end_title = "</"('h'|'H')(['0'-'9'])+">"
+let html_list = "<"('u'|'U')('l'|'L')">"
+let html_end_list = "</"('u'|'U')('l'|'L')">"
+let html_enum = "<"('o'|'O')('l'|'L')">"
+let html_end_enum = "</"('o'|'O')('l'|'L')">"
+let html_item = "<"('l'|'L')('i'|'I')">"
+let html_end_item = "</"('l'|'L')('i'|'I')">"
+let html_code = "<"('c'|'C')('o'|'O')('d'|'D')('e'|'E')">"
+let html_end_code = "</"('c'|'C')('o'|'O')('d'|'D')('e'|'E')">"
+let html_center = "<"('c'|'C')('e'|'E')('n'|'N')('t'|'T')('e'|'E')('r'|'R')">"
+let html_end_center = "</"('c'|'C')('e'|'E')('n'|'N')('t'|'T')('e'|'E')('r'|'R')">"
+let html_left = "<"('l'|'L')('e'|'E')('f'|'F')('t'|'T')">"
+let html_end_left = "</"('l'|'L')('e'|'E')('f'|'F')('t'|'T')">"
+let html_right = "<"('r'|'R')('i'|'I')('g'|'G')('h'|'H')('t'|'T')">"
+let html_end_right = "</"('r'|'R')('i'|'I')('g'|'G')('h'|'H')('t'|'T')">"
+
+
+let blank = [' ' '\013' '\009' '\012']
+let blank_nl = [' ' '\013' '\009' '\012' '\010']
+let label = ['a'-'z']+['a'-'z' 'A'-'Z' '0'-'9' '_']*
+
+(** special strings *)
+
+let end = "}"
+ | html_end_bold
+ | html_end_italic
+ | html_end_title
+ | html_end_list
+ | html_end_enum
+ | html_end_item
+ | html_end_center
+let begin_title =
+ ("{" ['0'-'9']+(":"label)? blank_nl)
+ | html_title
+
+let begin_bold = "{b"blank_nl | html_bold
+let begin_emp = "{e"blank_nl
+let begin_center = "{C"blank_nl | html_center
+let begin_left = "{L"blank_nl
+let begin_right = "{R"blank_nl
+let begin_italic = "{i"blank_nl | html_italic
+let begin_list = "{ul"blank_nl? | html_list
+let begin_enum = "{ol"blank_nl? | html_enum
+let begin_item = "{li"blank_nl | "{- " | html_item
+let begin_link = "{{:"
+let begin_target = "{%"['a'-'z''A'-'Z''0'-'9''-''_']+":"blank_nl?
+let begin_latex = "{%"blank_nl
+let end_target = "%}"
+let begin_code = "[" | html_code
+let end_code = "]" | html_end_code
+let begin_code_pre = "{["
+let end_code_pre = "]}"
+let begin_verb = "{v"blank_nl
+let end_verb = blank_nl"v}"
+
+let begin_ele_ref = "{!"blank_nl | "{!"
+let begin_val_ref = "{!val:"blank_nl | "{!val:"
+let begin_typ_ref = "{!type:"blank_nl | "{!type:"
+let begin_exc_ref = "{!exception:"blank_nl | "{!exception:"
+let begin_mod_ref = "{!module:"blank_nl | "{!module:"
+let begin_modt_ref = "{!modtype:"blank_nl | "{!modtype:"
+let begin_cla_ref = "{!class:"blank_nl | "{!class:"
+let begin_clt_ref = "{!classtype:"blank_nl | "{!classtype:"
+let begin_att_ref = "{!attribute:"blank_nl | "{!attribute:"
+let begin_met_ref = "{!method:"blank_nl | "{!method:"
+let begin_sec_ref = "{!section:"blank_nl | "{!section:"
+let begin_mod_list_ref = "{!modules:"blank_nl | "{!modules:"
+let index_list = "{!indexlist}"
+let begin_custom = "{"['a'-'z''A'-'Z']['a'-'z''A'-'Z''0'-'9']*
+let begin_superscript = "{^"blank_nl | "{^"
+let begin_subscript = "{_"blank_nl | "{_"
+
+let shortcut_list_item = '\n'blank*"- "
+let shortcut_enum_item = '\n'blank*"+ "
+let end_shortcut_list = '\n'(blank*'\n')+
+
+rule main = parse
+| "\\{"
+| "\\}"
+| "\\["
+| "\\]"
+ {
+ incr_cpts lexbuf ;
+ let s = Lexing.lexeme lexbuf in
+ Char (String.sub s 1 1)
+ }
+
+| end
+ {
+ print_DEBUG "end";
+ incr_cpts lexbuf ;
+ if !verb_mode or !target_mode or !code_pre_mode or
+ (!open_brackets >= 1) then
+ Char (Lexing.lexeme lexbuf)
+ else
+ let _ =
+ if !ele_ref_mode then
+ ele_ref_mode := false
+ in
+ END
+ }
+| begin_title
+ {
+ print_DEBUG "begin_title";
+ incr_cpts lexbuf ;
+ if !verb_mode or !target_mode or !code_pre_mode or
+ (!open_brackets >= 1) or !ele_ref_mode then
+ Char (Lexing.lexeme lexbuf)
+ else
+ let s = Lexing.lexeme lexbuf in
+ try
+ (* chech if the "{..." or html_title mark was used. *)
+ if s.[0] = '<' then
+ let (n, l) = (2, (String.length s - 3)) in
+ let s2 = String.sub s n l in
+ Title (int_of_string s2, None)
+ else
+ let (n, l) = (1, (String.length s - 2)) in
+ let s2 = String.sub s n l in
+ try
+ let i = String.index s2 ':' in
+ let s_n = String.sub s2 0 i in
+ let s_label = String.sub s2 (i+1) (l-i-1) in
+ Title (int_of_string s_n, Some s_label)
+ with
+ Not_found ->
+ Title (int_of_string s2, None)
+ with
+ _ ->
+ Title (1, None)
+ }
+| begin_bold
+ {
+ incr_cpts lexbuf ;
+ if !verb_mode or !target_mode or !code_pre_mode or
+ (!open_brackets >= 1) or !ele_ref_mode then
+ Char (Lexing.lexeme lexbuf)
+ else
+ BOLD
+ }
+| begin_italic
+ {
+ incr_cpts lexbuf ;
+ if !verb_mode or !target_mode or !code_pre_mode or
+ (!open_brackets >= 1) or !ele_ref_mode then
+ Char (Lexing.lexeme lexbuf)
+ else
+ ITALIC
+ }
+| begin_link
+ {
+ incr_cpts lexbuf ;
+ if !verb_mode or !target_mode or !code_pre_mode or
+ (!open_brackets >= 1) or !ele_ref_mode then
+ Char (Lexing.lexeme lexbuf)
+ else
+ LINK
+ }
+| begin_emp
+ {
+ incr_cpts lexbuf ;
+ if !verb_mode or !target_mode or !code_pre_mode or
+ (!open_brackets >= 1) or !ele_ref_mode then
+ Char (Lexing.lexeme lexbuf)
+ else
+ EMP
+ }
+| begin_superscript
+ {
+ incr_cpts lexbuf ;
+ if !verb_mode or !target_mode or !code_pre_mode or
+ (!open_brackets >= 1) or !ele_ref_mode then
+ Char (Lexing.lexeme lexbuf)
+ else
+ SUPERSCRIPT
+ }
+| begin_subscript
+ {
+ incr_cpts lexbuf ;
+ if !verb_mode or !target_mode or !code_pre_mode or
+ (!open_brackets >= 1) or !ele_ref_mode then
+ Char (Lexing.lexeme lexbuf)
+ else
+ SUBSCRIPT
+ }
+| begin_center
+ {
+ incr_cpts lexbuf ;
+ if !verb_mode or !target_mode or !code_pre_mode or
+ (!open_brackets >= 1) or !ele_ref_mode then
+ Char (Lexing.lexeme lexbuf)
+ else
+ CENTER
+ }
+| begin_left
+ {
+ incr_cpts lexbuf ;
+ if !verb_mode or !target_mode or !code_pre_mode or
+ (!open_brackets >= 1) or !ele_ref_mode then
+ Char (Lexing.lexeme lexbuf)
+ else
+ LEFT
+ }
+| begin_right
+ {
+ incr_cpts lexbuf ;
+ if !verb_mode or !target_mode or !code_pre_mode
+ or (!open_brackets >= 1) or !ele_ref_mode then
+ Char (Lexing.lexeme lexbuf)
+ else
+ RIGHT
+ }
+| begin_list
+ {
+ print_DEBUG "LIST";
+ incr_cpts lexbuf ;
+ if !verb_mode or !target_mode or !code_pre_mode or
+ (!open_brackets >= 1) or !ele_ref_mode then
+ Char (Lexing.lexeme lexbuf)
+ else
+ LIST
+ }
+| begin_enum
+ {
+ incr_cpts lexbuf ;
+ if !verb_mode or !target_mode or !code_pre_mode or
+ (!open_brackets >= 1) or !ele_ref_mode then
+ Char (Lexing.lexeme lexbuf)
+ else
+ ENUM
+ }
+| begin_item
+ {
+ print_DEBUG "ITEM";
+ incr_cpts lexbuf ;
+ if !verb_mode or !target_mode or !code_pre_mode or
+ (!open_brackets >= 1) or !ele_ref_mode then
+ Char (Lexing.lexeme lexbuf)
+ else
+ ITEM
+ }
+| begin_target
+ {
+ incr_cpts lexbuf ;
+ if !verb_mode or !target_mode or !code_pre_mode or
+ (!open_brackets >= 1) or !ele_ref_mode then
+ Char (Lexing.lexeme lexbuf)
+ else
+ (
+ let s = Lexing.lexeme lexbuf in
+ let fmt =
+ let p1 = String.index s '%' in
+ let p2 = String.index s ':' in
+ String.sub s (p1 + 1) (p2 - p1 - 1)
+ in
+ target_mode := true;
+ Target fmt
+ )
+ }
+| begin_latex
+ {
+ incr_cpts lexbuf ;
+ if !verb_mode or !target_mode or !code_pre_mode or
+ (!open_brackets >= 1) or !ele_ref_mode then
+ Char (Lexing.lexeme lexbuf)
+ else
+ (
+ target_mode := true;
+ LATEX
+ )
+ }
+| end_target
+ {
+ incr_cpts lexbuf ;
+ if !verb_mode or (!open_brackets >= 1) or !code_pre_mode or
+ !ele_ref_mode then
+ Char (Lexing.lexeme lexbuf)
+ else
+ (
+ target_mode := false;
+ END_TARGET
+ )
+ }
+| begin_code end_code
+ {
+ incr_cpts lexbuf ;
+ Char (Lexing.lexeme lexbuf)
+ }
+
+| begin_code
+ {
+ incr_cpts lexbuf ;
+ if !verb_mode or !target_mode or !code_pre_mode or !ele_ref_mode then
+ Char (Lexing.lexeme lexbuf)
+ else
+ if !open_brackets <= 0 then
+ (
+ open_brackets := 1;
+ CODE
+ )
+ else
+ (
+ incr open_brackets;
+ Char (Lexing.lexeme lexbuf)
+ )
+ }
+| end_code
+ {
+ incr_cpts lexbuf ;
+ if !verb_mode or !target_mode or !code_pre_mode or !ele_ref_mode then
+ Char (Lexing.lexeme lexbuf)
+ else
+ if !open_brackets > 1 then
+ (
+ decr open_brackets;
+ Char "]"
+ )
+ else
+ (
+ open_brackets := 0;
+ END_CODE
+ )
+ }
+
+| begin_code_pre end_code_pre
+ {
+ incr_cpts lexbuf ;
+ Char (Lexing.lexeme lexbuf)
+ }
+
+| begin_code_pre
+ {
+ incr_cpts lexbuf ;
+ if !verb_mode or !target_mode or !code_pre_mode or !ele_ref_mode then
+ Char (Lexing.lexeme lexbuf)
+ else
+ (
+ code_pre_mode := true;
+ CODE_PRE
+ )
+ }
+| end_code_pre
+ {
+ incr_cpts lexbuf ;
+ if !verb_mode or !target_mode or !ele_ref_mode then
+ Char (Lexing.lexeme lexbuf)
+ else
+ if !open_brackets >= 1 then
+ (
+ lexbuf.Lexing.lex_curr_pos <- lexbuf.Lexing.lex_curr_pos - 1;
+ lexbuf.Lexing.lex_curr_p <-
+ { lexbuf.Lexing.lex_curr_p with
+ pos_cnum = lexbuf.Lexing.lex_curr_p.pos_cnum - 1
+ } ;
+ decr char_number ;
+ if !open_brackets > 1 then
+ (
+ decr open_brackets;
+ Char "]"
+ )
+ else
+ (
+ open_brackets := 0;
+ END_CODE
+ )
+ )
+ else
+ if !code_pre_mode then
+ (
+ code_pre_mode := false;
+ END_CODE_PRE
+ )
+ else
+ Char (Lexing.lexeme lexbuf)
+ }
+
+| begin_ele_ref end
+ {
+ incr_cpts lexbuf ;
+ Char (Lexing.lexeme lexbuf)
+ }
+
+| begin_ele_ref
+ {
+ incr_cpts lexbuf ;
+ if !verb_mode or !target_mode or !code_pre_mode or !open_brackets >= 1 then
+ Char (Lexing.lexeme lexbuf)
+ else
+ if not !ele_ref_mode then
+ (
+ ele_ref_mode := true;
+ ELE_REF
+ )
+ else
+ (
+ Char (Lexing.lexeme lexbuf)
+ )
+ }
+
+
+| begin_val_ref
+ {
+ incr_cpts lexbuf ;
+ if !verb_mode or !target_mode or !code_pre_mode or !open_brackets >= 1 then
+ Char (Lexing.lexeme lexbuf)
+ else
+ if not !ele_ref_mode then
+ (
+ ele_ref_mode := true;
+ VAL_REF
+ )
+ else
+ (
+ Char (Lexing.lexeme lexbuf)
+ )
+ }
+
+| begin_typ_ref
+ {
+ incr_cpts lexbuf ;
+ if !verb_mode or !target_mode or !code_pre_mode or !open_brackets >= 1 then
+ Char (Lexing.lexeme lexbuf)
+ else
+ if not !ele_ref_mode then
+ (
+ ele_ref_mode := true;
+ TYP_REF
+ )
+ else
+ (
+ Char (Lexing.lexeme lexbuf)
+ )
+ }
+
+| begin_exc_ref
+ {
+ incr_cpts lexbuf ;
+ if !verb_mode or !target_mode or !code_pre_mode or !open_brackets >= 1 then
+ Char (Lexing.lexeme lexbuf)
+ else
+ if not !ele_ref_mode then
+ (
+ ele_ref_mode := true;
+ EXC_REF
+ )
+ else
+ (
+ Char (Lexing.lexeme lexbuf)
+ )
+ }
+
+| begin_mod_ref
+ {
+ incr_cpts lexbuf ;
+ if !verb_mode or !target_mode or !code_pre_mode or !open_brackets >= 1 then
+ Char (Lexing.lexeme lexbuf)
+ else
+ if not !ele_ref_mode then
+ (
+ ele_ref_mode := true;
+ MOD_REF
+ )
+ else
+ (
+ Char (Lexing.lexeme lexbuf)
+ )
+ }
+
+| begin_modt_ref
+ {
+ incr_cpts lexbuf ;
+ if !verb_mode or !target_mode or !code_pre_mode or !open_brackets >= 1 then
+ Char (Lexing.lexeme lexbuf)
+ else
+ if not !ele_ref_mode then
+ (
+ ele_ref_mode := true;
+ MODT_REF
+ )
+ else
+ (
+ Char (Lexing.lexeme lexbuf)
+ )
+ }
+
+| begin_cla_ref
+ {
+ incr_cpts lexbuf ;
+ if !verb_mode or !target_mode or !code_pre_mode or !open_brackets >= 1 then
+ Char (Lexing.lexeme lexbuf)
+ else
+ if not !ele_ref_mode then
+ (
+ ele_ref_mode := true;
+ CLA_REF
+ )
+ else
+ (
+ Char (Lexing.lexeme lexbuf)
+ )
+ }
+
+| begin_clt_ref
+ {
+ incr_cpts lexbuf ;
+ if !verb_mode or !target_mode or !code_pre_mode or !open_brackets >= 1 then
+ Char (Lexing.lexeme lexbuf)
+ else
+ if not !ele_ref_mode then
+ (
+ ele_ref_mode := true;
+ CLT_REF
+ )
+ else
+ (
+ Char (Lexing.lexeme lexbuf)
+ )
+ }
+
+| begin_att_ref
+ {
+ incr_cpts lexbuf ;
+ if !verb_mode or !target_mode or !code_pre_mode or !open_brackets >= 1 then
+ Char (Lexing.lexeme lexbuf)
+ else
+ if not !ele_ref_mode then
+ (
+ ele_ref_mode := true;
+ ATT_REF
+ )
+ else
+ (
+ Char (Lexing.lexeme lexbuf)
+ )
+ }
+
+| begin_met_ref
+ {
+ incr_cpts lexbuf ;
+ if !verb_mode or !target_mode or !code_pre_mode or !open_brackets >= 1 then
+ Char (Lexing.lexeme lexbuf)
+ else
+ if not !ele_ref_mode then
+ (
+ ele_ref_mode := true;
+ MET_REF
+ )
+ else
+ (
+ Char (Lexing.lexeme lexbuf)
+ )
+ }
+
+| begin_sec_ref
+ {
+ incr_cpts lexbuf ;
+ if !verb_mode or !target_mode or !code_pre_mode or !open_brackets >= 1 then
+ Char (Lexing.lexeme lexbuf)
+ else
+ if not !ele_ref_mode then
+ (
+ ele_ref_mode := true;
+ SEC_REF
+ )
+ else
+ (
+ Char (Lexing.lexeme lexbuf)
+ )
+ }
+
+| begin_mod_list_ref
+ {
+ incr_cpts lexbuf ;
+ if !verb_mode or !target_mode or !code_pre_mode or !open_brackets >= 1 then
+ Char (Lexing.lexeme lexbuf)
+ else
+ if not !ele_ref_mode then
+ (
+ ele_ref_mode := true;
+ MOD_LIST_REF
+ )
+ else
+ (
+ Char (Lexing.lexeme lexbuf)
+ )
+ }
+
+| index_list
+ {
+ incr_cpts lexbuf ;
+ if !verb_mode or !target_mode or !code_pre_mode or !open_brackets >= 1 then
+ Char (Lexing.lexeme lexbuf)
+ else
+ if not !ele_ref_mode then
+ INDEX_LIST
+ else
+ Char (Lexing.lexeme lexbuf)
+ }
+
+| begin_verb
+ {
+ incr_cpts lexbuf ;
+ if !target_mode or (!open_brackets >= 1) or !code_pre_mode or !ele_ref_mode then
+ Char (Lexing.lexeme lexbuf)
+ else
+ (
+ verb_mode := true;
+ VERB
+ )
+ }
+| end_verb
+ {
+ incr_cpts lexbuf ;
+ if !target_mode or (!open_brackets >= 1) or !code_pre_mode or !ele_ref_mode then
+ Char (Lexing.lexeme lexbuf)
+ else
+ (
+ verb_mode := false;
+ END_VERB
+ )
+ }
+
+| shortcut_list_item
+ {
+ incr_cpts lexbuf ;
+ if !shortcut_list_mode then
+ (
+ SHORTCUT_LIST_ITEM
+ )
+ else
+ (
+ shortcut_list_mode := true;
+ BEGIN_SHORTCUT_LIST_ITEM
+ )
+ }
+
+| shortcut_enum_item
+ {
+ incr_cpts lexbuf ;
+ if !shortcut_list_mode then
+ SHORTCUT_ENUM_ITEM
+ else
+ (
+ shortcut_list_mode := true;
+ BEGIN_SHORTCUT_ENUM_ITEM
+ )
+ }
+| end_shortcut_list
+ {
+ incr_cpts lexbuf ;
+ lexbuf.Lexing.lex_curr_pos <- lexbuf.Lexing.lex_curr_pos - 1;
+ lexbuf.Lexing.lex_curr_p <-
+ { lexbuf.Lexing.lex_curr_p with
+ pos_cnum = lexbuf.Lexing.lex_curr_p.pos_cnum - 1 ;
+ } ;
+ decr line_number ;
+ if !shortcut_list_mode then
+ (
+ shortcut_list_mode := false;
+ (* go back one char to re-use the last '\n', so we can
+ restart another shortcut-list with a single blank line,
+ and not two.*)
+ END_SHORTCUT_LIST
+ )
+ else
+ if !target_mode or (!open_brackets >= 1) or !code_pre_mode or !ele_ref_mode or !verb_mode then
+ Char (Lexing.lexeme lexbuf)
+ else
+ BLANK_LINE
+ }
+
+| eof { EOF }
+
+| begin_custom
+ {
+ print_DEBUG "begin_custom";
+ incr_cpts lexbuf ;
+ if !verb_mode or !target_mode or !code_pre_mode or
+ (!open_brackets >= 1) or !ele_ref_mode then
+ Char (Lexing.lexeme lexbuf)
+ else
+ let s = Lexing.lexeme lexbuf in
+ let len = String.length s in
+ (* remove this starting '{' *)
+ let tag = Odoc_misc.no_blanks (String.sub s 1 (len - 1)) in
+ CUSTOM tag
+ }
+
+| "{"
+ {
+ incr_cpts lexbuf ;
+ if !target_mode or (!open_brackets >= 1) or !code_pre_mode or !ele_ref_mode then
+ Char (Lexing.lexeme lexbuf)
+ else
+ LBRACE
+ }
+| _
+ {
+ incr_cpts lexbuf ;
+ Char (Lexing.lexeme lexbuf)
+ }
diff --git a/ocaml-binary-annot/ocamldoc/odoc_text_parser.mly b/ocaml-binary-annot/ocamldoc/odoc_text_parser.mly
new file mode 100644
index 0000000000..478cfa074e
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_text_parser.mly
@@ -0,0 +1,197 @@
+%{
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+open Odoc_types
+
+let identchar =
+ "[A-Z a-z_\192-\214\216-\246\248-\255'0-9]"
+let blank = "[ \010\013\009\012]"
+
+let remove_beginning_blanks s =
+ Str.global_replace (Str.regexp ("^"^blank^"+")) "" s
+
+let remove_trailing_blanks s =
+ Str.global_replace (Str.regexp (blank^"+$")) "" s
+
+let print_DEBUG s = print_string s; print_newline ()
+%}
+
+%token END
+%token <int * string option> Title
+%token BOLD
+%token EMP
+%token CENTER
+%token LEFT
+%token RIGHT
+%token ITALIC
+%token <string> CUSTOM
+%token LIST
+%token ENUM
+%token ITEM
+%token LINK
+%token CODE
+%token END_CODE
+%token CODE_PRE
+%token END_CODE_PRE
+%token VERB
+%token END_VERB
+%token LATEX
+%token <string> Target
+%token END_TARGET
+%token LBRACE
+
+%token ELE_REF
+%token VAL_REF
+%token TYP_REF
+%token EXC_REF
+%token MOD_REF
+%token MODT_REF
+%token CLA_REF
+%token CLT_REF
+%token ATT_REF
+%token MET_REF
+%token SEC_REF
+%token MOD_LIST_REF
+%token INDEX_LIST
+
+%token SUPERSCRIPT
+%token SUBSCRIPT
+
+%token BEGIN_SHORTCUT_LIST_ITEM
+%token BEGIN_SHORTCUT_ENUM_ITEM
+%token SHORTCUT_LIST_ITEM
+%token SHORTCUT_ENUM_ITEM
+%token END_SHORTCUT_LIST
+
+%token BLANK_LINE
+
+%token EOF
+%token <string> Char
+
+/* Start Symbols */
+%start main
+%type <Odoc_types.text> main
+
+%%
+main:
+ text EOF { $1 }
+| EOF { [Raw ""] }
+;
+
+text:
+ text_element_list { $1 }
+;
+
+text_element_list:
+ text_element { [ $1 ] }
+| text_element text_element_list { $1 :: $2 }
+;
+
+ele_ref_kind:
+ ELE_REF { None }
+| VAL_REF { Some RK_value }
+| TYP_REF { Some RK_type }
+| EXC_REF { Some RK_exception }
+| MOD_REF { Some RK_module }
+| MODT_REF { Some RK_module_type }
+| CLA_REF { Some RK_class }
+| CLT_REF { Some RK_class_type }
+| ATT_REF { Some RK_attribute }
+| MET_REF { Some RK_method }
+| SEC_REF { Some (RK_section [])}
+;
+
+text_element:
+ Title text END { let n, l_opt = $1 in Title (n, l_opt, $2) }
+| BOLD text END { Bold $2 }
+| ITALIC text END { Italic $2 }
+| CUSTOM text END { Custom ($1, $2) }
+| EMP text END { Emphasize $2 }
+| SUPERSCRIPT text END { Superscript $2 }
+| SUBSCRIPT text END { Subscript $2 }
+| CENTER text END { Center $2 }
+| LEFT text END { Left $2 }
+| RIGHT text END { Right $2 }
+| LIST list END { List $2 }
+| ENUM list END { Enum $2 }
+| CODE string END_CODE { Code $2 }
+| CODE_PRE string END_CODE_PRE { CodePre $2 }
+| ele_ref_kind string END {
+ let s2 = remove_beginning_blanks $2 in
+ let s3 = remove_trailing_blanks s2 in
+ Ref (s3, $1, None)
+ }
+| LBRACE ele_ref_kind string END text END {
+ let s2 = remove_beginning_blanks $3 in
+ let s3 = remove_trailing_blanks s2 in
+ Ref (s3, $2, Some $5)
+ }
+
+| MOD_LIST_REF string END {
+ let s2 = remove_beginning_blanks $2 in
+ let s3 = remove_trailing_blanks s2 in
+ let l = Odoc_misc.split_with_blanks s3 in
+ Module_list l
+ }
+| INDEX_LIST { Index_list }
+| VERB string END_VERB { Verbatim $2 }
+| LATEX string END_TARGET { Latex $2 }
+| Target string END_TARGET { Target ($1, $2) }
+| LINK string END text END { Link ($2, $4) }
+| BLANK_LINE { Newline }
+| BEGIN_SHORTCUT_LIST_ITEM shortcut_list END_SHORTCUT_LIST { List $2 }
+| BEGIN_SHORTCUT_LIST_ITEM shortcut_list EOF { List $2 }
+| BEGIN_SHORTCUT_ENUM_ITEM shortcut_enum END_SHORTCUT_LIST { Enum $2 }
+| BEGIN_SHORTCUT_ENUM_ITEM shortcut_enum EOF { Enum $2 }
+| string { Raw $1 }
+;
+
+list:
+| string { [] (* A VOIR : un test pour voir qu'il n'y a que des blancs *) }
+| string list { $2 }
+| list string { $1 }
+| item { [ $1 ] }
+| item list { $1 :: $2 }
+
+;
+
+item:
+ ITEM text END { $2 }
+;
+
+shortcut_list:
+ text shortcut_list2 { $1 :: $2 }
+| text { [ $1 ] }
+;
+
+shortcut_list2:
+| SHORTCUT_LIST_ITEM shortcut_list { $2 }
+;
+
+shortcut_enum:
+ text shortcut_enum2 { $1 :: $2 }
+| text { [ $1 ] }
+;
+
+shortcut_enum2:
+| SHORTCUT_ENUM_ITEM shortcut_enum { $2 }
+;
+
+
+string:
+ Char { $1 }
+| Char string { $1^$2 }
+;
+
+%%
diff --git a/ocaml-binary-annot/ocamldoc/odoc_to_text.ml b/ocaml-binary-annot/ocamldoc/odoc_to_text.ml
new file mode 100644
index 0000000000..591f81d613
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_to_text.ml
@@ -0,0 +1,603 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Text generation.
+
+ This module contains the class [to_text] with methods used to transform
+ information about elements to a [text] structure.*)
+
+open Odoc_info
+open Exception
+open Type
+open Value
+open Module
+open Class
+open Parameter
+
+(** A class used to get a [text] for info structures. *)
+class virtual info =
+ object (self)
+ (** The list of pairs [(tag, f)] where [f] is a function taking
+ the [text] associated to [tag] and returning a [text].
+ Add a pair here to handle a tag.*)
+ val mutable tag_functions = ([] : (string * (Odoc_info.text -> Odoc_info.text)) list)
+
+ (** @return [etxt] value for an authors list. *)
+ method text_of_author_list l =
+ match l with
+ [] ->
+ []
+ | _ ->
+ [ Bold [Raw (Odoc_messages.authors^": ")] ;
+ Raw (String.concat ", " l) ;
+ Newline
+ ]
+
+ (** @return [text] value for the given optional version information.*)
+ method text_of_version_opt v_opt =
+ match v_opt with
+ None -> []
+ | Some v -> [ Bold [Raw (Odoc_messages.version^": ")] ;
+ Raw v ;
+ Newline
+ ]
+
+ (** @return [text] value for the given optional since information.*)
+ method text_of_since_opt s_opt =
+ match s_opt with
+ None -> []
+ | Some s -> [ Bold [Raw (Odoc_messages.since^": ")] ;
+ Raw s ;
+ Newline
+ ]
+
+ (** @return [text] value to represent the list of "before" information. *)
+ method text_of_before = function
+ [] -> []
+ | l ->
+ let f (v, text) =
+ (Bold [Raw (Printf.sprintf "%s %s " Odoc_messages.before v) ]) ::
+ text @
+ [Newline]
+ in
+ List.flatten (List.map f l)
+
+ (** @return [text] value for the given list of raised exceptions.*)
+ method text_of_raised_exceptions l =
+ match l with
+ [] -> []
+ | (s, t) :: [] ->
+ [ Bold [ Raw Odoc_messages.raises ] ;
+ Raw " " ;
+ Code s ;
+ Raw " "
+ ]
+ @ t
+ @ [ Newline ]
+ | _ ->
+ [ Bold [ Raw Odoc_messages.raises ] ;
+ Raw " " ;
+ List
+ (List.map
+ (fun (ex, desc) ->(Code ex) :: (Raw " ") :: desc )
+ l
+ ) ;
+ Newline
+ ]
+
+ (** Return [text] value for the given "see also" reference. *)
+ method text_of_see (see_ref, t) =
+ let t_ref =
+ match see_ref with
+ Odoc_info.See_url s -> [ Odoc_info.Link (s, t) ]
+ | Odoc_info.See_file s -> (Odoc_info.Code s) :: (Odoc_info.Raw " ") :: t
+ | Odoc_info.See_doc s -> (Odoc_info.Italic [Odoc_info.Raw s]) :: (Odoc_info.Raw " ") :: t
+ in
+ t_ref
+
+ (** Return [text] value for the given list of "see also" references.*)
+ method text_of_sees l =
+ match l with
+ [] -> []
+ | see :: [] ->
+ (Bold [ Raw Odoc_messages.see_also ]) ::
+ (Raw " ") ::
+ (self#text_of_see see) @ [ Newline ]
+ | _ ->
+ (Bold [ Raw Odoc_messages.see_also ]) ::
+ [ List
+ (List.map
+ (fun see -> self#text_of_see see)
+ l
+ );
+ Newline
+ ]
+
+ (** @return [text] value for the given optional return information.*)
+ method text_of_return_opt return_opt =
+ match return_opt with
+ None -> []
+ | Some t -> (Bold [Raw (Odoc_messages.returns^" ")]) :: t @ [ Newline ]
+
+ (** Return a [text] for the given list of custom tagged texts. *)
+ method text_of_custom l =
+ List.fold_left
+ (fun acc -> fun (tag, text) ->
+ try
+ let f = List.assoc tag tag_functions in
+ match acc with
+ [] -> f text
+ | _ -> acc @ (Newline :: (f text))
+ with
+ Not_found ->
+ Odoc_info.warning (Odoc_messages.tag_not_handled tag) ;
+ acc
+ )
+ []
+ l
+
+ (** @return [text] value for a description, except for the i_params field. *)
+ method text_of_info ?(block=true) info_opt =
+ match info_opt with
+ None ->
+ []
+ | Some info ->
+ let t =
+ (match info.i_deprecated with
+ None -> []
+ | Some t -> ( Italic [Raw (Odoc_messages.deprecated^" ")] ) :: t
+ ) @
+ (match info.i_desc with
+ None -> []
+ | Some t when t = [Odoc_info.Raw ""] -> []
+ | Some t -> t @ [ Newline ]
+ ) @
+ (self#text_of_author_list info.i_authors) @
+ (self#text_of_version_opt info.i_version) @
+ (self#text_of_before info.i_before) @
+ (self#text_of_since_opt info.i_since) @
+ (self#text_of_raised_exceptions info.i_raised_exceptions) @
+ (self#text_of_return_opt info.i_return_value) @
+ (self#text_of_sees info.i_sees) @
+ (self#text_of_custom info.i_custom)
+ in
+ if block then
+ [Block t]
+ else
+ t
+ end
+
+(** This class defines methods to generate a [text] structure from elements. *)
+class virtual to_text =
+ object (self)
+ inherit info
+
+ method virtual label : ?no_: bool -> string -> string
+
+ (** Take a string and return the string where fully qualified idents
+ have been replaced by idents relative to the given module name.
+ Also remove the "hidden modules".*)
+ method relative_idents m_name s =
+ let f str_t =
+ let match_s = Str.matched_string str_t in
+ let rel = Name.get_relative m_name match_s in
+ Odoc_info.apply_if_equal Odoc_info.use_hidden_modules match_s rel
+ in
+ let s2 = Str.global_substitute
+ (Str.regexp "\\([A-Z]\\([a-zA-Z_'0-9]\\)*\\.\\)+\\([a-z][a-zA-Z_'0-9]*\\)")
+ f
+ s
+ in
+ s2
+
+ (** Take a string and return the string where fully qualified idents
+ have been replaced by idents relative to the given module name.
+ Also remove the "hidden modules".*)
+ method relative_module_idents m_name s =
+ let f str_t =
+ let match_s = Str.matched_string str_t in
+ let rel = Name.get_relative m_name match_s in
+ Odoc_info.apply_if_equal Odoc_info.use_hidden_modules match_s rel
+ in
+ let s2 = Str.global_substitute
+ (Str.regexp "\\([A-Z]\\([a-zA-Z_'0-9]\\)*\\.\\)+\\([A-Z][a-zA-Z_'0-9]*\\)")
+ f
+ s
+ in
+ s2
+
+ (** Get a string for a [Types.class_type] where all idents are relative. *)
+ method normal_class_type m_name t =
+ self#relative_idents m_name (Odoc_info.string_of_class_type t)
+
+ (** Get a string for a [Types.module_type] where all idents are relative. *)
+ method normal_module_type ?code m_name t =
+ self#relative_module_idents m_name (Odoc_info.string_of_module_type ?code t)
+
+ (** Get a string for a type where all idents are relative. *)
+ method normal_type m_name t =
+ self#relative_idents m_name (Odoc_info.string_of_type_expr t)
+
+ (** Get a string for a list of types where all idents are relative. *)
+ method normal_type_list ?par m_name sep t =
+ self#relative_idents m_name (Odoc_info.string_of_type_list ?par sep t)
+
+ (** Get a string for a list of class or class type type parameters
+ where all idents are relative. *)
+ method normal_class_type_param_list m_name t =
+ self#relative_idents m_name (Odoc_info.string_of_class_type_param_list t)
+
+ (** Get a string for the parameters of a class (with arrows) where all idents are relative. *)
+ method normal_class_params m_name c =
+ let s = Odoc_info.string_of_class_params c in
+ self#relative_idents m_name
+ (Odoc_info.remove_ending_newline s)
+
+ (** @return [text] value to represent a [Types.type_expr].*)
+ method text_of_type_expr module_name t =
+ let t = List.flatten
+ (List.map
+ (fun s -> [Code s ; Newline ])
+ (Str.split (Str.regexp "\n")
+ (self#normal_type module_name t))
+ )
+ in
+ t
+
+ (** Return [text] value for a given short [Types.type_expr].*)
+ method text_of_short_type_expr module_name t =
+ [ Code (self#normal_type module_name t) ]
+
+ (** Return [text] value or the given list of [Types.type_expr], with
+ the given separator. *)
+ method text_of_type_expr_list module_name sep l =
+ [ Code (self#normal_type_list module_name sep l) ]
+
+ (** Return [text] value or the given list of [Types.type_expr],
+ as type parameters of a class of class type. *)
+ method text_of_class_type_param_expr_list module_name l =
+ [ Code (self#normal_class_type_param_list module_name l) ]
+
+ (** @return [text] value to represent parameters of a class (with arraows).*)
+ method text_of_class_params module_name c =
+ let t = Odoc_info.text_concat
+ [Newline]
+ (List.map
+ (fun s -> [Code s])
+ (Str.split (Str.regexp "\n")
+ (self#normal_class_params module_name c))
+ )
+ in
+ t
+
+ (** @return [text] value to represent a [Types.module_type]. *)
+ method text_of_module_type t =
+ let s = String.concat "\n"
+ (Str.split (Str.regexp "\n") (Odoc_info.string_of_module_type t))
+ in
+ [ Code s ]
+
+ (** @return [text] value for a value. *)
+ method text_of_value v =
+ let name = v.val_name in
+ let s_name = Name.simple name in
+ let s =
+ Format.fprintf Format.str_formatter "@[<hov 2>val %s :@ %s"
+ s_name
+ (self#normal_type (Name.father v.val_name) v.val_type);
+ Format.flush_str_formatter ()
+ in
+ [ CodePre s ] @
+ [Latex ("\\index{"^(self#label s_name)^"@\\verb`"^(self#label ~no_:false s_name)^"`}\n")] @
+ (self#text_of_info v.val_info)
+
+ (** @return [text] value for a class attribute. *)
+ method text_of_attribute a =
+ let s_name = Name.simple a.att_value.val_name in
+ let mod_name = Name.father a.att_value.val_name in
+ let s =
+ Format.fprintf Format.str_formatter "@[<hov 2>val %s%s%s :@ %s"
+ (if a.att_virtual then "virtual " else "")
+ (if a.att_mutable then "mutable " else "")
+ s_name
+ (self#normal_type mod_name a.att_value.val_type);
+ Format.flush_str_formatter ()
+ in
+ (CodePre s) ::
+ [Latex ("\\index{"^(self#label s_name)^"@\\verb`"^(self#label ~no_:false s_name)^"`}\n")] @
+ (self#text_of_info a.att_value.val_info)
+
+ (** @return [text] value for a class method. *)
+ method text_of_method m =
+ let s_name = Name.simple m.met_value.val_name in
+ let mod_name = Name.father m.met_value.val_name in
+ let s =
+ Format.fprintf Format.str_formatter "@[<hov 2>method %s%s%s :@ %s"
+ (if m.met_private then "private " else "")
+ (if m.met_virtual then "virtual " else "")
+ s_name
+ (self#normal_type mod_name m.met_value.val_type);
+ Format.flush_str_formatter ()
+ in
+ (CodePre s) ::
+ [Latex ("\\index{"^(self#label s_name)^"@\\verb`"^(self#label ~no_:false s_name)^"`}\n")] @
+ (self#text_of_info m.met_value.val_info)
+
+
+ (** @return [text] value for an exception. *)
+ method text_of_exception e =
+ let s_name = Name.simple e.ex_name in
+ Format.fprintf Format.str_formatter "@[<hov 2>exception %s" s_name ;
+ (match e.ex_args with
+ [] -> ()
+ | _ ->
+ Format.fprintf Format.str_formatter "@ of "
+ );
+ let s = self#normal_type_list
+ ~par: false (Name.father e.ex_name) " * " e.ex_args
+ in
+ let s2 =
+ Format.fprintf Format.str_formatter "%s" s ;
+ (match e.ex_alias with
+ None -> ()
+ | Some ea ->
+ Format.fprintf Format.str_formatter " = %s"
+ (
+ match ea.ea_ex with
+ None -> ea.ea_name
+ | Some e -> e.ex_name
+ )
+ );
+ Format.flush_str_formatter ()
+ in
+ [ CodePre s2 ] @
+ [Latex ("\\index{"^(self#label s_name)^"@\\verb`"^(self#label ~no_:false s_name)^"`}\n")] @
+ (self#text_of_info e.ex_info)
+
+ (** Return [text] value for the description of a function parameter. *)
+ method text_of_parameter_description p =
+ match Parameter.names p with
+ [] -> []
+ | name :: [] ->
+ (
+ (* Only one name, no need for label for the description. *)
+ match Parameter.desc_by_name p name with
+ None -> []
+ | Some t -> t
+ )
+ | l ->
+ (* A list of names, we display those with a description. *)
+ let l2 = List.filter (fun n -> (Parameter.desc_by_name p n) <> None) l in
+ match l2 with
+ [] -> []
+ | _ ->
+ [List
+ (List.map
+ (fun n ->
+ match Parameter.desc_by_name p n with
+ None -> [] (* should not occur *)
+ | Some t -> [Code (n^" ") ; Raw ": "] @ t
+ )
+ l2
+ )
+ ]
+
+
+ (** Return [text] value for a list of parameters. *)
+ method text_of_parameter_list m_name l =
+ match l with
+ [] ->
+ []
+ | _ ->
+ [ Bold [Raw Odoc_messages.parameters] ;
+ Raw ":" ;
+ List
+ (List.map
+ (fun p ->
+ (match Parameter.complete_name p with
+ "" -> Code "?"
+ | s -> Code s
+ ) ::
+ [Code " : "] @
+ (self#text_of_short_type_expr m_name (Parameter.typ p)) @
+ [Newline] @
+ (self#text_of_parameter_description p)
+ )
+ l
+ )
+ ]
+
+ (** Return [text] value for a list of module parameters. *)
+ method text_of_module_parameter_list l =
+ match l with
+ [] ->
+ []
+ | _ ->
+ [ Newline ;
+ Bold [Raw Odoc_messages.parameters] ;
+ Raw ":" ;
+ List
+ (List.map
+ (fun (p, desc_opt) ->
+ [Code (p.mp_name^" : ")] @
+ (self#text_of_module_type p.mp_type) @
+ (match desc_opt with
+ None -> []
+ | Some t -> (Raw " ") :: t)
+ )
+ l
+ )
+ ]
+
+(**/**)
+
+ (** Return [text] value for the given [class_kind].*)
+ method text_of_class_kind father ckind =
+ match ckind with
+ Class_structure _ ->
+ [Code Odoc_messages.object_end]
+
+ | Class_apply capp ->
+ [Code
+ (
+ (
+ match capp.capp_class with
+ None -> capp.capp_name
+ | Some cl -> cl.cl_name
+ )^
+ " "^
+ (String.concat " "
+ (List.map
+ (fun s -> "("^s^")")
+ capp.capp_params_code))
+ )
+ ]
+
+ | Class_constr cco ->
+ (
+ match cco.cco_type_parameters with
+ [] -> []
+ | l ->
+ (Code "[")::
+ (self#text_of_type_expr_list father ", " l)@
+ [Code "] "]
+ )@
+ [Code (
+ match cco.cco_class with
+ None -> cco.cco_name
+ | Some (Cl cl) -> Name.get_relative father cl.cl_name
+ | Some (Cltype (clt,_)) -> Name.get_relative father clt.clt_name
+ )
+ ]
+
+ | Class_constraint (ck, ctk) ->
+ [Code "( "] @
+ (self#text_of_class_kind father ck) @
+ [Code " : "] @
+ (self#text_of_class_type_kind father ctk) @
+ [Code " )"]
+
+
+ (** Return [text] value for the given [class_type_kind].*)
+ method text_of_class_type_kind father ctkind =
+ match ctkind with
+ Class_type cta ->
+ (
+ match cta.cta_type_parameters with
+ [] -> []
+ | l ->
+ (Code "[") ::
+ (self#text_of_class_type_param_expr_list father l) @
+ [Code "] "]
+ ) @
+ (
+ match cta.cta_class with
+ None -> [ Code cta.cta_name ]
+ | Some (Cltype (clt, _)) ->
+ let rel = Name.get_relative father clt.clt_name in
+ [Code rel]
+ | Some (Cl cl) ->
+ let rel = Name.get_relative father cl.cl_name in
+ [Code rel]
+ )
+ | Class_signature _ ->
+ [Code Odoc_messages.object_end]
+
+ (** Return [text] value for a [module_kind]. *)
+ method text_of_module_kind ?(with_def_syntax=true) k =
+ match k with
+ Module_alias m_alias ->
+ (match m_alias.ma_module with
+ None ->
+ [Code ((if with_def_syntax then " = " else "")^m_alias.ma_name)]
+ | Some (Mod m) ->
+ [Code ((if with_def_syntax then " = " else "")^m.m_name)]
+ | Some (Modtype mt) ->
+ [Code ((if with_def_syntax then " = " else "")^mt.mt_name)]
+ )
+ | Module_apply (k1, k2) ->
+ (if with_def_syntax then [Code " = "] else []) @
+ (self#text_of_module_kind ~with_def_syntax: false k1) @
+ [Code " ( "] @
+ (self#text_of_module_kind ~with_def_syntax: false k2) @
+ [Code " ) "]
+
+ | Module_with (tk, code) ->
+ (if with_def_syntax then [Code " : "] else []) @
+ (self#text_of_module_type_kind ~with_def_syntax: false tk) @
+ [Code code]
+
+ | Module_constraint (k, tk) ->
+ (if with_def_syntax then [Code " : "] else []) @
+ [Code "( "] @
+ (self#text_of_module_kind ~with_def_syntax: false k) @
+ [Code " : "] @
+ (self#text_of_module_type_kind ~with_def_syntax: false tk) @
+ [Code " )"]
+
+ | Module_struct _ ->
+ [Code ((if with_def_syntax then " : " else "")^
+ Odoc_messages.struct_end^" ")]
+
+ | Module_functor (p, k) ->
+ (if with_def_syntax then [Code " : "] else []) @
+ [Code "functor ... "] @
+ [Code " -> "] @
+ (self#text_of_module_kind ~with_def_syntax: false k)
+
+ | Module_typeof s ->
+ let code = Printf.sprintf "%smodule type of %s"
+ (if with_def_syntax then " : " else "")
+ s
+ in
+ [Code code]
+ | Module_unpack (code, _) ->
+ let code = Printf.sprintf "%s%s"
+ (if with_def_syntax then " : " else "")
+ code
+ in
+ [Code code]
+
+ (** Return html code for a [module_type_kind].*)
+ method text_of_module_type_kind ?(with_def_syntax=true) tk =
+ match tk with
+ | Module_type_struct _ ->
+ [Code ((if with_def_syntax then " = " else "")^Odoc_messages.sig_end)]
+
+ | Module_type_functor (p, k) ->
+ let t1 =
+ [Code ("("^p.mp_name^" : ")] @
+ (self#text_of_module_type_kind p.mp_kind) @
+ [Code ") -> "]
+ in
+ let t2 = self#text_of_module_type_kind ~with_def_syntax: false k in
+ (if with_def_syntax then [Code " = "] else []) @ t1 @ t2
+
+ | Module_type_with (tk2, code) ->
+ let t = self#text_of_module_type_kind ~with_def_syntax: false tk2 in
+ (if with_def_syntax then [Code " = "] else []) @
+ t @ [Code code]
+
+ | Module_type_alias mt_alias ->
+ [Code ((if with_def_syntax then " = " else "")^
+ (match mt_alias.mta_module with
+ None -> mt_alias.mta_name
+ | Some mt -> mt.mt_name))
+ ]
+
+ | Odoc_module.Module_type_typeof s ->
+ let code = Printf.sprintf "%smodule type of %s"
+ (if with_def_syntax then " = " else "") s
+ in
+ [ Code code ]
+ end
diff --git a/ocaml-binary-annot/ocamldoc/odoc_type.ml b/ocaml-binary-annot/ocamldoc/odoc_type.ml
new file mode 100644
index 0000000000..9d19dc67d9
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_type.ml
@@ -0,0 +1,55 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Representation and manipulation of a type, but not class nor module type.*)
+
+module Name = Odoc_name
+
+type private_flag = Asttypes.private_flag =
+ Private | Public
+
+(** Description of a variant type constructor. *)
+type variant_constructor = {
+ vc_name : string ;
+ vc_args : Types.type_expr list ; (** arguments of the constructor *)
+ mutable vc_text : Odoc_types.text option ; (** optional user description *)
+ }
+
+(** Description of a record type field. *)
+type record_field = {
+ rf_name : string ;
+ rf_mutable : bool ; (** true if mutable *)
+ rf_type : Types.type_expr ;
+ mutable rf_text : Odoc_types.text option ; (** optional user description *)
+ }
+
+(** The various kinds of type. *)
+type type_kind =
+ Type_abstract
+ | Type_variant of variant_constructor list
+ (** constructors *)
+ | Type_record of record_field list
+ (** fields *)
+
+(** Representation of a type. *)
+type t_type = {
+ ty_name : Name.t ;
+ mutable ty_info : Odoc_types.info option ; (** optional user information *)
+ ty_parameters : (Types.type_expr * bool * bool) list ;
+ (** type parameters: (type, covariant, contravariant) *)
+ ty_kind : type_kind ;
+ ty_private : private_flag;
+ ty_manifest : Types.type_expr option; (** type manifest *)
+ mutable ty_loc : Odoc_types.location ;
+ mutable ty_code : string option;
+ }
diff --git a/ocaml-binary-annot/ocamldoc/odoc_types.ml b/ocaml-binary-annot/ocamldoc/odoc_types.ml
new file mode 100644
index 0000000000..5c58afe165
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_types.ml
@@ -0,0 +1,136 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+type ref_kind =
+ RK_module
+ | RK_module_type
+ | RK_class
+ | RK_class_type
+ | RK_value
+ | RK_type
+ | RK_exception
+ | RK_attribute
+ | RK_method
+ | RK_section of text
+
+and text_element =
+ | Raw of string
+ | Code of string
+ | CodePre of string
+ | Verbatim of string
+ | Bold of text
+ | Italic of text
+ | Emphasize of text
+ | Center of text
+ | Left of text
+ | Right of text
+ | List of text list
+ | Enum of text list
+ | Newline
+ | Block of text
+ | Title of int * string option * text
+ | Latex of string
+ | Link of string * text
+ | Ref of string * ref_kind option * text option
+ | Superscript of text
+ | Subscript of text
+ | Module_list of string list
+ | Index_list
+ | Custom of string * text
+ | Target of string * string
+
+and text = text_element list
+
+type see_ref =
+ See_url of string
+ | See_file of string
+ | See_doc of string
+
+type see = see_ref * text
+
+type param = (string * text)
+
+type raised_exception = (string * text)
+
+type info = {
+ i_desc : text option;
+ i_authors : string list;
+ i_version : string option;
+ i_sees : see list;
+ i_since : string option;
+ i_before : (string * text) list;
+ i_deprecated : text option;
+ i_params : param list;
+ i_raised_exceptions : raised_exception list;
+ i_return_value : text option ;
+ i_custom : (string * text) list ;
+ }
+
+let dummy_info = {
+ i_desc = None ;
+ i_authors = [] ;
+ i_version = None ;
+ i_sees = [] ;
+ i_since = None ;
+ i_before = [] ;
+ i_deprecated = None ;
+ i_params = [] ;
+ i_raised_exceptions = [] ;
+ i_return_value = None ;
+ i_custom = [] ;
+}
+
+type location = {
+ loc_impl : (string * int) option ;
+ loc_inter : (string * int) option ;
+ }
+
+let dummy_loc = { loc_impl = None ; loc_inter = None }
+
+type merge_option =
+ | Merge_description
+ | Merge_author
+ | Merge_version
+ | Merge_see
+ | Merge_since
+ | Merge_deprecated
+ | Merge_param
+ | Merge_raised_exception
+ | Merge_return_value
+ | Merge_custom
+
+let all_merge_options = [
+ Merge_description ;
+ Merge_author ;
+ Merge_version ;
+ Merge_see ;
+ Merge_since ;
+ Merge_deprecated ;
+ Merge_param ;
+ Merge_raised_exception ;
+ Merge_return_value ;
+ Merge_custom ;
+]
+
+type magic = string
+
+let magic = Odoc_messages.magic
+
+type 'a dump = Dump of magic * 'a
+
+let make_dump a = Dump (magic, a)
+
+let open_dump = function
+ Dump (m, a) ->
+ if m = magic then a
+ else raise (Failure Odoc_messages.bad_magic_number)
diff --git a/ocaml-binary-annot/ocamldoc/odoc_types.mli b/ocaml-binary-annot/ocamldoc/odoc_types.mli
new file mode 100644
index 0000000000..639697f593
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_types.mli
@@ -0,0 +1,136 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Types for the information collected in comments. *)
+
+(** The differents kinds of element references. *)
+type ref_kind =
+ RK_module
+ | RK_module_type
+ | RK_class
+ | RK_class_type
+ | RK_value
+ | RK_type
+ | RK_exception
+ | RK_attribute
+ | RK_method
+ | RK_section of text
+
+and text_element =
+ | Raw of string (** Raw text. *)
+ | Code of string (** The string is source code. *)
+ | CodePre of string (** The string is pre-formatted source code. *)
+ | Verbatim of string (** String 'as is'. *)
+ | Bold of text (** Text in bold style. *)
+ | Italic of text (** Text in italic. *)
+ | Emphasize of text (** Emphasized text. *)
+ | Center of text (** Centered text. *)
+ | Left of text (** Left alignment. *)
+ | Right of text (** Right alignment. *)
+ | List of text list (** A list. *)
+ | Enum of text list (** An enumerated list. *)
+ | Newline (** To force a line break. *)
+ | Block of text (** Like html's block quote. *)
+ | Title of int * string option * text
+ (** Style number, optional label, and text. *)
+ | Latex of string (** A string for latex. *)
+ | Link of string * text (** A reference string and the link text. *)
+ | Ref of string * ref_kind option * text option
+ (** A reference to an element. Complete name and kind. An optional
+ text can be given to display this text instead of the element name.*)
+ | Superscript of text (** Superscripts. *)
+ | Subscript of text (** Subscripts. *)
+ | Module_list of string list
+ (** The table of the given modules with their abstract; *)
+ | Index_list (** The links to the various indexes (values, types, ...) *)
+ | Custom of string * text (** to extend \{foo syntax *)
+ | Target of string * string (** (target, code) : to specify code for a specific target format *)
+
+(** [text] is a list of text_elements. The order matters. *)
+and text = text_element list
+
+(** The different forms of references in \@see tags. *)
+type see_ref =
+ See_url of string
+ | See_file of string
+ | See_doc of string
+
+(** The information in a \@see tag. *)
+type see = see_ref * text
+
+(** Parameter name and description. *)
+type param = (string * text)
+
+(** Raised exception name and description. *)
+type raised_exception = (string * text)
+
+(** Information in a special comment. *)
+type info = {
+ i_desc : text option; (** The description text. *)
+ i_authors : string list; (** The list of authors in \@author tags. *)
+ i_version : string option; (** The string in the \@version tag. *)
+ i_sees : see list; (** The list of \@see tags. *)
+ i_since : string option; (** The string in the \@since tag. *)
+ i_before : (string * text) list; (** the version number and text in \@before tag *)
+ i_deprecated : text option; (** The of the \@deprecated tag. *)
+ i_params : param list; (** The list of parameter descriptions. *)
+ i_raised_exceptions : raised_exception list; (** The list of raised exceptions. *)
+ i_return_value : text option ; (** The description text of the return value. *)
+ i_custom : (string * text) list ; (** A text associated to a custom @-tag. *)
+ }
+
+(** An empty info structure. *)
+val dummy_info : info
+
+(** Location of elements in implementation and interface files. *)
+type location = {
+ loc_impl : (string * int) option ; (** implementation file name and position *)
+ loc_inter : (string * int) option ; (** interface file name and position *)
+ }
+
+(** A dummy location. *)
+val dummy_loc : location
+
+(** The information to merge from two elements when they both have some information. *)
+type merge_option =
+ | Merge_description (** Descriptions are concatenated. *)
+ | Merge_author (** Lists of authors are concatenated. *)
+ | Merge_version (** Versions are concatenated. *)
+ | Merge_see (** See references are concatenated. *)
+ | Merge_since (** Since information are concatenated. *)
+ | Merge_deprecated (** Deprecated information are concatenated. *)
+ | Merge_param (** Information on each parameter is concatenated,
+ and all parameters are kept. *)
+ | Merge_raised_exception (** Information on each raised_exception is concatenated,
+ and all raised exceptions are kept. *)
+ | Merge_return_value (** Information on return value are concatenated. *)
+ | Merge_custom (** Merge custom tags (all pairs (tag, text) are kept). *)
+
+(** The list with all merge options. *)
+val all_merge_options : merge_option list
+
+(** Type of magic numbers. *)
+type magic
+
+(** The magic number for the dumps of this version of ocamldoc. *)
+val magic : magic
+
+(** A dump of a structure. *)
+type 'a dump
+
+(** Create a dump structure. *)
+val make_dump : 'a -> 'a dump
+
+(** Verify that a dump has the correct magic number
+ and return its content. *)
+val open_dump : 'a dump -> 'a
diff --git a/ocaml-binary-annot/ocamldoc/odoc_value.ml b/ocaml-binary-annot/ocamldoc/odoc_value.ml
new file mode 100644
index 0000000000..a210f0851e
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_value.ml
@@ -0,0 +1,144 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Representation and manipulation of values, class attributes and class methods. *)
+
+module Name = Odoc_name
+
+(** Types *)
+
+(** Representation of a value. *)
+type t_value = {
+ val_name : Name.t ;
+ mutable val_info : Odoc_types.info option ;
+ val_type : Types.type_expr ;
+ val_recursive : bool ;
+ mutable val_parameters : Odoc_parameter.parameter list ;
+ mutable val_code : string option ;
+ mutable val_loc : Odoc_types.location ;
+ }
+
+(** Representation of a class attribute. *)
+type t_attribute = {
+ att_value : t_value ; (** an attribute has almost all the same information
+ as a value *)
+ att_mutable : bool ;
+ att_virtual : bool ;
+ }
+
+(** Representation of a class method. *)
+type t_method = {
+ met_value : t_value ; (** a method has almost all the same information
+ as a value *)
+ met_private : bool ;
+ met_virtual : bool ;
+ }
+
+(** Functions *)
+
+(** Returns the text associated to the given parameter name
+ in the given value, or None. *)
+let value_parameter_text_by_name v name =
+ match v.val_info with
+ None -> None
+ | Some i ->
+ try
+ let t = List.assoc name i.Odoc_types.i_params in
+ Some t
+ with
+ Not_found ->
+ None
+
+(** Update the parameters text of a t_value, according to the val_info field. *)
+let update_value_parameters_text v =
+ let f p =
+ Odoc_parameter.update_parameter_text (value_parameter_text_by_name v) p
+ in
+ List.iter f v.val_parameters
+
+(** Create a list of (parameter name, typ) from a type, according to the arrows.
+ [parameter_list_from_arrows t = [ a ; b ]] if t = a -> b -> c.*)
+let parameter_list_from_arrows typ =
+ let rec iter t =
+ match t.Types.desc with
+ Types.Tarrow (l, t1, t2, _) ->
+ (l, t1) :: (iter t2)
+ | Types.Tlink texp
+ | Types.Tsubst texp ->
+ iter texp
+ | Types.Tpoly (texp, _) -> iter texp
+ | Types.Tvar
+ | Types.Ttuple _
+ | Types.Tconstr _
+ | Types.Tobject _
+ | Types.Tfield _
+ | Types.Tnil
+ | Types.Tunivar
+ | Types.Tpackage _
+ | Types.Tvariant _ ->
+ []
+ in
+ iter typ
+
+(** Create a list of parameters with dummy names "??" from a type list.
+ Used when we want to merge the parameters of a value, from the .ml
+ and the .mli file. In the .mli file we don't have parameter names
+ so there is nothing to merge. With this dummy list we can merge the
+ parameter names from the .ml and the type from the .mli file. *)
+let dummy_parameter_list typ =
+ let normal_name s =
+ match s with
+ "" -> s
+ | _ ->
+ match s.[0] with
+ '?' -> String.sub s 1 ((String.length s) - 1)
+ | _ -> s
+ in
+ Printtyp.mark_loops typ;
+ let liste_param = parameter_list_from_arrows typ in
+ let rec iter (label, t) =
+ match t.Types.desc with
+ | Types.Ttuple l ->
+ if label = "" then
+ Odoc_parameter.Tuple
+ (List.map (fun t2 -> iter ("", t2)) l, t)
+ else
+ (* if there is a label, then we don't want to decompose the tuple *)
+ Odoc_parameter.Simple_name
+ { Odoc_parameter.sn_name = normal_name label ;
+ Odoc_parameter.sn_type = t ;
+ Odoc_parameter.sn_text = None }
+ | Types.Tlink t2
+ | Types.Tsubst t2 ->
+ (iter (label, t2))
+
+ | _ ->
+ Odoc_parameter.Simple_name
+ { Odoc_parameter.sn_name = normal_name label ;
+ Odoc_parameter.sn_type = t ;
+ Odoc_parameter.sn_text = None }
+ in
+ List.map iter liste_param
+
+(** Return true if the value is a function, i.e. has a functional type.*)
+let is_function v =
+ let rec f t =
+ match t.Types.desc with
+ Types.Tarrow _ ->
+ true
+ | Types.Tlink t ->
+ f t
+ | _ ->
+ false
+ in
+ f v.val_type
diff --git a/ocaml-binary-annot/ocamldoc/remove_DEBUG b/ocaml-binary-annot/ocamldoc/remove_DEBUG
new file mode 100755
index 0000000000..78b11e6128
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/remove_DEBUG
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+#(***********************************************************************)
+#(* OCamldoc *)
+#(* *)
+#(* Damien Doligez, projet Moscova, INRIA Rocquencourt *)
+#(* *)
+#(* Copyright 2003 Institut National de Recherche en Informatique et *)
+#(* en Automatique. All rights reserved. This file is distributed *)
+#(* under the terms of the Q Public License version 1.0. *)
+#(* *)
+#(***********************************************************************)
+
+# $Id$
+
+# usage: remove_DEBUG <file>
+# remove from <file> every line that contains the string "DEBUG",
+# respecting the cpp # line annotation conventions
+
+echo "# 1 \"$1\""
+LC_ALL=C sed -e '/DEBUG/c\
+(* DEBUG statement removed *)' "$1"
diff --git a/ocaml-binary-annot/ocamldoc/runocamldoc b/ocaml-binary-annot/ocamldoc/runocamldoc
new file mode 100644
index 0000000000..a71d705ccd
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/runocamldoc
@@ -0,0 +1,12 @@
+#!/bin/sh
+# $Id$
+
+case "$1" in
+ true) shift
+ exec ../boot/ocamlrun -I ../otherlibs/unix -I ../otherlibs/str \
+ ./ocamldoc "$@"
+ ;;
+ *) shift
+ exec ./ocamldoc "$@"
+ ;;
+esac