utils/ccomp.cmx : utils/misc.cmx utils/config.cmx utils/clflags.cmx \
utils/ccomp.cmi
utils/ccomp.cmi :
-utils/clflags.cmo : utils/numbers.cmi utils/misc.cmi utils/config.cmi \
- utils/arg_helper.cmi utils/clflags.cmi
-utils/clflags.cmx : utils/numbers.cmx utils/misc.cmx utils/config.cmx \
- utils/arg_helper.cmx utils/clflags.cmi
-utils/clflags.cmi : utils/misc.cmi
+utils/clflags.cmo : utils/profile.cmi utils/numbers.cmi utils/misc.cmi \
+ utils/config.cmi utils/arg_helper.cmi utils/clflags.cmi
+utils/clflags.cmx : utils/profile.cmx utils/numbers.cmx utils/misc.cmx \
+ utils/config.cmx utils/arg_helper.cmx utils/clflags.cmi
+utils/clflags.cmi : utils/profile.cmi utils/misc.cmi
utils/config.cmo : utils/config.cmi
utils/config.cmx : utils/config.cmi
utils/config.cmi :
utils/misc.cmo : utils/misc.cmi
utils/misc.cmx : utils/misc.cmi
utils/misc.cmi :
-utils/numbers.cmo : utils/identifiable.cmi utils/numbers.cmi
-utils/numbers.cmx : utils/identifiable.cmx utils/numbers.cmi
+utils/numbers.cmo : utils/misc.cmi utils/identifiable.cmi utils/numbers.cmi
+utils/numbers.cmx : utils/misc.cmx utils/identifiable.cmx utils/numbers.cmi
utils/numbers.cmi : utils/identifiable.cmi
+utils/profile.cmo : utils/misc.cmi utils/profile.cmi
+utils/profile.cmx : utils/misc.cmx utils/profile.cmi
+utils/profile.cmi :
utils/strongly_connected_components.cmo : utils/numbers.cmi utils/misc.cmi \
utils/identifiable.cmi utils/strongly_connected_components.cmi
utils/strongly_connected_components.cmx : utils/numbers.cmx utils/misc.cmx \
utils/terminfo.cmo : utils/terminfo.cmi
utils/terminfo.cmx : utils/terminfo.cmi
utils/terminfo.cmi :
-utils/timings.cmo : utils/timings.cmi
-utils/timings.cmx : utils/timings.cmi
-utils/timings.cmi :
utils/warnings.cmo : utils/misc.cmi utils/warnings.cmi
utils/warnings.cmx : utils/misc.cmx utils/warnings.cmi
utils/warnings.cmi :
parsing/attr_helper.cmi : parsing/parsetree.cmi parsing/location.cmi \
parsing/asttypes.cmi
parsing/builtin_attributes.cmo : utils/warnings.cmi parsing/parsetree.cmi \
- parsing/location.cmi parsing/asttypes.cmi parsing/ast_iterator.cmi \
- parsing/builtin_attributes.cmi
+ parsing/location.cmi parsing/asttypes.cmi parsing/builtin_attributes.cmi
parsing/builtin_attributes.cmx : utils/warnings.cmx parsing/parsetree.cmi \
- parsing/location.cmx parsing/asttypes.cmi parsing/ast_iterator.cmx \
- parsing/builtin_attributes.cmi
-parsing/builtin_attributes.cmi : parsing/parsetree.cmi parsing/location.cmi \
- parsing/ast_iterator.cmi
+ parsing/location.cmx parsing/asttypes.cmi parsing/builtin_attributes.cmi
+parsing/builtin_attributes.cmi : parsing/parsetree.cmi parsing/location.cmi
parsing/depend.cmo : parsing/parsetree.cmi utils/misc.cmi \
parsing/longident.cmi parsing/location.cmi utils/clflags.cmi \
parsing/builtin_attributes.cmi parsing/asttypes.cmi parsing/depend.cmi
typing/path.cmi parsing/longident.cmi parsing/location.cmi \
typing/ident.cmi utils/consistbl.cmi typing/cmi_format.cmi \
parsing/asttypes.cmi
-typing/envaux.cmo : typing/types.cmi typing/subst.cmi typing/printtyp.cmi \
- typing/path.cmi utils/misc.cmi typing/ident.cmi typing/env.cmi \
- parsing/asttypes.cmi typing/envaux.cmi
-typing/envaux.cmx : typing/types.cmx typing/subst.cmx typing/printtyp.cmx \
- typing/path.cmx utils/misc.cmx typing/ident.cmx typing/env.cmx \
- parsing/asttypes.cmi typing/envaux.cmi
+typing/envaux.cmo : typing/subst.cmi typing/printtyp.cmi typing/path.cmi \
+ typing/ident.cmi typing/env.cmi parsing/asttypes.cmi typing/envaux.cmi
+typing/envaux.cmx : typing/subst.cmx typing/printtyp.cmx typing/path.cmx \
+ typing/ident.cmx typing/env.cmx parsing/asttypes.cmi typing/envaux.cmi
typing/envaux.cmi : typing/subst.cmi typing/path.cmi typing/env.cmi
typing/ident.cmo : utils/identifiable.cmi typing/ident.cmi
typing/ident.cmx : utils/identifiable.cmx typing/ident.cmi
typing/ident.cmi : utils/identifiable.cmi
typing/includeclass.cmo : typing/types.cmi typing/printtyp.cmi \
- typing/ctype.cmi typing/includeclass.cmi
+ typing/path.cmi typing/ctype.cmi parsing/builtin_attributes.cmi \
+ typing/includeclass.cmi
typing/includeclass.cmx : typing/types.cmx typing/printtyp.cmx \
- typing/ctype.cmx typing/includeclass.cmi
-typing/includeclass.cmi : typing/types.cmi typing/env.cmi typing/ctype.cmi
+ typing/path.cmx typing/ctype.cmx parsing/builtin_attributes.cmx \
+ typing/includeclass.cmi
+typing/includeclass.cmi : typing/types.cmi parsing/location.cmi \
+ typing/env.cmi typing/ctype.cmi
typing/includecore.cmo : typing/types.cmi typing/typedtree.cmi \
typing/path.cmi typing/ident.cmi typing/env.cmi typing/ctype.cmi \
- typing/btype.cmi parsing/asttypes.cmi typing/includecore.cmi
+ parsing/builtin_attributes.cmi typing/btype.cmi parsing/asttypes.cmi \
+ typing/includecore.cmi
typing/includecore.cmx : typing/types.cmx typing/typedtree.cmx \
typing/path.cmx typing/ident.cmx typing/env.cmx typing/ctype.cmx \
- typing/btype.cmx parsing/asttypes.cmi typing/includecore.cmi
+ parsing/builtin_attributes.cmx typing/btype.cmx parsing/asttypes.cmi \
+ typing/includecore.cmi
typing/includecore.cmi : typing/types.cmi typing/typedtree.cmi \
- typing/ident.cmi typing/env.cmi
+ parsing/location.cmi typing/ident.cmi typing/env.cmi
typing/includemod.cmo : typing/types.cmi typing/typedtree.cmi utils/tbl.cmi \
typing/subst.cmi typing/printtyp.cmi typing/primitive.cmi typing/path.cmi \
typing/mtype.cmi utils/misc.cmi parsing/location.cmi \
typing/includecore.cmi typing/includeclass.cmi typing/ident.cmi \
typing/env.cmi typing/ctype.cmi typing/cmt_format.cmi utils/clflags.cmi \
- typing/includemod.cmi
+ parsing/builtin_attributes.cmi typing/btype.cmi typing/includemod.cmi
typing/includemod.cmx : typing/types.cmx typing/typedtree.cmx utils/tbl.cmx \
typing/subst.cmx typing/printtyp.cmx typing/primitive.cmx typing/path.cmx \
typing/mtype.cmx utils/misc.cmx parsing/location.cmx \
typing/includecore.cmx typing/includeclass.cmx typing/ident.cmx \
typing/env.cmx typing/ctype.cmx typing/cmt_format.cmx utils/clflags.cmx \
- typing/includemod.cmi
+ parsing/builtin_attributes.cmx typing/btype.cmx typing/includemod.cmi
typing/includemod.cmi : typing/types.cmi typing/typedtree.cmi \
typing/path.cmi parsing/location.cmi typing/includecore.cmi \
typing/ident.cmi typing/env.cmi typing/ctype.cmi
typing/types.cmi typing/typedtreeIter.cmi typing/typedtree.cmi \
typing/subst.cmi typing/predef.cmi typing/path.cmi parsing/parsetree.cmi \
utils/misc.cmi parsing/longident.cmi parsing/location.cmi \
- typing/ident.cmi typing/env.cmi typing/ctype.cmi typing/btype.cmi \
- parsing/asttypes.cmi parsing/ast_helper.cmi typing/parmatch.cmi
+ typing/ident.cmi typing/env.cmi typing/ctype.cmi utils/config.cmi \
+ typing/btype.cmi parsing/asttypes.cmi parsing/ast_helper.cmi \
+ typing/parmatch.cmi
typing/parmatch.cmx : utils/warnings.cmx typing/untypeast.cmx \
typing/types.cmx typing/typedtreeIter.cmx typing/typedtree.cmx \
typing/subst.cmx typing/predef.cmx typing/path.cmx parsing/parsetree.cmi \
utils/misc.cmx parsing/longident.cmx parsing/location.cmx \
- typing/ident.cmx typing/env.cmx typing/ctype.cmx typing/btype.cmx \
- parsing/asttypes.cmi parsing/ast_helper.cmx typing/parmatch.cmi
+ typing/ident.cmx typing/env.cmx typing/ctype.cmx utils/config.cmx \
+ typing/btype.cmx parsing/asttypes.cmi parsing/ast_helper.cmx \
+ typing/parmatch.cmi
typing/parmatch.cmi : typing/types.cmi typing/typedtree.cmi \
parsing/parsetree.cmi parsing/longident.cmi parsing/location.cmi \
typing/env.cmi parsing/asttypes.cmi
parsing/location.cmx typing/ident.cmx typing/btype.cmx \
parsing/asttypes.cmi typing/predef.cmi
typing/predef.cmi : typing/types.cmi typing/path.cmi typing/ident.cmi
-typing/primitive.cmo : utils/warnings.cmi parsing/parsetree.cmi \
- typing/outcometree.cmi utils/misc.cmi parsing/location.cmi \
- parsing/attr_helper.cmi typing/primitive.cmi
-typing/primitive.cmx : utils/warnings.cmx parsing/parsetree.cmi \
- typing/outcometree.cmi utils/misc.cmx parsing/location.cmx \
- parsing/attr_helper.cmx typing/primitive.cmi
+typing/primitive.cmo : parsing/parsetree.cmi typing/outcometree.cmi \
+ utils/misc.cmi parsing/location.cmi parsing/attr_helper.cmi \
+ typing/primitive.cmi
+typing/primitive.cmx : parsing/parsetree.cmi typing/outcometree.cmi \
+ utils/misc.cmx parsing/location.cmx parsing/attr_helper.cmx \
+ typing/primitive.cmi
typing/primitive.cmi : parsing/parsetree.cmi typing/outcometree.cmi \
parsing/location.cmi
typing/printtyp.cmo : typing/types.cmi typing/primitive.cmi \
typing/printtyp.cmi : typing/types.cmi typing/path.cmi \
typing/outcometree.cmi parsing/longident.cmi typing/ident.cmi \
typing/env.cmi parsing/asttypes.cmi
-typing/printtyped.cmo : typing/typedtree.cmi parsing/printast.cmi \
- typing/path.cmi utils/misc.cmi parsing/longident.cmi parsing/location.cmi \
- typing/ident.cmi parsing/asttypes.cmi typing/printtyped.cmi
-typing/printtyped.cmx : typing/typedtree.cmx parsing/printast.cmx \
- typing/path.cmx utils/misc.cmx parsing/longident.cmx parsing/location.cmx \
- typing/ident.cmx parsing/asttypes.cmi typing/printtyped.cmi
+typing/printtyped.cmo : typing/types.cmi typing/typedtree.cmi \
+ parsing/printast.cmi typing/path.cmi utils/misc.cmi parsing/longident.cmi \
+ parsing/location.cmi typing/ident.cmi parsing/asttypes.cmi \
+ typing/printtyped.cmi
+typing/printtyped.cmx : typing/types.cmx typing/typedtree.cmx \
+ parsing/printast.cmx typing/path.cmx utils/misc.cmx parsing/longident.cmx \
+ parsing/location.cmx typing/ident.cmx parsing/asttypes.cmi \
+ typing/printtyped.cmi
typing/printtyped.cmi : typing/typedtree.cmi
-typing/stypes.cmo : typing/typedtree.cmi typing/printtyp.cmi \
+typing/stypes.cmo : typing/typedtree.cmi typing/printtyp.cmi utils/misc.cmi \
parsing/location.cmi utils/clflags.cmi typing/annot.cmi typing/stypes.cmi
-typing/stypes.cmx : typing/typedtree.cmx typing/printtyp.cmx \
+typing/stypes.cmx : typing/typedtree.cmx typing/printtyp.cmx utils/misc.cmx \
parsing/location.cmx utils/clflags.cmx typing/annot.cmi typing/stypes.cmi
typing/stypes.cmi : typing/typedtree.cmi parsing/location.cmi \
typing/annot.cmi
parsing/parsetree.cmi parsing/longident.cmi parsing/location.cmi \
typing/ident.cmi typing/env.cmi typing/ctype.cmi parsing/asttypes.cmi
typing/typecore.cmo : utils/warnings.cmi typing/typetexp.cmi \
- typing/types.cmi typing/typedtree.cmi typing/typedecl.cmi \
- typing/subst.cmi typing/stypes.cmi typing/printtyp.cmi \
- typing/primitive.cmi typing/predef.cmi typing/path.cmi \
- parsing/parsetree.cmi typing/parmatch.cmi typing/oprint.cmi \
- utils/misc.cmi parsing/longident.cmi parsing/location.cmi \
- typing/ident.cmi typing/env.cmi typing/ctype.cmi typing/cmt_format.cmi \
- utils/clflags.cmi parsing/builtin_attributes.cmi typing/btype.cmi \
- parsing/asttypes.cmi parsing/ast_helper.cmi typing/annot.cmi \
- typing/typecore.cmi
+ typing/types.cmi typing/typeopt.cmi typing/typedtree.cmi \
+ typing/typedecl.cmi typing/subst.cmi typing/stypes.cmi \
+ typing/printtyp.cmi typing/primitive.cmi typing/predef.cmi \
+ typing/path.cmi parsing/parsetree.cmi typing/parmatch.cmi \
+ typing/oprint.cmi utils/misc.cmi parsing/longident.cmi \
+ parsing/location.cmi typing/ident.cmi typing/env.cmi typing/ctype.cmi \
+ typing/cmt_format.cmi utils/clflags.cmi parsing/builtin_attributes.cmi \
+ typing/btype.cmi parsing/asttypes.cmi parsing/ast_helper.cmi \
+ typing/annot.cmi typing/typecore.cmi
typing/typecore.cmx : utils/warnings.cmx typing/typetexp.cmx \
- typing/types.cmx typing/typedtree.cmx typing/typedecl.cmx \
- typing/subst.cmx typing/stypes.cmx typing/printtyp.cmx \
- typing/primitive.cmx typing/predef.cmx typing/path.cmx \
- parsing/parsetree.cmi typing/parmatch.cmx typing/oprint.cmx \
- utils/misc.cmx parsing/longident.cmx parsing/location.cmx \
- typing/ident.cmx typing/env.cmx typing/ctype.cmx typing/cmt_format.cmx \
- utils/clflags.cmx parsing/builtin_attributes.cmx typing/btype.cmx \
- parsing/asttypes.cmi parsing/ast_helper.cmx typing/annot.cmi \
- typing/typecore.cmi
+ typing/types.cmx typing/typeopt.cmx typing/typedtree.cmx \
+ typing/typedecl.cmx typing/subst.cmx typing/stypes.cmx \
+ typing/printtyp.cmx typing/primitive.cmx typing/predef.cmx \
+ typing/path.cmx parsing/parsetree.cmi typing/parmatch.cmx \
+ typing/oprint.cmx utils/misc.cmx parsing/longident.cmx \
+ parsing/location.cmx typing/ident.cmx typing/env.cmx typing/ctype.cmx \
+ typing/cmt_format.cmx utils/clflags.cmx parsing/builtin_attributes.cmx \
+ typing/btype.cmx parsing/asttypes.cmi parsing/ast_helper.cmx \
+ typing/annot.cmi typing/typecore.cmi
typing/typecore.cmi : typing/types.cmi typing/typedtree.cmi typing/path.cmi \
parsing/parsetree.cmi parsing/longident.cmi parsing/location.cmi \
typing/ident.cmi typing/env.cmi parsing/asttypes.cmi typing/annot.cmi
parsing/location.cmi typing/includemod.cmi typing/ident.cmi \
typing/env.cmi typing/ctype.cmi utils/config.cmi typing/cmt_format.cmi \
typing/cmi_format.cmi utils/clflags.cmi parsing/builtin_attributes.cmi \
- typing/btype.cmi parsing/asttypes.cmi parsing/ast_iterator.cmi \
- typing/annot.cmi typing/typemod.cmi
+ typing/btype.cmi parsing/asttypes.cmi typing/annot.cmi typing/typemod.cmi
typing/typemod.cmx : utils/warnings.cmx typing/typetexp.cmx typing/types.cmx \
typing/typedtree.cmx typing/typedecl.cmx typing/typecore.cmx \
typing/typeclass.cmx typing/subst.cmx typing/stypes.cmx \
parsing/location.cmx typing/includemod.cmx typing/ident.cmx \
typing/env.cmx typing/ctype.cmx utils/config.cmx typing/cmt_format.cmx \
typing/cmi_format.cmx utils/clflags.cmx parsing/builtin_attributes.cmx \
- typing/btype.cmx parsing/asttypes.cmi parsing/ast_iterator.cmx \
- typing/annot.cmi typing/typemod.cmi
+ typing/btype.cmx parsing/asttypes.cmi typing/annot.cmi typing/typemod.cmi
typing/typemod.cmi : typing/types.cmi typing/typedtree.cmi typing/path.cmi \
parsing/parsetree.cmi utils/misc.cmi parsing/longident.cmi \
parsing/location.cmi typing/includemod.cmi typing/ident.cmi \
typing/env.cmi typing/cmi_format.cmi parsing/asttypes.cmi
+typing/typeopt.cmo : typing/types.cmi typing/typedtree.cmi \
+ typing/typedecl.cmi typing/predef.cmi typing/path.cmi bytecomp/lambda.cmi \
+ typing/ident.cmi typing/env.cmi typing/ctype.cmi utils/config.cmi \
+ parsing/asttypes.cmi typing/typeopt.cmi
+typing/typeopt.cmx : typing/types.cmx typing/typedtree.cmx \
+ typing/typedecl.cmx typing/predef.cmx typing/path.cmx bytecomp/lambda.cmx \
+ typing/ident.cmx typing/env.cmx typing/ctype.cmx utils/config.cmx \
+ parsing/asttypes.cmi typing/typeopt.cmi
+typing/typeopt.cmi : typing/types.cmi typing/typedtree.cmi typing/path.cmi \
+ bytecomp/lambda.cmi typing/env.cmi
typing/types.cmo : typing/primitive.cmi typing/path.cmi \
parsing/parsetree.cmi parsing/longident.cmi parsing/location.cmi \
typing/ident.cmi parsing/asttypes.cmi typing/types.cmi
typing/types.cmi : typing/primitive.cmi typing/path.cmi \
parsing/parsetree.cmi parsing/longident.cmi parsing/location.cmi \
typing/ident.cmi parsing/asttypes.cmi
-typing/typetexp.cmo : utils/warnings.cmi typing/types.cmi \
- typing/typedtree.cmi utils/tbl.cmi typing/printtyp.cmi typing/predef.cmi \
- typing/path.cmi parsing/parsetree.cmi utils/misc.cmi \
- parsing/longident.cmi parsing/location.cmi typing/env.cmi \
- typing/ctype.cmi utils/clflags.cmi parsing/builtin_attributes.cmi \
- typing/btype.cmi parsing/asttypes.cmi parsing/ast_helper.cmi \
- typing/typetexp.cmi
-typing/typetexp.cmx : utils/warnings.cmx typing/types.cmx \
- typing/typedtree.cmx utils/tbl.cmx typing/printtyp.cmx typing/predef.cmx \
- typing/path.cmx parsing/parsetree.cmi utils/misc.cmx \
- parsing/longident.cmx parsing/location.cmx typing/env.cmx \
- typing/ctype.cmx utils/clflags.cmx parsing/builtin_attributes.cmx \
- typing/btype.cmx parsing/asttypes.cmi parsing/ast_helper.cmx \
- typing/typetexp.cmi
+typing/typetexp.cmo : typing/types.cmi typing/typedtree.cmi utils/tbl.cmi \
+ typing/printtyp.cmi typing/predef.cmi typing/path.cmi \
+ parsing/parsetree.cmi utils/misc.cmi parsing/longident.cmi \
+ parsing/location.cmi typing/env.cmi typing/ctype.cmi utils/clflags.cmi \
+ parsing/builtin_attributes.cmi typing/btype.cmi parsing/asttypes.cmi \
+ parsing/ast_helper.cmi typing/typetexp.cmi
+typing/typetexp.cmx : typing/types.cmx typing/typedtree.cmx utils/tbl.cmx \
+ typing/printtyp.cmx typing/predef.cmx typing/path.cmx \
+ parsing/parsetree.cmi utils/misc.cmx parsing/longident.cmx \
+ parsing/location.cmx typing/env.cmx typing/ctype.cmx utils/clflags.cmx \
+ parsing/builtin_attributes.cmx typing/btype.cmx parsing/asttypes.cmi \
+ parsing/ast_helper.cmx typing/typetexp.cmi
typing/typetexp.cmi : typing/types.cmi typing/typedtree.cmi typing/path.cmi \
parsing/parsetree.cmi parsing/longident.cmi parsing/location.cmi \
typing/env.cmi parsing/asttypes.cmi
utils/config.cmx parsing/asttypes.cmi bytecomp/bytegen.cmi
bytecomp/bytegen.cmi : bytecomp/lambda.cmi bytecomp/instruct.cmi
bytecomp/bytelibrarian.cmo : utils/misc.cmi parsing/location.cmi \
- utils/config.cmi bytecomp/cmo_format.cmi utils/clflags.cmi \
- bytecomp/bytelink.cmi bytecomp/bytelibrarian.cmi
+ bytecomp/emitcode.cmi utils/config.cmi bytecomp/cmo_format.cmi \
+ utils/clflags.cmi bytecomp/bytelink.cmi bytecomp/bytelibrarian.cmi
bytecomp/bytelibrarian.cmx : utils/misc.cmx parsing/location.cmx \
- utils/config.cmx bytecomp/cmo_format.cmi utils/clflags.cmx \
- bytecomp/bytelink.cmx bytecomp/bytelibrarian.cmi
+ bytecomp/emitcode.cmx utils/config.cmx bytecomp/cmo_format.cmi \
+ utils/clflags.cmx bytecomp/bytelink.cmx bytecomp/bytelibrarian.cmi
bytecomp/bytelibrarian.cmi :
bytecomp/bytelink.cmo : utils/warnings.cmi bytecomp/symtable.cmi \
bytecomp/opcodes.cmo utils/misc.cmi parsing/location.cmi \
bytecomp/lambda.cmi bytecomp/instruct.cmi typing/ident.cmi \
- bytecomp/dll.cmi utils/consistbl.cmi utils/config.cmi \
- bytecomp/cmo_format.cmi utils/clflags.cmi utils/ccomp.cmi \
- bytecomp/bytesections.cmi bytecomp/bytelink.cmi
+ bytecomp/emitcode.cmi bytecomp/dll.cmi utils/consistbl.cmi \
+ utils/config.cmi bytecomp/cmo_format.cmi utils/clflags.cmi \
+ utils/ccomp.cmi bytecomp/bytesections.cmi bytecomp/bytelink.cmi
bytecomp/bytelink.cmx : utils/warnings.cmx bytecomp/symtable.cmx \
bytecomp/opcodes.cmx utils/misc.cmx parsing/location.cmx \
bytecomp/lambda.cmx bytecomp/instruct.cmx typing/ident.cmx \
- bytecomp/dll.cmx utils/consistbl.cmx utils/config.cmx \
- bytecomp/cmo_format.cmi utils/clflags.cmx utils/ccomp.cmx \
- bytecomp/bytesections.cmx bytecomp/bytelink.cmi
+ bytecomp/emitcode.cmx bytecomp/dll.cmx utils/consistbl.cmx \
+ utils/config.cmx bytecomp/cmo_format.cmi utils/clflags.cmx \
+ utils/ccomp.cmx bytecomp/bytesections.cmx bytecomp/bytelink.cmi
bytecomp/bytelink.cmi : bytecomp/symtable.cmi bytecomp/cmo_format.cmi
bytecomp/bytepackager.cmo : typing/typemod.cmi bytecomp/translmod.cmi \
typing/subst.cmi bytecomp/printlambda.cmi typing/path.cmi utils/misc.cmi \
parsing/asttypes.cmi bytecomp/lambda.cmi
bytecomp/lambda.cmi : typing/types.cmi typing/primitive.cmi typing/path.cmi \
parsing/location.cmi typing/ident.cmi typing/env.cmi parsing/asttypes.cmi
-bytecomp/matching.cmo : typing/types.cmi bytecomp/typeopt.cmi \
+bytecomp/matching.cmo : typing/types.cmi typing/typeopt.cmi \
typing/typedtree.cmi bytecomp/switch.cmi bytecomp/printlambda.cmi \
typing/primitive.cmi typing/predef.cmi typing/path.cmi \
typing/parmatch.cmi utils/misc.cmi parsing/longident.cmi \
parsing/location.cmi bytecomp/lambda.cmi typing/ident.cmi typing/env.cmi \
utils/clflags.cmi typing/btype.cmi parsing/asttypes.cmi \
bytecomp/matching.cmi
-bytecomp/matching.cmx : typing/types.cmx bytecomp/typeopt.cmx \
+bytecomp/matching.cmx : typing/types.cmx typing/typeopt.cmx \
typing/typedtree.cmx bytecomp/switch.cmx bytecomp/printlambda.cmx \
typing/primitive.cmx typing/predef.cmx typing/path.cmx \
typing/parmatch.cmx utils/misc.cmx parsing/longident.cmx \
bytecomp/simplif.cmi
bytecomp/simplif.cmi : utils/misc.cmi parsing/location.cmi \
bytecomp/lambda.cmi typing/ident.cmi
-bytecomp/switch.cmo : bytecomp/switch.cmi
-bytecomp/switch.cmx : bytecomp/switch.cmi
-bytecomp/switch.cmi :
+bytecomp/switch.cmo : parsing/location.cmi bytecomp/switch.cmi
+bytecomp/switch.cmx : parsing/location.cmx bytecomp/switch.cmi
+bytecomp/switch.cmi : parsing/location.cmi
bytecomp/symtable.cmo : utils/tbl.cmi bytecomp/runtimedef.cmi \
typing/predef.cmi utils/misc.cmi bytecomp/meta.cmi parsing/location.cmi \
bytecomp/lambda.cmi typing/ident.cmi bytecomp/dll.cmi utils/config.cmi \
bytecomp/translattribute.cmi
bytecomp/translattribute.cmi : typing/typedtree.cmi parsing/parsetree.cmi \
parsing/location.cmi bytecomp/lambda.cmi
-bytecomp/translclass.cmo : typing/types.cmi bytecomp/typeopt.cmi \
+bytecomp/translclass.cmo : typing/types.cmi typing/typeopt.cmi \
typing/typedtree.cmi bytecomp/translobj.cmi bytecomp/translcore.cmi \
typing/path.cmi bytecomp/matching.cmi parsing/location.cmi \
bytecomp/lambda.cmi typing/ident.cmi typing/env.cmi utils/clflags.cmi \
typing/btype.cmi parsing/asttypes.cmi bytecomp/translclass.cmi
-bytecomp/translclass.cmx : typing/types.cmx bytecomp/typeopt.cmx \
+bytecomp/translclass.cmx : typing/types.cmx typing/typeopt.cmx \
typing/typedtree.cmx bytecomp/translobj.cmx bytecomp/translcore.cmx \
typing/path.cmx bytecomp/matching.cmx parsing/location.cmx \
bytecomp/lambda.cmx typing/ident.cmx typing/env.cmx utils/clflags.cmx \
typing/btype.cmx parsing/asttypes.cmi bytecomp/translclass.cmi
bytecomp/translclass.cmi : typing/typedtree.cmi parsing/location.cmi \
bytecomp/lambda.cmi typing/ident.cmi parsing/asttypes.cmi
-bytecomp/translcore.cmo : typing/types.cmi bytecomp/typeopt.cmi \
+bytecomp/translcore.cmo : typing/types.cmi typing/typeopt.cmi \
typing/typedtree.cmi typing/typecore.cmi bytecomp/translobj.cmi \
bytecomp/translattribute.cmi typing/primitive.cmi typing/predef.cmi \
typing/path.cmi typing/parmatch.cmi utils/misc.cmi bytecomp/matching.cmi \
parsing/longident.cmi parsing/location.cmi bytecomp/lambda.cmi \
typing/ident.cmi typing/env.cmi utils/config.cmi utils/clflags.cmi \
typing/btype.cmi parsing/asttypes.cmi bytecomp/translcore.cmi
-bytecomp/translcore.cmx : typing/types.cmx bytecomp/typeopt.cmx \
+bytecomp/translcore.cmx : typing/types.cmx typing/typeopt.cmx \
typing/typedtree.cmx typing/typecore.cmx bytecomp/translobj.cmx \
bytecomp/translattribute.cmx typing/primitive.cmx typing/predef.cmx \
typing/path.cmx typing/parmatch.cmx utils/misc.cmx bytecomp/matching.cmx \
typing/ident.cmx typing/env.cmx utils/config.cmx utils/clflags.cmx \
typing/btype.cmx parsing/asttypes.cmi bytecomp/translobj.cmi
bytecomp/translobj.cmi : bytecomp/lambda.cmi typing/ident.cmi typing/env.cmi
-bytecomp/typeopt.cmo : typing/types.cmi typing/typedtree.cmi \
- typing/typedecl.cmi typing/predef.cmi typing/path.cmi bytecomp/lambda.cmi \
- typing/ident.cmi typing/env.cmi typing/ctype.cmi bytecomp/typeopt.cmi
-bytecomp/typeopt.cmx : typing/types.cmx typing/typedtree.cmx \
- typing/typedecl.cmx typing/predef.cmx typing/path.cmx bytecomp/lambda.cmx \
- typing/ident.cmx typing/env.cmx typing/ctype.cmx bytecomp/typeopt.cmi
-bytecomp/typeopt.cmi : typing/types.cmi typing/typedtree.cmi typing/path.cmi \
- bytecomp/lambda.cmi typing/env.cmi
asmcomp/CSE.cmo : asmcomp/mach.cmi asmcomp/CSEgen.cmi asmcomp/arch.cmo
asmcomp/CSE.cmx : asmcomp/mach.cmx asmcomp/CSEgen.cmx asmcomp/arch.cmx
asmcomp/CSEgen.cmo : asmcomp/reg.cmi asmcomp/proc.cmi asmcomp/mach.cmi \
asmcomp/arch.cmo : utils/config.cmi utils/clflags.cmi
asmcomp/arch.cmx : utils/config.cmx utils/clflags.cmx
asmcomp/asmgen.cmo : asmcomp/un_anf.cmi bytecomp/translmod.cmi \
- utils/timings.cmi middle_end/base_types/symbol.cmi asmcomp/split.cmi \
- asmcomp/spill.cmi asmcomp/selection.cmi asmcomp/scheduling.cmi \
- asmcomp/reload.cmi asmcomp/reg.cmi asmcomp/proc.cmi asmcomp/printmach.cmi \
+ middle_end/base_types/symbol.cmi asmcomp/split.cmi asmcomp/spill.cmi \
+ asmcomp/selection.cmi asmcomp/scheduling.cmi asmcomp/reload.cmi \
+ asmcomp/reg.cmi utils/profile.cmi asmcomp/proc.cmi asmcomp/printmach.cmi \
asmcomp/printlinear.cmi asmcomp/printcmm.cmi asmcomp/printclambda.cmi \
typing/primitive.cmi utils/misc.cmi asmcomp/mach.cmi parsing/location.cmi \
- asmcomp/liveness.cmi middle_end/base_types/linkage_name.cmi \
- asmcomp/linearize.cmi bytecomp/lambda.cmi asmcomp/interf.cmi \
+ asmcomp/liveness.cmi asmcomp/linscan.cmi \
+ middle_end/base_types/linkage_name.cmi asmcomp/linearize.cmi \
+ bytecomp/lambda.cmi asmcomp/interval.cmi asmcomp/interf.cmi \
typing/ident.cmi asmcomp/flambda_to_clambda.cmi middle_end/flambda.cmi \
asmcomp/emitaux.cmi asmcomp/emit.cmi asmcomp/deadcode.cmi \
utils/config.cmi asmcomp/compilenv.cmi asmcomp/comballoc.cmi \
asmcomp/coloring.cmi asmcomp/cmmgen.cmi asmcomp/cmm.cmi \
asmcomp/closure.cmi utils/clflags.cmi asmcomp/clambda.cmi asmcomp/CSE.cmo \
- asmcomp/build_export_info.cmi asmcomp/asmgen.cmi
+ asmcomp/build_export_info.cmi asmcomp/debug/available_regs.cmi \
+ asmcomp/asmgen.cmi
asmcomp/asmgen.cmx : asmcomp/un_anf.cmx bytecomp/translmod.cmx \
- utils/timings.cmx middle_end/base_types/symbol.cmx asmcomp/split.cmx \
- asmcomp/spill.cmx asmcomp/selection.cmx asmcomp/scheduling.cmx \
- asmcomp/reload.cmx asmcomp/reg.cmx asmcomp/proc.cmx asmcomp/printmach.cmx \
+ middle_end/base_types/symbol.cmx asmcomp/split.cmx asmcomp/spill.cmx \
+ asmcomp/selection.cmx asmcomp/scheduling.cmx asmcomp/reload.cmx \
+ asmcomp/reg.cmx utils/profile.cmx asmcomp/proc.cmx asmcomp/printmach.cmx \
asmcomp/printlinear.cmx asmcomp/printcmm.cmx asmcomp/printclambda.cmx \
typing/primitive.cmx utils/misc.cmx asmcomp/mach.cmx parsing/location.cmx \
- asmcomp/liveness.cmx middle_end/base_types/linkage_name.cmx \
- asmcomp/linearize.cmx bytecomp/lambda.cmx asmcomp/interf.cmx \
+ asmcomp/liveness.cmx asmcomp/linscan.cmx \
+ middle_end/base_types/linkage_name.cmx asmcomp/linearize.cmx \
+ bytecomp/lambda.cmx asmcomp/interval.cmx asmcomp/interf.cmx \
typing/ident.cmx asmcomp/flambda_to_clambda.cmx middle_end/flambda.cmx \
asmcomp/emitaux.cmx asmcomp/emit.cmx asmcomp/deadcode.cmx \
utils/config.cmx asmcomp/compilenv.cmx asmcomp/comballoc.cmx \
asmcomp/coloring.cmx asmcomp/cmmgen.cmx asmcomp/cmm.cmx \
asmcomp/closure.cmx utils/clflags.cmx asmcomp/clambda.cmx asmcomp/CSE.cmx \
- asmcomp/build_export_info.cmx asmcomp/asmgen.cmi
-asmcomp/asmgen.cmi : utils/timings.cmi bytecomp/lambda.cmi typing/ident.cmi \
+ asmcomp/build_export_info.cmx asmcomp/debug/available_regs.cmx \
+ asmcomp/asmgen.cmi
+asmcomp/asmgen.cmi : bytecomp/lambda.cmi typing/ident.cmi \
middle_end/flambda.cmi asmcomp/cmm.cmi middle_end/backend_intf.cmi
asmcomp/asmlibrarian.cmo : utils/misc.cmi parsing/location.cmi \
asmcomp/export_info.cmi utils/config.cmi asmcomp/compilenv.cmi \
asmcomp/cmx_format.cmi utils/clflags.cmx asmcomp/clambda.cmx \
utils/ccomp.cmx asmcomp/asmlink.cmx asmcomp/asmlibrarian.cmi
asmcomp/asmlibrarian.cmi :
-asmcomp/asmlink.cmo : utils/timings.cmi bytecomp/runtimedef.cmi \
+asmcomp/asmlink.cmo : bytecomp/runtimedef.cmi utils/profile.cmi \
utils/misc.cmi parsing/location.cmi asmcomp/emitaux.cmi asmcomp/emit.cmi \
utils/consistbl.cmi utils/config.cmi asmcomp/compilenv.cmi \
asmcomp/cmx_format.cmi asmcomp/cmmgen.cmi utils/clflags.cmi \
utils/ccomp.cmi asmcomp/asmgen.cmi asmcomp/asmlink.cmi
-asmcomp/asmlink.cmx : utils/timings.cmx bytecomp/runtimedef.cmx \
+asmcomp/asmlink.cmx : bytecomp/runtimedef.cmx utils/profile.cmx \
utils/misc.cmx parsing/location.cmx asmcomp/emitaux.cmx asmcomp/emit.cmx \
utils/consistbl.cmx utils/config.cmx asmcomp/compilenv.cmx \
asmcomp/cmx_format.cmi asmcomp/cmmgen.cmx utils/clflags.cmx \
utils/ccomp.cmx asmcomp/asmgen.cmx asmcomp/asmlink.cmi
asmcomp/asmlink.cmi : asmcomp/cmx_format.cmi
asmcomp/asmpackager.cmo : typing/typemod.cmi bytecomp/translmod.cmi \
- utils/timings.cmi utils/misc.cmi middle_end/middle_end.cmi \
+ utils/profile.cmi utils/misc.cmi middle_end/middle_end.cmi \
parsing/location.cmi bytecomp/lambda.cmi typing/ident.cmi \
asmcomp/export_info_for_pack.cmi asmcomp/export_info.cmi typing/env.cmi \
utils/config.cmi asmcomp/compilenv.cmi \
utils/clflags.cmi utils/ccomp.cmi asmcomp/asmlink.cmi asmcomp/asmgen.cmi \
asmcomp/asmpackager.cmi
asmcomp/asmpackager.cmx : typing/typemod.cmx bytecomp/translmod.cmx \
- utils/timings.cmx utils/misc.cmx middle_end/middle_end.cmx \
+ utils/profile.cmx utils/misc.cmx middle_end/middle_end.cmx \
parsing/location.cmx bytecomp/lambda.cmx typing/ident.cmx \
asmcomp/export_info_for_pack.cmx asmcomp/export_info.cmx typing/env.cmx \
utils/config.cmx asmcomp/compilenv.cmx \
middle_end/base_types/compilation_unit.cmx asmcomp/cmx_format.cmi \
middle_end/base_types/closure_id.cmx utils/clflags.cmx \
asmcomp/clambda.cmx asmcomp/compilenv.cmi
-asmcomp/compilenv.cmi : utils/timings.cmi middle_end/base_types/symbol.cmi \
+asmcomp/compilenv.cmi : middle_end/base_types/symbol.cmi \
middle_end/base_types/set_of_closures_id.cmi \
middle_end/base_types/linkage_name.cmi typing/ident.cmi \
middle_end/flambda.cmi asmcomp/export_info.cmi \
middle_end/base_types/tag.cmi middle_end/base_types/symbol.cmi \
middle_end/base_types/static_exception.cmi \
middle_end/base_types/set_of_closures_id.cmi typing/primitive.cmi \
- utils/numbers.cmi middle_end/base_types/mutable_variable.cmi \
- utils/misc.cmi middle_end/base_types/linkage_name.cmi typing/ident.cmi \
+ middle_end/parameter.cmi utils/numbers.cmi \
+ middle_end/base_types/mutable_variable.cmi utils/misc.cmi \
+ middle_end/base_types/linkage_name.cmi typing/ident.cmi \
middle_end/flambda_utils.cmi middle_end/flambda.cmi \
asmcomp/export_info.cmi middle_end/debuginfo.cmi asmcomp/compilenv.cmi \
asmcomp/closure_offsets.cmi middle_end/base_types/closure_id.cmi \
middle_end/base_types/tag.cmx middle_end/base_types/symbol.cmx \
middle_end/base_types/static_exception.cmx \
middle_end/base_types/set_of_closures_id.cmx typing/primitive.cmx \
- utils/numbers.cmx middle_end/base_types/mutable_variable.cmx \
- utils/misc.cmx middle_end/base_types/linkage_name.cmx typing/ident.cmx \
+ middle_end/parameter.cmx utils/numbers.cmx \
+ middle_end/base_types/mutable_variable.cmx utils/misc.cmx \
+ middle_end/base_types/linkage_name.cmx typing/ident.cmx \
middle_end/flambda_utils.cmx middle_end/flambda.cmx \
asmcomp/export_info.cmx middle_end/debuginfo.cmx asmcomp/compilenv.cmx \
asmcomp/closure_offsets.cmx middle_end/base_types/closure_id.cmx \
asmcomp/interf.cmx : asmcomp/reg.cmx asmcomp/proc.cmx asmcomp/mach.cmx \
asmcomp/cmm.cmx asmcomp/interf.cmi
asmcomp/interf.cmi : asmcomp/mach.cmi
+asmcomp/interval.cmo : asmcomp/reg.cmi asmcomp/proc.cmi asmcomp/mach.cmi \
+ asmcomp/interval.cmi
+asmcomp/interval.cmx : asmcomp/reg.cmx asmcomp/proc.cmx asmcomp/mach.cmx \
+ asmcomp/interval.cmi
+asmcomp/interval.cmi : asmcomp/reg.cmi asmcomp/mach.cmi
asmcomp/linearize.cmo : asmcomp/reg.cmi asmcomp/proc.cmi utils/misc.cmi \
asmcomp/mach.cmi middle_end/debuginfo.cmi utils/config.cmi \
asmcomp/cmm.cmi asmcomp/linearize.cmi
asmcomp/cmm.cmx asmcomp/linearize.cmi
asmcomp/linearize.cmi : asmcomp/reg.cmi asmcomp/mach.cmi \
middle_end/debuginfo.cmi asmcomp/cmm.cmi
+asmcomp/linscan.cmo : asmcomp/reg.cmi asmcomp/proc.cmi asmcomp/interval.cmi \
+ asmcomp/linscan.cmi
+asmcomp/linscan.cmx : asmcomp/reg.cmx asmcomp/proc.cmx asmcomp/interval.cmx \
+ asmcomp/linscan.cmi
+asmcomp/linscan.cmi :
asmcomp/liveness.cmo : asmcomp/reg.cmi asmcomp/proc.cmi \
asmcomp/printmach.cmi utils/misc.cmi asmcomp/mach.cmi utils/config.cmi \
asmcomp/cmm.cmi asmcomp/liveness.cmi
asmcomp/printmach.cmx utils/misc.cmx asmcomp/mach.cmx utils/config.cmx \
asmcomp/cmm.cmx asmcomp/liveness.cmi
asmcomp/liveness.cmi : asmcomp/mach.cmi
-asmcomp/mach.cmo : asmcomp/reg.cmi middle_end/debuginfo.cmi asmcomp/cmm.cmi \
- asmcomp/arch.cmo asmcomp/mach.cmi
-asmcomp/mach.cmx : asmcomp/reg.cmx middle_end/debuginfo.cmx asmcomp/cmm.cmx \
- asmcomp/arch.cmx asmcomp/mach.cmi
-asmcomp/mach.cmi : asmcomp/reg.cmi middle_end/debuginfo.cmi asmcomp/cmm.cmi \
+asmcomp/mach.cmo : asmcomp/debug/reg_with_debug_info.cmi \
+ asmcomp/debug/reg_availability_set.cmi asmcomp/reg.cmi typing/ident.cmi \
+ middle_end/debuginfo.cmi asmcomp/cmm.cmi asmcomp/arch.cmo \
+ asmcomp/mach.cmi
+asmcomp/mach.cmx : asmcomp/debug/reg_with_debug_info.cmx \
+ asmcomp/debug/reg_availability_set.cmx asmcomp/reg.cmx typing/ident.cmx \
+ middle_end/debuginfo.cmx asmcomp/cmm.cmx asmcomp/arch.cmx \
+ asmcomp/mach.cmi
+asmcomp/mach.cmi : asmcomp/debug/reg_availability_set.cmi asmcomp/reg.cmi \
+ typing/ident.cmi middle_end/debuginfo.cmi asmcomp/cmm.cmi \
asmcomp/arch.cmo
asmcomp/printclambda.cmo : bytecomp/printlambda.cmi bytecomp/lambda.cmi \
typing/ident.cmi asmcomp/clambda.cmi parsing/asttypes.cmi \
asmcomp/mach.cmx asmcomp/linearize.cmx middle_end/debuginfo.cmx \
asmcomp/printlinear.cmi
asmcomp/printlinear.cmi : asmcomp/linearize.cmi
-asmcomp/printmach.cmo : asmcomp/reg.cmi asmcomp/proc.cmi \
- asmcomp/printcmm.cmi asmcomp/mach.cmi middle_end/debuginfo.cmi \
- utils/config.cmi asmcomp/cmm.cmi asmcomp/arch.cmo asmcomp/printmach.cmi
-asmcomp/printmach.cmx : asmcomp/reg.cmx asmcomp/proc.cmx \
- asmcomp/printcmm.cmx asmcomp/mach.cmx middle_end/debuginfo.cmx \
- utils/config.cmx asmcomp/cmm.cmx asmcomp/arch.cmx asmcomp/printmach.cmi
+asmcomp/printmach.cmo : asmcomp/debug/reg_availability_set.cmi \
+ asmcomp/reg.cmi asmcomp/proc.cmi asmcomp/printcmm.cmi asmcomp/mach.cmi \
+ asmcomp/interval.cmi typing/ident.cmi middle_end/debuginfo.cmi \
+ utils/config.cmi asmcomp/cmm.cmi utils/clflags.cmi asmcomp/arch.cmo \
+ asmcomp/printmach.cmi
+asmcomp/printmach.cmx : asmcomp/debug/reg_availability_set.cmx \
+ asmcomp/reg.cmx asmcomp/proc.cmx asmcomp/printcmm.cmx asmcomp/mach.cmx \
+ asmcomp/interval.cmx typing/ident.cmx middle_end/debuginfo.cmx \
+ utils/config.cmx asmcomp/cmm.cmx utils/clflags.cmx asmcomp/arch.cmx \
+ asmcomp/printmach.cmi
asmcomp/printmach.cmi : asmcomp/reg.cmi asmcomp/mach.cmi
asmcomp/proc.cmo : asmcomp/x86_proc.cmi asmcomp/reg.cmi utils/misc.cmi \
asmcomp/mach.cmi utils/config.cmi asmcomp/cmm.cmi asmcomp/arch.cmo \
parsing/asttypes.cmi asmcomp/arch.cmx asmcomp/spacetime_profiling.cmi
asmcomp/spacetime_profiling.cmi : asmcomp/selectgen.cmi
asmcomp/spill.cmo : asmcomp/reg.cmi asmcomp/proc.cmi utils/misc.cmi \
- asmcomp/mach.cmi asmcomp/cmm.cmi asmcomp/spill.cmi
+ asmcomp/mach.cmi asmcomp/cmm.cmi utils/clflags.cmi asmcomp/spill.cmi
asmcomp/spill.cmx : asmcomp/reg.cmx asmcomp/proc.cmx utils/misc.cmx \
- asmcomp/mach.cmx asmcomp/cmm.cmx asmcomp/spill.cmi
+ asmcomp/mach.cmx asmcomp/cmm.cmx utils/clflags.cmx asmcomp/spill.cmi
asmcomp/spill.cmi : asmcomp/mach.cmi
asmcomp/split.cmo : asmcomp/reg.cmi utils/misc.cmi asmcomp/mach.cmi \
asmcomp/split.cmi
asmcomp/split.cmx : asmcomp/reg.cmx utils/misc.cmx asmcomp/mach.cmx \
asmcomp/split.cmi
asmcomp/split.cmi : asmcomp/mach.cmi
-asmcomp/strmatch.cmo : bytecomp/lambda.cmi typing/ident.cmi \
- middle_end/debuginfo.cmi asmcomp/cmm.cmi parsing/asttypes.cmi \
- asmcomp/arch.cmo asmcomp/strmatch.cmi
-asmcomp/strmatch.cmx : bytecomp/lambda.cmx typing/ident.cmx \
- middle_end/debuginfo.cmx asmcomp/cmm.cmx parsing/asttypes.cmi \
- asmcomp/arch.cmx asmcomp/strmatch.cmi
-asmcomp/strmatch.cmi : middle_end/debuginfo.cmi asmcomp/cmm.cmi
+asmcomp/strmatch.cmo : parsing/location.cmi bytecomp/lambda.cmi \
+ typing/ident.cmi middle_end/debuginfo.cmi asmcomp/cmm.cmi \
+ parsing/asttypes.cmi asmcomp/arch.cmo asmcomp/strmatch.cmi
+asmcomp/strmatch.cmx : parsing/location.cmx bytecomp/lambda.cmx \
+ typing/ident.cmx middle_end/debuginfo.cmx asmcomp/cmm.cmx \
+ parsing/asttypes.cmi asmcomp/arch.cmx asmcomp/strmatch.cmi
+asmcomp/strmatch.cmi : parsing/location.cmi middle_end/debuginfo.cmi \
+ asmcomp/cmm.cmi
asmcomp/un_anf.cmo : bytecomp/semantics_of_primitives.cmi \
asmcomp/printclambda.cmi utils/misc.cmi bytecomp/lambda.cmi \
typing/ident.cmi middle_end/debuginfo.cmi utils/clflags.cmi \
middle_end/allocated_const.cmx : middle_end/allocated_const.cmi
middle_end/allocated_const.cmi :
middle_end/augment_specialised_args.cmo : middle_end/base_types/variable.cmi \
- middle_end/projection.cmi middle_end/pass_wrapper.cmi utils/misc.cmi \
- middle_end/inlining_cost.cmi middle_end/inline_and_simplify_aux.cmi \
- utils/identifiable.cmi middle_end/flambda_utils.cmi \
- middle_end/flambda.cmi middle_end/debuginfo.cmi \
- middle_end/base_types/closure_id.cmi utils/clflags.cmi \
- middle_end/backend_intf.cmi middle_end/augment_specialised_args.cmi
+ middle_end/projection.cmi middle_end/pass_wrapper.cmi \
+ middle_end/parameter.cmi utils/misc.cmi middle_end/inlining_cost.cmi \
+ middle_end/inline_and_simplify_aux.cmi utils/identifiable.cmi \
+ middle_end/flambda_utils.cmi middle_end/flambda.cmi \
+ middle_end/debuginfo.cmi middle_end/base_types/closure_id.cmi \
+ utils/clflags.cmi middle_end/backend_intf.cmi \
+ middle_end/augment_specialised_args.cmi
middle_end/augment_specialised_args.cmx : middle_end/base_types/variable.cmx \
- middle_end/projection.cmx middle_end/pass_wrapper.cmx utils/misc.cmx \
- middle_end/inlining_cost.cmx middle_end/inline_and_simplify_aux.cmx \
- utils/identifiable.cmx middle_end/flambda_utils.cmx \
- middle_end/flambda.cmx middle_end/debuginfo.cmx \
- middle_end/base_types/closure_id.cmx utils/clflags.cmx \
- middle_end/backend_intf.cmi middle_end/augment_specialised_args.cmi
+ middle_end/projection.cmx middle_end/pass_wrapper.cmx \
+ middle_end/parameter.cmx utils/misc.cmx middle_end/inlining_cost.cmx \
+ middle_end/inline_and_simplify_aux.cmx utils/identifiable.cmx \
+ middle_end/flambda_utils.cmx middle_end/flambda.cmx \
+ middle_end/debuginfo.cmx middle_end/base_types/closure_id.cmx \
+ utils/clflags.cmx middle_end/backend_intf.cmi \
+ middle_end/augment_specialised_args.cmi
middle_end/augment_specialised_args.cmi : middle_end/base_types/variable.cmi \
middle_end/projection.cmi middle_end/inlining_cost.cmi \
middle_end/inline_and_simplify_aux.cmi middle_end/flambda.cmi
middle_end/closure_conversion.cmo : middle_end/base_types/variable.cmi \
middle_end/base_types/tag.cmi middle_end/base_types/symbol.cmi \
middle_end/base_types/static_exception.cmi bytecomp/simplif.cmi \
- bytecomp/printlambda.cmi typing/predef.cmi utils/numbers.cmi \
- middle_end/base_types/mutable_variable.cmi utils/misc.cmi \
- parsing/location.cmi middle_end/base_types/linkage_name.cmi \
- middle_end/lift_code.cmi bytecomp/lambda.cmi typing/ident.cmi \
- middle_end/flambda_utils.cmi middle_end/flambda.cmi \
- middle_end/debuginfo.cmi utils/config.cmi \
+ bytecomp/printlambda.cmi typing/predef.cmi middle_end/parameter.cmi \
+ utils/numbers.cmi middle_end/base_types/mutable_variable.cmi \
+ utils/misc.cmi parsing/location.cmi \
+ middle_end/base_types/linkage_name.cmi middle_end/lift_code.cmi \
+ bytecomp/lambda.cmi typing/ident.cmi middle_end/flambda_utils.cmi \
+ middle_end/flambda.cmi middle_end/debuginfo.cmi utils/config.cmi \
middle_end/base_types/compilation_unit.cmi \
middle_end/base_types/closure_id.cmi \
middle_end/closure_conversion_aux.cmi utils/clflags.cmi \
middle_end/closure_conversion.cmx : middle_end/base_types/variable.cmx \
middle_end/base_types/tag.cmx middle_end/base_types/symbol.cmx \
middle_end/base_types/static_exception.cmx bytecomp/simplif.cmx \
- bytecomp/printlambda.cmx typing/predef.cmx utils/numbers.cmx \
- middle_end/base_types/mutable_variable.cmx utils/misc.cmx \
- parsing/location.cmx middle_end/base_types/linkage_name.cmx \
- middle_end/lift_code.cmx bytecomp/lambda.cmx typing/ident.cmx \
- middle_end/flambda_utils.cmx middle_end/flambda.cmx \
- middle_end/debuginfo.cmx utils/config.cmx \
+ bytecomp/printlambda.cmx typing/predef.cmx middle_end/parameter.cmx \
+ utils/numbers.cmx middle_end/base_types/mutable_variable.cmx \
+ utils/misc.cmx parsing/location.cmx \
+ middle_end/base_types/linkage_name.cmx middle_end/lift_code.cmx \
+ bytecomp/lambda.cmx typing/ident.cmx middle_end/flambda_utils.cmx \
+ middle_end/flambda.cmx middle_end/debuginfo.cmx utils/config.cmx \
middle_end/base_types/compilation_unit.cmx \
middle_end/base_types/closure_id.cmx \
middle_end/closure_conversion_aux.cmx utils/clflags.cmx \
middle_end/base_types/static_exception.cmi \
middle_end/base_types/set_of_closures_origin.cmi \
middle_end/base_types/set_of_closures_id.cmi middle_end/projection.cmi \
- bytecomp/printlambda.cmi utils/numbers.cmi \
+ bytecomp/printlambda.cmi middle_end/parameter.cmi utils/numbers.cmi \
middle_end/base_types/mutable_variable.cmi utils/misc.cmi \
bytecomp/lambda.cmi utils/identifiable.cmi middle_end/debuginfo.cmi \
middle_end/base_types/compilation_unit.cmi \
middle_end/base_types/static_exception.cmx \
middle_end/base_types/set_of_closures_origin.cmx \
middle_end/base_types/set_of_closures_id.cmx middle_end/projection.cmx \
- bytecomp/printlambda.cmx utils/numbers.cmx \
+ bytecomp/printlambda.cmx middle_end/parameter.cmx utils/numbers.cmx \
middle_end/base_types/mutable_variable.cmx utils/misc.cmx \
bytecomp/lambda.cmx utils/identifiable.cmx middle_end/debuginfo.cmx \
middle_end/base_types/compilation_unit.cmx \
middle_end/base_types/static_exception.cmi \
middle_end/base_types/set_of_closures_origin.cmi \
middle_end/base_types/set_of_closures_id.cmi middle_end/projection.cmi \
- utils/numbers.cmi middle_end/base_types/mutable_variable.cmi \
- bytecomp/lambda.cmi utils/identifiable.cmi middle_end/debuginfo.cmi \
+ middle_end/parameter.cmi utils/numbers.cmi \
+ middle_end/base_types/mutable_variable.cmi bytecomp/lambda.cmi \
+ utils/identifiable.cmi middle_end/debuginfo.cmi \
middle_end/base_types/closure_id.cmi parsing/asttypes.cmi \
middle_end/allocated_const.cmi
middle_end/flambda_invariants.cmo : middle_end/base_types/variable.cmi \
middle_end/base_types/static_exception.cmi \
middle_end/base_types/set_of_closures_origin.cmi \
middle_end/base_types/set_of_closures_id.cmi middle_end/projection.cmi \
- bytecomp/printlambda.cmi utils/numbers.cmi \
+ bytecomp/printlambda.cmi middle_end/parameter.cmi utils/numbers.cmi \
middle_end/base_types/mutable_variable.cmi utils/misc.cmi \
bytecomp/lambda.cmi typing/ident.cmi middle_end/flambda_iterators.cmi \
middle_end/flambda.cmi middle_end/debuginfo.cmi \
middle_end/base_types/static_exception.cmx \
middle_end/base_types/set_of_closures_origin.cmx \
middle_end/base_types/set_of_closures_id.cmx middle_end/projection.cmx \
- bytecomp/printlambda.cmx utils/numbers.cmx \
+ bytecomp/printlambda.cmx middle_end/parameter.cmx utils/numbers.cmx \
middle_end/base_types/mutable_variable.cmx utils/misc.cmx \
bytecomp/lambda.cmx typing/ident.cmx middle_end/flambda_iterators.cmx \
middle_end/flambda.cmx middle_end/debuginfo.cmx \
middle_end/base_types/symbol.cmi bytecomp/switch.cmi \
middle_end/base_types/static_exception.cmi \
middle_end/base_types/set_of_closures_id.cmi middle_end/projection.cmi \
- middle_end/base_types/mutable_variable.cmi utils/misc.cmi \
- middle_end/base_types/linkage_name.cmi middle_end/flambda_iterators.cmi \
- middle_end/flambda.cmi middle_end/debuginfo.cmi \
- middle_end/base_types/compilation_unit.cmi \
+ middle_end/parameter.cmi middle_end/base_types/mutable_variable.cmi \
+ utils/misc.cmi middle_end/base_types/linkage_name.cmi bytecomp/lambda.cmi \
+ middle_end/flambda_iterators.cmi middle_end/flambda.cmi \
+ middle_end/debuginfo.cmi middle_end/base_types/compilation_unit.cmi \
middle_end/base_types/closure_id.cmi middle_end/backend_intf.cmi \
middle_end/allocated_const.cmi middle_end/flambda_utils.cmi
middle_end/flambda_utils.cmx : middle_end/base_types/variable.cmx \
middle_end/base_types/symbol.cmx bytecomp/switch.cmx \
middle_end/base_types/static_exception.cmx \
middle_end/base_types/set_of_closures_id.cmx middle_end/projection.cmx \
- middle_end/base_types/mutable_variable.cmx utils/misc.cmx \
- middle_end/base_types/linkage_name.cmx middle_end/flambda_iterators.cmx \
- middle_end/flambda.cmx middle_end/debuginfo.cmx \
- middle_end/base_types/compilation_unit.cmx \
+ middle_end/parameter.cmx middle_end/base_types/mutable_variable.cmx \
+ utils/misc.cmx middle_end/base_types/linkage_name.cmx bytecomp/lambda.cmx \
+ middle_end/flambda_iterators.cmx middle_end/flambda.cmx \
+ middle_end/debuginfo.cmx middle_end/base_types/compilation_unit.cmx \
middle_end/base_types/closure_id.cmx middle_end/backend_intf.cmi \
middle_end/allocated_const.cmx middle_end/flambda_utils.cmi
middle_end/flambda_utils.cmi : middle_end/base_types/variable.cmi \
middle_end/base_types/tag.cmi middle_end/base_types/symbol.cmi \
bytecomp/switch.cmi middle_end/base_types/static_exception.cmi \
middle_end/base_types/set_of_closures_id.cmi middle_end/projection.cmi \
- middle_end/flambda.cmi middle_end/base_types/closure_id.cmi \
- middle_end/backend_intf.cmi
+ middle_end/parameter.cmi middle_end/flambda.cmi \
+ middle_end/base_types/closure_id.cmi middle_end/backend_intf.cmi
middle_end/freshening.cmo : middle_end/base_types/variable.cmi \
middle_end/base_types/var_within_closure.cmi \
middle_end/base_types/symbol.cmi \
middle_end/base_types/static_exception.cmi middle_end/projection.cmi \
- middle_end/base_types/mutable_variable.cmi utils/misc.cmi \
- utils/identifiable.cmi middle_end/flambda_utils.cmi \
+ middle_end/parameter.cmi middle_end/base_types/mutable_variable.cmi \
+ utils/misc.cmi utils/identifiable.cmi middle_end/flambda_utils.cmi \
middle_end/flambda_iterators.cmi middle_end/flambda.cmi \
middle_end/base_types/closure_id.cmi middle_end/freshening.cmi
middle_end/freshening.cmx : middle_end/base_types/variable.cmx \
middle_end/base_types/var_within_closure.cmx \
middle_end/base_types/symbol.cmx \
middle_end/base_types/static_exception.cmx middle_end/projection.cmx \
- middle_end/base_types/mutable_variable.cmx utils/misc.cmx \
- utils/identifiable.cmx middle_end/flambda_utils.cmx \
+ middle_end/parameter.cmx middle_end/base_types/mutable_variable.cmx \
+ utils/misc.cmx utils/identifiable.cmx middle_end/flambda_utils.cmx \
middle_end/flambda_iterators.cmx middle_end/flambda.cmx \
middle_end/base_types/closure_id.cmx middle_end/freshening.cmi
middle_end/freshening.cmi : middle_end/base_types/variable.cmi \
middle_end/base_types/closure_id.cmi
middle_end/inconstant_idents.cmo : middle_end/base_types/variable.cmi \
middle_end/base_types/symbol.cmi \
- middle_end/base_types/set_of_closures_id.cmi utils/numbers.cmi \
- utils/misc.cmi bytecomp/lambda.cmi utils/identifiable.cmi \
- middle_end/flambda_utils.cmi middle_end/flambda.cmi \
- middle_end/base_types/compilation_unit.cmi \
+ middle_end/base_types/set_of_closures_id.cmi middle_end/parameter.cmi \
+ utils/numbers.cmi utils/misc.cmi bytecomp/lambda.cmi \
+ utils/identifiable.cmi middle_end/flambda_utils.cmi \
+ middle_end/flambda.cmi middle_end/base_types/compilation_unit.cmi \
middle_end/base_types/closure_id.cmi middle_end/backend_intf.cmi \
parsing/asttypes.cmi middle_end/inconstant_idents.cmi
middle_end/inconstant_idents.cmx : middle_end/base_types/variable.cmx \
middle_end/base_types/symbol.cmx \
- middle_end/base_types/set_of_closures_id.cmx utils/numbers.cmx \
- utils/misc.cmx bytecomp/lambda.cmx utils/identifiable.cmx \
- middle_end/flambda_utils.cmx middle_end/flambda.cmx \
- middle_end/base_types/compilation_unit.cmx \
+ middle_end/base_types/set_of_closures_id.cmx middle_end/parameter.cmx \
+ utils/numbers.cmx utils/misc.cmx bytecomp/lambda.cmx \
+ utils/identifiable.cmx middle_end/flambda_utils.cmx \
+ middle_end/flambda.cmx middle_end/base_types/compilation_unit.cmx \
middle_end/base_types/closure_id.cmx middle_end/backend_intf.cmi \
parsing/asttypes.cmi middle_end/inconstant_idents.cmi
middle_end/inconstant_idents.cmi : middle_end/base_types/variable.cmi \
middle_end/simplify_primitives.cmi middle_end/simple_value_approx.cmi \
middle_end/remove_unused_arguments.cmi \
middle_end/remove_free_vars_equal_to_args.cmi middle_end/projection.cmi \
- typing/predef.cmi utils/misc.cmi parsing/location.cmi \
- middle_end/lift_code.cmi bytecomp/lambda.cmi \
+ typing/predef.cmi middle_end/parameter.cmi utils/misc.cmi \
+ parsing/location.cmi middle_end/lift_code.cmi bytecomp/lambda.cmi \
middle_end/invariant_params.cmi middle_end/inlining_stats.cmi \
middle_end/inlining_decision.cmi middle_end/inlining_cost.cmi \
middle_end/inline_and_simplify_aux.cmi typing/ident.cmi \
middle_end/freshening.cmi middle_end/flambda_utils.cmi \
middle_end/flambda.cmi middle_end/effect_analysis.cmi \
- middle_end/debuginfo.cmi middle_end/base_types/closure_id.cmi \
- utils/clflags.cmi middle_end/backend_intf.cmi \
- middle_end/allocated_const.cmi middle_end/inline_and_simplify.cmi
+ middle_end/debuginfo.cmi utils/config.cmi \
+ middle_end/base_types/closure_id.cmi utils/clflags.cmi \
+ middle_end/backend_intf.cmi middle_end/allocated_const.cmi \
+ middle_end/inline_and_simplify.cmi
middle_end/inline_and_simplify.cmx : utils/warnings.cmx \
middle_end/base_types/variable.cmx \
middle_end/base_types/var_within_closure.cmx \
middle_end/simplify_primitives.cmx middle_end/simple_value_approx.cmx \
middle_end/remove_unused_arguments.cmx \
middle_end/remove_free_vars_equal_to_args.cmx middle_end/projection.cmx \
- typing/predef.cmx utils/misc.cmx parsing/location.cmx \
- middle_end/lift_code.cmx bytecomp/lambda.cmx \
+ typing/predef.cmx middle_end/parameter.cmx utils/misc.cmx \
+ parsing/location.cmx middle_end/lift_code.cmx bytecomp/lambda.cmx \
middle_end/invariant_params.cmx middle_end/inlining_stats.cmx \
middle_end/inlining_decision.cmx middle_end/inlining_cost.cmx \
middle_end/inline_and_simplify_aux.cmx typing/ident.cmx \
middle_end/freshening.cmx middle_end/flambda_utils.cmx \
middle_end/flambda.cmx middle_end/effect_analysis.cmx \
- middle_end/debuginfo.cmx middle_end/base_types/closure_id.cmx \
- utils/clflags.cmx middle_end/backend_intf.cmi \
- middle_end/allocated_const.cmx middle_end/inline_and_simplify.cmi
+ middle_end/debuginfo.cmx utils/config.cmx \
+ middle_end/base_types/closure_id.cmx utils/clflags.cmx \
+ middle_end/backend_intf.cmi middle_end/allocated_const.cmx \
+ middle_end/inline_and_simplify.cmi
middle_end/inline_and_simplify.cmi : middle_end/base_types/variable.cmi \
middle_end/inline_and_simplify_aux.cmi middle_end/flambda.cmi \
middle_end/backend_intf.cmi
middle_end/base_types/static_exception.cmi \
middle_end/simple_value_approx.cmi \
middle_end/base_types/set_of_closures_origin.cmi \
- middle_end/projection.cmi middle_end/base_types/mutable_variable.cmi \
- utils/misc.cmi middle_end/inlining_stats.cmi middle_end/inlining_cost.cmi \
+ middle_end/projection.cmi middle_end/parameter.cmi \
+ middle_end/base_types/mutable_variable.cmi utils/misc.cmi \
+ middle_end/inlining_stats.cmi middle_end/inlining_cost.cmi \
middle_end/freshening.cmi middle_end/flambda.cmi middle_end/debuginfo.cmi \
middle_end/base_types/compilation_unit.cmi \
middle_end/base_types/closure_id.cmi utils/clflags.cmi \
middle_end/base_types/static_exception.cmx \
middle_end/simple_value_approx.cmx \
middle_end/base_types/set_of_closures_origin.cmx \
- middle_end/projection.cmx middle_end/base_types/mutable_variable.cmx \
- utils/misc.cmx middle_end/inlining_stats.cmx middle_end/inlining_cost.cmx \
+ middle_end/projection.cmx middle_end/parameter.cmx \
+ middle_end/base_types/mutable_variable.cmx utils/misc.cmx \
+ middle_end/inlining_stats.cmx middle_end/inlining_cost.cmx \
middle_end/freshening.cmx middle_end/flambda.cmx middle_end/debuginfo.cmx \
middle_end/base_types/compilation_unit.cmx \
middle_end/base_types/closure_id.cmx utils/clflags.cmx \
middle_end/flambda.cmi
middle_end/inlining_decision.cmo : middle_end/base_types/variable.cmi \
middle_end/base_types/var_within_closure.cmi \
- middle_end/simple_value_approx.cmi utils/misc.cmi bytecomp/lambda.cmi \
- middle_end/inlining_transforms.cmi middle_end/inlining_stats_types.cmi \
- middle_end/inlining_cost.cmi middle_end/inline_and_simplify_aux.cmi \
- middle_end/flambda_utils.cmi middle_end/flambda.cmi \
- middle_end/find_recursive_functions.cmi \
+ middle_end/simple_value_approx.cmi middle_end/parameter.cmi \
+ utils/misc.cmi bytecomp/lambda.cmi middle_end/inlining_transforms.cmi \
+ middle_end/inlining_stats_types.cmi middle_end/inlining_cost.cmi \
+ middle_end/inline_and_simplify_aux.cmi middle_end/flambda_utils.cmi \
+ middle_end/flambda.cmi middle_end/find_recursive_functions.cmi \
middle_end/base_types/closure_id.cmi utils/clflags.cmi \
middle_end/inlining_decision.cmi
middle_end/inlining_decision.cmx : middle_end/base_types/variable.cmx \
middle_end/base_types/var_within_closure.cmx \
- middle_end/simple_value_approx.cmx utils/misc.cmx bytecomp/lambda.cmx \
- middle_end/inlining_transforms.cmx middle_end/inlining_stats_types.cmx \
- middle_end/inlining_cost.cmx middle_end/inline_and_simplify_aux.cmx \
- middle_end/flambda_utils.cmx middle_end/flambda.cmx \
- middle_end/find_recursive_functions.cmx \
+ middle_end/simple_value_approx.cmx middle_end/parameter.cmx \
+ utils/misc.cmx bytecomp/lambda.cmx middle_end/inlining_transforms.cmx \
+ middle_end/inlining_stats_types.cmx middle_end/inlining_cost.cmx \
+ middle_end/inline_and_simplify_aux.cmx middle_end/flambda_utils.cmx \
+ middle_end/flambda.cmx middle_end/find_recursive_functions.cmx \
middle_end/base_types/closure_id.cmx utils/clflags.cmx \
middle_end/inlining_decision.cmi
middle_end/inlining_decision.cmi : middle_end/base_types/variable.cmi \
middle_end/inlining_stats_types.cmi : middle_end/inlining_cost.cmi
middle_end/inlining_transforms.cmo : middle_end/base_types/variable.cmi \
middle_end/base_types/var_within_closure.cmi \
- middle_end/simple_value_approx.cmi utils/misc.cmi bytecomp/lambda.cmi \
- middle_end/inlining_cost.cmi middle_end/inline_and_simplify_aux.cmi \
- middle_end/freshening.cmi middle_end/flambda_utils.cmi \
- middle_end/flambda_iterators.cmi middle_end/flambda.cmi \
- middle_end/base_types/compilation_unit.cmi \
+ middle_end/simple_value_approx.cmi middle_end/parameter.cmi \
+ utils/misc.cmi bytecomp/lambda.cmi middle_end/inlining_cost.cmi \
+ middle_end/inline_and_simplify_aux.cmi middle_end/freshening.cmi \
+ middle_end/flambda_utils.cmi middle_end/flambda_iterators.cmi \
+ middle_end/flambda.cmi middle_end/base_types/compilation_unit.cmi \
middle_end/base_types/closure_id.cmi middle_end/backend_intf.cmi \
middle_end/inlining_transforms.cmi
middle_end/inlining_transforms.cmx : middle_end/base_types/variable.cmx \
middle_end/base_types/var_within_closure.cmx \
- middle_end/simple_value_approx.cmx utils/misc.cmx bytecomp/lambda.cmx \
- middle_end/inlining_cost.cmx middle_end/inline_and_simplify_aux.cmx \
- middle_end/freshening.cmx middle_end/flambda_utils.cmx \
- middle_end/flambda_iterators.cmx middle_end/flambda.cmx \
- middle_end/base_types/compilation_unit.cmx \
+ middle_end/simple_value_approx.cmx middle_end/parameter.cmx \
+ utils/misc.cmx bytecomp/lambda.cmx middle_end/inlining_cost.cmx \
+ middle_end/inline_and_simplify_aux.cmx middle_end/freshening.cmx \
+ middle_end/flambda_utils.cmx middle_end/flambda_iterators.cmx \
+ middle_end/flambda.cmx middle_end/base_types/compilation_unit.cmx \
middle_end/base_types/closure_id.cmx middle_end/backend_intf.cmi \
middle_end/inlining_transforms.cmi
middle_end/inlining_transforms.cmi : middle_end/base_types/variable.cmi \
middle_end/inline_and_simplify_aux.cmi middle_end/flambda.cmi \
middle_end/debuginfo.cmi middle_end/base_types/closure_id.cmi
middle_end/invariant_params.cmo : middle_end/base_types/variable.cmi \
- middle_end/base_types/symbol.cmi middle_end/flambda_utils.cmi \
- middle_end/flambda_iterators.cmi middle_end/flambda.cmi \
- middle_end/base_types/closure_id.cmi utils/clflags.cmi \
- middle_end/backend_intf.cmi middle_end/invariant_params.cmi
+ middle_end/base_types/symbol.cmi middle_end/parameter.cmi \
+ middle_end/flambda_utils.cmi middle_end/flambda_iterators.cmi \
+ middle_end/flambda.cmi middle_end/base_types/closure_id.cmi \
+ utils/clflags.cmi middle_end/backend_intf.cmi \
+ middle_end/invariant_params.cmi
middle_end/invariant_params.cmx : middle_end/base_types/variable.cmx \
- middle_end/base_types/symbol.cmx middle_end/flambda_utils.cmx \
- middle_end/flambda_iterators.cmx middle_end/flambda.cmx \
- middle_end/base_types/closure_id.cmx utils/clflags.cmx \
- middle_end/backend_intf.cmi middle_end/invariant_params.cmi
+ middle_end/base_types/symbol.cmx middle_end/parameter.cmx \
+ middle_end/flambda_utils.cmx middle_end/flambda_iterators.cmx \
+ middle_end/flambda.cmx middle_end/base_types/closure_id.cmx \
+ utils/clflags.cmx middle_end/backend_intf.cmi \
+ middle_end/invariant_params.cmi
middle_end/invariant_params.cmi : middle_end/base_types/variable.cmi \
middle_end/flambda.cmi middle_end/backend_intf.cmi
middle_end/lift_code.cmo : middle_end/base_types/variable.cmi \
middle_end/lift_let_to_initialize_symbol.cmi : middle_end/flambda.cmi \
middle_end/backend_intf.cmi
middle_end/middle_end.cmo : utils/warnings.cmi \
- middle_end/base_types/variable.cmi utils/timings.cmi \
- middle_end/base_types/symbol.cmi middle_end/share_constants.cmi \
+ middle_end/base_types/variable.cmi middle_end/base_types/symbol.cmi \
+ middle_end/share_constants.cmi \
middle_end/remove_unused_program_constructs.cmi \
middle_end/remove_unused_closure_vars.cmi middle_end/ref_to_variables.cmi \
- utils/misc.cmi parsing/location.cmi \
+ utils/profile.cmi utils/misc.cmi parsing/location.cmi \
middle_end/lift_let_to_initialize_symbol.cmi \
middle_end/lift_constants.cmi middle_end/lift_code.cmi \
middle_end/inlining_cost.cmi middle_end/inline_and_simplify.cmi \
middle_end/base_types/closure_id.cmi middle_end/closure_conversion.cmi \
utils/clflags.cmi middle_end/backend_intf.cmi middle_end/middle_end.cmi
middle_end/middle_end.cmx : utils/warnings.cmx \
- middle_end/base_types/variable.cmx utils/timings.cmx \
- middle_end/base_types/symbol.cmx middle_end/share_constants.cmx \
+ middle_end/base_types/variable.cmx middle_end/base_types/symbol.cmx \
+ middle_end/share_constants.cmx \
middle_end/remove_unused_program_constructs.cmx \
middle_end/remove_unused_closure_vars.cmx middle_end/ref_to_variables.cmx \
- utils/misc.cmx parsing/location.cmx \
+ utils/profile.cmx utils/misc.cmx parsing/location.cmx \
middle_end/lift_let_to_initialize_symbol.cmx \
middle_end/lift_constants.cmx middle_end/lift_code.cmx \
middle_end/inlining_cost.cmx middle_end/inline_and_simplify.cmx \
middle_end/flambda.cmx middle_end/debuginfo.cmx \
middle_end/base_types/closure_id.cmx middle_end/closure_conversion.cmx \
utils/clflags.cmx middle_end/backend_intf.cmi middle_end/middle_end.cmi
-middle_end/middle_end.cmi : utils/timings.cmi bytecomp/lambda.cmi \
- typing/ident.cmi middle_end/flambda.cmi middle_end/backend_intf.cmi
+middle_end/middle_end.cmi : bytecomp/lambda.cmi typing/ident.cmi \
+ middle_end/flambda.cmi middle_end/backend_intf.cmi
+middle_end/parameter.cmo : middle_end/base_types/variable.cmi \
+ utils/identifiable.cmi middle_end/parameter.cmi
+middle_end/parameter.cmx : middle_end/base_types/variable.cmx \
+ utils/identifiable.cmx middle_end/parameter.cmi
+middle_end/parameter.cmi : middle_end/base_types/variable.cmi \
+ utils/identifiable.cmi middle_end/base_types/compilation_unit.cmi
middle_end/pass_wrapper.cmo : utils/clflags.cmi middle_end/pass_wrapper.cmi
middle_end/pass_wrapper.cmx : utils/clflags.cmx middle_end/pass_wrapper.cmi
middle_end/pass_wrapper.cmi :
middle_end/ref_to_variables.cmi : middle_end/flambda.cmi
middle_end/remove_free_vars_equal_to_args.cmo : \
middle_end/base_types/variable.cmi middle_end/pass_wrapper.cmi \
- middle_end/flambda_utils.cmi middle_end/flambda.cmi \
- middle_end/remove_free_vars_equal_to_args.cmi
+ middle_end/parameter.cmi middle_end/flambda_utils.cmi \
+ middle_end/flambda.cmi middle_end/remove_free_vars_equal_to_args.cmi
middle_end/remove_free_vars_equal_to_args.cmx : \
middle_end/base_types/variable.cmx middle_end/pass_wrapper.cmx \
- middle_end/flambda_utils.cmx middle_end/flambda.cmx \
- middle_end/remove_free_vars_equal_to_args.cmi
+ middle_end/parameter.cmx middle_end/flambda_utils.cmx \
+ middle_end/flambda.cmx middle_end/remove_free_vars_equal_to_args.cmi
middle_end/remove_free_vars_equal_to_args.cmi : middle_end/flambda.cmi
middle_end/remove_unused_arguments.cmo : middle_end/base_types/variable.cmi \
- middle_end/projection.cmi middle_end/invariant_params.cmi \
- middle_end/flambda_utils.cmi middle_end/flambda_iterators.cmi \
- middle_end/flambda.cmi middle_end/find_recursive_functions.cmi \
+ middle_end/projection.cmi middle_end/parameter.cmi \
+ middle_end/invariant_params.cmi middle_end/flambda_utils.cmi \
+ middle_end/flambda_iterators.cmi middle_end/flambda.cmi \
+ middle_end/find_recursive_functions.cmi \
middle_end/base_types/compilation_unit.cmi \
middle_end/base_types/closure_id.cmi utils/clflags.cmi \
middle_end/remove_unused_arguments.cmi
middle_end/remove_unused_arguments.cmx : middle_end/base_types/variable.cmx \
- middle_end/projection.cmx middle_end/invariant_params.cmx \
- middle_end/flambda_utils.cmx middle_end/flambda_iterators.cmx \
- middle_end/flambda.cmx middle_end/find_recursive_functions.cmx \
+ middle_end/projection.cmx middle_end/parameter.cmx \
+ middle_end/invariant_params.cmx middle_end/flambda_utils.cmx \
+ middle_end/flambda_iterators.cmx middle_end/flambda.cmx \
+ middle_end/find_recursive_functions.cmx \
middle_end/base_types/compilation_unit.cmx \
middle_end/base_types/closure_id.cmx utils/clflags.cmx \
middle_end/remove_unused_arguments.cmi
middle_end/backend_intf.cmi
middle_end/remove_unused_closure_vars.cmo : \
middle_end/base_types/variable.cmi \
- middle_end/base_types/var_within_closure.cmi middle_end/flambda_utils.cmi \
- middle_end/flambda_iterators.cmi middle_end/flambda.cmi \
- middle_end/base_types/closure_id.cmi \
+ middle_end/base_types/var_within_closure.cmi middle_end/parameter.cmi \
+ middle_end/flambda_utils.cmi middle_end/flambda_iterators.cmi \
+ middle_end/flambda.cmi middle_end/base_types/closure_id.cmi \
middle_end/remove_unused_closure_vars.cmi
middle_end/remove_unused_closure_vars.cmx : \
middle_end/base_types/variable.cmx \
- middle_end/base_types/var_within_closure.cmx middle_end/flambda_utils.cmx \
- middle_end/flambda_iterators.cmx middle_end/flambda.cmx \
- middle_end/base_types/closure_id.cmx \
+ middle_end/base_types/var_within_closure.cmx middle_end/parameter.cmx \
+ middle_end/flambda_utils.cmx middle_end/flambda_iterators.cmx \
+ middle_end/flambda.cmx middle_end/base_types/closure_id.cmx \
middle_end/remove_unused_closure_vars.cmi
middle_end/remove_unused_closure_vars.cmi : middle_end/flambda.cmi
middle_end/remove_unused_program_constructs.cmo : \
middle_end/simple_value_approx.cmo : middle_end/base_types/variable.cmi \
middle_end/base_types/var_within_closure.cmi \
middle_end/base_types/tag.cmi middle_end/base_types/symbol.cmi \
- middle_end/base_types/set_of_closures_id.cmi utils/misc.cmi \
- bytecomp/lambda.cmi middle_end/inlining_cost.cmi \
+ middle_end/base_types/set_of_closures_id.cmi middle_end/parameter.cmi \
+ utils/misc.cmi bytecomp/lambda.cmi middle_end/inlining_cost.cmi \
middle_end/freshening.cmi middle_end/flambda_utils.cmi \
middle_end/flambda.cmi middle_end/base_types/export_id.cmi \
middle_end/effect_analysis.cmi middle_end/base_types/closure_id.cmi \
middle_end/simple_value_approx.cmx : middle_end/base_types/variable.cmx \
middle_end/base_types/var_within_closure.cmx \
middle_end/base_types/tag.cmx middle_end/base_types/symbol.cmx \
- middle_end/base_types/set_of_closures_id.cmx utils/misc.cmx \
- bytecomp/lambda.cmx middle_end/inlining_cost.cmx \
+ middle_end/base_types/set_of_closures_id.cmx middle_end/parameter.cmx \
+ utils/misc.cmx bytecomp/lambda.cmx middle_end/inlining_cost.cmx \
middle_end/freshening.cmx middle_end/flambda_utils.cmx \
middle_end/flambda.cmx middle_end/base_types/export_id.cmx \
middle_end/effect_analysis.cmx middle_end/base_types/closure_id.cmx \
middle_end/base_types/variable.cmi
middle_end/base_types/variable.cmi : utils/identifiable.cmi typing/ident.cmi \
middle_end/base_types/compilation_unit.cmi
+asmcomp/debug/available_regs.cmo : asmcomp/debug/reg_with_debug_info.cmi \
+ asmcomp/debug/reg_availability_set.cmi asmcomp/reg.cmi asmcomp/proc.cmi \
+ asmcomp/printmach.cmi utils/misc.cmi asmcomp/mach.cmi typing/ident.cmi \
+ utils/clflags.cmi asmcomp/debug/available_regs.cmi
+asmcomp/debug/available_regs.cmx : asmcomp/debug/reg_with_debug_info.cmx \
+ asmcomp/debug/reg_availability_set.cmx asmcomp/reg.cmx asmcomp/proc.cmx \
+ asmcomp/printmach.cmx utils/misc.cmx asmcomp/mach.cmx typing/ident.cmx \
+ utils/clflags.cmx asmcomp/debug/available_regs.cmi
+asmcomp/debug/available_regs.cmi : asmcomp/mach.cmi
+asmcomp/debug/reg_availability_set.cmo : \
+ asmcomp/debug/reg_with_debug_info.cmi typing/ident.cmi \
+ asmcomp/debug/reg_availability_set.cmi
+asmcomp/debug/reg_availability_set.cmx : \
+ asmcomp/debug/reg_with_debug_info.cmx typing/ident.cmx \
+ asmcomp/debug/reg_availability_set.cmi
+asmcomp/debug/reg_availability_set.cmi : \
+ asmcomp/debug/reg_with_debug_info.cmi asmcomp/reg.cmi
+asmcomp/debug/reg_with_debug_info.cmo : asmcomp/reg.cmi typing/ident.cmi \
+ asmcomp/debug/reg_with_debug_info.cmi
+asmcomp/debug/reg_with_debug_info.cmx : asmcomp/reg.cmx typing/ident.cmx \
+ asmcomp/debug/reg_with_debug_info.cmi
+asmcomp/debug/reg_with_debug_info.cmi : asmcomp/reg.cmi typing/ident.cmi
driver/compdynlink.cmi :
-driver/compenv.cmo : utils/warnings.cmi utils/misc.cmi parsing/location.cmi \
- utils/config.cmi utils/clflags.cmi utils/ccomp.cmi driver/compenv.cmi
-driver/compenv.cmx : utils/warnings.cmx utils/misc.cmx parsing/location.cmx \
- utils/config.cmx utils/clflags.cmx utils/ccomp.cmx driver/compenv.cmi
+driver/compenv.cmo : utils/warnings.cmi utils/profile.cmi utils/misc.cmi \
+ parsing/location.cmi utils/config.cmi utils/clflags.cmi utils/ccomp.cmi \
+ driver/compenv.cmi
+driver/compenv.cmx : utils/warnings.cmx utils/profile.cmx utils/misc.cmx \
+ parsing/location.cmx utils/config.cmx utils/clflags.cmx utils/ccomp.cmx \
+ driver/compenv.cmi
driver/compenv.cmi :
driver/compile.cmo : utils/warnings.cmi typing/typemod.cmi \
typing/typedtree.cmi typing/typecore.cmi bytecomp/translmod.cmi \
- utils/timings.cmi typing/stypes.cmi bytecomp/simplif.cmi \
+ typing/stypes.cmi bytecomp/simplif.cmi utils/profile.cmi \
typing/printtyped.cmi typing/printtyp.cmi bytecomp/printlambda.cmi \
bytecomp/printinstr.cmi parsing/printast.cmi parsing/pprintast.cmi \
driver/pparse.cmi utils/misc.cmi bytecomp/lambda.cmi \
bytecomp/bytegen.cmi parsing/builtin_attributes.cmi driver/compile.cmi
driver/compile.cmx : utils/warnings.cmx typing/typemod.cmx \
typing/typedtree.cmx typing/typecore.cmx bytecomp/translmod.cmx \
- utils/timings.cmx typing/stypes.cmx bytecomp/simplif.cmx \
+ typing/stypes.cmx bytecomp/simplif.cmx utils/profile.cmx \
typing/printtyped.cmx typing/printtyp.cmx bytecomp/printlambda.cmx \
bytecomp/printinstr.cmx parsing/printast.cmx parsing/pprintast.cmx \
driver/pparse.cmx utils/misc.cmx bytecomp/lambda.cmx \
driver/errors.cmo : parsing/location.cmi driver/errors.cmi
driver/errors.cmx : parsing/location.cmx driver/errors.cmi
driver/errors.cmi :
-driver/main.cmo : utils/warnings.cmi utils/timings.cmi utils/misc.cmi \
- driver/main_args.cmi parsing/location.cmi utils/config.cmi \
- driver/compplugin.cmi driver/compmisc.cmi driver/compile.cmi \
- driver/compenv.cmi utils/clflags.cmi bytecomp/bytepackager.cmi \
- bytecomp/bytelink.cmi bytecomp/bytelibrarian.cmi driver/main.cmi
-driver/main.cmx : utils/warnings.cmx utils/timings.cmx utils/misc.cmx \
- driver/main_args.cmx parsing/location.cmx utils/config.cmx \
- driver/compplugin.cmx driver/compmisc.cmx driver/compile.cmx \
- driver/compenv.cmx utils/clflags.cmx bytecomp/bytepackager.cmx \
- bytecomp/bytelink.cmx bytecomp/bytelibrarian.cmx driver/main.cmi
+driver/main.cmo : utils/warnings.cmi utils/profile.cmi utils/misc.cmi \
+ driver/makedepend.cmi driver/main_args.cmi parsing/location.cmi \
+ utils/config.cmi driver/compplugin.cmi driver/compmisc.cmi \
+ driver/compile.cmi driver/compenv.cmi utils/clflags.cmi \
+ bytecomp/bytepackager.cmi bytecomp/bytelink.cmi \
+ bytecomp/bytelibrarian.cmi driver/main.cmi
+driver/main.cmx : utils/warnings.cmx utils/profile.cmx utils/misc.cmx \
+ driver/makedepend.cmx driver/main_args.cmx parsing/location.cmx \
+ utils/config.cmx driver/compplugin.cmx driver/compmisc.cmx \
+ driver/compile.cmx driver/compenv.cmx utils/clflags.cmx \
+ bytecomp/bytepackager.cmx bytecomp/bytelink.cmx \
+ bytecomp/bytelibrarian.cmx driver/main.cmi
driver/main.cmi :
-driver/main_args.cmo : utils/warnings.cmi utils/config.cmi utils/clflags.cmi \
- driver/main_args.cmi
-driver/main_args.cmx : utils/warnings.cmx utils/config.cmx utils/clflags.cmx \
- driver/main_args.cmi
+driver/main_args.cmo : utils/warnings.cmi utils/profile.cmi utils/config.cmi \
+ utils/clflags.cmi driver/main_args.cmi
+driver/main_args.cmx : utils/warnings.cmx utils/profile.cmx utils/config.cmx \
+ utils/clflags.cmx driver/main_args.cmi
driver/main_args.cmi :
+driver/makedepend.cmo : driver/pparse.cmi parsing/parsetree.cmi \
+ parsing/parser.cmi parsing/parse.cmi utils/misc.cmi parsing/longident.cmi \
+ parsing/location.cmi parsing/lexer.cmi parsing/depend.cmi \
+ utils/config.cmi driver/compplugin.cmi driver/compenv.cmi \
+ utils/clflags.cmi driver/makedepend.cmi
+driver/makedepend.cmx : driver/pparse.cmx parsing/parsetree.cmi \
+ parsing/parser.cmx parsing/parse.cmx utils/misc.cmx parsing/longident.cmx \
+ parsing/location.cmx parsing/lexer.cmx parsing/depend.cmx \
+ utils/config.cmx driver/compplugin.cmx driver/compenv.cmx \
+ utils/clflags.cmx driver/makedepend.cmi
+driver/makedepend.cmi :
driver/optcompile.cmo : utils/warnings.cmi typing/typemod.cmi \
typing/typedtree.cmi typing/typecore.cmi bytecomp/translmod.cmi \
- utils/timings.cmi typing/stypes.cmi bytecomp/simplif.cmi \
+ typing/stypes.cmi bytecomp/simplif.cmi utils/profile.cmi \
typing/printtyped.cmi typing/printtyp.cmi bytecomp/printlambda.cmi \
parsing/printast.cmi parsing/pprintast.cmi driver/pparse.cmi \
utils/misc.cmi middle_end/middle_end.cmi bytecomp/lambda.cmi \
parsing/builtin_attributes.cmi asmcomp/asmgen.cmi driver/optcompile.cmi
driver/optcompile.cmx : utils/warnings.cmx typing/typemod.cmx \
typing/typedtree.cmx typing/typecore.cmx bytecomp/translmod.cmx \
- utils/timings.cmx typing/stypes.cmx bytecomp/simplif.cmx \
+ typing/stypes.cmx bytecomp/simplif.cmx utils/profile.cmx \
typing/printtyped.cmx typing/printtyp.cmx bytecomp/printlambda.cmx \
parsing/printast.cmx parsing/pprintast.cmx driver/pparse.cmx \
utils/misc.cmx middle_end/middle_end.cmx bytecomp/lambda.cmx \
driver/opterrors.cmo : parsing/location.cmi driver/opterrors.cmi
driver/opterrors.cmx : parsing/location.cmx driver/opterrors.cmi
driver/opterrors.cmi :
-driver/optmain.cmo : utils/warnings.cmi utils/timings.cmi asmcomp/proc.cmi \
+driver/optmain.cmo : utils/warnings.cmi utils/profile.cmi asmcomp/proc.cmi \
asmcomp/printmach.cmi driver/optcompile.cmi utils/misc.cmi \
- driver/main_args.cmi parsing/location.cmi asmcomp/import_approx.cmi \
- utils/config.cmi driver/compplugin.cmi driver/compmisc.cmi \
- asmcomp/compilenv.cmi driver/compenv.cmi utils/clflags.cmi \
- middle_end/backend_intf.cmi asmcomp/asmpackager.cmi asmcomp/asmlink.cmi \
- asmcomp/asmlibrarian.cmi asmcomp/arch.cmo driver/optmain.cmi
-driver/optmain.cmx : utils/warnings.cmx utils/timings.cmx asmcomp/proc.cmx \
+ driver/makedepend.cmi driver/main_args.cmi parsing/location.cmi \
+ asmcomp/import_approx.cmi utils/config.cmi driver/compplugin.cmi \
+ driver/compmisc.cmi asmcomp/compilenv.cmi driver/compenv.cmi \
+ utils/clflags.cmi middle_end/backend_intf.cmi asmcomp/asmpackager.cmi \
+ asmcomp/asmlink.cmi asmcomp/asmlibrarian.cmi asmcomp/arch.cmo \
+ driver/optmain.cmi
+driver/optmain.cmx : utils/warnings.cmx utils/profile.cmx asmcomp/proc.cmx \
asmcomp/printmach.cmx driver/optcompile.cmx utils/misc.cmx \
- driver/main_args.cmx parsing/location.cmx asmcomp/import_approx.cmx \
- utils/config.cmx driver/compplugin.cmx driver/compmisc.cmx \
- asmcomp/compilenv.cmx driver/compenv.cmx utils/clflags.cmx \
- middle_end/backend_intf.cmi asmcomp/asmpackager.cmx asmcomp/asmlink.cmx \
- asmcomp/asmlibrarian.cmx asmcomp/arch.cmx driver/optmain.cmi
+ driver/makedepend.cmx driver/main_args.cmx parsing/location.cmx \
+ asmcomp/import_approx.cmx utils/config.cmx driver/compplugin.cmx \
+ driver/compmisc.cmx asmcomp/compilenv.cmx driver/compenv.cmx \
+ utils/clflags.cmx middle_end/backend_intf.cmi asmcomp/asmpackager.cmx \
+ asmcomp/asmlink.cmx asmcomp/asmlibrarian.cmx asmcomp/arch.cmx \
+ driver/optmain.cmi
driver/optmain.cmi :
-driver/pparse.cmo : utils/timings.cmi parsing/parsetree.cmi \
+driver/pparse.cmo : utils/profile.cmi parsing/parsetree.cmi \
parsing/parse.cmi utils/misc.cmi parsing/location.cmi utils/config.cmi \
utils/clflags.cmi utils/ccomp.cmi parsing/ast_mapper.cmi \
parsing/ast_invariants.cmi driver/pparse.cmi
-driver/pparse.cmx : utils/timings.cmx parsing/parsetree.cmi \
+driver/pparse.cmx : utils/profile.cmx parsing/parsetree.cmi \
parsing/parse.cmx utils/misc.cmx parsing/location.cmx utils/config.cmx \
utils/clflags.cmx utils/ccomp.cmx parsing/ast_mapper.cmx \
parsing/ast_invariants.cmx driver/pparse.cmi
toplevel/opttopdirs.cmi : parsing/longident.cmi
toplevel/opttoploop.cmo : utils/warnings.cmi typing/types.cmi \
typing/typemod.cmi typing/typedtree.cmi typing/typecore.cmi \
- bytecomp/translmod.cmi utils/timings.cmi bytecomp/simplif.cmi \
- asmcomp/proc.cmi typing/printtyped.cmi typing/printtyp.cmi \
- bytecomp/printlambda.cmi parsing/printast.cmi typing/predef.cmi \
- parsing/pprintast.cmi driver/pparse.cmi typing/path.cmi \
- parsing/parsetree.cmi parsing/parse.cmi typing/outcometree.cmi \
- typing/oprint.cmi utils/misc.cmi middle_end/middle_end.cmi \
- parsing/longident.cmi parsing/location.cmi parsing/lexer.cmi \
- bytecomp/lambda.cmi typing/includemod.cmi asmcomp/import_approx.cmi \
- typing/ident.cmi toplevel/genprintval.cmi typing/env.cmi utils/config.cmi \
- driver/compmisc.cmi asmcomp/compilenv.cmi driver/compdynlink.cmi \
- utils/clflags.cmi typing/btype.cmi middle_end/backend_intf.cmi \
- parsing/asttypes.cmi parsing/ast_helper.cmi asmcomp/asmlink.cmi \
- asmcomp/asmgen.cmi asmcomp/arch.cmo toplevel/opttoploop.cmi
+ bytecomp/translmod.cmi bytecomp/simplif.cmi asmcomp/proc.cmi \
+ typing/printtyped.cmi typing/printtyp.cmi bytecomp/printlambda.cmi \
+ parsing/printast.cmi typing/predef.cmi parsing/pprintast.cmi \
+ driver/pparse.cmi typing/path.cmi parsing/parsetree.cmi parsing/parse.cmi \
+ typing/outcometree.cmi typing/oprint.cmi utils/misc.cmi \
+ middle_end/middle_end.cmi parsing/longident.cmi parsing/location.cmi \
+ parsing/lexer.cmi bytecomp/lambda.cmi typing/includemod.cmi \
+ asmcomp/import_approx.cmi typing/ident.cmi toplevel/genprintval.cmi \
+ typing/env.cmi utils/config.cmi driver/compmisc.cmi asmcomp/compilenv.cmi \
+ driver/compdynlink.cmi utils/clflags.cmi typing/btype.cmi \
+ middle_end/backend_intf.cmi parsing/asttypes.cmi parsing/ast_helper.cmi \
+ asmcomp/asmlink.cmi asmcomp/asmgen.cmi asmcomp/arch.cmo \
+ toplevel/opttoploop.cmi
toplevel/opttoploop.cmx : utils/warnings.cmx typing/types.cmx \
typing/typemod.cmx typing/typedtree.cmx typing/typecore.cmx \
- bytecomp/translmod.cmx utils/timings.cmx bytecomp/simplif.cmx \
- asmcomp/proc.cmx typing/printtyped.cmx typing/printtyp.cmx \
- bytecomp/printlambda.cmx parsing/printast.cmx typing/predef.cmx \
- parsing/pprintast.cmx driver/pparse.cmx typing/path.cmx \
- parsing/parsetree.cmi parsing/parse.cmx typing/outcometree.cmi \
- typing/oprint.cmx utils/misc.cmx middle_end/middle_end.cmx \
- parsing/longident.cmx parsing/location.cmx parsing/lexer.cmx \
- bytecomp/lambda.cmx typing/includemod.cmx asmcomp/import_approx.cmx \
- typing/ident.cmx toplevel/genprintval.cmx typing/env.cmx utils/config.cmx \
- driver/compmisc.cmx asmcomp/compilenv.cmx driver/compdynlink.cmi \
- utils/clflags.cmx typing/btype.cmx middle_end/backend_intf.cmi \
- parsing/asttypes.cmi parsing/ast_helper.cmx asmcomp/asmlink.cmx \
- asmcomp/asmgen.cmx asmcomp/arch.cmx toplevel/opttoploop.cmi
+ bytecomp/translmod.cmx bytecomp/simplif.cmx asmcomp/proc.cmx \
+ typing/printtyped.cmx typing/printtyp.cmx bytecomp/printlambda.cmx \
+ parsing/printast.cmx typing/predef.cmx parsing/pprintast.cmx \
+ driver/pparse.cmx typing/path.cmx parsing/parsetree.cmi parsing/parse.cmx \
+ typing/outcometree.cmi typing/oprint.cmx utils/misc.cmx \
+ middle_end/middle_end.cmx parsing/longident.cmx parsing/location.cmx \
+ parsing/lexer.cmx bytecomp/lambda.cmx typing/includemod.cmx \
+ asmcomp/import_approx.cmx typing/ident.cmx toplevel/genprintval.cmx \
+ typing/env.cmx utils/config.cmx driver/compmisc.cmx asmcomp/compilenv.cmx \
+ driver/compdynlink.cmi utils/clflags.cmx typing/btype.cmx \
+ middle_end/backend_intf.cmi parsing/asttypes.cmi parsing/ast_helper.cmx \
+ asmcomp/asmlink.cmx asmcomp/asmgen.cmx asmcomp/arch.cmx \
+ toplevel/opttoploop.cmi
toplevel/opttoploop.cmi : utils/warnings.cmi typing/types.cmi \
typing/path.cmi parsing/parsetree.cmi typing/outcometree.cmi \
parsing/longident.cmi parsing/location.cmi typing/env.cmi
toplevel/opttopmain.cmo : utils/warnings.cmi asmcomp/printmach.cmi \
toplevel/opttoploop.cmi toplevel/opttopdirs.cmi utils/misc.cmi \
driver/main_args.cmi parsing/location.cmi utils/config.cmi \
- driver/compplugin.cmi driver/compenv.cmi utils/clflags.cmi \
+ driver/compmisc.cmi driver/compenv.cmi utils/clflags.cmi \
toplevel/opttopmain.cmi
toplevel/opttopmain.cmx : utils/warnings.cmx asmcomp/printmach.cmx \
toplevel/opttoploop.cmx toplevel/opttopdirs.cmx utils/misc.cmx \
driver/main_args.cmx parsing/location.cmx utils/config.cmx \
- driver/compplugin.cmx driver/compenv.cmx utils/clflags.cmx \
+ driver/compmisc.cmx driver/compenv.cmx utils/clflags.cmx \
toplevel/opttopmain.cmi
toplevel/opttopmain.cmi :
toplevel/opttopstart.cmo : toplevel/opttopmain.cmi
parsing/parsetree.cmi typing/outcometree.cmi parsing/longident.cmi \
parsing/location.cmi typing/env.cmi
toplevel/topmain.cmo : utils/warnings.cmi toplevel/toploop.cmi \
- toplevel/topdirs.cmi utils/misc.cmi driver/main_args.cmi \
- parsing/location.cmi utils/config.cmi driver/compplugin.cmi \
- driver/compenv.cmi utils/clflags.cmi toplevel/topmain.cmi
+ toplevel/topdirs.cmi utils/profile.cmi utils/misc.cmi \
+ driver/main_args.cmi parsing/location.cmi utils/config.cmi \
+ driver/compmisc.cmi driver/compenv.cmi utils/clflags.cmi \
+ toplevel/topmain.cmi
toplevel/topmain.cmx : utils/warnings.cmx toplevel/toploop.cmx \
- toplevel/topdirs.cmx utils/misc.cmx driver/main_args.cmx \
- parsing/location.cmx utils/config.cmx driver/compplugin.cmx \
- driver/compenv.cmx utils/clflags.cmx toplevel/topmain.cmi
+ toplevel/topdirs.cmx utils/profile.cmx utils/misc.cmx \
+ driver/main_args.cmx parsing/location.cmx utils/config.cmx \
+ driver/compmisc.cmx driver/compenv.cmx utils/clflags.cmx \
+ toplevel/topmain.cmi
toplevel/topmain.cmi :
toplevel/topstart.cmo : toplevel/topmain.cmi
toplevel/topstart.cmx : toplevel/topmain.cmx
# Default behaviour, for if core.autocrlf isn't set
* text=auto
+# Don't believe there's a way to wrap lines in .gitattributes
+.gitattributes ocaml-typo=long-line
+
# Binary files
/boot/ocamlc binary
/boot/ocamllex binary
# 'union' merge driver just unions textual content in case of conflict
# http://krlmlr.github.io/using-gitattributes-to-avoid-merge-conflicts/
/.mailmap merge=union
-/Changes merge=union
+
+
+# We tried using 'union' for Changes and it did not work:
+# instead of creating Changes conflict it would silently duplicate
+# the lines involved in the conflict, which is arguably worse
+#/Changes merge=union
# No header for text files (would be too obtrusive).
*.md ocaml-typo=missing-header
/Changes ocaml-typo=non-ascii,missing-header
/INSTALL ocaml-typo=missing-header
/LICENSE ocaml-typo=long-line,very-long-line,missing-header
-/appveyor.yml ocaml-typo=long-line,very-long-line
+# appveyor_build.cmd only has missing-header because dra27 too lazy to update
+# check-typo to interpret Cmd-style comments!
+/appveyor_build.cmd ocaml-typo=long-line,very-long-line,missing-header text eol=crlf
+/appveyor_build.sh ocaml-typo=non-ascii
asmcomp/*/emit.mlp ocaml-typo=tab,long-line,unused-prop
-asmcomp/power/NOTES.md ocaml-typo=missing-header,long-line
+asmcomp/power/NOTES.md ocaml-typo=missing-header
asmrun/i386.S ocaml-typo=long-line
config/gnu ocaml-typo=prune
emacs/*.el ocaml-typo=long-line,unused-prop
+emacs/caml.el ocaml-typo=long-line,unused-prop,missing-header
emacs/COPYING ocaml-typo=tab,non-printing,missing-header
emacs/ocamltags.in ocaml-typo=non-printing
stdlib/hashbang ocaml-typo=white-at-eol,missing-lf
testsuite/tests/** ocaml-typo=missing-header
+testsuite/tests/lib-unix/win-stat/fakeclock.c ocaml-typo=
testsuite/tests/lib-bigarray-2/bigarrf.f ocaml-typo=missing-header,tab
testsuite/tests/misc-unsafe/almabench.ml ocaml-typo=missing-header,long-line
testsuite/typing ocaml-typo=missing-header
config/gnu/config.guess text eol=lf
config/gnu/config.sub text eol=lf
ocamldoc/remove_DEBUG text eol=lf
+ocamltest/getocamloptdefaultflags text eol=lf
stdlib/Compflags text eol=lf
stdlib/sharpbang text eol=lf
tools/check-typo text eol=lf
tools/ci-build text eol=lf
-tools/cleanup-header text eol=lf
tools/msvs-promote-path text eol=lf
tools/gdb-macros text eol=lf
tools/magic text eol=lf
manual/tools/htmlthread text eol=lf
manual/tools/texexpand text eol=lf
-# Checking out the parsetree test files with \r\n endings causes all the
-# locations to change, so use \n endings only, even on Windows
+# Tests which include references spanning multiple lines fail with \r\n
+# endings, so use \n endings only, even on Windows.
testsuite/tests/parsing/*.ml text eol=lf
-
-# Similarly, the docstring tests fail for the same reason on Windows
testsuite/tests/docstrings/empty.ml text eol=lf
-
-# And w04.ml
+testsuite/tests/functors/functors.ml text eol=lf
+testsuite/tests/translprim/module_coercion.ml text eol=lf
testsuite/tests/warnings/w04.ml text eol=lf
+testsuite/tests/warnings/w32.ml text eol=lf
# These are forced to \n to allow the Cygwin testsuite to pass on a
# Windows-checkout
testsuite/tests/formatting/margins.ml text eol=lf
+testsuite/tests/letrec-disallowed/disallowed.ml text eol=lf
+testsuite/tests/letrec-disallowed/extension_constructor.ml text eol=lf
+testsuite/tests/letrec-disallowed/float_block.ml text eol=lf
+testsuite/tests/letrec-disallowed/generic_arrays.ml text eol=lf
+testsuite/tests/letrec-disallowed/module_constraints.ml text eol=lf
+testsuite/tests/letrec-disallowed/pr7215.ml text eol=lf
+testsuite/tests/lexing/uchar_esc.ml text eol=lf
testsuite/tests/match-exception-warnings/exhaustiveness_warnings.ml text eol=lf
testsuite/tests/typing-extension-constructor/test.ml text eol=lf
testsuite/tests/typing-extensions/extensions.ml text eol=lf
testsuite/tests/typing-warnings/application.ml text eol=lf
testsuite/tests/typing-warnings/coercions.ml text eol=lf
testsuite/tests/typing-warnings/exhaustiveness.ml text eol=lf
+testsuite/tests/typing-warnings/pr6587.ml text eol=lf
testsuite/tests/typing-warnings/pr6872.ml text eol=lf
testsuite/tests/typing-warnings/pr7085.ml text eol=lf
testsuite/tests/typing-warnings/pr7115.ml text eol=lf
+testsuite/tests/typing-warnings/pr7261.ml text eol=lf
testsuite/tests/typing-warnings/pr7297.ml text eol=lf
+testsuite/tests/typing-warnings/pr7553.ml text eol=lf
testsuite/tests/typing-warnings/records.ml text eol=lf
testsuite/tests/typing-warnings/unused_types.ml text eol=lf
*.annot
*.exe
*.exe.manifest
-.depend
-.depend.nt
.DS_Store
*.out
*.out.dSYM
*.swp
+_ocamltest
# local to root directory
/asmrun/afl.c
/asmrun/array.c
/asmrun/backtrace.c
+/asmrun/bigarray.c
/asmrun/callback.c
/asmrun/compact.c
/asmrun/compare.c
/bytecomp/opcodes.ml
/byterun/caml/jumptbl.h
+/byterun/caml/m.h
+/byterun/caml/s.h
/byterun/primitives
/byterun/prims.c
/byterun/caml/opnames.h
/byterun/*.d.c
/byterun/*.pic.c
-/config/m.h
-/config/s.h
/config/Makefile
/config/auto-aux/hashbang4
/ocamldoc/test_latex
/ocamldoc/test
+/ocamltest/ocamltest
+/ocamltest/ocamltest.opt
+/ocamltest/ocamltest_config.ml
+/ocamltest/tsl_lexer.ml
+/ocamltest/tsl_parser.ml
+/ocamltest/tsl_parser.mli
+
/otherlibs/dynlink/extract_crc
-/otherlibs/systhreads/thread.ml
/otherlibs/threads/marshal.mli
/otherlibs/threads/pervasives.mli
/otherlibs/threads/unix.mli
/otherlibs/win32unix/chmod.c
/otherlibs/win32unix/cst2constr.c
/otherlibs/win32unix/cstringv.c
-/otherlibs/win32unix/envir.c
/otherlibs/win32unix/execv.c
/otherlibs/win32unix/execve.c
/otherlibs/win32unix/execvp.c
/otherlibs/win32unix/getproto.c
/otherlibs/win32unix/getserv.c
/otherlibs/win32unix/gmtime.c
+/otherlibs/win32unix/mmap_ba.c
/otherlibs/win32unix/putenv.c
/otherlibs/win32unix/rmdir.c
/otherlibs/win32unix/socketaddr.c
/testsuite/**/*.native
/testsuite/**/program
/testsuite/**/_log
+/testsuite/failure.stamp
/testsuite/_retries
/testsuite/tests/asmcomp/*.out.manifest
/testsuite/tests/basic/*.safe-string
-/testsuite/tests/basic/pr6322.ml
/testsuite/tests/embedded/caml
/testsuite/tests/lib-threads/*.byt
+/testsuite/tests/lib-unix/win-stat/*-file
+/testsuite/tests/lib-unix/win-symlink/link*
+/testsuite/tests/lib-unix/win-symlink/test.txt
+
+/testsuite/tests/lib-unix/win-symlink/link*
+/testsuite/tests/lib-unix/win-symlink/test.txt
+
/testsuite/tests/opaque/*/*.mli
+/testsuite/tests/output_obj/*.bc.c
+/testsuite/tests/output_obj/*_stub
+/testsuite/tests/output_obj/*_stub
+
/testsuite/tests/runtime-errors/*.bytecode
/testsuite/tests/self-contained-toplevel/cached_cmi.ml
/testsuite/tests/tool-lexyacc/grammar.mli
/testsuite/tests/tool-lexyacc/grammar.ml
+/testsuite/tests/typing-misc/false.flat-float
+/testsuite/tests/typing-misc/true.flat-float
+/testsuite/tests/typing-misc/pr6939.ml
+
/testsuite/tests/typing-multifile/a.ml
/testsuite/tests/typing-multifile/b.ml
/testsuite/tests/typing-multifile/c.ml
+/testsuite/tests/typing-multifile/d.mli
+/testsuite/tests/typing-multifile/e.ml
+/testsuite/tests/typing-multifile/f.ml
+/testsuite/tests/typing-multifile/g.ml
+/testsuite/tests/typing-multifile/test
+
+/testsuite/tests/typing-unboxed-types/false.flat-float
+/testsuite/tests/typing-unboxed-types/true.flat-float
+/testsuite/tests/typing-unboxed-types/test.ml.reference
+
+/testsuite/tests/translprim/false.flat-float
+/testsuite/tests/translprim/true.flat-float
+/testsuite/tests/translprim/array_spec.ml.reference
+/testsuite/tests/translprim/module_coercion.ml.reference
/testsuite/tests/unboxed-primitive-args/main.ml
/testsuite/tests/unboxed-primitive-args/stubs.c
/testsuite/tests/warnings/w55.opt.opt_result
/testsuite/tests/warnings/w58.opt.opt_result
+/testsuite/tests/win-unicode/symlink_tests.precheck
+
/testsuite/tools/expect_test
/tools/ocamldep
Alain Frisch <alain@frisch.fr> alainfrisch <alain@frisch.fr>
<damien.doligez@inria.fr> <damien.doligez-inria.fr>
<damien.doligez@inria.fr> <damien.doligez@gmail.com>
+Luc Maranget <luc.maranget@inria.fr>
<luc.maranget@inria.fr> <Luc.Maranget@inria.fr>
<luc.maranget@inria.fr> <maranget@pl-59086.rocq.inria.fr>
<pierre.chambart@ocamlpro.com> <chambart@users.noreply.github.com>
Damien Doligez <damien.doligez@inria.fr> doligez <damien.doligez@inria.fr>
Mohamed Iguernelala <mohamed.iguernelala@gmail.com>
Jérémie Dimino <jdimino@janestreet.com>
+Jeremy Yallop <yallop@gmail.com> yallop <yallop@gmail.com>
# The aliases below correspond to preference expressed by
# contributors on the name under which they credited, for example
Kenji Tokudome <pocarist>
Philippe Veber <pveber>
Valentin Gatien-Baron <sliquister>
+Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
Stephen Dolan <stedolan>
Junsong Li <lijunsong@mantis>
Junsong Li <ljs.darkfish@gmail.com>
Thomas Leonard <talex5@github>
Adrien Nader <adrien-n@github>
Sébastien Hinderer <shindere@github>
+Sébastien Hinderer <Sebastien.Hinderer@inria.fr>
Gabriel Scherer <gasche@github>
Immanuel Litzroth <sdev@mantis>
Jacques Le Normand <rathereasy@github>
+Konstantin Romanov <const-rs@github>
+Arseniy Alekseyev <aalekseyev@janestreet.com>
+Dwight Guth <dwight.guth@runtimeverification.com>
+Dwight Guth <dwightguth@github>
+Andreas Hauptmann <andreashauptmann@t-online.de> fdopen <andreashauptmann@t-online.de>
+Andreas Hauptmann <andreashauptmann@t-online.de> <fdopen@users.noreply.github.com>
+Hendrik Tews <hendrik@askra.de>
+Hugo Heuzard <hugo.heuzard@gmail.com>
+Miod Vallat <miod@mantis>
# These contributors prefer to be referred to pseudonymously
-<whitequark@mantis> <whitequark@mantis>
+whitequark <whitequark@whitequark.org>
<william@mantis> <william@mantis>
tkob <ether4@gmail.com> tkob <ether4@gmail.com>
ygrek <ygrek@autistici.org> ygrek <ygrek@autistici.org>
S ./utils
B ./utils
+
+S ./ocamltest
+B ./ocamltest
+#!/bin/bash
#**************************************************************************
#* *
#* OCaml *
PREFIX=~/local
+MAKE=make SHELL=dash
+
+# TRAVIS_COMMIT_RANGE has the form <commit1>...<commit2>
+# TRAVIS_CUR_HEAD is <commit1>
+# TRAVIS_PR_HEAD is <commit2>
+#
+# The following diagram illustrates the relationship between
+# the commits:
+#
+# (trunk) (pr branch)
+# TRAVIS_CUR_HEAD TRAVIS_PR_HEAD
+# | /
+# ... ...
+# | /
+# TRAVIS_MERGE_BASE
+#
+echo TRAVIS_COMMIT_RANGE=$TRAVIS_COMMIT_RANGE
+TRAVIS_CUR_HEAD=${TRAVIS_COMMIT_RANGE%%...*}
+TRAVIS_PR_HEAD=${TRAVIS_COMMIT_RANGE##*...}
+case $TRAVIS_EVENT_TYPE in
+ # If this is not a pull request then TRAVIS_COMMIT_RANGE may be empty.
+ pull_request)
+ TRAVIS_MERGE_BASE=$(git merge-base $TRAVIS_CUR_HEAD $TRAVIS_PR_HEAD);;
+esac
+
BuildAndTest () {
- case $XARCH in
- i386)
+ mkdir -p $PREFIX
cat<<EOF
------------------------------------------------------------------------
-This test builds the OCaml compiler distribution with your pull request,
-runs its testsuite, and then tries to install some important OCaml software
-(currently camlp4) on top of it.
+This test builds the OCaml compiler distribution with your pull request
+and runs its testsuite.
Failing to build the compiler distribution, or testsuite failures are
critical errors that must be understood and fixed before your pull
-request can be merged. The later installation attempts try to run
-bleeding-edge software, and failures can sometimes be out of your
-control.
+request can be merged.
------------------------------------------------------------------------
EOF
- mkdir -p $PREFIX
+ case $XARCH in
+ x64)
./configure --prefix $PREFIX -with-debug-runtime \
-with-instrumented-runtime $CONFIG_ARG
- export PATH=$PREFIX/bin:$PATH
- make world.opt
- make ocamlnat
- (cd testsuite && make all)
- (cd testsuite && make USE_RUNTIME="d" all)
- make install
- # check_all_arches checks tries to compile all backends in place,
- # we need to redo (small parts of) world.opt afterwards
- make check_all_arches
- make world.opt
- make manual-pregen
- mkdir external-packages
- cd external-packages
- git clone git://github.com/ocaml/ocamlbuild
- mkdir ocamlbuild-install
- (cd ocamlbuild &&
- make -f configure.make Makefile.config src/ocamlbuild_config.ml \
- OCAMLBUILD_PREFIX=$PREFIX \
- OCAMLBUILD_BINDIR=$PREFIX/bin \
- OCAMLBUILD_LIBDIR=$PREFIX/lib \
- OCAML_NATIVE=true \
- OCAML_NATIVE_TOOLS=true &&
- make all &&
- make install)
- git clone git://github.com/ocaml/camlp4 -b 4.05
- (cd camlp4 &&
- ./configure --bindir=$PREFIX/bin --libdir=$PREFIX/lib/ocaml \
- --pkgdir=$PREFIX/lib/ocaml && \
- make && make install)
- # git clone git://github.com/ocaml/opam
- # (cd opam && ./configure --prefix $PREFIX &&\
- # make lib-ext && make && make install)
- # git config --global user.email "some@name.com"
- # git config --global user.name "Some Name"
- # opam init -y -a git://github.com/ocaml/opam-repository
- # opam install -y oasis
- # opam pin add -y utop git://github.com/diml/utop
+ ;;
+ i386)
+ ./configure --prefix $PREFIX -with-debug-runtime \
+ -with-instrumented-runtime $CONFIG_ARG \
+ -host i686-pc-linux-gnu
;;
*)
echo unknown arch
exit 1
;;
esac
+
+ export PATH=$PREFIX/bin:$PATH
+ $MAKE world.opt
+ $MAKE ocamlnat
+ (cd testsuite && $MAKE all)
+ [ $XARCH = "i386" ] || (cd testsuite && $MAKE USE_RUNTIME="d" all)
+ $MAKE install
+ $MAKE manual-pregen
+ # check_all_arches checks tries to compile all backends in place,
+ # we would need to redo (small parts of) world.opt afterwards to
+ # use the compiler again
+ $MAKE check_all_arches
}
CheckChangesModified () {
------------------------------------------------------------------------
EOF
# check that Changes has been modified
- git diff $TRAVIS_COMMIT_RANGE --name-only --exit-code Changes > /dev/null \
- && CheckNoChangesMessage || echo pass
+ git diff $TRAVIS_MERGE_BASE..$TRAVIS_PR_HEAD --name-only --exit-code Changes \
+ > /dev/null && CheckNoChangesMessage || echo pass
}
CheckNoChangesMessage () {
- if test -n "$(git log --grep="[Nn]o [Cc]hange.* needed" --max-count=1 $TRAVIS_COMMIT_RANGE)"
+ API_URL=https://api.github.com/repos/$TRAVIS_REPO_SLUG/issues/$TRAVIS_PULL_REQUEST/labels
+ if test -n "$(git log --grep="[Nn]o [Cc]hange.* needed" --max-count=1 \
+ ${TRAVIS_MERGE_BASE}..${TRAVIS_PR_HEAD})"
then echo pass
- elif test -n "$(curl https://api.github.com/repos/$TRAVIS_REPO_SLUG/issues/$TRAVIS_PULL_REQUEST/labels \
- | grep 'no-change-entry-needed')"
+ elif test -n "$(curl $API_URL | grep 'no-change-entry-needed')"
then echo pass
else exit 1
fi
------------------------------------------------------------------------
EOF
# check that at least a file in testsuite/ has been modified
- git diff $TRAVIS_COMMIT_RANGE --name-only --exit-code testsuite > /dev/null \
- && exit 1 || echo pass
+ git diff $TRAVIS_MERGE_BASE..$TRAVIS_PR_HEAD --name-only --exit-code \
+ testsuite > /dev/null && exit 1 || echo pass
}
case $CI_KIND in
matrix:
include:
- env: CI_KIND=build XARCH=i386
- - env: CI_KIND=build XARCH=i386 CONFIG_ARG=-flambda OCAMLRUNPARAM=b,v=0
+ addons:
+ apt:
+ packages:
+ - gcc:i386
+ - cpp:i386
+ - binutils:i386
+ - binutils-dev:i386
+ - libx11-dev:i386
+ - libc6-dev:i386
+ - env: CI_KIND=build XARCH=x64
+ - env: CI_KIND=build XARCH=x64 CONFIG_ARG=-flambda OCAMLRUNPARAM=b,v=0
- env: CI_KIND=changes
- env: CI_KIND=tests
allow_failures:
- env: CI_KIND=tests
+addons:
+ apt:
+ packages:
+ - binutils-dev
+
+notifications:
+ email:
+ - ocaml-ci-notifications@inria.fr
improvement to documentation or implementation comments, which are
valuable changes on their own.)
+## Workflow
+
+All changes to the OCaml distribution need to be processed through the
+GitHub Pull Request (PR) system. In order to propose a change, a
+contributor thus needs to have a GitHub account, fork the ocaml/ocaml
+repository, create a branch for the proposal on their fork and submit
+it as a Pull Request on the upstream repository. (If you are not yet
+familiar with GitHub, don't worry, all these steps are actually quite
+easy!)
+
+The current rule is that a PR needs to get an explicit approval from
+one of the core maintainer in order to be merged. Reviews by
+external contributors are very much appreciated.
+
+Since core maintainers cannot push directly without going through an
+approved PR, they need to be able to apply small changes to the
+contributed branches themselves. Such changes include fixing
+conflicts, adjusting a Changelog entry, or applying some code changes
+required by the reviewers. Contributors are thus strongly advised to
+check the [**Allow edits from maintainer**](
+https://help.github.com/articles/allowing-changes-to-a-pull-request-branch-created-from-a-fork/
+) flag on their PRs in the GitHub interface. Failing to do so might
+significantly delay the inclusion of an otherwise perfectly ok
+contribution.
+
## Coding guidelines
from a commit message, but it should make sense to end-users
reading release notes)
-- crediting the people that worked on the feature
-
- The people that wrote the code should be credited of course,
- but also substantial code reviews or design advice, and the
- reporter of the bug (if applicable) or designer of the
- feature request (if novel).
+- crediting the people that worked on the feature. The people that
+ wrote the code should be credited of course, but also substantial
+ code reviews or design advice, and the reporter of the bug
+ (if applicable) or designer of the feature request (if novel).
- following the format
+OCaml 4.06.0 (3 Nov 2017):
+--------------------------
+
+(Changes that can break existing programs are marked with a "*")
+
+### Language features:
+
+- MPR#6271, MPR#7529, GPR#1249: Support "let open M in ..."
+ in class expressions and class type expressions.
+ (Alain Frisch, reviews by Thomas Refis and Jacques Garrigue)
+
+- GPR#792: fix limitations of destructive substitutions, by
+ allowing "S with type t := type-expr",
+ "S with type M.t := type-expr", "S with module M.N := path"
+ (Valentin Gatien-Baron, review by Jacques Garrigue and Leo White)
+
+* GPR#1064, GPR#1392: extended indexing operators, add a new class of
+ user-defined indexing operators, obtained by adding at least
+ one operator character after the dot symbol to the standard indexing
+ operators: e,g ".%()", ".?[]", ".@{}<-":
+ let ( .%() ) = List.nth in [0; 1; 2].%(1)
+ After this change, functions or methods with an explicit polymorphic type
+ annotation and of which the first argument is optional now requires a space
+ between the dot and the question mark,
+ e.g. "<f:'a.?opt:int->unit>" must now be written "<f:'a. ?opt:int->unit>".
+ (Florian Angeletti, review by Damien Doligez and Gabriel Radanne)
+
+- GPR#1118: Support inherited field in object type expression
+ type t = < m : int >
+ type u = < n : int; t; k : int >
+ (Runhang Li, reivew by Jeremy Yallop, Leo White, Jacques Garrigue,
+ and Florian Angeletti)
+
+* GPR#1232: Support Unicode character escape sequences in string
+ literals via the \u{X+} syntax. These escapes are substituted by the
+ UTF-8 encoding of the Unicode character.
+ (Daniel Bünzli, review by Damien Doligez, Alain Frisch, Xavier
+ Leroy and Leo White)
+
+- GPR#1247: M.(::) construction for expressions
+ and patterns (plus fix printing of (::) in the toplevel)
+ (Florian Angeletti, review by Alain Frisch, Gabriel Scherer)
+
+* GPR#1252: The default mode is now safe-string, can be overridden
+ at configure time or at compile time.
+ (See GPR#1386 below for the configure-time options)
+ This breaks the code that uses the 'string' type as mutable
+ strings (instead of Bytes.t, introduced by 4.02 in 2014).
+ (Damien Doligez)
+
+* GPR#1253: Private extensible variants
+ This change breaks code relying on the undocumented ability to export
+ extension constructors for abstract type in signature. Briefly,
+ module type S = sig
+ type t
+ type t += A
+ end
+ must now be written
+ module type S = sig
+ type t = private ..
+ type t += A
+ end
+ (Leo White, review by Alain Frisch)
+
+- GPR#1333: turn off warning 40 by default
+ (Constructor or label name used out of scope)
+ (Leo White)
+
+- GPR#1348: accept anonymous type parameters in `with` constraints:
+ S with type _ t = int
+ (Valentin Gatien-Baron, report by Jeremy Yallop)
+
+### Type system
+
+- MPR#248, GPR#1225: unique names for weak type variables
+ # ref [];;
+ - : '_weak1 list ref = {contents = []}
+ (Florian Angeletti, review by Frédéric Bour, Jacques Garrigue,
+ Gabriel Radanne and Gabriel Scherer)
+
+* MPR#6738, MPR#7215, MPR#7231, GPR#556: Add a new check that 'let rec'
+ bindings are well formed.
+ (Jeremy Yallop, reviews by Stephen Dolan, Gabriel Scherer, Leo
+ White, and Damien Doligez)
+
+- GPR#1142: Mark assertions nonexpansive, so that 'assert false'
+ can be used as a placeholder for a polymorphic function.
+ (Stephen Dolan)
+
+### Standard library:
+
+- MPR#1771, MPR#7309, GPR#1026: Add update to maps. Allows to update a
+ binding in a map or create a new binding if the key had no binding
+ val update: key -> ('a option -> 'a option) -> 'a t -> 'a t
+ (Sébastien Briais, review by Daniel Buenzli, Alain Frisch and
+ Gabriel Scherer)
+
+- MPR#7515, GPR#1147: Arg.align now optionally uses the tab character '\t' to
+ separate the "unaligned" and "aligned" parts of the documentation string. If
+ tab is not present, then space is used as a fallback. Allows to have spaces in
+ the unaligned part, which is useful for Tuple options.
+ (Nicolas Ojeda Bar, review by Alain Frisch and Gabriel Scherer)
+
+* GPR#615: Format, add symbolic formatters that output symbolic
+ pretty-printing items. New fields have been added to the
+ formatter_out_functions record, thus this change will break any code building
+ such record from scratch.
+ When building Format.formatter_out_functions values redefinining the out_spaces field,
+ "{ fmt_out_funs with out_spaces = f; }" should be replaced by
+ "{ fmt_out_funs with out_spaces = f; out_indent = f; }" to maintain the old behavior.
+ (Richard Bonichon and Pierre Weis, review by Alain Frisch, original request by
+ Spiros Eliopoulos in GPR#506)
+
+* GPR#943: Fixed the divergence of the Pervasives module between the stdlib
+ and threads implementations. In rare circumstances this can change the
+ behavior of existing applications: the implementation of Pervasives.close_out
+ used when compiling with thread support was inconsistent with the manual.
+ It will now not suppress exceptions escaping Pervasives.flush anymore.
+ Developers who want the old behavior should use Pervasives.close_out_noerr
+ instead. The stdlib implementation, used by applications not compiled
+ with thread support, will now only suppress Sys_error exceptions in
+ Pervasives.flush_all. This should allow exceedingly unlikely assertion
+ exceptions to escape, which could help reveal bugs in the standard library.
+ (Markus Mottl, review by Hezekiah M. Carty, Jeremie Dimino, Damien Doligez,
+ Alain Frisch, Xavier Leroy, Gabriel Scherer and Mark Shinwell)
+
+- GPR#1034: List.init : int -> (int -> 'a) -> 'a list
+ (Richard Degenne, review by David Allsopp, Thomas Braibant, Florian
+ Angeletti, Gabriel Scherer, Nathan Moreau, Alain Frisch)
+
+- GRP#1091 Add the Uchar.{bom,rep} constants.
+ (Daniel Bünzli, Alain Frisch)
+
+- GPR#1091: Add Buffer.add_utf_{8,16le,16be}_uchar to encode Uchar.t
+ values to the corresponding UTF-X transformation formats in Buffer.t
+ values.
+ (Daniel Bünzli, review by Damien Doligez, Max Mouratov)
+
+- GPR#1175: Bigarray, add a change_layout function to each Array[N]
+ submodules.
+ (Florian Angeletti)
+
+* GPR#1306: In the MSVC and Mingw ports, "Sys.rename src dst" no longer fails if
+ file "dst" exists, but replaces it with file "src", like in the other ports.
+ (Xavier Leroy)
+
+- GPR#1314: Format, use the optional width information
+ when formatting a boolean: "%8B", "%-8B" for example
+ (Xavier Clerc, review by Gabriel Scherer)
+
+- c9cc0f25138ce58e4f4e68c4219afe33e2a9d034: Resurrect tabulation boxes
+ in module Format. Rewrite/extend documentation of tabulation boxes.
+ (Pierre Weis)
+
+### Other libraries:
+
+- MPR#7564, GPR#1211: Allow forward slashes in the target of symbolic links
+ created by Unix.symlink under Windows.
+ (Nicolas Ojeda Bar, review by David Allsopp)
+
+* MPR#7640, GPR#1414: reimplementation of Unix.execvpe to fix issues
+ with the 4.05 implementation. The main issue is that the current
+ directory was always searched (last), even if the current directory
+ is not listed in the PATH.
+ (Xavier Leroy, report by Louis Gesbert and Arseniy Alekseyev,
+ review by Ivan Gotovchits)
+
+- GPR#997, GPR#1077: Deprecate Bigarray.*.map_file and add Unix.map_file as a
+ first step towards moving Bigarray to the stdlib
+ (Jérémie Dimino and Xavier Leroy)
+
+* GPR#1178: remove the Num library for arbitrary-precision arithmetic.
+ It now lives as a separate project https://github.com/ocaml/num
+ with an OPAM package called "num".
+ (Xavier Leroy)
+
+- GPR#1217: Restrict Unix.environment in privileged contexts; add
+ Unix.unsafe_environment.
+ (Jeremy Yallop, review by Mark Shinwell, Nicolas Ojeda Bar,
+ Damien Doligez and Hannes Mehnert)
+
+- GPR#1321: Reimplement Unix.isatty on Windows. It no longer returns true for
+ the null device.
+ (David Allsopp)
+
+### Compiler user-interface and warnings:
+
+- MPR#7361, GPR#1248: support "ocaml.warning" in all attribute contexts, and
+ arrange so that "ocaml.ppwarning" is correctly scoped by surrounding
+ "ocaml.warning" attributes
+ (Alain Frisch, review by Florian Angeletti and Thomas Refis)
+
+- MPR#7444, GPR#1138: trigger deprecation warning when a "deprecated"
+ attribute is hidden by signature coercion
+ (Alain Frisch, report by bmillwood, review by Leo White)
+
+- MPR#7472: ensure .cmi files are created atomically,
+ to avoid corruption of .cmi files produced simultaneously by a run
+ of ocamlc and a run of ocamlopt.
+ (Xavier Leroy, from a suggestion by Gerd Stolpmann)
+
+* MPR#7514, GPR#1152: add -dprofile option, similar to -dtimings but
+ also displays memory allocation and consumption.
+ The corresponding addition of a new compiler-internal
+ Profile module may affect some users of
+ compilers-libs/ocamlcommon (by creating module conflicts).
+ (Valentin Gatien-Baron, report by Gabriel Scherer)
+
+- MPR#7620, GPR#1317: Typecore.force_delayed_checks does not run with -i option
+ (Jacques Garrigue, report by Jun Furuse)
+
+- MPR#7624: handle warning attributes placed on let bindings
+ (Xavier Clerc, report by dinosaure, review by Alain Frisch)
+
+- GPR#896: "-compat-32" is now taken into account when building .cmo/.cma
+ (Hugo Heuzard)
+
+- GPR#948: the compiler now reports warnings-as-errors by prefixing
+ them with "Error (warning ..):", instead of "Warning ..:" and
+ a trailing "Error: Some fatal warnings were triggered" message.
+ (Valentin Gatien-Baron, review by Alain Frisch)
+
+- GPR#1032: display the output of -dtimings as a hierarchy
+ (Valentin Gatien-Baron, review by Gabriel Scherer)
+
+- GPR#1114, GPR#1393, GPR#1429: refine the (ocamlc -config) information
+ on C compilers: the variables `{bytecode,native}_c_compiler` are deprecated
+ (the distinction is now mostly meaningless) in favor of a single
+ `c_compiler` variable combined with `ocaml{c,opt}_cflags`
+ and `ocaml{c,opt}_cppflags`.
+ (Sébastien Hinderer, Jeremy Yallop, Gabriel Scherer, review by
+ Adrien Nader and David Allsopp)
+
+* GPR#1189: allow MSVC ports to use -l option in ocamlmklib
+ (David Allsopp)
+
+- GPR#1332: fix ocamlc handling of "-output-complete-obj"
+ (François Bobot)
+
+- GPR#1336: -thread and -vmthread option information is propagated to
+ PPX rewriters.
+ (Jun Furuse, review by Alain Frisch)
+
+### Code generation and optimizations:
+
+- MPR#5324, GPR#375: An alternative Linear Scan register allocator for
+ ocamlopt, activated with the -linscan command-line flag. This
+ allocator represents a trade-off between worse generated code
+ performance for higher compilation speed (especially interesting in
+ some cases graph coloring is necessarily quadratic).
+ (Marcell Fischbach and Benedikt Meurer, adapted by Nicolas Ojeda
+ Bar, review by Nicolas Ojeda Bar and Alain Frisch)
+
+- MPR#6927, GPR#988: On macOS, when compiling bytecode stubs, plugins,
+ and shared libraries through -output-obj, generate dylibs instead of
+ bundles.
+ (whitequark)
+
+- MPR#7447, GPR#995: incorrect code generation for nested recursive bindings
+ (Leo White and Jeremy Yallop, report by Stephen Dolan)
+
+- MPR#7501, GPR#1089: Consider arrays of length zero as constants
+ when using Flambda.
+ (Pierre Chambart, review by Mark Shinwell and Leo White)
+
+- MPR#7531, GPR#1162: Erroneous code transformation at partial applications
+ (Mark Shinwell)
+
+- MPR#7614, GPR#1313: Ensure that inlining does not depend on the order
+ of symbols (flambda)
+ (Leo White, Xavier Clerc, report by Alex, review by Gabriel Scherer
+ and Pierre Chambart)
+
+- MPR#7616, GPR#1339: don't warn on mutation of zero size blocks.
+ (Leo White)
+
+- MPR#7631, GPR#1355: "-linscan" option crashes ocamlopt
+ (Xavier Clerc, report by Paul Steckler)
+
+- MPR#7642, GPR#1411: ARM port: wrong register allocation for integer
+ multiply on ARMv4 and ARMv5; possible wrong register allocation for
+ floating-point multiply and add on VFP and for floating-point
+ negation and absolute value on soft FP emulation.
+ (Xavier Leroy, report by Stéphane Glondu and Ximin Luo,
+ review and additional sightings by Mark Shinwell)
+
+* GPR#659: Remove support for SPARC native code generation
+ (Mark Shinwell)
+
+- GPR#850: Optimize away some physical equality
+ (Pierre Chambart, review by Mark Shinwell and Leo White)
+
+- GPR#856: Register availability analysis
+ (Mark Shinwell, Thomas Refis, review by Pierre Chambart)
+
+- GPR#1143: tweaked several allocation functions in the runtime by
+ checking for likely conditions before unlikely ones and eliminating
+ some redundant checks.
+ (Markus Mottl, review by Alain Frisch, Xavier Leroy, Gabriel Scherer,
+ Mark Shinwell and Leo White)
+
+- GPR#1183: compile curried functors to multi-argument functions
+ earlier in the compiler pipeline; correctly propagate [@@inline]
+ attributes on such functors; mark functor coercion veneers as
+ stubs.
+ (Mark Shinwell, review by Pierre Chambart and Leo White)
+
+- GPR#1195: Merge functions based on partiality rather than
+ Parmatch.irrefutable.
+ (Leo White, review by Thomas Refis, Alain Frisch and Gabriel Scherer)
+
+- GPR#1215: Improve compilation of short-circuit operators
+ (Leo White, review by Frédéric Bour and Mark Shinwell)
+
+- GPR#1250: illegal ARM64 assembly code generated for large combined allocations
+ (report and initial fix by Steve Walk, review and final fix by Xavier Leroy)
+
+- GPR#1271: Don't generate Ialloc instructions for closures that exceed
+ Max_young_wosize; instead allocate them on the major heap. (Related
+ to GPR#1250.)
+ (Mark Shinwell)
+
+- GPR#1294: Add a configure-time option to remove the dynamic float array
+ optimization and add a floatarray type to let the user choose when to
+ flatten float arrays. Note that float-only records are unchanged: they
+ are still optimized by unboxing their fields.
+ (Damien Doligez, review by Alain Frisch and Mark Shinwell)
+
+- GPR#1304: Mark registers clobbered by PLT stubs as destroyed across
+ allocations.
+ (Mark Shinwell, Xavier Clerc, report and initial debugging by
+ Valentin Gatien-Baron)
+
+- GPR#1323: make sure that frame tables are generated in the data
+ section and not in the read-only data section, as was the case
+ before in the PPC and System-Z ports. This avoids relocations in
+ the text segment of shared libraries and position-independent
+ executables generated by ocamlopt.
+ (Xavier Leroy, review by Mark Shinwell)
+
+- GPR#1330: when generating dynamically-linkable code on AArch64, always
+ reference symbols (even locally-defined ones) through the GOT.
+ (Mark Shinwell, review by Xavier Leroy)
+
+### Tools:
+
+- MPR#1956, GPR#973: tools/check-symbol-names checks for globally
+ linked names not namespaced with caml_
+ (Stephen Dolan)
+
+- MPR#6928, GPR#1103: ocamldoc, do not introduce an empty <h1> in index.html
+ when no -title has been provided
+ (Pierre Boutillier)
+
+- MPR#7048: ocamldoc, in -latex mode, don't escape Latin-1 accented letters
+ (Xavier Leroy, report by Hugo Herbelin)
+
+* MPR#7351: ocamldoc, use semantic tags rather than <br> tags in the html
+ backend
+ (Florian Angeletti, request and review by Daniel Bünzli )
+
+* MPR#7352, MPR#7353: ocamldoc, better paragraphs in html output
+ (Florian Angeletti, request by Daniel Bünzli)
+
+* MPR#7363, GPR#830: ocamldoc, start heading levels at {1 not {2 or {6.
+ This change modifies the mapping between ocamldoc heading level and
+ html heading level, breaking custom css style for ocamldoc.
+ (Florian Angeletti, request and review by Daniel Bünzli)
+
+* MPR#7478, GPR#1037: ocamldoc, do not use as a module preamble documentation
+ comments that occur after the first module element. This change may break
+ existing documenation. In particular, module preambles must now come before
+ any `open` statement.
+ (Florian Angeletti, review by David Allsopp and report by Daniel Bünzli)
+
+- MPR#7521, GPR#1159: ocamldoc, end generated latex file with a new line
+ (Florian Angeletti)
+
+- MPR#7575, GPR#1219: Switch compilers from -no-keep-locs
+ to -keep-locs by default: produced .cmi files will contain locations.
+ This provides better error messages. Note that, as a consequence,
+ .cmi digests now depend on the file path as given to the compiler.
+ (Daniel Bünzli)
+
+- MPR#7610, GPR#1346: caml.el (the Emacs editing mode) was cleaned up
+ and made compatible with Emacs 25.
+ (Stefan Monnier, Christophe Troestler)
+
+- MPR#7635, GPR#1383: ocamldoc, add an identifier to module
+ and module type elements
+ (Florian Angeletti, review by Yawar Amin and Gabriel Scherer)
+
+- GPR#681, GPR#1426: Introduce ocamltest, a new test driver for the
+ OCaml compiler testsuite
+ (Sébastien Hinderer, review by Damien Doligez)
+
+- GPR#1012: ocamlyacc, fix parsing of raw strings and nested comments, as well
+ as the handling of ' characters in identifiers.
+ (Demi Obenour)
+
+- GPR#1045: ocamldep, add a "-shared" option to generate dependencies
+ for native plugin files (i.e. .cmxs files)
+ (Florian Angeletti, suggestion by Sébastien Hinderer)
+
+- GPR#1078: add a subcommand "-depend" to "ocamlc" and "ocamlopt",
+ to behave as ocamldep. Should be used mostly to replace "ocamldep" in the
+ "boot" directory to reduce its size in the future.
+ (Fabrice Le Fessant)
+
+- GPR#1036: ocamlcmt (tools/read_cmt) is installed, converts .cmt to .annot
+ (Fabrice Le Fessant)
+
+- GPR#1180: Add support for recording numbers of direct and indirect
+ calls over the lifetime of a program when using Spacetime profiling
+ (Mark Shinwell)
+
+- GPR#1457, ocamldoc: restore label for exception in the latex backend
+ (omitted since 4.04.0)
+ (Florian Angeletti, review by Gabriel Scherer)
+
+### Toplevel:
+
+- MPR#7570: remove unusable -plugin option from the toplevel
+ (Florian Angeletti)
+
+- GPR#1041: -nostdlib no longer ignored by toplevel.
+ (David Allsopp, review by Xavier Leroy)
+
+- GPR#1231: improved printing of unicode texts in the toplevel,
+ unless OCAMLTOP_UTF_8 is set to false.
+ (Florian Angeletti, review by Daniel Bünzli, Xavier Leroy and
+ Gabriel Scherer)
+
+### Runtime system:
+
+* MPR#3771, GPR#153, GPR#1200, GPR#1357, GPR#1362, GPR#1363, GPR#1369, GPR#1398,
+ GPR#1446, GPR#1448: Unicode support for the Windows runtime.
+ (ygrek, Nicolas Ojeda Bar, review by Alain Frisch, David Allsopp, Damien
+ Doligez)
+
+* MPR#7594, GPR#1274, GPR#1368: String_val now returns 'const char*', not
+ 'char*' when -safe-string is enabled at configure time. New macro Bytes_val
+ for accessing bytes values.
+ (Jeremy Yallop, reviews by Mark Shinwell and Xavier Leroy)
+
+- GPR#71: The runtime can now be shut down gracefully by means of the new
+ caml_shutdown and caml_startup_pooled functions. The new 'c' flag in
+ OCAMLRUNPARAM enables shutting the runtime properly on process exit.
+ (Max Mouratov, review and discussion by Damien Doligez, Gabriel Scherer,
+ Mark Shinwell, Thomas Braibant, Stephen Dolan, Pierre Chambart,
+ François Bobot, Jacques Garrigue, David Allsopp, and Alain Frisch)
+
+- GPR#938, GPR#1170, GPR#1289: Stack overflow detection on 64-bit Windows
+ (Olivier Andrieu, tweaked by David Allsopp)
+
+- GPR#1070, GPR#1295: enable gcc typechecking for caml_alloc_sprintf,
+ caml_gc_message. Make caml_gc_message a variadic function. Fix many
+ caml_gc_message format strings.
+ (Olivier Andrieu, review and 32bit fix by David Allsopp)
+
+- GPR#1073: Remove statically allocated compare stack.
+ (Stephen Dolan)
+
+- GPR#1086: in Sys.getcwd, just fail instead of calling getwd()
+ if HAS_GETCWD is not set.
+ (Report and first fix by Sebastian Markbåge, final fix by Xavier Leroy,
+ review by MarK Shinwell)
+
+- GPR#1269: Remove 50ms delay at exit for programs using threads
+ (Valentin Gatien-Baron, review by Stephen Dolan)
+
+* GPR#1309: open files with O_CLOEXEC (or equivalent) in caml_sys_open, thus
+ unifying the semantics between Unix and Windows and also eliminating race
+ condition on Unix.
+ (David Allsopp, report by Andreas Hauptmann)
+
+- GPR#1326: Enable use of CFI directives in AArch64 and ARM runtime
+ systems' assembly code (asmrun/arm64.S). Add CFI directives to enable
+ unwinding through [caml_c_call] and [caml_call_gc] with correct termination
+ of unwinding at [main].
+ (Mark Shinwell, review by Xavier Leroy and Gabriel Scherer, with thanks
+ to Daniel Bünzli and Fu Yong Quah for testing)
+
+- GPR#1338: Add "-g" for bytecode runtime system compilation
+ (Mark Shinwell)
+
+* GPR#1416, GPR#1444: switch the Windows 10 Console to UTF-8 encoding.
+ (David Allsopp, reviews by Nicolás Ojeda Bär and Xavier Leroy)
+
+### Manual and documentation:
+
+- MPR#6548: remove obsolete limitation in the description of private
+ type abbreviations
+ (Florian Angeletti, suggestion by Leo White)
+
+- MPR#6676, GPR#1110: move record notation to tutorial
+ (Florian Angeletti, review by Gabriel Scherer)
+
+- MPR#6676, GPR#1112: move local opens to tutorial
+ (Florian Angeletti)
+
+- MPR#6676, GPR#1153: move overriding class definitions to reference
+ manual and tutorial
+ (Florian Angeletti)
+
+- MPR#6709: document the associativity and precedence level of
+ pervasive operators
+ (Florian Angeletti, review by David Allsopp)
+
+- MPR#7254, GPR#1096: Rudimentary documentation of ocamlnat
+ (Mark Shinwell)
+
+- MPR#7281, GPR#1259: fix .TH macros in generated manpages
+ (Olaf Hering)
+
+- MPR#7507: Align the description of the printf conversion
+ specification "%g" with the ISO C90 description.
+ (Florian Angeletti, suggestion by Armaël Guéneau)
+
+- MPR#7551, GPR#1194 : make the final ";;" potentially optional in
+ caml_example
+ (Florian Angeletti, review and suggestion by Gabriel Scherer)
+
+- MPR#7588, GPR#1291: make format documentation predictable
+ (Florian Angeletti, review by Gabriel Radanne)
+
+- MPR#7604: Minor Ephemeron documentation fixes
+ (Miod Vallat, review by Florian Angeletti)
+
+- GPR#594: New chapter on polymorphism troubles:
+ weakly polymorphic types, polymorphic recursion,and higher-ranked
+ polymorphism.
+ (Florian Angeletti, review by Damien Doligez, Gabriel Scherer,
+ and Gerd Stolpmann)
+
+- GPR#1187: Minimal documentation for compiler plugins
+ (Florian Angeletti)
+
+- GPR#1202: Fix Typos in comments as well as basic grammar errors.
+ (JP Rodi, review and suggestions by David Allsopp, Max Mouratov,
+ Florian Angeletti, Xavier Leroy, Mark Shinwell and Damien Doligez)
+
+- GPR#1220: Fix "-keep-docs" option in ocamlopt manpage
+ (Etienne Millon)
+
+### Compiler distribution build system:
+
+- MPR#6373, GPR#1093: Suppress trigraph warnings from macOS assembler
+ (Mark Shinwell)
+
+- MPR#7639, GPR#1371: fix configure script for correct detection of
+ int64 alignment on Mac OS X 10.13 (High Sierra) and above; fix bug in
+ configure script relating to such detection.
+ (Mark Shinwell, report by John Whitington, review by Xavier Leroy)
+
+- GPR#558: enable shared library and natdynlink support on more Linux
+ platforms
+ (Felix Janda, Mark Shinwell)
+
+* GPR#1104: remove support for the NeXTStep platform
+ (Sébastien Hinderer)
+
+- GPR#1130: enable detection of IBM XL C compiler (one need to run configure
+ with "-cc <path to xlc compiler>"). Enable shared library support for
+ bytecode executables on AIX/xlc (tested on AIX 7.1, XL C 12).
+ To enable 64-bit, run both "configure" and "make world" with OBJECT_MODE=64.
+ (Konstantin Romanov, Enrique Naudon)
+
+- GPR#1203: speed up the manual build by using ocamldoc.opt
+ (Gabriel Scherer, review by Florian Angeletti)
+
+- GPR#1214: harden config/Makefile against '#' characters in PREFIX
+ (Gabriel Scherer, review by David Allsopp and Damien Doligez)
+
+- GPR#1216: move Compplugin and friends from BYTECOMP to COMP
+ (Leo White, review by Mark Shinwell)
+
+* GPR#1242: disable C plugins loading by default
+ (Alexey Egorov)
+
+- GPR#1275: correct configure test for Spacetime availability
+ (Mark Shinwell)
+
+- GPR#1278: discover presence of <sys/shm.h> during configure for afl runtime
+ (Hannes Mehnert)
+
+- GPR#1386: provide configure-time options to fine-tune the safe-string
+ options and default settings changed by GPR#1525.
+
+ The previous configure option -safe-string is now
+ renamed -force-safe-string.
+
+ At configure-time, -force-safe-string forces all module to use
+ immutable strings (this disables the per-file, compile-time
+ -unsafe-string option). The new default-(un)safe-string options
+ let you set the default choice for the per-file compile-time
+ option. (The new GPR#1252 behavior corresponds to having
+ -default-safe-string, while 4.05 and older had
+ -default-unsafe-string).
+
+ (Gabriel Scherer, review by Jacques-Pascal Deplaix and Damien Doligez)
+
+- GPR#1409: Fix to enable NetBSD/powerpc to work.
+ (Håvard Eidnes)
+
+### Internal/compiler-libs changes:
+
+- MPR#6826, GPR#828, GPR#834: improve compilation time for open
+ (Alain Frisch, review by Frédéric Bour and Jacques Garrigue)
+
+- MPR#7127, GPR#454, GPR#1058: in toplevel, print bytes and strip
+ strings longer than the size specified by the "print_length" directive
+ (Fabrice Le Fessant, initial PR by Junsong Li)
+
+- GPR#406: remove polymorphic comparison for Types.constructor_tag in compiler
+ (Dwight Guth, review by Gabriel Radanne, Damien Doligez, Gabriel Scherer,
+ Pierre Chambart, Mark Shinwell)
+
+- GRP#1119: Change Set (private) type to inline records.
+ (Albin Coquereau)
+
+* GPR#1127: move config/{m,s}.h to byterun/caml and install them.
+ User code should not have to include them directly since they are
+ included by other header files.
+ Previously {m,s}.h were not installed but they were substituted into
+ caml/config.h; they are now just #include-d by this file. This may
+ break some scripts relying on the (unspecified) presence of certain
+ #define in config.h instead of m.h and s.h -- they can be rewritten
+ to try to grep those files if they exist.
+ (Sébastien Hinderer)
+
+- GPR#1281: avoid formatter flushes inside exported printers in Location
+ (Florian Angeletti, review by Gabriel Scherer)
+
+### Bug fixes
+
+- MPR#5927: Type equality broken for conjunctive polymorphic variant tags
+ (Jacques Garrigue, report by Leo White)
+
+- MPR#6329, GPR#1437: Introduce padding word before "data_end" symbols
+ to ensure page table tests work correctly on an immediately preceding
+ block of zero size.
+ (Mark Shinwell, review by Xavier Leroy)
+
+- MPR#6587: only elide Pervasives from printed type paths in unambiguous context
+ (Florian Angeletti and Jacques Garrigue)
+
+- MPR#6934: nonrec misbehaves with GADTs
+ (Jacques Garrigue, report by Markus Mottl)
+
+- MPR#7070, GPR#1139: Unexported values can cause non-generalisable variables
+ error
+ (Leo White)
+
+- MPR#7261: Warn on type constraints in GADT declarations
+ (Jacques Garrigue, report by Fabrice Le Botlan)
+
+- MPR#7321: Private type in signature clashes with type definition via
+ functor instantiation
+ (Jacques Garrigue, report by Markus Mottl)
+
+- MPR#7372, GPR#834: fix type-checker bug with GADT and inline records
+ (Alain Frisch, review by Frédéric Bour and Jacques Garrigue)
+
+- MPR#7344: Inconsistent behavior with type annotations on let
+ (Jacques Garrigue, report by Leo White)
+
+- MPR#7468: possible GC problem in caml_alloc_sprintf
+ (Xavier Leroy, discovery by Olivier Andrieu)
+
+- MPR#7496: Fixed conjunctive polymorphic variant tags do not unify
+ with themselves
+ (Jacques Garrigue, report by Leo White)
+
+- MPR#7506: pprintast ignores attributes in tails of a list
+ (Alain Frisch, report by Kenichi Asai and Gabriel Scherer)
+
+- MPR#7513: List.compare_length_with mishandles negative numbers / overflow
+ (Fabrice Le Fessant, report by Jeremy Yallop)
+
+- MPR#7519: Incorrect rejection of program due to faux scope escape
+ (Jacques Garrigue, report by Markus Mottl)
+
+- MPR#7540, GPR#1179: Fixed setting of breakpoints within packed modules
+ for ocamldebug
+ (Hugo Herbelin, review by Gabriel Scherer, Damien Doligez)
+
+- MPR#7543: short-paths printtyp can fail on packed type error messages
+ (Florian Angeletti)
+
+- MPR#7553, GPR#1191: Prevent repeated warnings with recursive modules.
+ (Leo White, review by Josh Berdine and Alain Frisch)
+
+- MPR#7563, GPR#1210: code generation bug when a module alias and
+ an extension constructor have the same name in the same module
+ (Gabriel Scherer, report by Manuel Fähndrich,
+ review by Jacques Garrigue and Leo White)
+
+- MPR#7591, GPR#1257: on x86-64, frame table is not 8-aligned
+ (Xavier Leroy, report by Mantis user "voglerr", review by Gabriel Scherer)
+
+- MPR#7601, GPR#1320: It seems like a hidden non-generalized type variable
+ remains in some inferred signatures, which leads to strange errors
+ (Jacques Garrigue, report by Mandrikin)
+
+- MPR#7609: use-after-free memory corruption if a program debugged
+ under ocamldebug calls Pervasives.flush_all
+ (Xavier Leroy, report by Paul Steckler, review by Gabriel Scherer)
+
+- MPR#7612, GPR#1345: afl-instrumentation bugfix for classes.
+ (Stephen Dolan, review by Gabriel Scherer and David Allsopp)
+
+- MPR#7617, MPR#7618, GPR#1318: Ambiguous (mistakenly) type escaping the
+ scope of its equation
+ (Jacques Garrigue, report by Thomas Refis)
+
+- MPR#7619, GPR#1387: position of the optional last semi-column not included
+ in the position of the expression (same behavior as for lists)
+ (Christophe Raffalli, review by Gabriel Scherer)
+
+- MPR#7638: in the Windows Mingw64 port, multithreaded programs compiled
+ to bytecode could crash when raising an exception from C code.
+ This looks like a Mingw64 issue, which we work around with GCC builtins.
+ (Xavier Leroy)
+
+- MPR#7656, GPR#1423: false 'unused type/constructor/value' alarms
+ in the 4.06 development version
+ (Alain Frisch, review by Jacques Garrigue, report by Jacques-Pascal Deplaix)
+
+- MPR#7657, GPR#1424: ensures correct call-by-value semantics when
+ eta-expanding functions to eliminate optional arguments
+ (Alain Frisch, report by sliquister, review by Leo White and Jacques
+ Garrigue)
+
+- MPR#7658, GPR#1439: Fix Spacetime runtime system compilation with
+ -force-safe-string
+ (Mark Shinwell, report by Christoph Spiel, review by Gabriel Scherer)
+
+- GPR#1155: Fix a race condition with WAIT_NOHANG on Windows
+ (Jérémie Dimino and David Allsopp)
+
+- GPR#1199: Pretty-printing formatting cleanup in pprintast
+ (Ethan Aubin, suggestion by Gabriel Scherer, review by David Allsopp,
+ Florian Angeletti, and Gabriel Scherer)
+
+- GPR#1223: Fix corruption of the environment when using -short-paths
+ with the toplevel.
+ (Leo White, review by Alain Frisch)
+
+- GPR#1243: Fix pprintast for #... infix operators
+ (Alain Frisch, report by Omar Chebib)
+
+- GPR#1324: ensure that flambda warning are printed only once
+ (Xavier Clerc)
+
+- GPR#1329: Prevent recursive polymorphic variant names
+ (Jacques Garrigue, fix suggested by Leo White)
+
+- GPR#1308: Only treat pure patterns as inactive
+ (Leo White, review by Alain Frisch and Gabriel Scherer)
+
+- GPR#1390: fix the [@@unboxed] type check to accept parametrized types
+ (Leo White, review by Damien Doligez)
+
+- GPR#1407: Fix raw_spacetime_lib
+ (Leo White, review by Gabriel Scherer and Damien Doligez)
+
OCaml 4.05.0 (13 Jul 2017):
---------------------------
* MPR#7414, GPR#929: Soundness bug with non-generalized type variables and
functors.
+ (compatibility: some code using module-global mutable state will
+ fail at compile-time and is fixed by adding extra annotations;
+ see the Mantis and Github discussions.)
(Jacques Garrigue, report by Leo White)
### Compiler user-interface and warnings:
(Xavier Leroy)
- GPR#1015: add option "-plugin PLUGIN" to ocamldep too. Use compilerlibs
- to build ocamldep.
+ to build ocamldep. Add option "-depend" to ocamlc/ocamlopt to behave
+ as ocamldep. Remove any use of ocamldep to build the distribution.
(Fabrice Le Fessant)
- GPR#1027: various improvements to -dtimings, mostly including time
- GPR#996: correctly update caml_top_of_stack in systhreads
(Fabrice Le Fessant)
+- GPR#997, GPR#1077: Deprecate Bigarray.*.map_file and add Unix.map_file as a
+ first step towards moving Bigarray to the stdlib
+ (Jérémie Dimino and Xavier Leroy)
+
### Toplevel:
- MPR#7060, GPR#1035: Print exceptions in installed custom printers
- MPR#7443, GPR#990: spurious unused open warning with local open in patterns
(Florian Angeletti, report by Gabriel Scherer)
-- MPR#7504: fix warning 8 with unconstrained records
- (Florian Angeletti, report by John Whitington)
-
- MPR#7456, GPR#1092: fix slow compilation on source files containing a lot
of similar debugging information location entries
(Mark Shinwell)
-- GPR#795: remove 256-character limitation on Sys.executable_name
- (Xavier Leroy)
+- MPR#7504: fix warning 8 with unconstrained records
+ (Florian Angeletti, report by John Whitington)
+
+- MPR#7511, GPR#1133: Unboxed type with unboxed argument should not be accepted
+ (Damien Doligez, review by Jeremy Yallop and Leo White)
- GPR#805, GPR#815, GPR#833: check for integer overflow in String.concat
(Jeremy Yallop,
(Mark Shinwell, Leo White, review by Xavier Leroy)
* GPR#1088: Gc.minor_words now returns accurate numbers.
+ (compatibility: the .mli declaration of `Gc.minor_words`
+ and `Gc.get_minor_free` changed, which may break libraries
+ re-exporting these values.)
(Stephen Dolan, review by Pierre Chambart and Xavier Leroy)
OCaml 4.04.2 (23 Jun 2017):
OCaml 4.04.1 (14 Apr 2017):
---------------------------
-- PR#7501, GPR#1089: Consider arrays of length zero as constants
- when using Flambda.
- (Pierre Chambart, review by Mark Shinwell and Leo White)
-
### Standard library:
- PR#7403, GPR#894: fix a bug in Set.map as introduced in 4.04.0
Bigarray.Genarray.change_layout.
(Damien Doligez and Xavier Leroy, report by Liang Wang)
-- PR#7511, GPR#1133: Unboxed type with unboxed argument should not be accepted
- (Damien Doligez, review by Jeremy Yallop and Leo White)
-
- GPR#912: Fix segfault in Unix.create_process on Windows caused by wrong header
configuration.
(David Allsopp)
it now calls (nano)sleep for 0 seconds as in (< 4.03) versions.
(Hannes Mehnert, review by Damien Doligez)
+- PR#7259 and GPR#603: flambda does not collapse pattern matching
+ in some cases
+ (Pierre Chambart, report by Reed Wilson, review by Mark Shinwell)
+
- PR#7260: GADT + subtyping compile time crash
(Jacques Garrigue, report by Nicolas Ojeda Bar)
- GPR#880: Fix [@@inline] with default parameters in flambda (Leo White)
+* GPR#1353: add labels to BytesLabels.sub_string (Jacques Garrigue)
+
### Internal/compiler-libs changes:
- PR#7200, GPR#539: Improve, fix, and add test for parsing/pprintast.ml
-= Hacking the compiler 🐫
+= Hacking the compiler :camel:
This document is a work-in-progress attempt to provide useful
information for people willing to inspect or modify the compiler
* http://caml.inria.fr/mantis/view_all_bug_page.php[The OCaml
bugtracker] contains reported bugs and feature requests. Some
changes that should be accessible to newcomers are marked with the
- tag
- http://caml.inria.fr/mantis/search.php?project_id=1&sticky_issues=1&sortby=last_updated&dir=DESC&highlight_changed=24&hide_status_id=90&tag_string=junior_job[junior_job].
+ tag link:++http://caml.inria.fr/mantis/search.php?
+project_id=1&sticky_issues=1&sortby=last_updated&dir=DESC&highlight_changed=24&hide_status_id=90&tag_string=junior_job++[
+ junior_job].
* The
https://github.com/ocamllabs/compiler-hacking/wiki/Things-to-work-on[OCaml
link:parsing/HACKING.adoc[].
The logic for Camlp4 and Ppx preprocessing is not in link:parsing/[],
-but in link:driver/[], see link:driver/pparse.mli[],
-link:driver/pparse.mli[].
+but in link:driver/[], see link:driver/pparse.mli[] and
+link:driver/pparse.ml[].
==== Typing -- link:typing/[]
link:otherlibs/[]:: External libraries such as `unix`, `threads`,
`dynlink`, `str` and `bigarray`.
+Instructions for building the full reference manual are provided in
+link:manual/README.md[]. However, if you only modify the documentation
+comments in `.mli` files in the compiler codebase, you can observe the
+result by running
+
+----
+make html_doc
+----
+
+and then opening link:./ocamldoc/stdlib_html/index.html[] in a web browser.
+
=== Tools
link:lex/[]:: The `ocamllex` lexer generator.
LICENSE:: license and copyright notice
Makefile:: main Makefile
Makefile.nt:: Windows Makefile (deprecated)
- Makefile.shared:: common Makefile
Makefile.tools:: used by manual/ and testsuite/ Makefiles
README.adoc:: general information on the compiler distribution
README.win32.adoc:: general information on the Windows ports of OCaml
==== Github's CI: Travis and AppVeyor
+The script that is run on Travis continuous integration servers is
+link:.travis-ci.sh[]; its configuration can be found as
+a Travis configuration file in link:.travis.yml[].
+
+For example, if you want to reproduce the default build on your
+machine, you can use the configuration values and run command taken from
+link:.travis.yml[]:
+
+----
+CI_KIND=build XARCH=x64 bash -ex .travis-ci.sh
+----
+
+The scripts support two other kinds of tests (values of the
+`CI_KIND` variable) which both inspect the patch submitted as part of
+a pull request. `tests` checks that the testsuite has been modified
+(hopefully, improved) by the patch, and `changes` checks that the
+link:Changes[] file has been modified (hopefully to add a new entry).
+
+These tests rely on the `$TRAVIS_COMMIT_RANGE` variable which you can
+set explicitly to reproduce them locally.
+
+The `changes` check can be disabled by including "(no change
+entry needed)" in one of your commit messages -- but in general all
+patches submitted should come with a Changes entry; see the guidelines
+in link:CONTRIBUTING.md[].
+
==== INRIA's Continuous Integration (CI)
INRIA provides a Jenkins continuous integration service that OCaml
You do not need to be an INRIA employee to open an account on this
jenkins service; anyone can create an account there to access build
-logs, enable email notifications, and manually restart builds. If you
-would like to do this but have trouble doing it, please contact Damien
-Doligez or Gabriel Scherer.
+logs and manually restart builds. If you
+would like to do this but have trouble doing it, please email
+ocaml-ci-admin@inria.fr
+
+To be notified by email of build failures, you can subscribe to the
+ocaml-ci-notifications@inria.fr mailing list by visiting
+https://sympa.inria.fr/sympa/info/ocaml-ci-notifications[its web page]
-==== Running INRIA's CI on a github Pull Request (PR)
+==== Running INRIA's CI on a publicly available git branch
-If you have suspicions that a PR may fail on exotic architectures
-(it touches the build system or the backend code generator,
+If you have suspicions that your changes may fail on exotic architectures
+(they touch the build system or the backend code generator,
for example) and would like to get wider testing than github's CI
provides, it is possible to manually start INRIA's CI on arbitrary git
-branches by pushing to a `precheck` branch of the main repository.
+branches even before opening a pull request as follows:
+
+1. Make sure you have an account on Inria's CI as described before.
+
+2. Make sure you have been added to the ocaml project.
+
+3. Prepare a branch with the code you'd like to test, say "mybranch". It
+is probably a good idea to make sure your branch is based on the latest
+trunk.
+
+4. Make your branch publicly available. For instance, you can fork
+OCaml's GitHub repository and then push "mybranch" to your fork.
-This is done by pushing to a specific github repository that the CI
-watches, namely
-link:https://github.com/ocaml/precheck[ocaml/precheck]. You thus need
-to have write/push/commit access to this repository to perform this operation.
+5. Visit https://ci.inria.fr/ocaml/job/precheck and log in. Click on
+"Build with parameters".
-Just checkout the commit/branch you want to test, then run
+6. Fill in the REPO_URL and BRANCH fields as appropriate and run the build.
- git push --force git@github.com:ocaml/precheck.git HEAD:trunk
+7. You should receive a bunch of e-mails with the build logs for each
+slave and each tested configuration (with and without flambda) attached.
-(This is the syntax to push the current `HEAD` state into the `trunk`
-reference on the specified remote.)
\ No newline at end of file
+Happy Hacking!
./configure
+
-This generates the three configuration files `Makefile`, `m.h` and `s.h`
-in the `config/` subdirectory.
+This generates the three configuration files `config/Makefile`,
+`byterun/caml/m.h` and `byterun/caml/s.h`.
+
The `configure` script accepts the following options:
+
./configure -cc "acc -fast" -libs "-lucb"
-* For Sun Solaris on Sparc 64bit, to compile natively (32bit only)
-
- ./configure -cc "gcc -m32" -as "as -32" -aspp "gcc -m32 -c"
-
* For AIX 4.3 with the IBM compiler `xlc`:
./configure -cc "xlc_r -D_AIX43 -Wl,-bexpall,-brtl -qmaxmem=8192"
Read the "common problems" and "machine-specific hints" section at the end of
this file.
-Check the files `m.h` and `s.h` in `config/`. Wrong endian-ness or alignment
-constraints in `m.h` will immediately crash the bytecode interpreter.
+Check the files `m.h` and `s.h` in `byterun/caml/`.
+Wrong endianness or alignment constraints in `machine.h` will
+immediately crash the bytecode interpreter.
If you get a "segmentation violation" signal, check the limits on the stack size
and data segment size (type `limit` under csh or `ulimit -a` under bash). Make
CAMLC=$(CAMLRUN) boot/ocamlc -g -nostdlib -I boot -use-prims byterun/primitives
CAMLOPT=$(CAMLRUN) ./ocamlopt -g -nostdlib -I stdlib -I otherlibs/dynlink
-ARCHES=amd64 i386 arm arm64 power sparc s390x
+ARCHES=amd64 i386 arm arm64 power s390x
INCLUDES=-I utils -I parsing -I typing -I bytecomp -I middle_end \
- -I middle_end/base_types -I asmcomp -I driver -I toplevel
+ -I middle_end/base_types -I asmcomp -I asmcomp/debug \
+ -I driver -I toplevel
COMPFLAGS=-strict-sequence -principal -absname -w +a-4-9-41-42-44-45-48 \
-warn-error A \
OCAML_NATDYNLINKOPTS = -ccopt "$(NATDYNLINKOPTS)"
endif
-ifeq "$(strip $(BYTECCLINKOPTS))" ""
-OCAML_BYTECCLINKOPTS=
-else
-OCAML_BYTECCLINKOPTS = -ccopt "$(BYTECCLINKOPTS)"
-endif
-
YACCFLAGS=-v --strict
CAMLLEX=$(CAMLRUN) boot/ocamllex
CAMLDEP=$(CAMLRUN) tools/ocamldep
UTILS=utils/config.cmo utils/misc.cmo \
utils/identifiable.cmo utils/numbers.cmo utils/arg_helper.cmo \
- utils/clflags.cmo utils/tbl.cmo utils/timings.cmo \
+ utils/clflags.cmo utils/tbl.cmo utils/profile.cmo \
utils/terminfo.cmo utils/ccomp.cmo utils/warnings.cmo \
utils/consistbl.cmo \
utils/strongly_connected_components.cmo \
typing/tast_mapper.cmo \
typing/cmt_format.cmo typing/untypeast.cmo \
typing/includemod.cmo typing/typetexp.cmo typing/parmatch.cmo \
- typing/stypes.cmo typing/typedecl.cmo typing/typecore.cmo \
+ typing/stypes.cmo typing/typedecl.cmo typing/typeopt.cmo typing/typecore.cmo \
typing/typeclass.cmo \
typing/typemod.cmo
COMP=bytecomp/lambda.cmo bytecomp/printlambda.cmo \
bytecomp/semantics_of_primitives.cmo \
- bytecomp/typeopt.cmo bytecomp/switch.cmo bytecomp/matching.cmo \
+ bytecomp/switch.cmo bytecomp/matching.cmo \
bytecomp/translobj.cmo bytecomp/translattribute.cmo \
bytecomp/translcore.cmo \
bytecomp/translclass.cmo bytecomp/translmod.cmo \
bytecomp/simplif.cmo bytecomp/runtimedef.cmo \
+ bytecomp/meta.cmo bytecomp/opcodes.cmo \
+ bytecomp/bytesections.cmo bytecomp/dll.cmo \
+ bytecomp/symtable.cmo \
driver/pparse.cmo driver/main_args.cmo \
- driver/compenv.cmo driver/compmisc.cmo
+ driver/compenv.cmo driver/compmisc.cmo \
+ driver/compdynlink.cmo driver/compplugin.cmo driver/makedepend.cmo
+
COMMON=$(UTILS) $(PARSING) $(TYPING) $(COMP)
-BYTECOMP=bytecomp/meta.cmo bytecomp/instruct.cmo bytecomp/bytegen.cmo \
- bytecomp/printinstr.cmo bytecomp/opcodes.cmo bytecomp/emitcode.cmo \
- bytecomp/bytesections.cmo bytecomp/dll.cmo bytecomp/symtable.cmo \
+BYTECOMP=bytecomp/instruct.cmo bytecomp/bytegen.cmo \
+ bytecomp/printinstr.cmo bytecomp/emitcode.cmo \
bytecomp/bytelink.cmo bytecomp/bytelibrarian.cmo bytecomp/bytepackager.cmo \
- driver/compdynlink.cmo driver/compplugin.cmo \
driver/errors.cmo driver/compile.cmo
ARCH_SPECIFIC =\
$(ARCH_SPECIFIC_ASMCOMP) \
asmcomp/arch.cmo \
asmcomp/cmm.cmo asmcomp/printcmm.cmo \
- asmcomp/reg.cmo asmcomp/mach.cmo asmcomp/proc.cmo \
+ asmcomp/reg.cmo asmcomp/debug/reg_with_debug_info.cmo \
+ asmcomp/debug/reg_availability_set.cmo \
+ asmcomp/mach.cmo asmcomp/proc.cmo \
asmcomp/clambda.cmo asmcomp/printclambda.cmo \
asmcomp/export_info.cmo \
asmcomp/export_info_for_pack.cmo \
asmcomp/un_anf.cmo \
asmcomp/afl_instrument.cmo \
asmcomp/strmatch.cmo asmcomp/cmmgen.cmo \
+ asmcomp/interval.cmo \
asmcomp/printmach.cmo asmcomp/selectgen.cmo \
asmcomp/spacetime_profiling.cmo asmcomp/selection.cmo \
asmcomp/comballoc.cmo \
asmcomp/liveness.cmo \
asmcomp/spill.cmo asmcomp/split.cmo \
asmcomp/interf.cmo asmcomp/coloring.cmo \
+ asmcomp/linscan.cmo \
asmcomp/reloadgen.cmo asmcomp/reload.cmo \
asmcomp/deadcode.cmo \
asmcomp/printlinear.cmo asmcomp/linearize.cmo \
+ asmcomp/debug/available_regs.cmo \
asmcomp/schedgen.cmo asmcomp/scheduling.cmo \
asmcomp/branch_relaxation_intf.cmo \
asmcomp/branch_relaxation.cmo \
middle_end/base_types/symbol.cmo \
middle_end/pass_wrapper.cmo \
middle_end/allocated_const.cmo \
+ middle_end/parameter.cmo \
middle_end/projection.cmo \
middle_end/flambda.cmo \
middle_end/flambda_iterators.cmo \
else
BOOT_FLEXLINK_CMD = FLEXLINK_CMD="../boot/ocamlrun ../flexdll/flexlink.exe"
CAMLOPT := OCAML_FLEXLINK="boot/ocamlrun flexdll/flexlink.exe" $(CAMLOPT)
- FLEXDLL_DIR=$(if $(wildcard flexdll/flexdll_*.$(O)),"+flexdll")
+ FLEXDLL_DIR=$(if $(wildcard flexdll/flexdll_*.$(O)),+flexdll)
endif
else
FLEXDLL_DIR=
# The configuration file
-utils/config.ml: utils/config.mlp config/Makefile
- sed -e 's|%%AFL_INSTRUMENT%%|$(AFL_INSTRUMENT)|' \
- -e 's|%%ARCH%%|$(ARCH)|' \
- -e 's|%%ARCMD%%|$(ARCMD)|' \
- -e 's|%%ASM%%|$(ASM)|' \
- -e 's|%%ASM_CFI_SUPPORTED%%|$(ASM_CFI_SUPPORTED)|' \
- -e 's|%%BYTECCLIBS%%|$(BYTECCLIBS)|' \
- -e 's|%%BYTECODE_C_COMPILER%%|$(BYTECODE_C_COMPILER)|' \
- -e 's|%%BYTERUN%%|$(BYTERUN)|' \
- -e 's|%%CCOMPTYPE%%|$(CCOMPTYPE)|' \
- -e 's|%%CC_PROFILE%%|$(CC_PROFILE)|' \
- -e 's|%%EXT_ASM%%|$(EXT_ASM)|' \
- -e 's|%%EXT_DLL%%|$(EXT_DLL)|' \
- -e 's|%%EXT_EXE%%|$(EXE)|' \
- -e 's|%%EXT_LIB%%|$(EXT_LIB)|' \
- -e 's|%%EXT_OBJ%%|$(EXT_OBJ)|' \
- -e 's|%%FLAMBDA%%|$(FLAMBDA)|' \
- -e 's|%%FLEXLINK_FLAGS%%|$(subst \,\\,$(FLEXLINK_FLAGS))|' \
- -e 's|%%FLEXDLL_DIR%%|$(FLEXDLL_DIR)|' \
- -e 's|%%HOST%%|$(HOST)|' \
- -e 's|%%LIBDIR%%|$(LIBDIR)|' \
- -e 's|%%LIBUNWIND_AVAILABLE%%|$(LIBUNWIND_AVAILABLE)|' \
- -e 's|%%LIBUNWIND_LINK_FLAGS%%|$(LIBUNWIND_LINK_FLAGS)|' \
- -e 's|%%MKDLL%%|$(subst \,\\,$(MKDLL))|' \
- -e 's|%%MKEXE%%|$(subst \,\\,$(MKEXE))|' \
- -e 's|%%MKMAINDLL%%|$(subst \,\\,$(MKMAINDLL))|' \
- -e 's|%%MODEL%%|$(MODEL)|' \
- -e 's|%%NATIVECCLIBS%%|$(NATIVECCLIBS)|' \
- -e 's|%%NATIVE_C_COMPILER%%|$(NATIVE_C_COMPILER)|' \
- -e 's|%%PACKLD%%|$(PACKLD)|' \
- -e 's|%%PROFILING%%|$(PROFILING)|' \
- -e 's|%%PROFINFO_WIDTH%%|$(PROFINFO_WIDTH)|' \
- -e 's|%%RANLIBCMD%%|$(RANLIBCMD)|' \
- -e 's|%%SAFE_STRING%%|$(SAFE_STRING)|' \
- -e 's|%%SYSTEM%%|$(SYSTEM)|' \
- -e 's|%%SYSTHREAD_SUPPORT%%|$(SYSTHREAD_SUPPORT)|' \
- -e 's|%%TARGET%%|$(TARGET)|' \
- -e 's|%%WITH_FRAME_POINTERS%%|$(WITH_FRAME_POINTERS)|' \
- -e 's|%%WITH_PROFINFO%%|$(WITH_PROFINFO)|' \
- -e 's|%%WITH_SPACETIME%%|$(WITH_SPACETIME)|' \
+# SUBST generates the sed substitution for the variable *named* in $1
+# SUBST_QUOTE does the same, adding double-quotes around non-empty strings
+# (see FLEXDLL_DIR which must empty if FLEXDLL_DIR is empty but an OCaml
+# string otherwise)
+SUBST_ESCAPE=$(subst ",\\",$(subst \,\\,$(if $2,$2,$($1))))
+SUBST=-e 's|%%$1%%|$(call SUBST_ESCAPE,$1,$2)|'
+SUBST_QUOTE2=-e 's|%%$1%%|$(if $2,"$2")|'
+SUBST_QUOTE=$(call SUBST_QUOTE2,$1,$(call SUBST_ESCAPE,$1,$2))
+FLEXLINK_LDFLAGS=$(if $(LDFLAGS), -link "$(LDFLAGS)")
+utils/config.ml: utils/config.mlp config/Makefile Makefile
+ sed $(call SUBST,AFL_INSTRUMENT) \
+ $(call SUBST,ARCH) \
+ $(call SUBST,ARCMD) \
+ $(call SUBST,ASM) \
+ $(call SUBST,ASM_CFI_SUPPORTED) \
+ $(call SUBST,BYTECCLIBS) \
+ $(call SUBST,BYTERUN) \
+ $(call SUBST,CC) \
+ $(call SUBST,CCOMPTYPE) \
+ $(call SUBST,CC_PROFILE) \
+ $(call SUBST,OUTPUTOBJ) \
+ $(call SUBST,EXT_ASM) \
+ $(call SUBST,EXT_DLL) \
+ $(call SUBST,EXE) \
+ $(call SUBST,EXT_LIB) \
+ $(call SUBST,EXT_OBJ) \
+ $(call SUBST,FLAMBDA) \
+ $(call SUBST,FLEXLINK_FLAGS) \
+ $(call SUBST_QUOTE,FLEXDLL_DIR) \
+ $(call SUBST,HOST) \
+ $(call SUBST,LIBDIR) \
+ $(call SUBST,LIBUNWIND_AVAILABLE) \
+ $(call SUBST,LIBUNWIND_LINK_FLAGS) \
+ $(call SUBST,MKDLL) \
+ $(call SUBST,MKEXE) \
+ $(call SUBST,FLEXLINK_LDFLAGS) \
+ $(call SUBST,MKMAINDLL) \
+ $(call SUBST,MODEL) \
+ $(call SUBST,NATIVECCLIBS) \
+ $(call SUBST,OCAMLC_CFLAGS) \
+ $(call SUBST,OCAMLC_CPPFLAGS) \
+ $(call SUBST,OCAMLOPT_CFLAGS) \
+ $(call SUBST,OCAMLOPT_CPPFLAGS) \
+ $(call SUBST,PACKLD) \
+ $(call SUBST,PROFILING) \
+ $(call SUBST,PROFINFO_WIDTH) \
+ $(call SUBST,RANLIBCMD) \
+ $(call SUBST,FORCE_SAFE_STRING) \
+ $(call SUBST,DEFAULT_SAFE_STRING) \
+ $(call SUBST,WINDOWS_UNICODE) \
+ $(call SUBST,SYSTEM) \
+ $(call SUBST,SYSTHREAD_SUPPORT) \
+ $(call SUBST,TARGET) \
+ $(call SUBST,WITH_FRAME_POINTERS) \
+ $(call SUBST,WITH_PROFINFO) \
+ $(call SUBST,WITH_SPACETIME) \
+ $(call SUBST,ENABLE_CALL_COUNTS) \
+ $(call SUBST,FLAT_FLOAT_ARRAY) \
$< > $@
ifeq "$(UNIX_OR_WIN32)" "unix"
$(MAKE) ocaml
$(MAKE) opt-core
$(MAKE) ocamlc.opt
- $(MAKE) otherlibraries $(WITH_DEBUGGER) $(WITH_OCAMLDOC)
+ $(MAKE) otherlibraries $(WITH_DEBUGGER) $(WITH_OCAMLDOC) ocamltest
$(MAKE) ocamlopt.opt
$(MAKE) otherlibrariesopt
- $(MAKE) ocamllex.opt ocamltoolsopt ocamltoolsopt.opt $(OCAMLDOC_OPT)
+ $(MAKE) ocamllex.opt ocamltoolsopt ocamltoolsopt.opt $(OCAMLDOC_OPT) \
+ ocamltest.opt
else
opt.opt: core opt-core ocamlc.opt all ocamlopt.opt ocamllex.opt \
- ocamltoolsopt ocamltoolsopt.opt otherlibrariesopt $(OCAMLDOC_OPT)
+ ocamltoolsopt ocamltoolsopt.opt otherlibrariesopt $(OCAMLDOC_OPT) \
+ ocamltest.opt
endif
.PHONY: base.opt
$(MAKE) ocaml
$(MAKE) opt-core
$(MAKE) ocamlc.opt
- $(MAKE) otherlibraries $(WITH_DEBUGGER) $(WITH_OCAMLDOC)
+ $(MAKE) otherlibraries $(WITH_DEBUGGER) $(WITH_OCAMLDOC) ocamltest
$(MAKE) ocamlopt.opt
$(MAKE) otherlibrariesopt
all: runtime
$(MAKE) coreall
$(MAKE) ocaml
- $(MAKE) otherlibraries $(WITH_DEBUGGER) $(WITH_OCAMLDOC)
+ $(MAKE) otherlibraries $(WITH_DEBUGGER) $(WITH_OCAMLDOC) ocamltest
# Bootstrap and rebuild the whole system.
# The compilation of ocaml will fail if the runtime has changed.
.PHONY: flexdll
flexdll: flexdll/Makefile flexlink
$(MAKE) -C flexdll \
+ OCAML_CONFIG_FILE=../config/Makefile \
MSVC_DETECT=0 CHAINS=$(FLEXDLL_CHAIN) NATDYNLINK=false support
# Bootstrapping flexlink - leaves a bytecode image of flexlink.exe in flexdll/
cp byterun/ocamlrun$(EXE) boot/ocamlrun$(EXE)
$(MAKE) -C stdlib COMPILER=../boot/ocamlc stdlib.cma std_exit.cmo
cd stdlib && cp stdlib.cma std_exit.cmo *.cmi ../boot
- $(MAKE) -C flexdll MSVC_DETECT=0 TOOLCHAIN=$(TOOLCHAIN) \
- TOOLPREF=$(TOOLPREF) CHAINS=$(FLEXDLL_CHAIN) NATDYNLINK=false \
+ $(MAKE) -C flexdll MSVC_DETECT=0 OCAML_CONFIG_FILE=../config/Makefile \
+ CHAINS=$(FLEXDLL_CHAIN) NATDYNLINK=false \
OCAMLOPT="../boot/ocamlrun ../boot/ocamlc -I ../boot" \
flexlink.exe
$(MAKE) -C byterun clean
cd flexdll && \
mv flexlink.exe flexlink && \
$(MAKE) OCAML_FLEXLINK="../boot/ocamlrun ./flexlink" MSVC_DETECT=0 \
- TOOLCHAIN=$(TOOLCHAIN) TOOLPREF=$(TOOLPREF) \
+ OCAML_CONFIG_FILE=../config/Makefile \
OCAMLOPT="../ocamlopt.opt -I ../stdlib" flexlink.exe && \
mv flexlink.exe flexlink.opt && \
mv flexlink flexlink.exe
toplevel/topdirs.mli "$(INSTALL_LIBDIR)"
$(MAKE) -C tools install
ifeq "$(UNIX_OR_WIN32)" "unix" # Install manual pages only on Unix
- $(MKDIR) "$(INSTALL_MANDIR)/man$(MANEXT)"
+ $(MKDIR) "$(INSTALL_MANDIR)/man$(PROGRAMS_MAN_SECTION)"
-$(MAKE) -C man install
endif
for i in $(OTHERLIBRARIES); do \
$(MAKE) -C otherlibs/$$i install || exit $$?; \
done
+# Transitional: findlib 1.7.3 is confused if leftover num.cm? files remain
+# from an previous installation of OCaml before otherlibs/num was removed.
+ rm -f "$(INSTALL_LIBDIR)"/num.cm?
+# End transitional
if test -n "$(WITH_OCAMLDOC)"; then \
$(MAKE) -C ocamldoc install; \
fi
cp -f flexdll/flexlink.opt "$(INSTALL_BINDIR)/flexlink$(EXE)" ; \
fi
-
-
.PHONY: installoptopt
installoptopt:
cp ocamlc.opt "$(INSTALL_BINDIR)/ocamlc.opt$(EXE)"
# Run all tests
.PHONY: tests
-tests: opt.opt
+tests: opt.opt ocamltest
cd testsuite; $(MAKE) clean && $(MAKE) all
# Make clean in the test suite
rm -f compilerlibs/ocamloptcomp.cma
ocamlopt: compilerlibs/ocamlcommon.cma compilerlibs/ocamloptcomp.cma \
- compilerlibs/ocamlbytecomp.cma $(OPTSTART)
+ $(OPTSTART)
$(CAMLC) $(LINKFLAGS) -o $@ $^
partialclean::
ocamlc.opt: compilerlibs/ocamlcommon.cmxa compilerlibs/ocamlbytecomp.cmxa \
$(BYTESTART:.cmo=.cmx)
- $(CAMLOPT) $(LINKFLAGS) $(OCAML_BYTECCLINKOPTS) -o $@ \
- $^ -cclib "$(BYTECCLIBS)"
+ $(CAMLOPT) $(LINKFLAGS) -o $@ $^ -cclib "$(BYTECCLIBS)"
partialclean::
rm -f ocamlc.opt
rm -f compilerlibs/ocamloptcomp.cmxa compilerlibs/ocamloptcomp.$(A)
ocamlopt.opt: compilerlibs/ocamlcommon.cmxa compilerlibs/ocamloptcomp.cmxa \
- compilerlibs/ocamlbytecomp.cmxa \
$(OPTSTART:.cmo=.cmx)
$(CAMLOPT) $(LINKFLAGS) -o $@ $^
$(MAKE) -C byterun clean
rm -f stdlib/libcamlrun.$(A)
+otherlibs_all := bigarray dynlink graph raw_spacetime_lib \
+ str systhreads threads unix win32graph win32unix
+subdirs := asmrun byterun debugger lex ocamldoc ocamltest stdlib tools \
+ $(addprefix otherlibs/, $(otherlibs_all))
+
.PHONY: alldepend
-alldepend::
- $(MAKE) -C byterun depend
+ifeq "$(TOOLCHAIN)" "msvc"
+alldepend:
+ $(error Dependencies cannot be regenerated using the MSVC ports)
+else
+alldepend: depend
+ for dir in $(subdirs); do \
+ $(MAKE) -C $$dir depend || exit; \
+ done
+endif
# The runtime system for the native-code compiler
clean::
$(MAKE) -C asmrun clean
rm -f stdlib/libasmrun.$(A)
-alldepend::
- $(MAKE) -C asmrun depend
# The standard library
partialclean::
$(MAKE) -C stdlib clean
-alldepend::
- $(MAKE) -C stdlib depend
-
# The lexer and parser generators
.PHONY: ocamllex
partialclean::
$(MAKE) -C lex clean
-alldepend::
- $(MAKE) -C lex depend
-
.PHONY: ocamlyacc
ocamlyacc:
$(MAKE) -C yacc $(BOOT_FLEXLINK_CMD) all
ocamldoc.opt: ocamlc.opt ocamlyacc ocamllex
$(MAKE) -C ocamldoc opt.opt
+# OCamltest
+ocamltest: ocamlc ocamlyacc ocamllex
+ $(MAKE) -C ocamltest
+
+ocamltest.opt: ocamlc.opt ocamlyacc ocamllex
+ $(MAKE) -C ocamltest ocamltest.opt$(EXE)
+
+partialclean::
+ $(MAKE) -C ocamltest clean
+
# Documentation
.PHONY: html_doc
partialclean::
$(MAKE) -C ocamldoc clean
-alldepend::
- $(MAKE) -C ocamldoc depend
-
# The extra libraries
.PHONY: otherlibraries
($(MAKE) -C otherlibs/$$i clean); \
done
-alldepend::
- for i in $(OTHERLIBRARIES); do \
- ($(MAKE) -C otherlibs/$$i depend); \
- done
-
# The replay debugger
.PHONY: ocamldebugger
partialclean::
$(MAKE) -C debugger clean
-alldepend::
- $(MAKE) -C debugger depend
-
# Check that the stack limit is reasonable.
ifeq "$(UNIX_OR_WIN32)" "unix"
.PHONY: checkstack
checkstack:
- if $(MKEXE) -o tools/checkstack$(EXE) tools/checkstack.c; \
+ if $(MKEXE) $(OUTPUTEXE)tools/checkstack$(EXE) tools/checkstack.c; \
then tools/checkstack$(EXE); \
else :; \
fi
# Lint @since and @deprecated annotations
+VERSIONS=$(shell git tag|grep '^[0-9]*.[0-9]*.[0-9]*$$'|grep -v '^[12].')
.PHONY: lintapidiff
lintapidiff:
$(MAKE) -C tools lintapidiff.opt
git ls-files -- 'otherlibs/*/*.mli' 'stdlib/*.mli' |\
grep -Ev internal\|obj\|spacetime\|stdLabels\|moreLabels |\
- tools/lintapidiff.opt $(shell git tag|grep '^[0-9]*.[0-9]*.[0-9]*$$'|grep -v '^[12].')
+ tools/lintapidiff.opt $(VERSIONS)
# Make clean in the test suite
partialclean::
$(MAKE) -C tools clean
-alldepend::
- $(MAKE) -C tools depend
-
## Test compilation of backend-specific parts
partialclean::
partialclean::
for d in utils parsing typing bytecomp asmcomp middle_end \
- middle_end/base_types driver toplevel tools; do \
+ middle_end/base_types asmcomp/debug driver toplevel tools; do \
rm -f $$d/*.cm[ioxt] $$d/*.cmti $$d/*.annot $$d/*.$(S) \
$$d/*.$(O) $$d/*.$(SO) $d/*~; \
done
.PHONY: depend
depend: beforedepend
(for d in utils parsing typing bytecomp asmcomp middle_end \
- middle_end/base_types driver toplevel; \
- do $(CAMLDEP) -slash $(DEPFLAGS) $$d/*.mli $$d/*.ml; \
+ middle_end/base_types asmcomp/debug driver toplevel; \
+ do $(CAMLDEP) -slash $(DEPFLAGS) $$d/*.mli $$d/*.ml || exit; \
done) > .depend
$(CAMLDEP) -slash $(DEPFLAGS) -native \
-impl driver/compdynlink.mlopt >> .depend
$(CAMLDEP) -slash $(DEPFLAGS) -bytecode \
-impl driver/compdynlink.mlbyte >> .depend
-alldepend:: depend
-
.PHONY: distclean
distclean: clean
- rm -f asmrun/.depend.nt byterun/.depend.nt \
- otherlibs/bigarray/.depend.nt \
- otherlibs/str/.depend.nt
rm -f boot/ocamlrun boot/ocamlrun$(EXE) boot/camlheader \
boot/ocamlyacc boot/*.cm* boot/libcamlrun.$(A)
- rm -f config/Makefile config/m.h config/s.h
+ rm -f config/Makefile byterun/caml/m.h byterun/caml/s.h
rm -f tools/*.bak
rm -f ocaml ocamlc
rm -f testsuite/_log
+|=====
+| Branch `trunk` | Branch `4.05` | Branch `4.04`
+
+| image:https://travis-ci.org/ocaml/ocaml.svg?branch=trunk["TravisCI Build Status (trunk branch)",link="https://travis-ci.org/ocaml/ocaml"]
+ image:https://ci.appveyor.com/api/projects/status/github/ocaml/ocaml?branch=trunk&svg=true["AppVeyor Build Status (trunk branch)",link="https://ci.appveyor.com/project/avsm/ocaml"]
+| image:https://travis-ci.org/ocaml/ocaml.svg?branch=4.05["TravisCI Build Status (4.05 branch)",link="https://travis-ci.org/ocaml/ocaml"]
+ image:https://ci.appveyor.com/api/projects/status/github/ocaml/ocaml?branch=4.05&svg=true["AppVeyor Build Status (4.05 branch)",link="https://ci.appveyor.com/project/avsm/ocaml"]
+| image:https://travis-ci.org/ocaml/ocaml.svg?branch=4.04["TravisCI Build Status (4.04 branch)",link="https://travis-ci.org/ocaml/ocaml"]
+ image:https://ci.appveyor.com/api/projects/status/github/ocaml/ocaml?branch=4.04&svg=true["AppVeyor Build Status (4.04 branch)",link="https://ci.appveyor.com/project/avsm/ocaml"]
+
+|=====
+
= README =
== Overview
IA32 (Pentium):: NetBSD, OpenBSD, Solaris 9
PowerPC:: NetBSD
ARM:: NetBSD
-SPARC:: Solaris, Linux, NetBSD
Other operating systems for the processors above have not been tested, but
the compiler may work under other operating systems with little work.
instructions on how to build FlexDLL from sources, including how to bootstrap
FlexDLL and OCaml are given <<seflexdll,later in this document>>. Unless you
bootstrap FlexDLL, you will need to ensure that the directory to which you
-install FlexDLL is included in your `PATH` environment variable. Note: if you
-use Visual Studio 2015 or Visual Studio 2017, the binary distribution of
-FlexDLL will not work and you must build it from sources.
+install FlexDLL is included in your `PATH` environment variable. Note: binary
+distributions of FlexDLL are compatible only with Visual Studio 2013 and
+earlier; for Visual Studio 2015 and later, you will need to compile the C
+objects from source, or build ocaml using the flexdll target.
The base bytecode system (ocamlc, ocaml, ocamllex, ocamlyacc, ...) of all three
ports runs without any additional tools.
Now run:
- cp config/m-nt.h config/m.h
- cp config/s-nt.h config/s.h
+ cp config/m-nt.h byterun/caml/m.h
+ cp config/s-nt.h byterun/caml/s.h
followed by:
Now run:
- cp config/m-nt.h config/m.h
- cp config/s-nt.h config/s.h
+ cp config/m-nt.h byterun/caml/m.h
+ cp config/s-nt.h byterun/caml/s.h
followed by:
OCaml is then compiled as normal for the port you require, except that before
compiling `world`, you must compile `flexdll`, i.e.:
- make flexdll world [bootstrap] opt opt.opt install
+ make flexdll world [bootstrap] opt opt.opt flexlink.opt install
+ * You should ignore the error messages that say ocamlopt was not found.
* `make install` will install FlexDLL by placing `flexlink.exe`
(and the default manifest file for the Microsoft port) in `bin/` and the
FlexDLL object files in `lib/`.
- * If you don't include `make opt.opt`, `flexlink.exe` will be a
+ * If you don't include `make flexlink.opt`, `flexlink.exe` will be a
bytecode program. `make install` always installs the "best"
`flexlink.exe` (i.e. there is never a `flexlink.opt.exe` installed).
* If you have populated `flexdll/`, you *must* run
installed FlexDLL, you must erase the contents of `flexdll/` before
compiling.
+== Unicode support
+
+Prior to version 4.06, all filenames on the OCaml side were assumed
+to be encoded using the current 8-bit code page of the system. Some
+Unicode filenames could thus not be represented. Since version 4.06,
+OCaml adds to this legacy mode a new "Unicode" mode, where filenames
+are UTF-8 encoded strings. In addition to filenames,
+this applies to environment variables and command-line arguments.
+
+The mode must be decided before building the system, by tweaking
+the `WINDOWS_UNICODE` variable in `config/Makefile`. A value of 1
+enables the the new "Unicode" mode, while a value of 0 maintains
+the legacy mode.
+
+Technically, both modes use the Windows "wide" API, where filenames
+and other strings are made of 16-bit entities, usually interpreted as
+UTF-16 encoded strings.
+
+Some more details about the two modes:
+
+ * Unicode mode: OCaml strings are interpreted as being UTF-8 encoded
+ and translated to UTF-16 when calling Windows; strings returned by
+ Windows are interpreted as UTF-16 and translated to UTF-8 on their
+ way back to OCaml. Additionally, an OCaml string which is not
+ valid UTF-8 will be interpreted as being in the current 8-bit code
+ page. This fallback works well in practice, since the chances of
+ non-ASCII string encoded in the a 8-bit code page to be a valid
+ UTF-8 string are tiny. This means that filenames
+ obtained from e.g. a 8-bit UI or database layer would continue to
+ work fine. Application written for the legacy mode or older
+ versions of OCaml might still break if strings returned by
+ Windows (e.g. for `Sys.readdir`) are sent to components expecting
+ strings encoded in the current code page.
+
+ * Legacy mode: this mode emulates closely the behavior of OCaml <
+ 4.06 and is thus the safest choice in terms of backward
+ compatibility. In this mode, OCaml programs can only work with
+ filenames that can be encoded in the current code page, and the
+ same applies to ocaml tools themselves (ocamlc, ocamlopt, etc).
+
+The legacy mode will be deprecated and then removed in future versions
+of OCaml. Users are thus strongly encouraged to use the Unicode mode
+and adapt their existing code bases accordingly.
+
+Note: in order for ocaml tools to support Unicode pathnames, it is
+necessary to use a version of FlexDLL which has itself been compiled
+with OCaml >= 4.06 in Unicode mode. This is the case for binary distributions
+of FlexDLL starting from version 0.37 and above.
+
== Trademarks
Microsoft, Visual C++, Visual Studio and Windows are registered trademarks of
-4.05.0
+4.06.0
# The version string is the first line of this file.
# It must be in the format described in stdlib/sys.mli
image: Visual Studio 2015
-branches:
- only:
- - trunk
- - 4.05
-
# Do a shallow clone of the repo to speed up the build
clone_depth: 1
CYG_ROOT: C:/cygwin64
CYG_MIRROR: http://mirrors.kernel.org/sourceware/cygwin/
CYG_CACHE: C:/cygwin64/var/cache/setup
+ FLEXDLL_VERSION: 0.37
OCAMLRUNPARAM: v=0,b
- OCAMLROOT: "%PROGRAMFILES%/OCaml"
- OCAMLROOT2: "%PROGRAMFILES%/OCaml-mingw32"
cache:
- C:\cygwin64\var\cache\setup
install:
- - mkdir "%OCAMLROOT%/bin/flexdll"
- - appveyor DownloadFile "http://alain.frisch.fr/flexdll/flexdll-bin-0.35.zip" -FileName "flexdll.zip"
- - appveyor DownloadFile "http://alain.frisch.fr/flexdll/flexdll-0.35.tar.gz" -FileName "flexdll.tar.gz"
- - cinst 7zip.commandline
- - mkdir flexdll-tmp
- - cd flexdll-tmp
- - 7za x -y ..\flexdll.zip
- - for %%F in (flexdll.h flexlink.exe default_amd64.manifest) do copy %%F "%OCAMLROOT%\bin\flexdll"
- - cd ..
- # Make sure the Cygwin path comes before the Git one (otherwise
- # cygpath behaves crazily), but after the MSVC one.
- - set Path=C:\cygwin64\bin;%OCAMLROOT%\bin\flexdll;%Path%
- - '%CYG_ROOT%\bin\bash -lc "cygcheck -dc cygwin"'
- - '"%CYG_ROOT%\setup-x86_64.exe" -qgnNdO -R "%CYG_ROOT%" -s "%CYG_MIRROR%" -l "%CYG_CACHE%" -P diffutils -P make -P mingw64-i686-gcc-core >NUL'
- - '%CYG_ROOT%\bin\bash -lc "cygcheck -dc cygwin"'
- - set OCAML_PREV_PATH=%PATH%
- - set OCAML_PREV_LIB=%LIB%
- - set OCAML_PREV_INCLUDE=%INCLUDE%
- - call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64.bat"
+# This is a hangover from monitoring effects of MPR#7452
+ - wmic cpu get name
+ - call "%APPVEYOR_BUILD_FOLDER%\appveyor_build.cmd" install
build_script:
- - "%CYG_ROOT%/bin/bash -lc \"echo 'eval $($APPVEYOR_BUILD_FOLDER/tools/msvs-promote-path)' >> ~/.bash_profile\""
- - '%CYG_ROOT%/bin/bash -lc "$APPVEYOR_BUILD_FOLDER/appveyor_build.sh"'
- - set PATH=%OCAML_PREV_PATH%
- - set LIB=%OCAML_PREV_LIB%
- - set INCLUDE=%OCAML_PREV_INCLUDE%
- - call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x86
- - '%CYG_ROOT%/bin/bash -lc "$APPVEYOR_BUILD_FOLDER/appveyor_build.sh msvc32-only"'
+ - call "%APPVEYOR_BUILD_FOLDER%\appveyor_build.cmd" build
test_script:
- - set PATH=%OCAML_PREV_PATH%
- - set LIB=%OCAML_PREV_LIB%
- - set INCLUDE=%OCAML_PREV_INCLUDE%
- - call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64.bat"
- - '%APPVEYOR_BUILD_FOLDER%\ocamlc.opt -version'
- - set CAML_LD_LIBRARY_PATH=%OCAMLROOT%/lib/stublibs
- - '%CYG_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER && make tests"'
- - '%CYG_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER/../build-mingw32 && make tests"'
- - '%CYG_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER && make install"'
- - '%CYG_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER/../build-mingw32 && make install"'
+ - call "%APPVEYOR_BUILD_FOLDER%\appveyor_build.cmd" test
--- /dev/null
+@rem ***********************************************************************
+@rem * *
+@rem * OCaml *
+@rem * *
+@rem * David Allsopp, OCaml Labs, Cambridge. *
+@rem * *
+@rem * Copyright 2017 MetaStack Solutions Ltd. *
+@rem * *
+@rem * All rights reserved. This file is distributed under the terms of *
+@rem * the GNU Lesser General Public License version 2.1, with the *
+@rem * special exception on linking described in the file LICENSE. *
+@rem * *
+@rem ***********************************************************************
+
+@rem BE CAREFUL ALTERING THIS FILE TO ENSURE THAT ERRORS PROPAGATE
+@rem IF A COMMAND SHOULD FAIL IT PROBABLY NEEDS TO END WITH
+@rem || exit /b 1
+@rem BASICALLY, DO THE TESTING IN BASH...
+
+@rem Do not call setlocal!
+@echo off
+
+goto %1
+
+goto :EOF
+
+:SaveVars
+set OCAML_PREV_PATH=%PATH%
+set OCAML_PREV_LIB=%LIB%
+set OCAML_PREV_INCLUDE=%INCLUDE%
+goto :EOF
+
+:RestoreVars
+set PATH=%OCAML_PREV_PATH%
+set LIB=%OCAML_PREV_LIB%
+set INCLUDE=%OCAML_PREV_INCLUDE%
+goto :EOF
+
+:CheckPackage
+"%CYG_ROOT%\bin\bash.exe" -lc "cygcheck -dc %1" | findstr %1 > nul
+if %ERRORLEVEL% equ 1 (
+ echo Cygwin package %1 will be installed
+ set CYGWIN_INSTALL_PACKAGES=%CYGWIN_INSTALL_PACKAGES%,%1
+)
+goto :EOF
+
+:UpgradeCygwin
+if "%CYGWIN_INSTALL_PACKAGES%" neq "" "%CYG_ROOT%\setup-x86_64.exe" --quiet-mode --no-shortcuts --no-startmenu --no-desktop --only-site --root "%CYG_ROOT%" --site "%CYG_MIRROR%" --local-package-dir "%CYG_CACHE%" --packages %CYGWIN_INSTALL_PACKAGES:~1% > nul
+for %%P in (%CYGWIN_COMMANDS%) do "%CYG_ROOT%\bin\%%P.exe" --version > nul || set CYGWIN_UPGRADE_REQUIRED=1
+"%CYG_ROOT%\bin\bash.exe" -lc "cygcheck -dc %CYGWIN_PACKAGES%"
+if %CYGWIN_UPGRADE_REQUIRED% equ 1 (
+ echo Cygwin package upgrade required - please go and drink coffee
+ "%CYG_ROOT%\setup-x86_64.exe" --quiet-mode --no-shortcuts --no-startmenu --no-desktop --only-site --root "%CYG_ROOT%" --site "%CYG_MIRROR%" --local-package-dir "%CYG_CACHE%" --upgrade-also > nul
+ "%CYG_ROOT%\bin\bash.exe" -lc "cygcheck -dc %CYGWIN_PACKAGES%"
+)
+goto :EOF
+
+:install
+chcp 65001 > nul
+rem This must be kept in sync with appveyor_build.sh
+set BUILD_PREFIX=🐫реализация
+git worktree add "..\%BUILD_PREFIX%-msvc64" -b appveyor-build-msvc64
+git worktree add "..\%BUILD_PREFIX%-mingw32" -b appveyor-build-mingw32
+git worktree add "..\%BUILD_PREFIX%-msvc32" -b appveyor-build-msvc32
+cd "..\%BUILD_PREFIX%-mingw32"
+git submodule update --init flexdll
+
+cd "%APPVEYOR_BUILD_FOLDER%"
+appveyor DownloadFile "https://github.com/alainfrisch/flexdll/archive/0.37.tar.gz" -FileName "flexdll.tar.gz" || exit /b 1
+appveyor DownloadFile "https://github.com/alainfrisch/flexdll/releases/download/0.37/flexdll-bin-0.37.zip" -FileName "flexdll.zip" || exit /b 1
+rem flexdll.zip is processed here, rather than in appveyor_build.sh because the
+rem unzip command comes from MSYS2 (via Git for Windows) and it has to be
+rem invoked via cmd /c in a bash script which is weird(er).
+mkdir "%APPVEYOR_BUILD_FOLDER%\..\flexdll"
+move flexdll.zip "%APPVEYOR_BUILD_FOLDER%\..\flexdll"
+cd "%APPVEYOR_BUILD_FOLDER%\..\flexdll" && unzip -q flexdll.zip
+
+rem CYGWIN_PACKAGES is the list of required Cygwin packages (cygwin is included
+rem in the list just so that the Cygwin version is always displayed on the log).
+rem CYGWIN_COMMANDS is a corresponding command to run with --version to test
+rem whether the package works. This is used to verify whether the installation
+rem needs upgrading.
+set CYGWIN_PACKAGES=cygwin make diffutils mingw64-i686-gcc-core
+set CYGWIN_COMMANDS=cygcheck make diff i686-w64-mingw32-gcc
+
+set CYGWIN_INSTALL_PACKAGES=
+set CYGWIN_UPGRADE_REQUIRED=0
+
+for %%P in (%CYGWIN_PACKAGES%) do call :CheckPackage %%P
+call :UpgradeCygwin
+
+"%CYG_ROOT%\bin\bash.exe" -lec "$APPVEYOR_BUILD_FOLDER/appveyor_build.sh install" || exit /b 1
+
+call :SaveVars
+goto :EOF
+
+:build
+rem Run the msvc64 and mingw32 builds
+call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64.bat"
+"%CYG_ROOT%\bin\bash.exe" -lec "$APPVEYOR_BUILD_FOLDER/appveyor_build.sh" || exit /b 1
+
+rem Reconfigure the environment and run the msvc32 partial build
+call :RestoreVars
+call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x86
+"%CYG_ROOT%\bin\bash.exe" -lec "$APPVEYOR_BUILD_FOLDER/appveyor_build.sh msvc32-only" || exit /b 1
+goto :EOF
+
+:test
+rem Reconfigure the environment for the msvc64 build
+call :RestoreVars
+call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64.bat"
+"%CYG_ROOT%\bin\bash.exe" -lec "$APPVEYOR_BUILD_FOLDER/appveyor_build.sh test" || exit /b 1
+goto :EOF
#* *
#**************************************************************************
+BUILD_PID=0
+
function run {
NAME=$1
shift
CODE=$?
if [ $CODE -ne 0 ]; then
echo "-=-=- $NAME failed! -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-"
+ if [ $BUILD_PID -ne 0 ] ; then
+ kill -KILL $BUILD_PID 2>/dev/null
+ wait $BUILD_PID 2>/dev/null
+ fi
exit $CODE
else
echo "-=-=- End of $NAME -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-"
fi
}
-PREFIX="C:/Program Files/OCaml"
-
-wmic cpu get name
-
-if [[ $1 = "msvc32-only" ]] ; then
- cd $APPVEYOR_BUILD_FOLDER/flexdll-0.35
- make MSVC_DETECT=0 CHAINS=msvc MSVC_FLAGS="-nologo -MD -D_CRT_NO_DEPRECATE -GS- -WX" support
- cp flexdll*_msvc.obj "$PREFIX/bin/flexdll"
-
- cd $APPVEYOR_BUILD_FOLDER/../build-msvc32
- cp config/m-nt.h config/m.h
- cp config/s-nt.h config/s.h
-
- eval $(tools/msvs-promote-path)
-
- PREFIX="C:/Program Files/OCaml-msmvc32"
- echo "Edit config/Makefile to set PREFIX=$PREFIX"
- sed -e "s|PREFIX=.*|PREFIX=$PREFIX|" -e "/\(BYTE\|NATIVE\)CCCOMPOPTS=./s/\r\?$/ -WX\0/" config/Makefile.msvc > config/Makefile
-
- run "make world" make world
- run "make runtimeopt" make runtimeopt
- run "make -C otherlibs/systhreads libthreadsnat.lib" make -C otherlibs/systhreads libthreadsnat.lib
-
- exit 0
-fi
-
-cd $APPVEYOR_BUILD_FOLDER
-
-git worktree add ../build-mingw32 -b appveyor-build-mingw32
-git worktree add ../build-msvc32 -b appveyor-build-msvc32
+function set_configuration {
+ cp config/m-nt.h byterun/caml/m.h
+ cp config/s-nt.h byterun/caml/s.h
-cd ../build-mingw32
-git submodule update --init flexdll
-
-cd $APPVEYOR_BUILD_FOLDER
-
-tar -xzf flexdll.tar.gz
-cd flexdll-0.35
-make MSVC_DETECT=0 CHAINS=msvc64 support
-cp flexdll*_msvc64.obj "$PREFIX/bin/flexdll"
-cd ..
-
-cp config/m-nt.h config/m.h
-cp config/s-nt.h config/s.h
-
-echo "Edit config/Makefile to set PREFIX=$PREFIX"
-sed -e "s|PREFIX=.*|PREFIX=$PREFIX|" -e "/\(BYTE\|NATIVE\)CCCOMPOPTS=./s/\r\?$/ -WX\0/" config/Makefile.msvc64 > config/Makefile
-#run "Content of config/Makefile" cat config/Makefile
-
-run "make world" make world
-run "make bootstrap" make bootstrap
-run "make opt" make opt
-run "make opt.opt" make opt.opt
-
-cd ../build-mingw32
-
-cp config/m-nt.h config/m.h
-cp config/s-nt.h config/s.h
-
-PREFIX="C:/Program Files/OCaml-mingw32"
-echo "Edit config/Makefile to set PREFIX=$PREFIX"
-sed -e "s|PREFIX=.*|PREFIX=$PREFIX|" -e "/\(BYTE\|NATIVE\)CCCOMPOPTS=./s/\r\?$/ -Werror\0/" config/Makefile.mingw > config/Makefile
-#run "Content of config/Makefile" cat config/Makefile
+ FILE=$(pwd | cygpath -f - -m)/config/Makefile
+ echo "Edit $FILE to set PREFIX=$2"
+ sed -e "/PREFIX=/s|=.*|=$2|" \
+ -e "/^ *CFLAGS *=/s/\r\?$/ $3\0/" \
+ config/Makefile.$1 > config/Makefile
+# run "Content of $FILE" cat config/Makefile
+}
-run "make flexdll" make flexdll
-run "make world.opt" make world.opt
+APPVEYOR_BUILD_FOLDER=$(echo $APPVEYOR_BUILD_FOLDER| cygpath -f -)
+# These directory names are specified here, because getting UTF-8 correctly
+# through appveyor.yml -> Command Script -> Bash is quite painful...
+OCAMLROOT=$(echo $PROGRAMFILES/Бактріан🐫| cygpath -f - -m)
+
+# This must be kept in sync with appveyor_build.cmd
+BUILD_PREFIX=🐫реализация
+
+export PATH=$(echo $OCAMLROOT| cygpath -f -)/bin/flexdll:$PATH
+
+case "$1" in
+ install)
+ mkdir -p "$OCAMLROOT/bin/flexdll"
+ cd $APPVEYOR_BUILD_FOLDER/../flexdll
+ # msvc64 objects need to be compiled with VS2015, so are copied later from
+ # a source build.
+ for f in flexdll.h flexlink.exe flexdll*_msvc.obj default*.manifest ; do
+ cp $f "$OCAMLROOT/bin/flexdll/"
+ done
+ echo 'eval $($APPVEYOR_BUILD_FOLDER/tools/msvs-promote-path)' >> ~/.bash_profile
+ ;;
+ msvc32-only)
+ cd $APPVEYOR_BUILD_FOLDER/../$BUILD_PREFIX-msvc32
+
+ set_configuration msvc "$OCAMLROOT-msvc32" -WX
+
+ run "make world" make world
+ run "make runtimeopt" make runtimeopt
+ run "make -C otherlibs/systhreads libthreadsnat.lib" \
+ make -C otherlibs/systhreads libthreadsnat.lib
+
+ exit 0
+ ;;
+ test)
+ FULL_BUILD_PREFIX=$APPVEYOR_BUILD_FOLDER/../$BUILD_PREFIX
+ run "ocamlc.opt -version" $FULL_BUILD_PREFIX-msvc64/ocamlc.opt -version
+ run "test msvc64" make -C $FULL_BUILD_PREFIX-msvc64 tests
+ run "test mingw32" make -C $FULL_BUILD_PREFIX-mingw32 tests
+ run "install msvc64" make -C $FULL_BUILD_PREFIX-msvc64 install
+ run "install mingw32" make -C $FULL_BUILD_PREFIX-mingw32 install
+ ;;
+ *)
+ cd $APPVEYOR_BUILD_FOLDER/../$BUILD_PREFIX-msvc64
+
+ tar -xzf $APPVEYOR_BUILD_FOLDER/flexdll.tar.gz
+ cd flexdll-$FLEXDLL_VERSION
+ make MSVC_DETECT=0 CHAINS=msvc64 support
+ cp flexdll*_msvc64.obj "$OCAMLROOT/bin/flexdll/"
+ cd ..
+
+ set_configuration msvc64 "$OCAMLROOT" -WX
+
+ cd ../$BUILD_PREFIX-mingw32
+
+ set_configuration mingw "$OCAMLROOT-mingw32" -Werror
+
+ cd $APPVEYOR_BUILD_FOLDER/../$BUILD_PREFIX-msvc64
+
+ export TERM=ansi
+ script --quiet --return --command "make -C ../$BUILD_PREFIX-mingw32 flexdll world.opt" ../$BUILD_PREFIX-mingw32/build.log >/dev/null 2>/dev/null &
+ BUILD_PID=$!
+
+ run "make world" make world
+ run "make bootstrap" make bootstrap
+ run "make opt" make opt
+ run "make opt.opt" make opt.opt
+
+ set +e
+
+ # For an explanation of the sed command, see https://github.com/appveyor/ci/issues/1824
+ tail --pid=$BUILD_PID -n +1 -f ../$BUILD_PREFIX-mingw32/build.log | sed -e 's/\d027\[K//g' -e 's/\d027\[m/\d027[0m/g' -e 's/\d027\[01\([m;]\)/\d027[1\1/g' &
+ TAIL_PID=$!
+ wait $BUILD_PID
+ STATUS=$?
+ wait $TAIL_PID
+ exit $STATUS
+ ;;
+esac
class cse_generic = object (self)
-(* Default classification of operations. Can be overriden in
+(* Default classification of operations. Can be overridden in
processor-specific files to classify specific operations better. *)
method class_of_operation op =
| Inegf | Iabsf | Iaddf | Isubf | Imulf | Idivf
| Ifloatofint | Iintoffloat -> Op_pure
| Ispecific _ -> Op_other
+ | Iname_for_debugger _ -> Op_pure
(* Operations that are so cheap that it isn't worth factoring them. *)
| Ioffset_loc of int * addressing_mode (* Add a constant to a location *)
| Ifloatarithmem of float_operation * addressing_mode
(* Float arith operation with memory *)
- | Ibswap of int (* endiannes conversion *)
+ | Ibswap of int (* endianness conversion *)
| Isqrtf (* Float square root *)
| Ifloatsqrtf of addressing_mode (* Float square root from memory *)
and float_operation =
let rel_plt s =
if windows && !Clflags.dlcode then mem__imp s
else
- let use_plt =
- match system with
- | S_macosx | S_mingw64 | S_cygwin | S_win64 -> false
- | _ -> !Clflags.dlcode
- in
sym (if use_plt then emit_symbol s ^ "@PLT" else emit_symbol s)
let emit_call s = I.call (rel_plt s)
I.sqrtsd (arg i 0) (res i 0)
| Lop(Ispecific(Ifloatsqrtf addr)) ->
I.sqrtsd (addressing addr REAL8 i 0) (res i 0)
+ | Lop (Iname_for_debugger _) -> ()
| Lreloadretaddr ->
()
| Lreturn ->
emit_imp_table();
D.data ();
+ D.qword (const 0); (* PR#6329 *)
emit_global_label "data_end";
- D.long (const 0);
+ D.qword (const 0);
+ D.align 8; (* PR#7591 *)
emit_global_label "frametable";
let setcnt = ref 0 in
xmm0 - xmm3: C function arguments
rbx, rbp, rsi, rdi r12-r15 are preserved by C
xmm6-xmm15 are preserved by C
- Note (PR#5707): r11 should not be used for parameter passing, as it
- can be destroyed by the dynamic loader according to SVR4 ABI.
- Linux's dynamic loader also destroys r10.
+ Note (PR#5707, GPR#1304): PLT stubs (used for dynamic resolution of symbols
+ on Unix-like platforms) may clobber any register except those used for:
+ 1. C parameter passing;
+ 2. C return values;
+ 3. C callee-saved registers.
+ This translates to the set { r10, r11 }. These registers hence cannot
+ be used for OCaml parameter passing and must also be marked as
+ destroyed across [Ialloc] (otherwise a call to caml_call_gc@PLT might
+ clobber these two registers before the assembly stub saves them into
+ the GC regs block).
*)
let max_arguments_for_tailcalls = 10
let rax = phys_reg 0
let rdx = phys_reg 4
+let r10 = phys_reg 10
+let r11 = phys_reg 11
let r13 = phys_reg 9
let rbp = phys_reg 12
let rxmm15 = phys_reg 115
+let destroyed_by_plt_stub =
+ if not X86_proc.use_plt then [| |] else [| r10; r11 |]
+
+let num_destroyed_by_plt_stub = Array.length destroyed_by_plt_stub
+
+let destroyed_by_plt_stub_set = Reg.set_of_array destroyed_by_plt_stub
+
let stack_slot slot ty =
Reg.at_location ty (Stack slot)
end else begin
loc.(i) <- stack_slot (make_stack !ofs) ty;
ofs := !ofs + size_int
- end
+ end;
+ assert (not (Reg.Set.mem loc.(i) destroyed_by_plt_stub_set))
| Float ->
if !float <= last_float then begin
loc.(i) <- phys_reg !float;
100;101;102;103;104;105;106;107;
108;109;110;111;112;113;114;115])
+let destroyed_at_alloc =
+ let regs =
+ if Config.spacetime then
+ [| rax; loc_spacetime_node_hole |]
+ else
+ [| rax |]
+ in
+ Array.concat [regs; destroyed_by_plt_stub]
+
let destroyed_at_oper = function
Iop(Icall_ind _ | Icall_imm _ | Iextcall { alloc = true; }) ->
all_phys_regs
| Iop(Iintop(Idiv | Imod)) | Iop(Iintop_imm((Idiv | Imod), _))
-> [| rax; rdx |]
| Iop(Istore(Single, _, _)) -> [| rxmm15 |]
- | Iop(Ialloc _) when Config.spacetime
- -> [| rax; loc_spacetime_node_hole |]
- | Iop(Ialloc _ | Iintop(Imulh | Icomp _) | Iintop_imm((Icomp _), _))
+ | Iop(Ialloc _) -> destroyed_at_alloc
+ | Iop(Iintop(Imulh | Icomp _) | Iintop_imm((Icomp _), _))
-> [| rax |]
| Iop (Iintop (Icheckbound _)) when Config.spacetime ->
[| loc_spacetime_node_hole |]
if fp then [| 3; 0 |] else [| 4; 0 |]
| Iintop(Idiv | Imod) | Iintop_imm((Idiv | Imod), _) ->
if fp then [| 10; 16 |] else [| 11; 16 |]
- | Ialloc _ | Iintop(Icomp _) | Iintop_imm((Icomp _), _) ->
+ | Ialloc _ ->
+ if fp then [| 11 - num_destroyed_by_plt_stub; 16 |]
+ else [| 12 - num_destroyed_by_plt_stub; 16 |]
+ | Iintop(Icomp _) | Iintop_imm((Icomp _), _) ->
if fp then [| 11; 16 |] else [| 12; 16 |]
| Istore(Single, _, _) ->
if fp then [| 12; 15 |] else [| 13; 15 |]
| Imulsubf (* floating-point multiply and subtract *)
| Inegmulsubf (* floating-point negate, multiply and subtract *)
| Isqrtf (* floating-point square root *)
- | Ibswap of int (* endianess conversion *)
+ | Ibswap of int (* endianness conversion *)
and arith_operation =
Ishiftadd
(* Pending symbol literals *)
let symbol_literals = ref ([] : (string * label) list)
(* Total space (in words) occupied by pending literals *)
-let num_literals = ref 0
+let size_literals = ref 0
(* Label a floating-point literal *)
let float_literal f =
List.assoc f !float_literals
with Not_found ->
let lbl = new_label() in
- num_literals := !num_literals + 2;
+ size_literals := !size_literals + 2;
float_literals := (f, lbl) :: !float_literals;
lbl
(* Label a GOTREL literal *)
let gotrel_literal l =
let lbl = new_label() in
- num_literals := !num_literals + 1;
+ size_literals := !size_literals + 1;
gotrel_literals := (l, lbl) :: !gotrel_literals;
lbl
List.assoc s !symbol_literals
with Not_found ->
let lbl = new_label() in
- num_literals := !num_literals + 1;
+ size_literals := !size_literals + 1;
symbol_literals := (s, lbl) :: !symbol_literals;
lbl
gotrel_literals := [];
symbol_literals := []
end;
- num_literals := 0
+ size_literals := 0
(* Emit code to load the address of a symbol *)
let instr = name_for_int_operation op in
` {emit_string instr} {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, #{emit_int n}\n`; 1
| Lop(Iabsf | Inegf as op) when !fpu = Soft ->
+ assert (i.res.(0).loc = i.arg.(0).loc);
let instr = (match op with
Iabsf -> "bic"
| Inegf -> "eor"
` {emit_string instr} {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`;
1
| Lop(Ispecific(Imuladdf | Inegmuladdf | Imulsubf | Inegmulsubf as op)) ->
+ assert (i.res.(0).loc = i.arg.(0).loc);
let instr = (match op with
Imuladdf -> "fmacd"
| Inegmuladdf -> "fnmacd"
| _ ->
assert false
end
+ | Lop (Iname_for_debugger _) -> 0
| Lreloadretaddr ->
let n = frame_size() in
` ldr lr, [sp, #{emit_int(n-4)}]\n`; 1
tramtbl.(j) <- label i.next;
` .short ({emit_label tramtbl.(j)}-.)/2+{emit_int j}\n`
done;
+ let sz = ref (1 + (Array.length jumptbl + 1) / 2) in
(* Generate the necessary trampolines *)
for j = 0 to Array.length tramtbl - 1 do
- if tramtbl.(j) <> jumptbl.(j) then
- `{emit_label tramtbl.(j)}: b {emit_label jumptbl.(j)}\n`
- done
+ if tramtbl.(j) <> jumptbl.(j) then begin
+ `{emit_label tramtbl.(j)}: b {emit_label jumptbl.(j)}\n`;
+ incr sz
+ end
+ done;
+ !sz
end else if not !Clflags.pic_code then begin
` ldr pc, [pc, {emit_reg i.arg.(0)}, lsl #2]\n`;
` nop\n`;
for j = 0 to Array.length jumptbl - 1 do
` .word {emit_label jumptbl.(j)}\n`
- done
+ done;
+ 2 + Array.length jumptbl
end else begin
(* Slightly slower, but position-independent *)
` add pc, pc, {emit_reg i.arg.(0)}, lsl #2\n`;
` nop\n`;
for j = 0 to Array.length jumptbl - 1 do
` b {emit_label jumptbl.(j)}\n`
- done
- end;
- 2 + Array.length jumptbl
+ done;
+ 2 + Array.length jumptbl
+ end
| Lsetuptrap lbl ->
` bl {emit_label lbl}\n`; 1
| Lpushtrap ->
` pop \{trap_ptr, pc}\n`; 2
end
+(* Upper bound on the size of the code sequence for a Linear instruction,
+ in 32-bit words. *)
+
+let max_instruction_size i =
+ match i.desc with
+ | Lswitch jumptbl ->
+ if !arch > ARMv6 && !thumb
+ then 1 + (Array.length jumptbl + 1) / 2 + Array.length jumptbl
+ else 2 + Array.length jumptbl
+ | _ ->
+ 8 (* conservative upper bound; the true upper bound is probably 5 *)
+
(* Emission of an instruction sequence *)
-let rec emit_all ninstr i =
+let rec emit_all ninstr fallthrough i =
+ (* ninstr = number of 32-bit code words emitted since last constant island *)
+ (* fallthrough is true if previous instruction can fall through *)
if i.desc = Lend then () else begin
- let n = emit_instr i in
- let ninstr' = ninstr + n in
+ (* Make sure literals not yet emitted remain addressable,
+ or emit them in a new constant island. *)
(* fldd can address up to +/-1KB, ldr can address up to +/-4KB *)
let limit = (if !fpu >= VFPv2 && !float_literals <> []
then 127
else 511) in
- let limit = limit - !num_literals in
- if ninstr' >= limit - 64 && not(has_fallthrough i.desc) then begin
- emit_literals();
- emit_all 0 i.next
- end else if !num_literals != 0 && ninstr' >= limit then begin
- let lbl = new_label() in
- ` b {emit_label lbl}\n`;
- emit_literals();
- `{emit_label lbl}:\n`;
- emit_all 0 i.next
- end else
- emit_all ninstr' i.next
+ let limit = limit - !size_literals - max_instruction_size i in
+ let ninstr' =
+ if ninstr >= limit - 64 && not fallthrough then begin
+ emit_literals();
+ 0
+ end else if !size_literals != 0 && ninstr >= limit then begin
+ let lbl = new_label() in
+ ` b {emit_label lbl}\n`;
+ emit_literals();
+ `{emit_label lbl}:\n`;
+ 0
+ end else
+ ninstr in
+ let n = emit_instr i in
+ emit_all (ninstr' + n) (has_fallthrough i.desc) i.next
end
+
(* Emission of the profiling prelude *)
let emit_profile() =
end
end;
`{emit_label !tailrec_entry_point}:\n`;
- emit_all 0 fundecl.fun_body;
+ emit_all 0 true fundecl.fun_body;
emit_literals();
List.iter emit_call_gc !call_gc_sites;
List.iter emit_call_bound_error !bound_error_sites;
`{emit_symbol lbl_end}:\n`;
let lbl_end = Compilenv.make_symbol (Some "data_end") in
` .data\n`;
+ ` .long 0\n`; (* PR#6329 *)
` .globl {emit_symbol lbl_end}\n`;
`{emit_symbol lbl_end}:\n`;
` .long 0\n`;
Floating-point register map (VFPv{2,3}):
d0 - d7 general purpose (not preserved)
d8 - d15 general purpose (preserved)
- d16 - d31 generat purpose (not preserved), VFPv3 only
+ d16 - d31 general purpose (not preserved), VFPv3 only
*)
let int_reg_name =
(* *)
(**************************************************************************)
+open Arch
+open Mach
+
(* Reloading for the ARM *)
+class reload = object
+
+inherit Reloadgen.reload_generic as super
+
+method! reload_operation op arg res =
+ let ((arg', res') as argres') = super#reload_operation op arg res in
+ match op with
+ | Iintop Imul | Ispecific Imuladd ->
+ (* On ARM v4 and v5, module [Selection] adds a second, dummy
+ result to multiplication instructions (mul and muladd). This
+ second result is the same pseudoregister as the first
+ argument to the multiplication. As shown in MPR#7642,
+ reloading must maintain this invariant. Otherwise, the second
+ result and the first argument can end up in different registers,
+ and the second result can be used later, even though
+ it is not initialized. *)
+ if Array.length res' >= 2 then res'.(1) <- arg'.(0);
+ argres'
+ | Ispecific(Imuladdf | Inegmuladdf | Imulsubf | Inegmulsubf) ->
+ (* VFP float multiply-add instructions are "two-address" in the
+ sense that they must have [arg.(0) = res.(0)].
+ Preserve this invariant. *)
+ (arg', [|arg'.(0)|])
+ | Iabsf | Inegf when !fpu = Soft ->
+ (* Soft FP neg and abs also have a "two-address" constraint of sorts.
+ 64-bit floats are represented by pairs of 32-bit integers,
+ hence there are two arguments and two results.
+ The code emitter assumes [arg.(0) = res.(0)] but supports
+ [arg.(1)] and [res.(1)] being in different registers. *)
+ res'.(0) <- arg'.(0);
+ argres'
+ | _ ->
+ argres'
+end
+
let fundecl f =
- (new Reloadgen.reload_generic)#fundecl f
+ (new reload)#fundecl f
| Imulsubf (* floating-point multiply and subtract *)
| Inegmulsubf (* floating-point negate, multiply and subtract *)
| Isqrtf (* floating-point square root *)
- | Ibswap of int (* endianess conversion *)
+ | Ibswap of int (* endianness conversion *)
and arith_operation =
Ishiftadd
| Iindexed ofs ->
`[{emit_reg r}, #{emit_int ofs}]`
| Ibased(s, ofs) ->
+ assert (not !Clflags.dlcode); (* see selection.ml *)
`[{emit_reg r}, #:lo12:{emit_symbol_offset s ofs}]`
(* Record live pointers at call points *)
(* Emit code to load the address of a symbol *)
let emit_load_symbol_addr dst s =
- if (not !Clflags.dlcode) || Compilenv.symbol_in_current_unit s then begin
+ if not !Clflags.dlcode then begin
` adrp {emit_reg dst}, {emit_symbol s}\n`;
` add {emit_reg dst}, {emit_reg dst}, #:lo12:{emit_symbol s}\n`
end else begin
| Lop (Iload (size, addr)) | Lop (Istore (size, addr, _)) ->
let based = match addr with Iindexed _ -> 0 | Ibased _ -> 1 in
based + begin match size with Single -> 2 | _ -> 1 end
- | Lop (Ialloc _) when !fastcode_flag -> 4
- | Lop (Ispecific (Ifar_alloc _)) when !fastcode_flag -> 5
+ | Lop (Ialloc {words = num_words}) when !fastcode_flag ->
+ if num_words <= 0xFFF then 4 else 5
+ | Lop (Ispecific (Ifar_alloc {words = num_words})) when !fastcode_flag ->
+ if num_words <= 0xFFF then 5 else 6
| Lop (Ialloc { words = num_words; _ })
| Lop (Ispecific (Ifar_alloc { words = num_words; _ })) ->
begin match num_words with
| Lop (Ispecific (Imuladd | Imulsub)) -> 1
| Lop (Ispecific (Ibswap 16)) -> 2
| Lop (Ispecific (Ibswap _)) -> 1
+ | Lop (Iname_for_debugger _) -> 0
| Lreloadretaddr -> 0
| Lreturn -> epilogue_size ()
| Llabel _ -> 0
if !fastcode_flag then begin
let lbl_redo = new_label() in
let lbl_call_gc = new_label() in
+ assert (n < 0x1_000_000);
+ let nl = n land 0xFFF and nh = n land 0xFFF_000 in
`{emit_label lbl_redo}:`;
- ` sub {emit_reg reg_alloc_ptr}, {emit_reg reg_alloc_ptr}, #{emit_int n}\n`;
+ if nh <> 0 then
+ ` sub {emit_reg reg_alloc_ptr}, {emit_reg reg_alloc_ptr}, #{emit_int nh}\n`;
+ if nl <> 0 then
+ ` sub {emit_reg reg_alloc_ptr}, {emit_reg reg_alloc_ptr}, #{emit_int nl}\n`;
` cmp {emit_reg reg_alloc_ptr}, {emit_reg reg_alloc_limit}\n`;
` add {emit_reg i.res.(0)}, {emit_reg reg_alloc_ptr}, #8\n`;
if not far then begin
match addr with
| Iindexed _ -> i.arg.(0)
| Ibased(s, ofs) ->
+ assert (not !Clflags.dlcode); (* see selection.ml *)
` adrp {emit_reg reg_tmp1}, {emit_symbol_offset s ofs}\n`;
reg_tmp1 in
begin match size with
match addr with
| Iindexed _ -> i.arg.(1)
| Ibased(s, ofs) ->
+ assert (not !Clflags.dlcode);
` adrp {emit_reg reg_tmp1}, {emit_symbol_offset s ofs}\n`;
reg_tmp1 in
begin match size with
| _ ->
assert false
end
+ | Lop (Iname_for_debugger _) -> ()
| Lreloadretaddr ->
()
| Lreturn ->
let emit_item = function
| Cglobal_symbol s -> ` .globl {emit_symbol s}\n`;
- | Cdefine_symbol s -> `{emit_symbol s}:\n`
+ | Cdefine_symbol s ->
+ if !Clflags.dlcode then begin
+ (* GOT relocations against non-global symbols don't seem to work
+ properly: GOT entries are not created for the symbols and the
+ relocations evaluate to random other GOT entries. For the moment
+ force all symbols to be global. *)
+ ` .globl {emit_symbol s}\n`;
+ end;
+ `{emit_symbol s}:\n`
| Cint8 n -> ` .byte {emit_int n}\n`
| Cint16 n -> ` .short {emit_int n}\n`
| Cint32 n -> ` .long {emit_nativeint n}\n`
`{emit_symbol lbl_end}:\n`;
let lbl_end = Compilenv.make_symbol (Some "data_end") in
` .data\n`;
+ ` .quad 0\n`; (* PR#6329 *)
` .globl {emit_symbol lbl_end}\n`;
`{emit_symbol lbl_end}:\n`;
` .long 0\n`;
Floating-point register map:
d0 - d7 general purpose (caller-save)
d8 - d15 general purpose (callee-save)
- d16 - d31 generat purpose (caller-save)
+ d16 - d31 general purpose (caller-save)
*)
let int_reg_name =
[ "sqrt"; "caml_bswap16_direct"; "caml_int32_direct_bswap";
"caml_int64_direct_bswap"; "caml_nativeint_direct_bswap" ]
-let use_direct_addressing symb =
- (not !Clflags.dlcode) || Compilenv.symbol_in_current_unit symb
+let use_direct_addressing _symb =
+ not !Clflags.dlcode
(* Instruction selection *)
fatal_error(fd.Mach.fun_name ^
": function too complex, cannot complete register allocation");
dump_if ppf dump_live "Liveness analysis" fd;
- Interf.build_graph fd;
- if !dump_interf then Printmach.interferences ppf ();
- if !dump_prefer then Printmach.preferences ppf ();
- Coloring.allocate_registers();
+ if !use_linscan then begin
+ (* Linear Scan *)
+ Interval.build_intervals fd;
+ if !dump_interval then Printmach.intervals ppf ();
+ Linscan.allocate_registers()
+ end else begin
+ (* Graph Coloring *)
+ Interf.build_graph fd;
+ if !dump_interf then Printmach.interferences ppf ();
+ if !dump_prefer then Printmach.preferences ppf ();
+ Coloring.allocate_registers()
+ end;
dump_if ppf dump_regalloc "After register allocation" fd;
let (newfd, redo_regalloc) = Reload.fundecl fd in
dump_if ppf dump_reload "After insertion of reloading code" newfd;
let compile_fundecl (ppf : formatter) fd_cmm =
Proc.init ();
Reg.reset();
- let build = Compilenv.current_build () in
fd_cmm
- ++ Timings.(accumulate_time (Selection build)) Selection.fundecl
+ ++ Profile.record ~accumulate:true "selection" Selection.fundecl
++ pass_dump_if ppf dump_selection "After instruction selection"
- ++ Timings.(accumulate_time (Comballoc build)) Comballoc.fundecl
+ ++ Profile.record ~accumulate:true "comballoc" Comballoc.fundecl
++ pass_dump_if ppf dump_combine "After allocation combining"
- ++ Timings.(accumulate_time (CSE build)) CSE.fundecl
+ ++ Profile.record ~accumulate:true "cse" CSE.fundecl
++ pass_dump_if ppf dump_cse "After CSE"
- ++ Timings.(accumulate_time (Liveness build)) (liveness ppf)
- ++ Timings.(accumulate_time (Deadcode build)) Deadcode.fundecl
+ ++ Profile.record ~accumulate:true "liveness" (liveness ppf)
+ ++ Profile.record ~accumulate:true "deadcode" Deadcode.fundecl
++ pass_dump_if ppf dump_live "Liveness analysis"
- ++ Timings.(accumulate_time (Spill build)) Spill.fundecl
- ++ Timings.(accumulate_time (Liveness build)) (liveness ppf)
+ ++ Profile.record ~accumulate:true "spill" Spill.fundecl
+ ++ Profile.record ~accumulate:true "liveness" (liveness ppf)
++ pass_dump_if ppf dump_spill "After spilling"
- ++ Timings.(accumulate_time (Split build)) Split.fundecl
+ ++ Profile.record ~accumulate:true "split" Split.fundecl
++ pass_dump_if ppf dump_split "After live range splitting"
- ++ Timings.(accumulate_time (Liveness build)) (liveness ppf)
- ++ Timings.(accumulate_time (Regalloc build)) (regalloc ppf 1)
- ++ Timings.(accumulate_time (Linearize build)) Linearize.fundecl
+ ++ Profile.record ~accumulate:true "liveness" (liveness ppf)
+ ++ Profile.record ~accumulate:true "regalloc" (regalloc ppf 1)
+ ++ Profile.record ~accumulate:true "available_regs" Available_regs.fundecl
+ ++ Profile.record ~accumulate:true "linearize" Linearize.fundecl
++ pass_dump_linear_if ppf dump_linear "Linearized code"
- ++ Timings.(accumulate_time (Scheduling build)) Scheduling.fundecl
+ ++ Profile.record ~accumulate:true "scheduling" Scheduling.fundecl
++ pass_dump_linear_if ppf dump_scheduling "After instruction scheduling"
- ++ Timings.(accumulate_time (Emit build)) Emit.fundecl
+ ++ Profile.record ~accumulate:true "emit" Emit.fundecl
let compile_phrase ppf p =
if !dump_cmm then fprintf ppf "%a@." Printcmm.phrase p;
| _ -> ())
(Cmmgen.generic_functions true [Compilenv.current_unit_infos ()])
-let compile_unit ~source_provenance _output_prefix asm_filename keep_asm
+let compile_unit _output_prefix asm_filename keep_asm
obj_filename gen =
let create_asm = keep_asm || not !Emitaux.binary_backend_available in
Emitaux.create_asm_file := create_asm;
raise exn
end;
let assemble_result =
- Timings.(time (Assemble source_provenance))
+ Profile.record "assemble"
(Proc.assemble_file asm_filename) obj_filename
in
if assemble_result <> 0
Compilenv.set_export_info export;
(ulambda, prealloc, structured_constants)
-let end_gen_implementation ?toplevel ~source_provenance ppf
+let end_gen_implementation ?toplevel ppf
(clambda:clambda_and_constants) =
Emit.begin_assembly ();
clambda
- ++ Timings.(time (Cmm source_provenance)) Cmmgen.compunit
- ++ Timings.(time (Compile_phrases source_provenance))
- (List.iter (compile_phrase ppf))
+ ++ Profile.record "cmm" Cmmgen.compunit
+ ++ Profile.record "compile_phrases" (List.iter (compile_phrase ppf))
++ (fun () -> ());
(match toplevel with None -> () | Some f -> compile_genfuns ppf f);
);
Emit.end_assembly ()
-let flambda_gen_implementation ?toplevel ~source_provenance ~backend ppf
+let flambda_gen_implementation ?toplevel ~backend ppf
(program:Flambda.program) =
let export = Build_export_info.build_export_info ~backend program in
let (clambda, preallocated, constants) =
- Timings.time (Flambda_pass ("backend", source_provenance)) (fun () ->
+ Profile.record_call "backend" (fun () ->
(program, export)
++ Flambda_to_clambda.convert
++ flambda_raw_clambda_dump_if ppf
[Cmmgen.compunit_and_constants]. *)
Un_anf.apply expr ~what:"init_code", preallocated_blocks,
structured_constants, exported)
- ++ set_export_info) ()
+ ++ set_export_info)
in
let constants =
List.map (fun (symbol, definition) ->
definition })
(Symbol.Map.bindings constants)
in
- end_gen_implementation ?toplevel ~source_provenance ppf
+ end_gen_implementation ?toplevel ppf
(clambda, preallocated, constants)
-let lambda_gen_implementation ?toplevel ~source_provenance ppf
+let lambda_gen_implementation ?toplevel ppf
(lambda:Lambda.program) =
let clambda = Closure.intro lambda.main_module_block_size lambda.code in
let preallocated_block =
clambda, [preallocated_block], []
in
raw_clambda_dump_if ppf clambda_and_constants;
- end_gen_implementation ?toplevel ~source_provenance ppf clambda_and_constants
+ end_gen_implementation ?toplevel ppf clambda_and_constants
-let compile_implementation_gen ?toplevel ~source_provenance prefixname
+let compile_implementation_gen ?toplevel prefixname
~required_globals ppf gen_implementation program =
let asmfile =
if !keep_asm_file || !Emitaux.binary_backend_available
then prefixname ^ ext_asm
else Filename.temp_file "camlasm" ext_asm
in
- compile_unit ~source_provenance prefixname asmfile !keep_asm_file
+ compile_unit prefixname asmfile !keep_asm_file
(prefixname ^ ext_obj) (fun () ->
Ident.Set.iter Compilenv.require_global required_globals;
- gen_implementation ?toplevel ~source_provenance ppf program)
+ gen_implementation ?toplevel ppf program)
-let compile_implementation_clambda ?toplevel ~source_provenance prefixname
+let compile_implementation_clambda ?toplevel prefixname
ppf (program:Lambda.program) =
- compile_implementation_gen ?toplevel ~source_provenance prefixname
+ compile_implementation_gen ?toplevel prefixname
~required_globals:program.Lambda.required_globals
ppf lambda_gen_implementation program
-let compile_implementation_flambda ?toplevel ~source_provenance prefixname
+let compile_implementation_flambda ?toplevel prefixname
~required_globals ~backend ppf (program:Flambda.program) =
- compile_implementation_gen ?toplevel ~source_provenance prefixname
+ compile_implementation_gen ?toplevel prefixname
~required_globals ppf (flambda_gen_implementation ~backend) program
(* Error report *)
val compile_implementation_flambda :
?toplevel:(string -> bool) ->
- source_provenance:Timings.source_provenance ->
string ->
required_globals:Ident.Set.t ->
backend:(module Backend_intf.S) ->
val compile_implementation_clambda :
?toplevel:(string -> bool) ->
- source_provenance:Timings.source_provenance ->
string ->
Format.formatter -> Lambda.program -> unit
val compile_unit:
- source_provenance:Timings.source_provenance ->
string(*prefixname*) ->
string(*asm file*) -> bool(*keep asm*) ->
string(*obj file*) -> (unit -> unit) -> unit
let make_startup_file ppf units_list =
let compile_phrase p = Asmgen.compile_phrase ppf p in
Location.input_name := "caml_startup"; (* set name of "current" input *)
- Compilenv.reset ~source_provenance:Timings.Startup "_startup";
+ Compilenv.reset "_startup";
(* set the name of the "current" compunit *)
Emit.begin_assembly ();
let name_list =
let make_shared_startup_file ppf units =
let compile_phrase p = Asmgen.compile_phrase ppf p in
Location.input_name := "caml_startup";
- Compilenv.reset ~source_provenance:Timings.Startup "_shared_startup";
+ Compilenv.reset "_shared_startup";
Emit.begin_assembly ();
List.iter compile_phrase
(Cmmgen.generic_functions true (List.map fst units));
then raise(Error Linking_error)
let link_shared ppf objfiles output_name =
- let units_tolink = List.fold_right scan_file objfiles [] in
- List.iter
- (fun (info, file_name, crc) -> check_consistency file_name info crc)
- units_tolink;
- Clflags.ccobjs := !Clflags.ccobjs @ !lib_ccobjs;
- Clflags.all_ccopts := !lib_ccopts @ !Clflags.all_ccopts;
- let objfiles = List.rev (List.map object_file_name objfiles) @
- (List.rev !Clflags.ccobjs) in
-
- let startup =
- if !Clflags.keep_startup_file || !Emitaux.binary_backend_available
- then output_name ^ ".startup" ^ ext_asm
- else Filename.temp_file "camlstartup" ext_asm in
- let startup_obj = output_name ^ ".startup" ^ ext_obj in
- Asmgen.compile_unit ~source_provenance:Timings.Startup output_name
- startup !Clflags.keep_startup_file startup_obj
- (fun () ->
- make_shared_startup_file ppf
- (List.map (fun (ui,_,crc) -> (ui,crc)) units_tolink)
- );
- call_linker_shared (startup_obj :: objfiles) output_name;
- remove_file startup_obj
+ Profile.record_call output_name (fun () ->
+ let units_tolink = List.fold_right scan_file objfiles [] in
+ List.iter
+ (fun (info, file_name, crc) -> check_consistency file_name info crc)
+ units_tolink;
+ Clflags.ccobjs := !Clflags.ccobjs @ !lib_ccobjs;
+ Clflags.all_ccopts := !lib_ccopts @ !Clflags.all_ccopts;
+ let objfiles = List.rev (List.map object_file_name objfiles) @
+ (List.rev !Clflags.ccobjs) in
+
+ let startup =
+ if !Clflags.keep_startup_file || !Emitaux.binary_backend_available
+ then output_name ^ ".startup" ^ ext_asm
+ else Filename.temp_file "camlstartup" ext_asm in
+ let startup_obj = output_name ^ ".startup" ^ ext_obj in
+ Asmgen.compile_unit output_name
+ startup !Clflags.keep_startup_file startup_obj
+ (fun () ->
+ make_shared_startup_file ppf
+ (List.map (fun (ui,_,crc) -> (ui,crc)) units_tolink)
+ );
+ call_linker_shared (startup_obj :: objfiles) output_name;
+ remove_file startup_obj
+ )
let call_linker file_list startup_file output_name =
let main_dll = !Clflags.output_c_object
(* Main entry point *)
let link ppf objfiles output_name =
- let stdlib =
- if !Clflags.gprofile then "stdlib.p.cmxa" else "stdlib.cmxa" in
- let stdexit =
- if !Clflags.gprofile then "std_exit.p.cmx" else "std_exit.cmx" in
- let objfiles =
- if !Clflags.nopervasives then objfiles
- else if !Clflags.output_c_object then stdlib :: objfiles
- else stdlib :: (objfiles @ [stdexit]) in
- let units_tolink = List.fold_right scan_file objfiles [] in
- Array.iter remove_required Runtimedef.builtin_exceptions;
- begin match extract_missing_globals() with
- [] -> ()
- | mg -> raise(Error(Missing_implementations mg))
- end;
- List.iter
- (fun (info, file_name, crc) -> check_consistency file_name info crc)
- units_tolink;
- Clflags.ccobjs := !Clflags.ccobjs @ !lib_ccobjs;
- Clflags.all_ccopts := !lib_ccopts @ !Clflags.all_ccopts;
- (* put user's opts first *)
- let startup =
- if !Clflags.keep_startup_file || !Emitaux.binary_backend_available
- then output_name ^ ".startup" ^ ext_asm
- else Filename.temp_file "camlstartup" ext_asm in
- let startup_obj = Filename.temp_file "camlstartup" ext_obj in
- Asmgen.compile_unit ~source_provenance:Timings.Startup output_name
- startup !Clflags.keep_startup_file startup_obj
- (fun () -> make_startup_file ppf units_tolink);
- Misc.try_finally
- (fun () ->
- call_linker (List.map object_file_name objfiles) startup_obj output_name)
- (fun () -> remove_file startup_obj)
+ Profile.record_call output_name (fun () ->
+ let stdlib =
+ if !Clflags.gprofile then "stdlib.p.cmxa" else "stdlib.cmxa" in
+ let stdexit =
+ if !Clflags.gprofile then "std_exit.p.cmx" else "std_exit.cmx" in
+ let objfiles =
+ if !Clflags.nopervasives then objfiles
+ else if !Clflags.output_c_object then stdlib :: objfiles
+ else stdlib :: (objfiles @ [stdexit]) in
+ let units_tolink = List.fold_right scan_file objfiles [] in
+ Array.iter remove_required Runtimedef.builtin_exceptions;
+ begin match extract_missing_globals() with
+ [] -> ()
+ | mg -> raise(Error(Missing_implementations mg))
+ end;
+ List.iter
+ (fun (info, file_name, crc) -> check_consistency file_name info crc)
+ units_tolink;
+ Clflags.ccobjs := !Clflags.ccobjs @ !lib_ccobjs;
+ Clflags.all_ccopts := !lib_ccopts @ !Clflags.all_ccopts;
+ (* put user's opts first *)
+ let startup =
+ if !Clflags.keep_startup_file || !Emitaux.binary_backend_available
+ then output_name ^ ".startup" ^ ext_asm
+ else Filename.temp_file "camlstartup" ext_asm in
+ let startup_obj = Filename.temp_file "camlstartup" ext_obj in
+ Asmgen.compile_unit output_name
+ startup !Clflags.keep_startup_file startup_obj
+ (fun () -> make_startup_file ppf units_tolink);
+ Misc.try_finally
+ (fun () ->
+ call_linker (List.map object_file_name objfiles) startup_obj output_name)
+ (fun () -> remove_file startup_obj)
+ )
(* Error report *)
let make_package_object ppf members targetobj targetname coercion
~backend =
- let objtemp =
- if !Clflags.keep_asm_file
- then Filename.remove_extension targetobj ^ ".pack" ^ Config.ext_obj
- else
- (* Put the full name of the module in the temporary file name
- to avoid collisions with MSVC's link /lib in case of successive
- packs *)
- Filename.temp_file (Compilenv.make_symbol (Some "")) Config.ext_obj in
- let components =
- List.map
- (fun m ->
- match m.pm_kind with
- | PM_intf -> None
- | PM_impl _ -> Some(Ident.create_persistent m.pm_name))
- members in
- let module_ident = Ident.create_persistent targetname in
- let source_provenance = Timings.Pack targetname in
- let prefixname = Filename.remove_extension objtemp in
- if Config.flambda then begin
- let size, lam = Translmod.transl_package_flambda components coercion in
- let flam =
- Middle_end.middle_end ppf
- ~source_provenance
- ~prefixname
- ~backend
- ~size
- ~filename:targetname
- ~module_ident
- ~module_initializer:lam
+ Profile.record_call (Printf.sprintf "pack(%s)" targetname) (fun () ->
+ let objtemp =
+ if !Clflags.keep_asm_file
+ then Filename.remove_extension targetobj ^ ".pack" ^ Config.ext_obj
+ else
+ (* Put the full name of the module in the temporary file name
+ to avoid collisions with MSVC's link /lib in case of successive
+ packs *)
+ Filename.temp_file (Compilenv.make_symbol (Some "")) Config.ext_obj in
+ let components =
+ List.map
+ (fun m ->
+ match m.pm_kind with
+ | PM_intf -> None
+ | PM_impl _ -> Some(Ident.create_persistent m.pm_name))
+ members in
+ let module_ident = Ident.create_persistent targetname in
+ let prefixname = Filename.remove_extension objtemp in
+ if Config.flambda then begin
+ let size, lam = Translmod.transl_package_flambda components coercion in
+ let flam =
+ Middle_end.middle_end ppf
+ ~prefixname
+ ~backend
+ ~size
+ ~filename:targetname
+ ~module_ident
+ ~module_initializer:lam
+ in
+ Asmgen.compile_implementation_flambda
+ prefixname ~backend ~required_globals:Ident.Set.empty ppf flam;
+ end else begin
+ let main_module_block_size, code =
+ Translmod.transl_store_package
+ components (Ident.create_persistent targetname) coercion in
+ Asmgen.compile_implementation_clambda
+ prefixname ppf { Lambda.code; main_module_block_size;
+ module_ident; required_globals = Ident.Set.empty }
+ end;
+ let objfiles =
+ List.map
+ (fun m -> Filename.remove_extension m.pm_file ^ Config.ext_obj)
+ (List.filter (fun m -> m.pm_kind <> PM_intf) members) in
+ let ok =
+ Ccomp.call_linker Ccomp.Partial targetobj (objtemp :: objfiles) ""
in
- Asmgen.compile_implementation_flambda ~source_provenance
- prefixname ~backend ~required_globals:Ident.Set.empty ppf flam;
- end else begin
- let main_module_block_size, code =
- Translmod.transl_store_package
- components (Ident.create_persistent targetname) coercion in
- Asmgen.compile_implementation_clambda ~source_provenance
- prefixname ppf { Lambda.code; main_module_block_size;
- module_ident; required_globals = Ident.Set.empty }
- end;
- let objfiles =
- List.map
- (fun m -> Filename.remove_extension m.pm_file ^ Config.ext_obj)
- (List.filter (fun m -> m.pm_kind <> PM_intf) members) in
- let ok =
- Ccomp.call_linker Ccomp.Partial targetobj (objtemp :: objfiles) ""
- in
- remove_file objtemp;
- if not ok then raise(Error Linking_error)
-
+ remove_file objtemp;
+ if not ok then raise(Error Linking_error)
+ )
(* Make the .cmx file for the package *)
let get_export_info ui =
(* Set the name of the current "input" *)
Location.input_name := targetcmx;
(* Set the name of the current compunit *)
- Compilenv.reset ~source_provenance:(Timings.Pack targetname)
- ?packname:!Clflags.for_package targetname;
+ Compilenv.reset ?packname:!Clflags.for_package targetname;
try
let coercion =
Typemod.package_units initial_env files targetcmi targetname in
| Ulet of mutable_flag * value_kind * Ident.t * ulambda * ulambda
| Uletrec of (Ident.t * ulambda) list * ulambda
| Uprim of primitive * ulambda list * Debuginfo.t
- | Uswitch of ulambda * ulambda_switch
+ | Uswitch of ulambda * ulambda_switch * Debuginfo.t
| Ustringswitch of ulambda * (string * ulambda) list * ulambda option
| Ustaticfail of int * ulambda list
| Ucatch of int * Ident.t list * ulambda * ulambda
| Ulet of mutable_flag * value_kind * Ident.t * ulambda * ulambda
| Uletrec of (Ident.t * ulambda) list * ulambda
| Uprim of primitive * ulambda list * Debuginfo.t
- | Uswitch of ulambda * ulambda_switch
+ | Uswitch of ulambda * ulambda_switch * Debuginfo.t
| Ustringswitch of ulambda * (string * ulambda) list * ulambda option
| Ustaticfail of int * ulambda list
| Ucatch of int * Ident.t list * ulambda * ulambda
type t = lambda
type key = lambda
let make_key = Lambda.make_key
+ let compare_key = Pervasives.compare
end)
(* Auxiliaries for compiling functions *)
| Uletrec(decls, body) ->
List.exists (fun (_id, u) -> occurs u) decls || occurs body
| Uprim(_p, args, _) -> List.exists occurs args
- | Uswitch(arg, s) ->
+ | Uswitch(arg, s, _dbg) ->
occurs arg ||
occurs_array s.us_actions_consts || occurs_array s.us_actions_blocks
| Ustringswitch(arg,sw,d) ->
| Uprim(prim, args, _) ->
size := !size + prim_size prim args;
lambda_list_size args
- | Uswitch(lam, cases) ->
+ | Uswitch(lam, cases, _dbg) ->
if Array.length cases.us_actions_consts > 1 then size := !size + 5 ;
if Array.length cases.us_actions_blocks > 1 then size := !size + 5 ;
lambda_size lam;
let (res, _) =
simplif_prim fpc p (sargs, List.map approx_ulam sargs) dbg in
res
- | Uswitch(arg, sw) ->
+ | Uswitch(arg, sw, dbg) ->
let sarg = substitute loc fpc sb arg in
let action =
(* Unfortunately, we cannot easily deal with the
Array.map (substitute loc fpc sb) sw.us_actions_consts;
us_actions_blocks =
Array.map (substitute loc fpc sb) sw.us_actions_blocks;
- })
+ },
+ dbg)
end
| Ustringswitch(arg,sw,d) ->
Ustringswitch
let dbg = Debuginfo.from_location loc in
simplif_prim !Clflags.float_const_prop
p (close_list_approx fenv cenv args) dbg
- | Lswitch(arg, sw) ->
+ | Lswitch(arg, sw, dbg) ->
let fn fail =
let (uarg, _) = close fenv cenv arg in
let const_index, const_actions, fconst =
{us_index_consts = const_index;
us_actions_consts = const_actions;
us_index_blocks = block_index;
- us_actions_blocks = block_actions}) in
+ us_actions_blocks = block_actions},
+ Debuginfo.from_location dbg)
+ in
(fconst (fblock ulam),Value_unknown) in
(* NB: failaction might get copied, thus it should be some Lstaticraise *)
let fail = sw.sw_failaction in
| Ulet (_str, _kind, _, u1, u2) -> ulam u1; ulam u2
| Uletrec (l, u) -> List.iter (fun (_, u) -> ulam u) l; ulam u
| Uprim (_, ul, _) -> List.iter ulam ul
- | Uswitch (u, sl) ->
+ | Uswitch (u, sl, _dbg) ->
ulam u;
Array.iter ulam sl.us_actions_consts;
Array.iter ulam sl.us_actions_blocks
match i with
Cconst_int n ->
int_const n
- | Cop(Casr, [c; Cconst_int n], dbg) when n > 0 ->
- Cop(Cor, [asr_int c (Cconst_int (n - 1)) dbg; Cconst_int 1], dbg)
+ | Cop(Casr, [c; Cconst_int n], dbg') when n > 0 ->
+ Cop(Cor, [asr_int c (Cconst_int (n - 1)) dbg'; Cconst_int 1], dbg)
| c ->
Cop(Cor, [lsl_int c (Cconst_int 1) dbg; Cconst_int 1], dbg)
| Cop(Cor, [c; Cconst_int 1], _) -> Cop(Casr, [c; Cconst_int 1], dbg)
| c -> Cop(Casr, [c; Cconst_int 1], dbg)
-let if_then_else (cond, ifso, ifnot) =
+(* Description of the "then" and "else" continuations in [transl_if]. If
+ the "then" continuation is true and the "else" continuation is false then
+ we can use the condition directly as the result. Similarly, if the "then"
+ continuation is false and the "else" continuation is true then we can use
+ the negation of the condition directly as the result. *)
+type then_else =
+ | Then_true_else_false
+ | Then_false_else_true
+ | Unknown
+
+let invert_then_else = function
+ | Then_true_else_false -> Then_false_else_true
+ | Then_false_else_true -> Then_true_else_false
+ | Unknown -> Unknown
+
+let mk_if_then_else cond ifso ifnot =
match cond with
| Cconst_int 0 -> ifnot
| Cconst_int 1 -> ifso
| _ ->
Cifthenelse(cond, ifso, ifnot)
+let mk_not dbg cmm =
+ match cmm with
+ | Cop(Caddi, [Cop(Clsl, [c; Cconst_int 1], _); Cconst_int 1], dbg') -> begin
+ match c with
+ | Cop(Ccmpi cmp, [c1; c2], dbg'') ->
+ tag_int (Cop(Ccmpi (negate_comparison cmp), [c1; c2], dbg'')) dbg'
+ | Cop(Ccmpa cmp, [c1; c2], dbg'') ->
+ tag_int (Cop(Ccmpa (negate_comparison cmp), [c1; c2], dbg'')) dbg'
+ | Cop(Ccmpf cmp, [c1; c2], dbg'') ->
+ tag_int (Cop(Ccmpf (negate_comparison cmp), [c1; c2], dbg'')) dbg'
+ | _ ->
+ (* 0 -> 3, 1 -> 1 *)
+ Cop(Csubi, [Cconst_int 3; Cop(Clsl, [c; Cconst_int 1], dbg)], dbg)
+ end
+ | Cconst_int 3 -> Cconst_int 1
+ | Cconst_int 1 -> Cconst_int 3
+ | c ->
+ (* 1 -> 3, 3 -> 1 *)
+ Cop(Csubi, [Cconst_int 4; c], dbg)
+
+
(* Turning integer divisions into multiply-high then shift.
The [division_parameters] function is used in module Emit for
those target platforms that support this optimization. *)
| Cifthenelse(cond, e1, e2) ->
Cifthenelse(cond, unbox_float dbg e1, unbox_float dbg e2)
| Csequence(e1, e2) -> Csequence(e1, unbox_float dbg e2)
- | Cswitch(e, tbl, el, dbg) ->
- Cswitch(e, tbl, Array.map (unbox_float dbg) el, dbg)
+ | Cswitch(e, tbl, el, dbg') ->
+ Cswitch(e, tbl, Array.map (unbox_float dbg) el, dbg')
| Ccatch(rec_flag, handlers, body) ->
map_ccatch (unbox_float dbg) rec_flag handlers body
| Ctrywith(e1, id, e2) -> Ctrywith(unbox_float dbg e1, id, unbox_float dbg e2)
| Cconst_int n ->
let i = n asr 1 in
if i = 0 then ptr else Cop(add, [ptr; Cconst_int(i lsl log2size)], dbg)
- | Cop(Caddi, [Cop(Clsl, [c; Cconst_int 1], _); Cconst_int 1], _) ->
- Cop(add, [ptr; lsl_const c log2size dbg], dbg)
- | Cop(Caddi, [c; Cconst_int n], _) when log2size = 0 ->
+ | Cop(Caddi, [Cop(Clsl, [c; Cconst_int 1], _); Cconst_int 1], dbg') ->
+ Cop(add, [ptr; lsl_const c log2size dbg], dbg')
+ | Cop(Caddi, [c; Cconst_int n], dbg') when log2size = 0 ->
Cop(add, [Cop(add, [ptr; untag_int c dbg], dbg); Cconst_int (n asr 1)],
- dbg)
+ dbg')
| Cop(Caddi, [c; Cconst_int n], _) ->
Cop(add, [Cop(add, [ptr; lsl_const c (log2size - 1) dbg], dbg);
Cconst_int((n-1) lsl (log2size - 1))], dbg)
RHS_block (fundecls_size fundecls + List.length clos_vars)
| Ulet(_str, _kind, id, exp, body) ->
expr_size (Ident.add id (expr_size env exp) env) body
- | Uletrec(_bindings, body) ->
+ | Uletrec(bindings, body) ->
+ let env =
+ List.fold_right
+ (fun (id, exp) env -> Ident.add id (expr_size env exp) env)
+ bindings env
+ in
expr_size env body
| Uprim(Pmakeblock _, args, _) ->
RHS_block (List.length args)
RHS_block (List.length args)
| Uprim(Pmakearray(Pfloatarray, _), args, _) ->
RHS_floatblock (List.length args)
+ | Uprim(Pmakearray(Pgenarray, _), _, _) ->
+ (* Pgenarray is excluded from recursive bindings by the
+ check in Translcore.check_recursive_lambda *)
+ RHS_nonrec
| Uprim (Pduprecord ((Record_regular | Record_inlined _), sz), _, _) ->
RHS_block sz
| Uprim (Pduprecord (Record_unboxed _, _), _, _) ->
let rec unbox_int bi arg dbg =
match arg with
- Cop(Calloc, [_hdr; _ops; Cop(Clsl, [contents; Cconst_int 32], dbg')], dbg)
+ Cop(Calloc, [_hdr; _ops; Cop(Clsl, [contents; Cconst_int 32], dbg')], _dbg)
when bi = Pint32 && size_int = 8 && big_endian ->
(* Force sign-extension of low 32 bits *)
Cop(Casr, [Cop(Clsl, [contents; Cconst_int 32], dbg'); Cconst_int 32],
dbg)
- | Cop(Calloc, [_hdr; _ops; contents], dbg)
+ | Cop(Calloc, [_hdr; _ops; contents], _dbg)
when bi = Pint32 && size_int = 8 && not big_endian ->
(* Force sign-extension of low 32 bits *)
Cop(Casr, [Cop(Clsl, [contents; Cconst_int 32], dbg); Cconst_int 32], dbg)
| Cifthenelse(cond, e1, e2) ->
Cifthenelse(cond, unbox_int bi e1 dbg, unbox_int bi e2 dbg)
| Csequence(e1, e2) -> Csequence(e1, unbox_int bi e2 dbg)
- | Cswitch(e, tbl, el, dbg) ->
- Cswitch(e, tbl, Array.map (fun e -> unbox_int bi e dbg) el, dbg)
+ | Cswitch(e, tbl, el, dbg') ->
+ Cswitch(e, tbl, Array.map (fun e -> unbox_int bi e dbg) el, dbg')
| Ccatch(rec_flag, handlers, body) ->
map_ccatch (fun e -> unbox_int bi e dbg) rec_flag handlers body
| Ctrywith(e1, id, e2) ->
let make_isout h arg = Cop (Ccmpa Clt, [h ; arg], Debuginfo.none)
let make_isin h arg = Cop (Ccmpa Cge, [h ; arg], Debuginfo.none)
let make_if cond ifso ifnot = Cifthenelse (cond, ifso, ifnot)
- let make_switch arg cases actions =
- make_switch arg cases actions Debuginfo.none
+ let make_switch loc arg cases actions =
+ make_switch arg cases actions (Debuginfo.from_location loc)
let bind arg body = bind "switcher" arg body
let make_catch handler = match handler with
let make_key = function
| Cexit (i,[]) -> Some i
| _ -> None
+ let compare_key = Pervasives.compare
end)
module SwitcherBlocks = Switch.Make(SArgBlocks)
(* Int switcher, arg in [low..high],
cases is list of individual cases, and is sorted by first component *)
-let transl_int_switch arg low high cases default = match cases with
+let transl_int_switch loc arg low high cases default = match cases with
| [] -> assert false
| _::_ ->
let store = StoreExp.mk_store () in
bind "switcher" arg
(fun a ->
SwitcherBlocks.zyva
+ loc
(low,high)
a
(Array.of_list inters) store)
end
| Ulet (_, _, _, _, e) | Uletrec (_, e) | Usequence (_, e) ->
is_unboxed_number ~strict env e
- | Uswitch (_, switch) ->
+ | Uswitch (_, switch, _dbg) ->
let k = Array.fold_left join No_result switch.us_actions_consts in
Array.fold_left join k switch.us_actions_blocks
| Ustringswitch (_, actions, default_opt) ->
List.iter (fun f -> Queue.add f functions) fundecls;
Cconst_symbol lbl
| Uclosure(fundecls, clos_vars) ->
- let block_size =
- fundecls_size fundecls + List.length clos_vars in
let rec transl_fundecls pos = function
[] ->
List.map (transl env) clos_vars
| f :: rem ->
Queue.add f functions;
- let header =
- if pos = 0
- then alloc_closure_header block_size f.dbg
- else alloc_infix_header pos f.dbg in
- if f.arity = 1 || f.arity = 0 then
- header ::
- Cconst_symbol f.label ::
- int_const f.arity ::
- transl_fundecls (pos + 3) rem
- else
- header ::
- Cconst_symbol(curry_function f.arity) ::
- int_const f.arity ::
- Cconst_symbol f.label ::
- transl_fundecls (pos + 4) rem in
- Cop(Calloc, transl_fundecls 0 fundecls, Debuginfo.none)
+ let without_header =
+ if f.arity = 1 || f.arity = 0 then
+ Cconst_symbol f.label ::
+ int_const f.arity ::
+ transl_fundecls (pos + 3) rem
+ else
+ Cconst_symbol(curry_function f.arity) ::
+ int_const f.arity ::
+ Cconst_symbol f.label ::
+ transl_fundecls (pos + 4) rem
+ in
+ if pos = 0 then without_header
+ else (alloc_infix_header pos f.dbg) :: without_header
+ in
+ let dbg =
+ match fundecls with
+ | [] -> Debuginfo.none
+ | fundecl::_ -> fundecl.dbg
+ in
+ make_alloc dbg Obj.closure_tag (transl_fundecls 0 fundecls)
| Uoffset(arg, offset) ->
(* produces a valid Caml value, pointing just after an infix header *)
let ptr = transl env arg in
end
(* Control structures *)
- | Uswitch(arg, s) ->
- let dbg = Debuginfo.none in
+ | Uswitch(arg, s, dbg) ->
+ let loc = Debuginfo.to_location dbg in
(* As in the bytecode interpreter, only matching against constants
can be checked *)
if Array.length s.us_index_blocks = 0 then
(Array.map (transl env) s.us_actions_consts)
dbg
else if Array.length s.us_index_consts = 0 then
- transl_switch dbg env (get_tag (transl env arg) dbg)
+ transl_switch loc env (get_tag (transl env arg) dbg)
s.us_index_blocks s.us_actions_blocks
else
bind "switch" (transl env arg) (fun arg ->
Cifthenelse(
Cop(Cand, [arg; Cconst_int 1], dbg),
- transl_switch dbg env
+ transl_switch loc env
(untag_int arg dbg) s.us_index_consts s.us_actions_consts,
- transl_switch dbg env
+ transl_switch loc env
(get_tag arg dbg) s.us_index_blocks s.us_actions_blocks))
| Ustringswitch(arg,sw,d) ->
let dbg = Debuginfo.none in
ccatch(nfail, ids, transl env body, transl env handler)
| Utrywith(body, exn, handler) ->
Ctrywith(transl env body, exn, transl env handler)
- | Uifthenelse(Uprim(Pnot, [arg], _), ifso, ifnot) ->
- transl env (Uifthenelse(arg, ifnot, ifso))
- | Uifthenelse(cond, ifso, Ustaticfail (nfail, [])) ->
- let dbg = Debuginfo.none in
- exit_if_false dbg env cond (transl env ifso) nfail
- | Uifthenelse(cond, Ustaticfail (nfail, []), ifnot) ->
- let dbg = Debuginfo.none in
- exit_if_true dbg env cond nfail (transl env ifnot)
- | Uifthenelse(Uprim(Psequand, _, dbg) as cond, ifso, ifnot) ->
- let raise_num = next_raise_count () in
- make_catch
- raise_num
- (exit_if_false dbg env cond (transl env ifso) raise_num)
- (transl env ifnot)
- | Uifthenelse(Uprim(Psequor, _, dbg) as cond, ifso, ifnot) ->
- let raise_num = next_raise_count () in
- make_catch
- raise_num
- (exit_if_true dbg env cond raise_num (transl env ifnot))
- (transl env ifso)
- | Uifthenelse (Uifthenelse (cond, condso, condnot), ifso, ifnot) ->
- let dbg = Debuginfo.none in
- let num_true = next_raise_count () in
- make_catch
- num_true
- (make_catch2
- (fun shared_false ->
- if_then_else
- (test_bool dbg (transl env cond),
- exit_if_true dbg env condso num_true shared_false,
- exit_if_true dbg env condnot num_true shared_false))
- (transl env ifnot))
- (transl env ifso)
| Uifthenelse(cond, ifso, ifnot) ->
let dbg = Debuginfo.none in
- if_then_else(test_bool dbg (transl env cond), transl env ifso,
- transl env ifnot)
+ transl_if env cond dbg Unknown
+ (transl env ifso) (transl env ifnot)
| Usequence(exp1, exp2) ->
Csequence(remove_unit(transl env exp1), transl env exp2)
| Uwhile(cond, body) ->
return_unit
(ccatch
(raise_num, [],
- Cloop(exit_if_false dbg env cond
- (remove_unit(transl env body)) raise_num),
+ Cloop(transl_if env cond dbg Unknown
+ (remove_unit(transl env body))
+ (Cexit (raise_num,[]))),
Ctuple []))
| Ufor(id, low, high, dir, body) ->
let dbg = Debuginfo.none in
| Pnegint ->
Cop(Csubi, [Cconst_int 2; transl env arg], dbg)
| Pctconst c ->
- let const_of_bool b = tag_int (Cconst_int (if b then 1 else 0)) dbg in
+ let const_of_bool b = int_const (if b then 1 else 0) in
begin
match c with
| Big_endian -> const_of_bool Arch.big_endian
- | Word_size -> tag_int (Cconst_int (8*Arch.size_int)) dbg
- | Int_size -> tag_int (Cconst_int ((8*Arch.size_int) - 1)) dbg
- | Max_wosize ->
- tag_int (Cconst_int ((1 lsl ((8*Arch.size_int) - 10)) - 1 )) dbg
+ | Word_size -> int_const (8*Arch.size_int)
+ | Int_size -> int_const (8*Arch.size_int - 1)
+ | Max_wosize -> int_const ((1 lsl ((8*Arch.size_int) - 10)) - 1)
| Ostype_unix -> const_of_bool (Sys.os_type = "Unix")
| Ostype_win32 -> const_of_bool (Sys.os_type = "Win32")
| Ostype_cygwin -> const_of_bool (Sys.os_type = "Cygwin")
- | Backend_type ->
- tag_int (Cconst_int 0) dbg (* tag 0 is the same as Native here *)
+ | Backend_type -> int_const 0 (* tag 0 is the same as Native here *)
end
| Poffsetint n ->
if no_overflow_lsl n 1 then
end
(* Boolean operations *)
| Pnot ->
- Cop(Csubi, [Cconst_int 4; transl env arg], dbg) (* 1 -> 3, 3 -> 1 *)
+ transl_if env arg dbg Then_false_else_true
+ (Cconst_pointer 1) (Cconst_pointer 3)
(* Test integer/block *)
| Pisint ->
tag_int(Cop(Cand, [transl env arg; Cconst_int 1], dbg)) dbg
(* Boolean operations *)
| Psequand ->
- if_then_else(test_bool dbg (transl env arg1),
- transl env arg2, Cconst_int 1)
+ let dbg' = Debuginfo.none in
+ transl_sequand env arg1 dbg arg2 dbg' Then_true_else_false
+ (Cconst_pointer 3) (Cconst_pointer 1)
(* let id = Ident.create "res1" in
Clet(id, transl env arg1,
Cifthenelse(test_bool dbg (Cvar id), transl env arg2, Cvar id)) *)
| Psequor ->
- if_then_else(test_bool dbg (transl env arg1),
- Cconst_int 3, transl env arg2)
-
+ let dbg' = Debuginfo.none in
+ transl_sequor env arg1 dbg arg2 dbg' Then_true_else_false
+ (Cconst_pointer 3) (Cconst_pointer 1)
(* Integer operations *)
| Paddint ->
decr_int(add_int (transl env arg1) (transl env arg2) dbg) dbg
| Cexit (nexit,[]) when nexit=ncatch -> handler
| _ -> ccatch (ncatch, [], body, handler)
-and make_catch2 mk_body handler = match handler with
-| Cexit (_,[])|Ctuple []|Cconst_int _|Cconst_pointer _ ->
- mk_body handler
-| _ ->
+and is_shareable_cont exp =
+ match exp with
+ | Cexit (_,[]) -> true
+ | _ -> false
+
+and make_shareable_cont mk exp =
+ if is_shareable_cont exp then mk exp
+ else begin
let nfail = next_raise_count () in
make_catch
nfail
- (mk_body (Cexit (nfail,[])))
- handler
-
-and exit_if_true dbg env cond nfail otherwise =
- match cond with
- | Uconst (Uconst_ptr 0) -> otherwise
- | Uconst (Uconst_ptr 1) -> Cexit (nfail,[])
- | Uifthenelse (arg1, Uconst (Uconst_ptr 1), arg2)
- | Uprim(Psequor, [arg1; arg2], _) ->
- exit_if_true dbg env arg1 nfail
- (exit_if_true dbg env arg2 nfail otherwise)
- | Uifthenelse (_, _, Uconst (Uconst_ptr 0))
- | Uprim(Psequand, _, _) ->
- begin match otherwise with
- | Cexit (raise_num,[]) ->
- exit_if_false dbg env cond (Cexit (nfail,[])) raise_num
- | _ ->
- let raise_num = next_raise_count () in
- make_catch
- raise_num
- (exit_if_false dbg env cond (Cexit (nfail,[])) raise_num)
- otherwise
- end
- | Uprim(Pnot, [arg], _) ->
- exit_if_false dbg env arg otherwise nfail
- | Uifthenelse (cond, ifso, ifnot) ->
- make_catch2
- (fun shared ->
- if_then_else
- (test_bool dbg (transl env cond),
- exit_if_true dbg env ifso nfail shared,
- exit_if_true dbg env ifnot nfail shared))
- otherwise
- | _ ->
- if_then_else(test_bool dbg (transl env cond),
- Cexit (nfail, []), otherwise)
+ (mk (Cexit (nfail,[])))
+ exp
+ end
-and exit_if_false dbg env cond otherwise nfail =
+and transl_if env cond dbg approx then_ else_ =
match cond with
- | Uconst (Uconst_ptr 0) -> Cexit (nfail,[])
- | Uconst (Uconst_ptr 1) -> otherwise
- | Uifthenelse (arg1, arg2, Uconst (Uconst_ptr 0))
- | Uprim(Psequand, [arg1; arg2], _) ->
- exit_if_false dbg env arg1
- (exit_if_false dbg env arg2 otherwise nfail) nfail
- | Uifthenelse (_, Uconst (Uconst_ptr 1), _)
- | Uprim(Psequor, _, _) ->
- begin match otherwise with
- | Cexit (raise_num,[]) ->
- exit_if_true dbg env cond raise_num (Cexit (nfail,[]))
- | _ ->
- let raise_num = next_raise_count () in
- make_catch
- raise_num
- (exit_if_true dbg env cond raise_num (Cexit (nfail,[])))
- otherwise
- end
+ | Uconst (Uconst_ptr 0) -> else_
+ | Uconst (Uconst_ptr 1) -> then_
+ | Uifthenelse (arg1, arg2, Uconst (Uconst_ptr 0)) ->
+ let dbg' = Debuginfo.none in
+ transl_sequand env arg1 dbg' arg2 dbg approx then_ else_
+ | Uprim(Psequand, [arg1; arg2], dbg') ->
+ transl_sequand env arg1 dbg' arg2 dbg approx then_ else_
+ | Uifthenelse (arg1, Uconst (Uconst_ptr 1), arg2) ->
+ let dbg' = Debuginfo.none in
+ transl_sequor env arg1 dbg' arg2 dbg approx then_ else_
+ | Uprim(Psequor, [arg1; arg2], dbg') ->
+ transl_sequor env arg1 dbg' arg2 dbg approx then_ else_
| Uprim(Pnot, [arg], _) ->
- exit_if_true dbg env arg nfail otherwise
+ transl_if env arg dbg (invert_then_else approx) else_ then_
+ | Uifthenelse (Uconst (Uconst_ptr 1), ifso, _) ->
+ transl_if env ifso dbg approx then_ else_
+ | Uifthenelse (Uconst (Uconst_ptr 0), _, ifnot) ->
+ transl_if env ifnot dbg approx then_ else_
| Uifthenelse (cond, ifso, ifnot) ->
- make_catch2
- (fun shared ->
- if_then_else
- (test_bool dbg (transl env cond),
- exit_if_false dbg env ifso shared nfail,
- exit_if_false dbg env ifnot shared nfail))
- otherwise
- | _ ->
- if_then_else (test_bool dbg (transl env cond), otherwise,
- Cexit (nfail, []))
+ make_shareable_cont
+ (fun shareable_then ->
+ make_shareable_cont
+ (fun shareable_else ->
+ mk_if_then_else
+ (test_bool dbg (transl env cond))
+ (transl_if env ifso dbg approx
+ shareable_then shareable_else)
+ (transl_if env ifnot dbg approx
+ shareable_then shareable_else))
+ else_)
+ then_
+ | _ -> begin
+ match approx with
+ | Then_true_else_false ->
+ transl env cond
+ | Then_false_else_true ->
+ mk_not dbg (transl env cond)
+ | Unknown ->
+ mk_if_then_else (test_bool dbg (transl env cond)) then_ else_
+ end
-and transl_switch _dbg env arg index cases = match Array.length cases with
+and transl_sequand env arg1 dbg1 arg2 dbg2 approx then_ else_ =
+ make_shareable_cont
+ (fun shareable_else ->
+ transl_if env arg1 dbg1 Unknown
+ (transl_if env arg2 dbg2 approx then_ shareable_else)
+ shareable_else)
+ else_
+
+and transl_sequor env arg1 dbg1 arg2 dbg2 approx then_ else_ =
+ make_shareable_cont
+ (fun shareable_then ->
+ transl_if env arg1 dbg1 Unknown
+ shareable_then
+ (transl_if env arg2 dbg2 approx shareable_then else_))
+ then_
+
+and transl_switch loc env arg index cases = match Array.length cases with
| 0 -> fatal_error "Cmmgen.transl_switch"
| 1 -> transl env cases.(0)
| _ ->
bind "switcher" arg
(fun a ->
SwitcherBlocks.zyva
+ loc
(0,n_index-1)
a
(Array.of_list inters) store)
(Set_of_closures_id.Tbl.create 10
: Flambda.function_declarations option Set_of_closures_id.Tbl.t)
-let sourcefile = ref None
-
module CstMap =
Map.Make(struct
type t = Clambda.ustructured_constant
let current_unit_linkage_name () =
Linkage_name.create (make_symbol ~unitname:current_unit.ui_symbol None)
-let reset ?packname ~source_provenance:file name =
+let reset ?packname name =
Hashtbl.clear global_infos_table;
Set_of_closures_id.Tbl.clear imported_sets_of_closures_table;
let symbol = symbolname_for_pack packname name in
- sourcefile := Some file;
current_unit.ui_name <- name;
current_unit.ui_symbol <- symbol;
current_unit.ui_defines <- [symbol];
let current_unit_name () =
current_unit.ui_name
-let current_build () =
- match !sourcefile with
- | None -> assert false
- | Some v -> v
-
let make_symbol ?(unitname = current_unit.ui_symbol) idopt =
let prefix = "caml" ^ unitname in
match idopt with
: Flambda.function_declarations option Set_of_closures_id.Tbl.t
(* flambda-only *)
-val reset: ?packname:string -> source_provenance:Timings.source_provenance ->
- string -> unit
+val reset: ?packname:string -> string -> unit
(* Reset the environment and record the name of the unit being
compiled (arg). Optional argument is [-for-pack] prefix. *)
(* Return the linkage_name of the unit being compiled.
flambda-only *)
-val current_build: unit -> Timings.source_provenance
- (* Return the kind of build source being compiled. If it is a
- file compilation it also provides the filename. *)
-
val current_unit: unit -> Compilation_unit.t
(* flambda-only *)
(* Record the informations of the unit being compiled
flambda-only *)
val approx_env: unit -> Export_info.t
- (* Returns all the information loaded from extenal compilation units
+ (* Returns all the information loaded from external compilation units
flambda-only *)
val approx_for_global: Compilation_unit.t -> Export_info.t
(* Loads the exported information declaring the compilation_unit
val new_structured_constant:
Clambda.ustructured_constant ->
- shared:bool -> (* can be shared with another structually equal constant *)
+ shared:bool -> (* can be shared with another structurally equal constant *)
string
val structured_constants:
unit -> Clambda.preallocated_constant list
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Mark Shinwell and Thomas Refis, Jane Street Europe *)
+(* *)
+(* Copyright 2013--2017 Jane Street Group LLC *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+[@@@ocaml.warning "+a-4-9-30-40-41-42"]
+
+module M = Mach
+module R = Reg
+module RAS = Reg_availability_set
+module RD = Reg_with_debug_info
+
+(* This pass treats [avail_at_exit] like a "result" structure whereas the
+ equivalent in [Liveness] is like an "environment". (Which means we need
+ to be careful not to throw away information about further-out catch
+ handlers collected in [avail_at_exit].) *)
+let avail_at_exit = Hashtbl.create 42
+let avail_at_raise = ref RAS.Unreachable
+
+let augment_availability_at_raise avail =
+ avail_at_raise := RAS.inter avail !avail_at_raise
+
+let check_invariants (instr : M.instruction) ~(avail_before : RAS.t) =
+ match avail_before with
+ | Unreachable -> ()
+ | Ok avail_before ->
+ (* Every register that is live across an instruction should also be
+ available before the instruction. *)
+ if not (R.Set.subset instr.live (RD.Set.forget_debug_info avail_before))
+ then begin
+ Misc.fatal_errorf "Live registers not a subset of available registers: \
+ live={%a} avail_before=%a missing={%a} insn=%a"
+ Printmach.regset instr.live
+ (RAS.print ~print_reg:Printmach.reg)
+ (RAS.Ok avail_before)
+ Printmach.regset (R.Set.diff instr.live
+ (RD.Set.forget_debug_info avail_before))
+ Printmach.instr ({ instr with M. next = M.end_instr (); })
+ end;
+ (* Every register that is an input to an instruction should be
+ available. *)
+ let args = R.set_of_array instr.arg in
+ let avail_before_fdi = RD.Set.forget_debug_info avail_before in
+ if not (R.Set.subset args avail_before_fdi) then begin
+ Misc.fatal_errorf "Instruction has unavailable input register(s): \
+ avail_before=%a avail_before_fdi={%a} inputs={%a} insn=%a"
+ (RAS.print ~print_reg:Printmach.reg) (RAS.Ok avail_before)
+ Printmach.regset avail_before_fdi
+ Printmach.regset args
+ Printmach.instr ({ instr with M. next = M.end_instr (); })
+ end
+
+(* [available_regs ~instr ~avail_before] calculates, given the registers
+ "available before" an instruction [instr], the registers that are available
+ both "across" and immediately after [instr]. This is a forwards dataflow
+ analysis.
+
+ "available before" can be thought of, at the assembly level, as the set of
+ registers available when the program counter is equal to the address of the
+ particular instruction under consideration (that is to say, immediately
+ prior to the instruction being executed). Inputs to that instruction are
+ available at this point even if the instruction will clobber them. Results
+ from the previous instruction are also available at this point.
+
+ "available across" is the registers available during the execution of
+ some particular instruction. These are the registers "available before"
+ minus registers that may be clobbered or otherwise invalidated by the
+ instruction. (The notion of "available across" is only useful for [Iop]
+ instructions. Recall that some of these may expand into multiple
+ machine instructions including clobbers, e.g. for [Ialloc].)
+
+ The [available_before] and [available_across] fields of each instruction
+ is updated by this function.
+*)
+let rec available_regs (instr : M.instruction)
+ ~(avail_before : RAS.t) : RAS.t =
+ check_invariants instr ~avail_before;
+ instr.available_before <- avail_before;
+ let avail_across, avail_after =
+ let ok set = RAS.Ok set in
+ let unreachable = RAS.Unreachable in
+ match avail_before with
+ | Unreachable -> None, unreachable
+ | Ok avail_before ->
+ match instr.desc with
+ | Iend -> None, ok avail_before
+ | Ireturn -> None, unreachable
+ | Iop (Itailcall_ind _) | Iop (Itailcall_imm _) ->
+ Some (ok Reg_with_debug_info.Set.empty), unreachable
+ | Iop (Iname_for_debugger { ident; which_parameter; provenance;
+ is_assignment; }) ->
+ (* First forget about any existing debug info to do with [ident]
+ if the naming corresponds to an assignment operation. *)
+ let forgetting_ident =
+ if not is_assignment then
+ avail_before
+ else
+ RD.Set.map (fun reg ->
+ match RD.debug_info reg with
+ | None -> reg
+ | Some debug_info ->
+ if Ident.same (RD.Debug_info.holds_value_of debug_info) ident
+ then RD.clear_debug_info reg
+ else reg)
+ avail_before
+ in
+ let avail_after = ref forgetting_ident in
+ let num_parts_of_value = Array.length instr.arg in
+ (* Add debug info about [ident], but only for registers that are known
+ to be available. *)
+ for part_of_value = 0 to num_parts_of_value - 1 do
+ let reg = instr.arg.(part_of_value) in
+ if RD.Set.mem_reg forgetting_ident reg then begin
+ let regd =
+ RD.create ~reg
+ ~holds_value_of:ident
+ ~part_of_value
+ ~num_parts_of_value
+ ~which_parameter
+ ~provenance
+ in
+ avail_after := RD.Set.add regd (RD.Set.filter_reg !avail_after reg)
+ end
+ done;
+ Some (ok avail_before), ok !avail_after
+ | Iop (Imove | Ireload | Ispill) ->
+ (* Moves are special: they enable us to propagate names.
+ No-op moves need to be handled specially---in this case, we may
+ learn that a given hard register holds the value of multiple
+ pseudoregisters (all of which have the same value). This makes us
+ match up properly with [Liveness]. *)
+ let move_to_same_location =
+ let move_to_same_location = ref true in
+ for i = 0 to Array.length instr.arg - 1 do
+ let arg = instr.arg.(i) in
+ let res = instr.res.(i) in
+ (* Note that the register classes must be the same, so we don't
+ need to check that. *)
+ if arg.loc <> res.loc then begin
+ move_to_same_location := false
+ end
+ done;
+ !move_to_same_location
+ in
+ let made_unavailable =
+ if move_to_same_location then
+ RD.Set.empty
+ else
+ RD.Set.made_unavailable_by_clobber avail_before
+ ~regs_clobbered:instr.res
+ ~register_class:Proc.register_class
+ in
+ let results =
+ Array.map2 (fun arg_reg result_reg ->
+ match RD.Set.find_reg_exn avail_before arg_reg with
+ | exception Not_found ->
+ assert false (* see second invariant in [check_invariants] *)
+ | arg_reg ->
+ RD.create_copying_debug_info ~reg:result_reg
+ ~debug_info_from:arg_reg)
+ instr.arg instr.res
+ in
+ let avail_across = RD.Set.diff avail_before made_unavailable in
+ let avail_after = RD.Set.union avail_across (RD.Set.of_array results) in
+ Some (ok avail_across), ok avail_after
+ | Iop op ->
+ (* We split the calculation of registers that become unavailable after
+ a call into two parts. First: anything that the target marks as
+ destroyed by the operation, combined with any registers that will
+ be clobbered by the operation writing out its results. *)
+ let made_unavailable_1 =
+ let regs_clobbered =
+ Array.append (Proc.destroyed_at_oper instr.desc) instr.res
+ in
+ RD.Set.made_unavailable_by_clobber avail_before ~regs_clobbered
+ ~register_class:Proc.register_class
+ in
+ (* Second: the cases of (a) allocations and (b) OCaml to OCaml function
+ calls. In these cases, since the GC may run, registers always
+ become unavailable unless:
+ (a) they are "live across" the instruction; and/or
+ (b) they hold immediates and are assigned to the stack.
+ For the moment we assume that [Ispecific] instructions do not
+ run the GC. *)
+ (* CR-someday mshinwell: Consider factoring this out from here and
+ [Available_ranges.Make_ranges.end_pos_offset]. *)
+ let made_unavailable_2 =
+ match op with
+ | Icall_ind _ | Icall_imm _ | Ialloc _ ->
+ RD.Set.filter (fun reg ->
+ let holds_immediate = RD.holds_non_pointer reg in
+ let on_stack = RD.assigned_to_stack reg in
+ let live_across = Reg.Set.mem (RD.reg reg) instr.live in
+ let remains_available =
+ live_across
+ || (holds_immediate && on_stack)
+ in
+ not remains_available)
+ avail_before
+ | _ -> RD.Set.empty
+ in
+ let made_unavailable =
+ RD.Set.union made_unavailable_1 made_unavailable_2
+ in
+ let avail_across = RD.Set.diff avail_before made_unavailable in
+ if M.operation_can_raise op then begin
+ augment_availability_at_raise (ok avail_across)
+ end;
+ let avail_after =
+ RD.Set.union
+ (RD.Set.without_debug_info (Reg.set_of_array instr.res))
+ avail_across
+ in
+ Some (ok avail_across), ok avail_after
+ | Iifthenelse (_, ifso, ifnot) -> join [ifso; ifnot] ~avail_before
+ | Iswitch (_, cases) -> join (Array.to_list cases) ~avail_before
+ | Iloop body ->
+ let avail_after = ref (ok avail_before) in
+ begin try
+ while true do
+ let avail_after' =
+ RAS.inter !avail_after
+ (available_regs body ~avail_before:!avail_after)
+ in
+ if RAS.equal !avail_after avail_after' then begin
+ raise Exit
+ end;
+ avail_after := avail_after'
+ done
+ with Exit -> ()
+ end;
+ None, unreachable
+ | Icatch (recursive, handlers, body) ->
+ List.iter (fun (nfail, _handler) ->
+ (* In case there are nested [Icatch] expressions with the same
+ handler numbers, we rely on the [Hashtbl] shadowing
+ semantics. *)
+ Hashtbl.add avail_at_exit nfail unreachable)
+ handlers;
+ let avail_after_body =
+ available_regs body ~avail_before:(ok avail_before)
+ in
+ (* CR-someday mshinwell: Consider potential efficiency speedups
+ (see suggestions from @chambart on GPR#856). *)
+ let aux (nfail, handler) (nfail', avail_at_top_of_handler) =
+ assert (nfail = nfail');
+ available_regs handler ~avail_before:avail_at_top_of_handler
+ in
+ let aux_equal (nfail, avail_before_handler)
+ (nfail', avail_before_handler') =
+ assert (nfail = nfail');
+ RAS.equal avail_before_handler avail_before_handler'
+ in
+ let rec fixpoint avail_at_top_of_handlers =
+ let avail_after_handlers =
+ List.map2 aux handlers avail_at_top_of_handlers
+ in
+ let avail_at_top_of_handlers' =
+ List.map (fun (nfail, _handler) ->
+ match Hashtbl.find avail_at_exit nfail with
+ | exception Not_found -> assert false (* see above *)
+ | avail_at_top_of_handler -> nfail, avail_at_top_of_handler)
+ handlers
+ in
+ match recursive with
+ | Nonrecursive -> avail_after_handlers
+ | Recursive ->
+ if List.for_all2 aux_equal avail_at_top_of_handlers
+ avail_at_top_of_handlers'
+ then avail_after_handlers
+ else fixpoint avail_at_top_of_handlers'
+ in
+ let init_avail_at_top_of_handlers =
+ List.map (fun (nfail, _handler) ->
+ match Hashtbl.find avail_at_exit nfail with
+ | exception Not_found -> assert false (* see above *)
+ | avail_at_top_of_handler -> nfail, avail_at_top_of_handler)
+ handlers
+ in
+ let avail_after_handlers = fixpoint init_avail_at_top_of_handlers in
+ List.iter (fun (nfail, _handler) ->
+ Hashtbl.remove avail_at_exit nfail)
+ handlers;
+ let avail_after =
+ List.fold_left (fun avail_at_join avail_after_handler ->
+ RAS.inter avail_at_join avail_after_handler)
+ avail_after_body
+ avail_after_handlers
+ in
+ None, avail_after
+ | Iexit nfail ->
+ let avail_before = ok avail_before in
+ let avail_at_top_of_handler =
+ match Hashtbl.find avail_at_exit nfail with
+ | exception Not_found -> (* also see top of [Icatch] clause above *)
+ Misc.fatal_errorf "Iexit %d not in scope of Icatch" nfail
+ | avail_at_top_of_handler -> avail_at_top_of_handler
+ in
+ let avail_at_top_of_handler =
+ RAS.inter avail_at_top_of_handler avail_before
+ in
+ Hashtbl.replace avail_at_exit nfail avail_at_top_of_handler;
+ None, unreachable
+ | Itrywith (body, handler) ->
+ let saved_avail_at_raise = !avail_at_raise in
+ avail_at_raise := unreachable;
+ let avail_before = ok avail_before in
+ let after_body = available_regs body ~avail_before in
+ let avail_before_handler =
+ match !avail_at_raise with
+ | Unreachable -> unreachable
+ | Ok avail_at_raise ->
+ let without_exn_bucket =
+ RD.Set.filter_reg avail_at_raise Proc.loc_exn_bucket
+ in
+ let with_anonymous_exn_bucket =
+ RD.Set.add (RD.create_without_debug_info ~reg:Proc.loc_exn_bucket)
+ without_exn_bucket
+ in
+ ok with_anonymous_exn_bucket
+ in
+ avail_at_raise := saved_avail_at_raise;
+ let avail_after =
+ RAS.inter after_body
+ (available_regs handler ~avail_before:avail_before_handler)
+ in
+ None, avail_after
+ | Iraise _ ->
+ let avail_before = ok avail_before in
+ augment_availability_at_raise avail_before;
+ None, unreachable
+ in
+ instr.available_across <- avail_across;
+ match instr.desc with
+ | Iend -> avail_after
+ | _ -> available_regs instr.next ~avail_before:avail_after
+
+and join branches ~avail_before =
+ let avail_before = RAS.Ok avail_before in
+ let avails = List.map (available_regs ~avail_before) branches in
+ let avail_after =
+ match avails with
+ | [] -> avail_before
+ | avail::avails -> List.fold_left RAS.inter avail avails
+ in
+ None, avail_after
+
+let fundecl (f : M.fundecl) =
+ if !Clflags.debug && !Clflags.debug_runavail then begin
+ assert (Hashtbl.length avail_at_exit = 0);
+ avail_at_raise := RAS.Unreachable;
+ let fun_args = R.set_of_array f.fun_args in
+ let avail_before = RAS.Ok (RD.Set.without_debug_info fun_args) in
+ ignore ((available_regs f.fun_body ~avail_before) : RAS.t);
+ end;
+ f
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Mark Shinwell and Thomas Refis, Jane Street Europe *)
+(* *)
+(* Copyright 2013--2017 Jane Street Group LLC *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(** Available registers analysis used to determine which variables may be
+ shown in the debugger. *)
+
+val fundecl : Mach.fundecl -> Mach.fundecl
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Mark Shinwell, Jane Street Europe *)
+(* *)
+(* Copyright 2016--2017 Jane Street Group LLC *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+[@@@ocaml.warning "+a-4-9-30-40-41-42"]
+
+module RD = Reg_with_debug_info
+
+type t =
+ | Ok of RD.Set.t
+ | Unreachable
+
+let inter regs1 regs2 =
+ match regs1, regs2 with
+ | Unreachable, _ -> regs2
+ | _, Unreachable -> regs1
+ | Ok avail1, Ok avail2 ->
+ let result =
+ RD.Set.fold (fun reg1 result ->
+ match RD.Set.find_reg_exn avail2 (RD.reg reg1) with
+ | exception Not_found -> result
+ | reg2 ->
+ let debug_info1 = RD.debug_info reg1 in
+ let debug_info2 = RD.debug_info reg2 in
+ let debug_info =
+ match debug_info1, debug_info2 with
+ | None, None -> None
+ (* Example for this next case: the value of a mutable variable x
+ is copied into another variable y; then there is a conditional
+ where on one branch x is assigned and on the other branch it
+ is not. This means that on the former branch we have
+ forgotten about y holding the value of x; but we have not on
+ the latter. At the join point we must have forgotten the
+ information. *)
+ | None, Some _ | Some _, None -> None
+ | Some debug_info1, Some debug_info2 ->
+ if RD.Debug_info.compare debug_info1 debug_info2 = 0 then
+ Some debug_info1
+ else
+ None
+ in
+ let reg =
+ RD.create_with_debug_info ~reg:(RD.reg reg1)
+ ~debug_info
+ in
+ RD.Set.add reg result)
+ avail1
+ RD.Set.empty
+ in
+ Ok result
+
+let equal t1 t2 =
+ match t1, t2 with
+ | Unreachable, Unreachable -> true
+ | Unreachable, Ok _ | Ok _, Unreachable -> false
+ | Ok regs1, Ok regs2 -> RD.Set.equal regs1 regs2
+
+let canonicalise availability =
+ match availability with
+ | Unreachable -> Unreachable
+ | Ok availability ->
+ let regs_by_ident = Ident.Tbl.create 42 in
+ RD.Set.iter (fun reg ->
+ match RD.debug_info reg with
+ | None -> ()
+ | Some debug_info ->
+ let name = RD.Debug_info.holds_value_of debug_info in
+ if not (Ident.persistent name) then begin
+ match Ident.Tbl.find regs_by_ident name with
+ | exception Not_found -> Ident.Tbl.add regs_by_ident name reg
+ | (reg' : RD.t) ->
+ (* We prefer registers that are assigned to the stack since
+ they probably give longer available ranges (less likely to
+ be clobbered). *)
+ match RD.location reg, RD.location reg' with
+ | Reg _, Stack _
+ | Reg _, Reg _
+ | Stack _, Stack _
+ | _, Unknown
+ | Unknown, _ -> ()
+ | Stack _, Reg _ ->
+ Ident.Tbl.remove regs_by_ident name;
+ Ident.Tbl.add regs_by_ident name reg
+ end)
+ availability;
+ let result =
+ Ident.Tbl.fold (fun _ident reg availability ->
+ RD.Set.add reg availability)
+ regs_by_ident
+ RD.Set.empty
+ in
+ Ok result
+
+let print ~print_reg ppf = function
+ | Unreachable -> Format.fprintf ppf "<unreachable>"
+ | Ok availability ->
+ Format.fprintf ppf "{%a}"
+ (Format.pp_print_list ~pp_sep:(fun ppf () -> Format.fprintf ppf ",@ ")
+ (Reg_with_debug_info.print ~print_reg))
+ (RD.Set.elements availability)
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Mark Shinwell, Jane Street Europe *)
+(* *)
+(* Copyright 2016--2017 Jane Street Group LLC *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(** Register availability sets. *)
+
+type t =
+ | Ok of Reg_with_debug_info.Set.t
+ | Unreachable
+
+val inter : t -> t -> t
+(** Intersection of availabilities. *)
+
+val canonicalise : t -> t
+(** Return a subset of the given availability set which contains no registers
+ that are not associated with debug info (and holding values of
+ non-persistent identifiers); and where no two registers share the same
+ location. *)
+
+val equal : t -> t -> bool
+
+val print
+ : print_reg:(Format.formatter -> Reg.t -> unit)
+ -> Format.formatter
+ -> t
+ -> unit
+(** For debugging purposes only. *)
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Mark Shinwell, Jane Street Europe *)
+(* *)
+(* Copyright 2016--2017 Jane Street Group LLC *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+[@@@ocaml.warning "+a-4-9-30-40-41-42"]
+
+module Debug_info = struct
+ type t = {
+ holds_value_of : Ident.t;
+ part_of_value : int;
+ num_parts_of_value : int;
+ which_parameter : int option;
+ provenance : unit option;
+ }
+
+ let compare t1 t2 =
+ let c = Ident.compare t1.holds_value_of t2.holds_value_of in
+ if c <> 0 then c
+ else
+ Pervasives.compare
+ (t1.part_of_value, t1.num_parts_of_value, t1.which_parameter)
+ (t2.part_of_value, t2.num_parts_of_value, t2.which_parameter)
+
+ let holds_value_of t = t.holds_value_of
+ let part_of_value t = t.part_of_value
+ let num_parts_of_value t = t.num_parts_of_value
+ let which_parameter t = t.which_parameter
+ let provenance t = t.provenance
+
+ let print ppf t =
+ Format.fprintf ppf "%a" Ident.print t.holds_value_of;
+ if not (t.part_of_value = 0 && t.num_parts_of_value = 1) then begin
+ Format.fprintf ppf "(%d/%d)" t.part_of_value t.num_parts_of_value
+ end;
+ begin match t.which_parameter with
+ | None -> ()
+ | Some index -> Format.fprintf ppf "[P%d]" index
+ end
+end
+
+module T = struct
+ type t = {
+ reg : Reg.t;
+ debug_info : Debug_info.t option;
+ }
+
+ module Order = struct
+ type t = Reg.t
+ let compare (t1 : t) (t2 : t) = t1.stamp - t2.stamp
+ end
+
+ let compare t1 t2 =
+ Order.compare t1.reg t2.reg
+end
+
+include T
+
+type reg_with_debug_info = t
+
+let create ~reg ~holds_value_of ~part_of_value ~num_parts_of_value
+ ~which_parameter ~provenance =
+ assert (num_parts_of_value >= 1);
+ assert (part_of_value >= 0 && part_of_value < num_parts_of_value);
+ assert (match which_parameter with None -> true | Some index -> index >= 0);
+ let debug_info : Debug_info.t =
+ { holds_value_of;
+ part_of_value;
+ num_parts_of_value;
+ which_parameter;
+ provenance;
+ }
+ in
+ { reg;
+ debug_info = Some debug_info;
+ }
+
+let create_with_debug_info ~reg ~debug_info =
+ { reg;
+ debug_info;
+ }
+
+let create_without_debug_info ~reg =
+ { reg;
+ debug_info = None;
+ }
+
+let create_copying_debug_info ~reg ~debug_info_from =
+ { reg;
+ debug_info = debug_info_from.debug_info;
+ }
+
+let reg t = t.reg
+let location t = t.reg.loc
+
+let holds_pointer t =
+ match t.reg.typ with
+ | Addr | Val -> true
+ | Int | Float -> false
+
+let holds_non_pointer t = not (holds_pointer t)
+
+let assigned_to_stack t =
+ match t.reg.loc with
+ | Stack _ -> true
+ | Reg _ | Unknown -> false
+
+let regs_at_same_location (reg1 : Reg.t) (reg2 : Reg.t) ~register_class =
+ (* We need to check the register classes too: two locations both saying
+ "stack offset N" might actually be different physical locations, for
+ example if one is of class "Int" and another "Float" on amd64.
+ [register_class] will be [Proc.register_class], but cannot be here,
+ due to a circular dependency. *)
+ reg1.loc = reg2.loc
+ && register_class reg1 = register_class reg2
+
+let at_same_location t (reg : Reg.t) ~register_class =
+ regs_at_same_location t.reg reg ~register_class
+
+let debug_info t = t.debug_info
+
+let clear_debug_info t =
+ { t with debug_info = None; }
+
+module Order_distinguishing_names_and_locations = struct
+ type nonrec t = t
+
+ let compare t1 t2 =
+ match t1.debug_info, t2.debug_info with
+ | None, None -> 0
+ | None, Some _ -> -1
+ | Some _, None -> 1
+ | Some di1, Some di2 ->
+ let c = Ident.compare di1.holds_value_of di2.holds_value_of in
+ if c <> 0 then c
+ else Pervasives.compare t1.reg.loc t2.reg.loc
+end
+
+module Set_distinguishing_names_and_locations =
+ Set.Make (Order_distinguishing_names_and_locations)
+
+module Map_distinguishing_names_and_locations =
+ Map.Make (Order_distinguishing_names_and_locations)
+
+module Set = struct
+ include Set.Make (T)
+
+ let of_array elts =
+ of_list (Array.to_list elts)
+
+ let forget_debug_info t =
+ fold (fun t acc -> Reg.Set.add (reg t) acc) t Reg.Set.empty
+
+ let without_debug_info regs =
+ Reg.Set.fold (fun reg acc -> add (create_without_debug_info ~reg) acc)
+ regs
+ empty
+
+ let made_unavailable_by_clobber t ~regs_clobbered ~register_class =
+ Reg.Set.fold (fun reg acc ->
+ let made_unavailable =
+ filter (fun reg' ->
+ regs_at_same_location reg'.reg reg ~register_class)
+ t
+ in
+ union made_unavailable acc)
+ (Reg.set_of_array regs_clobbered)
+ (* ~init:*)empty
+
+ let mem_reg t (reg : Reg.t) =
+ exists (fun t -> t.reg.stamp = reg.stamp) t
+
+ let filter_reg t (reg : Reg.t) =
+ filter (fun t -> t.reg.stamp <> reg.stamp) t
+
+ (* CR-someday mshinwell: Well, it looks like we should have used a map.
+ mshinwell: Also see @chambart's suggestion on GPR#856. *)
+ let find_reg_exn t (reg : Reg.t) =
+ match elements (filter (fun t -> t.reg.stamp = reg.stamp) t) with
+ | [] -> raise Not_found
+ | [reg] -> reg
+ | _ -> assert false
+end
+
+let print ~print_reg ppf t =
+ match t.debug_info with
+ | None -> Format.fprintf ppf "%a" print_reg t.reg
+ | Some debug_info ->
+ Format.fprintf ppf "%a(%a)" print_reg t.reg Debug_info.print debug_info
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Mark Shinwell, Jane Street Europe *)
+(* *)
+(* Copyright 2016--2017 Jane Street Group LLC *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(** Registers equipped with information used for generating debugging
+ information. *)
+
+module Debug_info : sig
+ type t
+
+ val compare : t -> t -> int
+
+ val holds_value_of : t -> Ident.t
+ (** The identifier that the register holds (part of) the value of. *)
+
+ val part_of_value : t -> int
+ val num_parts_of_value : t -> int
+
+ val which_parameter : t -> int option
+ (** If the register corresponds to a function parameter, the value returned
+ is the zero-based index of said parameter; otherwise it is [None]. *)
+
+ val provenance : t -> unit option
+end
+
+type t
+
+type reg_with_debug_info = t
+
+val create
+ : reg:Reg.t
+ -> holds_value_of:Ident.t
+ -> part_of_value:int
+ -> num_parts_of_value:int
+ -> which_parameter:int option
+ -> provenance:unit option
+ -> t
+
+val create_with_debug_info : reg:Reg.t -> debug_info:Debug_info.t option -> t
+
+val create_without_debug_info : reg:Reg.t -> t
+
+val create_copying_debug_info : reg:Reg.t -> debug_info_from:t -> t
+
+val reg : t -> Reg.t
+val location : t -> Reg.location
+val debug_info : t -> Debug_info.t option
+
+val at_same_location : t -> Reg.t -> register_class:(Reg.t -> int) -> bool
+(** [at_same_location t reg] holds iff the register [t] corresponds to
+ the same (physical or pseudoregister) location as the register [reg],
+ which is not equipped with debugging information.
+ [register_class] should be [Proc.register_class].
+*)
+
+val holds_pointer : t -> bool
+val holds_non_pointer : t -> bool
+
+val assigned_to_stack : t -> bool
+(** [assigned_to_stack t] holds iff the location of [t] is a hard stack
+ slot. *)
+
+val clear_debug_info : t -> t
+
+module Set_distinguishing_names_and_locations
+ : Set.S with type elt = t
+
+module Map_distinguishing_names_and_locations
+ : Map.S with type key = t
+
+module Set : sig
+ include Set.S with type elt = t
+
+ val of_array : reg_with_debug_info array -> t
+
+ val mem_reg : t -> Reg.t -> bool
+
+ val find_reg_exn : t -> Reg.t -> reg_with_debug_info
+
+ val filter_reg : t -> Reg.t -> t
+
+ val forget_debug_info : t -> Reg.Set.t
+
+ val without_debug_info : Reg.Set.t -> t
+
+ val made_unavailable_by_clobber
+ : t
+ -> regs_clobbered:Reg.t array
+ -> register_class:(Reg.t -> int)
+ -> t
+ (** [made_unavailable_by_clobber t ~regs_clobbered ~register_class] returns
+ the largest subset of [t] whose locations do not overlap with any
+ registers in [regs_clobbered]. (Think of [t] as a set of available
+ registers.)
+ [register_class] should always be [Proc.register_class]. *)
+end
+
+val print
+ : print_reg:(Format.formatter -> Reg.t -> unit)
+ -> Format.formatter
+ -> t
+ -> unit
file_pos_nums := [];
file_pos_num_cnt := 1
-(* We only diplay .file if the file has not been seen before. We
+(* We only display .file if the file has not been seen before. We
display .loc for every instruction. *)
let emit_debug_info_gen dbg file_emitter loc_emitter =
if is_cfi_enabled () &&
us_actions_consts = const_actions;
us_index_blocks = block_index;
us_actions_blocks = block_actions;
- })
+ },
+ Debuginfo.none) (* debug info will be added by GPR#855 *)
in
(* Check that the [failaction] may be duplicated. If this is not the
case, share it through a static raise / static catch. *)
in
let env_body, params =
List.fold_right (fun var (env, params) ->
- let id, env = Env.add_fresh_ident env var in
+ let id, env = Env.add_fresh_ident env (Parameter.var var) in
env, id :: params)
function_decl.params (env, [])
in
in
let env_body, params =
List.fold_right (fun var (env, params) ->
- let id, env = Env.add_fresh_ident env var in
+ let id, env = Env.add_fresh_ident env (Parameter.var var) in
env, id :: params)
function_decl.params (env, [])
in
if Array.length i.arg = 2 && is_tos i.arg.(1) then
I.fxch st1;
emit_floatspecial s
+ | Lop (Iname_for_debugger _) -> ()
| Lreloadretaddr ->
()
| Lreturn ->
emit_global_label "code_end";
D.data ();
+ D.long (const 0); (* PR#6329 *)
emit_global_label "data_end";
D.long (const 0);
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Marcell Fischbach, University of Siegen *)
+(* Benedikt Meurer, University of Siegen *)
+(* *)
+(* Copyright 2011 Lehrstuhl für Compilerbau und Softwareanalyse, *)
+(* Universität Siegen. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Live intervals for the linear scan register allocator. *)
+
+open Mach
+open Reg
+
+type range =
+ {
+ mutable rbegin: int;
+ mutable rend: int;
+ }
+
+type t =
+ {
+ mutable reg: Reg.t;
+ mutable ibegin: int;
+ mutable iend: int;
+ mutable ranges: range list;
+ }
+
+type kind =
+ Result
+ | Argument
+ | Live
+
+let interval_list = ref ([] : t list)
+let fixed_interval_list = ref ([] : t list)
+let all_intervals() = !interval_list
+let all_fixed_intervals() = !fixed_interval_list
+
+(* Check if two intervals overlap *)
+
+let overlap i0 i1 =
+ let rec overlap_ranges rl0 rl1 =
+ match rl0, rl1 with
+ r0 :: rl0', r1 :: rl1' ->
+ if r0.rend >= r1.rbegin && r1.rend >= r0.rbegin then true
+ else if r0.rend < r1.rend then overlap_ranges rl0' rl1
+ else if r0.rend > r1.rend then overlap_ranges rl0 rl1'
+ else overlap_ranges rl0' rl1'
+ | _ -> false in
+ overlap_ranges i0.ranges i1.ranges
+
+let is_live i pos =
+ let rec is_live_in_ranges = function
+ [] -> false
+ | r :: rl -> if pos < r.rbegin then false
+ else if pos <= r.rend then true
+ else is_live_in_ranges rl in
+ is_live_in_ranges i.ranges
+
+let remove_expired_ranges i pos =
+ let rec filter = function
+ [] -> []
+ | r :: rl' as rl -> if pos < r.rend then rl
+ else filter rl' in
+ i.ranges <- filter i.ranges
+
+let update_interval_position intervals pos kind reg =
+ let i = intervals.(reg.stamp) in
+ let on = pos lsl 1 in
+ let off = on + 1 in
+ let rbegin = (match kind with Result -> off | _ -> on) in
+ let rend = (match kind with Argument -> on | _ -> off) in
+ if i.iend = 0 then begin
+ i.ibegin <- rbegin;
+ i.reg <- reg;
+ i.ranges <- [{rbegin = rbegin; rend = rend}]
+ end else begin
+ let r = List.hd i.ranges in
+ let ridx = r.rend asr 1 in
+ if pos - ridx <= 1 then
+ r.rend <- rend
+ else
+ i.ranges <- {rbegin = rbegin; rend = rend} :: i.ranges
+ end;
+ i.iend <- rend
+
+let update_interval_position_by_array intervals regs pos kind =
+ Array.iter (update_interval_position intervals pos kind) regs
+
+let update_interval_position_by_set intervals regs pos kind =
+ Set.iter (update_interval_position intervals pos kind) regs
+
+let update_interval_position_by_instr intervals instr pos =
+ update_interval_position_by_array intervals instr.arg pos Argument;
+ update_interval_position_by_array intervals instr.res pos Result;
+ update_interval_position_by_set intervals instr.live pos Live
+
+let insert_destroyed_at_oper intervals instr pos =
+ let destroyed = Proc.destroyed_at_oper instr.desc in
+ if Array.length destroyed > 0 then
+ update_interval_position_by_array intervals destroyed pos Result
+
+let insert_destroyed_at_raise intervals pos =
+ let destroyed = Proc.destroyed_at_raise in
+ if Array.length destroyed > 0 then
+ update_interval_position_by_array intervals destroyed pos Result
+
+(* Build all intervals.
+ The intervals will be expanded by one step at the start and end
+ of a basic block. *)
+
+let build_intervals fd =
+ let intervals = Array.init
+ (Reg.num_registers())
+ (fun _ -> {
+ reg = Reg.dummy;
+ ibegin = 0;
+ iend = 0;
+ ranges = []; }) in
+ let pos = ref 0 in
+ let rec walk_instruction i =
+ incr pos;
+ update_interval_position_by_instr intervals i !pos;
+ begin match i.desc with
+ Iend -> ()
+ | Iop(Icall_ind _ | Icall_imm _ | Iextcall{alloc = true; _}
+ | Itailcall_ind _ | Itailcall_imm _) ->
+ walk_instruction i.next
+ | Iop _ ->
+ insert_destroyed_at_oper intervals i !pos;
+ walk_instruction i.next
+ | Ireturn ->
+ insert_destroyed_at_oper intervals i !pos;
+ walk_instruction i.next
+ | Iifthenelse(_, ifso, ifnot) ->
+ insert_destroyed_at_oper intervals i !pos;
+ walk_instruction ifso;
+ walk_instruction ifnot;
+ walk_instruction i.next
+ | Iswitch(_, cases) ->
+ insert_destroyed_at_oper intervals i !pos;
+ Array.iter walk_instruction cases;
+ walk_instruction i.next
+ | Iloop body ->
+ insert_destroyed_at_oper intervals i !pos;
+ walk_instruction body;
+ walk_instruction i.next
+ | Icatch(_, handlers, body) ->
+ insert_destroyed_at_oper intervals i !pos;
+ List.iter (fun (_, i) -> walk_instruction i) handlers;
+ walk_instruction body;
+ walk_instruction i.next
+ | Iexit _ ->
+ insert_destroyed_at_oper intervals i !pos;
+ walk_instruction i.next
+ | Itrywith(body, handler) ->
+ insert_destroyed_at_oper intervals i !pos;
+ walk_instruction body;
+ insert_destroyed_at_raise intervals !pos;
+ walk_instruction handler;
+ walk_instruction i.next
+ | Iraise _ ->
+ walk_instruction i.next
+ end in
+ walk_instruction fd.fun_body;
+ (* Generate the interval and fixed interval lists *)
+ interval_list := [];
+ fixed_interval_list := [];
+ Array.iter
+ (fun i ->
+ if i.iend != 0 then begin
+ i.ranges <- List.rev i.ranges;
+ begin match i.reg.loc with
+ Reg _ ->
+ fixed_interval_list := i :: !fixed_interval_list
+ | _ ->
+ interval_list := i :: !interval_list
+ end
+ end)
+ intervals;
+ (* Sort the intervals according to their start position *)
+ interval_list := List.sort (fun i0 i1 -> i0.ibegin - i1.ibegin) !interval_list
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Marcell Fischbach, University of Siegen *)
+(* Benedikt Meurer, University of Siegen *)
+(* *)
+(* Copyright 2011 Lehrstuhl für Compilerbau und Softwareanalyse, *)
+(* Universität Siegen. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Live intervals for the linear scan register allocator. *)
+
+type range =
+ {
+ mutable rbegin: int;
+ mutable rend: int;
+ }
+
+type t =
+ {
+ mutable reg: Reg.t;
+ mutable ibegin: int;
+ mutable iend: int;
+ mutable ranges: range list;
+ }
+
+val all_intervals: unit -> t list
+val all_fixed_intervals: unit -> t list
+val overlap: t -> t -> bool
+val is_live: t -> int -> bool
+val remove_expired_ranges: t -> int -> unit
+val build_intervals: Mach.fundecl -> unit
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Marcell Fischbach, University of Siegen *)
+(* Benedikt Meurer, University of Siegen *)
+(* *)
+(* Copyright 2011 Lehrstuhl für Compilerbau und Softwareanalyse, *)
+(* Universität Siegen. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Linear scan register allocation. *)
+
+open Interval
+open Reg
+
+(* Live intervals per register class *)
+
+type class_intervals =
+ {
+ mutable ci_fixed: Interval.t list;
+ mutable ci_active: Interval.t list;
+ mutable ci_inactive: Interval.t list;
+ }
+
+let active = Array.init Proc.num_register_classes (fun _ -> {
+ ci_fixed = [];
+ ci_active = [];
+ ci_inactive = []
+})
+
+(* Insert interval into list sorted by end position *)
+
+let rec insert_interval_sorted i = function
+ [] -> [i]
+ | j :: _ as il when j.iend <= i.iend -> i :: il
+ | j :: il -> j :: insert_interval_sorted i il
+
+let rec release_expired_fixed pos = function
+ i :: il when i.iend >= pos ->
+ Interval.remove_expired_ranges i pos;
+ i :: release_expired_fixed pos il
+ | _ -> []
+
+let rec release_expired_active ci pos = function
+ i :: il when i.iend >= pos ->
+ Interval.remove_expired_ranges i pos;
+ if Interval.is_live i pos then
+ i :: release_expired_active ci pos il
+ else begin
+ ci.ci_inactive <- insert_interval_sorted i ci.ci_inactive;
+ release_expired_active ci pos il
+ end
+ | _ -> []
+
+let rec release_expired_inactive ci pos = function
+ i :: il when i.iend >= pos ->
+ Interval.remove_expired_ranges i pos;
+ if not (Interval.is_live i pos) then
+ i :: release_expired_inactive ci pos il
+ else begin
+ ci.ci_active <- insert_interval_sorted i ci.ci_active;
+ release_expired_inactive ci pos il
+ end
+ | _ -> []
+
+(* Allocate a new stack slot to the interval. *)
+
+let allocate_stack_slot i =
+ let cl = Proc.register_class i.reg in
+ let ss = Proc.num_stack_slots.(cl) in
+ Proc.num_stack_slots.(cl) <- succ ss;
+ i.reg.loc <- Stack(Local ss);
+ i.reg.spill <- true
+
+(* Find a register for the given interval and assigns this register.
+ The interval is added to active. Raises Not_found if no free registers
+ left. *)
+
+let allocate_free_register i =
+ begin match i.reg.loc, i.reg.spill with
+ Unknown, true ->
+ (* Allocate a stack slot for the already spilled interval *)
+ allocate_stack_slot i
+ | Unknown, _ ->
+ (* We need to allocate a register to this interval somehow *)
+ let cl = Proc.register_class i.reg in
+ begin match Proc.num_available_registers.(cl) with
+ 0 ->
+ (* There are no registers available for this class *)
+ raise Not_found
+ | rn ->
+ let ci = active.(cl) in
+ let r0 = Proc.first_available_register.(cl) in
+ (* Create register mask for this class
+ note: if frame pointers are enabled then some registers may have
+ indexes that are off-bounds; we hence protect write accesses
+ below (given that the assign function will not consider such
+ registers) *)
+ let regmask = Array.make rn true in
+ (* Remove all assigned registers from the register mask *)
+ List.iter
+ (function
+ {reg = {loc = Reg r}} ->
+ if r - r0 < rn then regmask.(r - r0) <- false
+ | _ -> ())
+ ci.ci_active;
+ (* Remove all overlapping registers from the register mask *)
+ let remove_bound_overlapping = function
+ {reg = {loc = Reg r}} as j ->
+ if (r - r0 < rn) && regmask.(r - r0) && Interval.overlap j i then
+ regmask.(r - r0) <- false
+ | _ -> () in
+ List.iter remove_bound_overlapping ci.ci_inactive;
+ List.iter remove_bound_overlapping ci.ci_fixed;
+ (* Assign the first free register (if any) *)
+ let rec assign r =
+ if r = rn then
+ raise Not_found
+ else if regmask.(r) then begin
+ (* Assign the free register and insert the
+ current interval into the active list *)
+ i.reg.loc <- Reg (r0 + r);
+ i.reg.spill <- false;
+ ci.ci_active <- insert_interval_sorted i ci.ci_active
+ end else
+ assign (succ r) in
+ assign 0
+ end
+ | _ -> ()
+ end
+
+let allocate_blocked_register i =
+ let cl = Proc.register_class i.reg in
+ let ci = active.(cl) in
+ match ci.ci_active with
+ | ilast :: il when
+ ilast.iend > i.iend &&
+ (* Last interval in active is the last interval, so spill it. *)
+ let chk r = r.reg.loc = ilast.reg.loc && Interval.overlap r i in
+ (* But only if its physical register is admissible for the current
+ interval. *)
+ not (List.exists chk ci.ci_fixed || List.exists chk ci.ci_inactive)
+ ->
+ begin match ilast.reg.loc with Reg _ -> () | _ -> assert false end;
+ (* Use register from last interval for current interval *)
+ i.reg.loc <- ilast.reg.loc;
+ (* Remove the last interval from active and insert the current *)
+ ci.ci_active <- insert_interval_sorted i il;
+ (* Now get a new stack slot for the spilled register *)
+ allocate_stack_slot ilast
+ | _ ->
+ (* Either the current interval is last and we have to spill it,
+ or there are no registers at all in the register class (i.e.
+ floating point class on i386). *)
+ allocate_stack_slot i
+
+let walk_interval i =
+ let pos = i.ibegin land (lnot 0x01) in
+ (* Release all intervals that have been expired at the current position *)
+ Array.iter
+ (fun ci ->
+ ci.ci_fixed <- release_expired_fixed pos ci.ci_fixed;
+ ci.ci_active <- release_expired_active ci pos ci.ci_active;
+ ci.ci_inactive <- release_expired_inactive ci pos ci.ci_inactive)
+ active;
+ try
+ (* Allocate free register (if any) *)
+ allocate_free_register i
+ with
+ Not_found ->
+ (* No free register, need to decide which interval to spill *)
+ allocate_blocked_register i
+
+let allocate_registers() =
+ (* Initialize the stack slots and interval lists *)
+ for cl = 0 to Proc.num_register_classes - 1 do
+ (* Start with empty interval lists *)
+ active.(cl) <- {
+ ci_fixed = [];
+ ci_active = [];
+ ci_inactive = []
+ };
+ Proc.num_stack_slots.(cl) <- 0
+ done;
+ (* Add all fixed intervals (sorted by end position) *)
+ List.iter
+ (fun i ->
+ let ci = active.(Proc.register_class i.reg) in
+ ci.ci_fixed <- insert_interval_sorted i ci.ci_fixed)
+ (Interval.all_fixed_intervals());
+ (* Walk all the intervals within the list *)
+ List.iter walk_interval (Interval.all_intervals())
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Marcell Fischbach, University of Siegen *)
+(* Benedikt Meurer, University of Siegen *)
+(* *)
+(* Copyright 2011 Lehrstuhl für Compilerbau und Softwareanalyse, *)
+(* Universität Siegen. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Linear scan register allocation. *)
+
+val allocate_registers: unit -> unit
let across_after = Reg.diff_set_array after i.res in
let across =
match op with
- | Icall_ind _ | Icall_imm _ | Iextcall _
+ | Icall_ind _ | Icall_imm _ | Iextcall _ | Ialloc _
| Iintop (Icheckbound _) | Iintop_imm(Icheckbound _, _) ->
(* The function call may raise an exception, branching to the
- nearest enclosing try ... with. Similarly for bounds checks.
+ nearest enclosing try ... with. Similarly for bounds checks
+ and allocation (for the latter: finalizers may throw
+ exceptions, as may signal handlers).
Hence, everything that must be live at the beginning of
the exception handler must also be live across this instr. *)
Reg.Set.union across_after !live_at_raise
Reg.Set.equal before_handler before_handler'
in
let live_at_exit_before = !live_at_exit in
- let live_at_exit_add before_handlers =
- List.map (fun (nfail, before_handler) ->
- (nfail, before_handler))
- before_handlers
- in
let rec fixpoint before_handlers =
- let live_at_exit_add = live_at_exit_add before_handlers in
- live_at_exit := live_at_exit_add @ !live_at_exit;
+ live_at_exit := before_handlers @ !live_at_exit;
let before_handlers' = List.map2 aux handlers before_handlers in
live_at_exit := live_at_exit_before;
match rec_flag with
(* We could use handler.live instead of Reg.Set.empty as the initial
value but we would need to clean the live field before doing the
analysis (to remove remnants of previous passes). *)
- live_at_exit := (live_at_exit_add before_handler) @ !live_at_exit;
+ live_at_exit := before_handler @ !live_at_exit;
let before_body = live body at_join in
live_at_exit := live_at_exit_before;
i.live <- before_body;
| Inegf | Iabsf | Iaddf | Isubf | Imulf | Idivf
| Ifloatofint | Iintoffloat
| Ispecific of Arch.specific_operation
+ | Iname_for_debugger of { ident : Ident.t; which_parameter : int option;
+ provenance : unit option; is_assignment : bool; }
type instruction =
{ desc: instruction_desc;
arg: Reg.t array;
res: Reg.t array;
dbg: Debuginfo.t;
- mutable live: Reg.Set.t }
+ mutable live: Reg.Set.t;
+ mutable available_before: Reg_availability_set.t;
+ mutable available_across: Reg_availability_set.t option;
+ }
and instruction_desc =
Iend
arg = [||];
res = [||];
dbg = Debuginfo.none;
- live = Reg.Set.empty }
+ live = Reg.Set.empty;
+ available_before = Reg_availability_set.Ok Reg_with_debug_info.Set.empty;
+ available_across = None;
+ }
let end_instr () =
{ desc = Iend;
arg = [||];
res = [||];
dbg = Debuginfo.none;
- live = Reg.Set.empty }
+ live = Reg.Set.empty;
+ available_before = Reg_availability_set.Ok Reg_with_debug_info.Set.empty;
+ available_across = None;
+ }
let instr_cons d a r n =
{ desc = d; next = n; arg = a; res = r;
- dbg = Debuginfo.none; live = Reg.Set.empty }
+ dbg = Debuginfo.none; live = Reg.Set.empty;
+ available_before = Reg_availability_set.Ok Reg_with_debug_info.Set.empty;
+ available_across = None;
+ }
let instr_cons_debug d a r dbg n =
- { desc = d; next = n; arg = a; res = r; dbg = dbg; live = Reg.Set.empty }
+ { desc = d; next = n; arg = a; res = r; dbg = dbg; live = Reg.Set.empty;
+ available_before = Reg_availability_set.Ok Reg_with_debug_info.Set.empty;
+ available_across = None;
+ }
let rec instr_iter f i =
match i.desc with
| Imove | Ispill | Ireload | Iconst_int _ | Iconst_float _
| Iconst_symbol _ | Istackoffset _ | Iload _ | Istore _
| Inegf | Iabsf | Iaddf | Isubf | Imulf | Idivf
- | Ifloatofint | Iintoffloat -> false
+ | Ifloatofint | Iintoffloat
+ | Iname_for_debugger _ -> false
end
| Iend | Ireturn | Iifthenelse _ | Iswitch _ | Iloop _ | Icatch _
| Iexit _ | Itrywith _ | Iraise _ -> false
+
+let operation_can_raise op =
+ match op with
+ | Icall_ind _ | Icall_imm _ | Iextcall _
+ | Iintop (Icheckbound _) | Iintop_imm (Icheckbound _, _)
+ | Ialloc _ -> true
+ | _ -> false
| Inegf | Iabsf | Iaddf | Isubf | Imulf | Idivf
| Ifloatofint | Iintoffloat
| Ispecific of Arch.specific_operation
+ | Iname_for_debugger of { ident : Ident.t; which_parameter : int option;
+ provenance : unit option; is_assignment : bool; }
+ (** [Iname_for_debugger] has the following semantics:
+ (a) The argument register(s) is/are deemed to contain the value of the
+ given identifier.
+ (b) If [is_assignment] is [true], any information about other [Reg.t]s
+ that have been previously deemed to hold the value of that
+ identifier is forgotten. *)
type instruction =
{ desc: instruction_desc;
arg: Reg.t array;
res: Reg.t array;
dbg: Debuginfo.t;
- mutable live: Reg.Set.t }
+ mutable live: Reg.Set.t;
+ mutable available_before: Reg_availability_set.t;
+ mutable available_across: Reg_availability_set.t option;
+ }
and instruction_desc =
Iend
val instr_iter: (instruction -> unit) -> instruction -> unit
val spacetime_node_hole_pointer_is_live_before : instruction -> bool
+
+val operation_can_raise : operation -> bool
| Lop(Ifloatofint) -> 9
| Lop(Iintoffloat) -> 4
| Lop(Ispecific _) -> 1
+ | Lop (Iname_for_debugger _) -> 0
| Lreloadretaddr -> 2
| Lreturn -> 2
| Llabel _ -> 0
| Lop(Ispecific sop) ->
let instr = name_for_specific sop in
` {emit_string instr} {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}, {emit_reg i.arg.(2)}\n`
+ | Lop (Iname_for_debugger _) -> ()
| Lreloadretaddr ->
` {emit_string lg} 11, {emit_int(retaddr_offset())}(1)\n`;
` mtlr 11\n`
emit_string data_space;
let lbl_end = Compilenv.make_symbol (Some "data_end") in
declare_global_data lbl_end;
+ ` {emit_string datag} 0\n`; (* PR#6329 *)
`{emit_symbol lbl_end}:\n`;
` {emit_string datag} 0\n`;
(* Emit the frame descriptors *)
- emit_string rodata_space;
+ emit_string data_space; (* not rodata_space because it contains relocations *)
let lbl = Compilenv.make_symbol (Some "frametable") in
declare_global_data lbl;
`{emit_symbol lbl}:\n`;
let lams ppf largs =
List.iter (fun l -> fprintf ppf "@ %a" lam l) largs in
fprintf ppf "@[<2>(%a%a)@]" Printlambda.primitive prim lams largs
- | Uswitch(larg, sw) ->
+ | Uswitch(larg, sw, _dbg) ->
let print_case tag index i ppf =
for j = 0 to Array.length index - 1 do
if index.(j) = i then fprintf ppf "case %s %i:" tag j
open Cmm
open Reg
open Mach
+open Interval
let reg ppf r =
if not (Reg.anonymous r) then
| Idivf -> fprintf ppf "%a /f %a" reg arg.(0) reg arg.(1)
| Ifloatofint -> fprintf ppf "floatofint %a" reg arg.(0)
| Iintoffloat -> fprintf ppf "intoffloat %a" reg arg.(0)
+ | Iname_for_debugger { ident; which_parameter; } ->
+ fprintf ppf "name_for_debugger %a%s=%a"
+ Ident.print ident
+ (match which_parameter with
+ | None -> ""
+ | Some index -> sprintf "[P%d]" index)
+ reg arg.(0)
| Ispecific op ->
Arch.print_specific_operation reg op ppf arg
fprintf ppf "@[<1>{%a" regsetaddr i.live;
if Array.length i.arg > 0 then fprintf ppf "@ +@ %a" regs i.arg;
fprintf ppf "}@]@,";
+ if !Clflags.dump_avail then begin
+ let module RAS = Reg_availability_set in
+ fprintf ppf "@[<1>AB={%a}" (RAS.print ~print_reg:reg) i.available_before;
+ begin match i.available_across with
+ | None -> ()
+ | Some available_across ->
+ fprintf ppf ",AA={%a}" (RAS.print ~print_reg:reg) available_across
+ end;
+ fprintf ppf "@]@,"
+ end
end;
begin match i.desc with
| Iend -> ()
fprintf ppf "*** Interferences@.";
List.iter (interference ppf) (Reg.all_registers())
+let interval ppf i =
+ let interv ppf =
+ List.iter
+ (fun r -> fprintf ppf "@ [%d;%d]" r.rbegin r.rend)
+ i.ranges in
+ fprintf ppf "@[<2>%a:%t@]@." reg i.reg interv
+
+let intervals ppf () =
+ fprintf ppf "*** Intervals@.";
+ List.iter (interval ppf) (Interval.all_fixed_intervals());
+ List.iter (interval ppf) (Interval.all_intervals())
+
let preference ppf r =
let prefs ppf =
List.iter
val fundecl: formatter -> Mach.fundecl -> unit
val phase: string -> formatter -> Mach.fundecl -> unit
val interferences: formatter -> unit -> unit
+val intervals: formatter -> unit -> unit
val preferences: formatter -> unit -> unit
val print_live: bool ref
assert (i.arg.(2).loc = i.res.(0).loc);
let instr = name_for_specific sop in
` {emit_string instr} {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`
+ | Lop (Iname_for_debugger _) -> ()
| Lreloadretaddr ->
let n = frame_size() in
` lg %r14, {emit_int(n - size_addr)}(%r15)\n`
` .align 8\n`;
let lbl_end = Compilenv.make_symbol (Some "data_end") in
declare_global_data lbl_end;
+ ` .quad 0\n`; (* PR#6329 *)
`{emit_symbol lbl_end}:\n`;
` .quad 0\n`;
(* Emit the frame descriptors *)
- emit_string rodata_space;
+ emit_string data_space; (* not rodata because relocations inside *)
` .align 8\n`;
let lbl = Compilenv.make_symbol (Some "frametable") in
declare_global_data lbl;
0 temporary, null register for some operations (volatile)
1 temporary (volatile)
2 - 5 function arguments and results (volatile)
- 6 function arguments and results (persevered by C)
+ 6 function arguments and results (preserved by C)
7 - 9 general purpose, preserved by C
10 allocation limit (preserved by C)
11 allocation pointer (preserved by C)
[] ->
node.length <-
if is_critical critical_outputs node.instr.res
- || node.instr.desc = Lreloadretaddr (* alway critical *)
+ || node.instr.desc = Lreloadretaddr (* always critical *)
then node.delay
else 0
| sons ->
(* Remove node from queue *)
let new_queue = ref (remove_instr node ready_queue) in
(* Update the start date and number of ancestors emitted of
- all descendents of this node. Enter those that become ready
+ all descendants of this node. Enter those that become ready
in the queue. *)
let issue_cycles = self#instr_issue_cycles node.instr in
List.iter
loc_arg (Proc.loc_external_results rd) in
self#insert_move_results loc_res rd stack_ofs;
Some rd
- | Ialloc { words = _; spacetime_index; label_after_call_gc; } ->
+ | Ialloc { words; spacetime_index; label_after_call_gc; } ->
+ assert (words <= Config.max_young_wosize);
let rd = self#regs_for typ_val in
let size = size_expr env (Ctuple new_args) in
let op =
(* informs the code emitter that the current function may call
a C function that never returns; by default, does nothing.
- It is unecessary to save the stack pointer in this situation
+ It is unnecessary to save the stack pointer in this situation
(which is the main purpose of tracking leaf functions) but some
architectures still need to ensure that the stack is properly
aligned when the C function is called. This is achieved by
(* *)
(* Mark Shinwell and Leo White, Jane Street Europe *)
(* *)
-(* Copyright 2015--2016 Jane Street Group LLC *)
+(* Copyright 2015--2017 Jane Street Group LLC *)
(* *)
(* All rights reserved. This file is distributed under the terms of *)
(* the GNU Lesser General Public License version 2.1, with the *)
let next_index_within_node ~part_of_shape ~label =
let index = !index_within_node in
begin match part_of_shape with
- | Mach.Direct_call_point _ | Mach.Indirect_call_point ->
+ | Mach.Direct_call_point _ ->
+ incr index_within_node;
+ if Config.enable_call_counts then begin
+ incr index_within_node
+ end
+ | Mach.Indirect_call_point ->
incr index_within_node
| Mach.Allocation_point ->
incr index_within_node;
(hard) node hole pointer register immediately before the call.
(That move is inserted in [Selectgen].) *)
match callee with
- | Direct _callee -> Cvar place_within_node
+ | Direct _callee ->
+ if Config.enable_call_counts then begin
+ let count_addr = Ident.create "call_count_addr" in
+ let count = Ident.create "call_count" in
+ Clet (count_addr,
+ Cop (Caddi, [Cvar place_within_node; Cconst_int Arch.size_addr], dbg),
+ Clet (count,
+ Cop (Cload (Word_int, Asttypes.Mutable), [Cvar count_addr], dbg),
+ Csequence (
+ Cop (Cstore (Word_int, Lambda.Assignment),
+ (* Adding 2 really means adding 1; the count is encoded
+ as an OCaml integer. *)
+ [Cvar count_addr; Cop (Caddi, [Cvar count; Cconst_int 2], dbg)],
+ dbg),
+ Cvar place_within_node)))
+ end else begin
+ Cvar place_within_node
+ end
| Indirect callee ->
let caller_node =
if is_tail then node
+++ /dev/null
-(**************************************************************************)
-(* *)
-(* OCaml *)
-(* *)
-(* Xavier Leroy, projet Gallium, INRIA Rocquencourt *)
-(* *)
-(* Copyright 2014 Institut National de Recherche en Informatique et *)
-(* en Automatique. *)
-(* *)
-(* All rights reserved. This file is distributed under the terms of *)
-(* the GNU Lesser General Public License version 2.1, with the *)
-(* special exception on linking described in the file LICENSE. *)
-(* *)
-(**************************************************************************)
-
-(* CSE for Sparc *)
-
-open Mach
-open CSEgen
-
-class cse = object
-
-inherit cse_generic (* as super *)
-
-method! is_cheap_operation op =
- match op with
- | Iconst_int n -> n <= 4095n && n >= -4096n
- | _ -> false
-
-end
-
-let fundecl f =
- (new cse)#fundecl f
+++ /dev/null
-# Supported platforms
-
-SPARC v8 and up, in 32-bit mode.
-
-Operating systems: Solaris, Linux
- (abandoned since major Linux distributions no longer support SPARC).
-
-Status of this port: nearly abandoned
- (no hardware or virtual machine available for testing).
-
-# Reference documents
-
-* Instruction set architecture:
- _The SPARC Architecture Manual_ version 8.
-* ELF application binary interface:
- _System V Application Binary Interface,
- SPARC Processor Supplement_
+++ /dev/null
-(**************************************************************************)
-(* *)
-(* OCaml *)
-(* *)
-(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
-(* *)
-(* Copyright 1996 Institut National de Recherche en Informatique et *)
-(* en Automatique. *)
-(* *)
-(* All rights reserved. This file is distributed under the terms of *)
-(* the GNU Lesser General Public License version 2.1, with the *)
-(* special exception on linking described in the file LICENSE. *)
-(* *)
-(**************************************************************************)
-
-(* Specific operations for the Sparc processor *)
-
-open Format
-
-(* SPARC V8 adds multiply and divide.
- SPARC V9 adds double precision float operations, conditional
- move, and more instructions that are only useful in 64 bit mode.
- Sun calls 32 bit V9 "V8+". *)
-type arch_version = SPARC_V7 | SPARC_V8 | SPARC_V9
-
-let arch_version = ref SPARC_V7
-
-let command_line_options =
- [ "-march=v8", Arg.Unit (fun () -> arch_version := SPARC_V8),
- " Generate code for SPARC V8 processors";
- "-march=v9", Arg.Unit (fun () -> arch_version := SPARC_V9),
- " Generate code for SPARC V9 processors" ]
-
-type specific_operation = unit (* None worth mentioning *)
-
-let spacetime_node_hole_pointer_is_live_before _specific_op = false
-
-(* Addressing modes *)
-
-type addressing_mode =
- Ibased of string * int (* symbol + displ *)
- | Iindexed of int (* reg + displ *)
-
-(* Sizes, endianness *)
-
-let big_endian = true
-
-let size_addr = 4
-let size_int = 4
-let size_float = 8
-
-let allow_unaligned_access = false
-
-(* Behavior of division *)
-
-let division_crashes_on_overflow = false
-
-(* Operations on addressing modes *)
-
-let identity_addressing = Iindexed 0
-
-let offset_addressing addr delta =
- match addr with
- Ibased(s, n) -> Ibased(s, n + delta)
- | Iindexed n -> Iindexed(n + delta)
-
-let num_args_addressing = function
- Ibased _ -> 0
- | Iindexed _ -> 1
-
-(* Printing operations and addressing modes *)
-
-let print_addressing printreg addr ppf arg =
- match addr with
- | Ibased(s, n) ->
- let idx = if n <> 0 then Printf.sprintf " + %i" n else "" in
- fprintf ppf "\"%s\"%s" s idx
- | Iindexed n ->
- let idx = if n <> 0 then Printf.sprintf " + %i" n else "" in
- fprintf ppf "%a%s" printreg arg.(0) idx
-
-let print_specific_operation _printreg _op _ppf _arg =
- Misc.fatal_error "Arch_sparc.print_specific_operation"
+++ /dev/null
-#2 "asmcomp/sparc/emit.mlp"
-(**************************************************************************)
-(* *)
-(* OCaml *)
-(* *)
-(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
-(* *)
-(* Copyright 1996 Institut National de Recherche en Informatique et *)
-(* en Automatique. *)
-(* *)
-(* All rights reserved. This file is distributed under the terms of *)
-(* the GNU Lesser General Public License version 2.1, with the *)
-(* special exception on linking described in the file LICENSE. *)
-(* *)
-(**************************************************************************)
-
-(* Emission of Sparc assembly code *)
-
-open Misc
-open Cmm
-open Arch
-open Proc
-open Reg
-open Mach
-open Linearize
-open Emitaux
-
-(* Solaris vs. the other ports *)
-
-let solaris = Config.system = "solaris"
-
-(* Tradeoff between code size and code speed *)
-
-let fastcode_flag = ref true
-
-(* Layout of the stack *)
-(* Always keep the stack 8-aligned.
- Always leave 96 bytes at the bottom of the stack *)
-
-let stack_offset = ref 0
-
-let frame_size () =
- let size =
- !stack_offset +
- 4 * num_stack_slots.(0) + 8 * num_stack_slots.(1) +
- (if !contains_calls then 4 else 0) in
- Misc.align size 8
-
-let slot_offset loc cl =
- match loc with
- Incoming n -> frame_size() + n + 96
- | Local n ->
- if cl = 0
- then !stack_offset + num_stack_slots.(1) * 8 + n * 4 + 96
- else !stack_offset + n * 8 + 96
- | Outgoing n -> n + 96
-
-(* Return the other register in a register pair *)
-
-let next_in_pair = function
- {loc = Reg r; typ = (Int | Addr | Val)} -> phys_reg (r + 1)
- | {loc = Reg r; typ = Float} -> phys_reg (r + 16)
- | _ -> fatal_error "Emit.next_in_pair"
-
-(* Symbols are prefixed with _ under SunOS *)
-
-let symbol_prefix =
- if Config.system = "sunos" then "_" else ""
-
-let emit_symbol s =
- if String.length s >= 1 && s.[0] = '.'
- then emit_string s
- else begin emit_string symbol_prefix; Emitaux.emit_symbol '$' s end
-
-let emit_size lbl =
- if Config.system = "solaris" then
- ` .size {emit_symbol lbl},.-{emit_symbol lbl}\n`
-
-let rodata () =
- if Config.system = "solaris" (* || Config.system = "linux" *)
- (* || Config.system = "gnu" *) then
- ` .section \".rodata\"\n`
- else
- ` .data\n`
-
-(* Check if an integer or native integer is an immediate operand *)
-
-let is_immediate n =
- n <= 4095 && n >= -4096
-
-let is_native_immediate n =
- n <= Nativeint.of_int 4095 && n >= Nativeint.of_int (-4096)
-
-(* Output a label *)
-
-let label_prefix =
- if Config.system = "sunos" then "L" else ".L"
-
-let emit_label lbl =
- emit_string label_prefix; emit_int lbl
-
-(* Output a pseudo-register *)
-
-let emit_reg r =
- match r.loc with
- Reg r -> emit_string (register_name r)
- | _ -> fatal_error "Emit.emit_reg"
-
-(* Output a stack reference *)
-
-let emit_stack r =
- match r.loc with
- Stack s ->
- let ofs = slot_offset s (register_class r) in `[%sp + {emit_int ofs}]`
- | _ -> fatal_error "Emit.emit_stack"
-
-(* Output a load *)
-
-let emit_load instr addr arg dst =
- match addr with
- Ibased(s, 0) ->
- ` sethi %hi({emit_symbol s}), %g1\n`;
- ` {emit_string instr} [%g1 + %lo({emit_symbol s})], {emit_reg dst}\n`
- | Ibased(s, ofs) ->
- ` sethi %hi({emit_symbol s} + {emit_int ofs}), %g1\n`;
- ` {emit_string instr} [%g1 + %lo({emit_symbol s} + {emit_int ofs})], {emit_reg dst}\n`
- | Iindexed ofs ->
- if is_immediate ofs then
- ` {emit_string instr} [{emit_reg arg.(0)} + {emit_int ofs}], {emit_reg dst}\n`
- else begin
- ` sethi %hi({emit_int ofs}), %g1\n`;
- ` or %g1, %lo({emit_int ofs}), %g1\n`;
- ` {emit_string instr} [{emit_reg arg.(0)} + %g1], {emit_reg dst}\n`
- end
-
-(* Output a store *)
-
-let emit_store instr addr arg src =
- match addr with
- Ibased(s, 0) ->
- ` sethi %hi({emit_symbol s}), %g1\n`;
- ` {emit_string instr} {emit_reg src}, [%g1 + %lo({emit_symbol s})]\n`
- | Ibased(s, ofs) ->
- ` sethi %hi({emit_symbol s} + {emit_int ofs}), %g1\n`;
- ` {emit_string instr} {emit_reg src}, [%g1 + %lo({emit_symbol s} + {emit_int ofs})]\n`
- | Iindexed ofs ->
- if is_immediate ofs then
- ` {emit_string instr} {emit_reg src}, [{emit_reg arg.(1)} + {emit_int ofs}]\n`
- else begin
- ` sethi %hi({emit_int ofs}), %g1\n`;
- ` or %g1, %lo({emit_int ofs}), %g1\n`;
- ` {emit_string instr} {emit_reg src}, [{emit_reg arg.(1)} + %g1]\n`
- end
-
-(* Record live pointers at call points *)
-
-type frame_descr =
- { fd_lbl: int; (* Return address *)
- fd_frame_size: int; (* Size of stack frame *)
- fd_live_offset: int list } (* Offsets/regs of live addresses *)
-
-let frame_descriptors = ref([] : frame_descr list)
-
-let record_frame ?label live =
- let lbl =
- match label with
- | None -> new_label()
- | Some label -> label
- in
- let live_offset = ref [] in
- Reg.Set.iter
- (function
- | {typ = Val; loc = Reg r} ->
- live_offset := ((r lsl 1) + 1) :: !live_offset
- | {typ = Val; loc = Stack s} as reg ->
- live_offset := slot_offset s (register_class reg) :: !live_offset
- | {typ = Addr} as r ->
- Misc.fatal_error ("bad GC root " ^ Reg.name r)
- | _ -> ())
- live;
- live_offset := List.sort_uniq (-) !live_offset;
- frame_descriptors :=
- { fd_lbl = lbl;
- fd_frame_size = frame_size();
- fd_live_offset = !live_offset } :: !frame_descriptors;
- `{emit_label lbl}:`
-
-let emit_frame fd =
- ` .word {emit_label fd.fd_lbl}\n`;
- ` .half {emit_int fd.fd_frame_size}\n`;
- ` .half {emit_int (List.length fd.fd_live_offset)}\n`;
- List.iter
- (fun n ->
- ` .half {emit_int n}\n`)
- fd.fd_live_offset;
- ` .align 4\n`
-
-(* Record floating-point constants *)
-
-let float_constants = ref ([] : (int * int64) list)
-
-let emit_float_constant (lbl, cst) =
- rodata ();
- ` .align 8\n`;
- `{emit_label lbl}:`;
- emit_float64_split_directive ".word" cst
-
-(* Emission of the profiling prelude *)
-let emit_profile () =
- begin match Config.system with
- "solaris" ->
- let lbl = new_label() in
- ` .section \".bss\"\n`;
- `{emit_label lbl}: .skip 4\n`;
- ` .text\n`;
- ` save %sp,-96,%sp\n`;
- ` sethi %hi({emit_label lbl}),%o0\n`;
- ` call _mcount\n`;
- ` or %o0,%lo({emit_label lbl}),%o0\n`;
- ` restore\n`
- | _ -> ()
- end
-
-(* Names of various instructions *)
-
-let name_for_int_operation = function
- Iadd -> "add"
- | Isub -> "sub"
- | Iand -> "and"
- | Ior -> "or"
- | Ixor -> "xor"
- | Ilsl -> "sll"
- | Ilsr -> "srl"
- | Iasr -> "sra"
- | Imul -> "smul"
- | _ -> Misc.fatal_error "Emit.name_for_int_operation"
-
-let name_for_float_operation = function
- Inegf -> if !arch_version = SPARC_V9 then "fnegd" else "fnegs"
- | Iabsf -> if !arch_version = SPARC_V9 then "fabsd" else "fabss"
- | Iaddf -> "faddd"
- | Isubf -> "fsubd"
- | Imulf -> "fmuld"
- | Idivf -> "fdivd"
- | _ -> Misc.fatal_error "Emit.name_for_float_operation"
-
-let name_for_int_movcc = function
- Isigned Ceq -> "e" | Isigned Cne -> "ne"
- | Isigned Cle -> "le" | Isigned Cgt -> "g"
- | Isigned Clt -> "l" | Isigned Cge -> "ge"
- | Iunsigned Ceq -> "e" | Iunsigned Cne -> "ne"
- | Iunsigned Cle -> "leu" | Iunsigned Cgt -> "gu"
- | Iunsigned Clt -> "lu" | Iunsigned Cge -> "geu"
-
-let name_for_int_comparison = function
- Isigned Ceq -> "be" | Isigned Cne -> "bne"
- | Isigned Cle -> "ble" | Isigned Cgt -> "bg"
- | Isigned Clt -> "bl" | Isigned Cge -> "bge"
- | Iunsigned Ceq -> "be" | Iunsigned Cne -> "bne"
- | Iunsigned Cle -> "bleu" | Iunsigned Cgt -> "bgu"
- | Iunsigned Clt -> "blu" | Iunsigned Cge -> "bgeu"
-
-let name_for_float_comparison cmp neg =
- match cmp with
- Ceq -> if neg then "fbne" else "fbe"
- | Cne -> if neg then "fbe" else "fbne"
- | Cle -> if neg then "fbug" else "fble"
- | Cgt -> if neg then "fbule" else "fbg"
- | Clt -> if neg then "fbuge" else "fbl"
- | Cge -> if neg then "fbul" else "fbge"
-
-(* Output the assembly code for an instruction *)
-
-let function_name = ref ""
-let tailrec_entry_point = ref 0
-let range_check_trap = ref 0
-
-let rec emit_instr i dslot =
- match i.desc with
- Lend -> ()
- | Lop(Imove | Ispill | Ireload) ->
- let src = i.arg.(0) and dst = i.res.(0) in
- begin match (src, dst) with
- {loc = Reg _; typ = (Int | Addr | Val)}, {loc = Reg _} ->
- ` mov {emit_reg src}, {emit_reg dst}\n`
- | {loc = Reg _; typ = Float}, {loc = Reg _; typ = Float} ->
- if !arch_version = SPARC_V9 then
- ` fmovd {emit_reg src}, {emit_reg dst}\n`
- else begin
- ` fmovs {emit_reg src}, {emit_reg dst}\n`;
- ` fmovs {emit_reg(next_in_pair src)}, {emit_reg(next_in_pair dst)}\n`
- end
- | {loc = Reg _; typ = Float}, {loc = Reg _; typ = (Int | Addr | Val)} ->
- (* This happens when calling C functions and passing a float arg
- in %o0...%o5 *)
- ` sub %sp, 8, %sp\n`;
- ` std {emit_reg src}, [%sp + 96]\n`;
- ` ld [%sp + 96], {emit_reg dst}\n`;
- let dst2 = i.res.(1) in
- begin match dst2 with
- | {loc = Reg _; typ = Int} ->
- ` ld [%sp + 100], {emit_reg dst2}\n`;
- | {loc = Stack _; typ = Int} ->
- ` ld [%sp + 100], %g1\n`;
- ` st %g1, {emit_stack dst2}\n`;
- | _ ->
- fatal_error "Emit: Imove Float [| _; _ |]"
- end;
- ` add %sp, 8, %sp\n`
- | {loc = Reg _; typ = (Int | Addr | Val)}, {loc = Stack _} ->
- ` st {emit_reg src}, {emit_stack dst}\n`
- | {loc = Reg _; typ = Float}, {loc = Stack _} ->
- ` std {emit_reg src}, {emit_stack dst}\n`
- | {loc = Stack _; typ = (Int | Addr | Val)}, {loc = Reg _} ->
- ` ld {emit_stack src}, {emit_reg dst}\n`
- | {loc = Stack _; typ = Float}, {loc = Reg _} ->
- ` ldd {emit_stack src}, {emit_reg dst}\n`
- | (_, _) ->
- fatal_error "Emit: Imove"
- end
- | Lop(Iconst_int n) ->
- if is_native_immediate n then
- ` mov {emit_nativeint n}, {emit_reg i.res.(0)}\n`
- else begin
- ` sethi %hi({emit_nativeint n}), %g1\n`;
- ` or %g1, %lo({emit_nativeint n}), {emit_reg i.res.(0)}\n`
- end
- | Lop(Iconst_float f) ->
- (* On UltraSPARC, the fzero instruction could be used to set a
- floating point register pair to zero. *)
- let lbl = new_label() in
- float_constants := (lbl, f) :: !float_constants;
- ` sethi %hi({emit_label lbl}), %g1\n`;
- ` ldd [%g1 + %lo({emit_label lbl})], {emit_reg i.res.(0)}\n`
- | Lop(Iconst_symbol s) ->
- ` sethi %hi({emit_symbol s}), %g1\n`;
- ` or %g1, %lo({emit_symbol s}), {emit_reg i.res.(0)}\n`
- | Lop(Icall_ind { label_after; }) ->
- `{record_frame i.live ~label:label_after} call {emit_reg i.arg.(0)}\n`;
- fill_delay_slot dslot
- | Lop(Icall_imm { func; label_after; }) ->
- `{record_frame i.live ~label:label_after} call {emit_symbol func}\n`;
- fill_delay_slot dslot
- | Lop(Itailcall_ind { label_after = _; }) ->
- let n = frame_size() in
- if !contains_calls then
- ` ld [%sp + {emit_int(n - 4 + 96)}], %o7\n`;
- ` jmp {emit_reg i.arg.(0)}\n`;
- ` add %sp, {emit_int n}, %sp\n` (* in delay slot *)
- | Lop(Itailcall_imm { func; label_after = _; }) ->
- let n = frame_size() in
- if func = !function_name then begin
- ` b {emit_label !tailrec_entry_point}\n`;
- fill_delay_slot dslot
- end else begin
- if !contains_calls then
- ` ld [%sp + {emit_int(n - 4 + 96)}], %o7\n`;
- ` sethi %hi({emit_symbol func}), %g1\n`;
- ` jmp %g1 + %lo({emit_symbol func})\n`;
- ` add %sp, {emit_int n}, %sp\n` (* in delay slot *)
- end
- | Lop(Iextcall { func; alloc; label_after; }) ->
- if alloc then begin
- ` sethi %hi({emit_symbol func}), %g2\n`;
- `{record_frame i.live ~label:label_after} call {emit_symbol "caml_c_call"}\n`;
- ` or %g2, %lo({emit_symbol func}), %g2\n` (* in delay slot *)
- end else begin
- ` call {emit_symbol func}\n`;
- fill_delay_slot dslot
- end
- | Lop(Istackoffset n) ->
- ` add %sp, {emit_int (-n)}, %sp\n`;
- stack_offset := !stack_offset + n
- | Lop(Iload(chunk, addr)) ->
- let dest = i.res.(0) in
- begin match chunk with
- Double_u ->
- emit_load "ld" addr i.arg dest;
- emit_load "ld" (offset_addressing addr 4) i.arg (next_in_pair dest)
- | Single ->
- emit_load "ld" addr i.arg dest;
- ` fstod {emit_reg dest}, {emit_reg dest}\n`
- | _ ->
- let loadinstr =
- match chunk with
- Byte_unsigned -> "ldub"
- | Byte_signed -> "ldsb"
- | Sixteen_unsigned -> "lduh"
- | Sixteen_signed -> "ldsh"
- | Double -> "ldd"
- | _ -> "ld" in
- emit_load loadinstr addr i.arg dest
- end
- | Lop(Istore(chunk, addr, _)) ->
- let src = i.arg.(0) in
- begin match chunk with
- Double_u ->
- emit_store "st" addr i.arg src;
- emit_store "st" (offset_addressing addr 4) i.arg (next_in_pair src)
- | Single ->
- ` fdtos {emit_reg src}, %f30\n`;
- emit_store "st" addr i.arg (phys_reg 115) (* %f30 *)
- | _ ->
- let storeinstr =
- match chunk with
- | Byte_unsigned | Byte_signed -> "stb"
- | Sixteen_unsigned | Sixteen_signed -> "sth"
- | Double -> "std"
- | _ -> "st" in
- emit_store storeinstr addr i.arg src
- end
- | Lop(Ialloc { words = n; label_after_call_gc; }) ->
- if !fastcode_flag then begin
- let lbl_cont = new_label() in
- if solaris then begin
- ` sub %l6, {emit_int n}, %l6\n`;
- ` cmp %l6, %l7\n`
- end else begin
- ` ld [%l7], %g1\n`;
- ` sub %l6, {emit_int n}, %l6\n`;
- ` cmp %l6, %g1\n`
- end;
- ` bgeu {emit_label lbl_cont}\n`;
- ` add %l6, 4, {emit_reg i.res.(0)}\n`; (* in delay slot *)
- `{record_frame i.live ?label:label_after_call_gc} call {emit_symbol "caml_call_gc"}\n`;
- ` mov {emit_int n}, %g2\n`; (* in delay slot *)
- ` add %l6, 4, {emit_reg i.res.(0)}\n`;
- `{emit_label lbl_cont}:\n`
- end else begin
- `{record_frame i.live} call {emit_symbol "caml_allocN"}\n`;
- ` mov {emit_int n}, %g2\n`; (* in delay slot *)
- ` add %l6, 4, {emit_reg i.res.(0)}\n`
- end
- | Lop(Iintop(Icomp cmp)) ->
- ` cmp {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`;
- if !arch_version = SPARC_V9 then begin
- let comp = name_for_int_movcc cmp in
- ` mov 0, {emit_reg i.res.(0)}\n`;
- ` mov{emit_string comp} %icc, 1, {emit_reg i.res.(0)}\n`
- end
- else begin
- let comp = name_for_int_comparison cmp
- and lbl = new_label() in
- ` {emit_string comp},a {emit_label lbl}\n`;
- ` mov 1, {emit_reg i.res.(0)}\n`;
- ` mov 0, {emit_reg i.res.(0)}\n`;
- `{emit_label lbl}:\n`
- end
- | Lop(Iintop (Icheckbound _)) ->
- ` cmp {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`;
- if solaris then
- ` tleu 5\n` (* 5 = ST_RANGE_CHECK *)
- else begin
- if !range_check_trap = 0 then range_check_trap := new_label();
- ` bleu {emit_label !range_check_trap}\n`;
- ` nop\n` (* delay slot *)
- end
- | Lop(Iintop Idiv) ->
- ` sra {emit_reg i.arg.(0)}, 31, %g1\n`;
- ` wr %g1, %y\n`;
- ` sdiv {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}, {emit_reg i.res.(0)}\n`
- | Lop(Iintop Imulh) ->
- ` smul {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}, %g1\n`;
- ` rd %y, {emit_reg i.res.(0)}\n`
- | Lop(Iintop op) ->
- let instr = name_for_int_operation op in
- ` {emit_string instr} {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}, {emit_reg i.res.(0)}\n`
- | Lop(Iintop_imm(Ilsl, 1)) ->
- (* UltraSPARC has two add units but only one shifter. *)
- ` add {emit_reg i.arg.(0)}, {emit_reg i.arg.(0)}, {emit_reg i.res.(0)}\n`
- | Lop(Iintop_imm(Icomp cmp, n)) ->
- ` cmp {emit_reg i.arg.(0)}, {emit_int n}\n`;
- if !arch_version = SPARC_V9 then begin
- let comp = name_for_int_movcc cmp in
- ` mov 0, {emit_reg i.res.(0)}\n`;
- ` mov{emit_string comp} %icc, 1, {emit_reg i.res.(0)}\n`
- end else begin
- let comp = name_for_int_comparison cmp
- and lbl = new_label() in
- ` {emit_string comp},a {emit_label lbl}\n`;
- ` mov 1, {emit_reg i.res.(0)}\n`;
- ` mov 0, {emit_reg i.res.(0)}\n`;
- `{emit_label lbl}:\n`
- end
- | Lop(Iintop_imm(Icheckbound _, n)) ->
- ` cmp {emit_reg i.arg.(0)}, {emit_int n}\n`;
- if solaris then
- ` tleu 5\n` (* 5 = ST_RANGE_CHECK *)
- else begin
- if !range_check_trap = 0 then range_check_trap := new_label();
- ` bleu {emit_label !range_check_trap}\n`;
- ` nop\n` (* delay slot *)
- end
- | Lop(Iintop_imm(Imulh, n)) ->
- ` smul {emit_reg i.arg.(0)}, {emit_int n}, %g1\n`;
- ` rd %y, {emit_reg i.res.(0)}\n`
- | Lop(Iintop_imm(op, n)) ->
- let instr = name_for_int_operation op in
- ` {emit_string instr} {emit_reg i.arg.(0)}, {emit_int n}, {emit_reg i.res.(0)}\n`
- | Lop(Inegf | Iabsf as op) ->
- let instr = name_for_float_operation op in
- ` {emit_string instr} {emit_reg i.arg.(0)}, {emit_reg i.res.(0)}\n`;
- if !arch_version <> SPARC_V9 then
- ` fmovs {emit_reg(next_in_pair i.arg.(0))}, {emit_reg(next_in_pair i.res.(0))}\n`
- | Lop(Iaddf | Isubf | Imulf | Idivf as op) ->
- let instr = name_for_float_operation op in
- ` {emit_string instr} {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}, {emit_reg i.res.(0)}\n`
- | Lop(Ifloatofint) ->
- ` sub %sp, 8, %sp\n`;
- ` st {emit_reg i.arg.(0)}, [%sp + 96]\n`;
- ` ld [%sp + 96], %f30\n`;
- ` add %sp, 8, %sp\n`;
- ` fitod %f30, {emit_reg i.res.(0)}\n`
- | Lop(Iintoffloat) ->
- ` fdtoi {emit_reg i.arg.(0)}, %f30\n`;
- ` sub %sp, 8, %sp\n`;
- ` st %f30, [%sp + 96]\n`;
- ` ld [%sp + 96], {emit_reg i.res.(0)}\n`;
- ` add %sp, 8, %sp\n`
- | Lop(Ispecific _) ->
- assert false
- | Lreloadretaddr ->
- let n = frame_size() in
- ` ld [%sp + {emit_int(n - 4 + 96)}], %o7\n`
- | Lreturn ->
- let n = frame_size() in
- ` retl\n`;
- if n = 0 then
- ` nop\n`
- else
- ` add %sp, {emit_int n}, %sp\n`
- | Llabel lbl ->
- `{emit_label lbl}:\n`
- | Lbranch lbl ->
- ` b {emit_label lbl}\n`;
- fill_delay_slot dslot
- | Lcondbranch(tst, lbl) ->
- begin match tst with
- Itruetest ->
- ` tst {emit_reg i.arg.(0)}\n`;
- ` bne {emit_label lbl}\n`
- | Ifalsetest ->
- ` tst {emit_reg i.arg.(0)}\n`;
- ` be {emit_label lbl}\n`
- | Iinttest cmp ->
- let comp = name_for_int_comparison cmp in
- ` cmp {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`;
- ` {emit_string comp} {emit_label lbl}\n`
- | Iinttest_imm(cmp, n) ->
- let comp = name_for_int_comparison cmp in
- ` cmp {emit_reg i.arg.(0)}, {emit_int n}\n`;
- ` {emit_string comp} {emit_label lbl}\n`
- | Ifloattest(cmp, neg) ->
- let comp = name_for_float_comparison cmp neg in
- ` fcmpd {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`;
- ` nop\n`;
- ` {emit_string comp} {emit_label lbl}\n`
- | Ioddtest ->
- ` andcc {emit_reg i.arg.(0)}, 1, %g0\n`;
- ` bne {emit_label lbl}\n`
- | Ieventest ->
- ` andcc {emit_reg i.arg.(0)}, 1, %g0\n`;
- ` be {emit_label lbl}\n`
- end;
- fill_delay_slot dslot
- | Lcondbranch3(lbl0, lbl1, lbl2) ->
- ` cmp {emit_reg i.arg.(0)}, 1\n`;
- begin match lbl0 with
- None -> ()
- | Some lbl -> ` bl {emit_label lbl}\n nop\n`
- end;
- begin match lbl1 with
- None -> ()
- | Some lbl -> ` be {emit_label lbl}\n nop\n`
- end;
- begin match lbl2 with
- None -> ()
- | Some lbl -> ` bg {emit_label lbl}\n nop\n`
- end
- | Lswitch jumptbl ->
- let lbl_jumptbl = new_label() in
- ` sethi %hi({emit_label lbl_jumptbl}), %g1\n`;
- ` or %g1, %lo({emit_label lbl_jumptbl}), %g1\n`;
- ` sll {emit_reg i.arg.(0)}, 2, %g2\n`;
- ` ld [%g1 + %g2], %g1\n`;
- ` jmp %g1\n`; (* poor scheduling *)
- ` nop\n`;
- `{emit_label lbl_jumptbl}:`;
- for i = 0 to Array.length jumptbl - 1 do
- ` .word {emit_label jumptbl.(i)}\n`
- done
- | Lsetuptrap lbl ->
- ` call {emit_label lbl}\n`;
- ` sub %sp, 8, %sp\n` (* in delay slot *)
- | Lpushtrap ->
- stack_offset := !stack_offset + 8;
- ` st %o7, [%sp + 96]\n`;
- ` st %l5, [%sp + 100]\n`;
- ` mov %sp, %l5\n`
- | Lpoptrap ->
- ` ld [%sp + 100], %l5\n`;
- ` add %sp, 8, %sp\n`;
- stack_offset := !stack_offset - 8
- | Lraise _ ->
- ` ld [%l5 + 96], %g1\n`;
- ` mov %l5, %sp\n`;
- ` ld [%sp + 100], %l5\n`;
- ` jmp %g1 + 8\n`;
- ` add %sp, 8, %sp\n`
-
-and fill_delay_slot = function
- None -> ` nop\n`
- | Some i -> emit_instr i None
-
-(* Checks if a pseudo-instruction expands to exactly one machine instruction
- that does not branch. *)
-
-let is_one_instr_op = function
- Imulh | Idiv | Imod | Icomp _ | Icheckbound _ -> false
- | _ -> true
-
-let is_one_instr i =
- match i.desc with
- Lop op ->
- begin match op with
- Imove | Ispill | Ireload ->
- i.arg.(0).typ <> Float && i.res.(0).typ <> Float
- | Iconst_int n -> is_native_immediate n
- | Istackoffset _ -> true
- | Iload(_, Iindexed n) -> i.res.(0).typ <> Float && is_immediate n
- | Istore(_, Iindexed n, _) -> i.arg.(0).typ <> Float && is_immediate n
- | Iintop(op) -> is_one_instr_op op
- | Iintop_imm(op, _) -> is_one_instr_op op
- | Iaddf | Isubf | Imulf | Idivf -> true
- | Iabsf | Inegf -> !arch_version = SPARC_V9
- | _ -> false
- end
- | _ -> false
-
-let no_interference res arg =
- try
- for i = 0 to Array.length arg - 1 do
- for j = 0 to Array.length res - 1 do
- if arg.(i).loc = res.(j).loc then raise Exit
- done
- done;
- true
- with Exit ->
- false
-
-(* Emit a sequence of instructions, trying to fill delay slots for branches *)
-
-let rec emit_all i =
- match i with
- {desc = Lend} -> ()
- | {next = {desc = Lop(Icall_imm _)
- | Lop(Iextcall { alloc = false; }) | Lbranch _}}
- when is_one_instr i ->
- emit_instr i.next (Some i);
- emit_all i.next.next
- | {next = {desc = Lop(Itailcall_imm { func; _ })}}
- when func = !function_name && is_one_instr i ->
- emit_instr i.next (Some i);
- emit_all i.next.next
- | {next = {desc = Lop(Icall_ind _)}}
- when is_one_instr i && no_interference i.res i.next.arg ->
- emit_instr i.next (Some i);
- emit_all i.next.next
- | {next = {desc = Lcondbranch(_, _)}}
- when is_one_instr i && no_interference i.res i.next.arg ->
- emit_instr i.next (Some i);
- emit_all i.next.next
- | _ ->
- emit_instr i None;
- emit_all i.next
-
-(* Emission of a function declaration *)
-
-let fundecl fundecl =
- function_name := fundecl.fun_name;
- fastcode_flag := fundecl.fun_fast;
- tailrec_entry_point := new_label();
- range_check_trap := 0;
- stack_offset := 0;
- float_constants := [];
- ` .text\n`;
- ` .align 4\n`;
- ` .global {emit_symbol fundecl.fun_name}\n`;
- if Config.system = "solaris" then
- ` .type {emit_symbol fundecl.fun_name},#function\n`;
- `{emit_symbol fundecl.fun_name}:\n`;
- if !Clflags.gprofile then emit_profile();
- let n = frame_size() in
- if n > 0 then
- ` sub %sp, {emit_int n}, %sp\n`;
- if !contains_calls then
- ` st %o7, [%sp + {emit_int(n - 4 + 96)}]\n`;
- `{emit_label !tailrec_entry_point}:\n`;
- emit_all fundecl.fun_body;
- if !range_check_trap > 0 then begin
- `{emit_label !range_check_trap}:\n`;
- ` call {emit_symbol "caml_ml_array_bound_error"}\n`;
- ` nop\n`
- end;
- emit_size fundecl.fun_name;
- List.iter emit_float_constant !float_constants
-
-(* Emission of data *)
-
-let emit_item = function
- Cglobal_symbol s ->
- ` .global {emit_symbol s}\n`;
- | Cdefine_symbol s ->
- `{emit_symbol s}:\n`
- | Cint8 n ->
- ` .byte {emit_int n}\n`
- | Cint16 n ->
- ` .half {emit_int n}\n`
- | Cint32 n ->
- ` .word {emit_nativeint n}\n`
- | Cint n ->
- ` .word {emit_nativeint n}\n`
- | Csingle f ->
- emit_float32_directive ".word" (Int32.bits_of_float f)
- | Cdouble f ->
- emit_float64_split_directive ".word" (Int64.bits_of_float f)
- | Csymbol_address s ->
- ` .word {emit_symbol s}\n`
- | Cstring s ->
- emit_string_directive " .ascii " s
- | Cskip n ->
- if n > 0 then ` .skip {emit_int n}\n`
- | Calign n ->
- ` .align {emit_int n}\n`
-
-let data l =
- ` .data\n`;
- List.iter emit_item l
-
-(* Beginning / end of an assembly file *)
-
-let begin_assembly() =
- let lbl_begin = Compilenv.make_symbol (Some "data_begin") in
- ` .data\n`;
- ` .global {emit_symbol lbl_begin}\n`;
- `{emit_symbol lbl_begin}:\n`;
- let lbl_begin = Compilenv.make_symbol (Some "code_begin") in
- ` .text\n`;
- ` .global {emit_symbol lbl_begin}\n`;
- `{emit_symbol lbl_begin}:\n`
-
-let end_assembly() =
- ` .text\n`;
- let lbl_end = Compilenv.make_symbol (Some "code_end") in
- ` .global {emit_symbol lbl_end}\n`;
- `{emit_symbol lbl_end}:\n`;
- ` .data\n`;
- let lbl_end = Compilenv.make_symbol (Some "data_end") in
- ` .global {emit_symbol lbl_end}\n`;
- `{emit_symbol lbl_end}:\n`;
- ` .word 0\n`;
- let lbl = Compilenv.make_symbol (Some "frametable") in
- rodata ();
- ` .global {emit_symbol lbl}\n`;
- if Config.system = "solaris" then
- ` .type {emit_symbol lbl},#object\n`;
- `{emit_symbol lbl}:\n`;
- ` .word {emit_int (List.length !frame_descriptors)}\n`;
- List.iter emit_frame !frame_descriptors;
- emit_size lbl;
- frame_descriptors := []
+++ /dev/null
-(**************************************************************************)
-(* *)
-(* OCaml *)
-(* *)
-(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
-(* *)
-(* Copyright 1996 Institut National de Recherche en Informatique et *)
-(* en Automatique. *)
-(* *)
-(* All rights reserved. This file is distributed under the terms of *)
-(* the GNU Lesser General Public License version 2.1, with the *)
-(* special exception on linking described in the file LICENSE. *)
-(* *)
-(**************************************************************************)
-
-(* Description of the Sparc processor *)
-
-open Misc
-open Cmm
-open Reg
-open Arch
-open Mach
-
-(* Instruction selection *)
-
-let word_addressed = false
-
-(* Registers available for register allocation *)
-
-(* Register map:
- %o0 - %o5 0 - 5 function results, C functions args / res
- %i0 - %i5 6 - 11 function arguments, preserved by C
- %l0 - %l4 12 - 16 general purpose, preserved by C
- %g3 - %g4 17 - 18 general purpose, not preserved by C
-
- %l5 exception pointer
- %l6 allocation pointer
- %l7 address of allocation limit
-
- %g0 always zero
- %g1 - %g2 temporaries
- %g5 - %g7 reserved for system libraries
-
- %f0 - %f10 100 - 105 function arguments and results
- %f12 - %f28 106 - 114 general purpose
- %f30 temporary *)
-
-let int_reg_name = [|
- (* 0-5 *) "%o0"; "%o1"; "%o2"; "%o3"; "%o4"; "%o5";
- (* 6-11 *) "%i0"; "%i1"; "%i2"; "%i3"; "%i4"; "%i5";
- (* 12-16 *) "%l0"; "%l1"; "%l2"; "%l3"; "%l4";
- (* 17-18 *) "%g3"; "%g4"
-|]
-
-let float_reg_name = [|
- (* 100-105 *) "%f0"; "%f2"; "%f4"; "%f6"; "%f8"; "%f10";
- (* 106-109 *) "%f12"; "%f14"; "%f16"; "%f18";
- (* 110-114 *) "%f20"; "%f22"; "%f24"; "%f26"; "%f28";
- (* 115 *) "%f30";
- (* Odd parts of register pairs *)
- (* 116-121 *) "%f1"; "%f3"; "%f5"; "%f7"; "%f9"; "%f11";
- (* 122-125 *) "%f13"; "%f15"; "%f17"; "%f19";
- (* 126-130 *) "%f21"; "%f23"; "%f25"; "%f27"; "%f29";
- (* 131 *) "%f31"
-|]
-
-let num_register_classes = 2
-
-let register_class r =
- match r.typ with
- | Val | Int | Addr -> 0
- | Float -> 1
-
-let num_available_registers = [| 19; 15 |]
-
-let first_available_register = [| 0; 100 |]
-
-let register_name r =
- if r < 100 then int_reg_name.(r) else float_reg_name.(r - 100)
-
-let rotate_registers = true
-
-(* Representation of hard registers by pseudo-registers *)
-
-let hard_int_reg =
- let v = Array.make 19 Reg.dummy in
- for i = 0 to 18 do v.(i) <- Reg.at_location Int (Reg i) done;
- v
-
-let hard_float_reg =
- let v = Array.make 32 Reg.dummy in
- for i = 0 to 31 do v.(i) <- Reg.at_location Float (Reg(100 + i)) done;
- v
-
-let all_phys_regs =
- Array.append hard_int_reg (Array.sub hard_float_reg 0 15)
- (* No need to include the odd parts of float register pairs,
- nor the temporary register %f30 *)
-
-let phys_reg n =
- if n < 100 then hard_int_reg.(n) else hard_float_reg.(n - 100)
-
-let stack_slot slot ty =
- Reg.at_location ty (Stack slot)
-
-let loc_spacetime_node_hole = Reg.dummy (* Spacetime unsupported *)
-
-(* Calling conventions *)
-
-let calling_conventions first_int last_int first_float last_float make_stack
- arg =
- let loc = Array.make (Array.length arg) Reg.dummy in
- let int = ref first_int in
- let float = ref first_float in
- let ofs = ref 0 in
- for i = 0 to Array.length arg - 1 do
- match arg.(i).typ with
- | Val | Int | Addr as ty ->
- if !int <= last_int then begin
- loc.(i) <- phys_reg !int;
- incr int
- end else begin
- loc.(i) <- stack_slot (make_stack !ofs) ty;
- ofs := !ofs + size_int
- end
- | Float ->
- if !float <= last_float then begin
- loc.(i) <- phys_reg !float;
- incr float
- end else begin
- loc.(i) <- stack_slot (make_stack !ofs) Float;
- ofs := !ofs + size_float
- end
- done;
- (loc, Misc.align !ofs 8) (* Keep stack 8-aligned *)
-
-let incoming ofs = Incoming ofs
-let outgoing ofs = Outgoing ofs
-let not_supported _ofs = fatal_error "Proc.loc_results: cannot call"
-
-let max_arguments_for_tailcalls = 10
-
-let loc_arguments arg =
- calling_conventions 6 15 100 105 outgoing arg
-let loc_parameters arg =
- let (loc, _ofs) = calling_conventions 6 15 100 105 incoming arg in loc
-let loc_results res =
- let (loc, _ofs) = calling_conventions 0 5 100 105 not_supported res in loc
-
-(* On the Sparc, all arguments to C functions, even floating-point arguments,
- are passed in %o0..%o5, then on the stack *)
-
-let loc_external_arguments arg =
- let loc = Array.make (Array.length arg) [| |] in
- let reg = ref 0 (* %o0 *) in
- let ofs = ref (-4) in (* start at sp + 92 = sp + 96 - 4 *)
- let next_loc typ =
- if !reg <= 5 (* %o5 *) then begin
- assert (size_component typ = size_int);
- let loc = phys_reg !reg in
- incr reg;
- loc
- end else begin
- let loc = stack_slot (outgoing !ofs) typ in
- ofs := !ofs + size_component typ;
- loc
- end
- in
- for i = 0 to Array.length arg - 1 do
- match arg.(i) with
- | [| { typ = (Val | Int | Addr as typ) } |] ->
- loc.(i) <- [| next_loc typ |]
- | [| { typ = Float } |] ->
- if !reg <= 5 then begin
- let loc1 = next_loc Int in
- let loc2 = next_loc Int in
- loc.(i) <- [| loc1; loc2 |]
- end else
- loc.(i) <- [| next_loc Float |]
- | [| { typ = Int }; { typ = Int } |] ->
- (* int64 unboxed *)
- let loc1 = next_loc Int in
- let loc2 = next_loc Int in
- loc.(i) <- [| loc1; loc2 |]
- | _ ->
- fatal_error "Proc.loc_external_arguments: cannot call"
- done;
- (* Keep stack 8-aligned *)
- (loc, Misc.align (!ofs + 4) 8)
-
-let loc_external_results res =
- let (loc, _ofs) = calling_conventions 0 1 100 100 not_supported res in loc
-
-let loc_exn_bucket = phys_reg 0 (* $o0 *)
-
-(* Volatile registers: none *)
-
-let regs_are_volatile _rs = false
-
-(* Registers destroyed by operations *)
-
-let destroyed_at_c_call = (* %l0-%l4, %i0-%i5 preserved *)
- Array.of_list(List.map phys_reg
- [0; 1; 2; 3; 4; 5; 17; 18;
- 100; 101; 102; 103; 104; 105; 106; 107;
- 108; 109; 110; 111; 112; 113; 114])
-
-let destroyed_at_oper = function
- Iop(Icall_ind _ | Icall_imm _ | Iextcall { alloc = true; }) ->
- all_phys_regs
- | Iop(Iextcall { alloc = false; }) -> destroyed_at_c_call
- | _ -> [||]
-
-let destroyed_at_raise = all_phys_regs
-
-(* Maximal register pressure *)
-
-let safe_register_pressure = function
- Iextcall _ -> 0
- | _ -> 15
-
-let max_register_pressure = function
- Iextcall _ -> [| 11; 0 |]
- | _ -> [| 19; 15 |]
-
-(* Pure operations (without any side effect besides updating their result
- registers). *)
-
-let op_is_pure = function
- | Icall_ind _ | Icall_imm _ | Itailcall_ind _ | Itailcall_imm _
- | Iextcall _ | Istackoffset _ | Istore _ | Ialloc _
- | Iintop(Icheckbound _) | Iintop_imm(Icheckbound _, _) -> false
- | _ -> true
-
-(* Layout of the stack *)
-
-let num_stack_slots = [| 0; 0 |]
-let contains_calls = ref false
-
-(* Calling the assembler and the archiver *)
-
-let assemble_file infile outfile =
- let asflags = begin match !arch_version with
- SPARC_V7 -> " -o "
- | SPARC_V8 -> " -xarch=v8 -o "
- | SPARC_V9 -> " -xarch=v8plus -o "
- end in
- Ccomp.command (Config.asm ^ asflags ^
- Filename.quote outfile ^ " " ^ Filename.quote infile)
-
-let init () = ()
+++ /dev/null
-(**************************************************************************)
-(* *)
-(* OCaml *)
-(* *)
-(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
-(* *)
-(* Copyright 1996 Institut National de Recherche en Informatique et *)
-(* en Automatique. *)
-(* *)
-(* All rights reserved. This file is distributed under the terms of *)
-(* the GNU Lesser General Public License version 2.1, with the *)
-(* special exception on linking described in the file LICENSE. *)
-(* *)
-(**************************************************************************)
-
-(* Reloading for the Sparc *)
-
-let fundecl f =
- (new Reloadgen.reload_generic)#fundecl f
+++ /dev/null
-(**************************************************************************)
-(* *)
-(* OCaml *)
-(* *)
-(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
-(* *)
-(* Copyright 1996 Institut National de Recherche en Informatique et *)
-(* en Automatique. *)
-(* *)
-(* All rights reserved. This file is distributed under the terms of *)
-(* the GNU Lesser General Public License version 2.1, with the *)
-(* special exception on linking described in the file LICENSE. *)
-(* *)
-(**************************************************************************)
-
-open Cmm
-open Mach
-
-(* Instruction scheduling for the Sparc *)
-
-class scheduler = object
-
-inherit Schedgen.scheduler_generic
-
-(* Latencies (in cycles). *)
-
-(* UltraSPARC issues two integer operations, plus a single load or store,
- per cycle. At most one of the integer instructions may be a shift.
- Most integer operations have one cycle latency. Unsigned loads take
- two cycles. Signed loads take three cycles. Conditional moves have
- two cycle latency and may not issue in the same cycle as any other
- instruction. Floating point issue rules are complicated, but in
- general independent add and multiply can dual issue with four cycle
- latency. *)
-
-method oper_latency = function
- Ireload -> 2
- | Iload((Byte_signed|Sixteen_signed|Thirtytwo_signed), _) -> 3
- | Iload(_, _) -> 2
- | Iconst_float _ -> 2 (* turned into a load *)
- | Inegf | Iabsf | Iaddf | Isubf | Imulf -> 4
- | Idivf -> 15
- | _ -> 1
-
-(* Issue cycles. Rough approximations. *)
-
-method oper_issue_cycles = function
- Iconst_float _ -> 2
- | Iconst_symbol _ -> 2
- | Ialloc _ -> 6
- | Iintop(Icomp _) -> 4
- | Iintop(Icheckbound _) -> 2
- | Iintop_imm(Icomp _, _) -> 4
- | Iintop_imm(Icheckbound _, _) -> 2
- | Inegf -> 2
- | Iabsf -> 2
- | Ifloatofint -> 6
- | Iintoffloat -> 6
- | _ -> 1
-
-end
-
-let fundecl f = (new scheduler)#schedule_fundecl f
+++ /dev/null
-(**************************************************************************)
-(* *)
-(* OCaml *)
-(* *)
-(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
-(* *)
-(* Copyright 1997 Institut National de Recherche en Informatique et *)
-(* en Automatique. *)
-(* *)
-(* All rights reserved. This file is distributed under the terms of *)
-(* the GNU Lesser General Public License version 2.1, with the *)
-(* special exception on linking described in the file LICENSE. *)
-(* *)
-(**************************************************************************)
-
-(* Instruction selection for the Sparc processor *)
-
-open Cmm
-open Reg
-open Arch
-open Mach
-
-class selector = object (self)
-
-inherit Selectgen.selector_generic as super
-
-method is_immediate n = (n <= 4095) && (n >= -4096)
-
-method select_addressing _chunk = function
- Cconst_symbol s ->
- (Ibased(s, 0), Ctuple [])
- | Cop((Caddv | Cadda), [Cconst_symbol s; Cconst_int n], _) ->
- (Ibased(s, n), Ctuple [])
- | Cop((Caddv | Cadda), [arg; Cconst_int n], _) ->
- (Iindexed n, arg)
- | Cop((Caddv | Cadda as op),
- [arg1; Cop(Caddi, [arg2; Cconst_int n], _)], dbg) ->
- (Iindexed n, Cop(op, [arg1; arg2], dbg))
- | arg ->
- (Iindexed 0, arg)
-
-method private iextcall (func, alloc) =
- Iextcall { func; alloc; label_after = Cmm.new_label (); }
-
-method! select_operation op args dbg =
- match (op, args) with
- (* For SPARC V7 multiplication, division and modulus are turned into
- calls to C library routines.
- For SPARC V8 and V9, use hardware multiplication and division,
- but C library routine for modulus. *)
- (Cmuli, _) when !arch_version = SPARC_V7 ->
- (self#iextcall(".umul", false), args)
- | (Cdivi, _) when !arch_version = SPARC_V7 ->
- (self#iextcall(".div", false), args)
- | (Cmodi, _) ->
- (self#iextcall(".rem", false), args)
- | _ ->
- super#select_operation op args dbg
-
-(* Override insert_move_args to deal correctly with floating-point
- arguments being passed into pairs of integer registers. *)
-method! insert_move_args arg loc stacksize =
- if stacksize <> 0 then self#insert (Iop(Istackoffset stacksize)) [||] [||];
- let locpos = ref 0 in
- for i = 0 to Array.length arg - 1 do
- let src = arg.(i) in
- let dst = loc.(!locpos) in
- match (src, dst) with
- ({typ = Float}, {typ = Int}) ->
- let dst2 = loc.(!locpos + 1) in
- self#insert (Iop Imove) [|src|] [|dst; dst2|];
- locpos := !locpos + 2
- | (_, _) ->
- self#insert_move src dst;
- incr locpos
- done
-
-end
-
-let fundecl f = (new selector)#emit_fundecl f
| Iop op ->
let new_before =
(* Quick check to see if the register pressure is below the maximum *)
- if Reg.Set.cardinal i.live + Array.length i.res <=
- Proc.safe_register_pressure op
+ if !Clflags.use_linscan ||
+ (Reg.Set.cardinal i.live + Array.length i.res <=
+ Proc.safe_register_pressure op)
then before
else add_superpressure_regs op i.live i.res before in
let after =
let before1 = Reg.diff_set_array after i.res in
let before =
match i.desc with
- Iop Icall_ind _ | Iop(Icall_imm _) | Iop(Iextcall _)
+ Iop Icall_ind _ | Iop(Icall_imm _) | Iop(Iextcall _) | Iop(Ialloc _)
| Iop(Iintop (Icheckbound _)) | Iop(Iintop_imm((Icheckbound _), _)) ->
Reg.Set.union before1 !spill_at_raise
| _ ->
module type I = sig
val string_block_length : Cmm.expression -> Cmm.expression
val transl_switch :
- Cmm.expression -> int -> int ->
+ Location.t -> Cmm.expression -> int -> int ->
(int * Cmm.expression) list -> Cmm.expression ->
Cmm.expression
end
(*
Switch according to pattern size
Argument from_ind is the starting index, it can be zero
- or one (when the swicth on the cell 0 has already been performed.
+ or one (when the switch on the cell 0 has already been performed.
In that latter case pattern len is string length-1 and is corrected.
*)
(len,act))
(by_size cases) in
let id = gen_size_id () in
- ignore dbg;
- let switch = I.transl_switch (Cvar id) 1 max_int size_cases default in
+ let loc = Debuginfo.to_location dbg in
+ let switch = I.transl_switch loc (Cvar id) 1 max_int size_cases default in
mk_let_size id str switch
(*
module type I = sig
val string_block_length : Cmm.expression -> Cmm.expression
val transl_switch :
- Cmm.expression -> int -> int ->
+ Location.t -> Cmm.expression -> int -> int ->
(int * Cmm.expression) list -> Cmm.expression ->
Cmm.expression
end
List.iter loop args;
ignore_debuginfo dbg
| Uswitch (cond, { us_index_consts; us_actions_consts;
- us_index_blocks; us_actions_blocks }) ->
+ us_index_blocks; us_actions_blocks }, dbg) ->
loop cond;
ignore_int_array us_index_consts;
Array.iter loop us_actions_consts;
ignore_int_array us_index_blocks;
- Array.iter loop us_actions_blocks
+ Array.iter loop us_actions_blocks;
+ ignore_debuginfo dbg
| Ustringswitch (cond, branches, default) ->
loop cond;
List.iter (fun (str, branch) ->
examine_argument_list args;
ignore_debuginfo dbg
| Uswitch (cond, { us_index_consts; us_actions_consts;
- us_index_blocks; us_actions_blocks }) ->
+ us_index_blocks; us_actions_blocks }, dbg) ->
examine_argument_list [cond];
ignore_int_array us_index_consts;
Array.iter (fun action ->
let_stack := [];
loop action)
us_actions_blocks;
+ ignore_debuginfo dbg;
let_stack := []
| Ustringswitch (cond, branches, default) ->
examine_argument_list [cond];
let_stack := []
| Ustaticfail (static_exn, args) ->
ignore_int static_exn;
- ignore_ulambda_list args;
- let_stack := []
+ examine_argument_list args
| Ucatch (static_exn, idents, body, handler) ->
ignore_int static_exn;
ignore_ident_list idents;
| Uprim (prim, args, dbg) ->
let args = substitute_let_moveable_list is_let_moveable env args in
Uprim (prim, args, dbg)
- | Uswitch (cond, sw) ->
+ | Uswitch (cond, sw, dbg) ->
let cond = substitute_let_moveable is_let_moveable env cond in
let sw =
{ sw with
sw.us_actions_blocks;
}
in
- Uswitch (cond, sw)
+ Uswitch (cond, sw, dbg)
| Ustringswitch (cond, branches, default) ->
let cond = substitute_let_moveable is_let_moveable env cond in
let branches =
un_anf_and_moveable ident_info env body
| Constant, _, true, false
(* A constant expression bound to an unassigned identifier can replace any
- occurances of the identifier. *)
+ occurrences of the identifier. *)
| Moveable, true, true, false ->
(* A moveable expression bound to a linear unassigned [Ident.t]
may replace the single occurrence of the identifier. *)
both_moveable args_moveable (primitive_moveable prim args ident_info)
in
Uprim (prim, args, dbg), moveable
- | Uswitch (cond, sw) ->
+ | Uswitch (cond, sw, dbg) ->
let cond = un_anf ident_info env cond in
let sw =
{ sw with
us_actions_blocks = un_anf_array ident_info env sw.us_actions_blocks;
}
in
- Uswitch (cond, sw), Fixed
+ Uswitch (cond, sw, dbg), Fixed
| Ustringswitch (cond, branches, default) ->
let cond = un_anf ident_info env cond in
let branches =
| RoundTruncate -> "roundsd.trunc"
| RoundNearest -> "roundsd.near"
-
(* These hooks can be used to insert optimization passes on
the assembly code. *)
let assembler_passes = ref ([] : (asm_program -> asm_program) list)
| S_win32 | S_win64 -> true
| _ -> false
+let use_plt =
+ match system with
+ | S_macosx | S_mingw64 | S_cygwin | S_win64 -> false
+ | _ -> !Clflags.dlcode
+
(* Shall we use an external assembler command ?
If [binary_content] contains some data, we can directly
save it. Otherwise, we have to ask an external command.
val masm: bool
val windows:bool
+(** Whether calls need to go via the PLT. *)
+val use_plt : bool
+
(** Support for plumbing a binary code emitter *)
val register_internal_assembler: (asm_program -> string -> unit) -> unit
-afl.o: afl.c ../byterun/caml/misc.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/osdeps.h
-alloc.o: alloc.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/custom.h ../byterun/caml/major_gc.h \
- ../byterun/caml/freelist.h ../byterun/caml/memory.h \
- ../byterun/caml/gc.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h ../byterun/caml/stacks.h
-array.o: array.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
- ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/signals.h ../byterun/caml/spacetime.h \
- ../byterun/caml/io.h ../byterun/caml/stack.h
-backtrace.o: backtrace.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/memory.h ../byterun/caml/gc.h \
- ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/backtrace.h ../byterun/caml/exec.h \
- ../byterun/caml/backtrace_prim.h ../byterun/caml/fail.h
-backtrace_prim.o: backtrace_prim.c ../byterun/caml/alloc.h \
- ../byterun/caml/misc.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/backtrace.h \
- ../byterun/caml/exec.h ../byterun/caml/backtrace_prim.h \
- ../byterun/caml/memory.h ../byterun/caml/gc.h \
+startup_aux.$(O): startup_aux.c ../byterun/caml/backtrace.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
+ ../byterun/caml/exec.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/stack.h
-callback.o: callback.c ../byterun/caml/callback.h \
+ ../byterun/caml/callback.h ../byterun/caml/osdeps.h \
+ ../byterun/caml/startup_aux.h
+startup.$(O): startup.c ../byterun/caml/callback.h \
../byterun/caml/mlvalues.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/misc.h ../byterun/caml/fail.h ../byterun/caml/memory.h \
- ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
- ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h
-clambda_checks.o: clambda_checks.c ../byterun/caml/mlvalues.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/misc.h
-compact.o: compact.c ../byterun/caml/address_class.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/misc.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/finalise.h \
- ../byterun/caml/roots.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
- ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/gc_ctrl.h \
- ../byterun/caml/weak.h ../byterun/caml/compact.h
-compare.o: compare.c ../byterun/caml/custom.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/misc.h \
- ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
- ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-custom.o: custom.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/custom.h ../byterun/caml/fail.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
+ ../byterun/caml/backtrace.h ../byterun/caml/exec.h \
+ ../byterun/caml/custom.h ../byterun/caml/debugger.h \
+ ../byterun/caml/fail.h ../byterun/caml/freelist.h ../byterun/caml/gc.h \
+ ../byterun/caml/gc_ctrl.h ../byterun/caml/intext.h \
+ ../byterun/caml/io.h ../byterun/caml/memory.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
+ ../byterun/caml/printexc.h ../byterun/caml/stack.h \
+ ../byterun/caml/startup_aux.h ../byterun/caml/sys.h
+main.$(O): main.c ../byterun/caml/misc.h ../byterun/caml/config.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/sys.h ../byterun/caml/osdeps.h \
../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-debugger.o: debugger.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/debugger.h ../byterun/caml/osdeps.h
-dynlink.o: dynlink.c ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/dynlink.h \
+fail.$(O): fail.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/fail.h ../byterun/caml/io.h \
+ ../byterun/caml/gc.h ../byterun/caml/memory.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
+ ../byterun/caml/printexc.h ../byterun/caml/signals.h \
+ ../byterun/caml/stack.h ../byterun/caml/roots.h \
+ ../byterun/caml/callback.h
+roots.$(O): roots.c ../byterun/caml/finalise.h ../byterun/caml/roots.h \
+ ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/address_class.h ../byterun/caml/globroots.h \
+ ../byterun/caml/stack.h
+signals.$(O): signals.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/callback.h \
../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/osdeps.h ../byterun/caml/prims.h \
- ../byterun/caml/signals.h
-extern.o: extern.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/custom.h ../byterun/caml/fail.h ../byterun/caml/gc.h \
- ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/md5.h \
- ../byterun/caml/memory.h ../byterun/caml/major_gc.h \
- ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h ../byterun/caml/reverse.h
-fail.o: fail.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/fail.h ../byterun/caml/io.h ../byterun/caml/gc.h \
- ../byterun/caml/memory.h ../byterun/caml/major_gc.h \
- ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h ../byterun/caml/printexc.h \
- ../byterun/caml/signals.h ../byterun/caml/stack.h \
- ../byterun/caml/roots.h ../byterun/caml/callback.h
-finalise.o: finalise.c ../byterun/caml/callback.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/misc.h ../byterun/caml/compact.h \
- ../byterun/caml/fail.h ../byterun/caml/finalise.h \
- ../byterun/caml/roots.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/roots.h ../byterun/caml/signals.h \
+ ../byterun/caml/signals_machdep.h ../byterun/caml/sys.h
+signals_asm.$(O): signals_asm.c ../byterun/caml/fail.h \
+ ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/signals.h
-floats.o: floats.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/osdeps.h ../byterun/caml/signals.h \
+ ../byterun/caml/signals_machdep.h signals_osdep.h \
+ ../byterun/caml/stack.h ../byterun/caml/spacetime.h \
+ ../byterun/caml/io.h
+misc.$(O): misc.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/misc.h ../byterun/caml/memory.h \
+ ../byterun/caml/gc.h ../byterun/caml/mlvalues.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/reverse.h ../byterun/caml/stacks.h
-freelist.o: freelist.c ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/freelist.h ../byterun/caml/misc.h \
+ ../byterun/caml/osdeps.h ../byterun/caml/version.h
+freelist.$(O): freelist.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/freelist.h ../byterun/caml/misc.h \
../byterun/caml/mlvalues.h ../byterun/caml/gc.h \
../byterun/caml/gc_ctrl.h ../byterun/caml/memory.h \
../byterun/caml/major_gc.h ../byterun/caml/minor_gc.h \
../byterun/caml/address_class.h
-gc_ctrl.o: gc_ctrl.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/backtrace.h ../byterun/caml/exec.h \
- ../byterun/caml/compact.h ../byterun/caml/custom.h \
+major_gc.$(O): major_gc.c ../byterun/caml/compact.h ../byterun/caml/config.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
../byterun/caml/fail.h ../byterun/caml/finalise.h \
../byterun/caml/roots.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
- ../byterun/caml/stack.h ../byterun/caml/startup_aux.h
-globroots.o: globroots.c ../byterun/caml/memory.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/gc.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
- ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/roots.h ../byterun/caml/globroots.h
-hash.o: hash.c ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/misc.h ../byterun/caml/custom.h \
- ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/weak.h
+minor_gc.$(O): minor_gc.c ../byterun/caml/custom.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
+ ../byterun/caml/fail.h ../byterun/caml/finalise.h \
+ ../byterun/caml/roots.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/hash.h
-intern.o: intern.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/callback.h ../byterun/caml/custom.h \
- ../byterun/caml/fail.h ../byterun/caml/gc.h ../byterun/caml/intext.h \
- ../byterun/caml/io.h ../byterun/caml/md5.h ../byterun/caml/memory.h \
+ ../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
+ ../byterun/caml/weak.h
+memory.$(O): memory.c ../byterun/caml/address_class.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/fail.h ../byterun/caml/freelist.h ../byterun/caml/gc.h \
+ ../byterun/caml/gc_ctrl.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/signals.h
+alloc.$(O): alloc.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/reverse.h
-ints.o: ints.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/custom.h ../byterun/caml/fail.h \
- ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/memory.h \
+ ../byterun/caml/stacks.h
+compare.$(O): compare.c ../byterun/caml/custom.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/misc.h ../byterun/caml/fail.h ../byterun/caml/memory.h \
../byterun/caml/gc.h ../byterun/caml/major_gc.h \
../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
../byterun/caml/address_class.h
-io.o: io.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/alloc.h \
- ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/custom.h ../byterun/caml/fail.h ../byterun/caml/io.h \
+ints.$(O): ints.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
+ ../byterun/caml/fail.h ../byterun/caml/intext.h ../byterun/caml/io.h \
+ ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
+floats.$(O): floats.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/osdeps.h ../byterun/caml/signals.h \
- ../byterun/caml/sys.h
-lexing.o: lexing.c ../byterun/caml/fail.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/stacks.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/reverse.h ../byterun/caml/stacks.h
+str.$(O): str.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
+ ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-main.o: main.c ../byterun/caml/misc.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/sys.h
-major_gc.o: major_gc.c ../byterun/caml/compact.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/custom.h ../byterun/caml/fail.h \
- ../byterun/caml/finalise.h ../byterun/caml/roots.h \
+array.$(O): array.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
- ../byterun/caml/weak.h
-md5.o: md5.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/fail.h ../byterun/caml/md5.h ../byterun/caml/io.h \
- ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/signals.h ../byterun/caml/spacetime.h \
+ ../byterun/caml/io.h ../byterun/caml/stack.h
+io.$(O): io.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
+ ../byterun/caml/fail.h ../byterun/caml/io.h ../byterun/caml/memory.h \
+ ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
+ ../byterun/caml/signals.h ../byterun/caml/sys.h
+extern.$(O): extern.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
+ ../byterun/caml/fail.h ../byterun/caml/gc.h ../byterun/caml/intext.h \
+ ../byterun/caml/io.h ../byterun/caml/md5.h ../byterun/caml/memory.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
../byterun/caml/reverse.h
-memory.o: memory.c ../byterun/caml/address_class.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/misc.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
- ../byterun/caml/freelist.h ../byterun/caml/gc.h \
- ../byterun/caml/gc_ctrl.h ../byterun/caml/major_gc.h \
- ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/signals.h
-meta.o: meta.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/fail.h ../byterun/caml/fix_code.h \
- ../byterun/caml/interp.h ../byterun/caml/intext.h ../byterun/caml/io.h \
+intern.$(O): intern.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/callback.h \
+ ../byterun/caml/custom.h ../byterun/caml/fail.h ../byterun/caml/gc.h \
+ ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/md5.h \
+ ../byterun/caml/memory.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/address_class.h ../byterun/caml/reverse.h
+hash.$(O): hash.c ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
+ ../byterun/caml/custom.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
+ ../byterun/caml/hash.h
+sys.$(O): sys.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/debugger.h \
+ ../byterun/caml/fail.h ../byterun/caml/gc_ctrl.h ../byterun/caml/io.h \
+ ../byterun/caml/osdeps.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
+ ../byterun/caml/signals.h ../byterun/caml/stacks.h \
+ ../byterun/caml/sys.h ../byterun/caml/version.h \
+ ../byterun/caml/callback.h ../byterun/caml/startup_aux.h
+parsing.$(O): parsing.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/prims.h ../byterun/caml/stacks.h
-minor_gc.o: minor_gc.c ../byterun/caml/custom.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/misc.h ../byterun/caml/fail.h \
+ ../byterun/caml/alloc.h
+gc_ctrl.$(O): gc_ctrl.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/backtrace.h \
+ ../byterun/caml/exec.h ../byterun/caml/compact.h \
+ ../byterun/caml/custom.h ../byterun/caml/fail.h \
../byterun/caml/finalise.h ../byterun/caml/roots.h \
../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
- ../byterun/caml/weak.h
-misc.o: misc.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/misc.h \
+ ../byterun/caml/stack.h ../byterun/caml/startup_aux.h
+terminfo.$(O): terminfo.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/fail.h ../byterun/caml/io.h
+md5.$(O): md5.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
+ ../byterun/caml/md5.h ../byterun/caml/io.h ../byterun/caml/memory.h \
+ ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/address_class.h ../byterun/caml/reverse.h
+obj.$(O): obj.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/fail.h ../byterun/caml/gc.h \
+ ../byterun/caml/interp.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/freelist.h ../byterun/caml/memory.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
+ ../byterun/caml/prims.h ../byterun/caml/spacetime.h \
+ ../byterun/caml/io.h ../byterun/caml/stack.h
+lexing.$(O): lexing.c ../byterun/caml/fail.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/stacks.h \
../byterun/caml/memory.h ../byterun/caml/gc.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
+unix.$(O): unix.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/fail.h ../byterun/caml/misc.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/memory.h \
+ ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
- ../byterun/caml/version.h
-natdynlink.o: natdynlink.c ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/signals.h ../byterun/caml/sys.h ../byterun/caml/io.h \
+ ../byterun/caml/alloc.h
+printexc.$(O): printexc.c ../byterun/caml/backtrace.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
+ ../byterun/caml/exec.h ../byterun/caml/callback.h \
+ ../byterun/caml/debugger.h ../byterun/caml/fail.h \
+ ../byterun/caml/printexc.h ../byterun/caml/memory.h \
+ ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/address_class.h
+callback.$(O): callback.c ../byterun/caml/callback.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
+ ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/stack.h ../byterun/caml/callback.h \
- ../byterun/caml/alloc.h ../byterun/caml/intext.h ../byterun/caml/io.h \
- ../byterun/caml/osdeps.h ../byterun/caml/fail.h \
- ../byterun/caml/signals.h ../byterun/caml/hooks.h
-obj.o: obj.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/fail.h ../byterun/caml/gc.h ../byterun/caml/interp.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
+weak.$(O): weak.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h ../byterun/caml/prims.h \
- ../byterun/caml/spacetime.h ../byterun/caml/io.h \
- ../byterun/caml/stack.h
-parsing.o: parsing.c ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
../byterun/caml/memory.h ../byterun/caml/gc.h \
- ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/alloc.h
-printexc.o: printexc.c ../byterun/caml/backtrace.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/misc.h ../byterun/caml/exec.h \
- ../byterun/caml/callback.h ../byterun/caml/debugger.h \
- ../byterun/caml/fail.h ../byterun/caml/printexc.h
-roots.o: roots.c ../byterun/caml/finalise.h ../byterun/caml/roots.h \
- ../byterun/caml/misc.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
+ ../byterun/caml/weak.h
+compact.$(O): compact.c ../byterun/caml/address_class.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/finalise.h ../byterun/caml/roots.h \
../byterun/caml/memory.h ../byterun/caml/gc.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/major_gc.h \
- ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h ../byterun/caml/globroots.h \
- ../byterun/caml/stack.h
-signals.o: signals.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/callback.h ../byterun/caml/fail.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/gc_ctrl.h \
+ ../byterun/caml/weak.h ../byterun/caml/compact.h
+finalise.$(O): finalise.c ../byterun/caml/callback.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
+ ../byterun/caml/compact.h ../byterun/caml/fail.h \
+ ../byterun/caml/finalise.h ../byterun/caml/roots.h \
../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/roots.h ../byterun/caml/signals.h \
- ../byterun/caml/signals_machdep.h ../byterun/caml/sys.h
-signals_asm.o: signals_asm.c ../byterun/caml/fail.h \
- ../byterun/caml/misc.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
+ ../byterun/caml/signals.h
+custom.$(O): custom.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
+ ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
+globroots.$(O): globroots.c ../byterun/caml/memory.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/gc.h ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
+ ../byterun/caml/roots.h ../byterun/caml/globroots.h
+backtrace_prim.$(O): backtrace_prim.c ../byterun/caml/alloc.h \
+ ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/backtrace.h ../byterun/caml/exec.h \
+ ../byterun/caml/backtrace_prim.h ../byterun/caml/memory.h \
+ ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/address_class.h ../byterun/caml/stack.h
+backtrace.$(O): backtrace.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
../byterun/caml/mlvalues.h ../byterun/caml/memory.h \
../byterun/caml/gc.h ../byterun/caml/major_gc.h \
../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
- ../byterun/caml/signals.h ../byterun/caml/signals_machdep.h \
- signals_osdep.h ../byterun/caml/stack.h ../byterun/caml/spacetime.h \
- ../byterun/caml/io.h
-spacetime.o: spacetime.c ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/address_class.h ../byterun/caml/backtrace.h \
+ ../byterun/caml/exec.h ../byterun/caml/backtrace_prim.h \
+ ../byterun/caml/fail.h
+natdynlink.$(O): natdynlink.c ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/memory.h \
+ ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/address_class.h ../byterun/caml/stack.h \
+ ../byterun/caml/callback.h ../byterun/caml/alloc.h \
+ ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/osdeps.h \
+ ../byterun/caml/fail.h ../byterun/caml/signals.h \
+ ../byterun/caml/hooks.h
+debugger.$(O): debugger.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/debugger.h \
+ ../byterun/caml/osdeps.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
+meta.$(O): meta.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
+ ../byterun/caml/fix_code.h ../byterun/caml/interp.h \
+ ../byterun/caml/intext.h ../byterun/caml/io.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
+ ../byterun/caml/prims.h ../byterun/caml/stacks.h
+dynlink.$(O): dynlink.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/dynlink.h \
+ ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
+ ../byterun/caml/osdeps.h ../byterun/caml/prims.h \
+ ../byterun/caml/signals.h
+clambda_checks.$(O): clambda_checks.c ../byterun/caml/mlvalues.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/misc.h
+spacetime.$(O): spacetime.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
../byterun/caml/mlvalues.h ../byterun/caml/backtrace_prim.h \
../byterun/caml/backtrace.h ../byterun/caml/exec.h \
../byterun/caml/fail.h ../byterun/caml/gc.h ../byterun/caml/intext.h \
../byterun/caml/osdeps.h ../byterun/caml/roots.h \
../byterun/caml/signals.h ../byterun/caml/stack.h \
../byterun/caml/sys.h ../byterun/caml/spacetime.h
-spacetime_offline.o: spacetime_offline.c ../byterun/caml/alloc.h \
- ../byterun/caml/misc.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/fail.h ../byterun/caml/gc.h \
+spacetime_snapshot.$(O): spacetime_snapshot.c ../byterun/caml/alloc.h \
+ ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/backtrace_prim.h ../byterun/caml/backtrace.h \
+ ../byterun/caml/exec.h ../byterun/caml/custom.h ../byterun/caml/fail.h \
+ ../byterun/caml/gc.h ../byterun/caml/gc_ctrl.h \
../byterun/caml/intext.h ../byterun/caml/io.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
../byterun/caml/address_class.h ../byterun/caml/roots.h \
../byterun/caml/signals.h ../byterun/caml/stack.h \
- ../byterun/caml/sys.h ../byterun/caml/spacetime.h ../config/s.h
-spacetime_snapshot.o: spacetime_snapshot.c ../byterun/caml/alloc.h \
- ../byterun/caml/misc.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/backtrace_prim.h \
- ../byterun/caml/backtrace.h ../byterun/caml/exec.h \
- ../byterun/caml/custom.h ../byterun/caml/fail.h ../byterun/caml/gc.h \
- ../byterun/caml/gc_ctrl.h ../byterun/caml/intext.h \
- ../byterun/caml/io.h ../byterun/caml/major_gc.h \
- ../byterun/caml/freelist.h ../byterun/caml/memory.h \
+ ../byterun/caml/sys.h ../byterun/caml/spacetime.h
+spacetime_offline.$(O): spacetime_offline.c ../byterun/caml/alloc.h \
+ ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
+ ../byterun/caml/gc.h ../byterun/caml/intext.h ../byterun/caml/io.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/address_class.h ../byterun/caml/roots.h \
+ ../byterun/caml/signals.h ../byterun/caml/stack.h \
+ ../byterun/caml/sys.h ../byterun/caml/spacetime.h
+afl.$(O): afl.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/osdeps.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
+bigarray.$(O): bigarray.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/bigarray.h \
+ ../byterun/caml/custom.h ../byterun/caml/fail.h \
+ ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/hash.h \
+ ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
+startup_aux.p.$(O): startup_aux.c ../byterun/caml/backtrace.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
+ ../byterun/caml/exec.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/roots.h ../byterun/caml/signals.h \
- ../byterun/caml/stack.h ../byterun/caml/sys.h \
- ../byterun/caml/spacetime.h
-startup.o: startup.c ../byterun/caml/callback.h \
+ ../byterun/caml/callback.h ../byterun/caml/osdeps.h \
+ ../byterun/caml/startup_aux.h
+startup.p.$(O): startup.c ../byterun/caml/callback.h \
../byterun/caml/mlvalues.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/misc.h ../byterun/caml/backtrace.h \
- ../byterun/caml/exec.h ../byterun/caml/custom.h \
- ../byterun/caml/debugger.h ../byterun/caml/fail.h \
- ../byterun/caml/freelist.h ../byterun/caml/gc.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
+ ../byterun/caml/backtrace.h ../byterun/caml/exec.h \
+ ../byterun/caml/custom.h ../byterun/caml/debugger.h \
+ ../byterun/caml/fail.h ../byterun/caml/freelist.h ../byterun/caml/gc.h \
../byterun/caml/gc_ctrl.h ../byterun/caml/intext.h \
../byterun/caml/io.h ../byterun/caml/memory.h \
../byterun/caml/major_gc.h ../byterun/caml/minor_gc.h \
../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
../byterun/caml/printexc.h ../byterun/caml/stack.h \
../byterun/caml/startup_aux.h ../byterun/caml/sys.h
-startup_aux.o: startup_aux.c ../byterun/caml/backtrace.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/misc.h ../byterun/caml/exec.h ../byterun/caml/memory.h \
- ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
- ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
- ../byterun/caml/startup_aux.h
-str.o: str.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/fail.h
-sys.o: sys.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/alloc.h \
- ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/debugger.h ../byterun/caml/fail.h \
- ../byterun/caml/gc_ctrl.h ../byterun/caml/instruct.h \
- ../byterun/caml/io.h ../byterun/caml/osdeps.h \
- ../byterun/caml/signals.h ../byterun/caml/stacks.h \
+main.p.$(O): main.c ../byterun/caml/misc.h ../byterun/caml/config.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/sys.h ../byterun/caml/osdeps.h \
../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
+fail.p.$(O): fail.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/fail.h ../byterun/caml/io.h \
+ ../byterun/caml/gc.h ../byterun/caml/memory.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
+ ../byterun/caml/printexc.h ../byterun/caml/signals.h \
+ ../byterun/caml/stack.h ../byterun/caml/roots.h \
+ ../byterun/caml/callback.h
+roots.p.$(O): roots.c ../byterun/caml/finalise.h ../byterun/caml/roots.h \
+ ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/address_class.h ../byterun/caml/globroots.h \
+ ../byterun/caml/stack.h
+signals.p.$(O): signals.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/callback.h \
+ ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/sys.h ../byterun/caml/version.h
-terminfo.o: terminfo.c ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/fail.h ../byterun/caml/io.h
-unix.o: unix.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/fail.h \
- ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/roots.h ../byterun/caml/signals.h \
+ ../byterun/caml/signals_machdep.h ../byterun/caml/sys.h
+signals_asm.p.$(O): signals_asm.c ../byterun/caml/fail.h \
+ ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/mlvalues.h \
../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
../byterun/caml/osdeps.h ../byterun/caml/signals.h \
- ../byterun/caml/sys.h ../byterun/caml/io.h
-weak.o: weak.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/fail.h ../byterun/caml/major_gc.h \
- ../byterun/caml/freelist.h ../byterun/caml/memory.h \
- ../byterun/caml/gc.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h ../byterun/caml/weak.h
-afl.p.o: afl.c ../byterun/caml/misc.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/osdeps.h
-alloc.p.o: alloc.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/custom.h ../byterun/caml/major_gc.h \
- ../byterun/caml/freelist.h ../byterun/caml/memory.h \
- ../byterun/caml/gc.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h ../byterun/caml/stacks.h
-array.p.o: array.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/signals_machdep.h signals_osdep.h \
+ ../byterun/caml/stack.h ../byterun/caml/spacetime.h \
+ ../byterun/caml/io.h
+misc.p.$(O): misc.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/misc.h ../byterun/caml/memory.h \
+ ../byterun/caml/gc.h ../byterun/caml/mlvalues.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/signals.h ../byterun/caml/spacetime.h \
- ../byterun/caml/io.h ../byterun/caml/stack.h
-backtrace.p.o: backtrace.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/osdeps.h ../byterun/caml/version.h
+freelist.p.$(O): freelist.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/freelist.h ../byterun/caml/misc.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/gc.h \
+ ../byterun/caml/gc_ctrl.h ../byterun/caml/memory.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/address_class.h
+major_gc.p.$(O): major_gc.c ../byterun/caml/compact.h ../byterun/caml/config.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
+ ../byterun/caml/fail.h ../byterun/caml/finalise.h \
+ ../byterun/caml/roots.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/backtrace.h ../byterun/caml/exec.h \
- ../byterun/caml/backtrace_prim.h ../byterun/caml/fail.h
-backtrace_prim.p.o: backtrace_prim.c ../byterun/caml/alloc.h \
- ../byterun/caml/misc.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/backtrace.h \
- ../byterun/caml/exec.h ../byterun/caml/backtrace_prim.h \
- ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
+ ../byterun/caml/weak.h
+minor_gc.p.$(O): minor_gc.c ../byterun/caml/custom.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
+ ../byterun/caml/fail.h ../byterun/caml/finalise.h \
+ ../byterun/caml/roots.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/stack.h
-callback.p.o: callback.c ../byterun/caml/callback.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
+ ../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
+ ../byterun/caml/weak.h
+memory.p.$(O): memory.c ../byterun/caml/address_class.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/fail.h ../byterun/caml/freelist.h ../byterun/caml/gc.h \
+ ../byterun/caml/gc_ctrl.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/signals.h
+alloc.p.$(O): alloc.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
+ ../byterun/caml/stacks.h
+compare.p.$(O): compare.c ../byterun/caml/custom.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
../byterun/caml/misc.h ../byterun/caml/fail.h ../byterun/caml/memory.h \
../byterun/caml/gc.h ../byterun/caml/major_gc.h \
../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
../byterun/caml/address_class.h
-clambda_checks.p.o: clambda_checks.c ../byterun/caml/mlvalues.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/misc.h
-compact.p.o: compact.c ../byterun/caml/address_class.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/misc.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/finalise.h \
- ../byterun/caml/roots.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
- ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/gc_ctrl.h \
- ../byterun/caml/weak.h ../byterun/caml/compact.h
-compare.p.o: compare.c ../byterun/caml/custom.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/misc.h \
- ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ints.p.$(O): ints.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
+ ../byterun/caml/fail.h ../byterun/caml/intext.h ../byterun/caml/io.h \
+ ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-custom.p.o: custom.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/custom.h ../byterun/caml/fail.h \
+floats.p.$(O): floats.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
+ ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
+ ../byterun/caml/reverse.h ../byterun/caml/stacks.h
+str.p.$(O): str.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-debugger.p.o: debugger.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/debugger.h ../byterun/caml/osdeps.h
-dynlink.p.o: dynlink.c ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/dynlink.h \
- ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+array.p.$(O): array.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
+ ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/osdeps.h ../byterun/caml/prims.h \
- ../byterun/caml/signals.h
-extern.p.o: extern.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/signals.h ../byterun/caml/spacetime.h \
+ ../byterun/caml/io.h ../byterun/caml/stack.h
+io.p.$(O): io.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
+ ../byterun/caml/fail.h ../byterun/caml/io.h ../byterun/caml/memory.h \
+ ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
+ ../byterun/caml/signals.h ../byterun/caml/sys.h
+extern.p.$(O): extern.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
+ ../byterun/caml/fail.h ../byterun/caml/gc.h ../byterun/caml/intext.h \
+ ../byterun/caml/io.h ../byterun/caml/md5.h ../byterun/caml/memory.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
+ ../byterun/caml/reverse.h
+intern.p.$(O): intern.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/callback.h \
../byterun/caml/custom.h ../byterun/caml/fail.h ../byterun/caml/gc.h \
../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/md5.h \
../byterun/caml/memory.h ../byterun/caml/major_gc.h \
../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
../byterun/caml/address_class.h ../byterun/caml/reverse.h
-fail.p.o: fail.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/fail.h ../byterun/caml/io.h ../byterun/caml/gc.h \
- ../byterun/caml/memory.h ../byterun/caml/major_gc.h \
- ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h ../byterun/caml/printexc.h \
- ../byterun/caml/signals.h ../byterun/caml/stack.h \
- ../byterun/caml/roots.h ../byterun/caml/callback.h
-finalise.p.o: finalise.c ../byterun/caml/callback.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/misc.h ../byterun/caml/compact.h \
- ../byterun/caml/fail.h ../byterun/caml/finalise.h \
- ../byterun/caml/roots.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+hash.p.$(O): hash.c ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
+ ../byterun/caml/custom.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/signals.h
-floats.p.o: floats.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/hash.h
+sys.p.$(O): sys.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/debugger.h \
+ ../byterun/caml/fail.h ../byterun/caml/gc_ctrl.h ../byterun/caml/io.h \
+ ../byterun/caml/osdeps.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/reverse.h ../byterun/caml/stacks.h
-freelist.p.o: freelist.c ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/freelist.h ../byterun/caml/misc.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/gc.h \
- ../byterun/caml/gc_ctrl.h ../byterun/caml/memory.h \
- ../byterun/caml/major_gc.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h
-gc_ctrl.p.o: gc_ctrl.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/backtrace.h ../byterun/caml/exec.h \
- ../byterun/caml/compact.h ../byterun/caml/custom.h \
- ../byterun/caml/fail.h ../byterun/caml/finalise.h \
- ../byterun/caml/roots.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/signals.h ../byterun/caml/stacks.h \
+ ../byterun/caml/sys.h ../byterun/caml/version.h \
+ ../byterun/caml/callback.h ../byterun/caml/startup_aux.h
+parsing.p.$(O): parsing.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
+ ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
+ ../byterun/caml/alloc.h
+gc_ctrl.p.$(O): gc_ctrl.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/backtrace.h \
+ ../byterun/caml/exec.h ../byterun/caml/compact.h \
+ ../byterun/caml/custom.h ../byterun/caml/fail.h \
+ ../byterun/caml/finalise.h ../byterun/caml/roots.h \
+ ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
../byterun/caml/stack.h ../byterun/caml/startup_aux.h
-globroots.p.o: globroots.c ../byterun/caml/memory.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/gc.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
- ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+terminfo.p.$(O): terminfo.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/fail.h ../byterun/caml/io.h
+md5.p.$(O): md5.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
+ ../byterun/caml/md5.h ../byterun/caml/io.h ../byterun/caml/memory.h \
+ ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/address_class.h ../byterun/caml/reverse.h
+obj.p.$(O): obj.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/fail.h ../byterun/caml/gc.h \
+ ../byterun/caml/interp.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/freelist.h ../byterun/caml/memory.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/roots.h ../byterun/caml/globroots.h
-hash.p.o: hash.c ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/misc.h ../byterun/caml/custom.h \
+ ../byterun/caml/prims.h ../byterun/caml/spacetime.h \
+ ../byterun/caml/io.h ../byterun/caml/stack.h
+lexing.p.$(O): lexing.c ../byterun/caml/fail.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/stacks.h \
../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/hash.h
-intern.p.o: intern.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/callback.h ../byterun/caml/custom.h \
- ../byterun/caml/fail.h ../byterun/caml/gc.h ../byterun/caml/intext.h \
- ../byterun/caml/io.h ../byterun/caml/md5.h ../byterun/caml/memory.h \
- ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/reverse.h
-ints.p.o: ints.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/custom.h ../byterun/caml/fail.h \
- ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/memory.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
+unix.p.$(O): unix.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/fail.h ../byterun/caml/misc.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/memory.h \
+ ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
+ ../byterun/caml/signals.h ../byterun/caml/sys.h ../byterun/caml/io.h \
+ ../byterun/caml/alloc.h
+printexc.p.$(O): printexc.c ../byterun/caml/backtrace.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
+ ../byterun/caml/exec.h ../byterun/caml/callback.h \
+ ../byterun/caml/debugger.h ../byterun/caml/fail.h \
+ ../byterun/caml/printexc.h ../byterun/caml/memory.h \
../byterun/caml/gc.h ../byterun/caml/major_gc.h \
../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
../byterun/caml/address_class.h
-io.p.o: io.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/alloc.h \
- ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/custom.h ../byterun/caml/fail.h ../byterun/caml/io.h \
- ../byterun/caml/memory.h ../byterun/caml/gc.h \
- ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/osdeps.h ../byterun/caml/signals.h \
- ../byterun/caml/sys.h
-lexing.p.o: lexing.c ../byterun/caml/fail.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/stacks.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+callback.p.$(O): callback.c ../byterun/caml/callback.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
+ ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-main.p.o: main.c ../byterun/caml/misc.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/sys.h
-major_gc.p.o: major_gc.c ../byterun/caml/compact.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
+weak.p.$(O): weak.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
+ ../byterun/caml/weak.h
+compact.p.$(O): compact.c ../byterun/caml/address_class.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/custom.h ../byterun/caml/fail.h \
../byterun/caml/finalise.h ../byterun/caml/roots.h \
../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
- ../byterun/caml/weak.h
-md5.p.o: md5.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/fail.h ../byterun/caml/md5.h ../byterun/caml/io.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/gc_ctrl.h \
+ ../byterun/caml/weak.h ../byterun/caml/compact.h
+finalise.p.$(O): finalise.c ../byterun/caml/callback.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
+ ../byterun/caml/compact.h ../byterun/caml/fail.h \
+ ../byterun/caml/finalise.h ../byterun/caml/roots.h \
../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/reverse.h
-memory.p.o: memory.c ../byterun/caml/address_class.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/misc.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
- ../byterun/caml/freelist.h ../byterun/caml/gc.h \
- ../byterun/caml/gc_ctrl.h ../byterun/caml/major_gc.h \
- ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
../byterun/caml/signals.h
-meta.p.o: meta.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/fail.h ../byterun/caml/fix_code.h \
- ../byterun/caml/interp.h ../byterun/caml/intext.h ../byterun/caml/io.h \
+custom.p.$(O): custom.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
+ ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/memory.h ../byterun/caml/gc.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/prims.h ../byterun/caml/stacks.h
-minor_gc.p.o: minor_gc.c ../byterun/caml/custom.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/misc.h ../byterun/caml/fail.h \
- ../byterun/caml/finalise.h ../byterun/caml/roots.h \
- ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
+globroots.p.$(O): globroots.c ../byterun/caml/memory.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/gc.h ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
- ../byterun/caml/weak.h
-misc.p.o: misc.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/misc.h \
- ../byterun/caml/memory.h ../byterun/caml/gc.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/roots.h ../byterun/caml/globroots.h
+backtrace_prim.p.$(O): backtrace_prim.c ../byterun/caml/alloc.h \
+ ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/backtrace.h ../byterun/caml/exec.h \
+ ../byterun/caml/backtrace_prim.h ../byterun/caml/memory.h \
+ ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
- ../byterun/caml/version.h
-natdynlink.p.o: natdynlink.c ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/address_class.h ../byterun/caml/stack.h
+backtrace.p.$(O): backtrace.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/memory.h \
+ ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/address_class.h ../byterun/caml/backtrace.h \
+ ../byterun/caml/exec.h ../byterun/caml/backtrace_prim.h \
+ ../byterun/caml/fail.h
+natdynlink.p.$(O): natdynlink.c ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/memory.h \
+ ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/address_class.h ../byterun/caml/stack.h \
+ ../byterun/caml/callback.h ../byterun/caml/alloc.h \
+ ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/osdeps.h \
+ ../byterun/caml/fail.h ../byterun/caml/signals.h \
+ ../byterun/caml/hooks.h
+debugger.p.$(O): debugger.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/debugger.h \
+ ../byterun/caml/osdeps.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/stack.h ../byterun/caml/callback.h \
- ../byterun/caml/alloc.h ../byterun/caml/intext.h ../byterun/caml/io.h \
- ../byterun/caml/osdeps.h ../byterun/caml/fail.h \
- ../byterun/caml/signals.h ../byterun/caml/hooks.h
-obj.p.o: obj.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/fail.h ../byterun/caml/gc.h ../byterun/caml/interp.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
+meta.p.$(O): meta.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
+ ../byterun/caml/fix_code.h ../byterun/caml/interp.h \
+ ../byterun/caml/intext.h ../byterun/caml/io.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h ../byterun/caml/prims.h \
- ../byterun/caml/spacetime.h ../byterun/caml/io.h \
- ../byterun/caml/stack.h
-parsing.p.o: parsing.c ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
../byterun/caml/memory.h ../byterun/caml/gc.h \
- ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/alloc.h
-printexc.p.o: printexc.c ../byterun/caml/backtrace.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/misc.h ../byterun/caml/exec.h \
- ../byterun/caml/callback.h ../byterun/caml/debugger.h \
- ../byterun/caml/fail.h ../byterun/caml/printexc.h
-roots.p.o: roots.c ../byterun/caml/finalise.h ../byterun/caml/roots.h \
- ../byterun/caml/misc.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/memory.h ../byterun/caml/gc.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/major_gc.h \
- ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h ../byterun/caml/globroots.h \
- ../byterun/caml/stack.h
-signals.p.o: signals.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/callback.h ../byterun/caml/fail.h \
- ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/prims.h ../byterun/caml/stacks.h
+dynlink.p.$(O): dynlink.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/dynlink.h \
+ ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/roots.h ../byterun/caml/signals.h \
- ../byterun/caml/signals_machdep.h ../byterun/caml/sys.h
-signals_asm.p.o: signals_asm.c ../byterun/caml/fail.h \
- ../byterun/caml/misc.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/memory.h \
- ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
- ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
- ../byterun/caml/signals.h ../byterun/caml/signals_machdep.h \
- signals_osdep.h ../byterun/caml/stack.h ../byterun/caml/spacetime.h \
- ../byterun/caml/io.h
-spacetime.p.o: spacetime.c ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/osdeps.h ../byterun/caml/prims.h \
+ ../byterun/caml/signals.h
+clambda_checks.p.$(O): clambda_checks.c ../byterun/caml/mlvalues.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/misc.h
+spacetime.p.$(O): spacetime.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
../byterun/caml/mlvalues.h ../byterun/caml/backtrace_prim.h \
../byterun/caml/backtrace.h ../byterun/caml/exec.h \
../byterun/caml/fail.h ../byterun/caml/gc.h ../byterun/caml/intext.h \
../byterun/caml/osdeps.h ../byterun/caml/roots.h \
../byterun/caml/signals.h ../byterun/caml/stack.h \
../byterun/caml/sys.h ../byterun/caml/spacetime.h
-spacetime_offline.p.o: spacetime_offline.c ../byterun/caml/alloc.h \
- ../byterun/caml/misc.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/fail.h ../byterun/caml/gc.h \
+spacetime_snapshot.p.$(O): spacetime_snapshot.c ../byterun/caml/alloc.h \
+ ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/backtrace_prim.h ../byterun/caml/backtrace.h \
+ ../byterun/caml/exec.h ../byterun/caml/custom.h ../byterun/caml/fail.h \
+ ../byterun/caml/gc.h ../byterun/caml/gc_ctrl.h \
../byterun/caml/intext.h ../byterun/caml/io.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
../byterun/caml/address_class.h ../byterun/caml/roots.h \
../byterun/caml/signals.h ../byterun/caml/stack.h \
- ../byterun/caml/sys.h ../byterun/caml/spacetime.h ../config/s.h
-spacetime_snapshot.p.o: spacetime_snapshot.c ../byterun/caml/alloc.h \
- ../byterun/caml/misc.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/backtrace_prim.h \
- ../byterun/caml/backtrace.h ../byterun/caml/exec.h \
- ../byterun/caml/custom.h ../byterun/caml/fail.h ../byterun/caml/gc.h \
- ../byterun/caml/gc_ctrl.h ../byterun/caml/intext.h \
- ../byterun/caml/io.h ../byterun/caml/major_gc.h \
- ../byterun/caml/freelist.h ../byterun/caml/memory.h \
+ ../byterun/caml/sys.h ../byterun/caml/spacetime.h
+spacetime_offline.p.$(O): spacetime_offline.c ../byterun/caml/alloc.h \
+ ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
+ ../byterun/caml/gc.h ../byterun/caml/intext.h ../byterun/caml/io.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/address_class.h ../byterun/caml/roots.h \
+ ../byterun/caml/signals.h ../byterun/caml/stack.h \
+ ../byterun/caml/sys.h ../byterun/caml/spacetime.h
+afl.p.$(O): afl.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/osdeps.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
+bigarray.p.$(O): bigarray.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/bigarray.h \
+ ../byterun/caml/custom.h ../byterun/caml/fail.h \
+ ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/hash.h \
+ ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
+startup_aux.d.$(O): startup_aux.c ../byterun/caml/backtrace.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
+ ../byterun/caml/exec.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/roots.h ../byterun/caml/signals.h \
- ../byterun/caml/stack.h ../byterun/caml/sys.h \
- ../byterun/caml/spacetime.h
-startup.p.o: startup.c ../byterun/caml/callback.h \
+ ../byterun/caml/callback.h ../byterun/caml/osdeps.h \
+ ../byterun/caml/startup_aux.h
+startup.d.$(O): startup.c ../byterun/caml/callback.h \
../byterun/caml/mlvalues.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/misc.h ../byterun/caml/backtrace.h \
- ../byterun/caml/exec.h ../byterun/caml/custom.h \
- ../byterun/caml/debugger.h ../byterun/caml/fail.h \
- ../byterun/caml/freelist.h ../byterun/caml/gc.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
+ ../byterun/caml/backtrace.h ../byterun/caml/exec.h \
+ ../byterun/caml/custom.h ../byterun/caml/debugger.h \
+ ../byterun/caml/fail.h ../byterun/caml/freelist.h ../byterun/caml/gc.h \
../byterun/caml/gc_ctrl.h ../byterun/caml/intext.h \
../byterun/caml/io.h ../byterun/caml/memory.h \
../byterun/caml/major_gc.h ../byterun/caml/minor_gc.h \
../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
../byterun/caml/printexc.h ../byterun/caml/stack.h \
../byterun/caml/startup_aux.h ../byterun/caml/sys.h
-startup_aux.p.o: startup_aux.c ../byterun/caml/backtrace.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/misc.h ../byterun/caml/exec.h ../byterun/caml/memory.h \
- ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
- ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
- ../byterun/caml/startup_aux.h
-str.p.o: str.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/fail.h
-sys.p.o: sys.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/alloc.h \
- ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/debugger.h ../byterun/caml/fail.h \
- ../byterun/caml/gc_ctrl.h ../byterun/caml/instruct.h \
- ../byterun/caml/io.h ../byterun/caml/osdeps.h \
- ../byterun/caml/signals.h ../byterun/caml/stacks.h \
+main.d.$(O): main.c ../byterun/caml/misc.h ../byterun/caml/config.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/sys.h ../byterun/caml/osdeps.h \
../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
+fail.d.$(O): fail.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/fail.h ../byterun/caml/io.h \
+ ../byterun/caml/gc.h ../byterun/caml/memory.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
+ ../byterun/caml/printexc.h ../byterun/caml/signals.h \
+ ../byterun/caml/stack.h ../byterun/caml/roots.h \
+ ../byterun/caml/callback.h
+roots.d.$(O): roots.c ../byterun/caml/finalise.h ../byterun/caml/roots.h \
+ ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/address_class.h ../byterun/caml/globroots.h \
+ ../byterun/caml/stack.h
+signals.d.$(O): signals.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/callback.h \
+ ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/sys.h ../byterun/caml/version.h
-terminfo.p.o: terminfo.c ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/fail.h ../byterun/caml/io.h
-unix.p.o: unix.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/fail.h \
- ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/roots.h ../byterun/caml/signals.h \
+ ../byterun/caml/signals_machdep.h ../byterun/caml/sys.h
+signals_asm.d.$(O): signals_asm.c ../byterun/caml/fail.h \
+ ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/mlvalues.h \
../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
../byterun/caml/osdeps.h ../byterun/caml/signals.h \
- ../byterun/caml/sys.h ../byterun/caml/io.h
-weak.p.o: weak.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/fail.h ../byterun/caml/major_gc.h \
- ../byterun/caml/freelist.h ../byterun/caml/memory.h \
- ../byterun/caml/gc.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h ../byterun/caml/weak.h
-afl.d.o: afl.c ../byterun/caml/misc.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/osdeps.h
-alloc.d.o: alloc.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/custom.h ../byterun/caml/major_gc.h \
- ../byterun/caml/freelist.h ../byterun/caml/memory.h \
- ../byterun/caml/gc.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h ../byterun/caml/stacks.h
-array.d.o: array.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
- ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/signals.h ../byterun/caml/spacetime.h \
- ../byterun/caml/io.h ../byterun/caml/stack.h
-backtrace.d.o: backtrace.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/signals_machdep.h signals_osdep.h \
+ ../byterun/caml/stack.h ../byterun/caml/spacetime.h \
+ ../byterun/caml/io.h
+misc.d.$(O): misc.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/misc.h ../byterun/caml/memory.h \
+ ../byterun/caml/gc.h ../byterun/caml/mlvalues.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/backtrace.h ../byterun/caml/exec.h \
- ../byterun/caml/backtrace_prim.h ../byterun/caml/fail.h
-backtrace_prim.d.o: backtrace_prim.c ../byterun/caml/alloc.h \
- ../byterun/caml/misc.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/backtrace.h \
- ../byterun/caml/exec.h ../byterun/caml/backtrace_prim.h \
- ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/osdeps.h ../byterun/caml/version.h
+freelist.d.$(O): freelist.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/freelist.h ../byterun/caml/misc.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/gc.h \
+ ../byterun/caml/gc_ctrl.h ../byterun/caml/memory.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/address_class.h
+major_gc.d.$(O): major_gc.c ../byterun/caml/compact.h ../byterun/caml/config.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
+ ../byterun/caml/fail.h ../byterun/caml/finalise.h \
+ ../byterun/caml/roots.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/stack.h
-callback.d.o: callback.c ../byterun/caml/callback.h \
+ ../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
+ ../byterun/caml/weak.h
+minor_gc.d.$(O): minor_gc.c ../byterun/caml/custom.h \
../byterun/caml/mlvalues.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/misc.h ../byterun/caml/fail.h ../byterun/caml/memory.h \
- ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
- ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h
-clambda_checks.d.o: clambda_checks.c ../byterun/caml/mlvalues.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/misc.h
-compact.d.o: compact.c ../byterun/caml/address_class.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/misc.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/finalise.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
+ ../byterun/caml/fail.h ../byterun/caml/finalise.h \
../byterun/caml/roots.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/gc_ctrl.h \
- ../byterun/caml/weak.h ../byterun/caml/compact.h
-compare.d.o: compare.c ../byterun/caml/custom.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/misc.h \
- ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
+ ../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
+ ../byterun/caml/weak.h
+memory.d.$(O): memory.c ../byterun/caml/address_class.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/fail.h ../byterun/caml/freelist.h ../byterun/caml/gc.h \
+ ../byterun/caml/gc_ctrl.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/signals.h
+alloc.d.$(O): alloc.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-custom.d.o: custom.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/custom.h ../byterun/caml/fail.h \
../byterun/caml/memory.h ../byterun/caml/gc.h \
- ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-debugger.d.o: debugger.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/debugger.h ../byterun/caml/osdeps.h
-dynlink.d.o: dynlink.c ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/dynlink.h \
- ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
- ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/osdeps.h ../byterun/caml/prims.h \
- ../byterun/caml/signals.h
-extern.d.o: extern.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/custom.h ../byterun/caml/fail.h ../byterun/caml/gc.h \
- ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/md5.h \
- ../byterun/caml/memory.h ../byterun/caml/major_gc.h \
- ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h ../byterun/caml/reverse.h
-fail.d.o: fail.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/fail.h ../byterun/caml/io.h ../byterun/caml/gc.h \
- ../byterun/caml/memory.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/stacks.h
+compare.d.$(O): compare.c ../byterun/caml/custom.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/misc.h ../byterun/caml/fail.h ../byterun/caml/memory.h \
+ ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h ../byterun/caml/printexc.h \
- ../byterun/caml/signals.h ../byterun/caml/stack.h \
- ../byterun/caml/roots.h ../byterun/caml/callback.h
-finalise.d.o: finalise.c ../byterun/caml/callback.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/misc.h ../byterun/caml/compact.h \
- ../byterun/caml/fail.h ../byterun/caml/finalise.h \
- ../byterun/caml/roots.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/address_class.h
+ints.d.$(O): ints.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
+ ../byterun/caml/fail.h ../byterun/caml/intext.h ../byterun/caml/io.h \
+ ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/signals.h
-floats.d.o: floats.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
+floats.d.$(O): floats.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
+ ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
../byterun/caml/reverse.h ../byterun/caml/stacks.h
-freelist.d.o: freelist.c ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/freelist.h ../byterun/caml/misc.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/gc.h \
- ../byterun/caml/gc_ctrl.h ../byterun/caml/memory.h \
- ../byterun/caml/major_gc.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h
-gc_ctrl.d.o: gc_ctrl.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/backtrace.h ../byterun/caml/exec.h \
- ../byterun/caml/compact.h ../byterun/caml/custom.h \
- ../byterun/caml/fail.h ../byterun/caml/finalise.h \
- ../byterun/caml/roots.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
- ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
- ../byterun/caml/stack.h ../byterun/caml/startup_aux.h
-globroots.d.o: globroots.c ../byterun/caml/memory.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/gc.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
+str.d.$(O): str.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
+ ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/roots.h ../byterun/caml/globroots.h
-hash.d.o: hash.c ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/misc.h ../byterun/caml/custom.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
+array.d.$(O): array.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/hash.h
-intern.d.o: intern.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/callback.h ../byterun/caml/custom.h \
+ ../byterun/caml/signals.h ../byterun/caml/spacetime.h \
+ ../byterun/caml/io.h ../byterun/caml/stack.h
+io.d.$(O): io.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
+ ../byterun/caml/fail.h ../byterun/caml/io.h ../byterun/caml/memory.h \
+ ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
+ ../byterun/caml/signals.h ../byterun/caml/sys.h
+extern.d.$(O): extern.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
../byterun/caml/fail.h ../byterun/caml/gc.h ../byterun/caml/intext.h \
../byterun/caml/io.h ../byterun/caml/md5.h ../byterun/caml/memory.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
../byterun/caml/reverse.h
-ints.d.o: ints.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/custom.h ../byterun/caml/fail.h \
- ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/memory.h \
- ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
+intern.d.$(O): intern.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/callback.h \
+ ../byterun/caml/custom.h ../byterun/caml/fail.h ../byterun/caml/gc.h \
+ ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/md5.h \
+ ../byterun/caml/memory.h ../byterun/caml/major_gc.h \
../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h
-io.d.o: io.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/alloc.h \
- ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/custom.h ../byterun/caml/fail.h ../byterun/caml/io.h \
- ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/address_class.h ../byterun/caml/reverse.h
+hash.d.$(O): hash.c ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
+ ../byterun/caml/custom.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/osdeps.h ../byterun/caml/signals.h \
- ../byterun/caml/sys.h
-lexing.d.o: lexing.c ../byterun/caml/fail.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/stacks.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/hash.h
+sys.d.$(O): sys.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/debugger.h \
+ ../byterun/caml/fail.h ../byterun/caml/gc_ctrl.h ../byterun/caml/io.h \
+ ../byterun/caml/osdeps.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-main.d.o: main.c ../byterun/caml/misc.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/sys.h
-major_gc.d.o: major_gc.c ../byterun/caml/compact.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
+ ../byterun/caml/signals.h ../byterun/caml/stacks.h \
+ ../byterun/caml/sys.h ../byterun/caml/version.h \
+ ../byterun/caml/callback.h ../byterun/caml/startup_aux.h
+parsing.d.$(O): parsing.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
+ ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
+ ../byterun/caml/alloc.h
+gc_ctrl.d.$(O): gc_ctrl.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/backtrace.h \
+ ../byterun/caml/exec.h ../byterun/caml/compact.h \
../byterun/caml/custom.h ../byterun/caml/fail.h \
../byterun/caml/finalise.h ../byterun/caml/roots.h \
../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
- ../byterun/caml/weak.h
-md5.d.o: md5.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/fail.h ../byterun/caml/md5.h ../byterun/caml/io.h \
+ ../byterun/caml/stack.h ../byterun/caml/startup_aux.h
+terminfo.d.$(O): terminfo.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/fail.h ../byterun/caml/io.h
+md5.d.$(O): md5.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
+ ../byterun/caml/md5.h ../byterun/caml/io.h ../byterun/caml/memory.h \
+ ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/address_class.h ../byterun/caml/reverse.h
+obj.d.$(O): obj.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/fail.h ../byterun/caml/gc.h \
+ ../byterun/caml/interp.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/freelist.h ../byterun/caml/memory.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
+ ../byterun/caml/prims.h ../byterun/caml/spacetime.h \
+ ../byterun/caml/io.h ../byterun/caml/stack.h
+lexing.d.$(O): lexing.c ../byterun/caml/fail.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/stacks.h \
../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/reverse.h
-memory.d.o: memory.c ../byterun/caml/address_class.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/misc.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
+unix.d.$(O): unix.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/fail.h ../byterun/caml/misc.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/memory.h \
+ ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
+ ../byterun/caml/signals.h ../byterun/caml/sys.h ../byterun/caml/io.h \
+ ../byterun/caml/alloc.h
+printexc.d.$(O): printexc.c ../byterun/caml/backtrace.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
+ ../byterun/caml/exec.h ../byterun/caml/callback.h \
+ ../byterun/caml/debugger.h ../byterun/caml/fail.h \
+ ../byterun/caml/printexc.h ../byterun/caml/memory.h \
+ ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/address_class.h
+callback.d.$(O): callback.c ../byterun/caml/callback.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
+ ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
+weak.d.$(O): weak.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
- ../byterun/caml/freelist.h ../byterun/caml/gc.h \
- ../byterun/caml/gc_ctrl.h ../byterun/caml/major_gc.h \
- ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/signals.h
-meta.d.o: meta.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/fail.h ../byterun/caml/fix_code.h \
- ../byterun/caml/interp.h ../byterun/caml/intext.h ../byterun/caml/io.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/prims.h ../byterun/caml/stacks.h
-minor_gc.d.o: minor_gc.c ../byterun/caml/custom.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/misc.h ../byterun/caml/fail.h \
+ ../byterun/caml/weak.h
+compact.d.$(O): compact.c ../byterun/caml/address_class.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
../byterun/caml/finalise.h ../byterun/caml/roots.h \
../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
- ../byterun/caml/weak.h
-misc.d.o: misc.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/misc.h \
- ../byterun/caml/memory.h ../byterun/caml/gc.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/major_gc.h \
- ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
- ../byterun/caml/version.h
-natdynlink.d.o: natdynlink.c ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/gc_ctrl.h \
+ ../byterun/caml/weak.h ../byterun/caml/compact.h
+finalise.d.$(O): finalise.c ../byterun/caml/callback.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
+ ../byterun/caml/compact.h ../byterun/caml/fail.h \
+ ../byterun/caml/finalise.h ../byterun/caml/roots.h \
../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/stack.h ../byterun/caml/callback.h \
- ../byterun/caml/alloc.h ../byterun/caml/intext.h ../byterun/caml/io.h \
- ../byterun/caml/osdeps.h ../byterun/caml/fail.h \
- ../byterun/caml/signals.h ../byterun/caml/hooks.h
-obj.d.o: obj.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/fail.h ../byterun/caml/gc.h ../byterun/caml/interp.h \
+ ../byterun/caml/signals.h
+custom.d.$(O): custom.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
+ ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h ../byterun/caml/prims.h \
- ../byterun/caml/spacetime.h ../byterun/caml/io.h \
- ../byterun/caml/stack.h
-parsing.d.o: parsing.c ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
- ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
+globroots.d.$(O): globroots.c ../byterun/caml/memory.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/gc.h ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/alloc.h
-printexc.d.o: printexc.c ../byterun/caml/backtrace.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/misc.h ../byterun/caml/exec.h \
- ../byterun/caml/callback.h ../byterun/caml/debugger.h \
- ../byterun/caml/fail.h ../byterun/caml/printexc.h
-roots.d.o: roots.c ../byterun/caml/finalise.h ../byterun/caml/roots.h \
- ../byterun/caml/misc.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/memory.h ../byterun/caml/gc.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/roots.h ../byterun/caml/globroots.h
+backtrace_prim.d.$(O): backtrace_prim.c ../byterun/caml/alloc.h \
+ ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/backtrace.h ../byterun/caml/exec.h \
+ ../byterun/caml/backtrace_prim.h ../byterun/caml/memory.h \
+ ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h ../byterun/caml/globroots.h \
- ../byterun/caml/stack.h
-signals.d.o: signals.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/callback.h ../byterun/caml/fail.h \
- ../byterun/caml/memory.h ../byterun/caml/gc.h \
- ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/roots.h ../byterun/caml/signals.h \
- ../byterun/caml/signals_machdep.h ../byterun/caml/sys.h
-signals_asm.d.o: signals_asm.c ../byterun/caml/fail.h \
- ../byterun/caml/misc.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
+ ../byterun/caml/address_class.h ../byterun/caml/stack.h
+backtrace.d.$(O): backtrace.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
../byterun/caml/mlvalues.h ../byterun/caml/memory.h \
../byterun/caml/gc.h ../byterun/caml/major_gc.h \
../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
- ../byterun/caml/signals.h ../byterun/caml/signals_machdep.h \
- signals_osdep.h ../byterun/caml/stack.h ../byterun/caml/spacetime.h \
- ../byterun/caml/io.h
-spacetime.d.o: spacetime.c ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/address_class.h ../byterun/caml/backtrace.h \
+ ../byterun/caml/exec.h ../byterun/caml/backtrace_prim.h \
+ ../byterun/caml/fail.h
+natdynlink.d.$(O): natdynlink.c ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/memory.h \
+ ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/address_class.h ../byterun/caml/stack.h \
+ ../byterun/caml/callback.h ../byterun/caml/alloc.h \
+ ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/osdeps.h \
+ ../byterun/caml/fail.h ../byterun/caml/signals.h \
+ ../byterun/caml/hooks.h
+debugger.d.$(O): debugger.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/debugger.h \
+ ../byterun/caml/osdeps.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
+meta.d.$(O): meta.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
+ ../byterun/caml/fix_code.h ../byterun/caml/interp.h \
+ ../byterun/caml/intext.h ../byterun/caml/io.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
+ ../byterun/caml/prims.h ../byterun/caml/stacks.h
+dynlink.d.$(O): dynlink.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/dynlink.h \
+ ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
+ ../byterun/caml/osdeps.h ../byterun/caml/prims.h \
+ ../byterun/caml/signals.h
+clambda_checks.d.$(O): clambda_checks.c ../byterun/caml/mlvalues.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/misc.h
+spacetime.d.$(O): spacetime.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
../byterun/caml/mlvalues.h ../byterun/caml/backtrace_prim.h \
../byterun/caml/backtrace.h ../byterun/caml/exec.h \
../byterun/caml/fail.h ../byterun/caml/gc.h ../byterun/caml/intext.h \
../byterun/caml/osdeps.h ../byterun/caml/roots.h \
../byterun/caml/signals.h ../byterun/caml/stack.h \
../byterun/caml/sys.h ../byterun/caml/spacetime.h
-spacetime_offline.d.o: spacetime_offline.c ../byterun/caml/alloc.h \
- ../byterun/caml/misc.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/fail.h ../byterun/caml/gc.h \
+spacetime_snapshot.d.$(O): spacetime_snapshot.c ../byterun/caml/alloc.h \
+ ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/backtrace_prim.h ../byterun/caml/backtrace.h \
+ ../byterun/caml/exec.h ../byterun/caml/custom.h ../byterun/caml/fail.h \
+ ../byterun/caml/gc.h ../byterun/caml/gc_ctrl.h \
../byterun/caml/intext.h ../byterun/caml/io.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
../byterun/caml/address_class.h ../byterun/caml/roots.h \
../byterun/caml/signals.h ../byterun/caml/stack.h \
- ../byterun/caml/sys.h ../byterun/caml/spacetime.h ../config/s.h
-spacetime_snapshot.d.o: spacetime_snapshot.c ../byterun/caml/alloc.h \
- ../byterun/caml/misc.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/backtrace_prim.h \
- ../byterun/caml/backtrace.h ../byterun/caml/exec.h \
- ../byterun/caml/custom.h ../byterun/caml/fail.h ../byterun/caml/gc.h \
- ../byterun/caml/gc_ctrl.h ../byterun/caml/intext.h \
- ../byterun/caml/io.h ../byterun/caml/major_gc.h \
- ../byterun/caml/freelist.h ../byterun/caml/memory.h \
+ ../byterun/caml/sys.h ../byterun/caml/spacetime.h
+spacetime_offline.d.$(O): spacetime_offline.c ../byterun/caml/alloc.h \
+ ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
+ ../byterun/caml/gc.h ../byterun/caml/intext.h ../byterun/caml/io.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/address_class.h ../byterun/caml/roots.h \
+ ../byterun/caml/signals.h ../byterun/caml/stack.h \
+ ../byterun/caml/sys.h ../byterun/caml/spacetime.h
+afl.d.$(O): afl.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/osdeps.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
+bigarray.d.$(O): bigarray.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/bigarray.h \
+ ../byterun/caml/custom.h ../byterun/caml/fail.h \
+ ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/hash.h \
+ ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
+startup_aux.i.$(O): startup_aux.c ../byterun/caml/backtrace.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
+ ../byterun/caml/exec.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/roots.h ../byterun/caml/signals.h \
- ../byterun/caml/stack.h ../byterun/caml/sys.h \
- ../byterun/caml/spacetime.h
-startup.d.o: startup.c ../byterun/caml/callback.h \
+ ../byterun/caml/callback.h ../byterun/caml/osdeps.h \
+ ../byterun/caml/startup_aux.h
+startup.i.$(O): startup.c ../byterun/caml/callback.h \
../byterun/caml/mlvalues.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/misc.h ../byterun/caml/backtrace.h \
- ../byterun/caml/exec.h ../byterun/caml/custom.h \
- ../byterun/caml/debugger.h ../byterun/caml/fail.h \
- ../byterun/caml/freelist.h ../byterun/caml/gc.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
+ ../byterun/caml/backtrace.h ../byterun/caml/exec.h \
+ ../byterun/caml/custom.h ../byterun/caml/debugger.h \
+ ../byterun/caml/fail.h ../byterun/caml/freelist.h ../byterun/caml/gc.h \
../byterun/caml/gc_ctrl.h ../byterun/caml/intext.h \
../byterun/caml/io.h ../byterun/caml/memory.h \
../byterun/caml/major_gc.h ../byterun/caml/minor_gc.h \
../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
../byterun/caml/printexc.h ../byterun/caml/stack.h \
../byterun/caml/startup_aux.h ../byterun/caml/sys.h
-startup_aux.d.o: startup_aux.c ../byterun/caml/backtrace.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/misc.h ../byterun/caml/exec.h ../byterun/caml/memory.h \
- ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
- ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
- ../byterun/caml/startup_aux.h
-str.d.o: str.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/fail.h
-sys.d.o: sys.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/alloc.h \
- ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/debugger.h ../byterun/caml/fail.h \
- ../byterun/caml/gc_ctrl.h ../byterun/caml/instruct.h \
- ../byterun/caml/io.h ../byterun/caml/osdeps.h \
- ../byterun/caml/signals.h ../byterun/caml/stacks.h \
+main.i.$(O): main.c ../byterun/caml/misc.h ../byterun/caml/config.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/sys.h ../byterun/caml/osdeps.h \
../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/sys.h ../byterun/caml/version.h
-terminfo.d.o: terminfo.c ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/fail.h ../byterun/caml/io.h
-unix.d.o: unix.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/fail.h \
- ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/memory.h ../byterun/caml/gc.h \
- ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/osdeps.h ../byterun/caml/signals.h \
- ../byterun/caml/sys.h ../byterun/caml/io.h
-weak.d.o: weak.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/fail.h ../byterun/caml/major_gc.h \
- ../byterun/caml/freelist.h ../byterun/caml/memory.h \
- ../byterun/caml/gc.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h ../byterun/caml/weak.h
-afl.i.o: afl.c ../byterun/caml/misc.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/osdeps.h
-alloc.i.o: alloc.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/custom.h ../byterun/caml/major_gc.h \
- ../byterun/caml/freelist.h ../byterun/caml/memory.h \
- ../byterun/caml/gc.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h ../byterun/caml/stacks.h
-array.i.o: array.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
+fail.i.$(O): fail.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/fail.h ../byterun/caml/io.h \
+ ../byterun/caml/gc.h ../byterun/caml/memory.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
+ ../byterun/caml/printexc.h ../byterun/caml/signals.h \
+ ../byterun/caml/stack.h ../byterun/caml/roots.h \
+ ../byterun/caml/callback.h
+roots.i.$(O): roots.c ../byterun/caml/finalise.h ../byterun/caml/roots.h \
+ ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/address_class.h ../byterun/caml/globroots.h \
+ ../byterun/caml/stack.h
+signals.i.$(O): signals.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/callback.h \
../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/signals.h ../byterun/caml/spacetime.h \
- ../byterun/caml/io.h ../byterun/caml/stack.h
-backtrace.i.o: backtrace.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/roots.h ../byterun/caml/signals.h \
+ ../byterun/caml/signals_machdep.h ../byterun/caml/sys.h
+signals_asm.i.$(O): signals_asm.c ../byterun/caml/fail.h \
+ ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/mlvalues.h \
../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/backtrace.h ../byterun/caml/exec.h \
- ../byterun/caml/backtrace_prim.h ../byterun/caml/fail.h
-backtrace_prim.i.o: backtrace_prim.c ../byterun/caml/alloc.h \
- ../byterun/caml/misc.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/backtrace.h \
- ../byterun/caml/exec.h ../byterun/caml/backtrace_prim.h \
- ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/osdeps.h ../byterun/caml/signals.h \
+ ../byterun/caml/signals_machdep.h signals_osdep.h \
+ ../byterun/caml/stack.h ../byterun/caml/spacetime.h \
+ ../byterun/caml/io.h
+misc.i.$(O): misc.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/misc.h ../byterun/caml/memory.h \
+ ../byterun/caml/gc.h ../byterun/caml/mlvalues.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/stack.h
-callback.i.o: callback.c ../byterun/caml/callback.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/misc.h ../byterun/caml/fail.h ../byterun/caml/memory.h \
- ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
- ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/osdeps.h ../byterun/caml/version.h
+freelist.i.$(O): freelist.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/freelist.h ../byterun/caml/misc.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/gc.h \
+ ../byterun/caml/gc_ctrl.h ../byterun/caml/memory.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/minor_gc.h \
../byterun/caml/address_class.h
-clambda_checks.i.o: clambda_checks.c ../byterun/caml/mlvalues.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/misc.h
-compact.i.o: compact.c ../byterun/caml/address_class.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/misc.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/finalise.h \
+major_gc.i.$(O): major_gc.c ../byterun/caml/compact.h ../byterun/caml/config.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
+ ../byterun/caml/fail.h ../byterun/caml/finalise.h \
../byterun/caml/roots.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/gc_ctrl.h \
- ../byterun/caml/weak.h ../byterun/caml/compact.h
-compare.i.o: compare.c ../byterun/caml/custom.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/misc.h \
- ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
- ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-custom.i.o: custom.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/custom.h ../byterun/caml/fail.h \
- ../byterun/caml/memory.h ../byterun/caml/gc.h \
- ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-debugger.i.o: debugger.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/debugger.h ../byterun/caml/osdeps.h
-dynlink.i.o: dynlink.c ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/dynlink.h \
- ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
- ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/osdeps.h ../byterun/caml/prims.h \
- ../byterun/caml/signals.h
-extern.i.o: extern.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/custom.h ../byterun/caml/fail.h ../byterun/caml/gc.h \
- ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/md5.h \
- ../byterun/caml/memory.h ../byterun/caml/major_gc.h \
- ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h ../byterun/caml/reverse.h
-fail.i.o: fail.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/fail.h ../byterun/caml/io.h ../byterun/caml/gc.h \
- ../byterun/caml/memory.h ../byterun/caml/major_gc.h \
- ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h ../byterun/caml/printexc.h \
- ../byterun/caml/signals.h ../byterun/caml/stack.h \
- ../byterun/caml/roots.h ../byterun/caml/callback.h
-finalise.i.o: finalise.c ../byterun/caml/callback.h \
+ ../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
+ ../byterun/caml/weak.h
+minor_gc.i.$(O): minor_gc.c ../byterun/caml/custom.h \
../byterun/caml/mlvalues.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/misc.h ../byterun/caml/compact.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
../byterun/caml/fail.h ../byterun/caml/finalise.h \
../byterun/caml/roots.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
+ ../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
+ ../byterun/caml/weak.h
+memory.i.$(O): memory.c ../byterun/caml/address_class.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/fail.h ../byterun/caml/freelist.h ../byterun/caml/gc.h \
+ ../byterun/caml/gc_ctrl.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
../byterun/caml/signals.h
-floats.i.o: floats.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+alloc.i.$(O): alloc.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/reverse.h ../byterun/caml/stacks.h
-freelist.i.o: freelist.c ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/freelist.h ../byterun/caml/misc.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/gc.h \
- ../byterun/caml/gc_ctrl.h ../byterun/caml/memory.h \
- ../byterun/caml/major_gc.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/stacks.h
+compare.i.$(O): compare.c ../byterun/caml/custom.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/misc.h ../byterun/caml/fail.h ../byterun/caml/memory.h \
+ ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
../byterun/caml/address_class.h
-gc_ctrl.i.o: gc_ctrl.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/backtrace.h ../byterun/caml/exec.h \
- ../byterun/caml/compact.h ../byterun/caml/custom.h \
- ../byterun/caml/fail.h ../byterun/caml/finalise.h \
- ../byterun/caml/roots.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ints.i.$(O): ints.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
+ ../byterun/caml/fail.h ../byterun/caml/intext.h ../byterun/caml/io.h \
+ ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
- ../byterun/caml/stack.h ../byterun/caml/startup_aux.h
-globroots.i.o: globroots.c ../byterun/caml/memory.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/gc.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
+floats.i.$(O): floats.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
+ ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/roots.h ../byterun/caml/globroots.h
-hash.i.o: hash.c ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/misc.h ../byterun/caml/custom.h \
+ ../byterun/caml/reverse.h ../byterun/caml/stacks.h
+str.i.$(O): str.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
+ ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
+array.i.$(O): array.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/hash.h
-intern.i.o: intern.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/callback.h ../byterun/caml/custom.h \
+ ../byterun/caml/signals.h ../byterun/caml/spacetime.h \
+ ../byterun/caml/io.h ../byterun/caml/stack.h
+io.i.$(O): io.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
+ ../byterun/caml/fail.h ../byterun/caml/io.h ../byterun/caml/memory.h \
+ ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
+ ../byterun/caml/signals.h ../byterun/caml/sys.h
+extern.i.$(O): extern.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
../byterun/caml/fail.h ../byterun/caml/gc.h ../byterun/caml/intext.h \
../byterun/caml/io.h ../byterun/caml/md5.h ../byterun/caml/memory.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
../byterun/caml/reverse.h
-ints.i.o: ints.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/custom.h ../byterun/caml/fail.h \
- ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/memory.h \
- ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
+intern.i.$(O): intern.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/callback.h \
+ ../byterun/caml/custom.h ../byterun/caml/fail.h ../byterun/caml/gc.h \
+ ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/md5.h \
+ ../byterun/caml/memory.h ../byterun/caml/major_gc.h \
../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h
-io.i.o: io.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/alloc.h \
- ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/custom.h ../byterun/caml/fail.h ../byterun/caml/io.h \
- ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/address_class.h ../byterun/caml/reverse.h
+hash.i.$(O): hash.c ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
+ ../byterun/caml/custom.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/osdeps.h ../byterun/caml/signals.h \
- ../byterun/caml/sys.h
-lexing.i.o: lexing.c ../byterun/caml/fail.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/stacks.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/hash.h
+sys.i.$(O): sys.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/debugger.h \
+ ../byterun/caml/fail.h ../byterun/caml/gc_ctrl.h ../byterun/caml/io.h \
+ ../byterun/caml/osdeps.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-main.i.o: main.c ../byterun/caml/misc.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/sys.h
-major_gc.i.o: major_gc.c ../byterun/caml/compact.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
+ ../byterun/caml/signals.h ../byterun/caml/stacks.h \
+ ../byterun/caml/sys.h ../byterun/caml/version.h \
+ ../byterun/caml/callback.h ../byterun/caml/startup_aux.h
+parsing.i.$(O): parsing.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
+ ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
+ ../byterun/caml/alloc.h
+gc_ctrl.i.$(O): gc_ctrl.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/backtrace.h \
+ ../byterun/caml/exec.h ../byterun/caml/compact.h \
../byterun/caml/custom.h ../byterun/caml/fail.h \
../byterun/caml/finalise.h ../byterun/caml/roots.h \
../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
- ../byterun/caml/weak.h
-md5.i.o: md5.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/fail.h ../byterun/caml/md5.h ../byterun/caml/io.h \
+ ../byterun/caml/stack.h ../byterun/caml/startup_aux.h
+terminfo.i.$(O): terminfo.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/fail.h ../byterun/caml/io.h
+md5.i.$(O): md5.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
+ ../byterun/caml/md5.h ../byterun/caml/io.h ../byterun/caml/memory.h \
+ ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/address_class.h ../byterun/caml/reverse.h
+obj.i.$(O): obj.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/fail.h ../byterun/caml/gc.h \
+ ../byterun/caml/interp.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/freelist.h ../byterun/caml/memory.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
+ ../byterun/caml/prims.h ../byterun/caml/spacetime.h \
+ ../byterun/caml/io.h ../byterun/caml/stack.h
+lexing.i.$(O): lexing.c ../byterun/caml/fail.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/stacks.h \
../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/reverse.h
-memory.i.o: memory.c ../byterun/caml/address_class.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/misc.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
+unix.i.$(O): unix.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/fail.h ../byterun/caml/misc.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/memory.h \
+ ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
+ ../byterun/caml/signals.h ../byterun/caml/sys.h ../byterun/caml/io.h \
+ ../byterun/caml/alloc.h
+printexc.i.$(O): printexc.c ../byterun/caml/backtrace.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
+ ../byterun/caml/exec.h ../byterun/caml/callback.h \
+ ../byterun/caml/debugger.h ../byterun/caml/fail.h \
+ ../byterun/caml/printexc.h ../byterun/caml/memory.h \
+ ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/address_class.h
+callback.i.$(O): callback.c ../byterun/caml/callback.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
+ ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
+weak.i.$(O): weak.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
- ../byterun/caml/freelist.h ../byterun/caml/gc.h \
- ../byterun/caml/gc_ctrl.h ../byterun/caml/major_gc.h \
- ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/signals.h
-meta.i.o: meta.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/fail.h ../byterun/caml/fix_code.h \
- ../byterun/caml/interp.h ../byterun/caml/intext.h ../byterun/caml/io.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/prims.h ../byterun/caml/stacks.h
-minor_gc.i.o: minor_gc.c ../byterun/caml/custom.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/misc.h ../byterun/caml/fail.h \
+ ../byterun/caml/weak.h
+compact.i.$(O): compact.c ../byterun/caml/address_class.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
../byterun/caml/finalise.h ../byterun/caml/roots.h \
../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
- ../byterun/caml/weak.h
-misc.i.o: misc.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/misc.h \
- ../byterun/caml/memory.h ../byterun/caml/gc.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/major_gc.h \
- ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
- ../byterun/caml/version.h
-natdynlink.i.o: natdynlink.c ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/gc_ctrl.h \
+ ../byterun/caml/weak.h ../byterun/caml/compact.h
+finalise.i.$(O): finalise.c ../byterun/caml/callback.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
+ ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
+ ../byterun/caml/compact.h ../byterun/caml/fail.h \
+ ../byterun/caml/finalise.h ../byterun/caml/roots.h \
../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/stack.h ../byterun/caml/callback.h \
- ../byterun/caml/alloc.h ../byterun/caml/intext.h ../byterun/caml/io.h \
- ../byterun/caml/osdeps.h ../byterun/caml/fail.h \
- ../byterun/caml/signals.h ../byterun/caml/hooks.h
-obj.i.o: obj.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/fail.h ../byterun/caml/gc.h ../byterun/caml/interp.h \
+ ../byterun/caml/signals.h
+custom.i.$(O): custom.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
+ ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h ../byterun/caml/prims.h \
- ../byterun/caml/spacetime.h ../byterun/caml/io.h \
- ../byterun/caml/stack.h
-parsing.i.o: parsing.c ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
- ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
+globroots.i.$(O): globroots.c ../byterun/caml/memory.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/gc.h ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/alloc.h
-printexc.i.o: printexc.c ../byterun/caml/backtrace.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/misc.h ../byterun/caml/exec.h \
- ../byterun/caml/callback.h ../byterun/caml/debugger.h \
- ../byterun/caml/fail.h ../byterun/caml/printexc.h
-roots.i.o: roots.c ../byterun/caml/finalise.h ../byterun/caml/roots.h \
- ../byterun/caml/misc.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/memory.h ../byterun/caml/gc.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/roots.h ../byterun/caml/globroots.h
+backtrace_prim.i.$(O): backtrace_prim.c ../byterun/caml/alloc.h \
+ ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/backtrace.h ../byterun/caml/exec.h \
+ ../byterun/caml/backtrace_prim.h ../byterun/caml/memory.h \
+ ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h ../byterun/caml/globroots.h \
- ../byterun/caml/stack.h
-signals.i.o: signals.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/callback.h ../byterun/caml/fail.h \
- ../byterun/caml/memory.h ../byterun/caml/gc.h \
- ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/roots.h ../byterun/caml/signals.h \
- ../byterun/caml/signals_machdep.h ../byterun/caml/sys.h
-signals_asm.i.o: signals_asm.c ../byterun/caml/fail.h \
- ../byterun/caml/misc.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
+ ../byterun/caml/address_class.h ../byterun/caml/stack.h
+backtrace.i.$(O): backtrace.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
../byterun/caml/mlvalues.h ../byterun/caml/memory.h \
../byterun/caml/gc.h ../byterun/caml/major_gc.h \
../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
- ../byterun/caml/signals.h ../byterun/caml/signals_machdep.h \
- signals_osdep.h ../byterun/caml/stack.h ../byterun/caml/spacetime.h \
- ../byterun/caml/io.h
-spacetime.i.o: spacetime.c ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/address_class.h ../byterun/caml/backtrace.h \
+ ../byterun/caml/exec.h ../byterun/caml/backtrace_prim.h \
+ ../byterun/caml/fail.h
+natdynlink.i.$(O): natdynlink.c ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/memory.h \
+ ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/address_class.h ../byterun/caml/stack.h \
+ ../byterun/caml/callback.h ../byterun/caml/alloc.h \
+ ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/osdeps.h \
+ ../byterun/caml/fail.h ../byterun/caml/signals.h \
+ ../byterun/caml/hooks.h
+debugger.i.$(O): debugger.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/debugger.h \
+ ../byterun/caml/osdeps.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
+meta.i.$(O): meta.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
+ ../byterun/caml/fix_code.h ../byterun/caml/interp.h \
+ ../byterun/caml/intext.h ../byterun/caml/io.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
+ ../byterun/caml/prims.h ../byterun/caml/stacks.h
+dynlink.i.$(O): dynlink.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/dynlink.h \
+ ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
+ ../byterun/caml/osdeps.h ../byterun/caml/prims.h \
+ ../byterun/caml/signals.h
+clambda_checks.i.$(O): clambda_checks.c ../byterun/caml/mlvalues.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/misc.h
+spacetime.i.$(O): spacetime.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
../byterun/caml/mlvalues.h ../byterun/caml/backtrace_prim.h \
../byterun/caml/backtrace.h ../byterun/caml/exec.h \
../byterun/caml/fail.h ../byterun/caml/gc.h ../byterun/caml/intext.h \
../byterun/caml/osdeps.h ../byterun/caml/roots.h \
../byterun/caml/signals.h ../byterun/caml/stack.h \
../byterun/caml/sys.h ../byterun/caml/spacetime.h
-spacetime_offline.i.o: spacetime_offline.c ../byterun/caml/alloc.h \
- ../byterun/caml/misc.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/fail.h ../byterun/caml/gc.h \
+spacetime_snapshot.i.$(O): spacetime_snapshot.c ../byterun/caml/alloc.h \
+ ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/backtrace_prim.h ../byterun/caml/backtrace.h \
+ ../byterun/caml/exec.h ../byterun/caml/custom.h ../byterun/caml/fail.h \
+ ../byterun/caml/gc.h ../byterun/caml/gc_ctrl.h \
../byterun/caml/intext.h ../byterun/caml/io.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
../byterun/caml/address_class.h ../byterun/caml/roots.h \
../byterun/caml/signals.h ../byterun/caml/stack.h \
- ../byterun/caml/sys.h ../byterun/caml/spacetime.h ../config/s.h
-spacetime_snapshot.i.o: spacetime_snapshot.c ../byterun/caml/alloc.h \
- ../byterun/caml/misc.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/backtrace_prim.h \
- ../byterun/caml/backtrace.h ../byterun/caml/exec.h \
- ../byterun/caml/custom.h ../byterun/caml/fail.h ../byterun/caml/gc.h \
- ../byterun/caml/gc_ctrl.h ../byterun/caml/intext.h \
- ../byterun/caml/io.h ../byterun/caml/major_gc.h \
- ../byterun/caml/freelist.h ../byterun/caml/memory.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/roots.h ../byterun/caml/signals.h \
- ../byterun/caml/stack.h ../byterun/caml/sys.h \
- ../byterun/caml/spacetime.h
-startup.i.o: startup.c ../byterun/caml/callback.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/misc.h ../byterun/caml/backtrace.h \
- ../byterun/caml/exec.h ../byterun/caml/custom.h \
- ../byterun/caml/debugger.h ../byterun/caml/fail.h \
- ../byterun/caml/freelist.h ../byterun/caml/gc.h \
- ../byterun/caml/gc_ctrl.h ../byterun/caml/intext.h \
- ../byterun/caml/io.h ../byterun/caml/memory.h \
- ../byterun/caml/major_gc.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
- ../byterun/caml/printexc.h ../byterun/caml/stack.h \
- ../byterun/caml/startup_aux.h ../byterun/caml/sys.h
-startup_aux.i.o: startup_aux.c ../byterun/caml/backtrace.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/misc.h ../byterun/caml/exec.h ../byterun/caml/memory.h \
- ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
- ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
- ../byterun/caml/startup_aux.h
-str.i.o: str.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/fail.h
-sys.i.o: sys.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/alloc.h \
- ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/debugger.h ../byterun/caml/fail.h \
- ../byterun/caml/gc_ctrl.h ../byterun/caml/instruct.h \
- ../byterun/caml/io.h ../byterun/caml/osdeps.h \
- ../byterun/caml/signals.h ../byterun/caml/stacks.h \
- ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/sys.h ../byterun/caml/spacetime.h
+spacetime_offline.i.$(O): spacetime_offline.c ../byterun/caml/alloc.h \
+ ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
+ ../byterun/caml/gc.h ../byterun/caml/intext.h ../byterun/caml/io.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/sys.h ../byterun/caml/version.h
-terminfo.i.o: terminfo.c ../byterun/caml/config.h \
- ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
- ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/mlvalues.h ../byterun/caml/fail.h ../byterun/caml/io.h
-unix.i.o: unix.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/fail.h \
- ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/address_class.h ../byterun/caml/roots.h \
+ ../byterun/caml/signals.h ../byterun/caml/stack.h \
+ ../byterun/caml/sys.h ../byterun/caml/spacetime.h
+afl.i.$(O): afl.c ../byterun/caml/config.h ../byterun/caml/m.h \
+ ../byterun/caml/s.h ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
+ ../byterun/caml/osdeps.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+ ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
+bigarray.i.$(O): bigarray.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/bigarray.h \
+ ../byterun/caml/custom.h ../byterun/caml/fail.h \
+ ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/hash.h \
../byterun/caml/memory.h ../byterun/caml/gc.h \
../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
- ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
- ../byterun/caml/osdeps.h ../byterun/caml/signals.h \
- ../byterun/caml/sys.h ../byterun/caml/io.h
-weak.i.o: weak.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
- ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
- ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
- ../byterun/caml/fail.h ../byterun/caml/major_gc.h \
- ../byterun/caml/freelist.h ../byterun/caml/memory.h \
- ../byterun/caml/gc.h ../byterun/caml/minor_gc.h \
- ../byterun/caml/address_class.h ../byterun/caml/weak.h
+ ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
parsing.c gc_ctrl.c terminfo.c md5.c obj.c lexing.c printexc.c callback.c \
weak.c compact.c finalise.c meta.c custom.c main.c globroots.c \
$(UNIX_OR_WIN32).c dynlink.c signals.c debugger.c startup_aux.c \
- backtrace.c afl.c
+ backtrace.c afl.c bigarray.c
-INSTALL_LIBDIR=$(DESTDIR)$(LIBDIR)
+# The following variable stores the list of files for which dependencies
+# should be computed. It includes even the files that won't actually be
+# compiled on the platform where make depend is run
+sources := $(LINKEDFILES)
-CC=$(NATIVECC)
+INSTALL_LIBDIR=$(DESTDIR)$(LIBDIR)
ifeq "$(UNIX_OR_WIN32)" "win32"
LN = cp
+sources += ../byterun/unix.c
else
LN = ln -s
+sources += ../byterun/win32.c
endif
-FLAGS=\
- -I../byterun \
- -DNATIVE_CODE -DTARGET_$(ARCH)
+CPPFLAGS += -I../byterun -DNATIVE_CODE -DTARGET_$(ARCH)
ifeq "$(UNIX_OR_WIN32)" "unix"
-FLAGS += -DMODEL_$(MODEL)
+CPPFLAGS += -DMODEL_$(MODEL)
endif
-FLAGS += -DSYS_$(SYSTEM) \
- $(NATIVECCCOMPOPTS) $(IFLEXDIR) \
- $(LIBUNWIND_INCLUDE_FLAGS)
+CPPFLAGS += -DSYS_$(SYSTEM) $(IFLEXDIR) $(LIBUNWIND_INCLUDE_FLAGS)
+
+ifneq "$(CCOMPTYPE)" "msvc"
+CFLAGS += -g
+endif
ifeq "$(TOOLCHAIN)" "msvc"
-DFLAGS=$(FLAGS) -DDEBUG
-PFLAGS=$(FLAGS) -DPROFILING $(NATIVECCPROFOPTS)
-OUTPUTOBJ = -Fo
+DFLAGS = $(CFLAGS) -DDEBUG
+PFLAGS=$(CFLAGS) -DPROFILING $(NATIVECCPROFOPTS)
ASMOBJS=$(ARCH)nt.$(O)
else
-DFLAGS=$(FLAGS) -g -DDEBUG
-PFLAGS=$(FLAGS) -pg -DPROFILING $(NATIVECCPROFOPTS)
-OUTPUTOBJ = -o
+DFLAGS = $(CFLAGS) -g -DDEBUG
+PFLAGS=$(CFLAGS) -pg -DPROFILING $(NATIVECCPROFOPTS)
ASMOBJS=$(ARCH).$(O)
endif
-IFLAGS=$(FLAGS) -DCAML_INSTR
-PICFLAGS=$(FLAGS) $(SHAREDCCCOMPOPTS)
+IFLAGS=$(CFLAGS) -DCAML_INSTR
+PICFLAGS=$(CFLAGS) $(SHAREDCCCOMPOPTS)
-ASPPFLAGS = -DSYS_$(SYSTEM)
+ASPPFLAGS = -DSYS_$(SYSTEM) -I../byterun
ifeq "$(UNIX_OR_WIN32)" "unix"
ASPPFLAGS += -DMODEL_$(MODEL)
-CFLAGS=$(FLAGS) -g
-else
-CFLAGS=$(FLAGS)
endif
COBJS=startup_aux.$(O) startup.$(O) main.$(O) fail.$(O) \
custom.$(O) globroots.$(O) backtrace_prim.$(O) backtrace.$(O) \
natdynlink.$(O) debugger.$(O) meta.$(O) dynlink.$(O) \
clambda_checks.$(O) spacetime.$(O) spacetime_snapshot.$(O) \
- spacetime_offline.$(O) afl.$(O)
+ spacetime_offline.$(O) afl.$(O) bigarray.$(O)
OBJS=$(COBJS) $(ASMOBJS)
$(LN) $< $@
%.d.$(O): %.c
- $(CC) -c $(DFLAGS) $(OUTPUTOBJ)$@ $<
+ $(CC) -c $(DFLAGS) $(CPPFLAGS) $(OUTPUTOBJ)$@ $<
%.i.$(O): %.c
- $(CC) -c $(IFLAGS) $(OUTPUTOBJ)$@ $<
+ $(CC) -c $(IFLAGS) $(CPPFLAGS) $(OUTPUTOBJ)$@ $<
%.p.$(O): %.c
- $(CC) -c $(PFLAGS) $(OUTPUTOBJ)$@ $<
+ $(CC) -c $(PFLAGS) $(CPPFLAGS) $(OUTPUTOBJ)$@ $<
%.pic.$(O): %.c
- $(CC) -c $(PICFLAGS) $(OUTPUTOBJ)$@ $<
+ $(CC) -c $(PICFLAGS) $(CPPFLAGS) $(OUTPUTOBJ)$@ $<
%.$(O): %.c
- $(CC) $(CFLAGS) -c $<
+ $(CC) -c $(CFLAGS) $(CPPFLAGS) $<
%.o: %.S
$(ASPP) $(ASPPFLAGS) -o $@ $< || \
distclean: clean
rm -r *~
-ifneq "$(TOOLCHAIN)" "msvc"
.PHONY: depend
-depend: $(COBJS:.$(O)=.c) $(LINKEDFILES)
- $(CC) -MM $(FLAGS) *.c > .depend
- $(CC) -MM $(FLAGS) -DPROFILING *.c | sed -e 's/\.o/.p.o/' >> .depend
- $(CC) -MM $(FLAGS) -DDEBUG *.c | sed -e 's/\.o/.d.o/' >> .depend
- $(CC) -MM $(FLAGS) -DCAML_INSTR *.c | sed -e 's/\.o/.i.o/' >> .depend
+ifeq "$(TOOLCHAIN)" "msvc"
+depend:
+ $(error Dependencies cannot be regenerated using the MSVC ports)
+else
+depend: $(COBJS:.$(O)=.c) $(sources)
+ $(CC) -MM $(CFLAGS) $(CPPFLAGS) $^ | sed -e 's/\.o/.$$(O)/' > .depend
+ $(CC) -MM $(PFLAGS) $(CPPFLAGS) $^ | sed -e 's/\.o/.p.$$(O)/' \
+ >> .depend
+ $(CC) -MM $(DFLAGS) $(CPPFLAGS) $^ | sed -e 's/\.o/.d.$$(O)/' \
+ >> .depend
+ $(CC) -MM $(IFLAGS) $(CPPFLAGS) $^ | sed -e 's/\.o/.i.$$(O)/' \
+ >> .depend
endif
-ifeq "$(UNIX_OR_WIN32)" "win32"
-.depend.nt: .depend
- sed -e 's/\.o/.$(O)/g' .depend > .depend.nt
-
-include .depend.nt
-
-else
include .depend
-endif
/* PIC mode support based on contribution by Paul Stravers (see PR#4795) */
-#include "../config/m.h"
+#include "caml/m.h"
#if defined(SYS_macosx)
/* Calls from OCaml to C must reserve 32 bytes of extra stack space */
# define PREPARE_FOR_C_CALL subq $32, %rsp; CFI_ADJUST(32)
# define CLEANUP_AFTER_C_CALL addq $32, %rsp; CFI_ADJUST(-32)
+ /* Stack probing mustn't be larger than the page size */
+# define STACK_PROBE_SIZE $4096
#else
# define PREPARE_FOR_C_CALL
# define CLEANUP_AFTER_C_CALL
+# define STACK_PROBE_SIZE $32768
#endif
.text
CFI_STARTPROC
RECORD_STACK_FRAME(0)
LBL(caml_call_gc):
-#if !defined(SYS_mingw64) && !defined(SYS_cygwin)
/* Touch the stack to trigger a recoverable segfault
if insufficient space remains */
- subq $32768, %rsp
+ subq STACK_PROBE_SIZE, %rsp
movq %rax, 0(%rsp)
- addq $32768, %rsp
-#endif
+ addq STACK_PROBE_SIZE, %rsp
/* Build array of registers, save it into caml_gc_regs */
#ifdef WITH_FRAME_POINTERS
ENTER_FUNCTION ;
STORE_VAR(%r13, caml_spacetime_trie_node_ptr)
#endif
subq $8, %rsp; CFI_ADJUST(8) /* equivalent to pushq %r12 */
-#if !defined(SYS_mingw64) && !defined(SYS_cygwin)
/* Touch the stack to trigger a recoverable segfault
if insufficient space remains */
- subq $32768, %rsp
+ subq STACK_PROBE_SIZE, %rsp
movq %rax, 0(%rsp)
- addq $32768, %rsp
-#endif
+ addq STACK_PROBE_SIZE, %rsp
/* Make the exception handler and alloc ptr available to the C code */
STORE_VAR(%r15, caml_young_ptr)
STORE_VAR(%r14, caml_exception_pointer)
.CODE
+ PUBLIC caml_system__code_begin
+caml_system__code_begin:
+ ret ; just one instruction, so that debuggers don't display
+ ; caml_system__code_begin instead of caml_call_gc
+
; Allocation
PUBLIC caml_call_gc
lea rax, [rsp+8]
mov caml_bottom_of_stack, rax
L105:
+ ; Touch the stack to trigger a recoverable segfault
+ ; if insufficient space remains
+ sub rsp, 01000h
+ mov [rsp], rax
+ add rsp, 01000h
; Save caml_young_ptr, caml_exception_pointer
mov caml_young_ptr, r15
mov caml_exception_pointer, r14
pop r12
mov caml_last_return_address, r12
mov caml_bottom_of_stack, rsp
+ ; Touch the stack to trigger a recoverable segfault
+ ; if insufficient space remains
+ sub rsp, 01000h
+ mov [rsp], rax
+ add rsp, 01000h
; Make the exception handler and alloc ptr available to the C code
mov caml_young_ptr, r15
mov caml_exception_pointer, r14
lea rax, caml_array_bound_error
jmp caml_c_call
+ PUBLIC caml_system__code_end
+caml_system__code_end:
+
.DATA
PUBLIC caml_system__frametable
caml_system__frametable LABEL QWORD
/* Asm part of the runtime system, ARM processor */
/* Must be preprocessed by cpp */
+#include "caml/m.h"
+
.syntax unified
.text
#if defined(SYS_linux_eabihf) && defined(MODEL_armv6)
#define CFI_STARTPROC .cfi_startproc
#define CFI_ENDPROC .cfi_endproc
#define CFI_ADJUST(n) .cfi_adjust_cfa_offset n
+#define CFI_REGISTER(r1,r2) .cfi_register r1,r2
+#define CFI_OFFSET(r,n) .cfi_offset r,n
#else
#define CFI_STARTPROC
#define CFI_ENDPROC
#define CFI_ADJUST(n)
+#define CFI_REGISTER(r1,r2)
+#define CFI_OFFSET(r,n)
#endif
/* Support for profiling with gprof */
#endif
/* Save integer registers and return address on the stack */
push {r0-r7,r12,lr}; CFI_ADJUST(40)
+#if defined(SYS_linux_eabihf) || defined(SYS_netbsd)
+ CFI_OFFSET(lr, -68)
+#else
+ CFI_OFFSET(lr, -4)
+#endif
/* Store pointer to saved integer registers in caml_gc_regs */
ldr r12, =caml_gc_regs
str sp, [r12]
str sp, [r6]
/* Preserve return address in callee-save register r4 */
mov r4, lr
+ CFI_REGISTER(lr, r4)
/* Make the exception handler alloc ptr available to the C code */
ldr r5, =caml_young_ptr
ldr r6, =caml_exception_pointer
#endif
/* Save return address and callee-save registers */
push {r4-r8,r10,r11,lr}; CFI_ADJUST(32) /* 8-byte alignment */
+#if defined(SYS_linux_eabihf) || defined(SYS_netbsd)
+ CFI_OFFSET(lr, -68)
+#else
+ CFI_OFFSET(lr, -4)
+#endif
/* Setup a callback link on the stack */
sub sp, sp, 16; CFI_ADJUST(16) /* 8-byte alignment */
ldr r4, =caml_bottom_of_stack
/* Asm part of the runtime system, ARM processor, 64-bit mode */
/* Must be preprocessed by cpp */
+#include "caml/m.h"
+
/* Special registers */
#define TRAP_PTR x26
#define CFI_STARTPROC .cfi_startproc
#define CFI_ENDPROC .cfi_endproc
#define CFI_ADJUST(n) .cfi_adjust_cfa_offset n
+#define CFI_REGISTER(r1,r2) .cfi_register r1,r2
+#define CFI_OFFSET(r,n) .cfi_offset r,n
#else
#define CFI_STARTPROC
#define CFI_ENDPROC
#define CFI_ADJUST(n)
+#define CFI_REGISTER(r1,r2)
+#define CFI_OFFSET(r,n)
#endif
/* Support for profiling with gprof */
.Lcaml_call_gc:
/* Set up stack space, saving return address and frame pointer */
/* (2 regs RA/GP, 24 allocatable int regs, 24 caller-save float regs) * 8 */
+ CFI_OFFSET(29, -400)
+ CFI_OFFSET(30, -392)
stp x29, x30, [sp, -400]!
CFI_ADJUST(400)
add x29, sp, #0
PROFILE
/* Preserve return address in callee-save register x19 */
mov x19, x30
+ CFI_REGISTER(30, 19)
/* Record lowest stack address and return address */
STOREGLOBAL(x30, caml_last_return_address)
add TMP, sp, #0
.Ljump_to_caml:
/* Set up stack frame and save callee-save registers */
+ CFI_OFFSET(29, -160)
+ CFI_OFFSET(30, -152)
stp x29, x30, [sp, -160]!
CFI_ADJUST(160)
add x29, sp, #0
}
int caml_alloc_backtrace_buffer(void){
- Assert(caml_backtrace_pos == 0);
- caml_backtrace_buffer = malloc(BACKTRACE_BUFFER_SIZE
- * sizeof(backtrace_slot));
+ CAMLassert(caml_backtrace_pos == 0);
+ caml_backtrace_buffer =
+ caml_stat_alloc_noexc(BACKTRACE_BUFFER_SIZE * sizeof(backtrace_slot));
if (caml_backtrace_buffer == NULL) return -1;
return 0;
}
for (trace_pos = 0; trace_pos < trace_size; trace_pos++) {
frame_descr * descr = caml_next_frame_descriptor(&pc, &sp);
- Assert(descr != NULL);
+ CAMLassert(descr != NULL);
Field(trace, trace_pos) = Val_backtrace_slot((backtrace_slot) descr);
}
}
/* Runtime checks to try to catch errors in code generation.
See flambda_to_clambda.ml for more information. */
-#include <assert.h>
#include <stdio.h>
#include <caml/mlvalues.h>
}
if (Tag_val(v) == Infix_tag) {
v -= Infix_offset_val(v);
- assert(Tag_val(v) == Closure_tag);
+ CAMLassert(Tag_val(v) == Closure_tag);
}
- assert(Wosize_val(v) >= 2);
+ CAMLassert(Wosize_val(v) >= 2);
return orig_v;
}
v -= offset;
pos += offset / sizeof(value);
}
- assert(Long_val(pos) >= 0);
+ CAMLassert(Long_val(pos) >= 0);
if (Long_val(pos) >= Wosize_val(v)) {
fprintf(stderr,
"Access to field %" ARCH_INT64_PRINTF_FORMAT
value bucket;
int i;
- Assert(1 + nargs <= Max_young_wosize);
+ CAMLassert(1 + nargs <= Max_young_wosize);
bucket = caml_alloc_small (1 + nargs, 0);
Field(bucket, 0) = tag;
for (i = 0; i < nargs; i++) Field(bucket, 1 + i) = args[i];
/* Asm part of the runtime system, Intel 386 processor */
/* Must be preprocessed by cpp */
-#include "../config/m.h"
+#include "caml/m.h"
/* Linux/BSD with ELF binaries and Solaris do not prefix identifiers with _.
Linux/BSD with a.out binaries and NextStep do. */
#include "caml/hooks.h"
-CAMLexport void (*caml_natdynlink_hook)(void* handle, char* unit) = NULL;
+CAMLexport void (*caml_natdynlink_hook)(void* handle, const char* unit) = NULL;
#include <stdio.h>
#include <string.h>
return res;
}
-static void *getsym(void *handle, char *module, char *name){
- char *fullname = caml_strconcat(3, "caml", module, name);
+static void *getsym(void *handle, const char *module, const char *name){
+ char *fullname = caml_stat_strconcat(3, "caml", module, name);
void *sym;
sym = caml_dlsym (handle, fullname);
/* printf("%s => %lx\n", fullname, (uintnat) sym); */
CAMLlocal3 (res, handle, header);
void *sym;
void *dlhandle;
- char *p;
+ char_os *p;
/* TODO: dlclose in case of error... */
- p = caml_strdup(String_val(filename));
+ p = caml_stat_strdup_to_os(String_val(filename));
caml_enter_blocking_section();
dlhandle = caml_dlopen(p, 1, Int_val(global));
caml_leave_blocking_section();
struct code_fragment * cf;
#define optsym(n) getsym(handle,unit,n)
- char *unit;
+ const char *unit;
void (*entrypoint)(void);
unit = String_val(symbol);
CAMLparam2 (filename, symbol);
CAMLlocal3 (res, v, handle_v);
void *handle;
- char *p;
+ char_os *p;
/* TODO: dlclose in case of error... */
- p = caml_strdup(String_val(filename));
+ p = caml_stat_strdup_to_os(String_val(filename));
caml_enter_blocking_section();
handle = caml_dlopen(p, 1, 1);
caml_leave_blocking_section();
intnat tblsize, increase, i;
link *tail = NULL;
- Assert(new_frametables);
+ CAMLassert(new_frametables);
tail = frametables_list_tail(new_frametables);
increase = count_descriptors(new_frametables);
/* special exception on linking described in the file LICENSE. */
/* */
/**************************************************************************/
+
+#if defined(__PIC__)
+
+#define Addrglobal(reg,glob) \
+ lgrl reg, glob@GOTENT
+#define Loadglobal(reg,glob) \
+ lgrl %r1, glob@GOTENT; lg reg, 0(%r1)
+#define Storeglobal(reg,glob) \
+ lgrl %r1, glob@GOTENT; stg reg, 0(%r1)
+#define Loadglobal32(reg,glob) \
+ lgrl %r1, glob@GOTENT; lgf reg, 0(%r1)
+#define Storeglobal32(reg,glob) \
+ lgrl %r1, glob@GOTENT; sty reg, 0(%r1)
+
+#else
+
#define Addrglobal(reg,glob) \
larl reg, glob
#define Loadglobal(reg,glob) \
#define Storeglobal32(reg,glob) \
strl reg, glob
+#endif
.section ".text"
.L106:
lg %r5, 0(%r15)
lg %r6, 8(%r15)
- lg %r1, 16(%r15)
+ lg %r0, 16(%r15)
Storeglobal(%r5, caml_bottom_of_stack)
Storeglobal(%r6, caml_last_return_address)
- Storeglobal(%r1, caml_gc_regs)
+ Storeglobal(%r0, caml_gc_regs)
la %r15, 32(%r15)
/* Update allocation pointer */
the frame descriptor for the call site is not correct */
Storeglobal(%r15, caml_bottom_of_stack)
lay %r15, -160(%r15) /* Reserve stack space for C call */
- larl %r7, caml_array_bound_error
+ Addrglobal(%r7, caml_array_bound_error)
j .L101
.globl caml_system__code_end
caml_system__code_end:
/* Machine- and OS-dependent handling of bound check trap */
#if defined(TARGET_power) \
- || defined(TARGET_s390x) \
- || (defined(TARGET_sparc) && defined(SYS_solaris))
+ || defined(TARGET_s390x)
DECLARE_SIGNAL_HANDLER(trap_handler)
{
-#if defined(SYS_solaris)
- if (info->si_code != ILL_ILLTRP) {
- /* Deactivate our exception handler and return. */
- struct sigaction act;
- act.sa_handler = SIG_DFL;
- act.sa_flags = 0;
- sigemptyset(&act.sa_mask);
- sigaction(sig, &act, NULL);
- return;
- }
-#endif
#if defined(SYS_rhapsody)
/* Unblock SIGTRAP */
{ sigset_t mask;
void caml_init_signals(void)
{
/* Bound-check trap handling */
-#if defined(TARGET_sparc) && defined(SYS_solaris)
- { struct sigaction act;
- sigemptyset(&act.sa_mask);
- SET_SIGACT(act, trap_handler);
- act.sa_flags |= SA_NODEFER;
- sigaction(SIGILL, &act, NULL);
- }
-#endif
#if defined(TARGET_power)
{ struct sigaction act;
if (sigaltstack(&stk, NULL) == 0) { sigaction(SIGSEGV, &act, NULL); }
}
#endif
-#if defined(_WIN32) && !defined(_WIN64)
- caml_win32_overflow_detection();
-#endif
}
#define CONTEXT_YOUNG_PTR (context->regs->gpr[31])
#define CONTEXT_SP (context->regs->gpr[1])
-/****************** s390x, ELF (Linux) */
-#elif defined(TARGET_s390x) && defined(SYS_elf)
+/****************** PowerPC, NetBSD */
+
+#elif defined(TARGET_power) && defined (SYS_netbsd)
+ #include <ucontext.h>
#define DECLARE_SIGNAL_HANDLER(name) \
- static void name(int sig, struct sigcontext * context)
+ static void name(int sig, siginfo_t * info, ucontext_t * context)
#define SET_SIGACT(sigact,name) \
- sigact.sa_handler = (void (*)(int)) (name); \
- sigact.sa_flags = 0
+ sigact.sa_sigaction = (void (*)(int,siginfo_t *,void *)) (name); \
+ sigact.sa_flags = SA_SIGINFO
+
+ typedef long context_reg;
+ #define CONTEXT_PC (_UC_MACHINE_PC(context))
+ #define CONTEXT_EXCEPTION_POINTER (context->uc_mcontext.__gregs[_REG_R29])
+ #define CONTEXT_YOUNG_LIMIT (context->uc_mcontext.__gregs[_REG_R30])
+ #define CONTEXT_YOUNG_PTR (context->uc_mcontext.__gregs[_REG_R31])
+ #define CONTEXT_SP (_UC_MACHINE_SP(context))
+ #define CONTEXT_FAULTING_ADDRESS ((char *) info->si_addr)
- typedef unsigned long context_reg;
- #define CONTEXT_PC (context->sregs->regs.psw.addr)
- #define CONTEXT_EXCEPTION_POINTER (context->sregs->regs.gprs[13])
- #define CONTEXT_YOUNG_LIMIT (context->sregs->regs.gprs[10])
- #define CONTEXT_YOUNG_PTR (context->sregs->regs.gprs[11])
- #define CONTEXT_SP (context->sregs->regs.gprs[15])
-/****************** PowerPC, BSD */
+/****************** PowerPC, other BSDs */
#elif defined(TARGET_power) && \
- (defined(SYS_bsd) || defined(SYS_bsd_elf) || defined(SYS_netbsd))
+ (defined(SYS_bsd) || defined(SYS_bsd_elf))
#define DECLARE_SIGNAL_HANDLER(name) \
static void name(int sig, int code, struct sigcontext * context)
#define CONTEXT_YOUNG_PTR (context->sc_frame.fixreg[31])
#define CONTEXT_SP (context->sc_frame.fixreg[1])
-/****************** SPARC, Solaris */
-
-#elif defined(TARGET_sparc) && defined(SYS_solaris)
-
- #include <ucontext.h>
+/****************** s390x, ELF (Linux) */
+#elif defined(TARGET_s390x) && defined(SYS_elf)
#define DECLARE_SIGNAL_HANDLER(name) \
- static void name(int sig, siginfo_t * info, ucontext_t * context)
+ static void name(int sig, struct sigcontext * context)
#define SET_SIGACT(sigact,name) \
- sigact.sa_sigaction = (void (*)(int,siginfo_t *,void *)) (name); \
- sigact.sa_flags = SA_SIGINFO
+ sigact.sa_handler = (void (*)(int)) (name); \
+ sigact.sa_flags = 0
- typedef long context_reg;
- #define CONTEXT_PC (context->uc_mcontext.gregs[REG_PC])
- /* Local register number N is saved on the stack N words
- after the stack pointer */
- #define CONTEXT_SP (context->uc_mcontext.gregs[REG_SP])
- #define SPARC_L_REG(n) ((long *)(context->uc_mcontext.gregs[REG_SP]))[n]
- #define CONTEXT_EXCEPTION_POINTER (SPARC_L_REG(5))
- #define CONTEXT_YOUNG_LIMIT (SPARC_L_REG(7))
- #define CONTEXT_YOUNG_PTR (SPARC_L_REG(6))
+ typedef unsigned long context_reg;
+ #define CONTEXT_PC (context->sregs->regs.psw.addr)
+ #define CONTEXT_EXCEPTION_POINTER (context->sregs->regs.gprs[13])
+ #define CONTEXT_YOUNG_LIMIT (context->sregs->regs.gprs[10])
+ #define CONTEXT_YOUNG_PTR (context->sregs->regs.gprs[11])
+ #define CONTEXT_SP (context->sregs->regs.gprs[15])
/******************** Default */
{
size_t index;
- start_of_free_node_block = (char*) malloc(chunk_size);
+ start_of_free_node_block = (char*) caml_stat_alloc_noexc(chunk_size);
end_of_free_node_block = start_of_free_node_block + chunk_size;
for (index = 0; index < chunk_size / sizeof(value); index++) {
extern value val_process_id;
#endif
-static uint32_t version_number = 0;
+enum {
+ FEATURE_CALL_COUNTS = 1,
+} features;
+
+static uint16_t version_number = 0;
static uint32_t magic_number_base = 0xace00ace;
static void caml_spacetime_write_magic_number_internal(struct channel* chan)
{
- value magic_number =
+ value magic_number;
+ uint16_t features = 0;
+
+#ifdef ENABLE_CALL_COUNTS
+ features |= FEATURE_CALL_COUNTS;
+#endif
+
+ magic_number =
Val_long(((uint64_t) magic_number_base)
- | (((uint64_t) version_number) << 32));
+ | (((uint64_t) version_number) << 32)
+ | (((uint64_t) features) << 48));
Lock(chan);
caml_output_val(chan, magic_number, Val_long(0));
caml_secure_getenv("OCAML_SPACETIME_SNAPSHOT_DIR");
if (user_specified_automatic_snapshot_dir == NULL) {
-#ifdef HAS_GETCWD
+#if defined(HAS_GETCWD)
if (getcwd(cwd, sizeof(cwd)) == NULL) {
dir_ok = 0;
}
#else
- if (getwd(cwd) == NULL) {
- dir_ok = 0;
- }
+ dir_ok = 0;
#endif
if (dir_ok) {
automatic_snapshot_dir = strdup(cwd);
void caml_spacetime_register_shapes(void* dynlinked_table)
{
shape_table* table;
- table = (shape_table*) malloc(sizeof(shape_table));
+ table = (shape_table*) caml_stat_alloc_noexc(sizeof(shape_table));
if (table == NULL) {
fprintf(stderr, "Out of memory whilst registering shape table");
abort();
{
per_thread* thr;
- thr = (per_thread*) malloc(sizeof(per_thread));
+ thr = (per_thread*) caml_stat_alloc_noexc(sizeof(per_thread));
if (thr == NULL) {
fprintf(stderr, "Out of memory while registering thread for profiling\n");
abort();
thr = thr->next;
num_marshalled++;
}
- Assert(num_marshalled == num_per_threads); */
+ CAMLassert(num_marshalled == num_per_threads); */
caml_extern_allow_out_of_heap = 0;
Unlock(chan);
c_node* caml_spacetime_c_node_of_stored_pointer(value node_stored)
{
- Assert(node_stored == Val_unit || Is_c_node(node_stored));
+ CAMLassert(node_stored == Val_unit || Is_c_node(node_stored));
return (node_stored == Val_unit) ? NULL : (c_node*) Hp_val(node_stored);
}
c_node* caml_spacetime_c_node_of_stored_pointer_not_null(
value node_stored)
{
- Assert(Is_c_node(node_stored));
+ CAMLassert(Is_c_node(node_stored));
return (c_node*) Hp_val(node_stored);
}
value caml_spacetime_stored_pointer_of_c_node(c_node* c_node)
{
value node;
- Assert(c_node != NULL);
+ CAMLassert(c_node != NULL);
node = Val_hp(c_node);
- Assert(Is_c_node(node));
+ CAMLassert(Is_c_node(node));
return node;
}
void* node;
uintnat size;
- Assert(size_including_header >= 3);
+ CAMLassert(size_including_header >= 3);
node = caml_stat_alloc(sizeof(uintnat) * size_including_header);
size = size_including_header * sizeof(value);
if (end_of_free_node_block - start_of_free_node_block < size) {
reinitialise_free_node_block();
node = (void*) start_of_free_node_block;
- Assert(end_of_free_node_block - start_of_free_node_block >= size);
+ CAMLassert(end_of_free_node_block - start_of_free_node_block >= size);
}
start_of_free_node_block += size;
/* We don't currently rely on [uintnat] alignment, but we do need some
alignment, so just be sure. */
- Assert (((uintnat) node) % sizeof(uintnat) == 0);
+ CAMLassert (((uintnat) node) % sizeof(uintnat) == 0);
return Val_hp(node);
}
pc = Encode_node_pc(callee);
do {
- Assert(Is_ocaml_node(node));
+ CAMLassert(Is_ocaml_node(node));
if (Node_pc(node) == pc) {
found = node;
}
that tail called the current function. (Such a value is necessary to
be able to find the start of the caller's node, and hence its tail
chain, so we as a tail-called callee can link ourselves in.) */
- Assert(Is_tail_caller_node_encoded(node));
+ CAMLassert(Is_tail_caller_node_encoded(node));
if (node != Val_unit) {
value tail_node;
node = allocate_uninitialized_ocaml_node(size_including_header);
Hd_val(node) =
Make_header(size_including_header - 1, OCaml_node_tag, Caml_black);
- Assert((((uintnat) pc) % 1) == 0);
+ CAMLassert((((uintnat) pc) % 1) == 0);
Node_pc(node) = Encode_node_pc(pc);
/* If the callee was tail called, then the tail link field will link this
new node into an existing tail chain. Otherwise, it is initialized with
if (end_of_free_node_block - start_of_free_node_block < sizeof(c_node)) {
reinitialise_free_node_block();
node = (c_node*) start_of_free_node_block;
- Assert(end_of_free_node_block - start_of_free_node_block
+ CAMLassert(end_of_free_node_block - start_of_free_node_block
>= sizeof(c_node));
}
start_of_free_node_block += sizeof(c_node);
- Assert((sizeof(c_node) % sizeof(uintnat)) == 0);
+ CAMLassert((sizeof(c_node) % sizeof(uintnat)) == 0);
/* CR-soon mshinwell: remove this and pad the structure properly */
for (index = 0; index < sizeof(c_node) / sizeof(value); index++) {
node->gc_header =
Make_header(sizeof(c_node)/sizeof(uintnat) - 1, C_node_tag, Caml_black);
- node->data.callee_node = Val_unit;
+ node->data.call.callee_node = Val_unit;
+ node->data.call.call_count = Val_long(0);
node->next = Val_unit;
return node;
call (e.g. [List.map] when not inlined). */
static void* last_indirect_node_hole_ptr_callee;
static value* last_indirect_node_hole_ptr_node_hole;
-static value* last_indirect_node_hole_ptr_result;
+static call_point* last_indirect_node_hole_ptr_result;
CAMLprim value* caml_spacetime_indirect_node_hole_ptr
(void* callee, value* node_hole, value caller_node)
if (callee == last_indirect_node_hole_ptr_callee
&& node_hole == last_indirect_node_hole_ptr_node_hole) {
- return last_indirect_node_hole_ptr_result;
+#ifdef ENABLE_CALL_COUNTS
+ last_indirect_node_hole_ptr_result->call_count =
+ Val_long (Long_val (last_indirect_node_hole_ptr_result->call_count) + 1);
+#endif
+ return &(last_indirect_node_hole_ptr_result->callee_node);
}
last_indirect_node_hole_ptr_callee = callee;
encoded_callee = Encode_c_node_pc_for_call(callee);
while (*node_hole != Val_unit) {
- Assert(((uintnat) *node_hole) % sizeof(value) == 0);
+ CAMLassert(((uintnat) *node_hole) % sizeof(value) == 0);
c_node = caml_spacetime_c_node_of_stored_pointer_not_null(*node_hole);
- Assert(c_node != NULL);
- Assert(caml_spacetime_classify_c_node(c_node) == CALL);
+ CAMLassert(c_node != NULL);
+ CAMLassert(caml_spacetime_classify_c_node(c_node) == CALL);
if (c_node->pc == encoded_callee) {
- last_indirect_node_hole_ptr_result = &(c_node->data.callee_node);
- return last_indirect_node_hole_ptr_result;
+#ifdef ENABLE_CALL_COUNTS
+ c_node->data.call.call_count =
+ Val_long (Long_val(c_node->data.call.call_count) + 1);
+#endif
+ last_indirect_node_hole_ptr_result = &(c_node->data.call);
+ return &(last_indirect_node_hole_ptr_result->callee_node);
}
else {
node_hole = &c_node->next;
Perform the initialization equivalent to that emitted by
[Spacetime.code_for_function_prologue] for direct tail call
sites. */
- c_node->data.callee_node = Encode_tail_caller_node(caller_node);
+ c_node->data.call.callee_node = Encode_tail_caller_node(caller_node);
}
*node_hole = caml_spacetime_stored_pointer_of_c_node(c_node);
- Assert(((uintnat) *node_hole) % sizeof(value) == 0);
- Assert(*node_hole != Val_unit);
+ CAMLassert(((uintnat) *node_hole) % sizeof(value) == 0);
+ CAMLassert(*node_hole != Val_unit);
- last_indirect_node_hole_ptr_result = &(c_node->data.callee_node);
+#ifdef ENABLE_CALL_COUNTS
+ c_node->data.call.call_count =
+ Val_long (Long_val(c_node->data.call.call_count) + 1);
+#endif
+ last_indirect_node_hole_ptr_result = &(c_node->data.call);
- return last_indirect_node_hole_ptr_result;
+ return &(last_indirect_node_hole_ptr_result->callee_node);
}
/* Some notes on why caml_call_gc doesn't need a distinguished node.
have_frames_already = 1;
}
else {
- frames = (struct ext_table*) malloc(sizeof(struct ext_table));
+ frames =
+ (struct ext_table*) caml_stat_alloc_noexc(sizeof(struct ext_table));
if (!frames) {
caml_fatal_error("Not enough memory for ext_table allocation");
}
for (frame = frames->size - 1; frame >= innermost_frame; frame--) {
c_node_type expected_type;
void* pc = frames->contents[frame];
- Assert (pc != (void*) caml_last_return_address);
+ CAMLassert (pc != (void*) caml_last_return_address);
if (!for_allocation) {
expected_type = CALL;
int found = 0;
node = caml_spacetime_c_node_of_stored_pointer_not_null(*node_hole);
- Assert(node != NULL);
- Assert(node->next == Val_unit
+ CAMLassert(node != NULL);
+ CAMLassert(node->next == Val_unit
|| (((uintnat) (node->next)) % sizeof(value) == 0));
prev = NULL;
}
}
if (!found) {
- Assert(prev != NULL);
+ CAMLassert(prev != NULL);
node = allocate_c_node();
node->pc = (expected_type == CALL ? Encode_c_node_pc_for_call(pc)
: Encode_c_node_pc_for_alloc_point(pc));
}
}
- Assert(node != NULL);
+ CAMLassert(node != NULL);
- Assert(caml_spacetime_classify_c_node(node) == expected_type);
- Assert(pc_inside_c_node_matches(node, pc));
- node_hole = &node->data.callee_node;
+ CAMLassert(caml_spacetime_classify_c_node(node) == expected_type);
+ CAMLassert(pc_inside_c_node_matches(node, pc));
+ node_hole = &node->data.call.callee_node;
}
if (must_initialise_node_for_allocation) {
}
if (for_allocation) {
- Assert(caml_spacetime_classify_c_node(node) == ALLOCATION);
- Assert(caml_spacetime_c_node_of_stored_pointer(node->next) != node);
- Assert(Profinfo_hd(node->data.allocation.profinfo) > 0);
+ CAMLassert(caml_spacetime_classify_c_node(node) == ALLOCATION);
+ CAMLassert(caml_spacetime_c_node_of_stored_pointer(node->next) != node);
+ CAMLassert(Profinfo_hd(node->data.allocation.profinfo) > 0);
node->data.allocation.count =
Val_long(Long_val(node->data.allocation.count) + (1 + wosize));
}
- Assert(node->next != (value) NULL);
+ CAMLassert(node->next != (value) NULL);
return for_allocation ? (void*) node : (void*) node_hole;
#else
node = allocate_uninitialized_ocaml_node(size_including_header);
Hd_val(node) =
Make_header(size_including_header - 1, OCaml_node_tag, Caml_black);
- Assert((((uintnat) identifying_pc_for_caml_start_program) % 1) == 0);
+ CAMLassert((((uintnat) identifying_pc_for_caml_start_program) % 1) == 0);
Node_pc(node) = Encode_node_pc(identifying_pc_for_caml_start_program);
Tail_link(node) = node;
Indirect_pc_linked_list(node, Node_num_header_words) = Val_unit;
/* If there is a node here already, it should never be an initialized
(but as yet unused) tail call point, since calls from OCaml into C
are never tail calls (and no C -> C call is marked as tail). */
- Assert(!Is_tail_caller_node_encoded(node));
+ CAMLassert(!Is_tail_caller_node_encoded(node));
}
- Assert(Is_ocaml_node(node));
- Assert(Decode_node_pc(Node_pc(node))
+ CAMLassert(Is_ocaml_node(node));
+ CAMLassert(Decode_node_pc(Node_pc(node))
== identifying_pc_for_caml_start_program);
- Assert(Tail_link(node) == node);
- Assert(Wosize_val(node) == Node_num_header_words + Indirect_num_fields);
+ CAMLassert(Tail_link(node) == node);
+ CAMLassert(Wosize_val(node) == Node_num_header_words + Indirect_num_fields);
/* Search the node to find the node hole corresponding to the indirect
call to the OCaml function. */
ocaml_entry_point,
&Indirect_pc_linked_list(node, Node_num_header_words),
Val_unit);
- Assert(*caml_spacetime_trie_node_ptr == Val_unit
+ CAMLassert(*caml_spacetime_trie_node_ptr == Val_unit
|| Is_ocaml_node(*caml_spacetime_trie_node_ptr));
}
(which already has to be done in the OCaml-generated code run before
this function). */
node = (value) profinfo_words;
- Assert(Alloc_point_profinfo(node, 0) == Val_unit);
+ CAMLassert(Alloc_point_profinfo(node, 0) == Val_unit);
/* The profinfo value is stored shifted to reduce the number of
instructions required on the OCaml side. It also enables us to use
profinfo = Make_header_with_profinfo(
index_within_node, Infix_tag, Caml_black, profinfo);
- Assert(!Is_block(profinfo));
+ CAMLassert(!Is_block(profinfo));
Alloc_point_profinfo(node, 0) = profinfo;
/* The count is set to zero by the initialisation when the node was
created (see above). */
- Assert(Alloc_point_count(node, 0) == Val_long(0));
+ CAMLassert(Alloc_point_count(node, 0) == Val_long(0));
/* Add the new allocation point into the linked list of all allocation
points. */
Alloc_point_next_ptr(node, 0) = (value) &caml_all_allocation_points->count;
}
else {
- Assert(Alloc_point_next_ptr(node, 0) == Val_unit);
+ CAMLassert(Alloc_point_next_ptr(node, 0) == Val_unit);
}
caml_all_allocation_points = (allocation_point*) node;
#include "caml/sys.h"
#include "caml/spacetime.h"
-#include "../config/s.h"
+#include "caml/s.h"
+
+#define SPACETIME_PROFINFO_WIDTH 26
+#define Spacetime_profinfo_hd(hd) \
+ (Gen_profinfo_hd(SPACETIME_PROFINFO_WIDTH, hd))
#ifdef ARCH_SIXTYFOUR
c_node* caml_spacetime_offline_c_node_of_stored_pointer_not_null
(value node_stored)
{
- Assert(Is_c_node(node_stored));
+ CAMLassert(Is_c_node(node_stored));
return (c_node*) Hp_val(node_stored);
}
CAMLprim value caml_spacetime_compare_node(
value node1, value node2)
{
- Assert(!Is_in_value_area(node1));
- Assert(!Is_in_value_area(node2));
+ CAMLassert(!Is_in_value_area(node1));
+ CAMLassert(!Is_in_value_area(node2));
if (node1 == node2) {
return Val_long(0);
CAMLprim value caml_spacetime_is_ocaml_node(value node)
{
- Assert(Is_ocaml_node(node) || Is_c_node(node));
+ CAMLassert(Is_ocaml_node(node) || Is_c_node(node));
return Val_bool(Is_ocaml_node(node));
}
CAMLprim value caml_spacetime_ocaml_function_identifier(value node)
{
- Assert(Is_ocaml_node(node));
+ CAMLassert(Is_ocaml_node(node));
return caml_copy_int64((uint64_t) Decode_node_pc(Node_pc(node)));
}
CAMLprim value caml_spacetime_ocaml_tail_chain(value node)
{
- Assert(Is_ocaml_node(node));
+ CAMLassert(Is_ocaml_node(node));
return Tail_link(node);
}
uintnat field;
value callee_node;
- Assert(Is_ocaml_node(node));
+ CAMLassert(Is_ocaml_node(node));
field = Long_val(offset);
{
uintnat profinfo_shifted;
profinfo_shifted = (uintnat) Alloc_point_profinfo(node, Long_val(offset));
- return Val_long(Profinfo_hd(profinfo_shifted));
+ return Val_long(Spacetime_profinfo_hd(profinfo_shifted));
}
CAMLprim value caml_spacetime_ocaml_allocation_point_count
(value node, value offset)
{
value count = Alloc_point_count(node, Long_val(offset));
- Assert(!Is_block(count));
+ CAMLassert(!Is_block(count));
return count;
}
return Direct_callee_node(node, Long_val(offset));
}
+CAMLprim value caml_spacetime_ocaml_direct_call_point_call_count
+(value node, value offset)
+{
+ return Direct_call_count(node, Long_val(offset));
+}
+
CAMLprim value caml_spacetime_ocaml_indirect_call_point_callees
(value node, value offset)
{
value callees = Indirect_pc_linked_list(node, Long_val(offset));
- Assert(Is_block(callees));
- Assert(Is_c_node(callees));
+ CAMLassert(Is_block(callees));
+ CAMLassert(Is_c_node(callees));
return callees;
}
CAMLprim value caml_spacetime_c_node_is_call(value node)
{
c_node* c_node;
- Assert(node != (value) NULL);
- Assert(Is_c_node(node));
+ CAMLassert(node != (value) NULL);
+ CAMLassert(Is_c_node(node));
c_node = caml_spacetime_offline_c_node_of_stored_pointer_not_null(node);
switch (caml_spacetime_offline_classify_c_node(c_node)) {
case CALL: return Val_true;
case ALLOCATION: return Val_false;
}
- Assert(0);
+ CAMLassert(0);
return Val_unit; /* silence compiler warning */
}
{
c_node* c_node;
- Assert(node != (value) NULL);
- Assert(Is_c_node(node));
+ CAMLassert(node != (value) NULL);
+ CAMLassert(Is_c_node(node));
c_node = caml_spacetime_offline_c_node_of_stored_pointer_not_null(node);
- Assert(c_node->next == Val_unit || Is_c_node(c_node->next));
+ CAMLassert(c_node->next == Val_unit || Is_c_node(c_node->next));
return c_node->next;
}
CAMLprim value caml_spacetime_c_node_call_site(value node)
{
c_node* c_node;
- Assert(node != (value) NULL);
- Assert(Is_c_node(node));
+ CAMLassert(node != (value) NULL);
+ CAMLassert(Is_c_node(node));
c_node = caml_spacetime_offline_c_node_of_stored_pointer_not_null(node);
return caml_copy_int64((uint64_t) Decode_c_node_pc(c_node->pc));
}
CAMLprim value caml_spacetime_c_node_callee_node(value node)
{
c_node* c_node;
- Assert(node != (value) NULL);
- Assert(Is_c_node(node));
+ CAMLassert(node != (value) NULL);
+ CAMLassert(Is_c_node(node));
c_node = caml_spacetime_offline_c_node_of_stored_pointer_not_null(node);
- Assert(caml_spacetime_offline_classify_c_node(c_node) == CALL);
+ CAMLassert(caml_spacetime_offline_classify_c_node(c_node) == CALL);
/* This might be an uninitialised tail call point: for example if an OCaml
callee was indirectly called but the callee wasn't instrumented (e.g. a
leaf function that doesn't allocate). */
- if (Is_tail_caller_node_encoded(c_node->data.callee_node)) {
+ if (Is_tail_caller_node_encoded(c_node->data.call.callee_node)) {
return Val_unit;
}
- return c_node->data.callee_node;
+ return c_node->data.call.callee_node;
+}
+
+CAMLprim value caml_spacetime_c_node_call_count(value node)
+{
+ c_node* c_node;
+ CAMLassert(node != (value) NULL);
+ CAMLassert(Is_c_node(node));
+ c_node = caml_spacetime_offline_c_node_of_stored_pointer_not_null(node);
+ CAMLassert(caml_spacetime_offline_classify_c_node(c_node) == CALL);
+ if (Is_tail_caller_node_encoded(c_node->data.call.callee_node)) {
+ return Val_long(0);
+ }
+ return c_node->data.call.call_count;
}
CAMLprim value caml_spacetime_c_node_profinfo(value node)
{
c_node* c_node;
- Assert(node != (value) NULL);
- Assert(Is_c_node(node));
+ CAMLassert(node != (value) NULL);
+ CAMLassert(Is_c_node(node));
c_node = caml_spacetime_offline_c_node_of_stored_pointer_not_null(node);
- Assert(caml_spacetime_offline_classify_c_node(c_node) == ALLOCATION);
- Assert(!Is_block(c_node->data.allocation.profinfo));
- return Val_long(Profinfo_hd(c_node->data.allocation.profinfo));
+ CAMLassert(caml_spacetime_offline_classify_c_node(c_node) == ALLOCATION);
+ CAMLassert(!Is_block(c_node->data.allocation.profinfo));
+ return Val_long(Spacetime_profinfo_hd(c_node->data.allocation.profinfo));
}
CAMLprim value caml_spacetime_c_node_allocation_count(value node)
{
c_node* c_node;
- Assert(node != (value) NULL);
- Assert(Is_c_node(node));
+ CAMLassert(node != (value) NULL);
+ CAMLassert(Is_c_node(node));
c_node = caml_spacetime_offline_c_node_of_stored_pointer_not_null(node);
- Assert(caml_spacetime_offline_classify_c_node(c_node) == ALLOCATION);
- Assert(!Is_block(c_node->data.allocation.count));
+ CAMLassert(caml_spacetime_offline_classify_c_node(c_node) == ALLOCATION);
+ CAMLassert(!Is_block(c_node->data.allocation.count));
return c_node->data.allocation.count;
}
/* CR-soon mshinwell: this function should live somewhere else */
header_t* block;
- Assert(size_in_bytes % sizeof(value) == 0);
+ CAMLassert(size_in_bytes % sizeof(value) == 0);
block = caml_stat_alloc(sizeof(header_t) + size_in_bytes);
*block = Make_header(size_in_bytes / sizeof(value), tag, Caml_black);
return (value) &block[1];
static value allocate_outside_heap(mlsize_t size_in_bytes)
{
- Assert(size_in_bytes > 0);
+ CAMLassert(size_in_bytes > 0);
return allocate_outside_heap_with_tag(size_in_bytes, 0);
}
Field(v_total, 2) = v_total_allocations;
v_total_allocations = v_total;
- Assert (total->next == Val_unit
+ CAMLassert (total->next == Val_unit
|| (Is_block(total->next) && Tag_val(total->next) == Infix_tag));
if (total->next == Val_unit) {
total = NULL;
words_scanned += Whsize_hd(hd);
if (profinfo > 0 && profinfo < PROFINFO_MASK) {
words_scanned_with_profinfo += Whsize_hd(hd);
- Assert (raw_entries[profinfo].num_blocks >= 0);
+ CAMLassert (raw_entries[profinfo].num_blocks >= 0);
if (raw_entries[profinfo].num_blocks == 0) {
num_distinct_profinfos++;
}
break;
}
hp += Bhsize_hd (hd);
- Assert (hp <= limit);
+ CAMLassert (hp <= limit);
}
chunk = Chunk_next (chunk);
entries = (snapshot_entries*) v_entries;
target_index = 0;
for (index = 0; index <= PROFINFO_MASK; index++) {
- Assert(raw_entries[index].num_blocks >= 0);
+ CAMLassert(raw_entries[index].num_blocks >= 0);
if (raw_entries[index].num_blocks > 0) {
- Assert(target_index < num_distinct_profinfos);
+ CAMLassert(target_index < num_distinct_profinfos);
entries->entries[target_index].profinfo = Val_long(index);
entries->entries[target_index].num_blocks
= Val_long(raw_entries[index].num_blocks);
v_entries = Atom(0);
}
- Assert(sizeof(double) == sizeof(value));
+ CAMLassert(sizeof(double) == sizeof(value));
v_time = allocate_outside_heap_with_tag(sizeof(double), Double_tag);
- Double_field(v_time, 0) = time;
+ Store_double_val(v_time, time);
v_snapshot = allocate_outside_heap(sizeof(snapshot));
heap_snapshot = (snapshot*) v_snapshot;
Field (result, wosize - 1) = 0;
offset_index = Bsize_wsize (wosize) - 1;
Byte (result, offset_index) = offset_index - len;
- memmove(String_val(result), s, len);
+ memmove(Bytes_val(result), s, len);
return result;
}
}
v_time = allocate_outside_heap_with_tag(sizeof(double), Double_tag);
- Double_field(v_time, 0) = time;
+ Store_double_val(v_time, time);
return v_time;
}
break;
default:
- Assert(0);
+ CAMLassert(0);
abort(); /* silence compiler warning */
}
static value spacetime_disabled()
{
caml_failwith("Spacetime profiling not enabled");
- Assert(0); /* unreachable */
}
CAMLprim value caml_spacetime_take_snapshot(value ignored)
+++ /dev/null
-/**************************************************************************/
-/* */
-/* OCaml */
-/* */
-/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */
-/* */
-/* Copyright 1996 Institut National de Recherche en Informatique et */
-/* en Automatique. */
-/* */
-/* All rights reserved. This file is distributed under the terms of */
-/* the GNU Lesser General Public License version 2.1, with the */
-/* special exception on linking described in the file LICENSE. */
-/* */
-/**************************************************************************/
-
-/* Asm part of the runtime system for the Sparc processor. */
-/* Must be preprocessed by cpp */
-
-#ifndef SYS_solaris
-#define INDIRECT_LIMIT
-#endif
-
-#define Exn_ptr %l5
-#define Alloc_ptr %l6
-#define Alloc_limit %l7
-
-#define Load(symb,reg) sethi %hi(symb), %g1; ld [%g1 + %lo(symb)], reg
-#define Store(reg,symb) sethi %hi(symb), %g1; st reg, [%g1 + %lo(symb)]
-#define Address(symb,reg) sethi %hi(symb), reg; or reg, %lo(symb), reg
-
-/* Allocation functions */
-
- .text
-
- .global caml_system__code_begin
-caml_system__code_begin:
-
- .global caml_allocN
- .global caml_call_gc
-
-/* Required size in %g2 */
-caml_allocN:
-#ifdef INDIRECT_LIMIT
- ld [Alloc_limit], %g1
- sub Alloc_ptr, %g2, Alloc_ptr
- cmp Alloc_ptr, %g1
-#else
- sub Alloc_ptr, %g2, Alloc_ptr
- cmp Alloc_ptr, Alloc_limit
-#endif
- /*blu,pt %icc, caml_call_gc*/
- blu caml_call_gc
- nop
- retl
- nop
-
-/* Required size in %g2 */
-caml_call_gc:
- /* Save exception pointer if GC raises */
- Store(Exn_ptr, caml_exception_pointer)
- /* Save current allocation pointer for debugging purposes */
- Store(Alloc_ptr, caml_young_ptr)
- /* Record lowest stack address */
- Store(%sp, caml_bottom_of_stack)
- /* Record last return address */
- Store(%o7, caml_last_return_address)
- /* Allocate space on stack for caml_context structure and float regs */
- sub %sp, 20*4 + 15*8, %sp
- /* Save int regs on stack and save it into caml_gc_regs */
-L100: add %sp, 96 + 15*8, %g1
- st %o0, [%g1]
- st %o1, [%g1 + 0x4]
- st %o2, [%g1 + 0x8]
- st %o3, [%g1 + 0xc]
- st %o4, [%g1 + 0x10]
- st %o5, [%g1 + 0x14]
- st %i0, [%g1 + 0x18]
- st %i1, [%g1 + 0x1c]
- st %i2, [%g1 + 0x20]
- st %i3, [%g1 + 0x24]
- st %i4, [%g1 + 0x28]
- st %i5, [%g1 + 0x2c]
- st %l0, [%g1 + 0x30]
- st %l1, [%g1 + 0x34]
- st %l2, [%g1 + 0x38]
- st %l3, [%g1 + 0x3c]
- st %l4, [%g1 + 0x40]
- st %g3, [%g1 + 0x44]
- st %g4, [%g1 + 0x48]
- st %g2, [%g1 + 0x4C] /* Save required size */
- mov %g1, %g2
- Store(%g2, caml_gc_regs)
- /* Save the floating-point registers */
- add %sp, 96, %g1
- std %f0, [%g1]
- std %f2, [%g1 + 0x8]
- std %f4, [%g1 + 0x10]
- std %f6, [%g1 + 0x18]
- std %f8, [%g1 + 0x20]
- std %f10, [%g1 + 0x28]
- std %f12, [%g1 + 0x30]
- std %f14, [%g1 + 0x38]
- std %f16, [%g1 + 0x40]
- std %f18, [%g1 + 0x48]
- std %f20, [%g1 + 0x50]
- std %f22, [%g1 + 0x58]
- std %f24, [%g1 + 0x60]
- std %f26, [%g1 + 0x68]
- std %f28, [%g1 + 0x70]
- /* Call the garbage collector */
- call caml_garbage_collection
- nop
- /* Restore all regs used by the code generator */
- add %sp, 96 + 15*8, %g1
- ld [%g1], %o0
- ld [%g1 + 0x4], %o1
- ld [%g1 + 0x8], %o2
- ld [%g1 + 0xc], %o3
- ld [%g1 + 0x10], %o4
- ld [%g1 + 0x14], %o5
- ld [%g1 + 0x18], %i0
- ld [%g1 + 0x1c], %i1
- ld [%g1 + 0x20], %i2
- ld [%g1 + 0x24], %i3
- ld [%g1 + 0x28], %i4
- ld [%g1 + 0x2c], %i5
- ld [%g1 + 0x30], %l0
- ld [%g1 + 0x34], %l1
- ld [%g1 + 0x38], %l2
- ld [%g1 + 0x3c], %l3
- ld [%g1 + 0x40], %l4
- ld [%g1 + 0x44], %g3
- ld [%g1 + 0x48], %g4
- ld [%g1 + 0x4C], %g2 /* Recover desired size */
- add %sp, 96, %g1
- ldd [%g1], %f0
- ldd [%g1 + 0x8], %f2
- ldd [%g1 + 0x10], %f4
- ldd [%g1 + 0x18], %f6
- ldd [%g1 + 0x20], %f8
- ldd [%g1 + 0x28], %f10
- ldd [%g1 + 0x30], %f12
- ldd [%g1 + 0x38], %f14
- ldd [%g1 + 0x40], %f16
- ldd [%g1 + 0x48], %f18
- ldd [%g1 + 0x50], %f20
- ldd [%g1 + 0x58], %f22
- ldd [%g1 + 0x60], %f24
- ldd [%g1 + 0x68], %f26
- ldd [%g1 + 0x70], %f28
- /* Reload alloc ptr */
- Load(caml_young_ptr, Alloc_ptr)
- /* Allocate space for block */
-#ifdef INDIRECT_LIMIT
- ld [Alloc_limit], %g1
- sub Alloc_ptr, %g2, Alloc_ptr
- cmp Alloc_ptr, %g1 /* Check that we have enough free space */
-#else
- Load(caml_young_limit,Alloc_limit)
- sub Alloc_ptr, %g2, Alloc_ptr
- cmp Alloc_ptr, Alloc_limit
-#endif
- blu L100 /* If not, call GC again */
- nop
- /* Return to caller */
- Load(caml_last_return_address, %o7)
- retl
- add %sp, 20*4 + 15*8, %sp /* in delay slot */
-
-/* Call a C function from Ocaml */
-
- .global caml_c_call
-/* Function to call is in %g2 */
-caml_c_call:
- /* Record lowest stack address and return address */
- Store(%sp, caml_bottom_of_stack)
- Store(%o7, caml_last_return_address)
- /* Save the exception handler and alloc pointer */
- Store(Exn_ptr, caml_exception_pointer)
- sethi %hi(caml_young_ptr), %g1
- /* Call the C function */
- call %g2
- st Alloc_ptr, [%g1 + %lo(caml_young_ptr)] /* in delay slot */
- /* Reload return address */
- Load(caml_last_return_address, %o7)
- /* Reload alloc pointer */
- sethi %hi(caml_young_ptr), %g1
- /* Return to caller */
- retl
- ld [%g1 + %lo(caml_young_ptr)], Alloc_ptr /* in delay slot */
-
-/* Start the Ocaml program */
-
- .global caml_start_program
-caml_start_program:
- /* Save all callee-save registers */
- save %sp, -96, %sp
- /* Address of code to call */
- Address(caml_program, %l2)
-
- /* Code shared with caml_callback* */
-L108:
- /* Set up a callback link on the stack. */
- sub %sp, 16, %sp
- Load(caml_bottom_of_stack, %l0)
- Load(caml_last_return_address, %l1)
- Load(caml_gc_regs, %l3)
- st %l0, [%sp + 96]
- st %l1, [%sp + 100]
- /* Set up a trap frame to catch exceptions escaping the Ocaml code */
- call L111
- st %l3, [%sp + 104]
- b L110
- nop
-L111: sub %sp, 8, %sp
- Load(caml_exception_pointer, Exn_ptr)
- st %o7, [%sp + 96]
- st Exn_ptr, [%sp + 100]
- mov %sp, Exn_ptr
- /* Reload allocation pointers */
- Load(caml_young_ptr, Alloc_ptr)
-#ifdef INDIRECT_LIMIT
- Address(caml_young_limit, Alloc_limit)
-#else
- Load(caml_young_limit, Alloc_limit)
-#endif
- /* Call the Ocaml code */
-L109: call %l2
- nop
- /* Pop trap frame and restore caml_exception_pointer */
- ld [%sp + 100], Exn_ptr
- add %sp, 8, %sp
- Store(Exn_ptr, caml_exception_pointer)
- /* Pop callback link, restoring the global variables */
-L112: ld [%sp + 96], %l0
- ld [%sp + 100], %l1
- ld [%sp + 104], %l2
- Store(%l0, caml_bottom_of_stack)
- Store(%l1, caml_last_return_address)
- Store(%l2, caml_gc_regs)
- add %sp, 16, %sp
- /* Save allocation pointer */
- Store(Alloc_ptr, caml_young_ptr)
- /* Reload callee-save registers and return */
- ret
- restore %o0, 0, %o0 /* copy %o0 in this window to caller's %o0 */
-L110:
- /* The trap handler */
- Store(Exn_ptr, caml_exception_pointer)
- /* Encode exception bucket as an exception result */
- b L112
- or %o0, 2, %o0
-
-/* Raise an exception from C */
-
- .global caml_raise_exception
-caml_raise_exception:
- /* Save exception bucket in a register outside the reg windows */
- mov %o0, %g2
- /* Load exception pointer in a register outside the reg windows */
- Load(caml_exception_pointer, %g3)
- /* Pop some frames until the trap pointer is in the current frame. */
- cmp %g3, %fp
- blt L107 /* if Exn_ptr < %fp, over */
- nop
-L106: restore
- cmp %fp, %g3 /* if %fp <= Exn_ptr, loop */
- ble L106
- nop
-L107:
- /* Reload allocation registers */
- Load(caml_young_ptr, Alloc_ptr)
-#ifdef INDIRECT_LIMIT
- Address(caml_young_limit, Alloc_limit)
-#else
- Load(caml_young_limit, Alloc_limit)
-#endif
- /* Branch to exception handler */
- mov %g3, %sp
- ld [%sp + 96], %g1
- ld [%sp + 100], Exn_ptr
- add %sp, 8, %sp
- jmp %g1 + 8
- /* Restore bucket, in delay slot */
- mov %g2, %o0
-
-/* Callbacks C -> ML */
-
- .global caml_callback_exn
-caml_callback_exn:
- /* Save callee-save registers and return address */
- save %sp, -96, %sp
- /* Initial shuffling of arguments */
- mov %i0, %g1
- mov %i1, %i0 /* first arg */
- mov %g1, %i1 /* environment */
- b L108
- ld [%g1], %l2 /* code pointer */
-
- .global caml_callback2_exn
-caml_callback2_exn:
- /* Save callee-save registers and return address */
- save %sp, -104, %sp
- /* Initial shuffling of arguments */
- mov %i0, %g1
- mov %i1, %i0 /* first arg */
- mov %i2, %i1 /* second arg */
- mov %g1, %i2 /* environment */
- sethi %hi(caml_apply2), %l2
- b L108
- or %l2, %lo(caml_apply2), %l2
-
- .global caml_callback3_exn
-caml_callback3_exn:
- /* Save callee-save registers and return address */
- save %sp, -104, %sp
- /* Initial shuffling of arguments */
- mov %i0, %g1
- mov %i1, %i0 /* first arg */
- mov %i2, %i1 /* second arg */
- mov %i3, %i2 /* third arg */
- mov %g1, %i3 /* environment */
- sethi %hi(caml_apply3), %l2
- b L108
- or %l2, %lo(caml_apply3), %l2
-
-#ifndef SYS_solaris
-/* Glue code to call [caml_array_bound_error] */
-
- .global caml_ml_array_bound_error
-caml_ml_array_bound_error:
- Address(caml_array_bound_error, %g2)
- b caml_c_call
- nop
-#endif
-
- .global caml_system__code_end
-caml_system__code_end:
-
-#ifdef SYS_solaris
- .section ".rodata"
-#else
- .data
-#endif
- .global caml_system__frametable
- .align 4 /* required for gas? */
-caml_system__frametable:
- .word 1 /* one descriptor */
- .word L109 /* return address into callback */
- .half -1 /* negative frame size => use callback link */
- .half 0 /* no roots */
-
-#ifdef SYS_solaris
- .type caml_allocN, #function
- .type caml_call_gc, #function
- .type caml_c_call, #function
- .type caml_start_program, #function
- .type caml_raise_exception, #function
- .type caml_system__frametable, #object
-#endif
extern value caml_start_program (void);
extern void caml_init_ieee_floats (void);
extern void caml_init_signals (void);
+#ifdef _WIN32
+extern void caml_win32_overflow_detection (void);
+#endif
#if defined(_MSC_VER) && __STDC_SECURE_LIB__ >= 200411L
#endif
-value caml_startup_exn(char **argv)
+value caml_startup_common(char_os **argv, int pooling)
{
- char * exe_name, * proc_self_exe;
+ char_os * exe_name, * proc_self_exe;
char tos;
+ /* Determine options */
+#ifdef DEBUG
+ caml_verb_gc = 0x3F;
+#endif
+ caml_parse_ocamlrunparam();
+#ifdef DEBUG
+ caml_gc_message (-1, "### OCaml runtime: debug mode ###\n");
+#endif
+ if (caml_cleanup_on_exit)
+ pooling = 1;
+ if (!caml_startup_aux(pooling))
+ return Val_unit;
+
#ifdef WITH_SPACETIME
caml_spacetime_initialize();
#endif
#endif
caml_init_custom_operations();
caml_top_of_stack = &tos;
-#ifdef DEBUG
- caml_verb_gc = 0x3F;
-#endif
- caml_parse_ocamlrunparam();
-#ifdef DEBUG
- caml_gc_message (-1, "### OCaml runtime: debug mode ###\n", 0);
-#endif
caml_init_gc (caml_init_minor_heap_wsz, caml_init_heap_wsz,
caml_init_heap_chunk_sz, caml_init_percent_free,
caml_init_max_percent_free, caml_init_major_window);
init_static();
caml_init_signals();
+#ifdef _WIN32
+ caml_win32_overflow_detection();
+#endif
caml_init_backtrace();
caml_debugger_init (); /* force debugger.o stub to be linked */
exe_name = argv[0];
- if (exe_name == NULL) exe_name = "";
+ if (exe_name == NULL) exe_name = _T("");
proc_self_exe = caml_executable_name();
if (proc_self_exe != NULL)
exe_name = proc_self_exe;
return caml_start_program();
}
-void caml_startup(char **argv)
+value caml_startup_exn(char_os **argv)
{
- value res = caml_startup_exn(argv);
+ return caml_startup_common(argv, /* pooling */ 0);
+}
- if (Is_exception_result(res)) {
+void caml_startup(char_os **argv)
+{
+ value res = caml_startup_exn(argv);
+ if (Is_exception_result(res))
caml_fatal_uncaught_exception(Extract_exception(res));
- }
}
-void caml_main(char **argv)
+void caml_main(char_os **argv)
{
caml_startup(argv);
}
+
+value caml_startup_pooled_exn(char_os **argv)
+{
+ return caml_startup_common(argv, /* pooling */ 1);
+}
+
+void caml_startup_pooled(char_os **argv)
+{
+ value res = caml_startup_pooled_exn(argv);
+ if (Is_exception_result(res))
+ caml_fatal_uncaught_exception(Extract_exception(res));
+}
| _ -> false
;;
-let rec size_of_lambda = function
+let rec size_of_lambda env = function
+ | Lvar id ->
+ begin try Ident.find_same id env with Not_found -> RHS_nonrec end
| Lfunction{params} as funct ->
RHS_function (1 + IdentSet.cardinal(free_variables funct),
List.length params)
| Record_float -> RHS_floatblock size
| Record_extension -> RHS_block (size + 1)
end
- | Llet(_str, _k, _id, _arg, body) -> size_of_lambda body
- | Lletrec(_bindings, body) -> size_of_lambda body
+ | Llet(_str, _k, id, arg, body) ->
+ size_of_lambda (Ident.add id (size_of_lambda env arg) env) body
+ | Lletrec(bindings, body) ->
+ let env = List.fold_right
+ (fun (id, e) env -> Ident.add id (size_of_lambda env e) env)
+ bindings env
+ in
+ size_of_lambda env body
| Lprim(Pmakeblock _, args, _) -> RHS_block (List.length args)
| Lprim (Pmakearray ((Paddrarray|Pintarray), _), args, _) ->
RHS_block (List.length args)
| Lprim (Pmakearray (Pfloatarray, _), args, _) ->
RHS_floatblock (List.length args)
- | Lprim (Pmakearray (Pgenarray, _), _, _) -> assert false
+ | Lprim (Pmakearray (Pgenarray, _), _, _) ->
+ (* Pgenarray is excluded from recursive bindings by the
+ check in Translcore.check_recursive_lambda *)
+ RHS_nonrec
| Lprim (Pduprecord ((Record_regular | Record_inlined _), size), _, _) ->
RHS_block size
| Lprim (Pduprecord (Record_unboxed _, _), _, _) ->
| Lprim (Pduprecord (Record_extension, size), _, _) ->
RHS_block (size + 1)
| Lprim (Pduprecord (Record_float, size), _, _) -> RHS_floatblock size
- | Levent (lam, _) -> size_of_lambda lam
- | Lsequence (_lam, lam') -> size_of_lambda lam'
+ | Levent (lam, _) -> size_of_lambda env lam
+ | Lsequence (_lam, lam') -> size_of_lambda env lam'
| _ -> RHS_nonrec
(**** Merging consecutive events ****)
| Pstring_set_64(_) -> Kccall("caml_string_set64", 3)
| Parraylength _ -> Kvectlength
| Parrayrefs Pgenarray -> Kccall("caml_array_get", 2)
- | Parrayrefs Pfloatarray -> Kccall("caml_array_get_float", 2)
+ | Parrayrefs Pfloatarray -> Kccall("caml_floatarray_get", 2)
| Parrayrefs _ -> Kccall("caml_array_get_addr", 2)
| Parraysets Pgenarray -> Kccall("caml_array_set", 3)
- | Parraysets Pfloatarray -> Kccall("caml_array_set_float", 3)
+ | Parraysets Pfloatarray -> Kccall("caml_floatarray_set", 3)
| Parraysets _ -> Kccall("caml_array_set_addr", 3)
| Parrayrefu Pgenarray -> Kccall("caml_array_unsafe_get", 2)
- | Parrayrefu Pfloatarray -> Kccall("caml_array_unsafe_get_float", 2)
+ | Parrayrefu Pfloatarray -> Kccall("caml_floatarray_unsafe_get", 2)
| Parrayrefu _ -> Kgetvectitem
| Parraysetu Pgenarray -> Kccall("caml_array_unsafe_set", 3)
- | Parraysetu Pfloatarray -> Kccall("caml_array_unsafe_set_float", 3)
+ | Parraysetu Pfloatarray -> Kccall("caml_floatarray_unsafe_set", 3)
| Parraysetu _ -> Ksetvectitem
| Pctconst c ->
let const_name = match c with
module Storer =
Switch.Store
(struct type t = lambda type key = lambda
+ let compare_key = Pervasives.compare
let make_key = Lambda.make_key end)
(* Compile an expression.
(add_pop ndecl cont)))
end else begin
let decl_size =
- List.map (fun (id, exp) -> (id, exp, size_of_lambda exp)) decl in
+ List.map (fun (id, exp) -> (id, exp, size_of_lambda Ident.empty exp)) decl in
let rec comp_init new_env sz = function
| [] -> comp_nonrec new_env sz ndecl decl_size
| (id, _exp, RHS_floatblock blocksize) :: rem ->
comp_expr env (Lprim (Pccall prim_obj_dup, [arg], loc)) sz cont
| Lprim (Pduparray _, _, _) ->
Misc.fatal_error "Bytegen.comp_expr: Pduparray takes exactly one arg"
-(* Integer first for enabling futher optimization (cf. emitcode.ml) *)
+(* Integer first for enabling further optimization (cf. emitcode.ml) *)
| Lprim (Pintcomp c, [arg ; (Lconst _ as k)], _) ->
let p = Pintcomp (commute_comparison c)
and args = [k ; arg] in
(Kacc 1 :: Kpush :: Koffsetint offset :: Kassign 2 ::
Kacc 1 :: Kintcomp Cneq :: Kbranchif lbl_loop ::
Klabel lbl_exit :: add_const_unit (add_pop 2 cont))))
- | Lswitch(arg, sw) ->
+ | Lswitch(arg, sw, _loc) ->
let (branch, cont1) = make_branch cont in
let c = ref (discard_dead_code cont1) in
let ev = event (Event_after ty) info in
let cont1 = add_event ev cont in
comp_expr env lam sz cont1
+ | Lev_module_definition _ ->
+ comp_expr env lam sz cont
end
| Lifused (_, exp) ->
comp_expr env exp sz cont
lib_ccopts = !Clflags.all_ccopts @ !lib_ccopts;
lib_dllibs = !Clflags.dllibs @ !lib_dllibs } in
let pos_toc = pos_out outchan in
- output_value outchan toc;
+ Emitcode.marshal_to_channel_with_possibly_32bit_compat
+ ~filename:lib_name ~kind:"bytecode library"
+ outchan toc;
seek_out outchan ofs_pos_toc;
output_binary_int outchan pos_toc;
close_out outchan
| Custom_runtime
| File_exists of string
| Cannot_open_dll of string
- | Not_compatible_32
| Required_module_unavailable of string
exception Error of error
Symtable.output_primitive_names outchan;
Bytesections.record outchan "PRIM";
(* The table of global data *)
- begin try
- Marshal.to_channel outchan (Symtable.initial_global_table())
- (if !Clflags.bytecode_compatible_32
- then [Marshal.Compat_32] else [])
- with Failure _ ->
- raise (Error Not_compatible_32)
- end;
+ Emitcode.marshal_to_channel_with_possibly_32bit_compat
+ ~filename:exec_name ~kind:"bytecode executable"
+ outchan (Symtable.initial_global_table());
Bytesections.record outchan "DATA";
(* The map of global identifiers *)
Symtable.output_global_map outchan;
begin try
(* The bytecode *)
output_string outchan "\
-#ifdef __cplusplus\
+#define CAML_INTERNALS\
+\n\
+\n#ifdef __cplusplus\
\nextern \"C\" {\
\n#endif\
\n#include <caml/mlvalues.h>\
-\nCAMLextern void caml_startup_code(\
-\n code_t code, asize_t code_size,\
-\n char *data, asize_t data_size,\
-\n char *section_table, asize_t section_table_size,\
-\n char **argv);\n";
+\n#include <caml/startup.h>\n";
output_string outchan "static int caml_code[] = {\n";
Symtable.init();
clear_crc_interfaces ();
Symtable.output_primitive_table outchan;
(* The entry point *)
output_string outchan "\
-\nvoid caml_startup(char ** argv)\
+\nvoid caml_startup(char_os ** argv)\
+\n{\
+\n caml_startup_code(caml_code, sizeof(caml_code),\
+\n caml_data, sizeof(caml_data),\
+\n caml_sections, sizeof(caml_sections),\
+\n /* pooling */ 0,\
+\n argv);\
+\n}\
+\n\
+\nvalue caml_startup_exn(char_os ** argv)\
+\n{\
+\n return caml_startup_code_exn(caml_code, sizeof(caml_code),\
+\n caml_data, sizeof(caml_data),\
+\n caml_sections, sizeof(caml_sections),\
+\n /* pooling */ 0,\
+\n argv);\
+\n}\
+\n\
+\nvoid caml_startup_pooled(char_os ** argv)\
\n{\
\n caml_startup_code(caml_code, sizeof(caml_code),\
\n caml_data, sizeof(caml_data),\
\n caml_sections, sizeof(caml_sections),\
+\n /* pooling */ 1,\
\n argv);\
\n}\
-\nvalue caml_startup_exn(char ** argv)\
+\n\
+\nvalue caml_startup_pooled_exn(char_os ** argv)\
\n{\
\n return caml_startup_code_exn(caml_code, sizeof(caml_code),\
\n caml_data, sizeof(caml_data),\
\n caml_sections, sizeof(caml_sections),\
+\n /* pooling */ 1,\
\n argv);\
\n}\
\n#ifdef __cplusplus\
raise x
end else begin
let basename = Filename.chop_extension output_name in
+ let temps = ref [] in
let c_file =
- if !Clflags.output_complete_object
+ if !Clflags.output_complete_object && not (Filename.check_suffix output_name ".c")
then Filename.temp_file "camlobj" ".c"
- else basename ^ ".c"
- and obj_file =
+ else begin
+ let f = basename ^ ".c" in
+ if Sys.file_exists f then raise(Error(File_exists f));
+ f
+ end
+ in
+ let obj_file =
if !Clflags.output_complete_object
- then Filename.temp_file "camlobj" Config.ext_obj
+ then (Filename.chop_extension c_file) ^ Config.ext_obj
else basename ^ Config.ext_obj
in
- if Sys.file_exists c_file then raise(Error(File_exists c_file));
- let temps = ref [] in
try
link_bytecode_as_c ppf tolink c_file;
if not (Filename.check_suffix output_name ".c") then begin
temps := c_file :: !temps;
- if Ccomp.compile_file c_file <> 0 then
+ if Ccomp.compile_file ~output:obj_file c_file <> 0 then
raise(Error Custom_runtime);
if not (Filename.check_suffix output_name Config.ext_obj) ||
!Clflags.output_complete_object then begin
| Cannot_open_dll file ->
fprintf ppf "Error on dynamically loaded library: %a"
Location.print_filename file
- | Not_compatible_32 ->
- fprintf ppf "Generated bytecode executable cannot be run\
- \ on a 32-bit platform"
| Required_module_unavailable s ->
fprintf ppf "Required module `%s' is unavailable" s
| Custom_runtime
| File_exists of string
| Cannot_open_dll of string
- | Not_compatible_32
| Required_module_unavailable of string
exception Error of error
cu_force_link = !force_link;
cu_debug = if pos_final > pos_debug then pos_debug else 0;
cu_debugsize = pos_final - pos_debug } in
- output_value oc compunit;
+ Emitcode.marshal_to_channel_with_possibly_32bit_compat
+ ~filename:targetfile ~kind:"bytecode unit"
+ oc compunit;
seek_out oc pos_depl;
output_binary_int oc pos_final;
close_out oc
module StringSet = Set.Make(String)
+type error = Not_compatible_32 of (string * string)
+exception Error of error
+
+(* marshal and possibly check 32bit compat *)
+let marshal_to_channel_with_possibly_32bit_compat ~filename ~kind outchan obj =
+ try
+ Marshal.to_channel outchan obj
+ (if !Clflags.bytecode_compatible_32
+ then [Marshal.Compat_32] else [])
+ with Failure _ ->
+ raise (Error (Not_compatible_32 (filename, kind)))
+
+
+let report_error ppf (file, kind) =
+ Format.fprintf ppf "Generated %s %S cannot be used on a 32-bit platform" kind file
+let () =
+ Location.register_error_of_exn
+ (function
+ | Error (Not_compatible_32 info) -> Some (Location.error_of_printer_file report_error info)
+ | _ -> None
+ )
+
(* Buffering of bytecode *)
let out_buffer = ref(LongString.create 1024)
Btype.cleanup_abbrev (); (* Remove any cached abbreviation
expansion before saving *)
let pos_compunit = pos_out outchan in
- output_value outchan compunit;
+ marshal_to_channel_with_possibly_32bit_compat
+ ~filename:objfile ~kind:"bytecode unit"
+ outchan compunit;
seek_out outchan pos_depl;
output_binary_int outchan pos_compunit
relocation information (reversed) *)
val reset: unit -> unit
+
+val marshal_to_channel_with_possibly_32bit_compat : filename:string -> kind:string -> out_channel -> 'a -> unit
stack frame.
The ce_heap component gives the positions of variables residing in the
heap-allocated environment.
- The ce_rec component associate offsets to identifiers for functions
+ The ce_rec component associates offsets to identifiers for functions
bound by the same let rec as the current function. The offsets
are used by the OFFSETCLOSURE instruction to recover the closure
pointer of the desired function from the env register (which
| Llet of let_kind * value_kind * Ident.t * lambda * lambda
| Lletrec of (Ident.t * lambda) list * lambda
| Lprim of primitive * lambda list * Location.t
- | Lswitch of lambda * lambda_switch
+ | Lswitch of lambda * lambda_switch * Location.t
| Lstringswitch of
lambda * (string * lambda) list * lambda option * Location.t
| Lstaticraise of int * lambda list
| Lev_after of Types.type_expr
| Lev_function
| Lev_pseudo
+ | Lev_module_definition of Ident.t
type program =
{ module_ident : Ident.t;
Llet (str,k,y,ex,tr_rec (Ident.add x (Lvar y) env) e)
| Lprim (p,es,_) ->
Lprim (p,tr_recs env es, Location.none)
- | Lswitch (e,sw) ->
- Lswitch (tr_rec env e,tr_sw env sw)
+ | Lswitch (e,sw,loc) ->
+ Lswitch (tr_rec env e,tr_sw env sw,loc)
| Lstringswitch (e,sw,d,_) ->
Lstringswitch
(tr_rec env e,
List.iter (fun (_id, exp) -> f exp) decl
| Lprim(_p, args, _loc) ->
List.iter f args
- | Lswitch(arg, sw) ->
+ | Lswitch(arg, sw,_) ->
f arg;
List.iter (fun (_key, case) -> f case) sw.sw_consts;
List.iter (fun (_key, case) -> f case) sw.sw_blocks;
| Papply _ ->
fatal_error "Lambda.transl_path"
-(* Translation of value identifiers *)
+(* Translation of identifiers *)
-let transl_path ?(loc=Location.none) env path =
+let transl_module_path ?(loc=Location.none) env path =
transl_normal_path (Env.normalize_path (Some loc) env path)
+let transl_value_path ?(loc=Location.none) env path =
+ transl_normal_path (Env.normalize_path_prefix (Some loc) env path)
+
+let transl_class_path = transl_value_path
+let transl_extension_path = transl_value_path
+
+(* compatibility alias, deprecated in the .mli *)
+let transl_path = transl_value_path
+
(* Compile a sequence of expressions *)
let rec make_sequence fn = function
| Llet(str, k, id, arg, body) -> Llet(str, k, id, subst arg, subst body)
| Lletrec(decl, body) -> Lletrec(List.map subst_decl decl, subst body)
| Lprim(p, args, loc) -> Lprim(p, List.map subst args, loc)
- | Lswitch(arg, sw) ->
+ | Lswitch(arg, sw, loc) ->
Lswitch(subst arg,
{sw with sw_consts = List.map subst_case sw.sw_consts;
sw_blocks = List.map subst_case sw.sw_blocks;
- sw_failaction = subst_opt sw.sw_failaction; })
+ sw_failaction = subst_opt sw.sw_failaction; },
+ loc)
| Lstringswitch (arg,cases,default,loc) ->
Lstringswitch
(subst arg,List.map subst_strcase cases,subst_opt default,loc)
Lletrec (List.map (fun (v, e) -> (v, map f e)) idel, map f e2)
| Lprim (p, el, loc) ->
Lprim (p, List.map (map f) el, loc)
- | Lswitch (e, sw) ->
+ | Lswitch (e, sw, loc) ->
Lswitch (map f e,
{ sw_numconsts = sw.sw_numconsts;
sw_consts = List.map (fun (n, e) -> (n, map f e)) sw.sw_consts;
sw_numblocks = sw.sw_numblocks;
sw_blocks = List.map (fun (n, e) -> (n, map f e)) sw.sw_blocks;
sw_failaction = Misc.may_map (map f) sw.sw_failaction;
- })
+ },
+ loc)
| Lstringswitch (e, sw, default, loc) ->
Lstringswitch (
map f e,
Lconst (Const_immstring loc)
| Loc_LINE -> Lconst (Const_base (Const_int lnum))
+let merge_inline_attributes attr1 attr2 =
+ match attr1, attr2 with
+ | Default_inline, _ -> Some attr2
+ | _, Default_inline -> Some attr1
+ | _, _ ->
+ if attr1 = attr2 then Some attr1
+ else None
+
let reset () =
raise_count := 0
type let_kind = Strict | Alias | StrictOpt | Variable
(* Meaning of kinds for let x = e in e':
- Strict: e may have side-effets; always evaluate e first
+ Strict: e may have side-effects; always evaluate e first
(If e is a simple expression, e.g. a variable or constant,
we may still substitute e'[x/e].)
Alias: e is pure, we can substitute e'[x/e] if x has 0 or 1 occurrences
| Llet of let_kind * value_kind * Ident.t * lambda * lambda
| Lletrec of (Ident.t * lambda) list * lambda
| Lprim of primitive * lambda list * Location.t
- | Lswitch of lambda * lambda_switch
+ | Lswitch of lambda * lambda_switch * Location.t
(* switch on strings, clauses are sorted by string order,
strings are pairwise distinct *)
| Lstringswitch of
| Lev_after of Types.type_expr
| Lev_function
| Lev_pseudo
+ | Lev_module_definition of Ident.t
type program =
{ module_ident : Ident.t;
val transl_normal_path: Path.t -> lambda (* Path.t is already normal *)
val transl_path: ?loc:Location.t -> Env.t -> Path.t -> lambda
+[@@ocaml.deprecated "use transl_{module,value,extension,class}_path instead"]
+
+val transl_module_path: ?loc:Location.t -> Env.t -> Path.t -> lambda
+val transl_value_path: ?loc:Location.t -> Env.t -> Path.t -> lambda
+val transl_extension_path: ?loc:Location.t -> Env.t -> Path.t -> lambda
+val transl_class_path: ?loc:Location.t -> Env.t -> Path.t -> lambda
+
val make_sequence: ('a -> lambda) -> 'a list -> lambda
val subst_lambda: lambda Ident.tbl -> lambda -> lambda
val raise_kind: raise_kind -> string
val lam_of_loc : loc_kind -> Location.t -> lambda
+val merge_inline_attributes
+ : inline_attribute
+ -> inline_attribute
+ -> inline_attribute option
+
val reset: unit -> unit
-(* Identifing some semantically equivalent lambda-expressions,
+(* Identifying some semantically equivalent lambda-expressions,
Our goal here is also to
find alpha-equivalent (simple) terms *)
(struct
type t = lambda
type key = lambda
+ let compare_key = Pervasives.compare
let make_key = Lambda.make_key
end)
(*
- Simplify fonction normalize the first column of the match
+ The simplify function normalizes the first column of the match
- records are expanded so that they possess all fields
- aliases are removed and replaced by bindings in actions.
However or-patterns are simplified differently,
ap_args=[varg];
ap_inlined=Default_inline;
ap_specialised=Default_specialise}) ];
- sw_failaction = Some varg } ))))
+ sw_failaction = Some varg }, loc ))))
let inline_lazy_force arg loc =
if !Clflags.native_code then
bind_sw
(Lprim
(prim_string_compare,
- [arg; Lconst (Const_immstring s)], loc;))
+ [arg; Lconst (Const_immstring s)], loc))
(fun r ->
tree_way_test loc r
(do_make_string_test_tree loc arg lt delta d)
let sw =
List.map (fun (cst,act) -> cst,store.Switch.act_store act) sw in
-(* Retrieve all actions, including potentiel default *)
+(* Retrieve all actions, including potential default *)
let acts = store.Switch.act_get_shared () in
(* Array of actual actions *)
let make_isout h arg = Lprim (Pisout, [h ; arg],Location.none)
let make_isin h arg = Lprim (Pnot,[make_isout h arg],Location.none)
let make_if cond ifso ifnot = Lifthenelse (cond, ifso, ifnot)
- let make_switch arg cases acts =
+ let make_switch loc arg cases acts =
let l = ref [] in
for i = Array.length cases-1 downto 0 do
l := (i,acts.(cases.(i))) :: !l
Lswitch(arg,
{sw_numconsts = Array.length cases ; sw_consts = !l ;
sw_numblocks = 0 ; sw_blocks = [] ;
- sw_failaction = None})
+ sw_failaction = None}, loc)
let make_catch = make_catch_delayed
let make_exit = make_exit
| (i,act)::rem ->
let act_index =
(* In case there is some hole and that a switch is emitted,
- action 0 will be used as the action of unreacheable
+ action 0 will be used as the action of unreachable
cases (cf. switch.ml, make_switch).
Hence, this action will be shared *)
if some_hole rem then
| None -> as_interval_nofail l
| Some act -> as_interval_canfail act low high l)
-let call_switcher fail arg low high int_lambda_list =
+let call_switcher loc fail arg low high int_lambda_list =
let edges, (cases, actions) =
as_interval fail low high int_lambda_list in
- Switcher.zyva edges arg cases actions
+ Switcher.zyva loc edges arg cases actions
let rec list_as_pat = function
let int_lambda_list =
List.map (function Const_int n, l -> n,l | _ -> assert false)
const_lambda_list in
- call_switcher fail arg min_int max_int int_lambda_list
+ call_switcher loc fail arg min_int max_int int_lambda_list
| Const_char _ ->
let int_lambda_list =
List.map (function Const_char c, l -> (Char.code c, l)
| _ -> assert false)
const_lambda_list in
- call_switcher fail arg 0 255 int_lambda_list
+ call_switcher loc fail arg 0 255 int_lambda_list
| Const_string _ ->
(* Note as the bytecode compiler may resort to dichotomic search,
the clauses of stringswitch are sorted with duplicates removed.
let tests =
List.fold_right
(fun (path, act) rem ->
- Lifthenelse(Lprim(Pintcomp Ceq,
- [Lvar tag;
- transl_path ex_pat.pat_env path], loc),
+ let ext = transl_extension_path ex_pat.pat_env path in
+ Lifthenelse(Lprim(Pintcomp Ceq, [Lvar tag; ext], loc),
act, rem))
nonconsts
default
in
List.fold_right
(fun (path, act) rem ->
- Lifthenelse(Lprim(Pintcomp Ceq,
- [arg; transl_path ex_pat.pat_env path], loc),
+ let ext = transl_extension_path ex_pat.pat_env path in
+ Lifthenelse(Lprim(Pintcomp Ceq, [arg; ext], loc),
act, rem))
consts
nonconst_lambda
case *)
Lifthenelse(arg, act2, act1)
| (n,0,_,[]) -> (* The type defines constant constructors only *)
- call_switcher fail_opt arg 0 (n-1) consts
+ call_switcher loc fail_opt arg 0 (n-1) consts
| (n, _, _, _) ->
let act0 =
(* = Some act when all non-const constructors match to act *)
| Some act ->
Lifthenelse
(Lprim (Pisint, [arg], loc),
- call_switcher
+ call_switcher loc
fail_opt arg
0 (n-1) consts,
act)
sw_failaction = fail_opt} in
let hs,sw = share_actions_sw sw in
let sw = reintroduce_fail sw in
- hs (Lswitch (arg,sw)) in
+ hs (Lswitch (arg,sw,loc)) in
lambda1, jumps_union local_jumps total1
end
as_interval fail min_int max_int int_lambda_list in
Switcher.test_sequence arg cases actions
-let call_switcher_variant_constant fail arg int_lambda_list =
- call_switcher fail arg min_int max_int int_lambda_list
+let call_switcher_variant_constant loc fail arg int_lambda_list =
+ call_switcher loc fail arg min_int max_int int_lambda_list
let call_switcher_variant_constr loc fail arg int_lambda_list =
let v = Ident.create "variant" in
Llet(Alias, Pgenval, v, Lprim(Pfield 0, [arg], loc),
- call_switcher
+ call_switcher loc
fail (Lvar v) min_int max_int int_lambda_list)
let combine_variant loc row arg partial ctx def
end
| (_, _) ->
let lam_const =
- call_switcher_variant_constant
+ call_switcher_variant_constant loc
fail arg consts
and lam_nonconst =
call_switcher_variant_constr loc
let lambda1 =
let newvar = Ident.create "len" in
let switch =
- call_switcher
+ call_switcher loc
fail (Lvar newvar)
0 max_int len_lambda_list in
bind
Lifthenelse (cond, ifso, lower_bind v arg ifnot)
| _,_,_ -> bind Alias v arg lam
end
-| Lswitch (ls,({sw_consts=[i,act] ; sw_blocks = []} as sw))
+| Lswitch (ls,({sw_consts=[i,act] ; sw_blocks = []} as sw), loc)
when not (approx_present v ls) ->
- Lswitch (ls, {sw with sw_consts = [i,lower_bind v arg act]})
-| Lswitch (ls,({sw_consts=[] ; sw_blocks = [i,act]} as sw))
+ Lswitch (ls, {sw with sw_consts = [i,lower_bind v arg act]}, loc)
+| Lswitch (ls,({sw_consts=[] ; sw_blocks = [i,act]} as sw), loc)
when not (approx_present v ls) ->
- Lswitch (ls, {sw with sw_blocks = [i,lower_bind v arg act]})
+ Lswitch (ls, {sw with sw_blocks = [i,lower_bind v arg act]}, loc)
| Llet (Alias, k, vv, lv, l) ->
if approx_present v lv then
bind Alias v arg lam
let arg_to_var arg cls = match arg with
| Lvar v -> v,arg
| _ ->
- let v = name_pattern "match" cls in
+ let v = name_pattern "*match*" cls in
v,Lvar v
or lazy pattern execute arbitrary code that may perform side effects
and change the subject values.
LM:
- Lazy pattern was PR #5992, initial patch by lwp25.
+ Lazy pattern was PR#5992, initial patch by lpw25.
I have generalized the patch, so as to also find mutable fields.
*)
| Tpat_tuple args -> args::k
| Tpat_or (p1,p2,_) -> flatten_pat_line size p1 (flatten_pat_line size p2 k)
| Tpat_alias (p,_,_) -> (* Note: if this 'as' pat is here, then this is a
- useless binding, solves PR #3780 *)
+ useless binding, solves PR#3780 *)
flatten_pat_line size p k
| _ -> fatal_error "Matching.flatten_pat_line"
let next, nexts = split_precompile None pm1 in
let size = List.length paraml
- and idl = List.map (fun _ -> Ident.create "match") paraml in
+ and idl = List.map (fun _ -> Ident.create "*match*") paraml in
let args = List.map (fun id -> Lvar id, Alias) idl in
let flat_next = flatten_precompiled size args next
with Unused ->
assert false (* ; partial_function loc () *)
-(* #PR4828: Believe it or not, the 'paraml' argument below
+(* PR#4828: Believe it or not, the 'paraml' argument below
may not be side effect free. *)
let param_to_var param = match param with
| Lvar v -> v,None
-| _ -> Ident.create "match",Some param
+| _ -> Ident.create "*match*",Some param
let bind_opt (v,eo) k = match eo with
| None -> k
let lams ppf largs =
List.iter (fun l -> fprintf ppf "@ %a" lam l) largs in
fprintf ppf "@[<2>(%a%a)@]" primitive prim lams largs
- | Lswitch(larg, sw) ->
+ | Lswitch(larg, sw, _loc) ->
let switch ppf sw =
let spc = ref false in
List.iter
| Lev_after _ -> "after"
| Lev_function -> "funct-body"
| Lev_pseudo -> "pseudo"
+ | Lev_module_definition ident ->
+ Format.asprintf "module-defn(%a)" Ident.print ident
in
fprintf ppf "@[<2>(%s %s(%i)%s:%i-%i@ %a)@]" kind
ev.lev_loc.Location.loc_start.Lexing.pos_fname
Lassign(id, Lprim(Poffsetint delta, [Lvar id], loc))
| Lprim(p, el, loc) ->
Lprim(p, List.map (eliminate_ref id) el, loc)
- | Lswitch(e, sw) ->
+ | Lswitch(e, sw, loc) ->
Lswitch(eliminate_ref id e,
{sw_numconsts = sw.sw_numconsts;
sw_consts =
sw_blocks =
List.map (fun (n, e) -> (n, eliminate_ref id e)) sw.sw_blocks;
sw_failaction =
- Misc.may_map (eliminate_ref id) sw.sw_failaction; })
+ Misc.may_map (eliminate_ref id) sw.sw_failaction; },
+ loc)
| Lstringswitch(e, sw, default, loc) ->
Lstringswitch
(eliminate_ref id e,
List.iter (fun (_v, l) -> count l) bindings;
count body
| Lprim(_p, ll, _) -> List.iter count ll
- | Lswitch(l, sw) ->
+ | Lswitch(l, sw, _loc) ->
count_default sw ;
count l;
List.iter (fun (_, l) -> count l) sw.sw_consts;
end
| Lstaticraise (i,ls) -> incr_exit i ; List.iter count ls
| Lstaticcatch (l1,(i,[]),Lstaticraise (j,[])) ->
- (* i will be replaced by j in l1, so each occurence of i in l1
+ (* i will be replaced by j in l1, so each occurrence of i in l1
increases j's ref count *)
count l1 ;
let ic = count_exit i in
| _ -> Lprim(p, ll, loc)
end
- | Lswitch(l, sw) ->
+ | Lswitch(l, sw, loc) ->
let new_l = simplif l
and new_consts = List.map (fun (n, e) -> (n, simplif e)) sw.sw_consts
and new_blocks = List.map (fun (n, e) -> (n, simplif e)) sw.sw_blocks
Lswitch
(new_l,
{sw with sw_consts = new_consts ; sw_blocks = new_blocks;
- sw_failaction = new_fail})
+ sw_failaction = new_fail},
+ loc)
| Lstringswitch(l,sw,d,loc) ->
Lstringswitch
(simplif l,List.map (fun (s,l) -> s,simplif l) sw,
List.iter (fun (_v, l) -> count bv l) bindings;
count bv body
| Lprim(_p, ll, _) -> List.iter (count bv) ll
- | Lswitch(l, sw) ->
+ | Lswitch(l, sw, _loc) ->
count_default bv sw ;
count bv l;
List.iter (fun (_, l) -> count bv l) sw.sw_consts;
| Lletrec(bindings, body) ->
Lletrec(List.map (fun (v, l) -> (v, simplif l)) bindings, simplif body)
| Lprim(p, ll, loc) -> Lprim(p, List.map simplif ll, loc)
- | Lswitch(l, sw) ->
+ | Lswitch(l, sw, loc) ->
let new_l = simplif l
and new_consts = List.map (fun (n, e) -> (n, simplif e)) sw.sw_consts
and new_blocks = List.map (fun (n, e) -> (n, simplif e)) sw.sw_blocks
Lswitch
(new_l,
{sw with sw_consts = new_consts ; sw_blocks = new_blocks;
- sw_failaction = new_fail})
+ sw_failaction = new_fail},
+ loc)
| Lstringswitch (l,sw,d,loc) ->
Lstringswitch
(simplif l,List.map (fun (s,l) -> s,simplif l) sw,
emit_tail_infos is_tail arg2
| Lprim (_, l, _) ->
list_emit_tail_infos false l
- | Lswitch (lam, sw) ->
+ | Lswitch (lam, sw, _loc) ->
emit_tail_infos false lam;
list_emit_tail_infos_fun snd is_tail sw.sw_consts;
list_emit_tail_infos_fun snd is_tail sw.sw_blocks;
(* *)
(**************************************************************************)
+(** Lambda simplification and lambda plugin hooks *)
+
(* Elimination of useless Llet(Alias) bindings.
Transformation of let-bound references into variables.
Simplification over staticraise/staticcatch constructs.
module type Stored = sig
type t
type key
+ val compare_key : key -> key -> int
val make_key : t -> key option
end
module Store(A:Stored) = struct
module AMap =
- Map.Make(struct type t = A.key let compare = Pervasives.compare end)
+ Map.Make(struct type t = A.key let compare = A.compare_key end)
type intern =
{ mutable map : (bool * int) AMap.t ;
val make_isout : act -> act -> act
val make_isin : act -> act -> act
val make_if : act -> act -> act -> act
- val make_switch : act -> int array -> act array -> act
+ val make_switch : Location.t -> act -> int array -> act array -> act
val make_catch : act -> int * (act -> act)
val make_exit : int -> act
end
(*
- Intervall test x in [l,h] works by checking x-l in [0,h-l]
+ Interval test x in [l,h] works by checking x-l in [0,h-l]
* This may be false for arithmetic modulo 2^31
* Subtracting l may change the relative ordering of values
and invalid the invariant that matched values are given in
(* Minimal density of switches *)
let theta = ref 0.33333
-(* Minmal number of tests to make a switch *)
+(* Minimal number of tests to make a switch *)
let switch_min = ref 3
(* Particular case 0, 1, 2 *)
Adaptation of the correction to Bernstein
``Correction to `Producing Good Code for the Case Statement' ''
S.K. Kannan and T.A. Proebsting
- Software Practice and Exprience Vol. 24(2) 233 (Feb 1994)
+ Software Practice and Experience Vol. 24(2) 233 (Feb 1994)
*)
let comp_clusters s =
min_clusters.(len-1),k
(* Assume j > i *)
-let make_switch {cases=cases ; actions=actions} i j =
+let make_switch loc {cases=cases ; actions=actions} i j =
let ll,_,_ = cases.(i)
and _,hh,_ = cases.(j) in
let tbl = Array.make (hh-ll+1) 0
t ;
(fun ctx ->
match -ll-ctx.off with
- | 0 -> Arg.make_switch ctx.arg tbl acts
+ | 0 -> Arg.make_switch loc ctx.arg tbl acts
| _ ->
Arg.bind
(Arg.make_offset ctx.arg (-ll-ctx.off))
- (fun arg -> Arg.make_switch arg tbl acts))
+ (fun arg -> Arg.make_switch loc arg tbl acts))
-let make_clusters ({cases=cases ; actions=actions} as s) n_clusters k =
+let make_clusters loc ({cases=cases ; actions=actions} as s) n_clusters k =
let len = Array.length cases in
let r = Array.make n_clusters (0,0,0)
and t = Hashtbl.create 17
else (* assert i < j *)
let l,_,_ = cases.(i)
and _,h,_ = cases.(j) in
- r.(ir) <- (l,h,add_index (make_switch s i j))
+ r.(ir) <- (l,h,add_index (make_switch loc s i j))
end ;
if i > 0 then zyva (i-1) (ir-1) in
;;
-let do_zyva (low,high) arg cases actions =
+let do_zyva loc (low,high) arg cases actions =
let old_ok = !ok_inter in
ok_inter := (abs low <= inter_limit && abs high <= inter_limit) ;
if !ok_inter <> old_ok then Hashtbl.clear t ;
let s = {cases=cases ; actions=actions} in
(*
- Printf.eprintf "ZYVA: %b [low=%i,high=%i]\n" !ok_inter low high ;
+ Printf.eprintf "ZYVA: %B [low=%i,high=%i]\n" !ok_inter low high ;
pcases stderr cases ;
prerr_endline "" ;
*)
let n_clusters,k = comp_clusters s in
- let clusters = make_clusters s n_clusters k in
+ let clusters = make_clusters loc s n_clusters k in
c_test {arg=arg ; off=0} clusters
let abstract_shared actions =
actions in
!handlers,actions
-let zyva lh arg cases actions =
+let zyva loc lh arg cases actions =
assert (Array.length cases > 0) ;
let actions = actions.act_get_shared () in
let hs,actions = abstract_shared actions in
- hs (do_zyva lh arg cases actions)
+ hs (do_zyva loc lh arg cases actions)
and test_sequence arg cases actions =
assert (Array.length cases > 0) ;
{cases=cases ;
actions=Array.map (fun act -> (fun _ -> act)) actions} in
(*
- Printf.eprintf "SEQUENCE: %b\n" !ok_inter ;
+ Printf.eprintf "SEQUENCE: %B\n" !ok_inter ;
pcases stderr cases ;
prerr_endline "" ;
*)
module type Stored = sig
type t
type key
+ val compare_key : key -> key -> int
val make_key : t -> key option
end
make_switch arg cases acts
NB: cases is in the value form *)
val make_switch :
- act -> int array -> act array -> act
+ Location.t -> act -> int array -> act array -> act
(* Build last minute sharing of action stuff *)
val make_catch : act -> int * (act -> act)
val make_exit : int -> act
- actions is an array of actions.
All these arguments specify a switch construct and zyva
- returns an action that performs the switch,
+ returns an action that performs the switch.
*)
module Make :
functor (Arg : S) ->
sig
(* Standard entry point, sharing is tracked *)
val zyva :
+ Location.t ->
(int * int) ->
Arg.act ->
(int * int * int) array ->
fields;
block
| Const_float_array fields ->
- Obj.repr(Array.of_list(List.map (fun f -> float_of_string f) fields))
+ let res = Array.Floatarray.create (List.length fields) in
+ List.iteri (fun i f -> Array.Floatarray.set res i (float_of_string f))
+ fields;
+ Obj.repr res
(* Build the initial table of globals *)
let specialised = parse_specialise_attribute attr in
specialised, { e with exp_attributes }
-(* It also remove the attribute from the expression, like
+(* It also removes the attribute from the expression, like
get_inlined_attribute *)
let get_tailcall_attribute e =
let is_tailcall_attribute = function
(* XXX Rajouter des evenements... | Add more events... *)
-type error = Illegal_class_expr | Tags of label * label
+type error = Tags of label * label
exception Error of Location.t * error
build_object_init cl_table obj (vals @ params) inh_init obj_init cl
in
(inh_init, Translcore.transl_let rec_flag defs obj_init)
- | Tcl_constraint (cl, _, _vals, _pub_meths, _concr_meths) ->
+ | Tcl_open (_, _, _, _, cl)
+ | Tcl_constraint (cl, _, _, _, _) ->
build_object_init cl_table obj params inh_init obj_init cl
let rec build_object_init_0 cl_table params cl copy_env subst_env top ids =
Tcl_ident ( path, _, _) ->
begin match inh_init with
(obj_init, _path')::inh_init ->
- let lpath = transl_path ~loc:cl.cl_loc cl.cl_env path in
+ let lpath = transl_class_path ~loc:cl.cl_loc cl.cl_env path in
(inh_init,
Llet (Strict, Pgenval, obj_init,
mkappl(Lprim(Pfield 1, [lpath], Location.none), Lvar cla ::
Lsequence(mkappl (oo_prim "narrow", narrow_args),
cl_init))
end
+ | Tcl_open (_, _, _, _, cl) ->
+ build_class_init cla cstr super inh_init cl_init msubst top cl
-let rec build_class_lets cl ids =
+let rec build_class_lets cl =
match cl.cl_desc with
Tcl_let (rec_flag, defs, _vals, cl') ->
- let env, wrap = build_class_lets cl' [] in
+ let env, wrap = build_class_lets cl' in
(env, fun x ->
- let lam = Translcore.transl_let rec_flag defs (wrap x) in
- (* Check recursion in toplevel let-definitions *)
- if ids = [] || Translcore.check_recursive_lambda ids lam then lam
- else raise(Error(cl.cl_loc, Illegal_class_expr)))
+ Translcore.transl_let rec_flag defs (wrap x))
| _ ->
(cl.cl_env, fun x -> x)
| Tcl_fun (_, _, _, cl, _)
| Tcl_let (_, _, _, cl)
| Tcl_apply (cl, _)
+ | Tcl_open (_, _, _, _, cl)
| Tcl_constraint (cl, _, _, _, _) -> get_class_meths cl
(*
in
check_constraint cl.cl_type;
(path, obj_init)
+ | Tcl_open (_, _, _, _, cl) ->
+ transl_class_rebind obj_init cl vf
let rec transl_class_rebind_0 self obj_init cl vf =
match cl.cl_desc with
let path, obj_init = transl_class_rebind obj_init cl vf in
(path, lfunction [self] obj_init)
-let transl_class_rebind ids cl vf =
+let transl_class_rebind cl vf =
try
let obj_init = Ident.create "obj_init"
and self = Ident.create "self" in
ap_specialised=Default_specialise}
in
let path, obj_init' = transl_class_rebind_0 self obj_init0 cl vf in
- if not (Translcore.check_recursive_lambda ids obj_init') then
- raise(Error(cl.cl_loc, Illegal_class_expr));
let id = (obj_init' = lfunction [self] obj_init0) in
if id then transl_normal_path path else
env_init: parameterisation by the local environment
(env -> params -> obj_init)
(one for each combination of inherited class_init )
- env: environnement local
+ env: local environment
If ids=0 (immediate object), then only env_init is conserved.
*)
let transl_class ids cl_id pub_meths cl vflag =
(* First check if it is not only a rebind *)
- let rebind = transl_class_rebind ids cl vflag in
+ let rebind = transl_class_rebind cl vflag in
if rebind <> lambda_unit then rebind else
(* Prepare for heavy environment handling *)
let tables = Ident.create (Ident.name cl_id ^ "_tables") in
let (top_env, req) = oo_add_class tables in
let top = not req in
- let cl_env, llets = build_class_lets cl ids in
+ let cl_env, llets = build_class_lets cl in
let new_ids = if top then [] else Env.diff top_env cl_env in
let env2 = Ident.create "env" in
let meth_ids = get_class_meths cl in
if top && concrete then lclass lbody else
if top then llets (lbody_virt lambda_unit) else
- (* Now for the hard stuff: prepare for table cacheing *)
+ (* Now for the hard stuff: prepare for table caching *)
let envs = Ident.create "envs"
and cached = Ident.create "cached" in
let lenvs =
loc = Location.none;
params = [cla]; body = def_ids cla cl_init})
in
+ let lupdate_cache =
+ if ids = [] then ldirect () else
+ if not concrete then lclass_virt () else
+ lclass (
+ mkappl (oo_prim "make_class_store",
+ [transl_meth_list pub_meths;
+ Lvar class_init; Lvar cached])) in
+ let lcheck_cache =
+ if !Clflags.native_code && !Clflags.afl_instrument then
+ (* When afl-fuzz instrumentation is enabled, ignore the cache
+ so that the program's behaviour does not change between runs *)
+ lupdate_cache
+ else
+ Lifthenelse(lfield cached 0, lambda_unit, lupdate_cache) in
llets (
lcache (
- Lsequence(
- Lifthenelse(lfield cached 0, lambda_unit,
- if ids = [] then ldirect () else
- if not concrete then lclass_virt () else
- lclass (
- mkappl (oo_prim "make_class_store",
- [transl_meth_list pub_meths;
- Lvar class_init; Lvar cached]))),
+ Lsequence(lcheck_cache,
make_envs (
if ids = [] then mkappl (lfield cached 0, [lenvs]) else
Lprim(Pmakeblock(0, Immutable, None),
open Format
let report_error ppf = function
- | Illegal_class_expr ->
- fprintf ppf "This kind of recursive class expression is not allowed"
| Tags (lab1, lab2) ->
fprintf ppf "Method labels `%s' and `%s' are incompatible.@ %s"
lab1 lab2 "Change one of them."
Ident.t list -> Ident.t ->
string list -> class_expr -> Asttypes.virtual_flag -> lambda;;
-type error = Illegal_class_expr | Tags of string * string
+type error = Tags of string * string
exception Error of Location.t * error
open Lambda
type error =
- Illegal_letrec_pat
- | Illegal_letrec_expr
- | Free_super_var
+ Free_super_var
| Unknown_builtin_primitive of string
| Unreachable_reached
Lprim (prim_fresh_oo_id, [Lconst (Const_base (Const_int 0))], loc)],
loc)
| Text_rebind(path, _lid) ->
- transl_path ~loc env path
+ transl_extension_path ~loc env path
(* Translation of primitives *)
false)
]
+let gen_array_kind =
+ if Config.flat_float_array then Pgenarray else Paddrarray
+
let primitives_table = create_hashtable 57 [
"%identity", Pidentity;
"%bytes_to_string", Pbytes_to_string;
"%bytes_safe_set", Pbytessets;
"%bytes_unsafe_get", Pbytesrefu;
"%bytes_unsafe_set", Pbytessetu;
- "%array_length", Parraylength Pgenarray;
- "%array_safe_get", Parrayrefs Pgenarray;
- "%array_safe_set", Parraysets Pgenarray;
- "%array_unsafe_get", Parrayrefu Pgenarray;
- "%array_unsafe_set", Parraysetu Pgenarray;
- "%obj_size", Parraylength Pgenarray;
- "%obj_field", Parrayrefu Pgenarray;
- "%obj_set_field", Parraysetu Pgenarray;
+ "%array_length", Parraylength gen_array_kind;
+ "%array_safe_get", Parrayrefs gen_array_kind;
+ "%array_safe_set", Parraysets gen_array_kind;
+ "%array_unsafe_get", Parrayrefu gen_array_kind;
+ "%array_unsafe_set", Parraysetu gen_array_kind;
+ "%obj_size", Parraylength gen_array_kind;
+ "%obj_field", Parrayrefu gen_array_kind;
+ "%obj_set_field", Parraysetu gen_array_kind;
+ "%floatarray_length", Parraylength Pfloatarray;
+ "%floatarray_safe_get", Parrayrefs Pfloatarray;
+ "%floatarray_safe_set", Parraysets Pfloatarray;
+ "%floatarray_unsafe_get", Parrayrefu Pfloatarray;
+ "%floatarray_unsafe_set", Parraysetu Pfloatarray;
"%obj_is_int", Pisint;
"%lazy_force", Plazyforce;
"%nativeint_of_int", Pbintofint Pnativeint;
| () when is_base_type env ty Predef.path_int64 -> int64comp
| () -> gencomp
+(* The following function computes the greatest lower bound in the
+ semilattice of array kinds:
+ gen
+ / \
+ addr float
+ |
+ int
+ Note that the GLB is not guaranteed to exist, in which case we return
+ our first argument instead of raising a fatal error because, although
+ it cannot happen in a well-typed program, (ab)use of Obj.magic can
+ probably trigger it.
+*)
+let glb_array_type t1 t2 =
+ match t1, t2 with
+ | Pfloatarray, (Paddrarray | Pintarray)
+ | (Paddrarray | Pintarray), Pfloatarray -> t1
+
+ | Pgenarray, x | x, Pgenarray -> x
+ | Paddrarray, x | x, Paddrarray -> x
+ | Pintarray, Pintarray -> Pintarray
+ | Pfloatarray, Pfloatarray -> Pfloatarray
+
(* Specialize a primitive from available type information,
raise Not_found if primitive is unknown *)
match (p, params) with
(Psetfield(n, _, init), [_p1; p2]) ->
Psetfield(n, maybe_pointer_type env p2, init)
- | (Parraylength Pgenarray, [p]) -> Parraylength(array_type_kind env p)
- | (Parrayrefu Pgenarray, p1 :: _) -> Parrayrefu(array_type_kind env p1)
- | (Parraysetu Pgenarray, p1 :: _) -> Parraysetu(array_type_kind env p1)
- | (Parrayrefs Pgenarray, p1 :: _) -> Parrayrefs(array_type_kind env p1)
- | (Parraysets Pgenarray, p1 :: _) -> Parraysets(array_type_kind env p1)
+ | (Parraylength t, [p]) ->
+ Parraylength(glb_array_type t (array_type_kind env p))
+ | (Parrayrefu t, p1 :: _) ->
+ Parrayrefu(glb_array_type t (array_type_kind env p1))
+ | (Parraysetu t, p1 :: _) ->
+ Parraysetu(glb_array_type t (array_type_kind env p1))
+ | (Parrayrefs t, p1 :: _) ->
+ Parrayrefs(glb_array_type t (array_type_kind env p1))
+ | (Parraysets t, p1 :: _) ->
+ Parraysets(glb_array_type t (array_type_kind env p1))
| (Pbigarrayref(unsafe, n, Pbigarray_unknown, Pbigarray_unknown_layout),
p1 :: _) ->
let (k, l) = bigarray_type_kind_and_layout env p1 in
add_used_primitive loc env path;
Pccall prim
-
-(* To check the well-formedness of r.h.s. of "let rec" definitions *)
-
-let check_recursive_lambda idlist lam =
- let rec check_top idlist = function
- | Lvar v -> not (List.mem v idlist)
- | Llet _ as lam when check_recursive_recordwith idlist lam ->
- true
- | Llet(_str, _k, id, arg, body) ->
- check idlist arg && check_top (add_let id arg idlist) body
- | Lletrec(bindings, body) ->
- let idlist' = add_letrec bindings idlist in
- List.for_all (fun (_id, arg) -> check idlist' arg) bindings &&
- check_top idlist' body
- | Lprim (Pmakearray (Pgenarray, _), _, _) -> false
- | Lprim (Pmakearray (Pfloatarray, _), args, _) ->
- List.for_all (check idlist) args
- | Lsequence (lam1, lam2) -> check idlist lam1 && check_top idlist lam2
- | Levent (lam, _) -> check_top idlist lam
- | lam -> check idlist lam
-
- and check idlist = function
- | Lvar _ -> true
- | Lfunction _ -> true
- | Llet _ as lam when check_recursive_recordwith idlist lam ->
- true
- | Llet(_str, _k, id, arg, body) ->
- check idlist arg && check (add_let id arg idlist) body
- | Lletrec(bindings, body) ->
- let idlist' = add_letrec bindings idlist in
- List.for_all (fun (_id, arg) -> check idlist' arg) bindings &&
- check idlist' body
- | Lprim(Pmakeblock _, args, _) ->
- List.for_all (check idlist) args
- | Lprim (Pmakearray (Pfloatarray, _), _, _) -> false
- | Lprim (Pmakearray _, args, _) ->
- List.for_all (check idlist) args
- | Lsequence (lam1, lam2) -> check idlist lam1 && check idlist lam2
- | Levent (lam, _) -> check idlist lam
- | lam ->
- let fv = free_variables lam in
- not (List.exists (fun id -> IdentSet.mem id fv) idlist)
-
- and add_let id arg idlist =
- let fv = free_variables arg in
- if List.exists (fun id -> IdentSet.mem id fv) idlist
- then id :: idlist
- else idlist
-
- and add_letrec bindings idlist =
- List.fold_right (fun (id, arg) idl -> add_let id arg idl)
- bindings idlist
-
- (* reverse-engineering the code generated by transl_record case 2 *)
- (* If you change this, you probably need to change Bytegen.size_of_lambda. *)
- and check_recursive_recordwith idlist = function
- | Llet (Strict, _k, id1, Lprim (Pduprecord _, [e1], _), body) ->
- check_top idlist e1
- && check_recordwith_updates idlist id1 body
- | _ -> false
-
- and check_recordwith_updates idlist id1 = function
- | Lsequence (Lprim ((Psetfield _ | Psetfloatfield _), [Lvar id2; e1], _),
- cont)
- -> id2 = id1 && check idlist e1
- && check_recordwith_updates idlist id1 cont
- | Lvar id2 -> id2 = id1
- | _ -> false
-
- in check_top idlist lam
-
(* To propagate structured constants *)
exception Not_constant
| Texp_ident(_, _, {val_kind = Val_anc _}) ->
raise(Error(e.exp_loc, Free_super_var))
| Texp_ident(path, _, {val_kind = Val_reg | Val_self _}) ->
- transl_path ~loc:e.exp_loc e.exp_env path
+ transl_value_path ~loc:e.exp_loc e.exp_env path
| Texp_ident _ -> fatal_error "Translcore.transl_exp: bad Texp_ident"
| Texp_constant cst ->
Lconst(Const_base cst)
end
| Cstr_extension(path, is_const) ->
if is_const then
- transl_path e.exp_env path
+ transl_extension_path e.exp_env path
else
Lprim(Pmakeblock(0, Immutable, Some (Pgenval :: shape)),
- transl_path e.exp_env path :: ll, e.exp_loc)
+ transl_extension_path e.exp_env path :: ll, e.exp_loc)
end
| Texp_extension_constructor (_, path) ->
- transl_path e.exp_env path
+ transl_extension_path e.exp_env path
| Texp_variant(l, arg) ->
let tag = Btype.hash_variant l in
begin match arg with
| Texp_new (cl, {Location.loc=loc}, _) ->
Lapply{ap_should_be_tailcall=false;
ap_loc=loc;
- ap_func=Lprim(Pfield 0, [transl_path ~loc e.exp_env cl], loc);
+ ap_func=Lprim(Pfield 0, [transl_class_path ~loc e.exp_env cl], loc);
ap_args=[lambda_unit];
ap_inlined=Default_inline;
ap_specialised=Default_specialise}
(Lvar cpy) path expr, rem))
modifs
(Lvar cpy))
- | Texp_letmodule(id, _, modl, body) ->
- Llet(Strict, Pgenval, id,
- !transl_module Tcoerce_none None modl,
- transl_exp body)
+ | Texp_letmodule(id, loc, modl, body) ->
+ let defining_expr =
+ Levent (!transl_module Tcoerce_none None modl, {
+ lev_loc = loc.loc;
+ lev_kind = Lev_module_definition id;
+ lev_repr = None;
+ lev_env = Env.summary Env.empty;
+ })
+ in
+ Llet(Strict, Pgenval, id, defining_expr, transl_exp body)
| Texp_letexception(cd, body) ->
Llet(Strict, Pgenval,
cd.ext_id, transl_extension_constructor e.exp_env None cd,
(* when e needs no computation (constants, identifiers, ...), we
optimize the translation just as Lazy.lazy_from_val would
do *)
- begin match e.exp_desc with
+ begin match Typeopt.classify_lazy_argument e with
+ | `Constant_or_function ->
(* a constant expr of type <> float gets compiled as itself *)
- | Texp_constant
- ( Const_int _ | Const_char _ | Const_string _
- | Const_int32 _ | Const_int64 _ | Const_nativeint _ )
- | Texp_function _
- | Texp_construct (_, {cstr_arity = 0}, _)
- -> transl_exp e
- | Texp_constant(Const_float _) ->
+ transl_exp e
+ | `Float ->
(* We don't need to wrap with Popaque: this forward
block will never be shortcutted since it points to a float. *)
Lprim(Pmakeblock(Obj.forward_tag, Immutable, None),
[transl_exp e], e.exp_loc)
- | Texp_ident _ ->
- (* CR-someday mshinwell: Consider adding a new primitive
- that expresses the construction of forward_tag blocks.
- We need to use [Popaque] here to prevent unsound
- optimisation in Flambda, but the concept of a mutable
- block doesn't really match what is going on here. This
- value may subsequently turn into an immediate... *)
- if Typeopt.lazy_val_requires_forward e.exp_env e.exp_type
- then
- Lprim (Popaque,
- [Lprim(Pmakeblock(Obj.forward_tag, Immutable, None),
- [transl_exp e], e.exp_loc)],
- e.exp_loc)
- else transl_exp e
- (* other cases compile to a lazy block holding a function *)
- | _ ->
+ | `Identifier `Forward_value ->
+ (* CR-someday mshinwell: Consider adding a new primitive
+ that expresses the construction of forward_tag blocks.
+ We need to use [Popaque] here to prevent unsound
+ optimisation in Flambda, but the concept of a mutable
+ block doesn't really match what is going on here. This
+ value may subsequently turn into an immediate... *)
+ Lprim (Popaque,
+ [Lprim(Pmakeblock(Obj.forward_tag, Immutable, None),
+ [transl_exp e], e.exp_loc)],
+ e.exp_loc)
+ | `Identifier `Other ->
+ transl_exp e
+ | `Other ->
+ (* other cases compile to a lazy block holding a function *)
let fn = Lfunction {kind = Curried; params = [Ident.create "param"];
attr = default_function_attribute;
loc = e.exp_loc;
[{c_lhs=pat; c_guard=None;
c_rhs={exp_desc = Texp_function { arg_label = _; param = param'; cases;
partial = partial'; }} as exp}]
- when Parmatch.fluid pat ->
+ when Parmatch.inactive ~partial pat ->
let ((_, params), body) =
transl_function exp.exp_loc false repr partial' param' cases in
((Curried, param :: params),
(fun {vb_pat=pat} -> match pat.pat_desc with
Tpat_var (id,_) -> id
| Tpat_alias ({pat_desc=Tpat_any}, id,_) -> id
- | _ -> raise(Error(pat.pat_loc, Illegal_letrec_pat)))
+ | _ -> assert false)
pat_expr_list in
let transl_case {vb_expr=expr; vb_attributes; vb_loc} id =
let lam = transl_exp expr in
Translattribute.add_specialise_attribute lam vb_loc
vb_attributes
in
- if not (check_recursive_lambda idlist lam) then
- raise(Error(expr.exp_loc, Illegal_letrec_expr));
(id, lam) in
Lletrec(List.map2 transl_case pat_expr_list idlist, body)
| Tconstr(p, _, _) -> p
| _ -> assert false
in
- let slot = transl_path env path in
+ let slot = transl_extension_path env path in
Lprim(Pmakeblock(0, mut, Some (Pgenval :: shape)), slot :: ll, loc)
in
begin match opt_init_expr with
end else begin
(* Take a shallow copy of the init record, then mutate the fields
of the copy *)
- (* If you change anything here, you will likely have to change
- [check_recursive_recordwith] in this file. *)
let copy_id = Ident.create "newrecord" in
let update_field cont (lbl, definition) =
match definition with
open Format
let report_error ppf = function
- | Illegal_letrec_pat ->
- fprintf ppf
- "Only variables are allowed as left-hand side of `let rec'"
- | Illegal_letrec_expr ->
- fprintf ppf
- "This kind of expression is not allowed as right-hand side of `let rec'"
| Free_super_var ->
fprintf ppf
"Ancestor names can only be used to select inherited methods"
val transl_extension_constructor: Env.t -> Path.t option ->
extension_constructor -> lambda
-val check_recursive_lambda: Ident.t list -> lambda -> bool
-
val used_primitives: (Path.t, Location.t) Hashtbl.t
type error =
- Illegal_letrec_pat
- | Illegal_letrec_expr
- | Free_super_var
+ Free_super_var
| Unknown_builtin_primitive of string
| Unreachable_reached
type error =
Circular_dependency of Ident.t
-
+| Conflicting_inline_attributes
exception Error of Location.t * error
wrap_id_pos_list loc id_pos_list get_field lam)
| Tcoerce_functor(cc_arg, cc_res) ->
let param = Ident.create "funarg" in
- name_lambda strict arg (fun id ->
- Lfunction{kind = Curried; params = [param];
- attr = { default_function_attribute with
- is_a_functor = true };
- loc = loc;
- body = apply_coercion
- loc Strict cc_res
- (Lapply{ap_should_be_tailcall=false;
- ap_loc=loc;
- ap_func=Lvar id;
- ap_args=[apply_coercion loc Alias cc_arg
- (Lvar param)];
- ap_inlined=Default_inline;
- ap_specialised=Default_specialise})})
+ let carg = apply_coercion loc Alias cc_arg (Lvar param) in
+ apply_coercion_result loc strict arg [param] [carg] cc_res
| Tcoerce_primitive { pc_loc; pc_desc; pc_env; pc_type; } ->
transl_primitive pc_loc pc_desc pc_env pc_type None
| Tcoerce_alias (path, cc) ->
and apply_coercion_field loc get_field (pos, cc) =
apply_coercion loc Alias cc (get_field pos)
+and apply_coercion_result loc strict funct params args cc_res =
+ match cc_res with
+ | Tcoerce_functor(cc_arg, cc_res) ->
+ let param = Ident.create "funarg" in
+ let arg = apply_coercion loc Alias cc_arg (Lvar param) in
+ apply_coercion_result loc strict funct
+ (param :: params) (arg :: args) cc_res
+ | _ ->
+ name_lambda strict funct (fun id ->
+ Lfunction{kind = Curried; params = List.rev params;
+ attr = { default_function_attribute with
+ is_a_functor = true;
+ stub = true; };
+ loc = loc;
+ body = apply_coercion
+ loc Strict cc_res
+ (Lapply{ap_should_be_tailcall=false;
+ ap_loc=loc;
+ ap_func=Lvar id;
+ ap_args=List.rev args;
+ ap_inlined=Default_inline;
+ ap_specialised=Default_specialise})})
+
and wrap_id_pos_list loc id_pos_list get_field lam =
let fv = free_variables lam in
(*Format.eprintf "%a@." Printlambda.lambda lam;
c3
*)
-(* Record the primitive declarations occuring in the module compiled *)
+(* Record the primitive declarations occurring in the module compiled *)
let primitive_declarations = ref ([] : Primitive.description list)
let record_primitive = function
eval_rec_bindings
(reorder_rec_bindings
(List.map
- (fun {mb_id=id; mb_expr=modl; _} ->
- (id, modl.mod_loc, init_shape modl, compile_rhs id modl))
+ (fun {mb_id=id; mb_expr=modl; mb_loc=loc; _} ->
+ (id, modl.mod_loc, init_shape modl, compile_rhs id modl loc))
bindings))
cont
(id, transl_class ids id meths cl vf))
cl_list)
+(* Compile one or more functors, merging curried functors to produce
+ multi-argument functors. Any [@inline] attribute on a functor that is
+ merged must be consistent with any other [@inline] attribute(s) on the
+ functor(s) being merged with. Such an attribute will be placed on the
+ resulting merged functor. *)
+
+let merge_inline_attributes attr1 attr2 loc =
+ match Lambda.merge_inline_attributes attr1 attr2 with
+ | Some attr -> attr
+ | None -> raise (Error (loc, Conflicting_inline_attributes))
+
+let merge_functors mexp coercion root_path =
+ let rec merge mexp coercion path acc inline_attribute =
+ let finished = acc, mexp, path, coercion, inline_attribute in
+ match mexp.mod_desc with
+ | Tmod_functor (param, _, _, body) ->
+ let inline_attribute' =
+ Translattribute.get_inline_attribute mexp.mod_attributes
+ in
+ let arg_coercion, res_coercion =
+ match coercion with
+ | Tcoerce_none -> Tcoerce_none, Tcoerce_none
+ | Tcoerce_functor (arg_coercion, res_coercion) ->
+ arg_coercion, res_coercion
+ | _ -> fatal_error "Translmod.merge_functors: bad coercion"
+ in
+ let loc = mexp.mod_loc in
+ let path = functor_path path param in
+ let inline_attribute =
+ merge_inline_attributes inline_attribute inline_attribute' loc
+ in
+ merge body res_coercion path ((param, loc, arg_coercion) :: acc)
+ inline_attribute
+ | _ -> finished
+ in
+ merge mexp coercion root_path [] Default_inline
+
+let rec compile_functor mexp coercion root_path loc =
+ let functor_params_rev, body, body_path, res_coercion, inline_attribute =
+ merge_functors mexp coercion root_path
+ in
+ assert (List.length functor_params_rev >= 1); (* cf. [transl_module] *)
+ let params, body =
+ List.fold_left (fun (params, body) (param, loc, arg_coercion) ->
+ let param' = Ident.rename param in
+ let arg = apply_coercion loc Alias arg_coercion (Lvar param') in
+ let params = param' :: params in
+ let body = Llet (Alias, Pgenval, param, arg, body) in
+ params, body)
+ ([], transl_module res_coercion body_path body)
+ functor_params_rev
+ in
+ Lfunction {
+ kind = Curried;
+ params;
+ attr = {
+ inline = inline_attribute;
+ specialise = Default_specialise;
+ is_a_functor = true;
+ stub = false;
+ };
+ loc;
+ body;
+ }
+
(* Compile a module expression *)
-let rec transl_module cc rootpath mexp =
+and transl_module cc rootpath mexp =
List.iter (Translattribute.check_attribute_on_module mexp)
mexp.mod_attributes;
let loc = mexp.mod_loc in
match mexp.mod_type with
- Mty_alias _ -> apply_coercion loc Alias cc lambda_unit
+ Mty_alias (Mta_absent, _) -> apply_coercion loc Alias cc lambda_unit
| _ ->
match mexp.mod_desc with
Tmod_ident (path,_) ->
apply_coercion loc Strict cc
- (transl_path ~loc mexp.mod_env path)
+ (transl_module_path ~loc mexp.mod_env path)
| Tmod_structure str ->
fst (transl_struct loc [] cc rootpath str)
- | Tmod_functor(param, _, _, body) ->
- let bodypath = functor_path rootpath param in
- let inline_attribute =
- Translattribute.get_inline_attribute mexp.mod_attributes
- in
- oo_wrap mexp.mod_env true
- (function
- | Tcoerce_none ->
- Lfunction{kind = Curried; params = [param];
- attr = { inline = inline_attribute;
- specialise = Default_specialise;
- is_a_functor = true;
- stub = false; };
- loc = loc;
- body = transl_module Tcoerce_none bodypath body}
- | Tcoerce_functor(ccarg, ccres) ->
- let param' = Ident.create "funarg" in
- Lfunction{kind = Curried; params = [param'];
- attr = { inline = inline_attribute;
- specialise = Default_specialise;
- is_a_functor = true;
- stub = false; };
- loc = loc;
- body = Llet(Alias, Pgenval, param,
- apply_coercion loc Alias ccarg
- (Lvar param'),
- transl_module ccres bodypath body)}
- | _ ->
- fatal_error "Translmod.transl_module")
- cc
+ | Tmod_functor _ ->
+ oo_wrap mexp.mod_env true (fun () ->
+ compile_functor mexp cc rootpath loc) ()
| Tmod_apply(funct, arg, ccarg) ->
let inlined_attribute, funct =
Translattribute.get_and_remove_inlined_attribute_on_module funct
Translattribute.add_inline_attribute module_body mb.mb_loc
mb.mb_attributes
in
+ let module_body =
+ Levent (module_body, {
+ lev_loc = mb.mb_loc;
+ lev_kind = Lev_module_definition id;
+ lev_repr = None;
+ lev_env = Env.summary Env.empty;
+ })
+ in
Llet(pure_module mb.mb_expr, Pgenval, id,
module_body,
body), size
in
let lam =
compile_recmodule
- (fun id modl ->
- transl_module Tcoerce_none (field_path rootpath id) modl)
+ (fun id modl loc ->
+ let module_body =
+ transl_module Tcoerce_none (field_path rootpath id) modl
+ in
+ Levent (module_body, {
+ lev_loc = loc;
+ lev_kind = Lev_module_definition id;
+ lev_repr = None;
+ lev_env = Env.summary Env.empty;
+ }))
bindings
body
in
| Tstr_recmodule bindings ->
let ids = List.map (fun mb -> mb.mb_id) bindings in
compile_recmodule
- (fun id modl ->
+ (fun id modl _loc ->
subst_lambda subst
(transl_module Tcoerce_none
(field_path rootpath id) modl))
| Tstr_recmodule bindings ->
let idents = List.map (fun mb -> mb.mb_id) bindings in
compile_recmodule
- (fun id modl -> transl_module Tcoerce_none (Some(Pident id)) modl)
+ (fun id modl _loc -> transl_module Tcoerce_none (Some(Pident id)) modl)
bindings
(make_sequence toploop_setvalue_id idents)
| Tstr_class cl_list ->
"@[Cannot safely evaluate the definition@ \
of the recursively-defined module %a@]"
Printtyp.ident id
+ | Conflicting_inline_attributes ->
+ fprintf ppf
+ "@[Conflicting ``inline'' attributes@]"
let () =
Location.register_error_of_exn
type error =
Circular_dependency of Ident.t
+| Conflicting_inline_attributes
exception Error of Location.t * error
assert(Config.flambda);
let method_cache_id = Ident.create "method_cache" in
method_cache := Lvar method_cache_id;
- (* Calling f (usualy Translmod.transl_struct) requires the
+ (* Calling f (usually Translmod.transl_struct) requires the
method_cache variable to be initialised to be able to generate
method accesses. *)
let expr, size = f () in
+++ /dev/null
-(**************************************************************************)
-(* *)
-(* OCaml *)
-(* *)
-(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
-(* *)
-(* Copyright 1998 Institut National de Recherche en Informatique et *)
-(* en Automatique. *)
-(* *)
-(* All rights reserved. This file is distributed under the terms of *)
-(* the GNU Lesser General Public License version 2.1, with the *)
-(* special exception on linking described in the file LICENSE. *)
-(* *)
-(**************************************************************************)
-
-(* Auxiliaries for type-based optimizations, e.g. array kinds *)
-
-open Path
-open Types
-open Typedtree
-open Lambda
-
-let scrape_ty env ty =
- let ty = Ctype.expand_head_opt env (Ctype.correct_levels ty) in
- match ty.desc with
- | Tconstr (p, _, _) ->
- begin match Env.find_type p env with
- | {type_unboxed = {unboxed = true; _}; _} ->
- begin match Typedecl.get_unboxed_type_representation env ty with
- | None -> ty
- | Some ty2 -> ty2
- end
- | _ -> ty
- | exception Not_found -> ty
- end
- | _ -> ty
-
-let scrape env ty =
- (scrape_ty env ty).desc
-
-let is_function_type env ty =
- match scrape env ty with
- | Tarrow (_, lhs, rhs, _) -> Some (lhs, rhs)
- | _ -> None
-
-let is_base_type env ty base_ty_path =
- match scrape env ty with
- | Tconstr(p, _, _) -> Path.same p base_ty_path
- | _ -> false
-
-let maybe_pointer_type env ty =
- if Ctype.maybe_pointer_type env ty then
- Pointer
- else
- Immediate
-
-let maybe_pointer exp = maybe_pointer_type exp.exp_env exp.exp_type
-
-type classification =
- | Int
- | Float
- | Lazy
- | Addr (* anything except a float or a lazy *)
- | Any
-
-let classify env ty =
- let ty = scrape_ty env ty in
- if maybe_pointer_type env ty = Immediate then Int
- else match ty.desc with
- | Tvar _ | Tunivar _ ->
- Any
- | Tconstr (p, _args, _abbrev) ->
- if Path.same p Predef.path_float then Float
- else if Path.same p Predef.path_lazy_t then Lazy
- else if Path.same p Predef.path_string
- || Path.same p Predef.path_bytes
- || Path.same p Predef.path_array
- || Path.same p Predef.path_nativeint
- || Path.same p Predef.path_int32
- || Path.same p Predef.path_int64 then Addr
- else begin
- try
- match (Env.find_type p env).type_kind with
- | Type_abstract ->
- Any
- | Type_record _ | Type_variant _ | Type_open ->
- Addr
- with Not_found ->
- (* This can happen due to e.g. missing -I options,
- causing some .cmi files to be unavailable.
- Maybe we should emit a warning. *)
- Any
- end
- | Tarrow _ | Ttuple _ | Tpackage _ | Tobject _ | Tnil | Tvariant _ ->
- Addr
- | Tlink _ | Tsubst _ | Tpoly _ | Tfield _ ->
- assert false
-
-let array_type_kind env ty =
- match scrape env ty with
- | Tconstr(p, [elt_ty], _) | Tpoly({desc = Tconstr(p, [elt_ty], _)}, _)
- when Path.same p Predef.path_array ->
- begin match classify env elt_ty with
- | Any -> Pgenarray
- | Float -> Pfloatarray
- | Addr | Lazy -> Paddrarray
- | Int -> Pintarray
- end
-
- | _ ->
- (* This can happen with e.g. Obj.field *)
- Pgenarray
-
-let array_kind exp = array_type_kind exp.exp_env exp.exp_type
-
-let array_pattern_kind pat = array_type_kind pat.pat_env pat.pat_type
-
-let bigarray_decode_type env ty tbl dfl =
- match scrape env ty with
- | Tconstr(Pdot(Pident mod_id, type_name, _), [], _)
- when Ident.name mod_id = "Bigarray" ->
- begin try List.assoc type_name tbl with Not_found -> dfl end
- | _ ->
- dfl
-
-let kind_table =
- ["float32_elt", Pbigarray_float32;
- "float64_elt", Pbigarray_float64;
- "int8_signed_elt", Pbigarray_sint8;
- "int8_unsigned_elt", Pbigarray_uint8;
- "int16_signed_elt", Pbigarray_sint16;
- "int16_unsigned_elt", Pbigarray_uint16;
- "int32_elt", Pbigarray_int32;
- "int64_elt", Pbigarray_int64;
- "int_elt", Pbigarray_caml_int;
- "nativeint_elt", Pbigarray_native_int;
- "complex32_elt", Pbigarray_complex32;
- "complex64_elt", Pbigarray_complex64]
-
-let layout_table =
- ["c_layout", Pbigarray_c_layout;
- "fortran_layout", Pbigarray_fortran_layout]
-
-let bigarray_type_kind_and_layout env typ =
- match scrape env typ with
- | Tconstr(_p, [_caml_type; elt_type; layout_type], _abbrev) ->
- (bigarray_decode_type env elt_type kind_table Pbigarray_unknown,
- bigarray_decode_type env layout_type layout_table
- Pbigarray_unknown_layout)
- | _ ->
- (Pbigarray_unknown, Pbigarray_unknown_layout)
-
-let value_kind env ty =
- match scrape env ty with
- | Tconstr(p, _, _) when Path.same p Predef.path_int ->
- Pintval
- | Tconstr(p, _, _) when Path.same p Predef.path_char ->
- Pintval
- | Tconstr(p, _, _) when Path.same p Predef.path_float ->
- Pfloatval
- | Tconstr(p, _, _) when Path.same p Predef.path_int32 ->
- Pboxedintval Pint32
- | Tconstr(p, _, _) when Path.same p Predef.path_int64 ->
- Pboxedintval Pint64
- | Tconstr(p, _, _) when Path.same p Predef.path_nativeint ->
- Pboxedintval Pnativeint
- | _ ->
- Pgenval
-
-
-let lazy_val_requires_forward env ty =
- match classify env ty with
- | Any | Float | Lazy -> true
- | Addr | Int -> false
+++ /dev/null
-(**************************************************************************)
-(* *)
-(* OCaml *)
-(* *)
-(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
-(* *)
-(* Copyright 1998 Institut National de Recherche en Informatique et *)
-(* en Automatique. *)
-(* *)
-(* All rights reserved. This file is distributed under the terms of *)
-(* the GNU Lesser General Public License version 2.1, with the *)
-(* special exception on linking described in the file LICENSE. *)
-(* *)
-(**************************************************************************)
-
-(* Auxiliaries for type-based optimizations, e.g. array kinds *)
-
-val is_function_type :
- Env.t -> Types.type_expr -> (Types.type_expr * Types.type_expr) option
-val is_base_type : Env.t -> Types.type_expr -> Path.t -> bool
-
-val maybe_pointer_type : Env.t -> Types.type_expr
- -> Lambda.immediate_or_pointer
-val maybe_pointer : Typedtree.expression -> Lambda.immediate_or_pointer
-
-val array_type_kind : Env.t -> Types.type_expr -> Lambda.array_kind
-val array_kind : Typedtree.expression -> Lambda.array_kind
-val array_pattern_kind : Typedtree.pattern -> Lambda.array_kind
-val bigarray_type_kind_and_layout :
- Env.t -> Types.type_expr -> Lambda.bigarray_kind * Lambda.bigarray_layout
-val value_kind : Env.t -> Types.type_expr -> Lambda.value_kind
-
-val lazy_val_requires_forward : Env.t -> Types.type_expr -> bool
- (** Whether a forward block is needed for a lazy thunk on a value, i.e.
- if the value can be represented as a float/forward/lazy *)
-afl.o: afl.c caml/misc.h caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/mlvalues.h caml/osdeps.h
-alloc.o: alloc.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/custom.h caml/major_gc.h caml/freelist.h caml/memory.h caml/gc.h \
- caml/minor_gc.h caml/address_class.h caml/stacks.h
-array.o: array.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/signals.h caml/spacetime.h
-backtrace.o: backtrace.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/backtrace.h caml/exec.h \
- caml/backtrace_prim.h caml/fail.h
-backtrace_prim.o: backtrace_prim.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/mlvalues.h caml/misc.h caml/alloc.h \
- caml/custom.h caml/io.h caml/instruct.h caml/intext.h caml/exec.h \
- caml/fix_code.h caml/memory.h caml/gc.h caml/major_gc.h \
- caml/freelist.h caml/minor_gc.h caml/address_class.h caml/startup.h \
- caml/stacks.h caml/sys.h caml/backtrace.h caml/fail.h \
- caml/backtrace_prim.h
-callback.o: callback.c caml/callback.h caml/mlvalues.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/fail.h \
- caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/interp.h caml/instruct.h \
- caml/fix_code.h caml/stacks.h
-compact.o: compact.c caml/address_class.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/misc.h \
- caml/mlvalues.h caml/finalise.h caml/roots.h caml/memory.h caml/gc.h \
- caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/gc_ctrl.h \
- caml/weak.h caml/compact.h
-compare.o: compare.c caml/custom.h caml/mlvalues.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/fail.h \
- caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
+afl.$(O): afl.c caml/config.h caml/m.h caml/s.h caml/misc.h caml/mlvalues.h \
+ caml/osdeps.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
caml/minor_gc.h caml/address_class.h
-custom.o: custom.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/custom.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \
- caml/freelist.h caml/minor_gc.h caml/address_class.h
-debugger.o: debugger.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/debugger.h caml/osdeps.h caml/fail.h caml/fix_code.h \
- caml/instruct.h caml/intext.h caml/io.h caml/stacks.h caml/memory.h \
- caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
- caml/address_class.h caml/sys.h
-dynlink.o: dynlink.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/alloc.h caml/misc.h caml/mlvalues.h \
- caml/dynlink.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \
- caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \
- caml/prims.h caml/signals.h
-extern.o: extern.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/custom.h caml/fail.h caml/gc.h caml/intext.h caml/io.h caml/md5.h \
- caml/memory.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
- caml/address_class.h caml/reverse.h
-fail.o: fail.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/fail.h caml/io.h caml/gc.h caml/memory.h caml/major_gc.h \
- caml/freelist.h caml/minor_gc.h caml/address_class.h caml/printexc.h \
- caml/signals.h caml/stacks.h
-finalise.o: finalise.c caml/callback.h caml/mlvalues.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/compact.h \
- caml/fail.h caml/finalise.h caml/roots.h caml/memory.h caml/gc.h \
- caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \
- caml/signals.h
-fix_code.o: fix_code.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/debugger.h caml/misc.h caml/mlvalues.h \
- caml/fix_code.h caml/instruct.h caml/intext.h caml/io.h caml/md5.h \
+alloc.$(O): alloc.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/custom.h caml/major_gc.h caml/freelist.h \
+ caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \
+ caml/stacks.h
+array.$(O): array.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \
+ caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h \
+ caml/spacetime.h
+backtrace.$(O): backtrace.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \
+ caml/freelist.h caml/minor_gc.h caml/address_class.h caml/backtrace.h \
+ caml/exec.h caml/backtrace_prim.h caml/fail.h
+backtrace_prim.$(O): backtrace_prim.c caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/misc.h caml/alloc.h caml/custom.h caml/io.h \
+ caml/instruct.h caml/intext.h caml/exec.h caml/fix_code.h \
caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/reverse.h
-floats.o: floats.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/reverse.h caml/stacks.h
-freelist.o: freelist.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/freelist.h caml/misc.h caml/mlvalues.h \
- caml/gc.h caml/gc_ctrl.h caml/memory.h caml/major_gc.h caml/minor_gc.h \
- caml/address_class.h
-gc_ctrl.o: gc_ctrl.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/backtrace.h caml/exec.h caml/compact.h caml/custom.h caml/fail.h \
- caml/finalise.h caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h \
- caml/freelist.h caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h \
- caml/signals.h caml/stacks.h caml/startup_aux.h
-globroots.o: globroots.c caml/memory.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/gc.h caml/mlvalues.h \
- caml/misc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
- caml/address_class.h caml/roots.h caml/globroots.h
-hash.o: hash.c caml/mlvalues.h caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/misc.h caml/custom.h caml/memory.h \
- caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
- caml/address_class.h caml/hash.h
-instrtrace.o: instrtrace.c
-intern.o: intern.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/callback.h caml/custom.h caml/fail.h caml/gc.h caml/intext.h \
- caml/io.h caml/md5.h caml/memory.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/reverse.h
-interp.o: interp.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/backtrace.h caml/exec.h caml/callback.h caml/debugger.h \
- caml/fail.h caml/fix_code.h caml/instrtrace.h caml/instruct.h \
- caml/interp.h caml/major_gc.h caml/freelist.h caml/memory.h caml/gc.h \
- caml/minor_gc.h caml/address_class.h caml/prims.h caml/signals.h \
- caml/stacks.h caml/startup_aux.h caml/jumptbl.h
-ints.o: ints.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/custom.h caml/fail.h caml/intext.h caml/io.h caml/memory.h \
+ caml/minor_gc.h caml/address_class.h caml/startup.h caml/stacks.h \
+ caml/sys.h caml/backtrace.h caml/fail.h caml/backtrace_prim.h
+bigarray.$(O): bigarray.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/bigarray.h caml/custom.h caml/fail.h \
+ caml/intext.h caml/io.h caml/hash.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h
+callback.$(O): callback.c caml/callback.h caml/mlvalues.h caml/config.h \
+ caml/m.h caml/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \
+ caml/interp.h caml/instruct.h caml/fix_code.h caml/stacks.h
+compact.$(O): compact.c caml/address_class.h caml/config.h caml/m.h caml/s.h \
+ caml/misc.h caml/mlvalues.h caml/finalise.h caml/roots.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
+ caml/gc_ctrl.h caml/weak.h caml/compact.h
+compare.$(O): compare.c caml/custom.h caml/mlvalues.h caml/config.h caml/m.h \
+ caml/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h
+custom.$(O): custom.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/custom.h caml/fail.h caml/memory.h \
caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
caml/address_class.h
-io.o: io.c caml/config.h caml/../../config/m.h caml/../../config/s.h \
- caml/alloc.h caml/misc.h caml/mlvalues.h caml/custom.h caml/fail.h \
- caml/io.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/signals.h \
- caml/sys.h
-lexing.o: lexing.c caml/fail.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/stacks.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h
-main.o: main.c caml/misc.h caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/mlvalues.h caml/sys.h
-major_gc.o: major_gc.c caml/compact.h caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/misc.h caml/mlvalues.h caml/custom.h \
- caml/fail.h caml/finalise.h caml/roots.h caml/memory.h caml/gc.h \
+debugger.$(O): debugger.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/debugger.h caml/osdeps.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
+ caml/address_class.h caml/fail.h caml/fix_code.h caml/instruct.h \
+ caml/intext.h caml/io.h caml/stacks.h caml/sys.h
+dynlink.$(O): dynlink.c caml/config.h caml/m.h caml/s.h caml/alloc.h \
+ caml/misc.h caml/mlvalues.h caml/dynlink.h caml/fail.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
+ caml/address_class.h caml/osdeps.h caml/prims.h caml/signals.h
+extern.$(O): extern.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/custom.h caml/fail.h caml/gc.h \
+ caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/major_gc.h \
+ caml/freelist.h caml/minor_gc.h caml/address_class.h caml/reverse.h
+fail.$(O): fail.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/fail.h caml/io.h caml/gc.h caml/memory.h \
caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \
- caml/gc_ctrl.h caml/signals.h caml/weak.h
-md5.o: md5.c caml/alloc.h caml/misc.h caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/mlvalues.h caml/fail.h caml/md5.h caml/io.h \
- caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/reverse.h
-memory.o: memory.c caml/address_class.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/misc.h \
- caml/mlvalues.h caml/fail.h caml/freelist.h caml/gc.h caml/gc_ctrl.h \
- caml/major_gc.h caml/memory.h caml/minor_gc.h caml/signals.h
-meta.o: meta.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/fail.h caml/fix_code.h caml/interp.h caml/intext.h caml/io.h \
- caml/major_gc.h caml/freelist.h caml/memory.h caml/gc.h \
- caml/minor_gc.h caml/address_class.h caml/prims.h caml/stacks.h
-minor_gc.o: minor_gc.c caml/custom.h caml/mlvalues.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/fail.h \
+ caml/printexc.h caml/signals.h caml/stacks.h
+finalise.$(O): finalise.c caml/callback.h caml/mlvalues.h caml/config.h \
+ caml/m.h caml/s.h caml/misc.h caml/compact.h caml/fail.h \
caml/finalise.h caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h \
- caml/freelist.h caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h \
- caml/signals.h caml/weak.h
-misc.o: misc.c caml/config.h caml/../../config/m.h caml/../../config/s.h \
- caml/misc.h caml/memory.h caml/gc.h caml/mlvalues.h caml/major_gc.h \
- caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \
- caml/version.h
-obj.o: obj.c caml/alloc.h caml/misc.h caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/mlvalues.h caml/fail.h caml/gc.h \
- caml/interp.h caml/major_gc.h caml/freelist.h caml/memory.h \
- caml/minor_gc.h caml/address_class.h caml/prims.h caml/spacetime.h
-parsing.o: parsing.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/mlvalues.h caml/misc.h caml/memory.h \
- caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
- caml/address_class.h caml/alloc.h
-prims.o: prims.c caml/mlvalues.h caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/misc.h caml/prims.h
-printexc.o: printexc.c caml/backtrace.h caml/mlvalues.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/exec.h \
- caml/callback.h caml/debugger.h caml/fail.h caml/printexc.h
-roots.o: roots.c caml/finalise.h caml/roots.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/memory.h caml/gc.h \
- caml/mlvalues.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
- caml/address_class.h caml/globroots.h caml/stacks.h
-signals.o: signals.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/callback.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \
- caml/freelist.h caml/minor_gc.h caml/address_class.h caml/roots.h \
- caml/signals.h caml/signals_machdep.h caml/sys.h
-signals_byt.o: signals_byt.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/memory.h caml/gc.h caml/mlvalues.h \
- caml/misc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
- caml/address_class.h caml/osdeps.h caml/signals.h \
- caml/signals_machdep.h
-spacetime.o: spacetime.c caml/fail.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h
-stacks.o: stacks.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/fail.h caml/misc.h caml/mlvalues.h \
- caml/stacks.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h
-startup.o: startup.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/alloc.h caml/misc.h caml/mlvalues.h \
- caml/backtrace.h caml/exec.h caml/callback.h caml/custom.h \
- caml/debugger.h caml/dynlink.h caml/fail.h caml/fix_code.h \
- caml/freelist.h caml/gc_ctrl.h caml/instrtrace.h caml/interp.h \
- caml/intext.h caml/io.h caml/memory.h caml/gc.h caml/major_gc.h \
- caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/prims.h \
- caml/printexc.h caml/reverse.h caml/signals.h caml/stacks.h caml/sys.h \
- caml/startup.h caml/startup_aux.h caml/version.h
-startup_aux.o: startup_aux.c caml/backtrace.h caml/mlvalues.h \
- caml/config.h caml/../../config/m.h caml/../../config/s.h caml/misc.h \
- caml/exec.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/startup_aux.h
-str.o: str.c caml/alloc.h caml/misc.h caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/mlvalues.h caml/fail.h
-sys.o: sys.c caml/config.h caml/../../config/m.h caml/../../config/s.h \
- caml/alloc.h caml/misc.h caml/mlvalues.h caml/debugger.h caml/fail.h \
- caml/gc_ctrl.h caml/instruct.h caml/io.h caml/osdeps.h caml/signals.h \
- caml/stacks.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/sys.h caml/version.h
-terminfo.o: terminfo.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/alloc.h caml/misc.h caml/mlvalues.h \
- caml/fail.h caml/io.h
-unix.o: unix.c caml/config.h caml/../../config/m.h caml/../../config/s.h \
- caml/fail.h caml/misc.h caml/mlvalues.h caml/memory.h caml/gc.h \
+ caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h
+fix_code.$(O): fix_code.c caml/config.h caml/m.h caml/s.h caml/debugger.h \
+ caml/misc.h caml/mlvalues.h caml/fix_code.h caml/instruct.h \
+ caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/gc.h \
caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \
- caml/osdeps.h caml/signals.h caml/sys.h caml/io.h
-weak.o: weak.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/fail.h caml/major_gc.h caml/freelist.h caml/memory.h caml/gc.h \
- caml/minor_gc.h caml/address_class.h caml/weak.h
-afl.d.o: afl.c caml/misc.h caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/mlvalues.h caml/osdeps.h
-alloc.d.o: alloc.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/custom.h caml/major_gc.h caml/freelist.h caml/memory.h caml/gc.h \
- caml/minor_gc.h caml/address_class.h caml/stacks.h
-array.d.o: array.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/signals.h caml/spacetime.h
-backtrace.d.o: backtrace.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/backtrace.h caml/exec.h \
- caml/backtrace_prim.h caml/fail.h
-backtrace_prim.d.o: backtrace_prim.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/mlvalues.h caml/misc.h caml/alloc.h \
- caml/custom.h caml/io.h caml/instruct.h caml/intext.h caml/exec.h \
- caml/fix_code.h caml/memory.h caml/gc.h caml/major_gc.h \
- caml/freelist.h caml/minor_gc.h caml/address_class.h caml/startup.h \
- caml/stacks.h caml/sys.h caml/backtrace.h caml/fail.h \
- caml/backtrace_prim.h
-callback.d.o: callback.c caml/callback.h caml/mlvalues.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/fail.h \
- caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/interp.h caml/instruct.h \
- caml/fix_code.h caml/stacks.h
-compact.d.o: compact.c caml/address_class.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/misc.h \
- caml/mlvalues.h caml/finalise.h caml/roots.h caml/memory.h caml/gc.h \
- caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/gc_ctrl.h \
- caml/weak.h caml/compact.h
-compare.d.o: compare.c caml/custom.h caml/mlvalues.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/fail.h \
+ caml/reverse.h
+floats.$(O): floats.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \
+ caml/reverse.h caml/stacks.h
+freelist.$(O): freelist.c caml/config.h caml/m.h caml/s.h caml/freelist.h \
+ caml/misc.h caml/mlvalues.h caml/gc.h caml/gc_ctrl.h caml/memory.h \
+ caml/major_gc.h caml/minor_gc.h caml/address_class.h
+gc_ctrl.$(O): gc_ctrl.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h caml/compact.h \
+ caml/custom.h caml/fail.h caml/finalise.h caml/roots.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
+ caml/address_class.h caml/gc_ctrl.h caml/signals.h caml/stacks.h \
+ caml/startup_aux.h
+globroots.$(O): globroots.c caml/memory.h caml/config.h caml/m.h caml/s.h \
+ caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h caml/freelist.h \
+ caml/minor_gc.h caml/address_class.h caml/roots.h caml/globroots.h
+hash.$(O): hash.c caml/mlvalues.h caml/config.h caml/m.h caml/s.h \
+ caml/misc.h caml/custom.h caml/memory.h caml/gc.h caml/major_gc.h \
+ caml/freelist.h caml/minor_gc.h caml/address_class.h caml/hash.h
+instrtrace.$(O): instrtrace.c
+intern.$(O): intern.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/callback.h caml/custom.h caml/fail.h \
+ caml/gc.h caml/intext.h caml/io.h caml/md5.h caml/memory.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \
+ caml/reverse.h
+interp.$(O): interp.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h caml/callback.h \
+ caml/debugger.h caml/fail.h caml/fix_code.h caml/instrtrace.h \
+ caml/instruct.h caml/interp.h caml/major_gc.h caml/freelist.h \
+ caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \
+ caml/prims.h caml/signals.h caml/stacks.h caml/startup_aux.h \
+ caml/jumptbl.h
+ints.$(O): ints.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/custom.h caml/fail.h caml/intext.h caml/io.h \
caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
caml/minor_gc.h caml/address_class.h
-custom.d.o: custom.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/custom.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \
- caml/freelist.h caml/minor_gc.h caml/address_class.h
-debugger.d.o: debugger.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/debugger.h caml/osdeps.h caml/fail.h caml/fix_code.h \
- caml/instruct.h caml/intext.h caml/io.h caml/stacks.h caml/memory.h \
- caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
- caml/address_class.h caml/sys.h
-dynlink.d.o: dynlink.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/alloc.h caml/misc.h caml/mlvalues.h \
- caml/dynlink.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \
- caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \
- caml/prims.h caml/signals.h
-extern.d.o: extern.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/custom.h caml/fail.h caml/gc.h caml/intext.h caml/io.h caml/md5.h \
- caml/memory.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
+io.$(O): io.c caml/config.h caml/m.h caml/s.h caml/alloc.h caml/misc.h \
+ caml/mlvalues.h caml/custom.h caml/fail.h caml/io.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
+ caml/address_class.h caml/osdeps.h caml/signals.h caml/sys.h
+lexing.$(O): lexing.c caml/fail.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h
+main.$(O): main.c caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/sys.h caml/osdeps.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h
+major_gc.$(O): major_gc.c caml/compact.h caml/config.h caml/m.h caml/s.h \
+ caml/misc.h caml/mlvalues.h caml/custom.h caml/fail.h caml/finalise.h \
+ caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
+ caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h caml/signals.h \
+ caml/weak.h
+md5.$(O): md5.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/fail.h caml/md5.h caml/io.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
caml/address_class.h caml/reverse.h
-fail.d.o: fail.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/fail.h caml/io.h caml/gc.h caml/memory.h caml/major_gc.h \
- caml/freelist.h caml/minor_gc.h caml/address_class.h caml/printexc.h \
- caml/signals.h caml/stacks.h
-finalise.d.o: finalise.c caml/callback.h caml/mlvalues.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/compact.h \
- caml/fail.h caml/finalise.h caml/roots.h caml/memory.h caml/gc.h \
- caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \
+memory.$(O): memory.c caml/address_class.h caml/config.h caml/m.h caml/s.h \
+ caml/misc.h caml/mlvalues.h caml/fail.h caml/freelist.h caml/gc.h \
+ caml/gc_ctrl.h caml/major_gc.h caml/memory.h caml/minor_gc.h \
caml/signals.h
-fix_code.d.o: fix_code.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/debugger.h caml/misc.h caml/mlvalues.h \
- caml/fix_code.h caml/instruct.h caml/intext.h caml/io.h caml/md5.h \
+meta.$(O): meta.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/fail.h caml/fix_code.h caml/interp.h \
+ caml/intext.h caml/io.h caml/major_gc.h caml/freelist.h caml/memory.h \
+ caml/gc.h caml/minor_gc.h caml/address_class.h caml/prims.h \
+ caml/stacks.h
+minor_gc.$(O): minor_gc.c caml/custom.h caml/mlvalues.h caml/config.h \
+ caml/m.h caml/s.h caml/misc.h caml/fail.h caml/finalise.h caml/roots.h \
caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/reverse.h
-floats.d.o: floats.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/reverse.h caml/stacks.h
-freelist.d.o: freelist.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/freelist.h caml/misc.h caml/mlvalues.h \
- caml/gc.h caml/gc_ctrl.h caml/memory.h caml/major_gc.h caml/minor_gc.h \
- caml/address_class.h
-gc_ctrl.d.o: gc_ctrl.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/backtrace.h caml/exec.h caml/compact.h caml/custom.h caml/fail.h \
- caml/finalise.h caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h \
- caml/freelist.h caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h \
- caml/signals.h caml/stacks.h caml/startup_aux.h
-globroots.d.o: globroots.c caml/memory.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/gc.h caml/mlvalues.h \
- caml/misc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
- caml/address_class.h caml/roots.h caml/globroots.h
-hash.d.o: hash.c caml/mlvalues.h caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/misc.h caml/custom.h caml/memory.h \
- caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
- caml/address_class.h caml/hash.h
-instrtrace.d.o: instrtrace.c caml/instrtrace.h caml/mlvalues.h \
- caml/config.h caml/../../config/m.h caml/../../config/s.h caml/misc.h \
- caml/instruct.h caml/opnames.h caml/prims.h caml/stacks.h \
+ caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h caml/signals.h \
+ caml/weak.h
+misc.$(O): misc.c caml/config.h caml/m.h caml/s.h caml/misc.h caml/memory.h \
+ caml/gc.h caml/mlvalues.h caml/major_gc.h caml/freelist.h \
+ caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/version.h
+obj.$(O): obj.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/fail.h caml/gc.h caml/interp.h caml/major_gc.h \
+ caml/freelist.h caml/memory.h caml/minor_gc.h caml/address_class.h \
+ caml/prims.h caml/spacetime.h
+parsing.$(O): parsing.c caml/config.h caml/m.h caml/s.h caml/mlvalues.h \
+ caml/misc.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
+ caml/minor_gc.h caml/address_class.h caml/alloc.h
+prims.$(O): prims.c caml/mlvalues.h caml/config.h caml/m.h caml/s.h \
+ caml/misc.h caml/prims.h
+printexc.$(O): printexc.c caml/backtrace.h caml/mlvalues.h caml/config.h \
+ caml/m.h caml/s.h caml/misc.h caml/exec.h caml/callback.h \
+ caml/debugger.h caml/fail.h caml/printexc.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h
+roots.$(O): roots.c caml/finalise.h caml/roots.h caml/misc.h caml/config.h \
+ caml/m.h caml/s.h caml/memory.h caml/gc.h caml/mlvalues.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \
+ caml/globroots.h caml/stacks.h
+signals.$(O): signals.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/callback.h caml/fail.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
+ caml/address_class.h caml/roots.h caml/signals.h \
+ caml/signals_machdep.h caml/sys.h
+signals_byt.$(O): signals_byt.c caml/config.h caml/m.h caml/s.h \
+ caml/memory.h caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h \
+ caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \
+ caml/signals.h caml/signals_machdep.h
+spacetime.$(O): spacetime.c caml/fail.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h
+stacks.$(O): stacks.c caml/config.h caml/m.h caml/s.h caml/fail.h \
+ caml/misc.h caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h
+startup.$(O): startup.c caml/config.h caml/m.h caml/s.h caml/alloc.h \
+ caml/misc.h caml/mlvalues.h caml/backtrace.h caml/exec.h \
+ caml/callback.h caml/custom.h caml/debugger.h caml/dynlink.h \
+ caml/fail.h caml/fix_code.h caml/freelist.h caml/gc_ctrl.h \
+ caml/instrtrace.h caml/interp.h caml/intext.h caml/io.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/minor_gc.h caml/address_class.h \
+ caml/osdeps.h caml/prims.h caml/printexc.h caml/reverse.h \
+ caml/signals.h caml/stacks.h caml/sys.h caml/startup.h \
+ caml/startup_aux.h caml/version.h
+startup_aux.$(O): startup_aux.c caml/backtrace.h caml/mlvalues.h \
+ caml/config.h caml/m.h caml/s.h caml/misc.h caml/exec.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
+ caml/address_class.h caml/callback.h caml/dynlink.h caml/osdeps.h \
+ caml/startup_aux.h
+str.$(O): str.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \
+ caml/freelist.h caml/minor_gc.h caml/address_class.h
+sys.$(O): sys.c caml/config.h caml/m.h caml/s.h caml/alloc.h caml/misc.h \
+ caml/mlvalues.h caml/debugger.h caml/fail.h caml/gc_ctrl.h caml/io.h \
+ caml/osdeps.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
+ caml/minor_gc.h caml/address_class.h caml/signals.h caml/stacks.h \
+ caml/sys.h caml/version.h caml/callback.h caml/startup_aux.h
+terminfo.$(O): terminfo.c caml/config.h caml/m.h caml/s.h caml/alloc.h \
+ caml/misc.h caml/mlvalues.h caml/fail.h caml/io.h
+unix.$(O): unix.c caml/config.h caml/m.h caml/s.h caml/fail.h caml/misc.h \
+ caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \
+ caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \
+ caml/signals.h caml/sys.h caml/io.h caml/alloc.h
+weak.$(O): weak.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/fail.h caml/major_gc.h caml/freelist.h \
+ caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \
+ caml/weak.h
+afl.d.$(O): afl.c caml/config.h caml/m.h caml/s.h caml/misc.h caml/mlvalues.h \
+ caml/osdeps.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
+ caml/minor_gc.h caml/address_class.h
+alloc.d.$(O): alloc.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/custom.h caml/major_gc.h caml/freelist.h \
+ caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \
+ caml/stacks.h
+array.d.$(O): array.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \
+ caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h \
+ caml/spacetime.h
+backtrace.d.$(O): backtrace.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \
+ caml/freelist.h caml/minor_gc.h caml/address_class.h caml/backtrace.h \
+ caml/exec.h caml/backtrace_prim.h caml/fail.h
+backtrace_prim.d.$(O): backtrace_prim.c caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/misc.h caml/alloc.h caml/custom.h caml/io.h \
+ caml/instruct.h caml/intext.h caml/exec.h caml/fix_code.h \
caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/startup_aux.h
-intern.d.o: intern.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/callback.h caml/custom.h caml/fail.h caml/gc.h caml/intext.h \
- caml/io.h caml/md5.h caml/memory.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/reverse.h
-interp.d.o: interp.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/backtrace.h caml/exec.h caml/callback.h caml/debugger.h \
- caml/fail.h caml/fix_code.h caml/instrtrace.h caml/instruct.h \
- caml/interp.h caml/major_gc.h caml/freelist.h caml/memory.h caml/gc.h \
- caml/minor_gc.h caml/address_class.h caml/prims.h caml/signals.h \
- caml/stacks.h caml/startup_aux.h
-ints.d.o: ints.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/custom.h caml/fail.h caml/intext.h caml/io.h caml/memory.h \
+ caml/minor_gc.h caml/address_class.h caml/startup.h caml/stacks.h \
+ caml/sys.h caml/backtrace.h caml/fail.h caml/backtrace_prim.h
+bigarray.d.$(O): bigarray.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/bigarray.h caml/custom.h caml/fail.h \
+ caml/intext.h caml/io.h caml/hash.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h
+callback.d.$(O): callback.c caml/callback.h caml/mlvalues.h caml/config.h \
+ caml/m.h caml/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \
+ caml/interp.h caml/instruct.h caml/fix_code.h caml/stacks.h
+compact.d.$(O): compact.c caml/address_class.h caml/config.h caml/m.h caml/s.h \
+ caml/misc.h caml/mlvalues.h caml/finalise.h caml/roots.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
+ caml/gc_ctrl.h caml/weak.h caml/compact.h
+compare.d.$(O): compare.c caml/custom.h caml/mlvalues.h caml/config.h caml/m.h \
+ caml/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h
+custom.d.$(O): custom.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/custom.h caml/fail.h caml/memory.h \
caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
caml/address_class.h
-io.d.o: io.c caml/config.h caml/../../config/m.h caml/../../config/s.h \
- caml/alloc.h caml/misc.h caml/mlvalues.h caml/custom.h caml/fail.h \
- caml/io.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/signals.h \
- caml/sys.h
-lexing.d.o: lexing.c caml/fail.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/stacks.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h
-main.d.o: main.c caml/misc.h caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/mlvalues.h caml/sys.h
-major_gc.d.o: major_gc.c caml/compact.h caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/misc.h caml/mlvalues.h caml/custom.h \
- caml/fail.h caml/finalise.h caml/roots.h caml/memory.h caml/gc.h \
+debugger.d.$(O): debugger.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/debugger.h caml/osdeps.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
+ caml/address_class.h caml/fail.h caml/fix_code.h caml/instruct.h \
+ caml/intext.h caml/io.h caml/stacks.h caml/sys.h
+dynlink.d.$(O): dynlink.c caml/config.h caml/m.h caml/s.h caml/alloc.h \
+ caml/misc.h caml/mlvalues.h caml/dynlink.h caml/fail.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
+ caml/address_class.h caml/osdeps.h caml/prims.h caml/signals.h
+extern.d.$(O): extern.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/custom.h caml/fail.h caml/gc.h \
+ caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/major_gc.h \
+ caml/freelist.h caml/minor_gc.h caml/address_class.h caml/reverse.h
+fail.d.$(O): fail.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/fail.h caml/io.h caml/gc.h caml/memory.h \
caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \
- caml/gc_ctrl.h caml/signals.h caml/weak.h
-md5.d.o: md5.c caml/alloc.h caml/misc.h caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/mlvalues.h caml/fail.h caml/md5.h caml/io.h \
- caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/reverse.h
-memory.d.o: memory.c caml/address_class.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/misc.h \
- caml/mlvalues.h caml/fail.h caml/freelist.h caml/gc.h caml/gc_ctrl.h \
- caml/major_gc.h caml/memory.h caml/minor_gc.h caml/signals.h
-meta.d.o: meta.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/fail.h caml/fix_code.h caml/interp.h caml/intext.h caml/io.h \
- caml/major_gc.h caml/freelist.h caml/memory.h caml/gc.h \
- caml/minor_gc.h caml/address_class.h caml/prims.h caml/stacks.h
-minor_gc.d.o: minor_gc.c caml/custom.h caml/mlvalues.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/fail.h \
+ caml/printexc.h caml/signals.h caml/stacks.h
+finalise.d.$(O): finalise.c caml/callback.h caml/mlvalues.h caml/config.h \
+ caml/m.h caml/s.h caml/misc.h caml/compact.h caml/fail.h \
caml/finalise.h caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h \
- caml/freelist.h caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h \
- caml/signals.h caml/weak.h
-misc.d.o: misc.c caml/config.h caml/../../config/m.h caml/../../config/s.h \
- caml/misc.h caml/memory.h caml/gc.h caml/mlvalues.h caml/major_gc.h \
- caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \
- caml/version.h
-obj.d.o: obj.c caml/alloc.h caml/misc.h caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/mlvalues.h caml/fail.h caml/gc.h \
- caml/interp.h caml/major_gc.h caml/freelist.h caml/memory.h \
- caml/minor_gc.h caml/address_class.h caml/prims.h caml/spacetime.h
-parsing.d.o: parsing.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/mlvalues.h caml/misc.h caml/memory.h \
- caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
- caml/address_class.h caml/alloc.h
-prims.d.o: prims.c caml/mlvalues.h caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/misc.h caml/prims.h
-printexc.d.o: printexc.c caml/backtrace.h caml/mlvalues.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/exec.h \
- caml/callback.h caml/debugger.h caml/fail.h caml/printexc.h
-roots.d.o: roots.c caml/finalise.h caml/roots.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/memory.h caml/gc.h \
- caml/mlvalues.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
- caml/address_class.h caml/globroots.h caml/stacks.h
-signals.d.o: signals.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/callback.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \
- caml/freelist.h caml/minor_gc.h caml/address_class.h caml/roots.h \
- caml/signals.h caml/signals_machdep.h caml/sys.h
-signals_byt.d.o: signals_byt.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/memory.h caml/gc.h caml/mlvalues.h \
- caml/misc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
- caml/address_class.h caml/osdeps.h caml/signals.h \
- caml/signals_machdep.h
-spacetime.d.o: spacetime.c caml/fail.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h
-stacks.d.o: stacks.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/fail.h caml/misc.h caml/mlvalues.h \
- caml/stacks.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h
-startup.d.o: startup.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/alloc.h caml/misc.h caml/mlvalues.h \
- caml/backtrace.h caml/exec.h caml/callback.h caml/custom.h \
- caml/debugger.h caml/dynlink.h caml/fail.h caml/fix_code.h \
- caml/freelist.h caml/gc_ctrl.h caml/instrtrace.h caml/interp.h \
- caml/intext.h caml/io.h caml/memory.h caml/gc.h caml/major_gc.h \
- caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/prims.h \
- caml/printexc.h caml/reverse.h caml/signals.h caml/stacks.h caml/sys.h \
- caml/startup.h caml/startup_aux.h caml/version.h
-startup_aux.d.o: startup_aux.c caml/backtrace.h caml/mlvalues.h \
- caml/config.h caml/../../config/m.h caml/../../config/s.h caml/misc.h \
- caml/exec.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/startup_aux.h
-str.d.o: str.c caml/alloc.h caml/misc.h caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/mlvalues.h caml/fail.h
-sys.d.o: sys.c caml/config.h caml/../../config/m.h caml/../../config/s.h \
- caml/alloc.h caml/misc.h caml/mlvalues.h caml/debugger.h caml/fail.h \
- caml/gc_ctrl.h caml/instruct.h caml/io.h caml/osdeps.h caml/signals.h \
- caml/stacks.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/sys.h caml/version.h
-terminfo.d.o: terminfo.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/alloc.h caml/misc.h caml/mlvalues.h \
- caml/fail.h caml/io.h
-unix.d.o: unix.c caml/config.h caml/../../config/m.h caml/../../config/s.h \
- caml/fail.h caml/misc.h caml/mlvalues.h caml/memory.h caml/gc.h \
+ caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h
+fix_code.d.$(O): fix_code.c caml/config.h caml/m.h caml/s.h caml/debugger.h \
+ caml/misc.h caml/mlvalues.h caml/fix_code.h caml/instruct.h \
+ caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/gc.h \
caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \
- caml/osdeps.h caml/signals.h caml/sys.h caml/io.h
-weak.d.o: weak.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/fail.h caml/major_gc.h caml/freelist.h caml/memory.h caml/gc.h \
- caml/minor_gc.h caml/address_class.h caml/weak.h
-afl.i.o: afl.c caml/misc.h caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/mlvalues.h caml/osdeps.h
-alloc.i.o: alloc.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/custom.h caml/major_gc.h caml/freelist.h caml/memory.h caml/gc.h \
- caml/minor_gc.h caml/address_class.h caml/stacks.h
-array.i.o: array.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/signals.h caml/spacetime.h
-backtrace.i.o: backtrace.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/backtrace.h caml/exec.h \
- caml/backtrace_prim.h caml/fail.h
-backtrace_prim.i.o: backtrace_prim.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/mlvalues.h caml/misc.h caml/alloc.h \
- caml/custom.h caml/io.h caml/instruct.h caml/intext.h caml/exec.h \
- caml/fix_code.h caml/memory.h caml/gc.h caml/major_gc.h \
- caml/freelist.h caml/minor_gc.h caml/address_class.h caml/startup.h \
- caml/stacks.h caml/sys.h caml/backtrace.h caml/fail.h \
- caml/backtrace_prim.h
-callback.i.o: callback.c caml/callback.h caml/mlvalues.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/fail.h \
- caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/interp.h caml/instruct.h \
- caml/fix_code.h caml/stacks.h
-compact.i.o: compact.c caml/address_class.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/misc.h \
- caml/mlvalues.h caml/finalise.h caml/roots.h caml/memory.h caml/gc.h \
- caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/gc_ctrl.h \
- caml/weak.h caml/compact.h
-compare.i.o: compare.c caml/custom.h caml/mlvalues.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/fail.h \
+ caml/reverse.h
+floats.d.$(O): floats.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \
+ caml/reverse.h caml/stacks.h
+freelist.d.$(O): freelist.c caml/config.h caml/m.h caml/s.h caml/freelist.h \
+ caml/misc.h caml/mlvalues.h caml/gc.h caml/gc_ctrl.h caml/memory.h \
+ caml/major_gc.h caml/minor_gc.h caml/address_class.h
+gc_ctrl.d.$(O): gc_ctrl.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h caml/compact.h \
+ caml/custom.h caml/fail.h caml/finalise.h caml/roots.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
+ caml/address_class.h caml/gc_ctrl.h caml/signals.h caml/stacks.h \
+ caml/startup_aux.h
+globroots.d.$(O): globroots.c caml/memory.h caml/config.h caml/m.h caml/s.h \
+ caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h caml/freelist.h \
+ caml/minor_gc.h caml/address_class.h caml/roots.h caml/globroots.h
+hash.d.$(O): hash.c caml/mlvalues.h caml/config.h caml/m.h caml/s.h \
+ caml/misc.h caml/custom.h caml/memory.h caml/gc.h caml/major_gc.h \
+ caml/freelist.h caml/minor_gc.h caml/address_class.h caml/hash.h
+instrtrace.d.$(O): instrtrace.c caml/instrtrace.h caml/mlvalues.h \
+ caml/config.h caml/m.h caml/s.h caml/misc.h caml/instruct.h \
+ caml/opnames.h caml/prims.h caml/stacks.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \
+ caml/startup_aux.h
+intern.d.$(O): intern.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/callback.h caml/custom.h caml/fail.h \
+ caml/gc.h caml/intext.h caml/io.h caml/md5.h caml/memory.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \
+ caml/reverse.h
+interp.d.$(O): interp.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h caml/callback.h \
+ caml/debugger.h caml/fail.h caml/fix_code.h caml/instrtrace.h \
+ caml/instruct.h caml/interp.h caml/major_gc.h caml/freelist.h \
+ caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \
+ caml/prims.h caml/signals.h caml/stacks.h caml/startup_aux.h
+ints.d.$(O): ints.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/custom.h caml/fail.h caml/intext.h caml/io.h \
caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
caml/minor_gc.h caml/address_class.h
-custom.i.o: custom.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/custom.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \
- caml/freelist.h caml/minor_gc.h caml/address_class.h
-debugger.i.o: debugger.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/debugger.h caml/osdeps.h caml/fail.h caml/fix_code.h \
- caml/instruct.h caml/intext.h caml/io.h caml/stacks.h caml/memory.h \
- caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
- caml/address_class.h caml/sys.h
-dynlink.i.o: dynlink.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/alloc.h caml/misc.h caml/mlvalues.h \
- caml/dynlink.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \
- caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \
- caml/prims.h caml/signals.h
-extern.i.o: extern.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/custom.h caml/fail.h caml/gc.h caml/intext.h caml/io.h caml/md5.h \
- caml/memory.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
+io.d.$(O): io.c caml/config.h caml/m.h caml/s.h caml/alloc.h caml/misc.h \
+ caml/mlvalues.h caml/custom.h caml/fail.h caml/io.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
+ caml/address_class.h caml/osdeps.h caml/signals.h caml/sys.h
+lexing.d.$(O): lexing.c caml/fail.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h
+main.d.$(O): main.c caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/sys.h caml/osdeps.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h
+major_gc.d.$(O): major_gc.c caml/compact.h caml/config.h caml/m.h caml/s.h \
+ caml/misc.h caml/mlvalues.h caml/custom.h caml/fail.h caml/finalise.h \
+ caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
+ caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h caml/signals.h \
+ caml/weak.h
+md5.d.$(O): md5.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/fail.h caml/md5.h caml/io.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
caml/address_class.h caml/reverse.h
-fail.i.o: fail.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/fail.h caml/io.h caml/gc.h caml/memory.h caml/major_gc.h \
- caml/freelist.h caml/minor_gc.h caml/address_class.h caml/printexc.h \
- caml/signals.h caml/stacks.h
-finalise.i.o: finalise.c caml/callback.h caml/mlvalues.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/compact.h \
- caml/fail.h caml/finalise.h caml/roots.h caml/memory.h caml/gc.h \
- caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \
+memory.d.$(O): memory.c caml/address_class.h caml/config.h caml/m.h caml/s.h \
+ caml/misc.h caml/mlvalues.h caml/fail.h caml/freelist.h caml/gc.h \
+ caml/gc_ctrl.h caml/major_gc.h caml/memory.h caml/minor_gc.h \
caml/signals.h
-fix_code.i.o: fix_code.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/debugger.h caml/misc.h caml/mlvalues.h \
- caml/fix_code.h caml/instruct.h caml/intext.h caml/io.h caml/md5.h \
+meta.d.$(O): meta.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/fail.h caml/fix_code.h caml/interp.h \
+ caml/intext.h caml/io.h caml/major_gc.h caml/freelist.h caml/memory.h \
+ caml/gc.h caml/minor_gc.h caml/address_class.h caml/prims.h \
+ caml/stacks.h
+minor_gc.d.$(O): minor_gc.c caml/custom.h caml/mlvalues.h caml/config.h \
+ caml/m.h caml/s.h caml/misc.h caml/fail.h caml/finalise.h caml/roots.h \
caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/reverse.h
-floats.i.o: floats.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/reverse.h caml/stacks.h
-freelist.i.o: freelist.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/freelist.h caml/misc.h caml/mlvalues.h \
- caml/gc.h caml/gc_ctrl.h caml/memory.h caml/major_gc.h caml/minor_gc.h \
- caml/address_class.h
-gc_ctrl.i.o: gc_ctrl.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/backtrace.h caml/exec.h caml/compact.h caml/custom.h caml/fail.h \
- caml/finalise.h caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h \
- caml/freelist.h caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h \
- caml/signals.h caml/stacks.h caml/startup_aux.h
-globroots.i.o: globroots.c caml/memory.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/gc.h caml/mlvalues.h \
- caml/misc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
- caml/address_class.h caml/roots.h caml/globroots.h
-hash.i.o: hash.c caml/mlvalues.h caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/misc.h caml/custom.h caml/memory.h \
- caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
- caml/address_class.h caml/hash.h
-instrtrace.i.o: instrtrace.c
-intern.i.o: intern.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/callback.h caml/custom.h caml/fail.h caml/gc.h caml/intext.h \
- caml/io.h caml/md5.h caml/memory.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/reverse.h
-interp.i.o: interp.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/backtrace.h caml/exec.h caml/callback.h caml/debugger.h \
- caml/fail.h caml/fix_code.h caml/instrtrace.h caml/instruct.h \
- caml/interp.h caml/major_gc.h caml/freelist.h caml/memory.h caml/gc.h \
- caml/minor_gc.h caml/address_class.h caml/prims.h caml/signals.h \
- caml/stacks.h caml/startup_aux.h caml/jumptbl.h
-ints.i.o: ints.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/custom.h caml/fail.h caml/intext.h caml/io.h caml/memory.h \
+ caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h caml/signals.h \
+ caml/weak.h
+misc.d.$(O): misc.c caml/config.h caml/m.h caml/s.h caml/misc.h caml/memory.h \
+ caml/gc.h caml/mlvalues.h caml/major_gc.h caml/freelist.h \
+ caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/version.h
+obj.d.$(O): obj.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/fail.h caml/gc.h caml/interp.h caml/major_gc.h \
+ caml/freelist.h caml/memory.h caml/minor_gc.h caml/address_class.h \
+ caml/prims.h caml/spacetime.h
+parsing.d.$(O): parsing.c caml/config.h caml/m.h caml/s.h caml/mlvalues.h \
+ caml/misc.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
+ caml/minor_gc.h caml/address_class.h caml/alloc.h
+prims.d.$(O): prims.c caml/mlvalues.h caml/config.h caml/m.h caml/s.h \
+ caml/misc.h caml/prims.h
+printexc.d.$(O): printexc.c caml/backtrace.h caml/mlvalues.h caml/config.h \
+ caml/m.h caml/s.h caml/misc.h caml/exec.h caml/callback.h \
+ caml/debugger.h caml/fail.h caml/printexc.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h
+roots.d.$(O): roots.c caml/finalise.h caml/roots.h caml/misc.h caml/config.h \
+ caml/m.h caml/s.h caml/memory.h caml/gc.h caml/mlvalues.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \
+ caml/globroots.h caml/stacks.h
+signals.d.$(O): signals.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/callback.h caml/fail.h caml/memory.h \
caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
- caml/address_class.h
-io.i.o: io.c caml/config.h caml/../../config/m.h caml/../../config/s.h \
- caml/alloc.h caml/misc.h caml/mlvalues.h caml/custom.h caml/fail.h \
- caml/io.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/signals.h \
- caml/sys.h
-lexing.i.o: lexing.c caml/fail.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/stacks.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
+ caml/address_class.h caml/roots.h caml/signals.h \
+ caml/signals_machdep.h caml/sys.h
+signals_byt.d.$(O): signals_byt.c caml/config.h caml/m.h caml/s.h \
+ caml/memory.h caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h \
+ caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \
+ caml/signals.h caml/signals_machdep.h
+spacetime.d.$(O): spacetime.c caml/fail.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h
+stacks.d.$(O): stacks.c caml/config.h caml/m.h caml/s.h caml/fail.h \
+ caml/misc.h caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h
+startup.d.$(O): startup.c caml/config.h caml/m.h caml/s.h caml/alloc.h \
+ caml/misc.h caml/mlvalues.h caml/backtrace.h caml/exec.h \
+ caml/callback.h caml/custom.h caml/debugger.h caml/dynlink.h \
+ caml/fail.h caml/fix_code.h caml/freelist.h caml/gc_ctrl.h \
+ caml/instrtrace.h caml/interp.h caml/intext.h caml/io.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/minor_gc.h caml/address_class.h \
+ caml/osdeps.h caml/prims.h caml/printexc.h caml/reverse.h \
+ caml/signals.h caml/stacks.h caml/sys.h caml/startup.h \
+ caml/startup_aux.h caml/version.h
+startup_aux.d.$(O): startup_aux.c caml/backtrace.h caml/mlvalues.h \
+ caml/config.h caml/m.h caml/s.h caml/misc.h caml/exec.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
+ caml/address_class.h caml/callback.h caml/dynlink.h caml/osdeps.h \
+ caml/startup_aux.h
+str.d.$(O): str.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \
+ caml/freelist.h caml/minor_gc.h caml/address_class.h
+sys.d.$(O): sys.c caml/config.h caml/m.h caml/s.h caml/alloc.h caml/misc.h \
+ caml/mlvalues.h caml/debugger.h caml/fail.h caml/gc_ctrl.h caml/io.h \
+ caml/osdeps.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
+ caml/minor_gc.h caml/address_class.h caml/signals.h caml/stacks.h \
+ caml/sys.h caml/version.h caml/callback.h caml/startup_aux.h
+terminfo.d.$(O): terminfo.c caml/config.h caml/m.h caml/s.h caml/alloc.h \
+ caml/misc.h caml/mlvalues.h caml/fail.h caml/io.h
+unix.d.$(O): unix.c caml/config.h caml/m.h caml/s.h caml/fail.h caml/misc.h \
+ caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \
+ caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \
+ caml/signals.h caml/sys.h caml/io.h caml/alloc.h
+weak.d.$(O): weak.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/fail.h caml/major_gc.h caml/freelist.h \
+ caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \
+ caml/weak.h
+afl.i.$(O): afl.c caml/config.h caml/m.h caml/s.h caml/misc.h caml/mlvalues.h \
+ caml/osdeps.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
caml/minor_gc.h caml/address_class.h
-main.i.o: main.c caml/misc.h caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/mlvalues.h caml/sys.h
-major_gc.i.o: major_gc.c caml/compact.h caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/misc.h caml/mlvalues.h caml/custom.h \
- caml/fail.h caml/finalise.h caml/roots.h caml/memory.h caml/gc.h \
- caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \
- caml/gc_ctrl.h caml/signals.h caml/weak.h
-md5.i.o: md5.c caml/alloc.h caml/misc.h caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/mlvalues.h caml/fail.h caml/md5.h caml/io.h \
+alloc.i.$(O): alloc.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/custom.h caml/major_gc.h caml/freelist.h \
+ caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \
+ caml/stacks.h
+array.i.$(O): array.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \
+ caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h \
+ caml/spacetime.h
+backtrace.i.$(O): backtrace.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \
+ caml/freelist.h caml/minor_gc.h caml/address_class.h caml/backtrace.h \
+ caml/exec.h caml/backtrace_prim.h caml/fail.h
+backtrace_prim.i.$(O): backtrace_prim.c caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/misc.h caml/alloc.h caml/custom.h caml/io.h \
+ caml/instruct.h caml/intext.h caml/exec.h caml/fix_code.h \
caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/reverse.h
-memory.i.o: memory.c caml/address_class.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/misc.h \
- caml/mlvalues.h caml/fail.h caml/freelist.h caml/gc.h caml/gc_ctrl.h \
- caml/major_gc.h caml/memory.h caml/minor_gc.h caml/signals.h
-meta.i.o: meta.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/fail.h caml/fix_code.h caml/interp.h caml/intext.h caml/io.h \
- caml/major_gc.h caml/freelist.h caml/memory.h caml/gc.h \
- caml/minor_gc.h caml/address_class.h caml/prims.h caml/stacks.h
-minor_gc.i.o: minor_gc.c caml/custom.h caml/mlvalues.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/fail.h \
+ caml/minor_gc.h caml/address_class.h caml/startup.h caml/stacks.h \
+ caml/sys.h caml/backtrace.h caml/fail.h caml/backtrace_prim.h
+bigarray.i.$(O): bigarray.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/bigarray.h caml/custom.h caml/fail.h \
+ caml/intext.h caml/io.h caml/hash.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h
+callback.i.$(O): callback.c caml/callback.h caml/mlvalues.h caml/config.h \
+ caml/m.h caml/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \
+ caml/interp.h caml/instruct.h caml/fix_code.h caml/stacks.h
+compact.i.$(O): compact.c caml/address_class.h caml/config.h caml/m.h caml/s.h \
+ caml/misc.h caml/mlvalues.h caml/finalise.h caml/roots.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
+ caml/gc_ctrl.h caml/weak.h caml/compact.h
+compare.i.$(O): compare.c caml/custom.h caml/mlvalues.h caml/config.h caml/m.h \
+ caml/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h
+custom.i.$(O): custom.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/custom.h caml/fail.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
+ caml/address_class.h
+debugger.i.$(O): debugger.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/debugger.h caml/osdeps.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
+ caml/address_class.h caml/fail.h caml/fix_code.h caml/instruct.h \
+ caml/intext.h caml/io.h caml/stacks.h caml/sys.h
+dynlink.i.$(O): dynlink.c caml/config.h caml/m.h caml/s.h caml/alloc.h \
+ caml/misc.h caml/mlvalues.h caml/dynlink.h caml/fail.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
+ caml/address_class.h caml/osdeps.h caml/prims.h caml/signals.h
+extern.i.$(O): extern.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/custom.h caml/fail.h caml/gc.h \
+ caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/major_gc.h \
+ caml/freelist.h caml/minor_gc.h caml/address_class.h caml/reverse.h
+fail.i.$(O): fail.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/fail.h caml/io.h caml/gc.h caml/memory.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \
+ caml/printexc.h caml/signals.h caml/stacks.h
+finalise.i.$(O): finalise.c caml/callback.h caml/mlvalues.h caml/config.h \
+ caml/m.h caml/s.h caml/misc.h caml/compact.h caml/fail.h \
caml/finalise.h caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h \
- caml/freelist.h caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h \
- caml/signals.h caml/weak.h
-misc.i.o: misc.c caml/config.h caml/../../config/m.h caml/../../config/s.h \
- caml/misc.h caml/memory.h caml/gc.h caml/mlvalues.h caml/major_gc.h \
- caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \
- caml/version.h
-obj.i.o: obj.c caml/alloc.h caml/misc.h caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/mlvalues.h caml/fail.h caml/gc.h \
- caml/interp.h caml/major_gc.h caml/freelist.h caml/memory.h \
- caml/minor_gc.h caml/address_class.h caml/prims.h caml/spacetime.h
-parsing.i.o: parsing.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/mlvalues.h caml/misc.h caml/memory.h \
- caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
- caml/address_class.h caml/alloc.h
-prims.i.o: prims.c caml/mlvalues.h caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/misc.h caml/prims.h
-printexc.i.o: printexc.c caml/backtrace.h caml/mlvalues.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/exec.h \
- caml/callback.h caml/debugger.h caml/fail.h caml/printexc.h
-roots.i.o: roots.c caml/finalise.h caml/roots.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/memory.h caml/gc.h \
- caml/mlvalues.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
- caml/address_class.h caml/globroots.h caml/stacks.h
-signals.i.o: signals.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/callback.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \
- caml/freelist.h caml/minor_gc.h caml/address_class.h caml/roots.h \
- caml/signals.h caml/signals_machdep.h caml/sys.h
-signals_byt.i.o: signals_byt.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/memory.h caml/gc.h caml/mlvalues.h \
- caml/misc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
- caml/address_class.h caml/osdeps.h caml/signals.h \
- caml/signals_machdep.h
-spacetime.i.o: spacetime.c caml/fail.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h
-stacks.i.o: stacks.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/fail.h caml/misc.h caml/mlvalues.h \
- caml/stacks.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h
-startup.i.o: startup.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/alloc.h caml/misc.h caml/mlvalues.h \
- caml/backtrace.h caml/exec.h caml/callback.h caml/custom.h \
- caml/debugger.h caml/dynlink.h caml/fail.h caml/fix_code.h \
- caml/freelist.h caml/gc_ctrl.h caml/instrtrace.h caml/interp.h \
- caml/intext.h caml/io.h caml/memory.h caml/gc.h caml/major_gc.h \
- caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/prims.h \
- caml/printexc.h caml/reverse.h caml/signals.h caml/stacks.h caml/sys.h \
- caml/startup.h caml/startup_aux.h caml/version.h
-startup_aux.i.o: startup_aux.c caml/backtrace.h caml/mlvalues.h \
- caml/config.h caml/../../config/m.h caml/../../config/s.h caml/misc.h \
- caml/exec.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/startup_aux.h
-str.i.o: str.c caml/alloc.h caml/misc.h caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/mlvalues.h caml/fail.h
-sys.i.o: sys.c caml/config.h caml/../../config/m.h caml/../../config/s.h \
- caml/alloc.h caml/misc.h caml/mlvalues.h caml/debugger.h caml/fail.h \
- caml/gc_ctrl.h caml/instruct.h caml/io.h caml/osdeps.h caml/signals.h \
- caml/stacks.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/sys.h caml/version.h
-terminfo.i.o: terminfo.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/alloc.h caml/misc.h caml/mlvalues.h \
- caml/fail.h caml/io.h
-unix.i.o: unix.c caml/config.h caml/../../config/m.h caml/../../config/s.h \
- caml/fail.h caml/misc.h caml/mlvalues.h caml/memory.h caml/gc.h \
+ caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h
+fix_code.i.$(O): fix_code.c caml/config.h caml/m.h caml/s.h caml/debugger.h \
+ caml/misc.h caml/mlvalues.h caml/fix_code.h caml/instruct.h \
+ caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/gc.h \
caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \
- caml/osdeps.h caml/signals.h caml/sys.h caml/io.h
-weak.i.o: weak.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/fail.h caml/major_gc.h caml/freelist.h caml/memory.h caml/gc.h \
- caml/minor_gc.h caml/address_class.h caml/weak.h
-afl.pic.o: afl.c caml/misc.h caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/mlvalues.h caml/osdeps.h
-alloc.pic.o: alloc.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/custom.h caml/major_gc.h caml/freelist.h caml/memory.h caml/gc.h \
- caml/minor_gc.h caml/address_class.h caml/stacks.h
-array.pic.o: array.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/signals.h caml/spacetime.h
-backtrace.pic.o: backtrace.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/backtrace.h caml/exec.h \
- caml/backtrace_prim.h caml/fail.h
-backtrace_prim.pic.o: backtrace_prim.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/mlvalues.h caml/misc.h caml/alloc.h \
- caml/custom.h caml/io.h caml/instruct.h caml/intext.h caml/exec.h \
- caml/fix_code.h caml/memory.h caml/gc.h caml/major_gc.h \
- caml/freelist.h caml/minor_gc.h caml/address_class.h caml/startup.h \
- caml/stacks.h caml/sys.h caml/backtrace.h caml/fail.h \
- caml/backtrace_prim.h
-callback.pic.o: callback.c caml/callback.h caml/mlvalues.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/fail.h \
- caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/interp.h caml/instruct.h \
- caml/fix_code.h caml/stacks.h
-compact.pic.o: compact.c caml/address_class.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/misc.h \
- caml/mlvalues.h caml/finalise.h caml/roots.h caml/memory.h caml/gc.h \
- caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/gc_ctrl.h \
- caml/weak.h caml/compact.h
-compare.pic.o: compare.c caml/custom.h caml/mlvalues.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/fail.h \
+ caml/reverse.h
+floats.i.$(O): floats.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \
+ caml/reverse.h caml/stacks.h
+freelist.i.$(O): freelist.c caml/config.h caml/m.h caml/s.h caml/freelist.h \
+ caml/misc.h caml/mlvalues.h caml/gc.h caml/gc_ctrl.h caml/memory.h \
+ caml/major_gc.h caml/minor_gc.h caml/address_class.h
+gc_ctrl.i.$(O): gc_ctrl.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h caml/compact.h \
+ caml/custom.h caml/fail.h caml/finalise.h caml/roots.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
+ caml/address_class.h caml/gc_ctrl.h caml/signals.h caml/stacks.h \
+ caml/startup_aux.h
+globroots.i.$(O): globroots.c caml/memory.h caml/config.h caml/m.h caml/s.h \
+ caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h caml/freelist.h \
+ caml/minor_gc.h caml/address_class.h caml/roots.h caml/globroots.h
+hash.i.$(O): hash.c caml/mlvalues.h caml/config.h caml/m.h caml/s.h \
+ caml/misc.h caml/custom.h caml/memory.h caml/gc.h caml/major_gc.h \
+ caml/freelist.h caml/minor_gc.h caml/address_class.h caml/hash.h
+instrtrace.i.$(O): instrtrace.c
+intern.i.$(O): intern.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/callback.h caml/custom.h caml/fail.h \
+ caml/gc.h caml/intext.h caml/io.h caml/md5.h caml/memory.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \
+ caml/reverse.h
+interp.i.$(O): interp.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h caml/callback.h \
+ caml/debugger.h caml/fail.h caml/fix_code.h caml/instrtrace.h \
+ caml/instruct.h caml/interp.h caml/major_gc.h caml/freelist.h \
+ caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \
+ caml/prims.h caml/signals.h caml/stacks.h caml/startup_aux.h \
+ caml/jumptbl.h
+ints.i.$(O): ints.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/custom.h caml/fail.h caml/intext.h caml/io.h \
caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
caml/minor_gc.h caml/address_class.h
-custom.pic.o: custom.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/custom.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \
- caml/freelist.h caml/minor_gc.h caml/address_class.h
-debugger.pic.o: debugger.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/debugger.h caml/osdeps.h caml/fail.h caml/fix_code.h \
- caml/instruct.h caml/intext.h caml/io.h caml/stacks.h caml/memory.h \
- caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
- caml/address_class.h caml/sys.h
-dynlink.pic.o: dynlink.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/alloc.h caml/misc.h caml/mlvalues.h \
- caml/dynlink.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \
- caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \
- caml/prims.h caml/signals.h
-extern.pic.o: extern.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/custom.h caml/fail.h caml/gc.h caml/intext.h caml/io.h caml/md5.h \
- caml/memory.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
+io.i.$(O): io.c caml/config.h caml/m.h caml/s.h caml/alloc.h caml/misc.h \
+ caml/mlvalues.h caml/custom.h caml/fail.h caml/io.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
+ caml/address_class.h caml/osdeps.h caml/signals.h caml/sys.h
+lexing.i.$(O): lexing.c caml/fail.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h
+main.i.$(O): main.c caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/sys.h caml/osdeps.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h
+major_gc.i.$(O): major_gc.c caml/compact.h caml/config.h caml/m.h caml/s.h \
+ caml/misc.h caml/mlvalues.h caml/custom.h caml/fail.h caml/finalise.h \
+ caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
+ caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h caml/signals.h \
+ caml/weak.h
+md5.i.$(O): md5.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/fail.h caml/md5.h caml/io.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
caml/address_class.h caml/reverse.h
-fail.pic.o: fail.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/fail.h caml/io.h caml/gc.h caml/memory.h caml/major_gc.h \
- caml/freelist.h caml/minor_gc.h caml/address_class.h caml/printexc.h \
- caml/signals.h caml/stacks.h
-finalise.pic.o: finalise.c caml/callback.h caml/mlvalues.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/compact.h \
- caml/fail.h caml/finalise.h caml/roots.h caml/memory.h caml/gc.h \
- caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \
+memory.i.$(O): memory.c caml/address_class.h caml/config.h caml/m.h caml/s.h \
+ caml/misc.h caml/mlvalues.h caml/fail.h caml/freelist.h caml/gc.h \
+ caml/gc_ctrl.h caml/major_gc.h caml/memory.h caml/minor_gc.h \
caml/signals.h
-fix_code.pic.o: fix_code.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/debugger.h caml/misc.h caml/mlvalues.h \
- caml/fix_code.h caml/instruct.h caml/intext.h caml/io.h caml/md5.h \
+meta.i.$(O): meta.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/fail.h caml/fix_code.h caml/interp.h \
+ caml/intext.h caml/io.h caml/major_gc.h caml/freelist.h caml/memory.h \
+ caml/gc.h caml/minor_gc.h caml/address_class.h caml/prims.h \
+ caml/stacks.h
+minor_gc.i.$(O): minor_gc.c caml/custom.h caml/mlvalues.h caml/config.h \
+ caml/m.h caml/s.h caml/misc.h caml/fail.h caml/finalise.h caml/roots.h \
caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/reverse.h
-floats.pic.o: floats.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/reverse.h caml/stacks.h
-freelist.pic.o: freelist.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/freelist.h caml/misc.h caml/mlvalues.h \
- caml/gc.h caml/gc_ctrl.h caml/memory.h caml/major_gc.h caml/minor_gc.h \
+ caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h caml/signals.h \
+ caml/weak.h
+misc.i.$(O): misc.c caml/config.h caml/m.h caml/s.h caml/misc.h caml/memory.h \
+ caml/gc.h caml/mlvalues.h caml/major_gc.h caml/freelist.h \
+ caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/version.h
+obj.i.$(O): obj.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/fail.h caml/gc.h caml/interp.h caml/major_gc.h \
+ caml/freelist.h caml/memory.h caml/minor_gc.h caml/address_class.h \
+ caml/prims.h caml/spacetime.h
+parsing.i.$(O): parsing.c caml/config.h caml/m.h caml/s.h caml/mlvalues.h \
+ caml/misc.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
+ caml/minor_gc.h caml/address_class.h caml/alloc.h
+prims.i.$(O): prims.c caml/mlvalues.h caml/config.h caml/m.h caml/s.h \
+ caml/misc.h caml/prims.h
+printexc.i.$(O): printexc.c caml/backtrace.h caml/mlvalues.h caml/config.h \
+ caml/m.h caml/s.h caml/misc.h caml/exec.h caml/callback.h \
+ caml/debugger.h caml/fail.h caml/printexc.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h
+roots.i.$(O): roots.c caml/finalise.h caml/roots.h caml/misc.h caml/config.h \
+ caml/m.h caml/s.h caml/memory.h caml/gc.h caml/mlvalues.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \
+ caml/globroots.h caml/stacks.h
+signals.i.$(O): signals.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/callback.h caml/fail.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
+ caml/address_class.h caml/roots.h caml/signals.h \
+ caml/signals_machdep.h caml/sys.h
+signals_byt.i.$(O): signals_byt.c caml/config.h caml/m.h caml/s.h \
+ caml/memory.h caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h \
+ caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \
+ caml/signals.h caml/signals_machdep.h
+spacetime.i.$(O): spacetime.c caml/fail.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h
+stacks.i.$(O): stacks.c caml/config.h caml/m.h caml/s.h caml/fail.h \
+ caml/misc.h caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h
+startup.i.$(O): startup.c caml/config.h caml/m.h caml/s.h caml/alloc.h \
+ caml/misc.h caml/mlvalues.h caml/backtrace.h caml/exec.h \
+ caml/callback.h caml/custom.h caml/debugger.h caml/dynlink.h \
+ caml/fail.h caml/fix_code.h caml/freelist.h caml/gc_ctrl.h \
+ caml/instrtrace.h caml/interp.h caml/intext.h caml/io.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/minor_gc.h caml/address_class.h \
+ caml/osdeps.h caml/prims.h caml/printexc.h caml/reverse.h \
+ caml/signals.h caml/stacks.h caml/sys.h caml/startup.h \
+ caml/startup_aux.h caml/version.h
+startup_aux.i.$(O): startup_aux.c caml/backtrace.h caml/mlvalues.h \
+ caml/config.h caml/m.h caml/s.h caml/misc.h caml/exec.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
+ caml/address_class.h caml/callback.h caml/dynlink.h caml/osdeps.h \
+ caml/startup_aux.h
+str.i.$(O): str.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \
+ caml/freelist.h caml/minor_gc.h caml/address_class.h
+sys.i.$(O): sys.c caml/config.h caml/m.h caml/s.h caml/alloc.h caml/misc.h \
+ caml/mlvalues.h caml/debugger.h caml/fail.h caml/gc_ctrl.h caml/io.h \
+ caml/osdeps.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
+ caml/minor_gc.h caml/address_class.h caml/signals.h caml/stacks.h \
+ caml/sys.h caml/version.h caml/callback.h caml/startup_aux.h
+terminfo.i.$(O): terminfo.c caml/config.h caml/m.h caml/s.h caml/alloc.h \
+ caml/misc.h caml/mlvalues.h caml/fail.h caml/io.h
+unix.i.$(O): unix.c caml/config.h caml/m.h caml/s.h caml/fail.h caml/misc.h \
+ caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \
+ caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \
+ caml/signals.h caml/sys.h caml/io.h caml/alloc.h
+weak.i.$(O): weak.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/fail.h caml/major_gc.h caml/freelist.h \
+ caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \
+ caml/weak.h
+afl.pic.$(O): afl.c caml/config.h caml/m.h caml/s.h caml/misc.h caml/mlvalues.h \
+ caml/osdeps.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
+ caml/minor_gc.h caml/address_class.h
+alloc.pic.$(O): alloc.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/custom.h caml/major_gc.h caml/freelist.h \
+ caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \
+ caml/stacks.h
+array.pic.$(O): array.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \
+ caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h \
+ caml/spacetime.h
+backtrace.pic.$(O): backtrace.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \
+ caml/freelist.h caml/minor_gc.h caml/address_class.h caml/backtrace.h \
+ caml/exec.h caml/backtrace_prim.h caml/fail.h
+backtrace_prim.pic.$(O): backtrace_prim.c caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/misc.h caml/alloc.h caml/custom.h caml/io.h \
+ caml/instruct.h caml/intext.h caml/exec.h caml/fix_code.h \
+ caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
+ caml/minor_gc.h caml/address_class.h caml/startup.h caml/stacks.h \
+ caml/sys.h caml/backtrace.h caml/fail.h caml/backtrace_prim.h
+bigarray.pic.$(O): bigarray.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/bigarray.h caml/custom.h caml/fail.h \
+ caml/intext.h caml/io.h caml/hash.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h
+callback.pic.$(O): callback.c caml/callback.h caml/mlvalues.h caml/config.h \
+ caml/m.h caml/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \
+ caml/interp.h caml/instruct.h caml/fix_code.h caml/stacks.h
+compact.pic.$(O): compact.c caml/address_class.h caml/config.h caml/m.h caml/s.h \
+ caml/misc.h caml/mlvalues.h caml/finalise.h caml/roots.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
+ caml/gc_ctrl.h caml/weak.h caml/compact.h
+compare.pic.$(O): compare.c caml/custom.h caml/mlvalues.h caml/config.h caml/m.h \
+ caml/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h
+custom.pic.$(O): custom.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/custom.h caml/fail.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
caml/address_class.h
-gc_ctrl.pic.o: gc_ctrl.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/backtrace.h caml/exec.h caml/compact.h caml/custom.h caml/fail.h \
+debugger.pic.$(O): debugger.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/debugger.h caml/osdeps.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
+ caml/address_class.h caml/fail.h caml/fix_code.h caml/instruct.h \
+ caml/intext.h caml/io.h caml/stacks.h caml/sys.h
+dynlink.pic.$(O): dynlink.c caml/config.h caml/m.h caml/s.h caml/alloc.h \
+ caml/misc.h caml/mlvalues.h caml/dynlink.h caml/fail.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
+ caml/address_class.h caml/osdeps.h caml/prims.h caml/signals.h
+extern.pic.$(O): extern.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/custom.h caml/fail.h caml/gc.h \
+ caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/major_gc.h \
+ caml/freelist.h caml/minor_gc.h caml/address_class.h caml/reverse.h
+fail.pic.$(O): fail.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/fail.h caml/io.h caml/gc.h caml/memory.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \
+ caml/printexc.h caml/signals.h caml/stacks.h
+finalise.pic.$(O): finalise.c caml/callback.h caml/mlvalues.h caml/config.h \
+ caml/m.h caml/s.h caml/misc.h caml/compact.h caml/fail.h \
caml/finalise.h caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h \
- caml/freelist.h caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h \
- caml/signals.h caml/stacks.h caml/startup_aux.h
-globroots.pic.o: globroots.c caml/memory.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/gc.h caml/mlvalues.h \
- caml/misc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
- caml/address_class.h caml/roots.h caml/globroots.h
-hash.pic.o: hash.c caml/mlvalues.h caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/misc.h caml/custom.h caml/memory.h \
- caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
- caml/address_class.h caml/hash.h
-instrtrace.pic.o: instrtrace.c
-intern.pic.o: intern.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/callback.h caml/custom.h caml/fail.h caml/gc.h caml/intext.h \
- caml/io.h caml/md5.h caml/memory.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/reverse.h
-interp.pic.o: interp.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/backtrace.h caml/exec.h caml/callback.h caml/debugger.h \
- caml/fail.h caml/fix_code.h caml/instrtrace.h caml/instruct.h \
- caml/interp.h caml/major_gc.h caml/freelist.h caml/memory.h caml/gc.h \
- caml/minor_gc.h caml/address_class.h caml/prims.h caml/signals.h \
- caml/stacks.h caml/startup_aux.h caml/jumptbl.h
-ints.pic.o: ints.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/custom.h caml/fail.h caml/intext.h caml/io.h caml/memory.h \
+ caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h
+fix_code.pic.$(O): fix_code.c caml/config.h caml/m.h caml/s.h caml/debugger.h \
+ caml/misc.h caml/mlvalues.h caml/fix_code.h caml/instruct.h \
+ caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \
+ caml/reverse.h
+floats.pic.$(O): floats.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \
+ caml/reverse.h caml/stacks.h
+freelist.pic.$(O): freelist.c caml/config.h caml/m.h caml/s.h caml/freelist.h \
+ caml/misc.h caml/mlvalues.h caml/gc.h caml/gc_ctrl.h caml/memory.h \
+ caml/major_gc.h caml/minor_gc.h caml/address_class.h
+gc_ctrl.pic.$(O): gc_ctrl.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h caml/compact.h \
+ caml/custom.h caml/fail.h caml/finalise.h caml/roots.h caml/memory.h \
caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
- caml/address_class.h
-io.pic.o: io.c caml/config.h caml/../../config/m.h caml/../../config/s.h \
- caml/alloc.h caml/misc.h caml/mlvalues.h caml/custom.h caml/fail.h \
- caml/io.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/signals.h \
- caml/sys.h
-lexing.pic.o: lexing.c caml/fail.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/stacks.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h
-main.pic.o: main.c caml/misc.h caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/mlvalues.h caml/sys.h
-major_gc.pic.o: major_gc.c caml/compact.h caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/misc.h caml/mlvalues.h caml/custom.h \
- caml/fail.h caml/finalise.h caml/roots.h caml/memory.h caml/gc.h \
+ caml/address_class.h caml/gc_ctrl.h caml/signals.h caml/stacks.h \
+ caml/startup_aux.h
+globroots.pic.$(O): globroots.c caml/memory.h caml/config.h caml/m.h caml/s.h \
+ caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h caml/freelist.h \
+ caml/minor_gc.h caml/address_class.h caml/roots.h caml/globroots.h
+hash.pic.$(O): hash.c caml/mlvalues.h caml/config.h caml/m.h caml/s.h \
+ caml/misc.h caml/custom.h caml/memory.h caml/gc.h caml/major_gc.h \
+ caml/freelist.h caml/minor_gc.h caml/address_class.h caml/hash.h
+instrtrace.pic.$(O): instrtrace.c
+intern.pic.$(O): intern.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/callback.h caml/custom.h caml/fail.h \
+ caml/gc.h caml/intext.h caml/io.h caml/md5.h caml/memory.h \
caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \
- caml/gc_ctrl.h caml/signals.h caml/weak.h
-md5.pic.o: md5.c caml/alloc.h caml/misc.h caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/mlvalues.h caml/fail.h caml/md5.h caml/io.h \
+ caml/reverse.h
+interp.pic.$(O): interp.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h caml/callback.h \
+ caml/debugger.h caml/fail.h caml/fix_code.h caml/instrtrace.h \
+ caml/instruct.h caml/interp.h caml/major_gc.h caml/freelist.h \
+ caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \
+ caml/prims.h caml/signals.h caml/stacks.h caml/startup_aux.h \
+ caml/jumptbl.h
+ints.pic.$(O): ints.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/custom.h caml/fail.h caml/intext.h caml/io.h \
caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/reverse.h
-memory.pic.o: memory.c caml/address_class.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/misc.h \
- caml/mlvalues.h caml/fail.h caml/freelist.h caml/gc.h caml/gc_ctrl.h \
- caml/major_gc.h caml/memory.h caml/minor_gc.h caml/signals.h
-meta.pic.o: meta.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/fail.h caml/fix_code.h caml/interp.h caml/intext.h caml/io.h \
- caml/major_gc.h caml/freelist.h caml/memory.h caml/gc.h \
- caml/minor_gc.h caml/address_class.h caml/prims.h caml/stacks.h
-minor_gc.pic.o: minor_gc.c caml/custom.h caml/mlvalues.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/fail.h \
- caml/finalise.h caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h \
- caml/freelist.h caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h \
- caml/signals.h caml/weak.h
-misc.pic.o: misc.c caml/config.h caml/../../config/m.h caml/../../config/s.h \
- caml/misc.h caml/memory.h caml/gc.h caml/mlvalues.h caml/major_gc.h \
- caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \
- caml/version.h
-obj.pic.o: obj.c caml/alloc.h caml/misc.h caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/mlvalues.h caml/fail.h caml/gc.h \
- caml/interp.h caml/major_gc.h caml/freelist.h caml/memory.h \
- caml/minor_gc.h caml/address_class.h caml/prims.h caml/spacetime.h
-parsing.pic.o: parsing.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/mlvalues.h caml/misc.h caml/memory.h \
- caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
- caml/address_class.h caml/alloc.h
-prims.pic.o: prims.c caml/mlvalues.h caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/misc.h caml/prims.h
-printexc.pic.o: printexc.c caml/backtrace.h caml/mlvalues.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/misc.h caml/exec.h \
- caml/callback.h caml/debugger.h caml/fail.h caml/printexc.h
-roots.pic.o: roots.c caml/finalise.h caml/roots.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/memory.h caml/gc.h \
- caml/mlvalues.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
- caml/address_class.h caml/globroots.h caml/stacks.h
-signals.pic.o: signals.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/callback.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \
- caml/freelist.h caml/minor_gc.h caml/address_class.h caml/roots.h \
- caml/signals.h caml/signals_machdep.h caml/sys.h
-signals_byt.pic.o: signals_byt.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/memory.h caml/gc.h caml/mlvalues.h \
- caml/misc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
- caml/address_class.h caml/osdeps.h caml/signals.h \
- caml/signals_machdep.h
-spacetime.pic.o: spacetime.c caml/fail.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h
-stacks.pic.o: stacks.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/fail.h caml/misc.h caml/mlvalues.h \
- caml/stacks.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
caml/minor_gc.h caml/address_class.h
-startup.pic.o: startup.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/alloc.h caml/misc.h caml/mlvalues.h \
- caml/backtrace.h caml/exec.h caml/callback.h caml/custom.h \
- caml/debugger.h caml/dynlink.h caml/fail.h caml/fix_code.h \
- caml/freelist.h caml/gc_ctrl.h caml/instrtrace.h caml/interp.h \
- caml/intext.h caml/io.h caml/memory.h caml/gc.h caml/major_gc.h \
- caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/prims.h \
- caml/printexc.h caml/reverse.h caml/signals.h caml/stacks.h caml/sys.h \
- caml/startup.h caml/startup_aux.h caml/version.h
-startup_aux.pic.o: startup_aux.c caml/backtrace.h caml/mlvalues.h \
- caml/config.h caml/../../config/m.h caml/../../config/s.h caml/misc.h \
- caml/exec.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/startup_aux.h
-str.pic.o: str.c caml/alloc.h caml/misc.h caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/mlvalues.h caml/fail.h
-sys.pic.o: sys.c caml/config.h caml/../../config/m.h caml/../../config/s.h \
- caml/alloc.h caml/misc.h caml/mlvalues.h caml/debugger.h caml/fail.h \
- caml/gc_ctrl.h caml/instruct.h caml/io.h caml/osdeps.h caml/signals.h \
- caml/stacks.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
- caml/minor_gc.h caml/address_class.h caml/sys.h caml/version.h
-terminfo.pic.o: terminfo.c caml/config.h caml/../../config/m.h \
- caml/../../config/s.h caml/alloc.h caml/misc.h caml/mlvalues.h \
- caml/fail.h caml/io.h
-unix.pic.o: unix.c caml/config.h caml/../../config/m.h caml/../../config/s.h \
- caml/fail.h caml/misc.h caml/mlvalues.h caml/memory.h caml/gc.h \
+io.pic.$(O): io.c caml/config.h caml/m.h caml/s.h caml/alloc.h caml/misc.h \
+ caml/mlvalues.h caml/custom.h caml/fail.h caml/io.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
+ caml/address_class.h caml/osdeps.h caml/signals.h caml/sys.h
+lexing.pic.$(O): lexing.c caml/fail.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h
+main.pic.$(O): main.c caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/sys.h caml/osdeps.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h
+major_gc.pic.$(O): major_gc.c caml/compact.h caml/config.h caml/m.h caml/s.h \
+ caml/misc.h caml/mlvalues.h caml/custom.h caml/fail.h caml/finalise.h \
+ caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
+ caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h caml/signals.h \
+ caml/weak.h
+md5.pic.$(O): md5.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/fail.h caml/md5.h caml/io.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
+ caml/address_class.h caml/reverse.h
+memory.pic.$(O): memory.c caml/address_class.h caml/config.h caml/m.h caml/s.h \
+ caml/misc.h caml/mlvalues.h caml/fail.h caml/freelist.h caml/gc.h \
+ caml/gc_ctrl.h caml/major_gc.h caml/memory.h caml/minor_gc.h \
+ caml/signals.h
+meta.pic.$(O): meta.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/fail.h caml/fix_code.h caml/interp.h \
+ caml/intext.h caml/io.h caml/major_gc.h caml/freelist.h caml/memory.h \
+ caml/gc.h caml/minor_gc.h caml/address_class.h caml/prims.h \
+ caml/stacks.h
+minor_gc.pic.$(O): minor_gc.c caml/custom.h caml/mlvalues.h caml/config.h \
+ caml/m.h caml/s.h caml/misc.h caml/fail.h caml/finalise.h caml/roots.h \
+ caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
+ caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h caml/signals.h \
+ caml/weak.h
+misc.pic.$(O): misc.c caml/config.h caml/m.h caml/s.h caml/misc.h caml/memory.h \
+ caml/gc.h caml/mlvalues.h caml/major_gc.h caml/freelist.h \
+ caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/version.h
+obj.pic.$(O): obj.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/fail.h caml/gc.h caml/interp.h caml/major_gc.h \
+ caml/freelist.h caml/memory.h caml/minor_gc.h caml/address_class.h \
+ caml/prims.h caml/spacetime.h
+parsing.pic.$(O): parsing.c caml/config.h caml/m.h caml/s.h caml/mlvalues.h \
+ caml/misc.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
+ caml/minor_gc.h caml/address_class.h caml/alloc.h
+prims.pic.$(O): prims.c caml/mlvalues.h caml/config.h caml/m.h caml/s.h \
+ caml/misc.h caml/prims.h
+printexc.pic.$(O): printexc.c caml/backtrace.h caml/mlvalues.h caml/config.h \
+ caml/m.h caml/s.h caml/misc.h caml/exec.h caml/callback.h \
+ caml/debugger.h caml/fail.h caml/printexc.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h
+roots.pic.$(O): roots.c caml/finalise.h caml/roots.h caml/misc.h caml/config.h \
+ caml/m.h caml/s.h caml/memory.h caml/gc.h caml/mlvalues.h \
caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \
- caml/osdeps.h caml/signals.h caml/sys.h caml/io.h
-weak.pic.o: weak.c caml/alloc.h caml/misc.h caml/config.h \
- caml/../../config/m.h caml/../../config/s.h caml/mlvalues.h \
- caml/fail.h caml/major_gc.h caml/freelist.h caml/memory.h caml/gc.h \
- caml/minor_gc.h caml/address_class.h caml/weak.h
+ caml/globroots.h caml/stacks.h
+signals.pic.$(O): signals.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h caml/callback.h caml/fail.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
+ caml/address_class.h caml/roots.h caml/signals.h \
+ caml/signals_machdep.h caml/sys.h
+signals_byt.pic.$(O): signals_byt.c caml/config.h caml/m.h caml/s.h \
+ caml/memory.h caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h \
+ caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \
+ caml/signals.h caml/signals_machdep.h
+spacetime.pic.$(O): spacetime.c caml/fail.h caml/misc.h caml/config.h caml/m.h \
+ caml/s.h caml/mlvalues.h
+stacks.pic.$(O): stacks.c caml/config.h caml/m.h caml/s.h caml/fail.h \
+ caml/misc.h caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h
+startup.pic.$(O): startup.c caml/config.h caml/m.h caml/s.h caml/alloc.h \
+ caml/misc.h caml/mlvalues.h caml/backtrace.h caml/exec.h \
+ caml/callback.h caml/custom.h caml/debugger.h caml/dynlink.h \
+ caml/fail.h caml/fix_code.h caml/freelist.h caml/gc_ctrl.h \
+ caml/instrtrace.h caml/interp.h caml/intext.h caml/io.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/minor_gc.h caml/address_class.h \
+ caml/osdeps.h caml/prims.h caml/printexc.h caml/reverse.h \
+ caml/signals.h caml/stacks.h caml/sys.h caml/startup.h \
+ caml/startup_aux.h caml/version.h
+startup_aux.pic.$(O): startup_aux.c caml/backtrace.h caml/mlvalues.h \
+ caml/config.h caml/m.h caml/s.h caml/misc.h caml/exec.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \
+ caml/address_class.h caml/callback.h caml/dynlink.h caml/osdeps.h \
+ caml/startup_aux.h
+str.pic.$(O): str.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \
+ caml/freelist.h caml/minor_gc.h caml/address_class.h
+sys.pic.$(O): sys.c caml/config.h caml/m.h caml/s.h caml/alloc.h caml/misc.h \
+ caml/mlvalues.h caml/debugger.h caml/fail.h caml/gc_ctrl.h caml/io.h \
+ caml/osdeps.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \
+ caml/minor_gc.h caml/address_class.h caml/signals.h caml/stacks.h \
+ caml/sys.h caml/version.h caml/callback.h caml/startup_aux.h
+terminfo.pic.$(O): terminfo.c caml/config.h caml/m.h caml/s.h caml/alloc.h \
+ caml/misc.h caml/mlvalues.h caml/fail.h caml/io.h
+unix.pic.$(O): unix.c caml/config.h caml/m.h caml/s.h caml/fail.h caml/misc.h \
+ caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \
+ caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \
+ caml/signals.h caml/sys.h caml/io.h caml/alloc.h
+weak.pic.$(O): weak.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \
+ caml/mlvalues.h caml/fail.h caml/major_gc.h caml/freelist.h \
+ caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \
+ caml/weak.h
INSTALL_BINDIR=$(DESTDIR)$(BINDIR)
INSTALL_LIBDIR=$(DESTDIR)$(LIBDIR)
+INSTALL_INCDIR=$(INSTALL_LIBDIR)/caml
# The PROGRAMS (resp. LIBRARIES) variable list the files to build and
# install as programs in $(INSTALL_BINDIR) (resp. libraries in
endif
endif
-CC=$(BYTECC)
-
ifdef BOOTSTRAPPING_FLEXLINK
-CFLAGS=-DBOOTSTRAPPING_FLEXLINK
-else
-CFLAGS=
+CFLAGS += -DBOOTSTRAPPING_FLEXLINK
endif
# On Windows, OCAML_STDLIB_DIR needs to be defined dynamically
ifeq "$(UNIX_OR_WIN32)" "win32"
-CFLAGS += -DOCAML_STDLIB_DIR='"$(LIBDIR)"'
+# OCAML_STDLIB_DIR needs to arrive in dynlink.c as a string which both gcc and
+# msvc are willing parse without warning. This means we can't pass UTF-8
+# directly since, as far as I can tell, cl can cope, but the pre-processor
+# can't. So the string needs to be directly translated to L"" form. To do this,
+# we take advantage of the fact that Cygwin uses GNU libiconv which includes a
+# Java pseudo-encoding which translates any UTF-8 sequences to \uXXXX (and,
+# unlike the C99 pseudo-encoding, emits two surrogate values when needed, rather
+# than \UXXXXXXXX). The \u is then translated to \x in order to accommodate
+# pre-Visual Studio 2013 compilers where \x is a non-standard alias for \u.
+OCAML_STDLIB_DIR = $(shell echo $(LIBDIR)| iconv -t JAVA | sed -e 's/\\u/\\x/g')
+CFLAGS += -DOCAML_STDLIB_DIR='L"$(OCAML_STDLIB_DIR)"'
endif
-CFLAGS += $(IFLEXDIR) $(BYTECCCOMPOPTS)
+CFLAGS += $(IFLEXDIR)
+
+ifneq "$(CCOMPTYPE)" "msvc"
+CFLAGS += -g
+endif
DFLAGS=$(CFLAGS) -DDEBUG
IFLAGS=$(CFLAGS) -DCAML_INSTR
PICFLAGS=$(CFLAGS) $(SHAREDCCCOMPOPTS)
-ifneq "$(CCOMPTYPE)" "msvc"
-DFLAGS += -g
-endif
-
-ifeq "$(CCOMPTYPE)" "msvc"
-OUTPUTOBJ=-Fo
-else
-OUTPUTOBJ=-o
-endif
DBGO=d.$(O)
ifeq "$(UNIX_OR_WIN32)" "win32"
-LIBS = $(call SYSLIB,ws2_32) $(EXTRALIBS)
+LIBS = $(BYTECCLIBS) $(EXTRALIBS)
ifdef BOOTSTRAPPING_FLEXLINK
MAKE_OCAMLRUN=$(MKEXE_BOOT)
else
endif
else
LIBS = $(BYTECCLIBS)
-MAKE_OCAMLRUN = $(MKEXE) $(BYTECCLINKOPTS) -o $(1) $(2)
+MAKE_OCAMLRUN = $(MKEXE) $(LDFLAGS) -o $(1) $(2)
endif
PRIMS=\
compare ints floats str array io extern intern \
hash sys meta parsing gc_ctrl terminfo md5 obj \
lexing callback debugger weak compact finalise custom \
- dynlink spacetime afl $(UNIX_OR_WIN32) main)
+ dynlink spacetime afl $(UNIX_OR_WIN32) bigarray main)
DOBJS=$(OBJS:.$(O)=.$(DBGO)) instrtrace.$(DBGO)
IOBJS=$(OBJS:.$(O)=.i.$(O))
install:
cp $(PROGRAMS) "$(INSTALL_BINDIR)"
cp $(LIBRARIES) "$(INSTALL_LIBDIR)"
- mkdir -p "$(INSTALL_LIBDIR)/caml"
- for i in caml/*.h; do \
- sed -f ../tools/cleanup-header $$i \
- > "$(INSTALL_LIBDIR)/$$i"; \
- done
+ mkdir -p "$(INSTALL_INCDIR)"
+ cp caml/*.h "$(INSTALL_INCDIR)"
# If primitives contain duplicated lines (e.g. because the code is defined
# like
$(call MKLIB,$@, $^)
ocamlrund$(EXE): prims.$(O) libcamlrund.$(A)
- $(MKEXE) $(MKEXEDEBUGFLAG) $(BYTECCLINKOPTS) -o $@ $^ $(LIBS)
+ $(MKEXE) $(MKEXEDEBUGFLAG) -o $@ $^ $(LIBS)
libcamlrund.$(A): $(DOBJS)
$(call MKLIB,$@, $^)
ocamlruni$(EXE): prims.$(O) libcamlruni.$(A)
- $(MKEXE) $(BYTECCLINKOPTS) -o $@ $^ $(LIBS)
+ $(MKEXE) -o $@ $^ $(LIBS)
libcamlruni.$(A): $(IOBJS)
$(call MKLIB,$@, $^)
$(MKDLL) -o $@ $^ $(BYTECCLIBS)
%.$(O): %.c
- $(CC) $(CFLAGS) -c $<
+ $(CC) -c $(CFLAGS) $(CPPFLAGS) $<
%.$(DBGO): %.c
- $(CC) $(DFLAGS) -c $(OUTPUTOBJ)$@ $<
+ $(CC) -c $(DFLAGS) $(CPPFLAGS) $(OUTPUTOBJ)$@ $<
%.i.$(O): %.c
- $(CC) $(IFLAGS) -c $(OUTPUTOBJ)$@ $<
+ $(CC) -c $(IFLAGS) $(CPPFLAGS) $(OUTPUTOBJ)$@ $<
%.pic.$(O): %.c
- $(CC) $(PICFLAGS) -c $(OUTPUTOBJ)$@ $<
+ $(CC) -c $(PICFLAGS) $(CPPFLAGS) $(OUTPUTOBJ)$@ $<
-ifneq "$(TOOLCHAIN)" "msvc"
.PHONY: depend
-depend : prims.c caml/opnames.h caml/jumptbl.h caml/version.h
- -$(CC) -MM $(BYTECCCOMPOPTS) *.c > .depend
- -$(CC) -MM $(BYTECCCOMPOPTS) -DDEBUG *.c | sed -e 's/\.o/.d.o/' \
- >> .depend
- -$(CC) -MM $(BYTECCCOMPOPTS) -DCAML_INSTR *.c | sed -e 's/\.o/.i.o/' \
- >> .depend
- -$(CC) -MM $(BYTECCCOMPOPTS) *.c | sed -e 's/\.o/.pic.o/' >> .depend
+ifeq "$(TOOLCHAIN)" "msvc"
+depend:
+ $(error Dependencies cannot be regenerated using the MSVC ports)
+else
+depend: prims.c caml/opnames.h caml/jumptbl.h caml/version.h
+ $(CC) -MM $(CFLAGS) $(CPPFLAGS) *.c | sed -e 's/\.o/.$$(O)/'>.$@
+ $(CC) -MM $(DFLAGS) $(CPPFLAGS) *.c | sed -e 's/\.o/.d.$$(O)/'>>.$@
+ $(CC) -MM $(IFLAGS) $(CPPFLAGS) *.c | sed -e 's/\.o/.i.$$(O)/'>>.$@
+ $(CC) -MM $(PICFLAGS) $(CPPFLAGS) *.c | sed -e 's/\.o/.pic.$$(O)/'>>.$@
endif
-ifeq "$(UNIX_OR_WIN32)" "win32"
-.depend.nt: .depend
- rm -f .depend.win32
- echo "win32.o: win32.c caml/fail.h caml/compatibility.h \\"\
- >> .depend.win32
- echo " caml/misc.h caml/config.h ../config/m.h ../config/s.h \\"\
- >> .depend.win32
- echo " caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \\"\
- >> .depend.win32
- echo " caml/freelist.h caml/minor_gc.h caml/osdeps.h caml/signals.h"\
- >> .depend.win32
- cat .depend >> .depend.win32
- sed -ne '/\.pic\.o/q' \
- -e 's/^\(.*\)\.d\.o:/\1.$$(DBGO):/' \
- -e 's/^\(.*\)\.o:/\1.$$(O):/' \
- -e p \
- .depend.win32 > .depend.nt
- rm -f .depend.win32
-
-include .depend.nt
-
-else
include .depend
-endif
/**************************************************************************/
/* Runtime support for afl-fuzz */
+#include "caml/config.h"
-/* Android's libc does not implement System V shared memory. */
-#if defined(_WIN32) || defined(__ANDROID__)
+#if !defined(HAS_SYS_SHM_H)
#include "caml/mlvalues.h"
return Val_unit;
}
-#endif /* _WIN32 */
+#endif /* HAS_SYS_SHM_H */
value result;
mlsize_t i;
- Assert (tag < 256);
- Assert (tag != Infix_tag);
- if (wosize == 0){
- result = Atom (tag);
- }else if (wosize <= Max_young_wosize){
- Alloc_small (result, wosize, tag);
- if (tag < No_scan_tag){
- for (i = 0; i < wosize; i++) Field (result, i) = Val_unit;
+ CAMLassert (tag < 256);
+ CAMLassert (tag != Infix_tag);
+ if (wosize <= Max_young_wosize){
+ if (wosize == 0){
+ result = Atom (tag);
+ }else{
+ Alloc_small (result, wosize, tag);
+ if (tag < No_scan_tag){
+ for (i = 0; i < wosize; i++) Field (result, i) = Val_unit;
+ }
}
}else{
result = caml_alloc_shr (wosize, tag);
{
value result;
- Assert (wosize > 0);
- Assert (wosize <= Max_young_wosize);
- Assert (tag < 256);
+ CAMLassert (wosize > 0);
+ CAMLassert (wosize <= Max_young_wosize);
+ CAMLassert (tag < 256);
Alloc_small (result, wosize, tag);
return result;
}
else {
value result;
- Assert (wosize > 0);
- Assert (wosize <= Max_young_wosize);
- Assert (tag < 256);
+ CAMLassert (wosize > 0);
+ CAMLassert (wosize <= Max_young_wosize);
+ CAMLassert (tag < 256);
Alloc_small_with_profinfo (result, wosize, tag, profinfo);
return result;
}
return result;
}
+/* [len] is a number of bytes (chars) */
+CAMLexport value caml_alloc_initialized_string (mlsize_t len, const char *p)
+{
+ value result = caml_alloc_string (len);
+ memcpy((char *)String_val(result), p, len);
+ return result;
+}
+
/* [len] is a number of words.
[mem] and [max] are relative (without unit).
*/
value res;
len = strlen(s);
- res = caml_alloc_string(len);
- memmove(String_val(res), s, len);
+ res = caml_alloc_initialized_string(len, s);
return res;
}
nbr = 0;
while (arr[nbr] != 0) nbr++;
- if (nbr == 0) {
- CAMLreturn (Atom(0));
- } else {
- result = caml_alloc (nbr, 0);
- for (n = 0; n < nbr; n++) {
- /* The two statements below must be separate because of evaluation
- order (don't take the address &Field(result, n) before
- calling funct, which may cause a GC and move result). */
- v = funct(arr[n]);
- caml_modify(&Field(result, n), v);
- }
- CAMLreturn (result);
+ result = caml_alloc (nbr, 0);
+ for (n = 0; n < nbr; n++) {
+ /* The two statements below must be separate because of evaluation
+ order (don't take the address &Field(result, n) before
+ calling funct, which may cause a GC and move result). */
+ v = funct(arr[n]);
+ caml_modify(&Field(result, n), v);
}
+ CAMLreturn (result);
}
/* [len] is a number of floats */
CAMLprim value caml_alloc_float_array(mlsize_t len)
{
+#ifdef FLAT_FLOAT_ARRAY
mlsize_t wosize = len * Double_wosize;
value result;
/* For consistency with [caml_make_vect], which can't tell whether it should
create a float array or not when the size is zero, the tag is set to
zero when the size is zero. */
- if (wosize == 0)
- return Atom(0);
- else if (wosize <= Max_young_wosize){
- Alloc_small (result, wosize, Double_array_tag);
+ if (wosize <= Max_young_wosize){
+ if (wosize == 0)
+ return Atom(0);
+ else
+ Alloc_small (result, wosize, Double_array_tag);
}else {
result = caml_alloc_shr (wosize, Double_array_tag);
result = caml_check_urgent_gc (result);
}
return result;
+#else
+ return caml_alloc (len, 0);
+#endif
}
CAMLprim value caml_alloc_dummy(value size)
{
mlsize_t wosize = Long_val(size);
-
- if (wosize == 0) return Atom(0);
return caml_alloc (wosize, 0);
}
CAMLprim value caml_alloc_dummy_float (value size)
{
mlsize_t wosize = Long_val(size) * Double_wosize;
-
- if (wosize == 0) return Atom(0);
return caml_alloc (wosize, 0);
}
size = Wosize_val(newval);
tag = Tag_val (newval);
- Assert (size == Wosize_val(dummy));
- Assert (tag < No_scan_tag || tag == Double_array_tag);
+ CAMLassert (size == Wosize_val(dummy));
+ CAMLassert (tag < No_scan_tag || tag == Double_array_tag);
Tag_val(dummy) = tag;
if (tag == Double_array_tag){
size = Wosize_val (newval) / Double_wosize;
for (i = 0; i < size; i++){
- Store_double_field (dummy, i, Double_field (newval, i));
+ Store_double_flat_field (dummy, i, Double_flat_field (newval, i));
}
}else{
for (i = 0; i < size; i++){
static const mlsize_t mlsize_t_max = -1;
/* returns number of elements (either fields or floats) */
+/* [ 'a array -> int ] */
CAMLexport mlsize_t caml_array_length(value array)
{
+#ifdef FLAT_FLOAT_ARRAY
if (Tag_val(array) == Double_array_tag)
return Wosize_val(array) / Double_wosize;
else
+#endif
return Wosize_val(array);
}
return (Tag_val(array) == Double_array_tag);
}
+/* Note: the OCaml types on the following primitives will work both with
+ and without the -no-flat-float-array configure-time option. If you
+ respect them, your C code should work in both configurations.
+*/
+
+/* [ 'a array -> int -> 'a ] where 'a != float */
CAMLprim value caml_array_get_addr(value array, value index)
{
intnat idx = Long_val(index);
return Field(array, idx);
}
+/* [ float array -> int -> float ] */
CAMLprim value caml_array_get_float(value array, value index)
{
intnat idx = Long_val(index);
+#ifdef FLAT_FLOAT_ARRAY
double d;
value res;
if (idx < 0 || idx >= Wosize_val(array) / Double_wosize)
caml_array_bound_error();
- d = Double_field(array, idx);
+ d = Double_flat_field(array, idx);
#define Setup_for_gc
#define Restore_after_gc
Alloc_small(res, Double_wosize, Double_tag);
#undef Restore_after_gc
Store_double_val(res, d);
return res;
+#else
+ CAMLassert (Tag_val (array) != Double_array_tag);
+ if (idx < 0 || idx >= Wosize_val(array)) caml_array_bound_error();
+ return Field(array, idx);
+#endif /* FLAT_FLOAT_ARRAY */
}
+/* [ 'a array -> int -> 'a ] */
CAMLprim value caml_array_get(value array, value index)
{
+#ifdef FLAT_FLOAT_ARRAY
if (Tag_val(array) == Double_array_tag)
return caml_array_get_float(array, index);
- else
- return caml_array_get_addr(array, index);
+#else
+ CAMLassert (Tag_val(array) != Double_array_tag);
+#endif
+ return caml_array_get_addr(array, index);
+}
+
+/* [ floatarray -> int -> float ] */
+CAMLprim value caml_floatarray_get(value array, value index)
+{
+ intnat idx = Long_val(index);
+ double d;
+ value res;
+
+ CAMLassert (Tag_val(array) == Double_array_tag);
+ if (idx < 0 || idx >= Wosize_val(array) / Double_wosize)
+ caml_array_bound_error();
+ d = Double_flat_field(array, idx);
+#define Setup_for_gc
+#define Restore_after_gc
+ Alloc_small(res, Double_wosize, Double_tag);
+#undef Setup_for_gc
+#undef Restore_after_gc
+ Store_double_val(res, d);
+ return res;
}
+/* [ 'a array -> int -> 'a -> unit ] where 'a != float */
CAMLprim value caml_array_set_addr(value array, value index, value newval)
{
intnat idx = Long_val(index);
return Val_unit;
}
+/* [ float array -> int -> float -> unit ] */
CAMLprim value caml_array_set_float(value array, value index, value newval)
{
intnat idx = Long_val(index);
+#ifdef FLAT_FLOAT_ARRAY
+ double d = Double_val (newval);
if (idx < 0 || idx >= Wosize_val(array) / Double_wosize)
caml_array_bound_error();
- Store_double_field(array, idx, Double_val(newval));
+ Store_double_flat_field(array, idx, d);
+#else
+ CAMLassert (Tag_val (array) != Double_array_tag);
+ if (idx < 0 || idx >= Wosize_val(array)) caml_array_bound_error();
+ Modify(&Field(array, idx), newval);
+#endif
return Val_unit;
}
+/* [ 'a array -> int -> 'a -> unit ] */
CAMLprim value caml_array_set(value array, value index, value newval)
{
+#ifdef FLAT_FLOAT_ARRAY
if (Tag_val(array) == Double_array_tag)
return caml_array_set_float(array, index, newval);
- else
- return caml_array_set_addr(array, index, newval);
+#else
+ CAMLassert (Tag_val(array) != Double_array_tag);
+#endif
+ return caml_array_set_addr(array, index, newval);
+}
+
+/* [ floatarray -> int -> float -> unit ] */
+CAMLprim value caml_floatarray_set(value array, value index, value newval)
+{
+ intnat idx = Long_val(index);
+ double d = Double_val (newval);
+ CAMLassert (Tag_val(array) == Double_array_tag);
+ if (idx < 0 || idx >= Wosize_val(array) / Double_wosize)
+ caml_array_bound_error();
+ Store_double_flat_field(array, idx, d);
+ return Val_unit;
}
+/* [ float array -> int -> float ] */
CAMLprim value caml_array_unsafe_get_float(value array, value index)
{
+ intnat idx = Long_val (index);
+#ifdef FLAT_FLOAT_ARRAY
double d;
value res;
- d = Double_field(array, Long_val(index));
+ d = Double_flat_field(array, idx);
#define Setup_for_gc
#define Restore_after_gc
Alloc_small(res, Double_wosize, Double_tag);
#undef Restore_after_gc
Store_double_val(res, d);
return res;
+#else /* FLAT_FLOAT_ARRAY */
+ CAMLassert (Tag_val(array) != Double_array_tag);
+ return Field(array, idx);
+#endif /* FLAT_FLOAT_ARRAY */
}
+/* [ 'a array -> int -> 'a ] */
CAMLprim value caml_array_unsafe_get(value array, value index)
{
+#ifdef FLAT_FLOAT_ARRAY
if (Tag_val(array) == Double_array_tag)
return caml_array_unsafe_get_float(array, index);
- else
- return Field(array, Long_val(index));
+#else
+ CAMLassert (Tag_val(array) != Double_array_tag);
+#endif
+ return Field(array, Long_val(index));
}
+/* [ floatarray -> int -> float ] */
+CAMLprim value caml_floatarray_unsafe_get(value array, value index)
+{
+ intnat idx = Long_val(index);
+ double d;
+ value res;
+
+ CAMLassert (Tag_val(array) == Double_array_tag);
+ d = Double_flat_field(array, idx);
+#define Setup_for_gc
+#define Restore_after_gc
+ Alloc_small(res, Double_wosize, Double_tag);
+#undef Setup_for_gc
+#undef Restore_after_gc
+ Store_double_val(res, d);
+ return res;
+}
+
+/* [ 'a array -> int -> 'a -> unit ] where 'a != float */
CAMLprim value caml_array_unsafe_set_addr(value array, value index,value newval)
{
intnat idx = Long_val(index);
return Val_unit;
}
+/* [ float array -> int -> float -> unit ] */
CAMLprim value caml_array_unsafe_set_float(value array,value index,value newval)
{
- Store_double_field(array, Long_val(index), Double_val(newval));
+ intnat idx = Long_val(index);
+#ifdef FLAT_FLOAT_ARRAY
+ double d = Double_val (newval);
+ Store_double_flat_field(array, idx, d);
+#else
+ Modify(&Field(array, idx), newval);
+#endif
return Val_unit;
}
+/* [ 'a array -> int -> 'a -> unit ] */
CAMLprim value caml_array_unsafe_set(value array, value index, value newval)
{
+#ifdef FLAT_FLOAT_ARRAY
if (Tag_val(array) == Double_array_tag)
return caml_array_unsafe_set_float(array, index, newval);
- else
- return caml_array_unsafe_set_addr(array, index, newval);
+#else
+ CAMLassert (Tag_val(array) != Double_array_tag);
+#endif
+ return caml_array_unsafe_set_addr(array, index, newval);
}
-/* [len] is a [value] representing number of floats */
-CAMLprim value caml_make_float_vect(value len)
+/* [ floatarray -> int -> float -> unit ] */
+CAMLprim value caml_floatarray_unsafe_set(value array, value index,value newval)
+{
+ intnat idx = Long_val(index);
+ double d = Double_val (newval);
+ Store_double_flat_field(array, idx, d);
+ return Val_unit;
+}
+
+/* [len] is a [value] representing number of floats. */
+/* [ int -> floatarray ] */
+CAMLprim value caml_floatarray_create(value len)
{
mlsize_t wosize = Long_val(len) * Double_wosize;
value result;
- if (wosize == 0)
- return Atom(0);
- else if (wosize <= Max_young_wosize){
+ if (wosize <= Max_young_wosize){
+ if (wosize == 0)
+ return Atom(0);
+ else
#define Setup_for_gc
#define Restore_after_gc
- Alloc_small (result, wosize, Double_array_tag);
+ Alloc_small (result, wosize, Double_array_tag);
#undef Setup_for_gc
#undef Restore_after_gc
}else if (wosize > Max_wosize)
- caml_invalid_argument("Array.create_float");
+ caml_invalid_argument("Array.Floatarray.create");
else {
result = caml_alloc_shr (wosize, Double_array_tag);
result = caml_check_urgent_gc (result);
return result;
}
+/* [len] is a [value] representing number of floats */
+/* [ int -> float array ] */
+CAMLprim value caml_make_float_vect(value len)
+{
+#ifdef FLAT_FLOAT_ARRAY
+ return caml_floatarray_create (len);
+#else
+ return caml_alloc (Long_val (len), 0);
+#endif
+}
+
/* [len] is a [value] representing number of words or floats */
/* Spacetime profiling assumes that this function is only called from OCaml. */
CAMLprim value caml_make_vect(value len, value init)
{
CAMLparam2 (len, init);
CAMLlocal1 (res);
- mlsize_t size, wsize, i;
- double d;
+ mlsize_t size, i;
size = Long_val(len);
if (size == 0) {
res = Atom(0);
- }
- else if (Is_block(init)
+#ifdef FLAT_FLOAT_ARRAY
+ } else if (Is_block(init)
&& Is_in_value_area(init)
&& Tag_val(init) == Double_tag) {
+ mlsize_t wsize;
+ double d;
d = Double_val(init);
wsize = size * Double_wosize;
if (wsize > Max_wosize) caml_invalid_argument("Array.make");
res = caml_alloc(wsize, Double_array_tag);
for (i = 0; i < size; i++) {
- Store_double_field(res, i, d);
+ Store_double_flat_field(res, i, d);
}
+#endif
} else {
- if (size > Max_wosize) caml_invalid_argument("Array.make");
if (size <= Max_young_wosize) {
uintnat profinfo;
Get_my_profinfo_with_cached_backtrace(profinfo, size);
res = caml_alloc_small_with_my_or_given_profinfo(size, 0, profinfo);
for (i = 0; i < size; i++) Field(res, i) = init;
}
+ else if (size > Max_wosize) caml_invalid_argument("Array.make");
else if (Is_block(init) && Is_young(init)) {
/* We don't want to create so many major-to-minor references,
so [init] is moved to the major heap by doing a minor GC. */
CAMLreturn (res);
}
+/* This primitive is used internally by the compiler to compile
+ explicit array expressions.
+ For float arrays when FLAT_FLOAT_ARRAY is true, it takes an array of
+ boxed floats and returns the corresponding flat-allocated [float array].
+ In all other cases, it just returns its argument unchanged.
+*/
CAMLprim value caml_make_array(value init)
{
+#ifdef FLAT_FLOAT_ARRAY
CAMLparam1 (init);
mlsize_t wsize, size, i;
CAMLlocal2 (v, res);
res = caml_check_urgent_gc(res);
}
for (i = 0; i < size; i++) {
- Store_double_field(res, i, Double_val(Field(init, i)));
+ double d = Double_val(Field(init, i));
+ Store_double_flat_field(res, i, d);
}
CAMLreturn (res);
}
}
+#else
+ return init;
+#endif
}
/* Blitting */
value * src, * dst;
intnat count;
+#ifdef FLAT_FLOAT_ARRAY
if (Tag_val(a2) == Double_array_tag) {
/* Arrays of floats. The values being copied are floats, not
pointer, so we can do a direct copy. memmove takes care of
Long_val(n) * sizeof(double));
return Val_unit;
}
+#endif
+ CAMLassert (Tag_val(a2) != Double_array_tag);
if (Is_young(a2)) {
/* Arrays of values, destination is in young generation.
Here too we can do a direct copy since this cannot create
{
CAMLparamN(arrays, num_arrays);
value res; /* no need to register it as a root */
- int isfloat;
- mlsize_t i, size, wsize, count, pos;
+#ifdef FLAT_FLOAT_ARRAY
+ int isfloat = 0;
+ mlsize_t wsize;
+#endif
+ mlsize_t i, size, count, pos;
value * src;
/* Determine total size and whether result array is an array of floats */
size = 0;
- isfloat = 0;
for (i = 0; i < num_arrays; i++) {
if (mlsize_t_max - lengths[i] < size) caml_invalid_argument("Array.concat");
size += lengths[i];
+#ifdef FLAT_FLOAT_ARRAY
if (Tag_val(arrays[i]) == Double_array_tag) isfloat = 1;
+#endif
}
if (size == 0) {
/* If total size = 0, just return empty array */
res = Atom(0);
}
+#ifdef FLAT_FLOAT_ARRAY
else if (isfloat) {
/* This is an array of floats. We can use memcpy directly. */
if (size > Max_wosize/Double_wosize) caml_invalid_argument("Array.concat");
lengths[i] * sizeof(double));
pos += lengths[i];
}
- Assert(pos == size);
- }
- else if (size > Max_wosize) {
- /* Array of values, too big. */
- caml_invalid_argument("Array.concat");
+ CAMLassert(pos == size);
}
+#endif
else if (size <= Max_young_wosize) {
/* Array of values, small enough to fit in young generation.
We can use memcpy directly. */
lengths[i] * sizeof(value));
pos += lengths[i];
}
- Assert(pos == size);
+ CAMLassert(pos == size);
+ }
+ else if (size > Max_wosize) {
+ /* Array of values, too big. */
+ caml_invalid_argument("Array.concat");
} else {
/* Array of values, must be allocated in old generation and filled
using caml_initialize. */
caml_initialize(&Field(res, pos), *src);
}
}
- Assert(pos == size);
+ CAMLassert(pos == size);
/* Many caml_initialize in a row can create a lot of old-to-young
refs. Give the minor GC a chance to run if it needs to. */
lengths = static_lengths;
} else {
arrays = caml_stat_alloc(n * sizeof(value));
- offsets = malloc(n * sizeof(intnat));
+ offsets = caml_stat_alloc_noexc(n * sizeof(intnat));
if (offsets == NULL) {
caml_stat_free(arrays);
caml_raise_out_of_memory();
}
- lengths = malloc(n * sizeof(value));
+ lengths = caml_stat_alloc_noexc(n * sizeof(value));
if (lengths == NULL) {
caml_stat_free(offsets);
caml_stat_free(arrays);
/* The table of debug information fragments */
struct ext_table caml_debug_info;
-CAMLexport char * caml_cds_file = NULL;
+CAMLexport char_os * caml_cds_file = NULL;
/* Location of fields in the Instruct.debug_event record */
enum {
return 0;
}
-struct ev_info *process_debug_events(code_t code_start, value events_heap,
+static struct ev_info *process_debug_events(code_t code_start, value events_heap,
mlsize_t *num_events)
{
CAMLparam1(events_heap);
if (*num_events == 0)
CAMLreturnT(struct ev_info *, NULL);
- events = malloc(*num_events * sizeof(struct ev_info));
+ events = caml_stat_alloc_noexc(*num_events * sizeof(struct ev_info));
if(events == NULL)
caml_fatal_error ("caml_add_debug_info: out of memory");
{
uintnat fnsz = caml_string_length(Field(ev_start, POS_FNAME)) + 1;
- events[j].ev_filename = (char*)malloc(fnsz);
+ events[j].ev_filename = (char*)caml_stat_alloc_noexc(fnsz);
if(events[j].ev_filename == NULL)
caml_fatal_error ("caml_add_debug_info: out of memory");
memcpy(events[j].ev_filename,
}
}
- Assert(j == *num_events);
+ CAMLassert(j == *num_events);
qsort(events, *num_events, sizeof(struct ev_info), cmp_ev_info);
}
int caml_alloc_backtrace_buffer(void){
- Assert(caml_backtrace_pos == 0);
- caml_backtrace_buffer = malloc(BACKTRACE_BUFFER_SIZE * sizeof(code_t));
+ CAMLassert(caml_backtrace_pos == 0);
+ caml_backtrace_buffer =
+ caml_stat_alloc_noexc(BACKTRACE_BUFFER_SIZE * sizeof(code_t));
if (caml_backtrace_buffer == NULL) return -1;
return 0;
}
for (trace_pos = 0; trace_pos < trace_size; trace_pos++) {
code_t p = caml_next_frame_pointer(&sp, &trsp);
- Assert(p != NULL);
+ CAMLassert(p != NULL);
Field(trace, trace_pos) = Val_backtrace_slot(p);
}
}
#define O_BINARY 0
#endif
-void read_main_debug_info(struct debug_info *di)
+static void read_main_debug_info(struct debug_info *di)
{
CAMLparam0();
CAMLlocal3(events, evl, l);
- char *exec_name;
+ char_os *exec_name;
int fd, num_events, orig, i;
struct channel *chan;
struct exec_trailer trail;
- Assert(di->already_read == 0);
+ CAMLassert(di->already_read == 0);
di->already_read = 1;
if (caml_cds_file != NULL) {
--- /dev/null
+/**************************************************************************/
+/* */
+/* OCaml */
+/* */
+/* Manuel Serrano and Xavier Leroy, INRIA Rocquencourt */
+/* */
+/* Copyright 2000 Institut National de Recherche en Informatique et */
+/* en Automatique. */
+/* */
+/* All rights reserved. This file is distributed under the terms of */
+/* the GNU Lesser General Public License version 2.1, with the */
+/* special exception on linking described in the file LICENSE. */
+/* */
+/**************************************************************************/
+
+/* This file is an intermediate step in making the bigarray library
+ (in otherlibs/bigarray) a part of the standard library.
+ This file defines the basic allocation functions for bigarrays,
+ as well as the comparison, hashing and marshaling methods for
+ bigarrays. The other bigarray primitives are still defined
+ in otherlibs/bigarray. Memory-mapping a file as a bigarray
+ is being migrated to otherlibs/unix and otherlibs/win32unix. */
+
+#define CAML_INTERNALS
+
+#include <stddef.h>
+#include <stdarg.h>
+#include "caml/alloc.h"
+#include "caml/bigarray.h"
+#include "caml/custom.h"
+#include "caml/fail.h"
+#include "caml/intext.h"
+#include "caml/hash.h"
+#include "caml/memory.h"
+#include "caml/mlvalues.h"
+
+/* Compute the number of elements of a big array */
+
+CAMLexport uintnat caml_ba_num_elts(struct caml_ba_array * b)
+{
+ uintnat num_elts;
+ int i;
+ num_elts = 1;
+ for (i = 0; i < b->num_dims; i++) num_elts = num_elts * b->dim[i];
+ return num_elts;
+}
+
+/* Size in bytes of a bigarray element, indexed by bigarray kind */
+
+CAMLexport int caml_ba_element_size[] =
+{ 4 /*FLOAT32*/, 8 /*FLOAT64*/,
+ 1 /*SINT8*/, 1 /*UINT8*/,
+ 2 /*SINT16*/, 2 /*UINT16*/,
+ 4 /*INT32*/, 8 /*INT64*/,
+ sizeof(value) /*CAML_INT*/, sizeof(value) /*NATIVE_INT*/,
+ 8 /*COMPLEX32*/, 16 /*COMPLEX64*/,
+ 1 /*CHAR*/
+};
+
+/* Compute the number of bytes for the elements of a big array */
+
+CAMLexport uintnat caml_ba_byte_size(struct caml_ba_array * b)
+{
+ return caml_ba_num_elts(b)
+ * caml_ba_element_size[b->flags & CAML_BA_KIND_MASK];
+}
+
+/* Operation table for bigarrays */
+
+CAMLexport struct custom_operations caml_ba_ops = {
+ "_bigarray",
+ caml_ba_finalize,
+ caml_ba_compare,
+ caml_ba_hash,
+ caml_ba_serialize,
+ caml_ba_deserialize,
+ custom_compare_ext_default
+};
+
+/* Allocation of a big array */
+
+#define CAML_BA_MAX_MEMORY 1024*1024*1024
+/* 1 Gb -- after allocating that much, it's probably worth speeding
+ up the major GC */
+
+/* [caml_ba_alloc] will allocate a new bigarray object in the heap.
+ If [data] is NULL, the memory for the contents is also allocated
+ (with [malloc]) by [caml_ba_alloc].
+ [data] cannot point into the OCaml heap.
+ [dim] may point into an object in the OCaml heap.
+*/
+CAMLexport value
+caml_ba_alloc(int flags, int num_dims, void * data, intnat * dim)
+{
+ uintnat num_elts, asize, size;
+ int i;
+ value res;
+ struct caml_ba_array * b;
+ intnat dimcopy[CAML_BA_MAX_NUM_DIMS];
+
+ CAMLassert(num_dims >= 0 && num_dims <= CAML_BA_MAX_NUM_DIMS);
+ CAMLassert((flags & CAML_BA_KIND_MASK) <= CAML_BA_CHAR);
+ for (i = 0; i < num_dims; i++) dimcopy[i] = dim[i];
+ size = 0;
+ if (data == NULL) {
+ num_elts = 1;
+ for (i = 0; i < num_dims; i++) {
+ if (caml_umul_overflow(num_elts, dimcopy[i], &num_elts))
+ caml_raise_out_of_memory();
+ }
+ if (caml_umul_overflow(num_elts,
+ caml_ba_element_size[flags & CAML_BA_KIND_MASK],
+ &size))
+ caml_raise_out_of_memory();
+ data = malloc(size);
+ if (data == NULL && size != 0) caml_raise_out_of_memory();
+ flags |= CAML_BA_MANAGED;
+ }
+ asize = SIZEOF_BA_ARRAY + num_dims * sizeof(intnat);
+ res = caml_alloc_custom(&caml_ba_ops, asize, size, CAML_BA_MAX_MEMORY);
+ b = Caml_ba_array_val(res);
+ b->data = data;
+ b->num_dims = num_dims;
+ b->flags = flags;
+ b->proxy = NULL;
+ for (i = 0; i < num_dims; i++) b->dim[i] = dimcopy[i];
+ return res;
+}
+
+/* Same as caml_ba_alloc, but dimensions are passed as a list of
+ arguments */
+
+CAMLexport value caml_ba_alloc_dims(int flags, int num_dims, void * data, ...)
+{
+ va_list ap;
+ intnat dim[CAML_BA_MAX_NUM_DIMS];
+ int i;
+ value res;
+
+ CAMLassert(num_dims <= CAML_BA_MAX_NUM_DIMS);
+ va_start(ap, data);
+ for (i = 0; i < num_dims; i++) dim[i] = va_arg(ap, intnat);
+ va_end(ap);
+ res = caml_ba_alloc(flags, num_dims, data, dim);
+ return res;
+}
+
+/* Finalization of a big array */
+
+CAMLexport void caml_ba_finalize(value v)
+{
+ struct caml_ba_array * b = Caml_ba_array_val(v);
+
+ switch (b->flags & CAML_BA_MANAGED_MASK) {
+ case CAML_BA_EXTERNAL:
+ break;
+ case CAML_BA_MANAGED:
+ if (b->proxy == NULL) {
+ free(b->data);
+ } else {
+ if (-- b->proxy->refcount == 0) {
+ free(b->proxy->data);
+ free(b->proxy);
+ }
+ }
+ break;
+ case CAML_BA_MAPPED_FILE:
+ /* Bigarrays for mapped files use a different finalization method */
+ default:
+ CAMLassert(0);
+ }
+}
+
+/* Comparison of two big arrays */
+
+CAMLexport int caml_ba_compare(value v1, value v2)
+{
+ struct caml_ba_array * b1 = Caml_ba_array_val(v1);
+ struct caml_ba_array * b2 = Caml_ba_array_val(v2);
+ uintnat n, num_elts;
+ intnat flags1, flags2;
+ int i;
+
+ /* Compare kind & layout in case the arguments are of different types */
+ flags1 = b1->flags & (CAML_BA_KIND_MASK | CAML_BA_LAYOUT_MASK);
+ flags2 = b2->flags & (CAML_BA_KIND_MASK | CAML_BA_LAYOUT_MASK);
+ if (flags1 != flags2) return flags2 - flags1;
+ /* Compare number of dimensions */
+ if (b1->num_dims != b2->num_dims) return b2->num_dims - b1->num_dims;
+ /* Same number of dimensions: compare dimensions lexicographically */
+ for (i = 0; i < b1->num_dims; i++) {
+ intnat d1 = b1->dim[i];
+ intnat d2 = b2->dim[i];
+ if (d1 != d2) return d1 < d2 ? -1 : 1;
+ }
+ /* Same dimensions: compare contents lexicographically */
+ num_elts = caml_ba_num_elts(b1);
+
+#define DO_INTEGER_COMPARISON(type) \
+ { type * p1 = b1->data; type * p2 = b2->data; \
+ for (n = 0; n < num_elts; n++) { \
+ type e1 = *p1++; type e2 = *p2++; \
+ if (e1 < e2) return -1; \
+ if (e1 > e2) return 1; \
+ } \
+ return 0; \
+ }
+#define DO_FLOAT_COMPARISON(type) \
+ { type * p1 = b1->data; type * p2 = b2->data; \
+ for (n = 0; n < num_elts; n++) { \
+ type e1 = *p1++; type e2 = *p2++; \
+ if (e1 < e2) return -1; \
+ if (e1 > e2) return 1; \
+ if (e1 != e2) { \
+ caml_compare_unordered = 1; \
+ if (e1 == e1) return 1; \
+ if (e2 == e2) return -1; \
+ } \
+ } \
+ return 0; \
+ }
+
+ switch (b1->flags & CAML_BA_KIND_MASK) {
+ case CAML_BA_COMPLEX32:
+ num_elts *= 2; /*fallthrough*/
+ case CAML_BA_FLOAT32:
+ DO_FLOAT_COMPARISON(float);
+ case CAML_BA_COMPLEX64:
+ num_elts *= 2; /*fallthrough*/
+ case CAML_BA_FLOAT64:
+ DO_FLOAT_COMPARISON(double);
+ case CAML_BA_CHAR:
+ DO_INTEGER_COMPARISON(caml_ba_uint8);
+ case CAML_BA_SINT8:
+ DO_INTEGER_COMPARISON(caml_ba_int8);
+ case CAML_BA_UINT8:
+ DO_INTEGER_COMPARISON(caml_ba_uint8);
+ case CAML_BA_SINT16:
+ DO_INTEGER_COMPARISON(caml_ba_int16);
+ case CAML_BA_UINT16:
+ DO_INTEGER_COMPARISON(caml_ba_uint16);
+ case CAML_BA_INT32:
+ DO_INTEGER_COMPARISON(int32_t);
+ case CAML_BA_INT64:
+ DO_INTEGER_COMPARISON(int64_t);
+ case CAML_BA_CAML_INT:
+ case CAML_BA_NATIVE_INT:
+ DO_INTEGER_COMPARISON(intnat);
+ default:
+ CAMLassert(0);
+ return 0; /* should not happen */
+ }
+#undef DO_INTEGER_COMPARISON
+#undef DO_FLOAT_COMPARISON
+}
+
+/* Hashing of a bigarray */
+
+CAMLexport intnat caml_ba_hash(value v)
+{
+ struct caml_ba_array * b = Caml_ba_array_val(v);
+ intnat num_elts, n;
+ uint32_t h, w;
+ int i;
+
+ num_elts = 1;
+ for (i = 0; i < b->num_dims; i++) num_elts = num_elts * b->dim[i];
+ h = 0;
+
+ switch (b->flags & CAML_BA_KIND_MASK) {
+ case CAML_BA_CHAR:
+ case CAML_BA_SINT8:
+ case CAML_BA_UINT8: {
+ caml_ba_uint8 * p = b->data;
+ if (num_elts > 256) num_elts = 256;
+ for (n = 0; n + 4 <= num_elts; n += 4, p += 4) {
+ w = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
+ h = caml_hash_mix_uint32(h, w);
+ }
+ w = 0;
+ switch (num_elts & 3) {
+ case 3: w = p[2] << 16; /* fallthrough */
+ case 2: w |= p[1] << 8; /* fallthrough */
+ case 1: w |= p[0];
+ h = caml_hash_mix_uint32(h, w);
+ }
+ break;
+ }
+ case CAML_BA_SINT16:
+ case CAML_BA_UINT16: {
+ caml_ba_uint16 * p = b->data;
+ if (num_elts > 128) num_elts = 128;
+ for (n = 0; n + 2 <= num_elts; n += 2, p += 2) {
+ w = p[0] | (p[1] << 16);
+ h = caml_hash_mix_uint32(h, w);
+ }
+ if ((num_elts & 1) != 0)
+ h = caml_hash_mix_uint32(h, p[0]);
+ break;
+ }
+ case CAML_BA_INT32:
+ {
+ uint32_t * p = b->data;
+ if (num_elts > 64) num_elts = 64;
+ for (n = 0; n < num_elts; n++, p++) h = caml_hash_mix_uint32(h, *p);
+ break;
+ }
+ case CAML_BA_CAML_INT:
+ case CAML_BA_NATIVE_INT:
+ {
+ intnat * p = b->data;
+ if (num_elts > 64) num_elts = 64;
+ for (n = 0; n < num_elts; n++, p++) h = caml_hash_mix_intnat(h, *p);
+ break;
+ }
+ case CAML_BA_INT64:
+ {
+ int64_t * p = b->data;
+ if (num_elts > 32) num_elts = 32;
+ for (n = 0; n < num_elts; n++, p++) h = caml_hash_mix_int64(h, *p);
+ break;
+ }
+ case CAML_BA_COMPLEX32:
+ num_elts *= 2; /* fallthrough */
+ case CAML_BA_FLOAT32:
+ {
+ float * p = b->data;
+ if (num_elts > 64) num_elts = 64;
+ for (n = 0; n < num_elts; n++, p++) h = caml_hash_mix_float(h, *p);
+ break;
+ }
+ case CAML_BA_COMPLEX64:
+ num_elts *= 2; /* fallthrough */
+ case CAML_BA_FLOAT64:
+ {
+ double * p = b->data;
+ if (num_elts > 32) num_elts = 32;
+ for (n = 0; n < num_elts; n++, p++) h = caml_hash_mix_double(h, *p);
+ break;
+ }
+ }
+ return h;
+}
+
+static void caml_ba_serialize_longarray(void * data,
+ intnat num_elts,
+ intnat min_val, intnat max_val)
+{
+#ifdef ARCH_SIXTYFOUR
+ int overflow_32 = 0;
+ intnat * p, n;
+ for (n = 0, p = data; n < num_elts; n++, p++) {
+ if (*p < min_val || *p > max_val) { overflow_32 = 1; break; }
+ }
+ if (overflow_32) {
+ caml_serialize_int_1(1);
+ caml_serialize_block_8(data, num_elts);
+ } else {
+ caml_serialize_int_1(0);
+ for (n = 0, p = data; n < num_elts; n++, p++)
+ caml_serialize_int_4((int32_t) *p);
+ }
+#else
+ caml_serialize_int_1(0);
+ caml_serialize_block_4(data, num_elts);
+#endif
+}
+
+CAMLexport void caml_ba_serialize(value v,
+ uintnat * wsize_32,
+ uintnat * wsize_64)
+{
+ struct caml_ba_array * b = Caml_ba_array_val(v);
+ intnat num_elts;
+ int i;
+
+ /* Serialize header information */
+ caml_serialize_int_4(b->num_dims);
+ caml_serialize_int_4(b->flags & (CAML_BA_KIND_MASK | CAML_BA_LAYOUT_MASK));
+ /* On a 64-bit machine, if any of the dimensions is >= 2^32,
+ the size of the marshaled data will be >= 2^32 and
+ extern_value() will fail. So, it is safe to write the dimensions
+ as 32-bit unsigned integers. */
+ for (i = 0; i < b->num_dims; i++) caml_serialize_int_4(b->dim[i]);
+ /* Compute total number of elements */
+ num_elts = 1;
+ for (i = 0; i < b->num_dims; i++) num_elts = num_elts * b->dim[i];
+ /* Serialize elements */
+ switch (b->flags & CAML_BA_KIND_MASK) {
+ case CAML_BA_CHAR:
+ case CAML_BA_SINT8:
+ case CAML_BA_UINT8:
+ caml_serialize_block_1(b->data, num_elts); break;
+ case CAML_BA_SINT16:
+ case CAML_BA_UINT16:
+ caml_serialize_block_2(b->data, num_elts); break;
+ case CAML_BA_FLOAT32:
+ case CAML_BA_INT32:
+ caml_serialize_block_4(b->data, num_elts); break;
+ case CAML_BA_COMPLEX32:
+ caml_serialize_block_4(b->data, num_elts * 2); break;
+ case CAML_BA_FLOAT64:
+ case CAML_BA_INT64:
+ caml_serialize_block_8(b->data, num_elts); break;
+ case CAML_BA_COMPLEX64:
+ caml_serialize_block_8(b->data, num_elts * 2); break;
+ case CAML_BA_CAML_INT:
+ caml_ba_serialize_longarray(b->data, num_elts, -0x40000000, 0x3FFFFFFF);
+ break;
+ case CAML_BA_NATIVE_INT:
+ caml_ba_serialize_longarray(b->data, num_elts, -0x80000000, 0x7FFFFFFF);
+ break;
+ }
+ /* Compute required size in OCaml heap. Assumes struct caml_ba_array
+ is exactly 4 + num_dims words */
+ CAMLassert(SIZEOF_BA_ARRAY == 4 * sizeof(value));
+ *wsize_32 = (4 + b->num_dims) * 4;
+ *wsize_64 = (4 + b->num_dims) * 8;
+}
+
+static void caml_ba_deserialize_longarray(void * dest, intnat num_elts)
+{
+ int sixty = caml_deserialize_uint_1();
+#ifdef ARCH_SIXTYFOUR
+ if (sixty) {
+ caml_deserialize_block_8(dest, num_elts);
+ } else {
+ intnat * p, n;
+ for (n = 0, p = dest; n < num_elts; n++, p++)
+ *p = caml_deserialize_sint_4();
+ }
+#else
+ if (sixty)
+ caml_deserialize_error("input_value: cannot read bigarray "
+ "with 64-bit OCaml ints");
+ caml_deserialize_block_4(dest, num_elts);
+#endif
+}
+
+CAMLexport uintnat caml_ba_deserialize(void * dst)
+{
+ struct caml_ba_array * b = dst;
+ int i, elt_size;
+ uintnat num_elts;
+
+ /* Read back header information */
+ b->num_dims = caml_deserialize_uint_4();
+ b->flags = caml_deserialize_uint_4() | CAML_BA_MANAGED;
+ b->proxy = NULL;
+ for (i = 0; i < b->num_dims; i++) b->dim[i] = caml_deserialize_uint_4();
+ /* Compute total number of elements */
+ num_elts = caml_ba_num_elts(b);
+ /* Determine element size in bytes */
+ if ((b->flags & CAML_BA_KIND_MASK) > CAML_BA_CHAR)
+ caml_deserialize_error("input_value: bad bigarray kind");
+ elt_size = caml_ba_element_size[b->flags & CAML_BA_KIND_MASK];
+ /* Allocate room for data */
+ b->data = malloc(elt_size * num_elts);
+ if (b->data == NULL)
+ caml_deserialize_error("input_value: out of memory for bigarray");
+ /* Read data */
+ switch (b->flags & CAML_BA_KIND_MASK) {
+ case CAML_BA_CHAR:
+ case CAML_BA_SINT8:
+ case CAML_BA_UINT8:
+ caml_deserialize_block_1(b->data, num_elts); break;
+ case CAML_BA_SINT16:
+ case CAML_BA_UINT16:
+ caml_deserialize_block_2(b->data, num_elts); break;
+ case CAML_BA_FLOAT32:
+ case CAML_BA_INT32:
+ caml_deserialize_block_4(b->data, num_elts); break;
+ case CAML_BA_COMPLEX32:
+ caml_deserialize_block_4(b->data, num_elts * 2); break;
+ case CAML_BA_FLOAT64:
+ case CAML_BA_INT64:
+ caml_deserialize_block_8(b->data, num_elts); break;
+ case CAML_BA_COMPLEX64:
+ caml_deserialize_block_8(b->data, num_elts * 2); break;
+ case CAML_BA_CAML_INT:
+ case CAML_BA_NATIVE_INT:
+ caml_ba_deserialize_longarray(b->data, num_elts); break;
+ }
+ /* PR#5516: use C99's flexible array types if possible */
+ return SIZEOF_BA_ARRAY + b->num_dims * sizeof(intnat);
+}
opcode_t local_callback_code[7];
#endif
- Assert(narg + 4 <= 256);
+ CAMLassert(narg + 4 <= 256);
caml_extern_sp -= narg + 4;
for (i = 0; i < narg; i++) caml_extern_sp[i] = args[i]; /* arguments */
CAMLprim value caml_register_named_value(value vname, value val)
{
struct named_value * nv;
- char * name = String_val(vname);
+ const char * name = String_val(vname);
size_t namelen = strlen(name);
unsigned int h = hash_value_name(name);
it might belong to. */
#define Is_young(val) \
- (Assert (Is_block (val)), \
+ (CAMLassert (Is_block (val)), \
(addr)(val) < (addr)caml_young_end && (addr)(val) > (addr)caml_young_start)
#define Is_in_heap(a) (Classify_addr(a) & In_heap)
CAMLextern value caml_alloc_tuple (mlsize_t wosize);
CAMLextern value caml_alloc_float_array (mlsize_t len);
CAMLextern value caml_alloc_string (mlsize_t len); /* len in bytes (chars) */
+CAMLextern value caml_alloc_initialized_string (mlsize_t len, const char *);
CAMLextern value caml_copy_string (char const *);
CAMLextern value caml_copy_string_array (char const **);
CAMLextern value caml_copy_double (double);
CAMLextern value caml_copy_nativeint (intnat); /* defined in [ints.c] */
CAMLextern value caml_alloc_array (value (*funct) (char const *),
char const ** array);
-CAMLextern value caml_alloc_sprintf(const char * format, ...);
+CAMLextern value caml_alloc_sprintf(const char * format, ...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 1, 2)))
+#endif
+;
CAMLextern value caml_alloc_with_profinfo (mlsize_t, tag_t, intnat);
CAMLextern value caml_alloc_small_with_my_or_given_profinfo (
#ifndef NATIVE_CODE
/* Path to the file containing debug information, if any, or NULL. */
-CAMLextern char * caml_cds_file;
+CAMLextern char_os * caml_cds_file;
/* Primitive called _only_ by runtime to record unwinded frames to
* backtrace. A similar primitive exists for native code, but with a
--- /dev/null
+/**************************************************************************/
+/* */
+/* OCaml */
+/* */
+/* Manuel Serrano and Xavier Leroy, INRIA Rocquencourt */
+/* */
+/* Copyright 2000 Institut National de Recherche en Informatique et */
+/* en Automatique. */
+/* */
+/* All rights reserved. This file is distributed under the terms of */
+/* the GNU Lesser General Public License version 2.1, with the */
+/* special exception on linking described in the file LICENSE. */
+/* */
+/**************************************************************************/
+
+#ifndef CAML_BIGARRAY_H
+#define CAML_BIGARRAY_H
+
+#ifndef CAML_NAME_SPACE
+#include "compatibility.h"
+#endif
+#include "config.h"
+#include "mlvalues.h"
+
+typedef signed char caml_ba_int8;
+typedef unsigned char caml_ba_uint8;
+#if defined(HAS_STDINT_H)
+typedef int16_t caml_ba_int16;
+typedef uint16_t caml_ba_uint16;
+#elif SIZEOF_SHORT == 2
+typedef short caml_ba_int16;
+typedef unsigned short caml_ba_uint16;
+#else
+#error "No 16-bit integer type available"
+#endif
+
+#define CAML_BA_MAX_NUM_DIMS 16
+
+enum caml_ba_kind {
+ CAML_BA_FLOAT32, /* Single-precision floats */
+ CAML_BA_FLOAT64, /* Double-precision floats */
+ CAML_BA_SINT8, /* Signed 8-bit integers */
+ CAML_BA_UINT8, /* Unsigned 8-bit integers */
+ CAML_BA_SINT16, /* Signed 16-bit integers */
+ CAML_BA_UINT16, /* Unsigned 16-bit integers */
+ CAML_BA_INT32, /* Signed 32-bit integers */
+ CAML_BA_INT64, /* Signed 64-bit integers */
+ CAML_BA_CAML_INT, /* OCaml-style integers (signed 31 or 63 bits) */
+ CAML_BA_NATIVE_INT, /* Platform-native long integers (32 or 64 bits) */
+ CAML_BA_COMPLEX32, /* Single-precision complex */
+ CAML_BA_COMPLEX64, /* Double-precision complex */
+ CAML_BA_CHAR, /* Characters */
+ CAML_BA_KIND_MASK = 0xFF /* Mask for kind in flags field */
+};
+
+#define Caml_ba_kind_val(v) Int_val(v)
+
+#define Val_caml_ba_kind(k) Val_int(k)
+
+enum caml_ba_layout {
+ CAML_BA_C_LAYOUT = 0, /* Row major, indices start at 0 */
+ CAML_BA_FORTRAN_LAYOUT = 0x100, /* Column major, indices start at 1 */
+ CAML_BA_LAYOUT_MASK = 0x100, /* Mask for layout in flags field */
+ CAML_BA_LAYOUT_SHIFT = 8 /* Bit offset of layout flag */
+};
+
+#define Caml_ba_layout_val(v) (Int_val(v) << CAML_BA_LAYOUT_SHIFT)
+
+#define Val_caml_ba_layout(l) Val_int(l >> CAML_BA_LAYOUT_SHIFT)
+
+enum caml_ba_managed {
+ CAML_BA_EXTERNAL = 0, /* Data is not allocated by OCaml */
+ CAML_BA_MANAGED = 0x200, /* Data is allocated by OCaml */
+ CAML_BA_MAPPED_FILE = 0x400, /* Data is a memory mapped file */
+ CAML_BA_MANAGED_MASK = 0x600 /* Mask for "managed" bits in flags field */
+};
+
+struct caml_ba_proxy {
+ intnat refcount; /* Reference count */
+ void * data; /* Pointer to base of actual data */
+ uintnat size; /* Size of data in bytes (if mapped file) */
+};
+
+struct caml_ba_array {
+ void * data; /* Pointer to raw data */
+ intnat num_dims; /* Number of dimensions */
+ intnat flags; /* Kind of element array + memory layout + allocation status */
+ struct caml_ba_proxy * proxy; /* The proxy for sub-arrays, or NULL */
+ /* PR#5516: use C99's flexible array types if possible */
+#if (__STDC_VERSION__ >= 199901L)
+ intnat dim[] /*[num_dims]*/; /* Size in each dimension */
+#else
+ intnat dim[1] /*[num_dims]*/; /* Size in each dimension */
+#endif
+};
+
+/* Size of struct caml_ba_array, in bytes, without dummy first dimension */
+#if (__STDC_VERSION__ >= 199901L)
+#define SIZEOF_BA_ARRAY sizeof(struct caml_ba_array)
+#else
+#define SIZEOF_BA_ARRAY (sizeof(struct caml_ba_array) - sizeof(intnat))
+#endif
+
+#define Caml_ba_array_val(v) ((struct caml_ba_array *) Data_custom_val(v))
+
+#define Caml_ba_data_val(v) (Caml_ba_array_val(v)->data)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+CAMLextern value
+ caml_ba_alloc(int flags, int num_dims, void * data, intnat * dim);
+CAMLextern value caml_ba_alloc_dims(int flags, int num_dims, void * data,
+ ... /*dimensions, with type intnat */);
+CAMLextern uintnat caml_ba_byte_size(struct caml_ba_array * b);
+CAMLextern uintnat caml_ba_num_elts(struct caml_ba_array * b);
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef CAML_INTERNALS
+
+CAMLextern int caml_ba_element_size[];
+CAMLextern void caml_ba_finalize(value v);
+CAMLextern int caml_ba_compare(value v1, value v2);
+CAMLextern intnat caml_ba_hash(value v);
+CAMLextern void caml_ba_serialize(value, uintnat *, uintnat *);
+CAMLextern uintnat caml_ba_deserialize(void * dst);
+
+#endif
+
+#endif /* CAML_BIGARRAY_H */
typedef void (*caml_named_action) (value*, char *);
CAMLextern void caml_iterate_named_values(caml_named_action f);
-CAMLextern void caml_main (char ** argv);
-CAMLextern void caml_startup (char ** argv);
-CAMLextern value caml_startup_exn (char ** argv);
+CAMLextern void caml_main (char_os ** argv);
+CAMLextern void caml_startup (char_os ** argv);
+CAMLextern value caml_startup_exn (char_os ** argv);
+CAMLextern void caml_startup_pooled (char_os ** argv);
+CAMLextern value caml_startup_pooled_exn (char_os ** argv);
+CAMLextern void caml_shutdown (void);
CAMLextern int caml_callback_depth;
void caml_compact_heap (void);
void caml_compact_heap_maybe (void);
-void invert_root (value v, value *p);
+void caml_invert_root (value v, value *p);
#endif /* CAML_INTERNALS */
#ifndef CAML_CONFIG_H
#define CAML_CONFIG_H
-/* <include ../config/m.h> */
-/* <include ../config/s.h> */
+/* <include m.h> */
+/* <include s.h> */
/* <private> */
-#include "../../config/m.h"
-#include "../../config/s.h"
+#include "m.h"
+#include "s.h"
#ifdef BOOTSTRAPPING_FLEXLINK
#undef SUPPORT_DYNAMIC_LINKING
#endif
-/* </private> */
#ifndef CAML_NAME_SPACE
#include "compatibility.h"
#include <stdint.h>
#endif
+#ifndef ARCH_SIZET_PRINTF_FORMAT
+#define ARCH_SIZET_PRINTF_FORMAT "z"
+#endif
+
/* Types for 32-bit integers, 64-bit integers, and
native integers (as wide as a pointer type) */
#endif
#ifndef ARCH_INT64_TYPE
-#if SIZEOF_LONGLONG == 8
-#define ARCH_INT64_TYPE long long
-#define ARCH_UINT64_TYPE unsigned long long
-#define ARCH_INT64_PRINTF_FORMAT "ll"
-#elif SIZEOF_LONG == 8
+#if SIZEOF_LONG == 8
#define ARCH_INT64_TYPE long
#define ARCH_UINT64_TYPE unsigned long
#define ARCH_INT64_PRINTF_FORMAT "l"
+#elif SIZEOF_LONGLONG == 8
+#define ARCH_INT64_TYPE long long
+#define ARCH_UINT64_TYPE unsigned long long
+#define ARCH_INT64_PRINTF_FORMAT "ll"
#else
#error "No 64-bit integer type available"
#endif
/* Build the table of primitives, given a search path, a list
of shared libraries, and a list of primitive names
(all three 0-separated in char arrays).
- Abort the runtime system on error. */
-extern void caml_build_primitive_table(char * lib_path,
- char * libs,
+ Abort the runtime system on error.
+ Calling this frees caml_shared_libs_path (not touching its contents). */
+extern void caml_build_primitive_table(char_os * lib_path,
+ char_os * libs,
char * req_prims);
/* The search path for shared libraries */
Used for executables generated by ocamlc -output-obj. */
extern void caml_build_primitive_table_builtin(void);
+/* Unload all the previously loaded shared libraries */
+extern void caml_free_shared_libs(void);
+
#endif /* CAML_INTERNALS */
#endif /* CAML_DYNLINK_H */
struct longjmp_buffer {
sigjmp_buf buf;
};
+#elif defined(__MINGW64__) && defined(__GNUC__) && __GNUC__ >= 4
+/* MPR#7638: issues with setjmp/longjmp in Mingw64, use GCC builtins instead */
+struct longjmp_buffer {
+ intptr_t buf[5];
+};
+#define sigsetjmp(buf,save) __builtin_setjmp(buf)
+#define siglongjmp(buf,val) __builtin_longjmp(buf,val)
#else
struct longjmp_buffer {
jmp_buf buf;
/* This depends on the layout of the header. See [mlvalues.h]. */
#define Make_header(wosize, tag, color) \
- (/*Assert ((wosize) <= Max_wosize),*/ \
+ (/*CAMLassert ((wosize) <= Max_wosize),*/ \
((header_t) (((header_t) (wosize) << 10) \
+ (color) \
+ (tag_t) (tag))) \
/* executed just before calling the entry point of a dynamically
loaded native code module. */
-CAMLextern void (*caml_natdynlink_hook)(void* handle, char* unit);
+CAMLextern void (*caml_natdynlink_hook)(void* handle, const char* unit);
#endif /* NATIVE_CODE */
enum {
CHANNEL_FLAG_FROM_SOCKET = 1, /* For Windows */
#if defined(NATIVE_CODE) && defined(WITH_SPACETIME)
- CHANNEL_FLAG_BLOCKING_WRITE = 2,
+ CHANNEL_FLAG_BLOCKING_WRITE = 2, /* Don't release master lock when writing */
#endif
+ CHANNEL_FLAG_MANAGED_BY_GC = 4, /* Free and close using GC finalization */
};
/* For an output channel:
#define Subphase_mark_final 12
/* Subphase_mark_final: At the start of this subphase register which
value with an ocaml finalizer are not marked, the associated
- finalizer will be run later. So we mark now these value as alive,
+ finalizer will be run later. So we mark now these values as alive,
since they must be available for their finalizer.
*/
void caml_finish_major_cycle (void);
void caml_set_major_window (int);
-#endif /* CAML_INTERNALS */
+/* Forces finalisation of all heap-allocated values,
+ disregarding both local and global roots.
+
+ Warning: finalisation is performed by means of forced sweeping, which may
+ result in pointers referencing nonexistent values; therefore the function
+ should only be used on runtime shutdown.
+*/
+void caml_finalise_heap (void);
+
+#endif /* CAML_INTERNALiS */
#endif /* CAML_MAJOR_GC_H */
CAMLextern void caml_modify (value *, value);
CAMLextern void caml_initialize (value *, value);
CAMLextern value caml_check_urgent_gc (value);
-CAMLextern void * caml_stat_alloc (asize_t); /* Size in bytes. */
-CAMLextern void caml_stat_free (void *);
-CAMLextern void * caml_stat_resize (void *, asize_t); /* Size in bytes. */
CAMLextern int caml_init_alloc_for_heap (void);
CAMLextern char *caml_alloc_for_heap (asize_t request); /* Size in bytes. */
CAMLextern void caml_free_for_heap (char *mem);
CAMLextern int caml_huge_fallback_count;
+
+/* [caml_stat_*] functions below provide an interface to the static memory
+ manager built into the runtime, which can be used for managing static
+ (that is, non-moving) blocks of heap memory.
+
+ Function arguments that have type [caml_stat_block] must always be pointers
+ to blocks returned by the [caml_stat_*] functions below. Attempting to use
+ these functions on memory blocks allocated by a different memory manager
+ (e.g. the one from the C runtime) will cause undefined behaviour.
+*/
+typedef void* caml_stat_block;
+
+#ifdef CAML_INTERNALS
+
+/* The pool must be initialized with a call to [caml_stat_create_pool]
+ before it is possible to use any of the [caml_stat_*] functions below.
+
+ If the pool is not initialized, [caml_stat_*] functions will still work in
+ backward compatibility mode, becoming thin wrappers around [malloc] family
+ of functions. In this case, calling [caml_stat_destroy_pool] will not free
+ the claimed heap memory, resulting in leaks.
+*/
+CAMLextern void caml_stat_create_pool(void);
+
+/* [caml_stat_destroy_pool] frees all the heap memory claimed by the pool.
+
+ Once the pool is destroyed, [caml_stat_*] functions will continue to work
+ in backward compatibility mode, becoming thin wrappers around [malloc]
+ family of functions.
+*/
+CAMLextern void caml_stat_destroy_pool(void);
+
+#endif /* CAML_INTERNALS */
+
+/* [caml_stat_alloc(size)] allocates a memory block of the requested [size]
+ (in bytes) and returns a pointer to it. It throws an OCaml exception in case
+ the request fails, and so requires the runtime lock to be held.
+*/
+CAMLextern caml_stat_block caml_stat_alloc(asize_t);
+
+/* [caml_stat_alloc_noexc(size)] allocates a memory block of the requested [size]
+ (in bytes) and returns a pointer to it, or NULL in case the request fails.
+*/
+CAMLextern caml_stat_block caml_stat_alloc_noexc(asize_t);
+
+/* [caml_stat_alloc_aligned(size, modulo, block*)] allocates a memory block of
+ the requested [size] (in bytes), the starting address of which is aligned to
+ the provided [modulo] value. The function returns the aligned address, as
+ well as the unaligned [block] (as an output parameter). It throws an OCaml
+ exception in case the request fails, and so requires the runtime lock.
+*/
+CAMLextern void* caml_stat_alloc_aligned(asize_t, int modulo, caml_stat_block*);
+
+/* [caml_stat_alloc_aligned_noexc] is a variant of [caml_stat_alloc_aligned]
+ that returns NULL in case the request fails, and doesn't require the runtime
+ lock to be held.
+*/
+CAMLextern void* caml_stat_alloc_aligned_noexc(asize_t, int modulo,
+ caml_stat_block*);
+
+/* [caml_stat_calloc_noexc(num, size)] allocates a block of memory for an array
+ of [num] elements, each of them [size] bytes long, and initializes all its
+ bits to zero, effectively allocating a zero-initialized memory block of
+ [num * size] bytes. It returns NULL in case the request fails.
+*/
+CAMLextern caml_stat_block caml_stat_calloc_noexc(asize_t, asize_t);
+
+/* [caml_stat_free(block)] deallocates the provided [block]. */
+CAMLextern void caml_stat_free(caml_stat_block);
+
+/* [caml_stat_resize(block, size)] changes the size of the provided [block] to
+ [size] bytes. The function may move the memory block to a new location (whose
+ address is returned by the function). The content of the [block] is preserved
+ up to the smaller of the new and old sizes, even if the block is moved to a
+ new location. If the new size is larger, the value of the newly allocated
+ portion is indeterminate. The function throws an OCaml exception in case the
+ request fails, and so requires the runtime lock to be held.
+*/
+CAMLextern caml_stat_block caml_stat_resize(caml_stat_block, asize_t);
+
+/* [caml_stat_resize_noexc] is a variant of [caml_stat_resize] that returns NULL
+ in case the request fails, and doesn't require the runtime lock.
+*/
+CAMLextern caml_stat_block caml_stat_resize_noexc(caml_stat_block, asize_t);
+
+
+/* A [caml_stat_block] containing a NULL-terminated string */
+typedef char* caml_stat_string;
+
+/* [caml_stat_strdup(s)] returns a pointer to a heap-allocated string which is a
+ copy of the NULL-terminated string [s]. It throws an OCaml exception in case
+ the request fails, and so requires the runtime lock to be held.
+*/
+CAMLextern caml_stat_string caml_stat_strdup(const char *s);
+#ifdef _WIN32
+CAMLextern wchar_t* caml_stat_wcsdup(const wchar_t *s);
+#endif
+
+/* [caml_stat_strdup_noexc] is a variant of [caml_stat_strdup] that returns NULL
+ in case the request fails, and doesn't require the runtime lock.
+*/
+CAMLextern caml_stat_string caml_stat_strdup_noexc(const char *s);
+
+/* [caml_stat_strconcat(nargs, strings)] concatenates NULL-terminated [strings]
+ (an array of [char*] of size [nargs]) into a new string, dropping all NULLs,
+ except for the very last one. It throws an OCaml exception in case the
+ request fails, and so requires the runtime lock to be held.
+*/
+CAMLextern caml_stat_string caml_stat_strconcat(int n, ...);
+#ifdef _WIN32
+CAMLextern wchar_t* caml_stat_wcsconcat(int n, ...);
+#endif
+
+
/* void caml_shrink_heap (char *); Only used in compact.c */
#ifdef CAML_INTERNALS
#define DEBUG_clear(result, wosize)
#endif
-#define Alloc_small_with_profinfo(result, wosize, tag, profinfo) do { \
- CAMLassert ((wosize) >= 1); \
- CAMLassert ((tag_t) (tag) < 256); \
- CAMLassert ((wosize) <= Max_young_wosize); \
- caml_young_ptr -= Whsize_wosize (wosize); \
- if (caml_young_ptr < caml_young_trigger){ \
- caml_young_ptr += Whsize_wosize (wosize); \
- CAML_INSTR_INT ("force_minor/alloc_small@", 1); \
- Setup_for_gc; \
- caml_gc_dispatch (); \
- Restore_after_gc; \
- caml_young_ptr -= Whsize_wosize (wosize); \
- } \
- Hd_hp (caml_young_ptr) = \
- Make_header_with_profinfo ((wosize), (tag), Caml_black, profinfo); \
- (result) = Val_hp (caml_young_ptr); \
- DEBUG_clear ((result), (wosize)); \
+#define Alloc_small_with_profinfo(result, wosize, tag, profinfo) do { \
+ CAMLassert ((wosize) >= 1); \
+ CAMLassert ((tag_t) (tag) < 256); \
+ CAMLassert ((wosize) <= Max_young_wosize); \
+ caml_young_ptr -= Whsize_wosize (wosize); \
+ if (caml_young_ptr < caml_young_trigger){ \
+ caml_young_ptr += Whsize_wosize (wosize); \
+ CAML_INSTR_INT ("force_minor/alloc_small@", 1); \
+ Setup_for_gc; \
+ caml_gc_dispatch (); \
+ Restore_after_gc; \
+ caml_young_ptr -= Whsize_wosize (wosize); \
+ } \
+ Hd_hp (caml_young_ptr) = \
+ Make_header_with_profinfo ((wosize), (tag), Caml_black, profinfo); \
+ (result) = Val_hp (caml_young_ptr); \
+ DEBUG_clear ((result), (wosize)); \
}while(0)
#if defined(NATIVE_CODE) && defined(WITH_SPACETIME)
ephe_ref = tbl->ptr++;
ephe_ref->ephe = ar;
ephe_ref->offset = offset;
- Assert(ephe_ref->offset < Wosize_val(ephe_ref->ephe));
+ CAMLassert(ephe_ref->offset < Wosize_val(ephe_ref->ephe));
}
static inline void add_to_custom_table (struct caml_custom_table *tbl, value v,
which supports both GCC/Clang and MSVC.
Note: CAMLnoreturn is a different macro defined in memory.h,
- to be used in function bodies rather than aprototype attribute.
+ to be used in function bodies rather than as a prototype attribute.
*/
#ifdef __GNUC__
/* Works only in GCC 2.5 and later */
#define CAMLprim
#define CAMLextern extern
-/* Weak function definitions that can be overriden by external libs */
+/* Weak function definitions that can be overridden by external libs */
/* Conservatively restricted to ELF and MacOSX platforms */
#if defined(__GNUC__) && (defined (__ELF__) || defined(__APPLE__))
#define CAMLweakdef __attribute__((weak))
char *fmt2, char *arg2)
CAMLnoreturn_end;
-/* Safe string operations */
+/* Detection of available C built-in functions, the Clang way. */
+
+#ifdef __has_builtin
+#define Caml_has_builtin(x) __has_builtin(x)
+#else
+#define Caml_has_builtin(x) 0
+#endif
+
+/* Integer arithmetic with overflow detection.
+ The functions return 0 if no overflow, 1 if overflow.
+ The result of the operation is always stored at [*res].
+ If no overflow is reported, this is the exact result.
+ If overflow is reported, this is the exact result modulo 2 to the word size.
+*/
+
+static inline int caml_uadd_overflow(uintnat a, uintnat b, uintnat * res)
+{
+#if __GNUC__ >= 5 || Caml_has_builtin(__builtin_add_overflow)
+ return __builtin_add_overflow(a, b, res);
+#else
+ uintnat c = a + b;
+ *res = c;
+ return c < a;
+#endif
+}
+
+static inline int caml_usub_overflow(uintnat a, uintnat b, uintnat * res)
+{
+#if __GNUC__ >= 5 || Caml_has_builtin(__builtin_sub_overflow)
+ return __builtin_sub_overflow(a, b, res);
+#else
+ uintnat c = a - b;
+ *res = c;
+ return a < b;
+#endif
+}
+
+#if __GNUC__ >= 5 || Caml_has_builtin(__builtin_mul_overflow)
+static inline int caml_umul_overflow(uintnat a, uintnat b, uintnat * res)
+{
+ return __builtin_mul_overflow(a, b, res);
+}
+#else
+extern int caml_umul_overflow(uintnat a, uintnat b, uintnat * res);
+#endif
+
+/* Windows Unicode support */
+
+#ifdef _WIN32
+
+typedef wchar_t char_os;
+
+#define _T(x) L ## x
+
+#define access_os _waccess
+#define open_os _wopen
+#define stat_os _wstati64
+#define unlink_os _wunlink
+#define rename_os caml_win32_rename
+#define chdir_os _wchdir
+#define getcwd_os _wgetcwd
+#define getenv_os _wgetenv
+#define system_os _wsystem
+#define rmdir_os _wrmdir
+#define utime_os _wutime
+#define putenv_os _wputenv
+#define chmod_os _wchmod
+#define execv_os _wexecv
+#define execve_os _wexecve
+#define execvp_os _wexecvp
+#define execvpe_os _wexecvpe
+#define strcmp_os wcscmp
+#define strlen_os wcslen
+#define sscanf_os swscanf
+
+#define caml_stat_strdup_os caml_stat_wcsdup
+#define caml_stat_strconcat_os caml_stat_wcsconcat
+
+#define caml_stat_strdup_to_os caml_stat_strdup_to_utf16
+#define caml_stat_strdup_of_os caml_stat_strdup_of_utf16
+#define caml_copy_string_of_os caml_copy_string_of_utf16
+
+#else /* _WIN32 */
+
+typedef char char_os;
+
+#define _T(x) x
+
+#define access_os access
+#define open_os open
+#define stat_os stat
+#define unlink_os unlink
+#define rename_os rename
+#define chdir_os chdir
+#define getcwd_os getcwd
+#define getenv_os getenv
+#define system_os system
+#define rmdir_os rmdir
+#define utime_os utime
+#define putenv_os putenv
+#define chmod_os chmod
+#define execv_os execv
+#define execve_os execve
+#define execvp_os execvp
+#define execvpe_os execvpe
+#define strcmp_os strcmp
+#define strlen_os strlen
+#define sscanf_os sscanf
+
+#define caml_stat_strdup_os caml_stat_strdup
+#define caml_stat_strconcat_os caml_stat_strconcat
+
+#define caml_stat_strdup_to_os caml_stat_strdup
+#define caml_stat_strdup_of_os caml_stat_strdup
+#define caml_copy_string_of_os caml_copy_string
+
+#endif /* _WIN32 */
-CAMLextern char * caml_strdup(const char * s);
-CAMLextern char * caml_strconcat(int n, ...); /* n args of const char * type */
/* Use macros for some system calls being called from OCaml itself.
These calls can be either traced for security reasons, or changed to
#ifndef CAML_WITH_CPLUGINS
#define CAML_SYS_EXIT(retcode) exit(retcode)
-#define CAML_SYS_OPEN(filename,flags,perm) open(filename,flags,perm)
+#define CAML_SYS_OPEN(filename,flags,perm) open_os(filename,flags,perm)
#define CAML_SYS_CLOSE(fd) close(fd)
-#define CAML_SYS_STAT(filename,st) stat(filename,st)
-#define CAML_SYS_UNLINK(filename) unlink(filename)
-#define CAML_SYS_RENAME(old_name,new_name) rename(old_name, new_name)
-#define CAML_SYS_CHDIR(dirname) chdir(dirname)
-#define CAML_SYS_GETENV(varname) getenv(varname)
-#define CAML_SYS_SYSTEM(command) system(command)
+#define CAML_SYS_STAT(filename,st) stat_os(filename,st)
+#define CAML_SYS_UNLINK(filename) unlink_os(filename)
+#define CAML_SYS_RENAME(old_name,new_name) rename_os(old_name, new_name)
+#define CAML_SYS_CHDIR(dirname) chdir_os(dirname)
+#define CAML_SYS_GETENV(varname) getenv_os(varname)
+#define CAML_SYS_SYSTEM(command) system_os(command)
#define CAML_SYS_READ_DIRECTORY(dirname,tbl) caml_read_directory(dirname,tbl)
#else
caml_cplugins_prim(code,(intnat) (arg1),0,0)
#define CAML_SYS_STRING_PRIM_1(code,prim,arg1) \
(caml_cplugins_prim == NULL) ? prim(arg1) : \
- (char*)caml_cplugins_prim(code,(intnat) (arg1),0,0)
+ (char_os*)caml_cplugins_prim(code,(intnat) (arg1),0,0)
#define CAML_SYS_VOID_PRIM_1(code,prim,arg1) \
(caml_cplugins_prim == NULL) ? prim(arg1) : \
(void)caml_cplugins_prim(code,(intnat) (arg1),0,0)
#define CAML_SYS_EXIT(retcode) \
CAML_SYS_VOID_PRIM_1(CAML_CPLUGINS_EXIT,exit,retcode)
#define CAML_SYS_OPEN(filename,flags,perm) \
- CAML_SYS_PRIM_3(CAML_CPLUGINS_OPEN,open,filename,flags,perm)
+ CAML_SYS_PRIM_3(CAML_CPLUGINS_OPEN,open_os,filename,flags,perm)
#define CAML_SYS_CLOSE(fd) \
CAML_SYS_PRIM_1(CAML_CPLUGINS_CLOSE,close,fd)
#define CAML_SYS_STAT(filename,st) \
- CAML_SYS_PRIM_2(CAML_CPLUGINS_STAT,stat,filename,st)
+ CAML_SYS_PRIM_2(CAML_CPLUGINS_STAT,stat_os,filename,st)
#define CAML_SYS_UNLINK(filename) \
- CAML_SYS_PRIM_1(CAML_CPLUGINS_UNLINK,unlink,filename)
+ CAML_SYS_PRIM_1(CAML_CPLUGINS_UNLINK,unlink_os,filename)
#define CAML_SYS_RENAME(old_name,new_name) \
- CAML_SYS_PRIM_2(CAML_CPLUGINS_RENAME,rename,old_name,new_name)
+ CAML_SYS_PRIM_2(CAML_CPLUGINS_RENAME,rename_os,old_name,new_name)
#define CAML_SYS_CHDIR(dirname) \
- CAML_SYS_PRIM_1(CAML_CPLUGINS_CHDIR,chdir,dirname)
+ CAML_SYS_PRIM_1(CAML_CPLUGINS_CHDIR,chdir_os,dirname)
#define CAML_SYS_GETENV(varname) \
- CAML_SYS_STRING_PRIM_1(CAML_CPLUGINS_GETENV,getenv,varname)
+ CAML_SYS_STRING_PRIM_1(CAML_CPLUGINS_GETENV,getenv_os,varname)
#define CAML_SYS_SYSTEM(command) \
- CAML_SYS_PRIM_1(CAML_CPLUGINS_SYSTEM,system,command)
+ CAML_SYS_PRIM_1(CAML_CPLUGINS_SYSTEM,system_os,command)
#define CAML_SYS_READ_DIRECTORY(dirname,tbl) \
CAML_SYS_PRIM_2(CAML_CPLUGINS_READ_DIRECTORY,caml_read_directory, \
dirname,tbl)
struct cplugin_context {
int api_version;
int prims_bitmap;
- char *exe_name;
- char** argv;
- char *plugin; /* absolute filename of plugin, do a copy if you need it ! */
+ char_os *exe_name;
+ char_os** argv;
+ char_os *plugin; /* absolute filename of plugin, do a copy if you need it ! */
char *ocaml_version;
/* end of CAML_CPLUGIN_CONTEXT_API version 0 */
};
-extern void caml_cplugins_init(char * exe_name, char **argv);
+extern void caml_cplugins_init(char_os * exe_name, char_os **argv);
/* A plugin MUST define a symbol "caml_cplugin_init" with the prototype:
extern void caml_ext_table_free(struct ext_table * tbl, int free_entries);
extern void caml_ext_table_clear(struct ext_table * tbl, int free_entries);
-CAMLextern int caml_read_directory(char * dirname, struct ext_table * contents);
+CAMLextern int caml_read_directory(char_os * dirname, struct ext_table * contents);
+/* Deprecated aliases */
+#define caml_aligned_malloc caml_stat_alloc_aligned_noexc
+#define caml_strdup caml_stat_strdup
+#define caml_strconcat caml_stat_strconcat
#ifdef CAML_INTERNALS
/* GC flags and messages */
extern uintnat caml_verb_gc;
-void caml_gc_message (int, char *, uintnat);
+void caml_gc_message (int, char *, ...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 2, 3)))
+#endif
+;
/* Runtime warnings */
extern uintnat caml_runtime_warnings;
int caml_runtime_warnings_active(void);
-/* Memory routines */
-
-char *caml_aligned_malloc (asize_t bsize, int, void **);
-
#ifdef DEBUG
#ifdef ARCH_SIXTYFOUR
#define Debug_tag(x) (0xD700D7D7D700D6D7ul \
04 -> fields deallocated by [caml_obj_truncate]
10 -> uninitialised fields of minor objects
11 -> uninitialised fields of major objects
- 15 -> uninitialised words of [caml_aligned_malloc] blocks
- 85 -> filler bytes of [caml_aligned_malloc]
+ 15 -> uninitialised words of [caml_stat_alloc_aligned] blocks
+ 85 -> filler bytes of [caml_stat_alloc_aligned]
+ 99 -> the magic prefix of a memory block allocated by [caml_stat_alloc]
special case (byte by byte):
D7 -> uninitialised words of [caml_stat_alloc] blocks
#define Debug_uninit_major Debug_tag (0x11)
#define Debug_uninit_align Debug_tag (0x15)
#define Debug_filler_align Debug_tag (0x85)
+#define Debug_pool_magic Debug_tag (0x99)
#define Debug_uninit_stat 0xD7
#endif /* DEBUG */
-#ifndef CAML_AVOID_CONFLICTS
-#define Assert CAMLassert
-#endif
-
/* snprintf emulation for Win32 */
#if defined(_WIN32) && !defined(_UCRT)
#define CAML_INSTR_ALLOC(t) do{ \
if (caml_stat_minor_collections >= CAML_INSTR_STARTTIME \
&& caml_stat_minor_collections < CAML_INSTR_STOPTIME){ \
- t = malloc (sizeof (struct CAML_INSTR_BLOCK)); \
+ t = caml_stat_alloc_noexc (sizeof (struct CAML_INSTR_BLOCK)); \
t->index = 0; \
t->tag[0] = ""; \
t->next = CAML_INSTR_LOG; \
*/
-#define PROFINFO_SHIFT (64 - PROFINFO_WIDTH)
-#define PROFINFO_MASK ((1ull << PROFINFO_WIDTH) - 1ull)
-
#define Tag_hd(hd) ((tag_t) ((hd) & 0xFF))
+
+#define Gen_profinfo_shift(width) (64 - (width))
+#define Gen_profinfo_mask(width) ((1ull << (width)) - 1ull)
+#define Gen_profinfo_hd(width, hd) \
+ (((mlsize_t) ((hd) >> (Gen_profinfo_shift(width)))) \
+ & (Gen_profinfo_mask(width)))
+
#ifdef WITH_PROFINFO
+#define PROFINFO_SHIFT (Gen_profinfo_shift(PROFINFO_WIDTH))
+#define PROFINFO_MASK (Gen_profinfo_mask(PROFINFO_WIDTH))
#define Hd_no_profinfo(hd) ((hd) & ~(PROFINFO_MASK << PROFINFO_SHIFT))
#define Wosize_hd(hd) ((mlsize_t) ((Hd_no_profinfo(hd)) >> 10))
+#define Profinfo_hd(hd) (Gen_profinfo_hd(PROFINFO_WIDTH, hd))
#else
#define Wosize_hd(hd) ((mlsize_t) ((hd) >> 10))
#endif /* WITH_PROFINFO */
-#if defined(ARCH_SIXTYFOUR) && defined(WITH_PROFINFO)
-/* [Profinfo_hd] is used when the compiler is not configured for Spacetime
- (e.g. when decoding profiles). */
-#define Profinfo_hd(hd) (((mlsize_t) ((hd) >> PROFINFO_SHIFT)) & PROFINFO_MASK)
-#else
-#define Profinfo_hd(hd) ((hd) & 0)
-#endif /* ARCH_SIXTYFOUR && WITH_PROFINFO */
#define Hd_val(val) (((header_t *) (val)) [-1]) /* Also an l-value. */
#define Hd_op(op) (Hd_val (op)) /* Also an l-value. */
/* Strings. */
#define String_tag 252
+#ifdef CAML_SAFE_STRING
+#define String_val(x) ((const char *) Bp_val(x))
+#else
#define String_val(x) ((char *) Bp_val(x))
+#endif
+#define Bytes_val(x) ((unsigned char *) Bp_val(x))
CAMLextern mlsize_t caml_string_length (value); /* size in bytes */
CAMLextern int caml_string_is_c_safe (value);
/* true if string contains no '\0' null characters */
/* Arrays of floating-point numbers. */
#define Double_array_tag 254
-#define Double_field(v,i) Double_val((value)((double *)(v) + (i)))
-#define Store_double_field(v,i,d) do{ \
+
+/* The [_flat_field] macros are for [floatarray] values and float-only records.
+*/
+#define Double_flat_field(v,i) Double_val((value)((double *)(v) + (i)))
+#define Store_double_flat_field(v,i,d) do{ \
mlsize_t caml__temp_i = (i); \
double caml__temp_d = (d); \
Store_double_val((value)((double *) (v) + caml__temp_i), caml__temp_d); \
}while(0)
+
+/* The [_array_field] macros are for [float array]. */
+#ifdef FLAT_FLOAT_ARRAY
+ #define Double_array_field(v,i) Double_flat_field(v,i)
+ #define Store_double_array_field(v,i,d) Store_double_flat_field(v,i,d)
+#else
+ #define Double_array_field(v,i) Double_val (Field(v,i))
+ CAMLextern void caml_Store_double_array_field (value, mlsize_t, double);
+ #define Store_double_array_field(v,i,d) caml_Store_double_array_field (v,i,d)
+#endif
+
+/* The old [_field] macros are for backward compatibility only.
+ They work with [floatarray], float-only records, and [float array]. */
+#ifdef FLAT_FLOAT_ARRAY
+ #define Double_field(v,i) Double_flat_field(v,i)
+ #define Store_double_field(v,i,d) Store_double_flat_field(v,i,d)
+#else
+ static inline double Double_field (value v, mlsize_t i) {
+ if (Tag_val (v) == Double_array_tag){
+ return Double_flat_field (v, i);
+ }else{
+ return Double_array_field (v, i);
+ }
+ }
+ static inline void Store_double_field (value v, mlsize_t i, double d) {
+ if (Tag_val (v) == Double_array_tag){
+ Store_double_flat_field (v, i, d);
+ }else{
+ Store_double_array_field (v, i, d);
+ }
+ }
+#endif /* FLAT_FLOAT_ARRAY */
+
CAMLextern mlsize_t caml_array_length (value); /* size in items */
CAMLextern int caml_is_double_array (value); /* 0 is false, 1 is true */
#ifndef CAML_OSDEPS_H
#define CAML_OSDEPS_H
+#ifdef _WIN32
+extern unsigned short caml_win32_major;
+extern unsigned short caml_win32_minor;
+extern unsigned short caml_win32_build;
+extern unsigned short caml_win32_revision;
+#endif
+
#ifdef CAML_INTERNALS
#include "misc.h"
+#include "memory.h"
/* Read at most [n] bytes from file descriptor [fd] into buffer [buf].
[flags] indicates whether [fd] is a socket
extern int caml_write_fd(int fd, int flags, void * buf, int n);
/* Decompose the given path into a list of directories, and add them
- to the given table. Return the block to be freed later. */
-extern char * caml_decompose_path(struct ext_table * tbl, char * path);
+ to the given table. */
+extern char_os * caml_decompose_path(struct ext_table * tbl, char_os * path);
/* Search the given file in the given list of directories.
- If not found, return a copy of [name]. Result is allocated with
- [caml_stat_alloc]. */
-extern char * caml_search_in_path(struct ext_table * path, char * name);
+ If not found, return a copy of [name]. */
+extern char_os * caml_search_in_path(struct ext_table * path, const char_os * name);
/* Same, but search an executable name in the system path for executables. */
-CAMLextern char * caml_search_exe_in_path(char * name);
+CAMLextern char_os * caml_search_exe_in_path(const char_os * name);
/* Same, but search a shared library in the given path. */
-extern char * caml_search_dll_in_path(struct ext_table * path, char * name);
+extern char_os * caml_search_dll_in_path(struct ext_table * path, const char_os * name);
/* Open a shared library and return a handle on it.
If [for_execution] is true, perform full symbol resolution and
If [global] is true, symbols from the shared library can be used
to resolve for other libraries to be opened later on.
Return [NULL] on error. */
-extern void * caml_dlopen(char * libname, int for_execution, int global);
+extern void * caml_dlopen(char_os * libname, int for_execution, int global);
/* Close a shared library handle */
extern void caml_dlclose(void * handle);
/* Look up the given symbol in the given shared library.
Return [NULL] if not found, or symbol value if found. */
-extern void * caml_dlsym(void * handle, char * name);
+extern void * caml_dlsym(void * handle, const char * name);
-extern void * caml_globalsym(char * name);
+extern void * caml_globalsym(const char * name);
/* Return an error message describing the most recent dynlink failure. */
extern char * caml_dlerror(void);
/* Add to [contents] the (short) names of the files contained in
the directory named [dirname]. No entries are added for [.] and [..].
Return 0 on success, -1 on error; set errno in the case of error. */
-extern int caml_read_directory(char * dirname, struct ext_table * contents);
+extern int caml_read_directory(char_os * dirname, struct ext_table * contents);
/* Recover executable name if possible (/proc/sef/exe under Linux,
GetModuleFileName under Windows). Return NULL on error,
string allocated with [caml_stat_alloc] on success. */
-extern char * caml_executable_name(void);
+extern char_os * caml_executable_name(void);
/* Secure version of [getenv]: returns NULL if the process has special
privileges (setuid bit, setgid bit, capabilities).
*/
-extern char *caml_secure_getenv(char const *var);
+extern char_os *caml_secure_getenv(char_os const *var);
+
+#ifdef _WIN32
+
+extern int caml_win32_rename(const wchar_t *, const wchar_t *);
+
+extern void caml_probe_win32_version(void);
+extern void caml_setup_win32_terminal(void);
+extern void caml_restore_win32_terminal(void);
+
+/* Windows Unicode support */
+
+extern int win_multi_byte_to_wide_char(const char* s, int slen, wchar_t *out, int outlen);
+extern int win_wide_char_to_multi_byte(const wchar_t* s, int slen, char *out, int outlen);
+
+/* [caml_stat_strdup_to_utf16(s)] returns a NULL-terminated copy of [s],
+ re-encoded in UTF-16. The encoding of [s] is assumed to be UTF-8 if
+ [caml_windows_unicode_runtime_enabled] is non-zero **and** [s] is valid
+ UTF-8, or the current Windows code page otherwise.
+
+ The returned string is allocated with [caml_stat_alloc], so it should be free
+ using [caml_stat_free].
+*/
+extern wchar_t* caml_stat_strdup_to_utf16(const char *s);
+
+/* [caml_stat_strdup_of_utf16(s)] returns a NULL-terminated copy of [s],
+ re-encoded in UTF-8 if [caml_windows_unicode_runtime_enabled] is non-zero or
+ the current Windows code page otherwise.
+
+ The returned string is allocated with [caml_stat_alloc], so it should be free
+ using [caml_stat_free].
+*/
+extern char* caml_stat_strdup_of_utf16(const wchar_t *s);
+
+/* [caml_copy_string_of_utf16(s)] returns an OCaml string containing a copy of
+ [s] re-encoded in UTF-8 if [caml_windows_unicode_runtime_enabled] is non-zero
+ or in the current code page otherwise.
+*/
+extern value caml_copy_string_of_utf16(const wchar_t *s);
+
+#endif /* _WIN32 */
#endif /* CAML_INTERNALS */
#define Alloc_point_next_ptr(node, offset) (Field(node, offset + 2))
/* Direct call points (tail or non-tail) within OCaml nodes.
- They just hold a pointer to the child node. The call site and callee are
- both recorded in the shape. */
+ They hold a pointer to the child node and (if the compiler was so
+ configured) a call count.
+ The call site and callee are both recorded in the shape. */
#define Direct_callee_node(node,offset) (Field(node, offset))
+#define Direct_call_count(node,offset) (Field(node, offset + 1))
#define Encode_call_point_pc(pc) (((value) pc) | 1)
#define Decode_call_point_pc(pc) ((void*) (((value) pc) & ~((uintnat) 1)))
value next;
} allocation_point;
+typedef struct {
+ value callee_node;
+ value call_count;
+} call_point;
+
typedef struct {
/* CR-soon mshinwell: delete [gc_header], all the offset arithmetic will
then go away */
uintnat gc_header;
uintnat pc; /* see above for encodings */
union {
- value callee_node; /* for CALL */
+ call_point call; /* for CALL */
allocation_point allocation; /* for ALLOCATION */
} data;
value next; /* [Val_unit] for the end of the list */
/* Macros to access the stack frame */
-#ifdef TARGET_sparc
-#define Saved_return_address(sp) *((intnat *)((sp) + 92))
-#define Callback_link(sp) ((struct caml_context *)((sp) + 104))
-#endif
-
#ifdef TARGET_i386
#define Saved_return_address(sp) *((intnat *)((sp) - 4))
#ifndef SYS_win32
#include "mlvalues.h"
#include "exec.h"
-CAMLextern void caml_main(char **argv);
+CAMLextern void caml_main(char_os **argv);
CAMLextern void caml_startup_code(
code_t code, asize_t code_size,
char *data, asize_t data_size,
char *section_table, asize_t section_table_size,
- char **argv);
+ int pooling,
+ char_os **argv);
CAMLextern value caml_startup_code_exn(
code_t code, asize_t code_size,
char *data, asize_t data_size,
char *section_table, asize_t section_table_size,
- char **argv);
+ int pooling,
+ char_os **argv);
enum { FILE_NOT_FOUND = -1, BAD_BYTECODE = -2 };
-extern int caml_attempt_open(char **name, struct exec_trailer *trail,
+extern int caml_attempt_open(char_os **name, struct exec_trailer *trail,
int do_open_script);
extern void caml_read_section_descriptors(int fd, struct exec_trailer *trail);
extern int32_t caml_seek_optional_section(int fd, struct exec_trailer *trail,
extern uintnat caml_init_max_stack_wsz;
extern uintnat caml_init_major_window;
extern uintnat caml_trace_level;
+extern uintnat caml_cleanup_on_exit;
extern void caml_parse_ocamlrunparam (void);
+/* Common entry point to caml_startup.
+ Returns 0 if the runtime is already initialized.
+ If [pooling] is 0, [caml_stat_*] functions will not be backed by a pool. */
+extern int caml_startup_aux (int pooling);
+
#endif /* CAML_INTERNALS */
#endif /* CAML_STARTUP_AUX_H */
CAMLextern void caml_sys_error (value);
CAMLextern void caml_sys_io_error (value);
CAMLextern double caml_sys_time_unboxed(value);
-CAMLextern void caml_sys_init (char * exe_name, char ** argv);
+CAMLextern void caml_sys_init (char_os * exe_name, char_os ** argv);
CAMLextern value caml_sys_exit (value);
extern double caml_sys_time_unboxed(value);
CAMLextern value caml_sys_get_argv(value unit);
-extern char * caml_exe_name;
+extern char_os * caml_exe_name;
#ifdef __cplusplus
}
int release_data = 0;
mlsize_t size, i;
header_t hd;
- Assert(caml_gc_phase == Phase_clean);
+ CAMLassert(caml_gc_phase == Phase_clean);
hd = Hd_val (v);
size = Wosize_hd (hd);
Field (v, 1) = caml_ephe_none;
} else {
/* The mark phase must have marked it */
- Assert( !(Is_block (child) && Is_in_heap (child)
+ CAMLassert( !(Is_block (child) && Is_in_heap (child)
&& Is_white_val (child)) );
}
}
static void invert_pointer_at (word *p)
{
word q = *p;
- Assert (Ecolor ((intnat) p) == 0);
+ CAMLassert (Ecolor ((intnat) p) == 0);
/* Use Ecolor (q) == 0 instead of Is_block (q) because q could be an
inverted pointer for an infix header (with Ecolor == 2). */
word *hp = (word *) Hp_val (val);
while (Ecolor (*hp) == 0) hp = (word *) *hp;
- Assert (Ecolor (*hp) == 3);
+ CAMLassert (Ecolor (*hp) == 3);
if (Tag_ehd (*hp) == Closure_tag){
/* This is the first infix found in this block. */
/* Save original header. */
/* Change block header's tag to Infix_tag, and change its size
to point to the infix list. */
*hp = Make_ehd (Wosize_bhsize (q - val), Infix_tag, 3, (uintnat) 0);
- }else{ Assert (Tag_ehd (*hp) == Infix_tag);
+ }else{
+ CAMLassert (Tag_ehd (*hp) == Infix_tag);
/* Point the last of this infix list to the current first infix
list of the block. */
*p = (word) &Field (val, Wosize_ehd (*hp)) | 1;
}
}
-void invert_root (value v, value *p)
+void caml_invert_root (value v, value *p)
{
invert_pointer_at ((word *) p);
}
}
chunk = compact_fl;
while (Chunk_size (chunk) - Chunk_alloc (chunk) < size){
- chunk = Chunk_next (chunk); Assert (chunk != NULL);
+ chunk = Chunk_next (chunk);
+ CAMLassert (chunk != NULL);
}
adr = chunk + Chunk_alloc (chunk);
Chunk_alloc (chunk) += size;
static void do_compaction (void)
{
char *ch, *chend;
- Assert (caml_gc_phase == Phase_idle);
- caml_gc_message (0x10, "Compacting heap...\n", 0);
+ CAMLassert (caml_gc_phase == Phase_idle);
+ caml_gc_message (0x10, "Compacting heap...\n");
#ifdef DEBUG
caml_heap_check ();
if (Is_blue_hd (hd)){
/* Free object. Give it a string tag. */
Hd_hp (p) = Make_ehd (sz, String_tag, 3, (uintnat) 0);
- }else{ Assert (Is_white_hd (hd));
+ }else{
+ CAMLassert (Is_white_hd (hd));
/* Live object. Keep its tag. */
Hd_hp (p) = Make_ehd (sz, Tag_hd (hd), 3, Profinfo_hd (hd));
}
/* Invert roots first because the threads library needs some heap
data structures to find its roots. Fortunately, it doesn't need
the headers (see above). */
- caml_do_roots (invert_root, 1);
+ caml_do_roots (caml_invert_root, 1);
/* The values to be finalised are not roots but should still be inverted */
caml_final_invert_finalisable_values ();
if (t == Infix_tag){
/* Get the original header of this block. */
infixes = p + sz;
- q = *infixes; Assert (Ecolor (q) == 2);
+ q = *infixes;
+ CAMLassert (Ecolor (q) == 2);
while (Ecolor (q) != 3) q = * (word *) (q & ~(uintnat)3);
sz = Whsize_ehd (q);
t = Tag_ehd (q);
next = * (word *) q;
* (word *) q = (word) Val_hp ((word *) newadr + (infixes - p));
q = next;
- } Assert (Ecolor (q) == 1 || Ecolor (q) == 3);
+ }
+ CAMLassert (Ecolor (q) == 1 || Ecolor (q) == 3);
/* No need to preserve any profinfo value on the [Infix_tag]
headers; the Spacetime profiling heap snapshot code doesn't
look at them. */
}
}
p += sz;
- }else{ Assert (Ecolor (q) == 3);
+ }else{
+ CAMLassert (Ecolor (q) == 3);
/* This is guaranteed only if caml_compact_heap was called after a
- nonincremental major GC: Assert (Tag_ehd (q) == String_tag);
+ nonincremental major GC: CAMLassert (Tag_ehd (q) == String_tag);
*/
/* No pointers to the header and no infix header:
the object was free. */
memmove (newadr, p, sz);
p += Wsize_bsize (sz);
}else{
- Assert (Color_hd (q) == Caml_blue);
+ CAMLassert (Color_hd (q) == Caml_blue);
p += Whsize_hd (q);
}
}
}
}
++ caml_stat_compactions;
- caml_gc_message (0x10, "done.\n", 0);
+ caml_gc_message (0x10, "done.\n");
}
uintnat caml_percent_max; /* used in gc_ctrl.c and memory.c */
/* Recompact. */
char *chunk;
- caml_gc_message (0x10, "Recompacting heap (target=%luk words)\n",
+ caml_gc_message (0x10, "Recompacting heap (target=%"
+ ARCH_INTNAT_PRINTF_FORMAT "uk words)\n",
target_wsz / 1024);
chunk = caml_alloc_for_heap (Bsize_wsize (target_wsz));
caml_stat_top_heap_wsz = caml_stat_heap_wsz;
}
do_compaction ();
- Assert (caml_stat_heap_chunks == 1);
- Assert (Chunk_next (caml_heap_start) == NULL);
- Assert (caml_stat_heap_wsz == Wsize_bsize (Chunk_size (chunk)));
+ CAMLassert (caml_stat_heap_chunks == 1);
+ CAMLassert (Chunk_next (caml_heap_start) == NULL);
+ CAMLassert (caml_stat_heap_wsz == Wsize_bsize (Chunk_size (chunk)));
CAML_INSTR_TIME (tmr, "compact/recompact");
}
}
We compact the heap if FP > caml_percent_max
*/
float fw, fp;
- Assert (caml_gc_phase == Phase_idle);
+ CAMLassert (caml_gc_phase == Phase_idle);
if (caml_percent_max >= 1000000) return;
if (caml_stat_major_collections < 3) return;
if (caml_stat_heap_wsz <= 2 * caml_clip_heap_chunk_wsz (0)) return;
ARCH_INTNAT_PRINTF_FORMAT "u%%\n",
(uintnat) fp);
if (fp >= caml_percent_max){
- caml_gc_message (0x200, "Automatic compaction triggered.\n", 0);
+ caml_gc_message (0x200, "Automatic compaction triggered.\n");
caml_empty_minor_heap (); /* minor heap must be empty for compaction */
caml_finish_major_cycle ();
if (fp >= caml_percent_max)
caml_compact_heap ();
else
- caml_gc_message (0x200, "Automatic compaction aborted.\n", 0);
+ caml_gc_message (0x200, "Automatic compaction aborted.\n");
}
}
struct compare_item { value * v1, * v2; mlsize_t count; };
-#define COMPARE_STACK_INIT_SIZE 256
+#define COMPARE_STACK_INIT_SIZE 8
+#define COMPARE_STACK_MIN_ALLOC_SIZE 32
#define COMPARE_STACK_MAX_SIZE (1024*1024)
-
-static struct compare_item compare_stack_init[COMPARE_STACK_INIT_SIZE];
-
-static struct compare_item * compare_stack = compare_stack_init;
-static struct compare_item * compare_stack_limit = compare_stack_init
- + COMPARE_STACK_INIT_SIZE;
-
CAMLexport int caml_compare_unordered;
+struct compare_stack {
+ struct compare_item init_stack[COMPARE_STACK_INIT_SIZE];
+ struct compare_item* stack;
+ struct compare_item* limit;
+};
+
/* Free the compare stack if needed */
-static void compare_free_stack(void)
+static void compare_free_stack(struct compare_stack* stk)
{
- if (compare_stack != compare_stack_init) {
- free(compare_stack);
- /* Reinitialize the globals for next time around */
- compare_stack = compare_stack_init;
- compare_stack_limit = compare_stack + COMPARE_STACK_INIT_SIZE;
+ if (stk->stack != stk->init_stack) {
+ caml_stat_free(stk->stack);
+ stk->stack = NULL;
}
}
/* Same, then raise Out_of_memory */
-static void compare_stack_overflow(void)
+static void compare_stack_overflow(struct compare_stack* stk)
{
- caml_gc_message (0x04, "Stack overflow in structural comparison\n", 0);
- compare_free_stack();
+ caml_gc_message (0x04, "Stack overflow in structural comparison\n");
+ compare_free_stack(stk);
caml_raise_out_of_memory();
}
/* Grow the compare stack */
-static struct compare_item * compare_resize_stack(struct compare_item * sp)
+static struct compare_item * compare_resize_stack(struct compare_stack* stk,
+ struct compare_item * sp)
{
- asize_t newsize = 2 * (compare_stack_limit - compare_stack);
- asize_t sp_offset = sp - compare_stack;
+ asize_t newsize;
+ asize_t sp_offset = sp - stk->stack;
struct compare_item * newstack;
- if (newsize >= COMPARE_STACK_MAX_SIZE) compare_stack_overflow();
- if (compare_stack == compare_stack_init) {
- newstack = malloc(sizeof(struct compare_item) * newsize);
- if (newstack == NULL) compare_stack_overflow();
- memcpy(newstack, compare_stack_init,
+ if (stk->stack == stk->init_stack) {
+ newsize = COMPARE_STACK_MIN_ALLOC_SIZE;
+ newstack = caml_stat_alloc_noexc(sizeof(struct compare_item) * newsize);
+ if (newstack == NULL) compare_stack_overflow(stk);
+ memcpy(newstack, stk->init_stack,
sizeof(struct compare_item) * COMPARE_STACK_INIT_SIZE);
} else {
- newstack =
- realloc(compare_stack, sizeof(struct compare_item) * newsize);
- if (newstack == NULL) compare_stack_overflow();
+ newsize = 2 * (stk->limit - stk->stack);
+ if (newsize >= COMPARE_STACK_MAX_SIZE) compare_stack_overflow(stk);
+ newstack = caml_stat_resize_noexc(stk->stack,
+ sizeof(struct compare_item) * newsize);
+ if (newstack == NULL) compare_stack_overflow(stk);
}
- compare_stack = newstack;
- compare_stack_limit = newstack + newsize;
+ stk->stack = newstack;
+ stk->limit = newstack + newsize;
return newstack + sp_offset;
}
+
+static intnat do_compare_val(struct compare_stack* stk,
+ value v1, value v2, int total);
+
+static intnat compare_val(value v1, value v2, int total)
+{
+ struct compare_stack stk;
+ intnat res;
+ stk.stack = stk.init_stack;
+ stk.limit = stk.stack + COMPARE_STACK_INIT_SIZE;
+ res = do_compare_val(&stk, v1, v2, total);
+ compare_free_stack(&stk);
+ return res;
+}
+
/* Structural comparison */
+
#define LESS -1
#define EQUAL 0
#define GREATER 1
< 0 and > UNORDERED v1 is less than v2
UNORDERED v1 and v2 cannot be compared */
-static intnat compare_val(value v1, value v2, int total)
+static intnat do_compare_val(struct compare_stack* stk,
+ value v1, value v2, int total)
{
struct compare_item * sp;
tag_t t1, t2;
- sp = compare_stack;
+ sp = stk->stack;
while (1) {
if (v1 == v2 && total) goto next_item;
if (Is_long(v1)) {
mlsize_t i;
if (sz1 != sz2) return sz1 - sz2;
for (i = 0; i < sz1; i++) {
- double d1 = Double_field(v1, i);
- double d2 = Double_field(v2, i);
-#ifdef LACKS_SANE_NAN
+ double d1 = Double_flat_field(v1, i);
+ double d2 = Double_flat_field(v2, i);
+ #ifdef LACKS_SANE_NAN
if (isnan(d2)) {
if (! total) return UNORDERED;
if (isnan(d1)) break;
if (! total) return UNORDERED;
return LESS;
}
-#endif
+ #endif
if (d1 < d2) return LESS;
if (d1 > d2) return GREATER;
-#ifndef LACKS_SANE_NAN
+ #ifndef LACKS_SANE_NAN
if (d1 != d2) {
if (! total) return UNORDERED;
/* See comment for Double_tag case */
if (d1 == d1) return GREATER;
if (d2 == d2) return LESS;
}
-#endif
+ #endif
}
break;
}
case Abstract_tag:
- compare_free_stack();
+ compare_free_stack(stk);
caml_invalid_argument("compare: abstract value");
case Closure_tag:
case Infix_tag:
- compare_free_stack();
+ compare_free_stack(stk);
caml_invalid_argument("compare: functional value");
case Object_tag: {
intnat oid1 = Oid_val(v1);
? LESS : GREATER;
}
if (compare == NULL) {
- compare_free_stack();
+ compare_free_stack(stk);
caml_invalid_argument("compare: abstract value");
}
caml_compare_unordered = 0;
/* Remember that we still have to compare fields 1 ... sz - 1 */
if (sz1 > 1) {
sp++;
- if (sp >= compare_stack_limit) sp = compare_resize_stack(sp);
+ if (sp >= stk->limit) sp = compare_resize_stack(stk, sp);
sp->v1 = &Field(v1, 1);
sp->v2 = &Field(v2, 1);
sp->count = sz1 - 1;
}
next_item:
/* Pop one more item to compare, if any */
- if (sp == compare_stack) return EQUAL; /* we're done */
+ if (sp == stk->stack) return EQUAL; /* we're done */
v1 = *((sp->v1)++);
v2 = *((sp->v2)++);
if (--(sp->count) == 0) sp--;
{
intnat res = compare_val(v1, v2, 1);
/* Free stack if needed */
- if (compare_stack != compare_stack_init) compare_free_stack();
if (res < 0)
return Val_int(LESS);
else if (res > 0)
CAMLprim value caml_equal(value v1, value v2)
{
intnat res = compare_val(v1, v2, 0);
- if (compare_stack != compare_stack_init) compare_free_stack();
return Val_int(res == 0);
}
CAMLprim value caml_notequal(value v1, value v2)
{
intnat res = compare_val(v1, v2, 0);
- if (compare_stack != compare_stack_init) compare_free_stack();
return Val_int(res != 0);
}
CAMLprim value caml_lessthan(value v1, value v2)
{
intnat res = compare_val(v1, v2, 0);
- if (compare_stack != compare_stack_init) compare_free_stack();
return Val_int(res < 0 && res != UNORDERED);
}
CAMLprim value caml_lessequal(value v1, value v2)
{
intnat res = compare_val(v1, v2, 0);
- if (compare_stack != compare_stack_init) compare_free_stack();
return Val_int(res <= 0 && res != UNORDERED);
}
CAMLprim value caml_greaterthan(value v1, value v2)
{
intnat res = compare_val(v1, v2, 0);
- if (compare_stack != compare_stack_init) compare_free_stack();
return Val_int(res > 0);
}
CAMLprim value caml_greaterequal(value v1, value v2)
{
intnat res = compare_val(v1, v2, 0);
- if (compare_stack != compare_stack_init) compare_free_stack();
return Val_int(res >= 0);
}
{
struct custom_operations_list * l =
caml_stat_alloc(sizeof(struct custom_operations_list));
- Assert(ops->identifier != NULL);
- Assert(ops->deserialize != NULL);
+ CAMLassert(ops->identifier != NULL);
+ CAMLassert(ops->deserialize != NULL);
l->ops = ops;
l->next = custom_ops_table;
custom_ops_table = l;
extern struct custom_operations caml_int32_ops,
caml_nativeint_ops,
- caml_int64_ops;
+ caml_int64_ops,
+ caml_ba_ops;
void caml_init_custom_operations(void)
{
caml_register_custom_operations(&caml_int32_ops);
caml_register_custom_operations(&caml_nativeint_ops);
caml_register_custom_operations(&caml_int64_ops);
+ caml_register_custom_operations(&caml_ba_ops);
}
static struct channel * dbg_in; /* Input channel on the socket */
static struct channel * dbg_out;/* Output channel on the socket */
-static char *dbg_addr = "(none)";
+static char *dbg_addr = NULL;
static void open_connection(void)
{
#endif
if (dbg_socket == -1 ||
connect(dbg_socket, &sock_addr.s_gen, sock_addr_len) == -1){
- caml_fatal_error_arg2 ("cannot connect to debugger at %s\n", dbg_addr,
+ caml_fatal_error_arg2 ("cannot connect to debugger at %s\n", (dbg_addr ? dbg_addr : "(none)"),
"error: %s\n", strerror (errno));
}
#ifdef _WIN32
void caml_debugger_init(void)
{
char * address;
+ char_os * a;
char * port, * p;
struct hostent * host;
int n;
Store_field(marshal_flags, 0, Val_int(1)); /* Marshal.Closures */
Store_field(marshal_flags, 1, Val_emptylist);
- address = caml_secure_getenv("CAML_DEBUG_SOCKET");
+ a = caml_secure_getenv(_T("CAML_DEBUG_SOCKET"));
+ address = a ? caml_stat_strdup_of_os(a) : NULL;
if (address == NULL) return;
+ if (dbg_addr != NULL) caml_stat_free(dbg_addr);
dbg_addr = address;
#ifdef _WIN32
switch(caml_getch(dbg_in)) {
case REQ_SET_EVENT:
pos = caml_getword(dbg_in);
- Assert (pos >= 0);
- Assert (pos < caml_code_size);
+ CAMLassert (pos >= 0);
+ CAMLassert (pos < caml_code_size);
caml_set_instruction(caml_start_code + pos / sizeof(opcode_t), EVENT);
break;
case REQ_SET_BREAKPOINT:
pos = caml_getword(dbg_in);
- Assert (pos >= 0);
- Assert (pos < caml_code_size);
+ CAMLassert (pos >= 0);
+ CAMLassert (pos < caml_code_size);
caml_set_instruction(caml_start_code + pos / sizeof(opcode_t), BREAK);
break;
case REQ_RESET_INSTR:
pos = caml_getword(dbg_in);
- Assert (pos >= 0);
- Assert (pos < caml_code_size);
+ CAMLassert (pos >= 0);
+ CAMLassert (pos < caml_code_size);
pos = pos / sizeof(opcode_t);
caml_set_instruction(caml_start_code + pos, caml_saved_code[pos]);
break;
caml_putch(dbg_out, 0);
putval(dbg_out, Field(val, i));
} else {
- double d = Double_field(val, i);
+ double d = Double_flat_field(val, i);
caml_putch(dbg_out, 1);
caml_really_putblock(dbg_out, (char *) &d, 8);
}
/* Parse the OCAML_STDLIB_DIR/ld.conf file and add the directories
listed there to the search path */
-#define LD_CONF_NAME "ld.conf"
+#define LD_CONF_NAME _T("ld.conf")
-static char * parse_ld_conf(void)
+static char_os * parse_ld_conf(void)
{
- char * stdlib, * ldconfname, * config, * p, * q;
+ char_os * stdlib, * ldconfname, * wconfig, * p, * q;
+ char * config;
+#ifdef _WIN32
+ struct _stati64 st;
+#else
struct stat st;
+#endif
int ldconf, nread;
- stdlib = caml_secure_getenv("OCAMLLIB");
- if (stdlib == NULL) stdlib = caml_secure_getenv("CAMLLIB");
+ stdlib = caml_secure_getenv(_T("OCAMLLIB"));
+ if (stdlib == NULL) stdlib = caml_secure_getenv(_T("CAMLLIB"));
if (stdlib == NULL) stdlib = OCAML_STDLIB_DIR;
- ldconfname = caml_strconcat(3, stdlib, "/", LD_CONF_NAME);
- if (stat(ldconfname, &st) == -1) {
+ ldconfname = caml_stat_strconcat_os(3, stdlib, _T("/"), LD_CONF_NAME);
+ if (stat_os(ldconfname, &st) == -1) {
caml_stat_free(ldconfname);
return NULL;
}
- ldconf = open(ldconfname, O_RDONLY, 0);
+ ldconf = open_os(ldconfname, O_RDONLY, 0);
if (ldconf == -1)
caml_fatal_error_arg("Fatal error: cannot read loader config file %s\n",
- ldconfname);
+ caml_stat_strdup_of_os(ldconfname));
config = caml_stat_alloc(st.st_size + 1);
nread = read(ldconf, config, st.st_size);
if (nread == -1)
caml_fatal_error_arg
("Fatal error: error while reading loader config file %s\n",
- ldconfname);
+ caml_stat_strdup_of_os(ldconfname));
config[nread] = 0;
- q = config;
- for (p = config; *p != 0; p++) {
- if (*p == '\n') {
+ wconfig = caml_stat_strdup_to_os(config);
+ caml_stat_free(config);
+ q = wconfig;
+ for (p = wconfig; *p != 0; p++) {
+ if (*p == _T('\n')) {
*p = 0;
caml_ext_table_add(&caml_shared_libs_path, q);
q = p + 1;
if (q < p) caml_ext_table_add(&caml_shared_libs_path, q);
close(ldconf);
caml_stat_free(ldconfname);
- return config;
+ return wconfig;
}
/* Open the given shared library and add it to shared_libs.
Abort on error. */
-static void open_shared_lib(char * name)
+static void open_shared_lib(char_os * name)
{
- char * realname;
+ char_os * realname;
+ char * u8;
void * handle;
realname = caml_search_dll_in_path(&caml_shared_libs_path, name);
- caml_gc_message(0x100, "Loading shared library %s\n",
- (uintnat) realname);
+ u8 = caml_stat_strdup_of_os(realname);
+ caml_gc_message(0x100, "Loading shared library %s\n", u8);
+ caml_stat_free(u8);
caml_enter_blocking_section();
handle = caml_dlopen(realname, 1, 1);
caml_leave_blocking_section();
if (handle == NULL)
- caml_fatal_error_arg2("Fatal error: cannot load shared library %s\n", name,
+ caml_fatal_error_arg2("Fatal error: cannot load shared library %s\n",
+ caml_stat_strdup_of_os(name),
"Reason: %s\n", caml_dlerror());
caml_ext_table_add(&shared_libs, handle);
caml_stat_free(realname);
/* Build the table of primitives, given a search path and a list
of shared libraries (both 0-separated in a char array).
Abort the runtime system on error. */
-void caml_build_primitive_table(char * lib_path,
- char * libs,
+void caml_build_primitive_table(char_os * lib_path,
+ char_os * libs,
char * req_prims)
{
- char * tofree1, * tofree2;
- char * p;
+ char_os * tofree1, * tofree2;
+ char_os * p;
+ char * q;
/* Initialize the search path for dynamic libraries:
- directories specified on the command line with the -I option
- directories specified in the executable
- directories specified in the file <stdlib>/ld.conf */
tofree1 = caml_decompose_path(&caml_shared_libs_path,
- caml_secure_getenv("CAML_LD_LIBRARY_PATH"));
+ caml_secure_getenv(_T("CAML_LD_LIBRARY_PATH")));
if (lib_path != NULL)
- for (p = lib_path; *p != 0; p += strlen(p) + 1)
+ for (p = lib_path; *p != 0; p += strlen_os(p) + 1)
caml_ext_table_add(&caml_shared_libs_path, p);
tofree2 = parse_ld_conf();
/* Open the shared libraries */
caml_ext_table_init(&shared_libs, 8);
if (libs != NULL)
- for (p = libs; *p != 0; p += strlen(p) + 1)
+ for (p = libs; *p != 0; p += strlen_os(p) + 1)
open_shared_lib(p);
/* Build the primitive table */
caml_ext_table_init(&caml_prim_table, 0x180);
#ifdef DEBUG
caml_ext_table_init(&caml_prim_name_table, 0x180);
#endif
- for (p = req_prims; *p != 0; p += strlen(p) + 1) {
- c_primitive prim = lookup_primitive(p);
+ for (q = req_prims; *q != 0; q += strlen(q) + 1) {
+ c_primitive prim = lookup_primitive(q);
if (prim == NULL)
- caml_fatal_error_arg("Fatal error: unknown C primitive `%s'\n", p);
+ caml_fatal_error_arg("Fatal error: unknown C primitive `%s'\n", q);
caml_ext_table_add(&caml_prim_table, (void *) prim);
#ifdef DEBUG
- caml_ext_table_add(&caml_prim_name_table, strdup(p));
+ caml_ext_table_add(&caml_prim_name_table, caml_stat_strdup(q));
#endif
}
/* Clean up */
caml_ext_table_add(&caml_prim_table, (void *) caml_builtin_cprim[i]);
#ifdef DEBUG
caml_ext_table_add(&caml_prim_name_table,
- strdup(caml_names_of_builtin_cprim[i]));
+ caml_stat_strdup(caml_names_of_builtin_cprim[i]));
#endif
}
}
+void caml_free_shared_libs(void)
+{
+ while (shared_libs.size > 0)
+ caml_dlclose(shared_libs.contents[--shared_libs.size]);
+}
+
#endif /* NATIVE_CODE */
/** dlopen interface for the bytecode linker **/
{
void * handle;
value result;
- char * p;
+ char_os * p;
caml_gc_message(0x100, "Opening shared library %s\n",
- (uintnat) String_val(filename));
- p = caml_strdup(String_val(filename));
+ String_val(filename));
+ p = caml_stat_strdup_to_os(String_val(filename));
caml_enter_blocking_section();
handle = caml_dlopen(p, Int_val(mode), 1);
caml_leave_blocking_section();
static void extern_free_stack(void)
{
if (extern_stack != extern_stack_init) {
- free(extern_stack);
+ caml_stat_free(extern_stack);
/* Reinitialize the globals for next time around */
extern_stack = extern_stack_init;
extern_stack_limit = extern_stack + EXTERN_STACK_INIT_SIZE;
if (newsize >= EXTERN_STACK_MAX_SIZE) extern_stack_overflow();
if (extern_stack == extern_stack_init) {
- newstack = malloc(sizeof(struct extern_item) * newsize);
+ newstack = caml_stat_alloc_noexc(sizeof(struct extern_item) * newsize);
if (newstack == NULL) extern_stack_overflow();
memcpy(newstack, extern_stack_init,
sizeof(struct extern_item) * EXTERN_STACK_INIT_SIZE);
} else {
- newstack =
- realloc(extern_stack, sizeof(struct extern_item) * newsize);
+ newstack = caml_stat_resize_noexc(extern_stack,
+ sizeof(struct extern_item) * newsize);
if (newstack == NULL) extern_stack_overflow();
}
extern_stack = newstack;
}
if (blk == &extern_trail_first) break;
prevblk = blk->previous;
- free(blk);
+ caml_stat_free(blk);
blk = prevblk;
lim = &(blk->entries[ENTRIES_PER_TRAIL_BLOCK]);
}
if (extern_flags & NO_SHARING) return;
if (extern_trail_cur == extern_trail_limit) {
- struct trail_block * new_block = malloc(sizeof(struct trail_block));
+ struct trail_block * new_block = caml_stat_alloc_noexc(sizeof(struct trail_block));
if (new_block == NULL) extern_out_of_memory();
new_block->previous = extern_trail_block;
extern_trail_block = new_block;
static void init_extern_output(void)
{
extern_userprovided_output = NULL;
- extern_output_first = malloc(sizeof(struct output_block));
+ extern_output_first = caml_stat_alloc_noexc(sizeof(struct output_block));
if (extern_output_first == NULL) caml_raise_out_of_memory();
extern_output_block = extern_output_first;
extern_output_block->next = NULL;
if (extern_userprovided_output != NULL) return;
for (blk = extern_output_first; blk != NULL; blk = nextblk) {
nextblk = blk->next;
- free(blk);
+ caml_stat_free(blk);
}
extern_output_first = NULL;
extern_free_stack();
extra = 0;
else
extra = required;
- blk = malloc(sizeof(struct output_block) + extra);
+ blk = caml_stat_alloc_noexc(sizeof(struct output_block) + extra);
if (blk == NULL) extern_out_of_memory();
extern_output_block->next = blk;
extern_output_block = blk;
static void extern_stack_overflow(void)
{
- caml_gc_message (0x04, "Stack overflow in marshaling value\n", 0);
+ caml_gc_message (0x04, "Stack overflow in marshaling value\n");
extern_replay_trail();
free_extern_output();
caml_raise_out_of_memory();
*extern_ptr++ = c;
}
-static void writeblock(char * data, intnat len)
+static void writeblock(const char * data, intnat len)
{
if (extern_ptr + len > extern_limit) grow_extern_output(len);
memcpy(extern_ptr, data, len);
extern_ptr += len;
}
-static inline void writeblock_float8(double * data, intnat ndoubles)
+static inline void writeblock_float8(const double * data, intnat ndoubles)
{
#if ARCH_FLOAT_ENDIANNESS == 0x01234567 || ARCH_FLOAT_ENDIANNESS == 0x76543210
- writeblock((char *) data, ndoubles * 8);
+ writeblock((const char *) data, ndoubles * 8);
#else
caml_serialize_block_float_8(data, ndoubles);
#endif
value f = Forward_val (v);
if (Is_block (f)
&& (!Is_in_value_area(f) || Tag_val (f) == Forward_tag
- || Tag_val (f) == Lazy_tag || Tag_val (f) == Double_tag)){
+ || Tag_val (f) == Lazy_tag
+#ifdef FLAT_FLOAT_ARRAY
+ || Tag_val (f) == Double_tag
+#endif
+ )){
/* Do not short-circuit the pointer. */
}else{
v = f;
if ((extern_flags & CLOSURES) == 0)
extern_invalid_argument("output_value: functional value");
writecode32(CODE_CODEPOINTER, (char *) v - cf->code_start);
- writeblock((char *) cf->digest, 16);
+ writeblock((const char *)cf->digest, 16);
} else {
extern_invalid_argument("output_value: abstract value (outside heap)");
}
while (blk != NULL) {
caml_really_putblock(chan, blk->data, blk->end - blk->data);
nextblk = blk->next;
- free(blk);
+ caml_stat_free(blk);
blk = nextblk;
}
}
memcpy(&Byte(res, ofs), blk->data, n);
ofs += n;
nextblk = blk->next;
- free(blk);
+ caml_stat_free(blk);
blk = nextblk;
}
return res;
init_extern_output();
data_len = extern_value(v, flags, header, &header_len);
- res = malloc(header_len + data_len);
+ res = caml_stat_alloc_noexc(header_len + data_len);
if (res == NULL) extern_out_of_memory();
*buf = res;
*len = header_len + data_len;
value bucket;
int i;
- Assert(1 + nargs <= Max_young_wosize);
+ CAMLassert(1 + nargs <= Max_young_wosize);
bucket = caml_alloc_small (1 + nargs, 0);
Field(bucket, 0) = tag;
for (i = 0; i < nargs; i++) Field(bucket, 1 + i) = args[i];
/* [size] is a number of elements for the [to_do.item] array */
static void alloc_to_do (int size)
{
- struct to_do *result = malloc (sizeof (struct to_do)
- + size * sizeof (struct final));
+ struct to_do *result = caml_stat_alloc_noexc (sizeof (struct to_do) +
+ size * sizeof (struct final));
if (result == NULL) caml_fatal_error ("out of memory");
result->next = NULL;
result->size = size;
to_do_hd = result;
to_do_tl = result;
}else{
- Assert (to_do_tl->next == NULL);
+ CAMLassert (to_do_tl->next == NULL);
to_do_tl->next = result;
to_do_tl = result;
}
uintnat i, j, k;
uintnat todo_count = 0;
- Assert (final->old <= final->young);
+ CAMLassert (final->old <= final->young);
for (i = 0; i < final->old; i++){
- Assert (Is_block (final->table[i].val));
- Assert (Is_in_heap (final->table[i].val));
+ CAMLassert (Is_block (final->table[i].val));
+ CAMLassert (Is_in_heap (final->table[i].val));
if (Is_white_val (final->table[i].val)){
++ todo_count;
}
alloc_to_do (todo_count);
j = k = 0;
for (i = 0; i < final->old; i++){
- Assert (Is_block (final->table[i].val));
- Assert (Is_in_heap (final->table[i].val));
- Assert (Tag_val (final->table[i].val) != Forward_tag);
+ CAMLassert (Is_block (final->table[i].val));
+ CAMLassert (Is_in_heap (final->table[i].val));
+ CAMLassert (Tag_val (final->table[i].val) != Forward_tag);
if(Is_white_val (final->table[i].val)){
/** dead */
to_do_tl->item[k] = final->table[i];
if (running_finalisation_function) return;
if (to_do_hd != NULL){
if (caml_finalise_begin_hook != NULL) (*caml_finalise_begin_hook) ();
- caml_gc_message (0x80, "Calling finalisation functions.\n", 0);
+ caml_gc_message (0x80, "Calling finalisation functions.\n");
while (1){
while (to_do_hd != NULL && to_do_hd->size == 0){
struct to_do *next_hd = to_do_hd->next;
- free (to_do_hd);
+ caml_stat_free (to_do_hd);
to_do_hd = next_hd;
if (to_do_hd == NULL) to_do_tl = NULL;
}
if (to_do_hd == NULL) break;
- Assert (to_do_hd->size > 0);
+ CAMLassert (to_do_hd->size > 0);
-- to_do_hd->size;
f = to_do_hd->item[to_do_hd->size];
running_finalisation_function = 1;
running_finalisation_function = 0;
if (Is_exception_result (res)) caml_raise (Extract_exception (res));
}
- caml_gc_message (0x80, "Done calling finalisation functions.\n", 0);
+ caml_gc_message (0x80, "Done calling finalisation functions.\n");
if (caml_finalise_end_hook != NULL) (*caml_finalise_end_hook) ();
}
}
uintnat i;
struct to_do *todo;
- Assert (finalisable_first.old <= finalisable_first.young);
+ CAMLassert (finalisable_first.old <= finalisable_first.young);
for (i = 0; i < finalisable_first.young; i++){
Call_action (f, finalisable_first.table[i].fun);
};
- Assert (finalisable_last.old <= finalisable_last.young);
+ CAMLassert (finalisable_last.old <= finalisable_last.young);
for (i = 0; i < finalisable_last.young; i++){
Call_action (f, finalisable_last.table[i].fun);
};
}
}
-/* Call invert_root on the values of the finalisable set. This is called
+/* Call caml_invert_root on the values of the finalisable set. This is called
directly by the compactor.
*/
void caml_final_invert_finalisable_values ()
CAMLassert (finalisable_first.old <= finalisable_first.young);
for (i = 0; i < finalisable_first.young; i++){
- invert_root(finalisable_first.table[i].val,
+ caml_invert_root(finalisable_first.table[i].val,
&finalisable_first.table[i].val);
};
CAMLassert (finalisable_last.old <= finalisable_last.young);
for (i = 0; i < finalisable_last.young; i++){
- invert_root(finalisable_last.table[i].val,
+ caml_invert_root(finalisable_last.table[i].val,
&finalisable_last.table[i].val);
};
}
{
uintnat i;
- Assert (finalisable_first.old <= finalisable_first.young);
+ CAMLassert (finalisable_first.old <= finalisable_first.young);
for (i = finalisable_first.old; i < finalisable_first.young; i++){
caml_oldify_one(finalisable_first.table[i].fun,
&finalisable_first.table[i].fun);
&finalisable_first.table[i].val);
}
- Assert (finalisable_last.old <= finalisable_last.young);
+ CAMLassert (finalisable_last.old <= finalisable_last.young);
for (i = finalisable_last.old; i < finalisable_last.young; i++){
caml_oldify_one(finalisable_last.table[i].fun,
&finalisable_last.table[i].fun);
uintnat i, j, k;
uintnat todo_count = 0;
- Assert (final->old <= final->young);
+ CAMLassert (final->old <= final->young);
for (i = final->old; i < final->young; i++){
- Assert (Is_block (final->table[i].val));
- Assert (Is_in_heap_or_young (final->table[i].val));
+ CAMLassert (Is_block (final->table[i].val));
+ CAMLassert (Is_in_heap_or_young (final->table[i].val));
if (Is_young(final->table[i].val) && Hd_val(final->table[i].val) != 0){
++ todo_count;
}
k = 0;
j = final->old;
for (i = final->old; i < final->young; i++){
- Assert (Is_block (final->table[i].val));
- Assert (Is_in_heap_or_young (final->table[i].val));
- Assert (Tag_val (final->table[i].val) != Forward_tag);
+ CAMLassert (Is_block (final->table[i].val));
+ CAMLassert (Is_in_heap_or_young (final->table[i].val));
+ CAMLassert (Tag_val (final->table[i].val) != Forward_tag);
if(Is_young(final->table[j].val) && Hd_val(final->table[i].val) != 0){
/** dead */
to_do_tl->item[k] = final->table[i];
/** update the minor value to the copied major value */
for (i = final->old; i < final->young; i++){
- Assert (Is_block (final->table[i].val));
- Assert (Is_in_heap_or_young (final->table[i].val));
+ CAMLassert (Is_block (final->table[i].val));
+ CAMLassert (Is_in_heap_or_young (final->table[i].val));
if (Is_young(final->table[i].val)) {
CAMLassert (Hd_val(final->table[i].val) == 0);
final->table[i].val = Field(final->table[i].val,0);
}
/** check invariant */
- Assert (final->old <= final->young);
+ CAMLassert (final->old <= final->young);
for (i = 0; i < final->young; i++){
CAMLassert( Is_in_heap(final->table[i].val) );
};
if (!Is_block (v)
|| !Is_in_heap_or_young(v)
|| Tag_val (v) == Lazy_tag
+#ifdef FLAT_FLOAT_ARRAY
|| Tag_val (v) == Double_tag
+#endif
|| Tag_val (v) == Forward_tag) {
caml_invalid_argument ("Gc.finalise");
}
- Assert (final->old <= final->young);
+ CAMLassert (final->old <= final->young);
if (final->young >= final->size){
if (final->table == NULL){
uintnat new_size = 30;
final->table = caml_stat_alloc (new_size * sizeof (struct final));
- Assert (final->old == 0);
- Assert (final->young == 0);
+ CAMLassert (final->old == 0);
+ CAMLassert (final->young == 0);
final->size = new_size;
}else{
uintnat new_size = final->size * 2;
final->size = new_size;
}
}
- Assert (final->young < final->size);
+ CAMLassert (final->young < final->size);
final->table[final->young].fun = f;
if (Tag_val (v) == Infix_tag){
final->table[final->young].offset = Infix_offset_val (v);
p += l[instr];
}
}
- Assert(p == code + len);
+ CAMLassert(p == code + len);
}
#else
{
union { value v[2]; double d; } buffer;
- Assert(sizeof(double) == 2 * sizeof(value));
+ CAMLassert(sizeof(double) == 2 * sizeof(value));
buffer.v[0] = Field(val, 0);
buffer.v[1] = Field(val, 1);
return buffer.d;
{
union { value v[2]; double d; } buffer;
- Assert(sizeof(double) == 2 * sizeof(value));
+ CAMLassert(sizeof(double) == 2 * sizeof(value));
buffer.d = dbl;
Field(val, 0) = buffer.v[0];
Field(val, 1) = buffer.v[1];
return res;
}
+#ifndef FLAT_FLOAT_ARRAY
+CAMLexport void caml_Store_double_array_field(value val, mlsize_t i, double dbl)
+{
+ CAMLparam1 (val);
+ value d = caml_copy_double (dbl);
+
+ CAMLassert (Tag_val (val) != Double_array_tag);
+ caml_modify (&Field(val, i), d);
+ CAMLreturn0;
+}
+#endif /* ! FLAT_FLOAT_ARRAY */
+
CAMLprim value caml_format_float(value fmt, value arg)
{
value res;
CAMLprim value caml_float_of_string(value vs)
{
char parse_buffer[64];
- char * buf, * src, * dst, * end;
+ char * buf, * dst, * end;
+ const char *src;
mlsize_t len;
int sign;
double d;
cur = Next (prev);
while (cur != Val_NULL){
size_found += Whsize_bp (cur);
- Assert (Is_in_heap (cur));
+ CAMLassert (Is_in_heap (cur));
if (cur == fl_prev) prev_found = 1;
if (policy == Policy_first_fit && Wosize_bp (cur) > sz){
sz = Wosize_bp (cur);
if (flp_found < flp_size){
- Assert (Next (flp[flp_found]) == cur);
+ CAMLassert (Next (flp[flp_found]) == cur);
++ flp_found;
}else{
- Assert (beyond == Val_NULL || cur >= Next (beyond));
+ CAMLassert (beyond == Val_NULL || cur >= Next (beyond));
}
}
if (cur == caml_fl_merge) merge_found = 1;
prev = cur;
cur = Next (prev);
}
- if (policy == Policy_next_fit) Assert (prev_found || fl_prev == Fl_head);
- if (policy == Policy_first_fit) Assert (flp_found == flp_size);
- Assert (merge_found || caml_fl_merge == Fl_head);
- Assert (size_found == caml_fl_cur_wsz);
+ if (policy == Policy_next_fit) CAMLassert (prev_found || fl_prev == Fl_head);
+ if (policy == Policy_first_fit) CAMLassert (flp_found == flp_size);
+ CAMLassert (merge_found || caml_fl_merge == Fl_head);
+ CAMLassert (size_found == caml_fl_cur_wsz);
}
#endif
value cur)
{
header_t h = Hd_bp (cur);
- Assert (Whsize_hd (h) >= wh_sz);
+ CAMLassert (Whsize_hd (h) >= wh_sz);
if (Wosize_hd (h) < wh_sz + 1){ /* Cases 0 and 1. */
caml_fl_cur_wsz -= Whsize_hd (h);
Next (prev) = Next (cur);
- Assert (Is_in_heap (Next (prev)) || Next (prev) == Val_NULL);
+ CAMLassert (Is_in_heap (Next (prev)) || Next (prev) == Val_NULL);
if (caml_fl_merge == cur) caml_fl_merge = prev;
#ifdef DEBUG
fl_last = Val_NULL;
header_t *result;
int i;
mlsize_t sz, prevsz;
- Assert (sizeof (char *) == sizeof (value));
- Assert (wo_sz >= 1);
+ CAMLassert (sizeof (char *) == sizeof (value));
+ CAMLassert (wo_sz >= 1);
#ifdef CAML_INSTR
if (wo_sz < 10){
++instr_size[wo_sz];
switch (policy){
case Policy_next_fit:
- Assert (fl_prev != Val_NULL);
+ CAMLassert (fl_prev != Val_NULL);
/* Search from [fl_prev] to the end of the list. */
prev = fl_prev;
cur = Next (prev);
- while (cur != Val_NULL){ Assert (Is_in_heap (cur));
+ while (cur != Val_NULL){
+ CAMLassert (Is_in_heap (cur));
if (Wosize_bp (cur) >= wo_sz){
return allocate_block (Whsize_wosize (wo_sz), 0, prev, cur);
}
prev = flp[flp_size - 1];
}
prevsz = Wosize_bp (Next (flp[FLP_MAX-1]));
- Assert (prevsz < wo_sz);
+ CAMLassert (prevsz < wo_sz);
cur = Next (prev);
while (cur != Val_NULL){
- Assert (Is_in_heap (cur));
+ CAMLassert (Is_in_heap (cur));
sz = Wosize_bp (cur);
if (sz < prevsz){
beyond = cur;
update_flp: /* (i, sz) */
/* The block at [i] was removed or reduced. Update the table. */
- Assert (0 <= i && i < flp_size + 1);
+ CAMLassert (0 <= i && i < flp_size + 1);
if (i < flp_size){
if (i > 0){
prevsz = Wosize_bp (Next (flp[i-1]));
buf[j++] = prev;
prevsz = sz;
if (sz >= oldsz){
- Assert (sz == oldsz);
+ CAMLassert (sz == oldsz);
break;
}
}
break;
default:
- Assert (0); /* unknown policy */
+ CAMLassert (0); /* unknown policy */
break;
}
return NULL; /* NOT REACHED */
truncate_flp (Fl_head);
break;
default:
- Assert (0);
+ CAMLassert (0);
break;
}
caml_fl_cur_wsz = 0;
cur = Next (prev);
/* The sweep code makes sure that this is the right place to insert
this block: */
- Assert (prev < bp || prev == Fl_head);
- Assert (cur > bp || cur == Val_NULL);
+ CAMLassert (prev < bp || prev == Fl_head);
+ CAMLassert (cur > bp || cur == Val_NULL);
if (policy == Policy_first_fit) truncate_flp (prev);
#ifdef DEBUG
Hd_val (bp) = Debug_free_major;
#endif
- Assert (caml_fl_merge == prev);
+ CAMLassert (caml_fl_merge == prev);
}else if (Wosize_hd (hd) != 0){
Hd_val (bp) = Bluehd_hd (hd);
Next (bp) = cur;
*/
void caml_fl_add_blocks (value bp)
{
- Assert (fl_last != Val_NULL);
- Assert (Next (fl_last) == Val_NULL);
+ CAMLassert (fl_last != Val_NULL);
+ CAMLassert (Next (fl_last) == Val_NULL);
caml_fl_cur_wsz += Whsize_bp (bp);
if (bp > fl_last){
prev = Fl_head;
cur = Next (prev);
while (cur != Val_NULL && cur < bp){
- Assert (prev < bp || prev == Fl_head);
+ CAMLassert (prev < bp || prev == Fl_head);
/* XXX TODO: extend flp on the fly */
prev = cur;
cur = Next (prev);
- } Assert (prev < bp || prev == Fl_head);
- Assert (cur > bp || cur == Val_NULL);
+ }
+ CAMLassert (prev < bp || prev == Fl_head);
+ CAMLassert (cur > bp || cur == Val_NULL);
Next (Field (bp, 1)) = cur;
Next (prev) = bp;
/* When inserting blocks between [caml_fl_merge] and [caml_gc_sweep_hp],
/* Check that [v]'s header looks good. [v] must be a block in the heap. */
static void check_head (value v)
{
- Assert (Is_block (v));
- Assert (Is_in_heap (v));
+ CAMLassert (Is_block (v));
+ CAMLassert (Is_in_heap (v));
- Assert (Wosize_val (v) != 0);
- Assert (Color_hd (Hd_val (v)) != Caml_blue);
- Assert (Is_in_heap (v));
+ CAMLassert (Wosize_val (v) != 0);
+ CAMLassert (Color_hd (Hd_val (v)) != Caml_blue);
+ CAMLassert (Is_in_heap (v));
if (Tag_val (v) == Infix_tag){
int offset = Wsize_bsize (Infix_offset_val (v));
value trueval = Val_op (&Field (v, -offset));
- Assert (Tag_val (trueval) == Closure_tag);
- Assert (Wosize_val (trueval) > offset);
- Assert (Is_in_heap (&Field (trueval, Wosize_val (trueval) - 1)));
+ CAMLassert (Tag_val (trueval) == Closure_tag);
+ CAMLassert (Wosize_val (trueval) > offset);
+ CAMLassert (Is_in_heap (&Field (trueval, Wosize_val (trueval) - 1)));
}else{
- Assert (Is_in_heap (&Field (v, Wosize_val (v) - 1)));
+ CAMLassert (Is_in_heap (&Field (v, Wosize_val (v) - 1)));
}
if (Tag_val (v) == Double_tag){
- Assert (Wosize_val (v) == Double_wosize);
+ CAMLassert (Wosize_val (v) == Double_wosize);
}else if (Tag_val (v) == Double_array_tag){
- Assert (Wosize_val (v) % Double_wosize == 0);
+ CAMLassert (Wosize_val (v) % Double_wosize == 0);
}
}
case String_tag:
break;
case Double_tag:
- Assert (Wosize_val (v) == Double_wosize);
+ CAMLassert (Wosize_val (v) == Double_wosize);
break;
case Double_array_tag:
- Assert (Wosize_val (v) % Double_wosize == 0);
+ CAMLassert (Wosize_val (v) % Double_wosize == 0);
break;
case Custom_tag:
- Assert (!Is_in_heap (Custom_ops_val (v)));
+ CAMLassert (!Is_in_heap (Custom_ops_val (v)));
break;
case Infix_tag:
- Assert (0);
+ CAMLassert (0);
break;
default:
- Assert (Tag_hp (hp) < No_scan_tag);
+ CAMLassert (Tag_hp (hp) < No_scan_tag);
for (i = 0; i < Wosize_hp (hp); i++){
f = Field (v, i);
if (Is_block (f) && Is_in_heap (f)){
check_head (f);
- Assert (Color_val (f) != Caml_blue);
+ CAMLassert (Color_val (f) != Caml_blue);
}
}
}
header_t cur_hd;
#ifdef DEBUG
- caml_gc_message (-1, "### OCaml runtime: heap check ###\n", 0);
+ caml_gc_message (-1, "### OCaml runtime: heap check ###\n");
#endif
while (chunk != NULL){
cur_hp = (header_t *) chunk;
while (cur_hp < (header_t *) chunk_end){
cur_hd = Hd_hp (cur_hp);
- Assert (Next (cur_hp) <= (header_t *) chunk_end);
+ CAMLassert (Next (cur_hp) <= (header_t *) chunk_end);
switch (Color_hd (cur_hd)){
case Caml_white:
if (Wosize_hd (cur_hd) == 0){
++ fragments;
- Assert (prev_hp == NULL
- || Color_hp (prev_hp) != Caml_blue
- || cur_hp == (header_t *) caml_gc_sweep_hp);
+ CAMLassert (prev_hp == NULL
+ || Color_hp (prev_hp) != Caml_blue
+ || cur_hp == (header_t *) caml_gc_sweep_hp);
}else{
if (caml_gc_phase == Phase_sweep
&& cur_hp >= (header_t *) caml_gc_sweep_hp){
}
break;
case Caml_gray: case Caml_black:
- Assert (Wosize_hd (cur_hd) > 0);
+ CAMLassert (Wosize_hd (cur_hd) > 0);
++ live_blocks;
live_words += Whsize_hd (cur_hd);
#ifdef DEBUG
#endif
break;
case Caml_blue:
- Assert (Wosize_hd (cur_hd) > 0);
+ CAMLassert (Wosize_hd (cur_hd) > 0);
++ free_blocks;
free_words += Whsize_hd (cur_hd);
if (Whsize_hd (cur_hd) > largest_free){
largest_free = Whsize_hd (cur_hd);
}
/* not true any more with big heap chunks
- Assert (prev_hp == NULL
- || (Color_hp (prev_hp) != Caml_blue && Wosize_hp (prev_hp) > 0)
- || cur_hp == caml_gc_sweep_hp);
- Assert (Next (cur_hp) == chunk_end
- || (Color_hp (Next (cur_hp)) != Caml_blue
- && Wosize_hp (Next (cur_hp)) > 0)
- || (Whsize_hd (cur_hd) + Wosize_hp (Next (cur_hp)) > Max_wosize)
- || Next (cur_hp) == caml_gc_sweep_hp);
+ CAMLassert (prev_hp == NULL
+ || (Color_hp (prev_hp) != Caml_blue
+ && Wosize_hp (prev_hp) > 0)
+ || cur_hp == caml_gc_sweep_hp);
+ CAMLassert (Next (cur_hp) == chunk_end
+ || (Color_hp (Next (cur_hp)) != Caml_blue
+ && Wosize_hp (Next (cur_hp)) > 0)
+ || (Whsize_hd (cur_hd) + Wosize_hp (Next (cur_hp))
+ > Max_wosize)
+ || Next (cur_hp) == caml_gc_sweep_hp);
*/
break;
}
prev_hp = cur_hp;
#endif
cur_hp = Next (cur_hp);
- } Assert (cur_hp == (header_t *) chunk_end);
+ }
+ CAMLassert (cur_hp == (header_t *) chunk_end);
chunk = Chunk_next (chunk);
}
caml_final_invariant_check();
#endif
- Assert (heap_chunks == caml_stat_heap_chunks);
- Assert (live_words + free_words + fragments == caml_stat_heap_wsz);
+ CAMLassert (heap_chunks == caml_stat_heap_chunks);
+ CAMLassert (live_words + free_words + fragments == caml_stat_heap_wsz);
if (returnstats){
CAMLlocal1 (res);
{
value result;
CAML_INSTR_SETUP (tmr, "");
- Assert (v == Val_unit);
+ CAMLassert (v == Val_unit);
result = heap_stats (1);
CAML_INSTR_TIME (tmr, "explicit/gc_stat");
return result;
newpf = norm_pfree (Long_val (Field (v, 2)));
if (newpf != caml_percent_free){
caml_percent_free = newpf;
- caml_gc_message (0x20, "New space overhead: %d%%\n", caml_percent_free);
+ caml_gc_message (0x20, "New space overhead: %"
+ ARCH_INTNAT_PRINTF_FORMAT "u%%\n", caml_percent_free);
}
newpm = norm_pmax (Long_val (Field (v, 4)));
if (newpm != caml_percent_max){
caml_percent_max = newpm;
- caml_gc_message (0x20, "New max overhead: %d%%\n", caml_percent_max);
+ caml_gc_message (0x20, "New max overhead: %"
+ ARCH_INTNAT_PRINTF_FORMAT "u%%\n", caml_percent_max);
}
newheapincr = Long_val (Field (v, 1));
if (newheapincr != caml_major_heap_increment){
caml_major_heap_increment = newheapincr;
if (newheapincr > 1000){
- caml_gc_message (0x20, "New heap increment size: %luk words\n",
+ caml_gc_message (0x20, "New heap increment size: %"
+ ARCH_INTNAT_PRINTF_FORMAT "uk words\n",
caml_major_heap_increment/1024);
}else{
- caml_gc_message (0x20, "New heap increment size: %lu%%\n",
+ caml_gc_message (0x20, "New heap increment size: %"
+ ARCH_INTNAT_PRINTF_FORMAT "u%%\n",
caml_major_heap_increment);
}
}
oldpolicy = caml_allocation_policy;
caml_set_allocation_policy (Long_val (Field (v, 6)));
if (oldpolicy != caml_allocation_policy){
- caml_gc_message (0x20, "New allocation policy: %d\n",
- caml_allocation_policy);
+ caml_gc_message (0x20, "New allocation policy: %"
+ ARCH_INTNAT_PRINTF_FORMAT "u\n", caml_allocation_policy);
}
/* This field was added in 4.03.0. */
(thus invalidating [v]) and it can raise [Out_of_memory]. */
newminwsz = norm_minsize (Long_val (Field (v, 0)));
if (newminwsz != caml_minor_heap_wsz){
- caml_gc_message (0x20, "New minor heap size: %luk words\n",
- newminwsz / 1024);
+ caml_gc_message (0x20, "New minor heap size: %"
+ ARCH_SIZET_PRINTF_FORMAT "uk words\n", newminwsz / 1024);
caml_set_minor_heap_size (Bsize_wsize (newminwsz));
}
CAML_INSTR_TIME (tmr, "explicit/gc_set");
CAMLprim value caml_gc_minor(value v)
{
CAML_INSTR_SETUP (tmr, "");
- Assert (v == Val_unit);
+ CAMLassert (v == Val_unit);
caml_request_minor_gc ();
caml_gc_dispatch ();
CAML_INSTR_TIME (tmr, "explicit/gc_minor");
ARCH_INTNAT_PRINTF_FORMAT "u%%\n",
(uintnat) fp);
if (fp >= caml_percent_max){
- caml_gc_message (0x200, "Automatic compaction triggered.\n", 0);
+ caml_gc_message (0x200, "Automatic compaction triggered.\n");
caml_compact_heap ();
}
}
CAMLprim value caml_gc_major(value v)
{
CAML_INSTR_SETUP (tmr, "");
- Assert (v == Val_unit);
- caml_gc_message (0x1, "Major GC cycle requested\n", 0);
+ CAMLassert (v == Val_unit);
+ caml_gc_message (0x1, "Major GC cycle requested\n");
caml_empty_minor_heap ();
caml_finish_major_cycle ();
test_and_compact ();
CAMLprim value caml_gc_full_major(value v)
{
CAML_INSTR_SETUP (tmr, "");
- Assert (v == Val_unit);
- caml_gc_message (0x1, "Full major GC cycle requested\n", 0);
+ CAMLassert (v == Val_unit);
+ caml_gc_message (0x1, "Full major GC cycle requested\n");
caml_empty_minor_heap ();
caml_finish_major_cycle ();
caml_final_do_calls ();
CAMLprim value caml_gc_major_slice (value v)
{
CAML_INSTR_SETUP (tmr, "");
- Assert (Is_long (v));
+ CAMLassert (Is_long (v));
caml_major_collection_slice (Long_val (v));
CAML_INSTR_TIME (tmr, "explicit/gc_major_slice");
return Val_long (0);
CAMLprim value caml_gc_compaction(value v)
{
CAML_INSTR_SETUP (tmr, "");
- Assert (v == Val_unit);
- caml_gc_message (0x10, "Heap compaction requested\n", 0);
+ CAMLassert (v == Val_unit);
+ caml_gc_message (0x10, "Heap compaction requested\n");
caml_empty_minor_heap ();
caml_finish_major_cycle ();
caml_final_do_calls ();
caml_percent_max = norm_pmax (percent_m);
caml_init_major_heap (major_heap_size);
caml_major_window = norm_window (window);
- caml_gc_message (0x20, "Initial minor heap size: %luk words\n",
+ caml_gc_message (0x20, "Initial minor heap size: %"
+ ARCH_SIZET_PRINTF_FORMAT "uk words\n",
caml_minor_heap_wsz / 1024);
- caml_gc_message (0x20, "Initial major heap size: %luk bytes\n",
+ caml_gc_message (0x20, "Initial major heap size: %"
+ ARCH_INTNAT_PRINTF_FORMAT "uk bytes\n",
major_heap_size / 1024);
- caml_gc_message (0x20, "Initial space overhead: %lu%%\n", caml_percent_free);
- caml_gc_message (0x20, "Initial max overhead: %lu%%\n", caml_percent_max);
+ caml_gc_message (0x20, "Initial space overhead: %"
+ ARCH_INTNAT_PRINTF_FORMAT "u%%\n", caml_percent_free);
+ caml_gc_message (0x20, "Initial max overhead: %"
+ ARCH_INTNAT_PRINTF_FORMAT "u%%\n", caml_percent_max);
if (caml_major_heap_increment > 1000){
- caml_gc_message (0x20, "Initial heap increment: %luk words\n",
+ caml_gc_message (0x20, "Initial heap increment: %"
+ ARCH_INTNAT_PRINTF_FORMAT "uk words\n",
caml_major_heap_increment / 1024);
}else{
- caml_gc_message (0x20, "Initial heap increment: %lu%%\n",
+ caml_gc_message (0x20, "Initial heap increment: %"
+ ARCH_INTNAT_PRINTF_FORMAT "u%%\n",
caml_major_heap_increment);
}
- caml_gc_message (0x20, "Initial allocation policy: %d\n",
- caml_allocation_policy);
+ caml_gc_message (0x20, "Initial allocation policy: %"
+ ARCH_INTNAT_PRINTF_FORMAT "u\n", caml_allocation_policy);
caml_gc_message (0x20, "Initial smoothing window: %d\n",
caml_major_window);
}
CAMLprim value caml_runtime_parameters (value unit)
{
+#define F_Z ARCH_INTNAT_PRINTF_FORMAT
+#define F_S ARCH_SIZET_PRINTF_FORMAT
+
CAMLassert (unit == Val_unit);
return caml_alloc_sprintf
- ("a=%d,b=%d,H=%lu,i=%lu,l=%lu,o=%lu,O=%lu,p=%d,s=%lu,t=%lu,v=%lu,w=%d,W=%lu",
+ ("a=%d,b=%d,H=%"F_Z"u,i=%"F_Z"u,l=%"F_Z"u,o=%"F_Z"u,O=%"F_Z"u,p=%d,s=%"F_S"u,t=%"F_Z"u,v=%"F_Z"u,w=%d,W=%"F_Z"u",
/* a */ (int) caml_allocation_policy,
/* b */ caml_backtrace_active,
/* h */ /* missing */ /* FIXME add when changed to min_heap_size */
/* H */ caml_use_huge_pages,
/* i */ caml_major_heap_increment,
#ifdef NATIVE_CODE
- /* l */ 0UL,
+ /* l */ (uintnat) 0,
#else
/* l */ caml_max_stack_size,
#endif
/* w */ caml_major_window,
/* W */ caml_runtime_warnings
);
+#undef F_Z
+#undef F_S
}
/* Control runtime warnings */
"less random" than the most significant bits with a modulus of 2^m,
so consume most significant bits first */
while ((r & 0xC0000000U) == 0xC0000000U) { level++; r = r << 2; }
- Assert(level < NUM_LEVELS);
+ CAMLassert(level < NUM_LEVELS);
return level;
}
struct global_root * e, * f;
int i, new_level;
- Assert(0 <= rootlist->level && rootlist->level < NUM_LEVELS);
+ CAMLassert(0 <= rootlist->level && rootlist->level < NUM_LEVELS);
/* Init "cursor" to list head */
e = (struct global_root *) rootlist;
struct global_root * e, * f;
int i;
- Assert(0 <= rootlist->level && rootlist->level < NUM_LEVELS);
+ CAMLassert(0 <= rootlist->level && rootlist->level < NUM_LEVELS);
/* Init "cursor" to list head */
e = (struct global_root *) rootlist;
struct global_root * gr, * next;
int i;
- Assert(0 <= rootlist->level && rootlist->level < NUM_LEVELS);
+ CAMLassert(0 <= rootlist->level && rootlist->level < NUM_LEVELS);
for (gr = rootlist->forward[0]; gr != NULL; /**/) {
next = gr->forward[0];
CAMLexport void caml_register_global_root(value *r)
{
- Assert (((intnat) r & 3) == 0); /* compact.c demands this (for now) */
+ CAMLassert (((intnat) r & 3) == 0); /* compact.c demands this (for now) */
caml_insert_global_root(&caml_global_roots, r);
}
CAMLexport void caml_register_generational_global_root(value *r)
{
value v = *r;
- Assert (((intnat) r & 3) == 0); /* compact.c demands this (for now) */
+ CAMLassert (((intnat) r & 3) == 0); /* compact.c demands this (for now) */
if (Is_block(v)) {
if (Is_young(v))
caml_insert_global_root(&caml_global_roots_young, r);
break;
case Double_array_tag:
for (i = 0, len = Wosize_val(v) / Double_wosize; i < len; i++) {
- h = caml_hash_mix_double(h, Double_field(v, i));
+ h = caml_hash_mix_double(h, Double_flat_field(v, i));
num--;
if (num <= 0) break;
}
/* The old implementation */
-static uintnat hash_accu;
-static intnat hash_univ_limit, hash_univ_count;
+struct hash_state {
+ uintnat accu;
+ intnat univ_limit, univ_count;
+};
-static void hash_aux(value obj);
+static void hash_aux(struct hash_state*, value obj);
CAMLprim value caml_hash_univ_param(value count, value limit, value obj)
{
- hash_univ_limit = Long_val(limit);
- hash_univ_count = Long_val(count);
- hash_accu = 0;
- hash_aux(obj);
- return Val_long(hash_accu & 0x3FFFFFFF);
+ struct hash_state h;
+ h.univ_limit = Long_val(limit);
+ h.univ_count = Long_val(count);
+ h.accu = 0;
+ hash_aux(&h, obj);
+ return Val_long(h.accu & 0x3FFFFFFF);
/* The & has two purposes: ensure that the return value is positive
and give the same result on 32 bit and 64 bit architectures. */
}
#define Alpha 65599
#define Beta 19
-#define Combine(new) (hash_accu = hash_accu * Alpha + (new))
-#define Combine_small(new) (hash_accu = hash_accu * Beta + (new))
+#define Combine(new) (h->accu = h->accu * Alpha + (new))
+#define Combine_small(new) (h->accu = h->accu * Beta + (new))
-static void hash_aux(value obj)
+static void hash_aux(struct hash_state* h, value obj)
{
unsigned char * p;
mlsize_t i, j;
tag_t tag;
- hash_univ_limit--;
- if (hash_univ_count < 0 || hash_univ_limit < 0) return;
+ h->univ_limit--;
+ if (h->univ_count < 0 || h->univ_limit < 0) return;
again:
if (Is_long(obj)) {
- hash_univ_count--;
+ h->univ_count--;
Combine(Long_val(obj));
return;
}
/* Pointers into the heap are well-structured blocks. So are atoms.
We can inspect the block contents. */
- Assert (Is_block (obj));
+ CAMLassert (Is_block (obj));
if (Is_in_value_area(obj)) {
tag = Tag_val(obj);
switch (tag) {
case String_tag:
- hash_univ_count--;
+ h->univ_count--;
i = caml_string_length(obj);
for (p = &Byte_u(obj, 0); i > 0; i--, p++)
Combine_small(*p);
case Double_tag:
/* For doubles, we inspect their binary representation, LSB first.
The results are consistent among all platforms with IEEE floats. */
- hash_univ_count--;
+ h->univ_count--;
#ifdef ARCH_BIG_ENDIAN
for (p = &Byte_u(obj, sizeof(double) - 1), i = sizeof(double);
i > 0;
Combine_small(*p);
break;
case Double_array_tag:
- hash_univ_count--;
+ h->univ_count--;
for (j = 0; j < Bosize_val(obj); j += sizeof(double)) {
#ifdef ARCH_BIG_ENDIAN
for (p = &Byte_u(obj, j + sizeof(double) - 1), i = sizeof(double);
Better do nothing. */
break;
case Infix_tag:
- hash_aux(obj - Infix_offset_val(obj));
+ hash_aux(h, obj - Infix_offset_val(obj));
break;
case Forward_tag:
obj = Forward_val (obj);
goto again;
case Object_tag:
- hash_univ_count--;
+ h->univ_count--;
Combine(Oid_val(obj));
break;
case Custom_tag:
/* If no hashing function provided, do nothing */
if (Custom_ops_val(obj)->hash != NULL) {
- hash_univ_count--;
+ h->univ_count--;
Combine(Custom_ops_val(obj)->hash(obj));
}
break;
default:
- hash_univ_count--;
+ h->univ_count--;
Combine_small(tag);
i = Wosize_val(obj);
while (i != 0) {
i--;
- hash_aux(Field(obj, i));
+ hash_aux(h, Field(obj, i));
}
break;
}
caml_trace_value_file (value v, code_t prog, int proglen, FILE * f)
{
int i;
- fprintf (f, "%#lx", v);
+ fprintf (f, "%#" ARCH_INTNAT_PRINTF_FORMAT "x", v);
if (!v)
return;
if (prog && v % sizeof (int) == 0
case Double_array_tag:
fprintf (f, "=floatarray[s%d]", s);
for (i = 0; i < ((s>0xf)?0xf:s); i++)
- fprintf (f, " %g", Double_field (v, i));
+ fprintf (f, " %g", Double_flat_field (v, i));
goto displayfields;
case Abstract_tag:
fprintf (f, "=abstract[s%d]", s);
};
if (i > 0)
putc (' ', f);
- fprintf (f, "%#lx", Field (v, i));
+ fprintf (f, "%#" ARCH_INTNAT_PRINTF_FORMAT "x", Field (v, i));
};
if (s > 0)
putc (')', f);
/* This is asserted at the beginning of demarshaling primitives.
If it fails, it probably means that an exception was raised
without calling intern_cleanup() during the previous demarshaling. */
- Assert (intern_input == NULL && intern_obj_table == NULL \
+ CAMLassert (intern_input == NULL && intern_obj_table == NULL \
&& intern_extra_block == NULL && intern_block == 0);
intern_src = src;
intern_input = input;
static void intern_free_stack(void)
{
if (intern_stack != intern_stack_init) {
- free(intern_stack);
+ caml_stat_free(intern_stack);
/* Reinitialize the globals for next time around */
intern_stack = intern_stack_init;
intern_stack_limit = intern_stack + INTERN_STACK_INIT_SIZE;
/* Same, then raise Out_of_memory */
static void intern_stack_overflow(void)
{
- caml_gc_message (0x04, "Stack overflow in un-marshaling value\n", 0);
+ caml_gc_message (0x04, "Stack overflow in un-marshaling value\n");
intern_free_stack();
caml_raise_out_of_memory();
}
if (newsize >= INTERN_STACK_MAX_SIZE) intern_stack_overflow();
if (intern_stack == intern_stack_init) {
- newstack = malloc(sizeof(struct intern_item) * newsize);
+ newstack = caml_stat_alloc_noexc(sizeof(struct intern_item) * newsize);
if (newstack == NULL) intern_stack_overflow();
memcpy(newstack, intern_stack_init,
sizeof(struct intern_item) * INTERN_STACK_INIT_SIZE);
} else {
- newstack =
- realloc(intern_stack, sizeof(struct intern_item) * newsize);
+ newstack = caml_stat_resize_noexc(intern_stack,
+ sizeof(struct intern_item) * newsize);
if (newstack == NULL) intern_stack_overflow();
}
intern_stack = newstack;
intern_dest += 1 + size;
/* For objects, we need to freshen the oid */
if (tag == Object_tag) {
- Assert(size >= 2);
+ CAMLassert(size >= 2);
/* Request to read rest of the elements of the block */
ReadItems(&Field(v, 2), size - 2);
/* Request freshing OID */
Field(v, size - 1) = 0;
ofs_ind = Bsize_wsize(size) - 1;
Byte(v, ofs_ind) = ofs_ind - len;
- readblock(String_val(v), len);
+ readblock((char *)String_val(v), len);
} else {
switch(code) {
case CODE_INT8:
case CODE_SHARED8:
ofs = read8u();
read_shared:
- Assert (ofs > 0);
- Assert (ofs <= obj_counter);
- Assert (intern_obj_table != NULL);
+ CAMLassert (ofs > 0);
+ CAMLassert (ofs <= obj_counter);
+ CAMLassert (intern_obj_table != NULL);
v = intern_obj_table[obj_counter - ofs];
break;
case CODE_SHARED16:
*dest = v;
break;
default:
- Assert(0);
+ CAMLassert(0);
}
}
/* We are done. Cleanup the stack and leave the function */
mlsize_t wosize;
if (whsize == 0) {
- Assert (intern_extra_block == NULL && intern_block == 0
+ CAMLassert (intern_extra_block == NULL && intern_block == 0
&& intern_obj_table == NULL);
return;
}
wosize = Wosize_whsize(whsize);
- if (wosize > Max_wosize || outside_heap) {
+ if (outside_heap || wosize > Max_wosize) {
/* Round desired size up to next page */
asize_t request =
((Bsize_wsize(whsize) + Page_size - 1) >> Page_log) << Page_log;
intern_color =
outside_heap ? Caml_black : caml_allocation_color(intern_extra_block);
intern_dest = (header_t *) intern_extra_block;
- Assert (intern_block == 0);
+ CAMLassert (intern_block == 0);
} else {
/* this is a specialised version of caml_alloc from alloc.c */
- if (wosize == 0){
- intern_block = Atom (String_tag);
- }else if (wosize <= Max_young_wosize){
- intern_block = caml_alloc_small (wosize, String_tag);
+ if (wosize <= Max_young_wosize){
+ if (wosize == 0){
+ intern_block = Atom (String_tag);
+ } else {
+ intern_block = caml_alloc_small (wosize, String_tag);
+ }
}else{
intern_block = caml_alloc_shr_no_raise (wosize, String_tag);
/* do not do the urgent_gc check here because it might darken
- intern_block into gray and break the Assert 3 lines down */
+ intern_block into gray and break the intern_color assertion below */
if (intern_block == 0) {
intern_cleanup();
caml_raise_out_of_memory();
}
intern_header = Hd_val(intern_block);
intern_color = Color_hd(intern_header);
- Assert (intern_color == Caml_white || intern_color == Caml_black);
+ CAMLassert (intern_color == Caml_white || intern_color == Caml_black);
intern_dest = (header_t *) Hp_val(intern_block);
- Assert (intern_extra_block == NULL);
+ CAMLassert (intern_extra_block == NULL);
}
obj_counter = 0;
if (num_objects > 0) {
- intern_obj_table = (value *) malloc(num_objects * sizeof(value));
+ intern_obj_table = (value *) caml_stat_alloc_noexc(num_objects * sizeof(value));
if (intern_obj_table == NULL) {
intern_cleanup();
caml_raise_out_of_memory();
}
} else
- Assert(intern_obj_table == NULL);
+ CAMLassert(intern_obj_table == NULL);
}
static void intern_add_to_heap(mlsize_t whsize)
asize_t request = Chunk_size (intern_extra_block);
header_t * end_extra_block =
(header_t *) intern_extra_block + Wsize_bsize(request);
- Assert(intern_block == 0);
- Assert(intern_dest <= end_extra_block);
+ CAMLassert(intern_block == 0);
+ CAMLassert(intern_dest <= end_extra_block);
if (intern_dest < end_extra_block){
caml_make_free_blocks ((value *) intern_dest,
end_extra_block - intern_dest, 0, Caml_white);
#ifdef DEBUG
next_instr:
if (caml_icount-- == 0) caml_stop_here ();
- Assert(sp >= caml_stack_low);
- Assert(sp <= caml_stack_high);
+ CAMLassert(sp >= caml_stack_low);
+ CAMLassert(sp <= caml_stack_high);
#endif
goto *(void *)(jumptbl_base + *pc++); /* Jump to the first instruction */
#else
#ifdef DEBUG
caml_bcodcount++;
if (caml_icount-- == 0) caml_stop_here ();
- if (caml_trace_level>1) printf("\n##%ld\n", caml_bcodcount);
+ if (caml_trace_level>1) printf("\n##%" ARCH_INTNAT_PRINTF_FORMAT "d\n",
+ caml_bcodcount);
if (caml_trace_level>0) caml_disasm_instr(pc);
if (caml_trace_level>1) {
printf("env=");
caml_trace_accu_sp_file(accu,sp,prog,prog_size,stdout);
fflush(stdout);
};
- Assert(sp >= caml_stack_low);
- Assert(sp <= caml_stack_high);
+ CAMLassert(sp >= caml_stack_low);
+ CAMLassert(sp <= caml_stack_high);
#endif
curr_instr = *pc++;
} else {
block = caml_alloc_shr(size * Double_wosize, Double_array_tag);
}
- Store_double_field(block, 0, Double_val(accu));
+ Store_double_flat_field(block, 0, Double_val(accu));
for (i = 1; i < size; i++){
- Store_double_field(block, i, Double_val(*sp));
+ Store_double_flat_field(block, i, Double_val(*sp));
++ sp;
}
accu = block;
Instruct(GETFIELD):
accu = Field(accu, *pc); pc++; Next;
Instruct(GETFLOATFIELD): {
- double d = Double_field(accu, *pc);
+ double d = Double_flat_field(accu, *pc);
Alloc_small(accu, Double_wosize, Double_tag);
Store_double_val(accu, d);
pc++;
pc++;
Next;
Instruct(SETFLOATFIELD):
- Store_double_field(accu, *pc, Double_val(*sp));
+ Store_double_flat_field(accu, *pc, Double_val(*sp));
accu = Val_unit;
sp++;
pc++;
/* Array operations */
Instruct(VECTLENGTH): {
+ /* Todo: when FLAT_FLOAT_ARRAY is false, this instruction should
+ be split into VECTLENGTH and FLOATVECTLENGTH because we know
+ statically which one it is. */
mlsize_t size = Wosize_val(accu);
if (Tag_val(accu) == Double_array_tag) size = size / Double_wosize;
accu = Val_long(size);
uint32_t sizes = *pc++;
if (Is_block(accu)) {
intnat index = Tag_val(accu);
- Assert ((uintnat) index < (sizes >> 16));
+ CAMLassert ((uintnat) index < (sizes >> 16));
pc += pc[(sizes & 0xFFFF) + index];
} else {
intnat index = Long_val(accu);
- Assert ((uintnat) index < (sizes & 0xFFFF)) ;
+ CAMLassert ((uintnat) index < (sizes & 0xFFFF)) ;
pc += pc[index];
}
Next;
/* other implementations of the interpreter (such as an hypothetical
JIT translator) might want to do something with a bytecode before
running it */
- Assert(prog);
- Assert(prog_size>0);
+ CAMLassert(prog);
+ CAMLassert(prog_size>0);
/* actually, the threading of the bytecode might be done here */
}
/* other implementations of the interpreter (such as an hypothetical
JIT translator) might want to know when a bytecode is removed */
/* check that we have a program */
- Assert(prog);
- Assert(prog_size>0);
+ CAMLassert(prog);
+ CAMLassert(prog_size>0);
}
#include "caml/misc.h"
#include "caml/mlvalues.h"
-static char * parse_sign_and_base(char * p,
- /*out*/ int * base,
- /*out*/ int * signedness,
- /*out*/ int * sign)
+static const char * parse_sign_and_base(const char * p,
+ /*out*/ int * base,
+ /*out*/ int * signedness,
+ /*out*/ int * sign)
{
*sign = 1;
if (*p == '-') {
static intnat parse_intnat(value s, int nbits, const char *errmsg)
{
- char * p;
+ const char * p;
uintnat res, threshold;
int sign, base, signedness, d;
CAMLprim value caml_int64_of_string(value s)
{
- char * p;
+ const char * p;
uint64_t res, threshold;
int sign, base, signedness, d;
static void unlink_channel(struct channel *channel)
{
if (channel->prev == NULL) {
- Assert (channel == caml_all_opened_channels);
+ CAMLassert (channel == caml_all_opened_channels);
caml_all_opened_channels = caml_all_opened_channels->next;
if (caml_all_opened_channels != NULL)
caml_all_opened_channels->prev = NULL;
CAMLexport void caml_finalize_channel(value vchan)
{
struct channel * chan = Channel(vchan);
+ if ((chan->flags & CHANNEL_FLAG_MANAGED_BY_GC) == 0) return;
if (--chan->refcount > 0) return;
if (caml_channel_mutex_free != NULL) (*caml_channel_mutex_free)(chan);
CAMLprim value caml_ml_open_descriptor_in(value fd)
{
- return caml_alloc_channel(caml_open_descriptor_in(Int_val(fd)));
+ struct channel * chan = caml_open_descriptor_in(Int_val(fd));
+ chan->flags |= CHANNEL_FLAG_MANAGED_BY_GC;
+ return caml_alloc_channel(chan);
}
CAMLprim value caml_ml_open_descriptor_out(value fd)
{
- return caml_alloc_channel(caml_open_descriptor_out(Int_val(fd)));
+ struct channel * chan = caml_open_descriptor_out(Int_val(fd));
+ chan->flags |= CHANNEL_FLAG_MANAGED_BY_GC;
+ return caml_alloc_channel(chan);
}
CAMLprim value caml_ml_set_channel_name(value vchannel, value vname)
struct channel * channel = Channel(vchannel);
caml_stat_free(channel->name);
if (caml_string_length(vname) > 0)
- channel->name = caml_strdup(String_val(vname));
+ channel->name = caml_stat_strdup(String_val(vname));
else
channel->name = NULL;
return Val_unit;
#include "caml/misc.h"
#include "caml/mlvalues.h"
#include "caml/sys.h"
+#include "caml/osdeps.h"
+#ifdef _WIN32
+#include <windows.h>
+#endif
-CAMLextern void caml_main (char **);
+CAMLextern void caml_main (char_os **);
#ifdef _WIN32
-CAMLextern void caml_expand_command_line (int *, char ***);
-#endif
+CAMLextern void caml_expand_command_line (int *, wchar_t ***);
+int wmain(int argc, wchar_t **argv)
+#else
int main(int argc, char **argv)
+#endif
{
#ifdef _WIN32
/* Expand wildcards and diversions in command line */
caml_expand_command_line(&argc, &argv);
#endif
+
caml_main(argv);
caml_sys_exit(Val_int(0));
return 0; /* not reached */
{
value *new;
- Assert (gray_vals_cur == gray_vals_end);
+ CAMLassert (gray_vals_cur == gray_vals_end);
if (gray_vals_size < caml_stat_heap_wsz / 32){
caml_gc_message (0x08, "Growing gray_vals to %"
ARCH_INTNAT_PRINTF_FORMAT "uk bytes\n",
(intnat) gray_vals_size * sizeof (value) / 512);
- new = (value *) realloc ((char *) gray_vals,
- 2 * gray_vals_size * sizeof (value));
+ new = (value *) caml_stat_resize_noexc ((char *) gray_vals,
+ 2 * gray_vals_size *
+ sizeof (value));
if (new == NULL){
- caml_gc_message (0x08, "No room for growing gray_vals\n", 0);
+ caml_gc_message (0x08, "No room for growing gray_vals\n");
gray_vals_cur = gray_vals;
heap_is_pure = 0;
}else{
static void start_cycle (void)
{
- Assert (caml_gc_phase == Phase_idle);
- Assert (gray_vals_cur == gray_vals);
- caml_gc_message (0x01, "Starting new major GC cycle\n", 0);
+ CAMLassert (caml_gc_phase == Phase_idle);
+ CAMLassert (gray_vals_cur == gray_vals);
+ caml_gc_message (0x01, "Starting new major GC cycle\n");
caml_darken_all_roots_start ();
caml_gc_phase = Phase_mark;
caml_gc_subphase = Subphase_mark_roots;
if ((in_ephemeron && Is_long(f)) ||
(Is_block (f)
&& (!Is_in_value_area(f) || Tag_val (f) == Forward_tag
- || Tag_val (f) == Lazy_tag || Tag_val (f) == Double_tag))){
+ || Tag_val (f) == Lazy_tag
+#ifdef FLAT_FLOAT_ARRAY
+ || Tag_val (f) == Double_tag
+#endif
+ ))){
/* Do not short-circuit the pointer. */
}else{
/* The variable child is not changed because it must be mark alive */
v = *ephes_to_check;
hd = Hd_val(v);
- Assert(Tag_val (v) == Abstract_tag);
+ CAMLassert(Tag_val (v) == Abstract_tag);
data = Field(v,CAML_EPHE_DATA_OFFSET);
if ( data != caml_ephe_none &&
Is_block (data) && Is_in_heap (data) && Is_white_val (data)){
if (Is_long (f) ||
(Is_block (f) &&
(!Is_in_value_area(f) || Tag_val (f) == Forward_tag
- || Tag_val (f) == Lazy_tag || Tag_val (f) == Double_tag))){
+ || Tag_val (f) == Lazy_tag
+#ifdef FLAT_FLOAT_ARRAY
+ || Tag_val (f) == Double_tag
+#endif
+ ))){
/* Do not short-circuit the pointer. */
}else{
Field (v, i) = key = f;
#endif
int slice_pointers = 0; /** gcc removes it when not in CAML_INSTR */
- caml_gc_message (0x40, "Marking %ld words\n", work);
- caml_gc_message (0x40, "Subphase = %ld\n", caml_gc_subphase);
+ caml_gc_message (0x40, "Marking %"ARCH_INTNAT_PRINTF_FORMAT"d words\n", work);
+ caml_gc_message (0x40, "Subphase = %d\n", caml_gc_subphase);
gray_vals_ptr = gray_vals_cur;
v = current_value;
start = current_index;
}
if (v != 0){
hd = Hd_val(v);
- Assert (Is_gray_hd (hd));
+ CAMLassert (Is_gray_hd (hd));
size = Wosize_hd (hd);
end = start + work;
if (Tag_hd (hd) < No_scan_tag){
}
}else{
if (Is_gray_val (Val_hp (markhp))){
- Assert (gray_vals_ptr == gray_vals);
+ CAMLassert (gray_vals_ptr == gray_vals);
CAMLassert (v == 0 && start == 0);
v = Val_hp (markhp);
}
work = 0;
}
break;
- default: Assert (0);
+ default: CAMLassert (0);
}
}
}
{
value v;
- caml_gc_message (0x40, "Cleaning %ld words\n", work);
+ caml_gc_message (0x40, "Cleaning %"
+ ARCH_INTNAT_PRINTF_FORMAT "d words\n", work);
while (work > 0){
v = *ephes_to_check;
if (v != (value) NULL){
char *hp;
header_t hd;
- caml_gc_message (0x40, "Sweeping %ld words\n", work);
+ caml_gc_message (0x40, "Sweeping %"
+ ARCH_INTNAT_PRINTF_FORMAT "d words\n", work);
while (work > 0){
if (caml_gc_sweep_hp < limit){
hp = caml_gc_sweep_hp;
caml_fl_merge = Bp_hp (hp);
break;
default: /* gray or black */
- Assert (Color_hd (hd) == Caml_black);
+ CAMLassert (Color_hd (hd) == Caml_black);
Hd_hp (hp) = Whitehd_hd (hd);
break;
}
- Assert (caml_gc_sweep_hp <= limit);
+ CAMLassert (caml_gc_sweep_hp <= limit);
}else{
chunk = Chunk_next (chunk);
if (chunk == NULL){
CAML_INSTR_INT ("major/work/extra#",
(uintnat) (caml_extra_heap_resources * 1000000));
- caml_gc_message (0x40, "ordered work = %ld words\n", howmuch);
+ caml_gc_message (0x40, "ordered work = %"
+ ARCH_INTNAT_PRINTF_FORMAT "d words\n", howmuch);
caml_gc_message (0x40, "allocated_words = %"
ARCH_INTNAT_PRINTF_FORMAT "u\n",
caml_allocated_words);
}else{
computed_work = (intnat) (p * caml_stat_heap_wsz * 5 / 3);
}
- caml_gc_message (0x40, "computed work = %ld words\n", computed_work);
+ caml_gc_message (0x40, "computed work = %"
+ ARCH_INTNAT_PRINTF_FORMAT "d words\n", computed_work);
if (caml_gc_phase == Phase_mark){
CAML_INSTR_INT ("major/work/mark#", computed_work);
mark_slice (computed_work);
CAML_INSTR_TIME (tmr, mark_slice_name[caml_gc_subphase]);
- caml_gc_message (0x02, "!", 0);
+ caml_gc_message (0x02, "!");
}else if (caml_gc_phase == Phase_clean){
clean_slice (computed_work);
- caml_gc_message (0x02, "%%", 0);
+ caml_gc_message (0x02, "%%");
}else{
- Assert (caml_gc_phase == Phase_sweep);
+ CAMLassert (caml_gc_phase == Phase_sweep);
CAML_INSTR_INT ("major/work/sweep#", computed_work);
sweep_slice (computed_work);
CAML_INSTR_TIME (tmr, "major/sweep");
- caml_gc_message (0x02, "$", 0);
+ caml_gc_message (0x02, "$");
}
if (caml_gc_phase == Phase_idle){
if (caml_gc_phase == Phase_idle) start_cycle ();
while (caml_gc_phase == Phase_mark) mark_slice (LONG_MAX);
while (caml_gc_phase == Phase_clean) clean_slice (LONG_MAX);
- Assert (caml_gc_phase == Phase_sweep);
+ CAMLassert (caml_gc_phase == Phase_sweep);
while (caml_gc_phase == Phase_sweep) sweep_slice (LONG_MAX);
- Assert (caml_gc_phase == Phase_idle);
+ CAMLassert (caml_gc_phase == Phase_idle);
caml_stat_major_words += caml_allocated_words;
caml_allocated_words = 0;
}
caml_stat_heap_wsz = caml_clip_heap_chunk_wsz (Wsize_bsize (heap_size));
caml_stat_top_heap_wsz = caml_stat_heap_wsz;
- Assert (Bsize_wsize (caml_stat_heap_wsz) % Page_size == 0);
+ CAMLassert (Bsize_wsize (caml_stat_heap_wsz) % Page_size == 0);
caml_heap_start =
(char *) caml_alloc_for_heap (Bsize_wsize (caml_stat_heap_wsz));
if (caml_heap_start == NULL)
caml_stat_heap_wsz, 1, Caml_white);
caml_gc_phase = Phase_idle;
gray_vals_size = 2048;
- gray_vals = (value *) malloc (gray_vals_size * sizeof (value));
+ gray_vals = (value *) caml_stat_alloc_noexc (gray_vals_size * sizeof (value));
if (gray_vals == NULL)
caml_fatal_error ("Fatal error: not enough memory for the gray cache.\n");
gray_vals_cur = gray_vals;
}
caml_major_window = w;
}
+
+void caml_finalise_heap (void)
+{
+ /* Finishing major cycle (all values become white) */
+ caml_empty_minor_heap ();
+ caml_finish_major_cycle ();
+ CAMLassert (caml_gc_phase == Phase_idle);
+
+ /* Finalising all values (by means of forced sweeping) */
+ caml_fl_init_merge ();
+ caml_gc_phase = Phase_sweep;
+ chunk = caml_heap_start;
+ caml_gc_sweep_hp = chunk;
+ limit = chunk + Chunk_size (chunk);
+ while (caml_gc_phase == Phase_sweep)
+ sweep_slice (LONG_MAX);
+}
#include <stdlib.h>
#include <string.h>
+#include <stdarg.h>
+#include <stddef.h>
#include "caml/address_class.h"
#include "caml/config.h"
#include "caml/fail.h"
}
caml_page_table.mask = caml_page_table.size - 1;
caml_page_table.occupancy = 0;
- caml_page_table.entries = calloc(caml_page_table.size, sizeof(uintnat));
+ caml_page_table.entries =
+ caml_stat_calloc_noexc(caml_page_table.size, sizeof(uintnat));
if (caml_page_table.entries == NULL)
return -1;
else
uintnat * new_entries;
uintnat i, h;
- caml_gc_message (0x08, "Growing page table to %lu entries\n",
+ caml_gc_message (0x08, "Growing page table to %"
+ ARCH_INTNAT_PRINTF_FORMAT "u entries\n",
caml_page_table.size);
- new_entries = calloc(2 * old.size, sizeof(uintnat));
+ new_entries = caml_stat_calloc_noexc(2 * old.size, sizeof(uintnat));
if (new_entries == NULL) {
- caml_gc_message (0x08, "No room for growing page table\n", 0);
+ caml_gc_message (0x08, "No room for growing page table\n");
return -1;
}
caml_page_table.entries[h] = e;
}
- free(old.entries);
+ caml_stat_free(old.entries);
return 0;
}
{
uintnat h;
- Assert ((page & ~Page_mask) == 0);
+ CAMLassert ((page & ~Page_mask) == 0);
/* Resize to keep load factor below 1/2 */
if (caml_page_table.occupancy * 2 >= caml_page_table.size) {
uintnat j = Pagetable_index2(page);
if (caml_page_table[i] == caml_page_table_empty) {
- unsigned char * new_tbl = calloc(Pagetable2_size, 1);
+ unsigned char * new_tbl = caml_stat_calloc_noexc(Pagetable2_size, 1);
if (new_tbl == 0) return -1;
caml_page_table[i] = new_tbl;
}
void *block;
request = ((request + Page_size - 1) >> Page_log) << Page_log;
- mem = caml_aligned_malloc (request + sizeof (heap_chunk_head),
- sizeof (heap_chunk_head), &block);
+ mem = caml_stat_alloc_aligned_noexc (request + sizeof (heap_chunk_head),
+ sizeof (heap_chunk_head), &block);
if (mem == NULL) return NULL;
mem += sizeof (heap_chunk_head);
Chunk_size (mem) = request;
CAMLassert (0);
#endif
}else{
- free (Chunk_block (mem));
+ caml_stat_free (Chunk_block (mem));
}
}
/* Should check the contents of the block. */
#endif /* DEBUG */
- caml_gc_message (0x04, "Growing heap to %luk bytes\n",
+ caml_gc_message (0x04, "Growing heap to %"
+ ARCH_INTNAT_PRINTF_FORMAT "uk bytes\n",
(Bsize_wsize (caml_stat_heap_wsz) + Chunk_size (m)) / 1024);
/* Register block in page table */
value *mem, *hp, *prev;
asize_t over_request, malloc_request, remain;
- Assert (request <= Max_wosize);
+ CAMLassert (request <= Max_wosize);
over_request = request + request / 100 * caml_percent_free;
malloc_request = caml_clip_heap_chunk_wsz (over_request);
mem = (value *) caml_alloc_for_heap (Bsize_wsize (malloc_request));
if (mem == NULL){
- caml_gc_message (0x04, "No room for growing heap\n", 0);
+ caml_gc_message (0x04, "No room for growing heap\n");
return NULL;
}
remain = Wsize_bsize (Chunk_size (mem));
Hd_hp (hp) = Make_header_allocated_here (0, 0, Caml_white);
}
}
- Assert (Wosize_hp (mem) >= request);
+ CAMLassert (Wosize_hp (mem) >= request);
if (caml_add_to_heap ((char *) mem) != 0){
caml_free_for_heap ((char *) mem);
return NULL;
if (chunk == caml_heap_start) return;
caml_stat_heap_wsz -= Wsize_bsize (Chunk_size (chunk));
- caml_gc_message (0x04, "Shrinking heap to %luk words\n",
- (unsigned long) caml_stat_heap_wsz / 1024);
+ caml_gc_message (0x04, "Shrinking heap to %"
+ ARCH_INTNAT_PRINTF_FORMAT "uk words\n",
+ caml_stat_heap_wsz / 1024);
#ifdef DEBUG
{
|| (caml_gc_phase == Phase_sweep && (addr)hp >= (addr)caml_gc_sweep_hp)){
return Caml_black;
}else{
- Assert (caml_gc_phase == Phase_idle
+ CAMLassert (caml_gc_phase == Phase_idle
|| (caml_gc_phase == Phase_sweep
&& (addr)hp < (addr)caml_gc_sweep_hp));
return Caml_white;
hp = caml_fl_allocate (wosize);
}
- Assert (Is_in_heap (Val_hp (hp)));
+ CAMLassert (Is_in_heap (Val_hp (hp)));
/* Inline expansion of caml_allocation_color. */
if (caml_gc_phase == Phase_mark || caml_gc_phase == Phase_clean
|| (caml_gc_phase == Phase_sweep && (addr)hp >= (addr)caml_gc_sweep_hp)){
Hd_hp (hp) = Make_header_with_profinfo (wosize, tag, Caml_black, profinfo);
}else{
- Assert (caml_gc_phase == Phase_idle
+ CAMLassert (caml_gc_phase == Phase_idle
|| (caml_gc_phase == Phase_sweep
&& (addr)hp < (addr)caml_gc_sweep_hp));
Hd_hp (hp) = Make_header_with_profinfo (wosize, tag, Caml_white, profinfo);
}
- Assert (Hd_hp (hp)
+ CAMLassert (Hd_hp (hp)
== Make_header_with_profinfo (wosize, tag, caml_allocation_color (hp),
profinfo));
caml_allocated_words += Whsize_wosize (wosize);
}
}
-/* [sz] is a number of bytes */
-CAMLexport void * caml_stat_alloc (asize_t sz)
+
+/* Global memory pool.
+
+ The pool is structured as a ring of blocks, where each block's header
+ contains two links: to the previous and to the next block. The data
+ structure allows for insertions and removals of blocks in constant time,
+ given that a pointer to the operated block is provided.
+
+ Initially, the pool contains a single block -- a pivot with no data, the
+ guaranteed existence of which makes for a more concise implementation.
+
+ The API functions that operate on the pool receive not pointers to the
+ block's header, but rather pointers to the block's "data" field. This
+ behaviour is required to maintain compatibility with the interfaces of
+ [malloc], [realloc], and [free] family of functions, as well as to hide
+ the implementation from the user.
+*/
+
+/* A type with the most strict alignment requirements */
+union max_align {
+ char c;
+ short s;
+ long l;
+ int i;
+ float f;
+ double d;
+ void *v;
+ void (*q)(void);
+};
+
+struct pool_block {
+#ifdef DEBUG
+ long magic;
+#endif
+ struct pool_block *next;
+ struct pool_block *prev;
+ union max_align data[1]; /* not allocated, used for alignment purposes */
+};
+
+#define SIZEOF_POOL_BLOCK offsetof(struct pool_block, data)
+
+static struct pool_block *pool = NULL;
+
+
+/* Returns a pointer to the block header, given a pointer to "data" */
+static struct pool_block* get_pool_block(caml_stat_block b)
+{
+ if (b == NULL)
+ return NULL;
+
+ else {
+ struct pool_block *pb =
+ (struct pool_block*)(((char*)b) - SIZEOF_POOL_BLOCK);
+#ifdef DEBUG
+ CAMLassert(pb->magic == Debug_pool_magic);
+#endif
+ return pb;
+ }
+}
+
+CAMLexport void caml_stat_create_pool(void)
+{
+ if (pool == NULL) {
+ pool = malloc(SIZEOF_POOL_BLOCK);
+ if (pool == NULL)
+ caml_fatal_error("Fatal error: out of memory.\n");
+#ifdef DEBUG
+ pool->magic = Debug_pool_magic;
+#endif
+ pool->next = pool;
+ pool->prev = pool;
+ }
+}
+
+CAMLexport void caml_stat_destroy_pool(void)
+{
+ if (pool != NULL) {
+ pool->prev->next = NULL;
+ while (pool != NULL) {
+ struct pool_block *next = pool->next;
+ free(pool);
+ pool = next;
+ }
+ pool = NULL;
+ }
+}
+
+/* [sz] and [modulo] are numbers of bytes */
+CAMLexport void* caml_stat_alloc_aligned_noexc(asize_t sz, int modulo,
+ caml_stat_block *b)
{
- void * result = malloc (sz);
+ char *raw_mem;
+ uintnat aligned_mem;
+ CAMLassert (modulo < Page_size);
+ raw_mem = (char *) caml_stat_alloc_noexc(sz + Page_size);
+ if (raw_mem == NULL) return NULL;
+ *b = raw_mem;
+ raw_mem += modulo; /* Address to be aligned */
+ aligned_mem = (((uintnat) raw_mem / Page_size + 1) * Page_size);
+#ifdef DEBUG
+ {
+ uintnat *p;
+ uintnat *p0 = (void *) *b;
+ uintnat *p1 = (void *) (aligned_mem - modulo);
+ uintnat *p2 = (void *) (aligned_mem - modulo + sz);
+ uintnat *p3 = (void *) ((char *) *b + sz + Page_size);
+ for (p = p0; p < p1; p++) *p = Debug_filler_align;
+ for (p = p1; p < p2; p++) *p = Debug_uninit_align;
+ for (p = p2; p < p3; p++) *p = Debug_filler_align;
+ }
+#endif
+ return (char *) (aligned_mem - modulo);
+}
+/* [sz] and [modulo] are numbers of bytes */
+CAMLexport void* caml_stat_alloc_aligned(asize_t sz, int modulo,
+ caml_stat_block *b)
+{
+ void *result = caml_stat_alloc_aligned_noexc(sz, modulo, b);
/* malloc() may return NULL if size is 0 */
- if (result == NULL && sz != 0) caml_raise_out_of_memory ();
+ if ((result == NULL) && (sz != 0))
+ caml_raise_out_of_memory();
+ return result;
+}
+
+/* [sz] is a number of bytes */
+CAMLexport caml_stat_block caml_stat_alloc_noexc(asize_t sz)
+{
+ /* Backward compatibility mode */
+ if (pool == NULL)
+ return malloc(sz);
+ else {
+ struct pool_block *pb = malloc(sz + SIZEOF_POOL_BLOCK);
+ if (pb == NULL) return NULL;
#ifdef DEBUG
- memset (result, Debug_uninit_stat, sz);
+ memset(&(pb->data), Debug_uninit_stat, sz);
+ pb->magic = Debug_pool_magic;
#endif
+
+ /* Linking the block into the ring */
+ pb->next = pool->next;
+ pb->prev = pool;
+ pool->next->prev = pb;
+ pool->next = pb;
+
+ return &(pb->data);
+ }
+}
+
+/* [sz] is a number of bytes */
+CAMLexport caml_stat_block caml_stat_alloc(asize_t sz)
+{
+ void *result = caml_stat_alloc_noexc(sz);
+ /* malloc() may return NULL if size is 0 */
+ if ((result == NULL) && (sz != 0))
+ caml_raise_out_of_memory();
return result;
}
-CAMLexport void caml_stat_free (void * blk)
+CAMLexport void caml_stat_free(caml_stat_block b)
{
- free (blk);
+ /* Backward compatibility mode */
+ if (pool == NULL)
+ free(b);
+ else {
+ struct pool_block *pb = get_pool_block(b);
+ if (pb == NULL) return;
+
+ /* Unlinking the block from the ring */
+ pb->prev->next = pb->next;
+ pb->next->prev = pb->prev;
+
+ free(pb);
+ }
}
/* [sz] is a number of bytes */
-CAMLexport void * caml_stat_resize (void * blk, asize_t sz)
+CAMLexport caml_stat_block caml_stat_resize_noexc(caml_stat_block b, asize_t sz)
{
- void * result = realloc (blk, sz);
+ /* Backward compatibility mode */
+ if (pool == NULL)
+ return realloc(b, sz);
+ else {
+ struct pool_block *pb = get_pool_block(b);
+ struct pool_block *pb_new = realloc(pb, sz + SIZEOF_POOL_BLOCK);
+ if (pb_new == NULL) return NULL;
+
+ /* Relinking the new block into the ring in place of the old one */
+ pb_new->prev->next = pb_new;
+ pb_new->next->prev = pb_new;
+
+ return &(pb_new->data);
+ }
+}
- if (result == NULL) caml_raise_out_of_memory ();
+/* [sz] is a number of bytes */
+CAMLexport caml_stat_block caml_stat_resize(caml_stat_block b, asize_t sz)
+{
+ void *result = caml_stat_resize_noexc(b, sz);
+ if (result == NULL)
+ caml_raise_out_of_memory();
return result;
}
+
+/* [sz] is a number of bytes */
+CAMLexport caml_stat_block caml_stat_calloc_noexc(asize_t num, asize_t sz)
+{
+ uintnat total;
+ if (caml_umul_overflow(sz, num, &total))
+ return NULL;
+ else {
+ caml_stat_block result = caml_stat_alloc_noexc(total);
+ if (result != NULL)
+ memset(result, 0, total);
+ return result;
+ }
+}
+
+CAMLexport caml_stat_string caml_stat_strdup_noexc(const char *s)
+{
+ size_t slen = strlen(s);
+ caml_stat_block result = caml_stat_alloc_noexc(slen + 1);
+ if (result == NULL)
+ return NULL;
+ memcpy(result, s, slen + 1);
+ return result;
+}
+
+CAMLexport caml_stat_string caml_stat_strdup(const char *s)
+{
+ caml_stat_string result = caml_stat_strdup_noexc(s);
+ if (result == NULL)
+ caml_raise_out_of_memory();
+ return result;
+}
+
+#ifdef _WIN32
+
+CAMLexport wchar_t * caml_stat_wcsdup(const wchar_t *s)
+{
+ int slen = wcslen(s);
+ wchar_t* result = caml_stat_alloc((slen + 1)*sizeof(wchar_t));
+ if (result == NULL)
+ caml_raise_out_of_memory();
+ memcpy(result, s, (slen + 1)*sizeof(wchar_t));
+ return result;
+}
+
+#endif
+
+CAMLexport caml_stat_string caml_stat_strconcat(int n, ...)
+{
+ va_list args;
+ char *result, *p;
+ size_t len = 0;
+ int i;
+
+ va_start(args, n);
+ for (i = 0; i < n; i++) {
+ const char *s = va_arg(args, const char*);
+ len += strlen(s);
+ }
+ va_end(args);
+
+ result = caml_stat_alloc(len + 1);
+
+ va_start(args, n);
+ p = result;
+ for (i = 0; i < n; i++) {
+ const char *s = va_arg(args, const char*);
+ size_t l = strlen(s);
+ memcpy(p, s, l);
+ p += l;
+ }
+ va_end(args);
+
+ *p = 0;
+ return result;
+}
+
+#ifdef _WIN32
+
+CAMLexport wchar_t* caml_stat_wcsconcat(int n, ...)
+{
+ va_list args;
+ wchar_t *result, *p;
+ size_t len = 0;
+ int i;
+
+ va_start(args, n);
+ for (i = 0; i < n; i++) {
+ const wchar_t *s = va_arg(args, const wchar_t*);
+ len += wcslen(s);
+ }
+ va_end(args);
+
+ result = caml_stat_alloc((len + 1)*sizeof(wchar_t));
+
+ va_start(args, n);
+ p = result;
+ for (i = 0; i < n; i++) {
+ const wchar_t *s = va_arg(args, const wchar_t*);
+ size_t l = wcslen(s);
+ memcpy(p, s, l*sizeof(wchar_t));
+ p += l;
+ }
+ va_end(args);
+
+ *p = 0;
+ return result;
+}
+
+#endif
if (!cf) {
/* [cf] Not matched with a caml_reify_bytecode call; impossible. */
- Assert (0);
+ CAMLassert (0);
} else {
caml_ext_table_remove(&caml_code_fragments_table, cf);
}
actual_size = Wosize_val(caml_global_data);
if (requested_size >= actual_size) {
requested_size = (requested_size + 0x100) & 0xFFFFFF00;
- caml_gc_message (0x08, "Growing global data to %lu entries\n",
+ caml_gc_message (0x08, "Growing global data to %"
+ ARCH_INTNAT_PRINTF_FORMAT "u entries\n",
requested_size);
new_global_data = caml_alloc_shr(requested_size, 0);
for (i = 0; i < actual_size; i++)
tbl->size = sz;
tbl->reserve = rsv;
- new_table = (void *) malloc((tbl->size + tbl->reserve) * element_size);
+ new_table = (void *) caml_stat_alloc_noexc((tbl->size + tbl->reserve) *
+ element_size);
if (new_table == NULL) caml_fatal_error ("Fatal error: not enough memory\n");
if (tbl->base != NULL) caml_stat_free (tbl->base);
tbl->base = new_table;
char *new_heap;
void *new_heap_base;
- Assert (bsz >= Bsize_wsize(Minor_heap_min));
- Assert (bsz <= Bsize_wsize(Minor_heap_max));
- Assert (bsz % sizeof (value) == 0);
+ CAMLassert (bsz >= Bsize_wsize(Minor_heap_min));
+ CAMLassert (bsz <= Bsize_wsize(Minor_heap_max));
+ CAMLassert (bsz % sizeof (value) == 0);
if (caml_young_ptr != caml_young_alloc_end){
CAML_INSTR_INT ("force_minor/set_minor_heap_size@", 1);
caml_requested_minor_gc = 0;
caml_empty_minor_heap ();
}
CAMLassert (caml_young_ptr == caml_young_alloc_end);
- new_heap = caml_aligned_malloc(bsz, 0, &new_heap_base);
+ new_heap = caml_stat_alloc_aligned_noexc(bsz, 0, &new_heap_base);
if (new_heap == NULL) caml_raise_out_of_memory();
if (caml_page_table_add(In_young, new_heap, new_heap + bsz) != 0)
caml_raise_out_of_memory();
if (caml_young_start != NULL){
caml_page_table_remove(In_young, caml_young_start, caml_young_end);
- free (caml_young_base);
+ caml_stat_free (caml_young_base);
}
caml_young_base = new_heap_base;
caml_young_start = (value *) new_heap;
tail_call:
if (Is_block (v) && Is_young (v)){
- Assert ((value *) Hp_val (v) >= caml_young_ptr);
+ CAMLassert ((value *) Hp_val (v) >= caml_young_ptr);
hd = Hd_val (v);
if (hd == 0){ /* If already forwarded */
*p = Field (v, 0); /* then forward pointer is first field. */
Field (result, 1) = oldify_todo_list; /* Add this block */
oldify_todo_list = v; /* to the "to do" list. */
}else{
- Assert (sz == 1);
+ CAMLassert (sz == 1);
p = &Field (result, 0);
v = field0;
goto tail_call;
tag_t ft = 0;
int vv = 1;
- Assert (tag == Forward_tag);
+ CAMLassert (tag == Forward_tag);
if (Is_block (f)){
if (Is_young (f)){
vv = 1;
}
}
}
- if (!vv || ft == Forward_tag || ft == Lazy_tag || ft == Double_tag){
+ if (!vv || ft == Forward_tag || ft == Lazy_tag
+#ifdef FLAT_FLOAT_ARRAY
+ || ft == Double_tag
+#endif
+ ){
/* Do not short-circuit the pointer. Copy as a normal block. */
- Assert (Wosize_hd (hd) == 1);
+ CAMLassert (Wosize_hd (hd) == 1);
result = caml_alloc_shr_preserving_profinfo (1, Forward_tag, hd);
*p = result;
Hd_val (v) = 0; /* Set (GC) forward flag */
while (oldify_todo_list != 0){
v = oldify_todo_list; /* Get the head. */
- Assert (Hd_val (v) == 0); /* It must be forwarded. */
+ CAMLassert (Hd_val (v) == 0); /* It must be forwarded. */
new_v = Field (v, 0); /* Follow forward pointer. */
oldify_todo_list = Field (new_v, 1); /* Remove from list. */
CAML_INSTR_SETUP (tmr, "minor");
prev_alloc_words = caml_allocated_words;
caml_in_minor_collection = 1;
- caml_gc_message (0x02, "<", 0);
+ caml_gc_message (0x02, "<");
caml_oldify_local_roots();
CAML_INSTR_TIME (tmr, "minor/local_roots");
for (r = caml_ref_table.base; r < caml_ref_table.ptr; r++){
if (Hd_val (*key) == 0){ /* Value copied to major heap */
*key = Field (*key, 0);
}else{ /* Value not copied so it's dead */
- Assert(!ephe_check_alive_data(re));
+ CAMLassert(!ephe_check_alive_data(re));
*key = caml_ephe_none;
Field(re->ephe,1) = caml_ephe_none;
}
clear_table ((struct generic_table *) &caml_ref_table);
clear_table ((struct generic_table *) &caml_ephe_ref_table);
clear_table ((struct generic_table *) &caml_custom_table);
- caml_gc_message (0x02, ">", 0);
+ caml_gc_message (0x02, ">");
caml_in_minor_collection = 0;
caml_final_empty_young ();
CAML_INSTR_TIME (tmr, "minor/finalized");
(struct generic_table *tbl, asize_t element_size,
char * msg_intr_int, char *msg_threshold, char *msg_growing, char *msg_error)
{
- Assert (tbl->ptr == tbl->limit);
- Assert (tbl->limit <= tbl->end);
- Assert (tbl->limit >= tbl->threshold);
+ CAMLassert (tbl->ptr == tbl->limit);
+ CAMLassert (tbl->limit <= tbl->end);
+ CAMLassert (tbl->limit >= tbl->threshold);
if (tbl->base == NULL){
alloc_generic_table (tbl, caml_minor_heap_wsz / 8, 256,
tbl->size *= 2;
sz = (tbl->size + tbl->reserve) * element_size;
caml_gc_message (0x08, msg_growing, (intnat) sz/1024);
- tbl->base = (void *) realloc ((char *) tbl->base, sz);
+ tbl->base = caml_stat_resize_noexc (tbl->base, sz);
if (tbl->base == NULL){
caml_fatal_error (msg_error);
}
uintnat caml_verb_gc = 0;
-void caml_gc_message (int level, char *msg, uintnat arg)
+void caml_gc_message (int level, char *msg, ...)
{
if ((caml_verb_gc & level) != 0){
- fprintf (stderr, msg, arg);
+ va_list ap;
+ va_start(ap, msg);
+ vfprintf (stderr, msg, ap);
+ va_end(ap);
fflush (stderr);
}
}
exit(2);
}
-/* [size] and [modulo] are numbers of bytes */
-char *caml_aligned_malloc (asize_t size, int modulo, void **block)
-{
- char *raw_mem;
- uintnat aligned_mem;
- Assert (modulo < Page_size);
- raw_mem = (char *) malloc (size + Page_size);
- if (raw_mem == NULL) return NULL;
- *block = raw_mem;
- raw_mem += modulo; /* Address to be aligned */
- aligned_mem = (((uintnat) raw_mem / Page_size + 1) * Page_size);
-#ifdef DEBUG
- {
- uintnat *p;
- uintnat *p0 = (void *) *block,
- *p1 = (void *) (aligned_mem - modulo),
- *p2 = (void *) (aligned_mem - modulo + size),
- *p3 = (void *) ((char *) *block + size + Page_size);
-
- for (p = p0; p < p1; p++) *p = Debug_filler_align;
- for (p = p1; p < p2; p++) *p = Debug_uninit_align;
- for (p = p2; p < p3; p++) *p = Debug_filler_align;
- }
-#endif
- return (char *) (aligned_mem - modulo);
-}
-
/* If you change the caml_ext_table* functions, also update
asmrun/spacetime.c:find_trie_node_from_libunwind. */
tbl->contents = caml_stat_alloc(sizeof(void *) * init_capa);
}
-int caml_ext_table_add(struct ext_table * tbl, void * data)
+int caml_ext_table_add(struct ext_table * tbl, caml_stat_block data)
{
int res;
if (tbl->size >= tbl->capacity) {
return res;
}
-void caml_ext_table_remove(struct ext_table * tbl, void * data)
+void caml_ext_table_remove(struct ext_table * tbl, caml_stat_block data)
{
int i;
for (i = 0; i < tbl->size; i++) {
caml_stat_free(tbl->contents);
}
-CAMLexport char * caml_strdup(const char * s)
-{
- size_t slen = strlen(s);
- char * res = caml_stat_alloc(slen + 1);
- memcpy(res, s, slen + 1);
- return res;
-}
+/* Integer arithmetic with overflow detection */
-CAMLexport char * caml_strconcat(int n, ...)
+#if ! (__GNUC__ >= 5 || Caml_has_builtin(__builtin_mul_overflow))
+CAMLexport int caml_umul_overflow(uintnat a, uintnat b, uintnat * res)
{
- va_list args;
- char * res, * p;
- size_t len;
- int i;
-
- len = 0;
- va_start(args, n);
- for (i = 0; i < n; i++) {
- const char * s = va_arg(args, const char *);
- len += strlen(s);
- }
- va_end(args);
- res = caml_stat_alloc(len + 1);
- va_start(args, n);
- p = res;
- for (i = 0; i < n; i++) {
- const char * s = va_arg(args, const char *);
- size_t l = strlen(s);
- memcpy(p, s, l);
- p += l;
- }
- va_end(args);
- *p = 0;
- return res;
+#define HALF_SIZE (sizeof(uintnat) * 4)
+#define HALF_MASK (((uintnat)1 << HALF_SIZE) - 1)
+#define LOW_HALF(x) ((x) & HALF_MASK)
+#define HIGH_HALF(x) ((x) >> HALF_SIZE)
+ /* Cut in half words */
+ uintnat al = LOW_HALF(a);
+ uintnat ah = HIGH_HALF(a);
+ uintnat bl = LOW_HALF(b);
+ uintnat bh = HIGH_HALF(b);
+ /* Exact product is:
+ al * bl
+ + ah * bl << HALF_SIZE
+ + al * bh << HALF_SIZE
+ + ah * bh << 2*HALF_SIZE
+ Overflow occurs if:
+ ah * bh is not 0, i.e. ah != 0 and bh != 0
+ OR ah * bl has high half != 0
+ OR al * bh has high half != 0
+ OR the sum al * bl + LOW_HALF(ah * bl) << HALF_SIZE
+ + LOW_HALF(al * bh) << HALF_SIZE overflows.
+ This sum is equal to p = (a * b) modulo word size. */
+ uintnat p = a * b;
+ uintnat p1 = al * bh;
+ uintnat p2 = ah * bl;
+ *res = p;
+ if (ah == 0 && bh == 0) return 0;
+ if (ah != 0 && bh != 0) return 1;
+ if (HIGH_HALF(p1) != 0 || HIGH_HALF(p2) != 0) return 1;
+ p1 <<= HALF_SIZE;
+ p2 <<= HALF_SIZE;
+ p1 += p2;
+ if (p < p1 || p1 < p2) return 1; /* overflow in sums */
+ return 0;
+#undef HALF_SIZE
+#undef HALF_MASK
+#undef LOW_HALF
+#undef HIGH_HALF
}
+#endif
/* Runtime warnings */
for (p = CAML_INSTR_LOG; p != NULL; p = p->next){
for (i = 0; i < p->index; i++){
fprintf (f, "@@ %19ld %19ld %s\n",
- Get_time (p, i), Get_time(p, i+1), p->tag[i+1]);
+ (long) Get_time (p, i), (long) Get_time(p, i+1), p->tag[i+1]);
}
if (p->tag[0][0] != '\000'){
fprintf (f, "@@ %19ld %19ld %s\n",
- Get_time (p, 0), Get_time(p, p->index), p->tag[0]);
+ (long) Get_time (p, 0), (long) Get_time(p, p->index), p->tag[0]);
}
}
fclose (f);
before the block is reallocated (since there must be a minor
collection within each major cycle).
- [newsize] is a value encoding a number of words.
+ [newsize] is a value encoding a number of fields (words, except
+ for float arrays on 32-bit architectures).
*/
CAMLprim value caml_obj_truncate (value v, value newsize)
{
goto loop;
default: /* Should not happen */
- Assert(0);
+ CAMLassert(0);
return RAISE_PARSE_ERROR; /* Keeps gcc -Wall happy */
}
#include "caml/misc.h"
#include "caml/mlvalues.h"
#include "caml/printexc.h"
+#include "caml/memory.h"
struct stringbuf {
char * ptr;
if (buf->ptr < buf->end) *(buf->ptr++) = c;
}
-static void add_string(struct stringbuf *buf, char *s)
+static void add_string(struct stringbuf *buf, const char *s)
{
int len = strlen(s);
if (buf->ptr + len > buf->end) len = buf->end - buf->ptr;
*buf.ptr = 0; /* Terminate string */
i = buf.ptr - buf.data + 1;
- res = malloc(i);
+ res = caml_stat_alloc_noexc(i);
if (res == NULL) return NULL;
memmove(res, buf.data, i);
return res;
caml_backtrace_pos = saved_backtrace_pos;
/* Display the uncaught exception */
fprintf(stderr, "Fatal error: exception %s\n", msg);
- free(msg);
+ caml_stat_free(msg);
/* Display the backtrace if available */
if (caml_backtrace_active && !DEBUGGER_IN_USE)
caml_print_exception_backtrace();
static void caml_enter_blocking_section_default(void)
{
- Assert (caml_async_signal_mode == 0);
+ CAMLassert (caml_async_signal_mode == 0);
caml_async_signal_mode = 1;
}
static void caml_leave_blocking_section_default(void)
{
- Assert (caml_async_signal_mode == 1);
+ CAMLassert (caml_async_signal_mode == 1);
caml_async_signal_mode = 0;
}
/* */
/**************************************************************************/
-#include <assert.h>
#include "caml/fail.h"
#include "caml/mlvalues.h"
-int ensure_spacetime_dot_o_is_included = 42;
+int caml_ensure_spacetime_dot_o_is_included = 42;
CAMLprim value caml_spacetime_only_works_for_native_code(value foo, ...)
{
caml_failwith("Spacetime profiling only works for native code");
- assert(0); /* unreachable */
}
uintnat caml_spacetime_my_profinfo (void)
caml_trapsp = caml_stack_high;
caml_trap_barrier = caml_stack_high + 1;
caml_max_stack_size = initial_max_size;
- caml_gc_message (0x08, "Initial stack limit: %luk bytes\n",
+ caml_gc_message (0x08, "Initial stack limit: %"
+ ARCH_INTNAT_PRINTF_FORMAT "uk bytes\n",
caml_max_stack_size / 1024 * sizeof (value));
}
value * new_low, * new_high, * new_sp;
value * p;
- Assert(caml_extern_sp >= caml_stack_low);
+ CAMLassert(caml_extern_sp >= caml_stack_low);
size = caml_stack_high - caml_stack_low;
do {
if (size >= caml_max_stack_size) caml_raise_stack_overflow();
if (new_max_size < size) new_max_size = size;
if (new_max_size != caml_max_stack_size){
- caml_gc_message (0x08, "Changing stack limit to %luk bytes\n",
+ caml_gc_message (0x08, "Changing stack limit to %"
+ ARCH_INTNAT_PRINTF_FORMAT "uk bytes\n",
new_max_size * sizeof (value) / 1024);
}
caml_max_stack_size = new_max_size;
return BAD_BYTECODE;
}
-int caml_attempt_open(char **name, struct exec_trailer *trail,
+int caml_attempt_open(char_os **name, struct exec_trailer *trail,
int do_open_script)
{
- char * truename;
+ char_os * truename;
int fd;
int err;
- char buf [2];
+ char buf [2], * u8;
truename = caml_search_exe_in_path(*name);
- caml_gc_message(0x100, "Opening bytecode executable %s\n",
- (uintnat) truename);
- fd = open(truename, O_RDONLY | O_BINARY);
+ u8 = caml_stat_strdup_of_os(truename);
+ caml_gc_message(0x100, "Opening bytecode executable %s\n", u8);
+ caml_stat_free(u8);
+ fd = open_os(truename, O_RDONLY | O_BINARY);
if (fd == -1) {
caml_stat_free(truename);
- caml_gc_message(0x100, "Cannot open file\n", 0);
+ caml_gc_message(0x100, "Cannot open file\n");
return FILE_NOT_FOUND;
}
if (!do_open_script) {
if (err < 2 || (buf [0] == '#' && buf [1] == '!')) {
close(fd);
caml_stat_free(truename);
- caml_gc_message(0x100, "Rejected #! script\n", 0);
+ caml_gc_message(0x100, "Rejected #! script\n");
return BAD_BYTECODE;
}
}
if (err != 0) {
close(fd);
caml_stat_free(truename);
- caml_gc_message(0x100, "Not a bytecode executable\n", 0);
+ caml_gc_message(0x100, "Not a bytecode executable\n");
return err;
}
*name = truename;
return data;
}
+#ifdef _WIN32
+
+static char_os * read_section_to_os(int fd, struct exec_trailer *trail, char *name)
+{
+ int32_t len, wlen;
+ char * data;
+ wchar_t * wdata;
+
+ len = caml_seek_optional_section(fd, trail, name);
+ if (len == -1) return NULL;
+ data = caml_stat_alloc(len + 1);
+ if (read(fd, data, len) != len)
+ caml_fatal_error_arg("Fatal error: error reading section %s\n", name);
+ data[len] = 0;
+ wlen = win_multi_byte_to_wide_char(data, len, NULL, 0);
+ wdata = caml_stat_alloc((wlen + 1)*sizeof(wchar_t));
+ win_multi_byte_to_wide_char(data, len, wdata, wlen);
+ wdata[wlen] = 0;
+ caml_stat_free(data);
+ return wdata;
+}
+
+#else
+
+#define read_section_to_os read_section
+
+#endif
+
/* Invocation of ocamlrun: 4 cases.
1. runtime + bytecode
/* Parse options on the command line */
-static int parse_command_line(char **argv)
+static int parse_command_line(char_os **argv)
{
int i, j;
- for(i = 1; argv[i] != NULL && argv[i][0] == '-'; i++) {
+ for(i = 1; argv[i] != NULL && argv[i][0] == _T('-'); i++) {
switch(argv[i][1]) {
- case 't':
+ case _T('t'):
++ caml_trace_level; /* ignored unless DEBUG mode */
break;
- case 'v':
- if (!strcmp (argv[i], "-version")){
+ case _T('v'):
+ if (!strcmp_os (argv[i], _T("-version"))){
printf ("The OCaml runtime, version " OCAML_VERSION_STRING "\n");
exit (0);
- }else if (!strcmp (argv[i], "-vnum")){
+ }else if (!strcmp_os (argv[i], _T("-vnum"))){
printf (OCAML_VERSION_STRING "\n");
exit (0);
}else{
caml_verb_gc = 0x001+0x004+0x008+0x010+0x020;
}
break;
- case 'p':
+ case _T('p'):
for (j = 0; caml_names_of_builtin_cprim[j] != NULL; j++)
printf("%s\n", caml_names_of_builtin_cprim[j]);
exit(0);
break;
- case 'b':
+ case _T('b'):
caml_record_backtrace(Val_true);
break;
- case 'I':
+ case _T('I'):
if (argv[i + 1] != NULL) {
caml_ext_table_add(&caml_shared_libs_path, argv[i + 1]);
i++;
}
break;
default:
- caml_fatal_error_arg("Unknown option %s.\n", argv[i]);
+ caml_fatal_error_arg("Unknown option %s.\n", caml_stat_strdup_of_os(argv[i]));
}
}
return i;
#endif
-extern int ensure_spacetime_dot_o_is_included;
+extern int caml_ensure_spacetime_dot_o_is_included;
/* Main entry point when loading code from a file */
-CAMLexport void caml_main(char **argv)
+CAMLexport void caml_main(char_os **argv)
{
int fd, pos;
struct exec_trailer trail;
struct channel * chan;
value res;
- char * shared_lib_path, * shared_libs, * req_prims;
- char * exe_name, * proc_self_exe;
+ char * req_prims;
+ char_os * shared_lib_path, * shared_libs;
+ char_os * exe_name, * proc_self_exe;
+
+ caml_ensure_spacetime_dot_o_is_included++;
- ensure_spacetime_dot_o_is_included++;
+ /* Determine options */
+#ifdef DEBUG
+ caml_verb_gc = 0x3F;
+#endif
+ caml_parse_ocamlrunparam();
+#ifdef DEBUG
+ caml_gc_message (-1, "### OCaml runtime: debug mode ###\n");
+#endif
+ if (!caml_startup_aux(/* pooling */ caml_cleanup_on_exit))
+ return;
/* Machine-dependent initialization of the floating-point hardware
so that it behaves as much as possible as specified in IEEE */
caml_init_custom_operations();
caml_ext_table_init(&caml_shared_libs_path, 8);
caml_external_raise = NULL;
- /* Determine options and position of bytecode file */
-#ifdef DEBUG
- caml_verb_gc = 0x3F;
-#endif
- caml_parse_ocamlrunparam();
-#ifdef DEBUG
- caml_gc_message (-1, "### OCaml runtime: debug mode ###\n", 0);
-#endif
+ /* Determine position of bytecode file */
pos = 0;
/* First, try argv[0] (when ocamlrun is called by a bytecode program) */
fd = caml_attempt_open(&exe_name, &trail, 1);
switch(fd) {
case FILE_NOT_FOUND:
- caml_fatal_error_arg("Fatal error: cannot find file '%s'\n", argv[pos]);
+ caml_fatal_error_arg("Fatal error: cannot find file '%s'\n", caml_stat_strdup_of_os(argv[pos]));
break;
case BAD_BYTECODE:
caml_fatal_error_arg(
"Fatal error: the file '%s' is not a bytecode executable file\n",
- exe_name);
+ caml_stat_strdup_of_os(exe_name));
break;
}
}
caml_load_code(fd, caml_code_size);
caml_init_debug_info();
/* Build the table of primitives */
- shared_lib_path = read_section(fd, &trail, "DLPT");
- shared_libs = read_section(fd, &trail, "DLLS");
+ shared_lib_path = read_section_to_os(fd, &trail, "DLPT");
+ shared_libs = read_section_to_os(fd, &trail, "DLLS");
req_prims = read_section(fd, &trail, "PRIM");
if (req_prims == NULL) caml_fatal_error("Fatal error: no PRIM section\n");
caml_build_primitive_table(shared_lib_path, shared_libs, req_prims);
caml_sys_init(exe_name, argv + pos);
#ifdef _WIN32
/* Start a thread to handle signals */
- if (caml_secure_getenv("CAMLSIGPIPE"))
+ if (caml_secure_getenv(_T("CAMLSIGPIPE")))
_beginthread(caml_signal_thread, 4096, NULL);
#endif
/* Execute the program */
code_t code, asize_t code_size,
char *data, asize_t data_size,
char *section_table, asize_t section_table_size,
- char **argv)
+ int pooling,
+ char_os **argv)
{
- char * cds_file;
- char * exe_name;
+ char_os * cds_file;
+ char_os * exe_name;
+
+ /* Determine options */
+#ifdef DEBUG
+ caml_verb_gc = 0x3F;
+#endif
+ caml_parse_ocamlrunparam();
+#ifdef DEBUG
+ caml_gc_message (-1, "### OCaml runtime: debug mode ###\n");
+#endif
+ if (caml_cleanup_on_exit)
+ pooling = 1;
+ if (!caml_startup_aux(pooling))
+ return Val_unit;
caml_init_ieee_floats();
#if defined(_MSC_VER) && __STDC_SECURE_LIB__ >= 200411L
caml_install_invalid_parameter_handler();
#endif
caml_init_custom_operations();
-#ifdef DEBUG
- caml_verb_gc = 63;
-#endif
- cds_file = caml_secure_getenv("CAML_DEBUG_FILE");
+ cds_file = caml_secure_getenv(_T("CAML_DEBUG_FILE"));
if (cds_file != NULL) {
- caml_cds_file = caml_strdup(cds_file);
+ caml_cds_file = caml_stat_strdup_os(cds_file);
}
- caml_parse_ocamlrunparam();
exe_name = caml_executable_name();
if (exe_name == NULL) exe_name = caml_search_exe_in_path(argv[0]);
caml_external_raise = NULL;
code_t code, asize_t code_size,
char *data, asize_t data_size,
char *section_table, asize_t section_table_size,
- char **argv)
+ int pooling,
+ char_os **argv)
{
value res;
res = caml_startup_code_exn(code, code_size, data, data_size,
section_table, section_table_size,
- argv);
+ pooling, argv);
if (Is_exception_result(res)) {
caml_exn_bucket = Extract_exception(res);
if (caml_debugger_in_use) {
#include <stdio.h>
#include "caml/backtrace.h"
#include "caml/memory.h"
+#include "caml/callback.h"
+#include "caml/major_gc.h"
+#ifndef NATIVE_CODE
+#include "caml/dynlink.h"
+#endif
#include "caml/osdeps.h"
#include "caml/startup_aux.h"
uintnat caml_init_major_window = Major_window_def;
extern int caml_parser_trace;
uintnat caml_trace_level = 0;
+uintnat caml_cleanup_on_exit = 0;
-static void scanmult (char *opt, uintnat *var)
+static void scanmult (char_os *opt, uintnat *var)
{
- char mult = ' ';
+ char_os mult = _T(' ');
unsigned int val = 1;
- sscanf (opt, "=%u%c", &val, &mult);
- sscanf (opt, "=0x%x%c", &val, &mult);
+ sscanf_os (opt, _T("=%u%c"), &val, &mult);
+ sscanf_os (opt, _T("=0x%x%c"), &val, &mult);
switch (mult) {
- case 'k': *var = (uintnat) val * 1024; break;
- case 'M': *var = (uintnat) val * (1024 * 1024); break;
- case 'G': *var = (uintnat) val * (1024 * 1024 * 1024); break;
+ case _T('k'): *var = (uintnat) val * 1024; break;
+ case _T('M'): *var = (uintnat) val * (1024 * 1024); break;
+ case _T('G'): *var = (uintnat) val * (1024 * 1024 * 1024); break;
default: *var = (uintnat) val; break;
}
}
void caml_parse_ocamlrunparam(void)
{
- char *opt = caml_secure_getenv ("OCAMLRUNPARAM");
+ char_os *opt = caml_secure_getenv (_T("OCAMLRUNPARAM"));
uintnat p;
- if (opt == NULL) opt = caml_secure_getenv ("CAMLRUNPARAM");
+ if (opt == NULL) opt = caml_secure_getenv (_T("CAMLRUNPARAM"));
if (opt != NULL){
- while (*opt != '\0'){
+ while (*opt != _T('\0')){
switch (*opt++){
- case 'a': scanmult (opt, &p); caml_set_allocation_policy (p); break;
- case 'b': scanmult (opt, &p); caml_record_backtrace(Val_bool (p)); break;
- case 'h': scanmult (opt, &caml_init_heap_wsz); break;
- case 'H': scanmult (opt, &caml_use_huge_pages); break;
- case 'i': scanmult (opt, &caml_init_heap_chunk_sz); break;
- case 'l': scanmult (opt, &caml_init_max_stack_wsz); break;
- case 'o': scanmult (opt, &caml_init_percent_free); break;
- case 'O': scanmult (opt, &caml_init_max_percent_free); break;
- case 'p': scanmult (opt, &p); caml_parser_trace = p; break;
- case 'R': break; /* see stdlib/hashtbl.mli */
- case 's': scanmult (opt, &caml_init_minor_heap_wsz); break;
- case 't': scanmult (opt, &caml_trace_level); break;
- case 'v': scanmult (opt, &caml_verb_gc); break;
- case 'w': scanmult (opt, &caml_init_major_window); break;
- case 'W': scanmult (opt, &caml_runtime_warnings); break;
+ case _T('a'): scanmult (opt, &p); caml_set_allocation_policy (p); break;
+ case _T('b'): scanmult (opt, &p); caml_record_backtrace(Val_bool (p)); break;
+ case _T('c'): scanmult (opt, &p); caml_cleanup_on_exit = p; break;
+ case _T('h'): scanmult (opt, &caml_init_heap_wsz); break;
+ case _T('H'): scanmult (opt, &caml_use_huge_pages); break;
+ case _T('i'): scanmult (opt, &caml_init_heap_chunk_sz); break;
+ case _T('l'): scanmult (opt, &caml_init_max_stack_wsz); break;
+ case _T('o'): scanmult (opt, &caml_init_percent_free); break;
+ case _T('O'): scanmult (opt, &caml_init_max_percent_free); break;
+ case _T('p'): scanmult (opt, &p); caml_parser_trace = p; break;
+ case _T('R'): break; /* see stdlib/hashtbl.mli */
+ case _T('s'): scanmult (opt, &caml_init_minor_heap_wsz); break;
+ case _T('t'): scanmult (opt, &caml_trace_level); break;
+ case _T('v'): scanmult (opt, &caml_verb_gc); break;
+ case _T('w'): scanmult (opt, &caml_init_major_window); break;
+ case _T('W'): scanmult (opt, &caml_runtime_warnings); break;
}
- while (*opt != '\0'){
+ while (*opt != _T('\0')){
if (*opt++ == ',') break;
}
}
}
}
+
+
+/* The number of outstanding calls to caml_startup */
+static int startup_count = 0;
+
+/* Has the runtime been shut down already? */
+static int shutdown_happened = 0;
+
+
+int caml_startup_aux(int pooling)
+{
+ if (shutdown_happened == 1)
+ caml_fatal_error("Fatal error: caml_startup was called after the runtime "
+ "was shut down with caml_shutdown");
+
+ /* Second and subsequent calls are ignored,
+ since the runtime has already started */
+ startup_count++;
+ if (startup_count > 1)
+ return 0;
+
+ if (pooling)
+ caml_stat_create_pool();
+
+ return 1;
+}
+
+static void call_registered_value(char* name)
+{
+ value *f = caml_named_value(name);
+ if (f != NULL)
+ caml_callback_exn(*f, Val_unit);
+}
+
+CAMLexport void caml_shutdown(void)
+{
+ if (startup_count <= 0)
+ caml_fatal_error("Fatal error: a call to caml_shutdown has no "
+ "corresponding call to caml_startup");
+
+ /* Do nothing unless it's the last call remaining */
+ startup_count--;
+ if (startup_count > 0)
+ return;
+
+ call_registered_value("Pervasives.do_at_exit");
+ call_registered_value("Thread.at_shutdown");
+ caml_finalise_heap();
+#ifndef NATIVE_CODE
+ caml_free_shared_libs();
+#endif
+ caml_stat_destroy_pool();
+
+ shutdown_happened = 1;
+}
#include <stdarg.h>
#include "caml/alloc.h"
#include "caml/fail.h"
+#include "caml/memory.h"
#include "caml/mlvalues.h"
#include "caml/misc.h"
{
mlsize_t temp;
temp = Bosize_val(s) - 1;
- Assert (Byte (s, temp - Byte (s, temp)) == 0);
+ CAMLassert (Byte (s, temp - Byte (s, temp)) == 0);
return temp - Byte (s, temp);
}
{
mlsize_t temp;
temp = Bosize_val(s) - 1;
- Assert (Byte (s, temp - Byte (s, temp)) == 0);
+ CAMLassert (Byte (s, temp - Byte (s, temp)) == 0);
return Val_long(temp - Byte (s, temp));
}
CAMLexport value caml_alloc_sprintf(const char * format, ...)
{
va_list args;
- char buf[64];
+ char buf[128];
int n;
value res;
excluding the terminating '\0'. */
n = vsnprintf(buf, sizeof(buf), format, args);
va_end(args);
- /* Allocate a Caml string with length "n" as computed by vsnprintf. */
- res = caml_alloc_string(n);
if (n < sizeof(buf)) {
/* All output characters were written to buf, including the
- terminating '\0'. Just copy them to the result. */
- memcpy(String_val(res), buf, n);
+ terminating '\0'. Allocate a Caml string with length "n"
+ as computed by vsnprintf, and copy the output of vsnprintf into it. */
+ res = caml_alloc_initialized_string(n, buf);
} else {
+ /* PR#7568: if the format is in the Caml heap, the following
+ caml_alloc_string could move or free the format. To prevent
+ this, take a copy of the format outside the Caml heap. */
+ char * saved_format = caml_stat_strdup(format);
+ /* Allocate a Caml string with length "n" as computed by vsnprintf. */
+ res = caml_alloc_string(n);
/* Re-do the formatting, outputting directly in the Caml string.
Note that caml_alloc_string left room for a '\0' at position n,
so the size passed to vsnprintf is n+1. */
va_start(args, format);
- vsnprintf(String_val(res), n + 1, format, args);
+ vsnprintf((char *)String_val(res), n + 1, saved_format, args);
va_end(args);
+ caml_stat_free(saved_format);
}
return res;
#else
if (n >= 0 && n <= sizeof(buf)) {
/* All output characters were written to buf.
"n" is the actual length of the output.
- Copy the characters to a Caml string of length n. */
+ Allocate a Caml string of length "n" and copy the characters into it. */
res = caml_alloc_string(n);
memcpy(String_val(res), buf, n);
} else {
+ /* PR#7568: if the format is in the Caml heap, the following
+ caml_alloc_string could move or free the format. To prevent
+ this, take a copy of the format outside the Caml heap. */
+ char * saved_format = caml_stat_strdup(format);
/* Determine actual length of output, excluding final '\0' */
va_start(args, format);
n = _vscprintf(format, args);
Note that caml_alloc_string left room for a '\0' at position n,
so the size passed to _vsnprintf is n+1. */
va_start(args, format);
- _vsnprintf(String_val(res), n + 1, format, args);
+ _vsnprintf(String_val(res), n + 1, saved_format, args);
va_end(args);
+ caml_stat_free(saved_format);
}
return res;
#endif
#include <sys/stat.h>
#ifdef _WIN32
#include <io.h> /* for isatty */
+#include <direct.h> /* for _wchdir and _wgetcwd */
#else
#include <sys/wait.h>
#endif
#include "caml/debugger.h"
#include "caml/fail.h"
#include "caml/gc_ctrl.h"
-#include "caml/instruct.h"
#include "caml/io.h"
#include "caml/misc.h"
#include "caml/mlvalues.h"
#include "caml/stacks.h"
#include "caml/sys.h"
#include "caml/version.h"
+#include "caml/callback.h"
+#include "caml/startup_aux.h"
static char * error_message(void)
{
intnat heap_chunks = caml_stat_heap_chunks;
intnat top_heap_words = caml_stat_top_heap_wsz;
intnat cpct = caml_stat_compactions;
- caml_gc_message(0x400, "allocated_words: %ld\n", (long)allocated_words);
- caml_gc_message(0x400, "minor_words: %ld\n", (long) minwords);
- caml_gc_message(0x400, "promoted_words: %ld\n", (long) prowords);
- caml_gc_message(0x400, "major_words: %ld\n", (long) majwords);
- caml_gc_message(0x400, "minor_collections: %d\n", mincoll);
- caml_gc_message(0x400, "major_collections: %d\n", majcoll);
- caml_gc_message(0x400, "heap_words: %d\n", heap_words);
- caml_gc_message(0x400, "heap_chunks: %d\n", heap_chunks);
- caml_gc_message(0x400, "top_heap_words: %d\n", top_heap_words);
- caml_gc_message(0x400, "compactions: %d\n", cpct);
+ caml_gc_message(0x400, "allocated_words: %.0f\n", allocated_words);
+ caml_gc_message(0x400, "minor_words: %.0f\n", minwords);
+ caml_gc_message(0x400, "promoted_words: %.0f\n", prowords);
+ caml_gc_message(0x400, "major_words: %.0f\n", majwords);
+ caml_gc_message(0x400, "minor_collections: %"ARCH_INTNAT_PRINTF_FORMAT"d\n",
+ mincoll);
+ caml_gc_message(0x400, "major_collections: %"ARCH_INTNAT_PRINTF_FORMAT"d\n",
+ majcoll);
+ caml_gc_message(0x400, "heap_words: %"ARCH_INTNAT_PRINTF_FORMAT"d\n",
+ heap_words);
+ caml_gc_message(0x400, "heap_chunks: %"ARCH_INTNAT_PRINTF_FORMAT"d\n",
+ heap_chunks);
+ caml_gc_message(0x400, "top_heap_words: %"ARCH_INTNAT_PRINTF_FORMAT"d\n",
+ top_heap_words);
+ caml_gc_message(0x400, "compactions: %"ARCH_INTNAT_PRINTF_FORMAT"d\n",
+ cpct);
}
#ifndef NATIVE_CODE
caml_debugger(PROGRAM_EXIT);
#endif
CAML_INSTR_ATEXIT ();
+ if (caml_cleanup_on_exit)
+ caml_shutdown();
+#ifdef _WIN32
+ caml_restore_win32_terminal();
+#endif
CAML_SYS_EXIT(retcode);
return Val_unit;
}
{
CAMLparam3(path, vflags, vperm);
int fd, flags, perm;
- char * p;
+ char_os * p;
+
+#if defined(O_CLOEXEC)
+ flags = O_CLOEXEC;
+#elif defined(_WIN32)
+ flags = _O_NOINHERIT;
+#else
+ flags = 0;
+#endif
caml_sys_check_path(path);
- p = caml_strdup(String_val(path));
- flags = caml_convert_flag_list(vflags, sys_open_flags);
+ p = caml_stat_strdup_to_os(String_val(path));
+ flags |= caml_convert_flag_list(vflags, sys_open_flags);
perm = Int_val(vperm);
/* open on a named FIFO can block (PR#1533) */
caml_enter_blocking_section();
fd = CAML_SYS_OPEN(p, flags, perm);
/* fcntl on a fd can block (PR#5069)*/
-#if defined(F_SETFD) && defined(FD_CLOEXEC)
+#if defined(F_SETFD) && defined(FD_CLOEXEC) && !defined(_WIN32) \
+ && !defined(O_CLOEXEC)
if (fd != -1)
fcntl(fd, F_SETFD, FD_CLOEXEC);
#endif
#else
struct stat st;
#endif
- char * p;
+ char_os * p;
int ret;
if (! caml_string_is_c_safe(name)) return Val_false;
- p = caml_strdup(String_val(name));
+ p = caml_stat_strdup_to_os(String_val(name));
caml_enter_blocking_section();
-#ifdef _WIN32
- ret = _stati64(p, &st);
-#else
ret = CAML_SYS_STAT(p, &st);
-#endif
caml_leave_blocking_section();
caml_stat_free(p);
#else
struct stat st;
#endif
- char * p;
+ char_os * p;
int ret;
caml_sys_check_path(name);
- p = caml_strdup(String_val(name));
+ p = caml_stat_strdup_to_os(String_val(name));
caml_enter_blocking_section();
-#ifdef _WIN32
- ret = _stati64(p, &st);
-#else
ret = CAML_SYS_STAT(p, &st);
-#endif
caml_leave_blocking_section();
caml_stat_free(p);
CAMLprim value caml_sys_remove(value name)
{
CAMLparam1(name);
- char * p;
+ char_os * p;
int ret;
caml_sys_check_path(name);
- p = caml_strdup(String_val(name));
+ p = caml_stat_strdup_to_os(String_val(name));
caml_enter_blocking_section();
ret = CAML_SYS_UNLINK(p);
caml_leave_blocking_section();
CAMLprim value caml_sys_rename(value oldname, value newname)
{
- char * p_old;
- char * p_new;
+ char_os * p_old;
+ char_os * p_new;
int ret;
caml_sys_check_path(oldname);
caml_sys_check_path(newname);
- p_old = caml_strdup(String_val(oldname));
- p_new = caml_strdup(String_val(newname));
+ p_old = caml_stat_strdup_to_os(String_val(oldname));
+ p_new = caml_stat_strdup_to_os(String_val(newname));
caml_enter_blocking_section();
ret = CAML_SYS_RENAME(p_old, p_new);
caml_leave_blocking_section();
CAMLprim value caml_sys_chdir(value dirname)
{
CAMLparam1(dirname);
- char * p;
+ char_os * p;
int ret;
caml_sys_check_path(dirname);
- p = caml_strdup(String_val(dirname));
+ p = caml_stat_strdup_to_os(String_val(dirname));
caml_enter_blocking_section();
ret = CAML_SYS_CHDIR(p);
caml_leave_blocking_section();
CAMLprim value caml_sys_getcwd(value unit)
{
- char buff[4096];
+ char_os buff[4096];
+ char_os * ret;
#ifdef HAS_GETCWD
- if (getcwd(buff, sizeof(buff)) == 0) caml_sys_error(NO_ARG);
+ ret = getcwd_os(buff, sizeof(buff)/sizeof(*buff));
#else
- if (getwd(buff) == 0) caml_sys_error(NO_ARG);
+ caml_invalid_argument("Sys.getcwd not implemented");
#endif /* HAS_GETCWD */
- return caml_copy_string(buff);
+ if (ret == 0) caml_sys_error(NO_ARG);
+ return caml_copy_string_of_os(buff);
}
CAMLprim value caml_sys_unsafe_getenv(value var)
{
- char * res;
+ char_os * res, * p;
if (! caml_string_is_c_safe(var)) caml_raise_not_found();
- res = CAML_SYS_GETENV(String_val(var));
+ p = caml_stat_strdup_to_os(String_val(var));
+ res = CAML_SYS_GETENV(p);
+ caml_stat_free(p);
if (res == 0) caml_raise_not_found();
- return caml_copy_string(res);
+ return caml_copy_string_of_os(res);
}
CAMLprim value caml_sys_getenv(value var)
{
- char * res;
+ char_os * res, * p;
if (! caml_string_is_c_safe(var)) caml_raise_not_found();
- res = caml_secure_getenv(String_val(var));
+ p = caml_stat_strdup_to_os(String_val(var));
+ res = caml_secure_getenv(p);
+ caml_stat_free(p);
if (res == 0) caml_raise_not_found();
- return caml_copy_string(res);
+ return caml_copy_string_of_os(res);
}
-char * caml_exe_name;
-char ** caml_main_argv;
+char_os * caml_exe_name;
+char_os ** caml_main_argv;
CAMLprim value caml_sys_get_argv(value unit)
{
CAMLparam0 (); /* unit is unused */
CAMLlocal3 (exe_name, argv, res);
- exe_name = caml_copy_string(caml_exe_name);
- argv = caml_copy_string_array((char const **) caml_main_argv);
+ exe_name = caml_copy_string_of_os(caml_exe_name);
+ argv = caml_alloc_array((void *)caml_copy_string_of_os, (char const **) caml_main_argv);
res = caml_alloc_small(2, 0);
Field(res, 0) = exe_name;
Field(res, 1) = argv;
CAMLreturn(res);
}
-void caml_sys_init(char * exe_name, char **argv)
+void caml_sys_init(char_os * exe_name, char_os **argv)
{
+#ifdef _WIN32
+ /* Initialises the caml_win32_* globals on Windows with the version of
+ Windows which is running */
+ caml_probe_win32_version();
+#if WINDOWS_UNICODE
+ caml_setup_win32_terminal();
+#endif
+#endif
#ifdef CAML_WITH_CPLUGINS
caml_cplugins_init(exe_name, argv);
#endif
{
CAMLparam1 (command);
int status, retcode;
- char *buf;
+ char_os *buf;
if (! caml_string_is_c_safe (command)) {
errno = EINVAL;
caml_sys_error(command);
}
- buf = caml_strdup(String_val(command));
+ buf = caml_stat_strdup_to_os(String_val(command));
caml_enter_blocking_section ();
status = CAML_SYS_SYSTEM(buf);
caml_leave_blocking_section ();
CAMLparam1(path);
CAMLlocal1(result);
struct ext_table tbl;
- char * p;
+ char_os * p;
int ret;
caml_sys_check_path(path);
caml_ext_table_init(&tbl, 50);
- p = caml_strdup(String_val(path));
+ p = caml_stat_strdup_to_os(String_val(path));
caml_enter_blocking_section();
ret = CAML_SYS_READ_DIRECTORY(p, &tbl);
caml_leave_blocking_section();
static struct cplugin_context cplugin_context;
-void caml_load_plugin(char *plugin)
+void caml_load_plugin(char_os *plugin)
{
void* dll_handle = NULL;
+ char* u8;
dll_handle = caml_dlopen(plugin, DLL_EXECUTABLE, DLL_NOT_GLOBAL);
if( dll_handle != NULL ){
caml_dlclose(dll_handle);
}
} else {
+ u8 = caml_stat_strdup_of_os(plugin);
fprintf(stderr, "Cannot load C plugin %s\nReason: %s\n",
- plugin, caml_dlerror());
+ u8, caml_dlerror());
+ caml_stat_free(u8);
}
}
-void caml_cplugins_load(char *env_variable)
+void caml_cplugins_load(char_os *env_variable)
{
- char *plugins = caml_secure_getenv(env_variable);
+ char_os *plugins = caml_secure_getenv(env_variable);
if(plugins != NULL){
- char* curs = plugins;
+ char_os* curs = plugins;
while(*curs != 0){
- if(*curs == ','){
+ if(*curs == _T(',')){
if(curs > plugins){
*curs = 0;
caml_load_plugin(plugins);
}
}
-void caml_cplugins_init(char * exe_name, char **argv)
+void caml_cplugins_init(char_os * exe_name, char_os **argv)
{
cplugin_context.api_version = CAML_CPLUGIN_CONTEXT_API;
cplugin_context.prims_bitmap = CAML_CPLUGINS_PRIMS_BITMAP;
cplugin_context.exe_name = exe_name;
cplugin_context.argv = argv;
cplugin_context.ocaml_version = OCAML_VERSION_STRING;
- caml_cplugins_load("CAML_CPLUGINS");
+ caml_cplugins_load(_T("CAML_CPLUGINS"));
#ifdef NATIVE_CODE
- caml_cplugins_load("CAML_NATIVE_CPLUGINS");
+ caml_cplugins_load(_T("CAML_NATIVE_CPLUGINS"));
#else
- caml_cplugins_load("CAML_BYTE_CPLUGINS");
+ caml_cplugins_load(_T("CAML_BYTE_CPLUGINS"));
#endif
}
standout = tgetstr ("so", &area_p);
standend = tgetstr ("se", &area_p);
}
- Assert (area_p <= area + 1024);
+ CAMLassert (area_p <= area + 1024);
if (num_lines == -1 || up == NULL || down == NULL
|| standout == NULL || standend == NULL){
return Bad_term;
#include "caml/signals.h"
#include "caml/sys.h"
#include "caml/io.h"
+#include "caml/alloc.h"
#ifndef S_ISREG
#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
return retcode;
}
-char * caml_decompose_path(struct ext_table * tbl, char * path)
+caml_stat_string caml_decompose_path(struct ext_table * tbl, char * path)
{
char * p, * q;
size_t n;
if (path == NULL) return NULL;
- p = caml_strdup(path);
+ p = caml_stat_strdup(path);
q = p;
while (1) {
for (n = 0; q[n] != 0 && q[n] != ':'; n++) /*nothing*/;
return p;
}
-char * caml_search_in_path(struct ext_table * path, char * name)
+caml_stat_string caml_search_in_path(struct ext_table * path, const char * name)
{
- char * p, * dir, * fullname;
+ const char * p;
+ char * dir, * fullname;
int i;
struct stat st;
for (i = 0; i < path->size; i++) {
dir = path->contents[i];
if (dir[0] == 0) dir = "."; /* empty path component = current dir */
- fullname = caml_strconcat(3, dir, "/", name);
+ fullname = caml_stat_strconcat(3, dir, "/", name);
if (stat(fullname, &st) == 0 && S_ISREG(st.st_mode))
return fullname;
caml_stat_free(fullname);
}
not_found:
- return caml_strdup(name);
+ return caml_stat_strdup(name);
}
#ifdef __CYGWIN__
/* Cygwin needs special treatment because of the implicit ".exe" at the
end of executable file names */
-static int cygwin_file_exists(char * name)
+static int cygwin_file_exists(const char * name)
{
int fd;
/* Cannot use stat() here because it adds ".exe" implicitly */
return 1;
}
-static char * cygwin_search_exe_in_path(struct ext_table * path, char * name)
+static caml_stat_string cygwin_search_exe_in_path(struct ext_table * path, const char * name)
{
- char * p, * dir, * fullname;
+ const char * p;
+ char * dir, * fullname;
int i;
for (p = name; *p != 0; p++) {
for (i = 0; i < path->size; i++) {
dir = path->contents[i];
if (dir[0] == 0) dir = "."; /* empty path component = current dir */
- fullname = caml_strconcat(3, dir, "/", name);
+ fullname = caml_stat_strconcat(3, dir, "/", name);
if (cygwin_file_exists(fullname)) return fullname;
caml_stat_free(fullname);
- fullname = caml_strconcat(4, dir, "/", name, ".exe");
+ fullname = caml_stat_strconcat(4, dir, "/", name, ".exe");
if (cygwin_file_exists(fullname)) return fullname;
caml_stat_free(fullname);
}
not_found:
- if (cygwin_file_exists(name)) return caml_strdup(name);
- fullname = caml_strconcat(2, name, ".exe");
+ if (cygwin_file_exists(name)) return caml_stat_strdup(name);
+ fullname = caml_stat_strconcat(2, name, ".exe");
if (cygwin_file_exists(fullname)) return fullname;
caml_stat_free(fullname);
- return caml_strdup(name);
+ return caml_stat_strdup(name);
}
#endif
-char * caml_search_exe_in_path(char * name)
+caml_stat_string caml_search_exe_in_path(const char * name)
{
struct ext_table path;
char * tofree;
- char * res;
+ caml_stat_string res;
caml_ext_table_init(&path, 8);
tofree = caml_decompose_path(&path, getenv("PATH"));
return res;
}
-char * caml_search_dll_in_path(struct ext_table * path, char * name)
+caml_stat_string caml_search_dll_in_path(struct ext_table * path, const char * name)
{
- char * dllname;
- char * res;
+ caml_stat_string dllname;
+ caml_stat_string res;
- dllname = caml_strconcat(2, name, ".so");
+ dllname = caml_stat_strconcat(2, name, ".so");
res = caml_search_in_path(path, dllname);
caml_stat_free(dllname);
return res;
flexdll_dlclose(handle);
}
-void * caml_dlsym(void * handle, char * name)
+void * caml_dlsym(void * handle, const char * name)
{
return flexdll_dlsym(handle, name);
}
-void * caml_globalsym(char * name)
+void * caml_globalsym(const char * name)
{
return flexdll_dlsym(flexdll_dlopen(NULL,0), name);
}
#ifndef RTLD_LOCAL
#define RTLD_LOCAL 0
#endif
-#ifndef RTLD_NODELETE
-#define RTLD_NODELETE 0
-#endif
void * caml_dlopen(char * libname, int for_execution, int global)
{
- return dlopen(libname, RTLD_NOW | (global ? RTLD_GLOBAL : RTLD_LOCAL)
- | RTLD_NODELETE);
+ return dlopen(libname, RTLD_NOW | (global ? RTLD_GLOBAL : RTLD_LOCAL));
/* Could use RTLD_LAZY if for_execution == 0, but needs testing */
}
dlclose(handle);
}
-void * caml_dlsym(void * handle, char * name)
+void * caml_dlsym(void * handle, const char * name)
{
#ifdef DL_NEEDS_UNDERSCORE
char _name[1000] = "_";
return dlsym(handle, name);
}
-void * caml_globalsym(char * name)
+void * caml_globalsym(const char * name)
{
#ifdef RTLD_DEFAULT
return caml_dlsym(RTLD_DEFAULT, name);
{
}
-void * caml_dlsym(void * handle, char * name)
+void * caml_dlsym(void * handle, const char * name)
{
return NULL;
}
-void * caml_globalsym(char * name)
+void * caml_globalsym(const char * name)
{
return NULL;
}
e = readdir(d);
if (e == NULL) break;
if (strcmp(e->d_name, ".") == 0 || strcmp(e->d_name, "..") == 0) continue;
- caml_ext_table_add(contents, caml_strdup(e->d_name));
+ caml_ext_table_add(contents, caml_stat_strdup(e->d_name));
}
closedir(d);
return 0;
to determine the size of the buffer. Instead, we guess and adjust. */
namelen = 256;
while (1) {
- name = caml_stat_alloc(namelen + 1);
+ name = caml_stat_alloc(namelen);
retcode = readlink("/proc/self/exe", name, namelen);
if (retcode == -1) { caml_stat_free(name); return NULL; }
- if (retcode <= namelen) break;
+ if (retcode < namelen) break;
caml_stat_free(name);
if (namelen >= 1024*1024) return NULL; /* avoid runaway and overflow */
namelen *= 2;
}
- /* readlink() does not zero-terminate its result */
+ /* readlink() does not zero-terminate its result.
+ There is room for a final zero since retcode < namelen. */
name[retcode] = 0;
/* Make sure that the contents of /proc/self/exe is a regular file.
(Old Linux kernels return an inode number instead.) */
if (_NSGetExecutablePath(name, &namelen) == 0) return name;
caml_stat_free(name);
return NULL;
-
+
#else
return NULL;
Outside minor and major heap, x must be black.
*/
static inline int Is_Dead_during_clean(value x){
- Assert (x != caml_ephe_none); Assert (caml_gc_phase == Phase_clean);
+ CAMLassert (x != caml_ephe_none);
+ CAMLassert (caml_gc_phase == Phase_clean);
return Is_block (x) && !Is_young (x) && Is_white_val(x);
}
/** The minor heap doesn't have to be marked, outside they should
already be black
*/
static inline int Must_be_Marked_during_mark(value x){
- Assert (x != caml_ephe_none); Assert (caml_gc_phase == Phase_mark);
+ CAMLassert (x != caml_ephe_none);
+ CAMLassert (caml_gc_phase == Phase_mark);
return Is_block (x) && !Is_young (x);
}
#else
static inline int Is_Dead_during_clean(value x){
- Assert (x != caml_ephe_none); Assert (caml_gc_phase == Phase_clean);
+ CAMLassert (x != caml_ephe_none);
+ CAMLassert (caml_gc_phase == Phase_clean);
return Is_block (x) && Is_in_heap (x) && Is_white_val(x);
}
static inline int Must_be_Marked_during_mark(value x){
- Assert (x != caml_ephe_none); Assert (caml_gc_phase == Phase_mark);
+ CAMLassert (x != caml_ephe_none);
+ CAMLassert (caml_gc_phase == Phase_mark);
return Is_block (x) && Is_in_heap (x);
}
#endif
that is going to disappear is dead and so should trigger a cleaning
*/
static void do_check_key_clean(value ar, mlsize_t offset){
- Assert ( offset >= 2);
+ CAMLassert ( offset >= 2);
if (caml_gc_phase == Phase_clean){
value elt = Field (ar, offset);
if (elt != caml_ephe_none && Is_Dead_during_clean(elt)){
CAMLprim value caml_ephe_set_key (value ar, value n, value el)
{
mlsize_t offset = Long_val (n) + 2;
- Assert (Is_in_heap (ar));
+ CAMLassert (Is_in_heap (ar));
if (offset < 2 || offset >= Wosize_val (ar)){
caml_invalid_argument ("Weak.set");
}
CAMLprim value caml_ephe_unset_key (value ar, value n)
{
mlsize_t offset = Long_val (n) + 2;
- Assert (Is_in_heap (ar));
+ CAMLassert (Is_in_heap (ar));
if (offset < 2 || offset >= Wosize_val (ar)){
caml_invalid_argument ("Weak.set");
}
value caml_ephe_set_key_option (value ar, value n, value el)
{
mlsize_t offset = Long_val (n) + 2;
- Assert (Is_in_heap (ar));
+ CAMLassert (Is_in_heap (ar));
if (offset < 2 || offset >= Wosize_val (ar)){
caml_invalid_argument ("Weak.set");
}
do_check_key_clean(ar,offset);
if (el != None_val && Is_block (el)){
- Assert (Wosize_val (el) == 1);
+ CAMLassert (Wosize_val (el) == 1);
do_set (ar, offset, Field (el, 0));
}else{
Field (ar, offset) = caml_ephe_none;
CAMLprim value caml_ephe_set_data (value ar, value el)
{
- Assert (Is_in_heap (ar));
+ CAMLassert (Is_in_heap (ar));
if (caml_gc_phase == Phase_clean){
/* During this phase since we don't know which ephemeron have been
cleaned we always need to check it. */
CAMLprim value caml_ephe_unset_data (value ar)
{
- Assert (Is_in_heap (ar));
+ CAMLassert (Is_in_heap (ar));
Field (ar, CAML_EPHE_DATA_OFFSET) = caml_ephe_none;
return Val_unit;
}
-
-#define Setup_for_gc
-#define Restore_after_gc
-
CAMLprim value caml_ephe_get_key (value ar, value n)
{
CAMLparam2 (ar, n);
mlsize_t offset = Long_val (n) + 2;
CAMLlocal2 (res, elt);
- Assert (Is_in_heap (ar));
+ CAMLassert (Is_in_heap (ar));
if (offset < 2 || offset >= Wosize_val (ar)){
caml_invalid_argument ("Weak.get_key");
}
CAMLparam1 (ar);
mlsize_t offset = 1;
CAMLlocal2 (res, elt);
- Assert (Is_in_heap (ar));
+ CAMLassert (Is_in_heap (ar));
elt = Field (ar, offset);
if(caml_gc_phase == Phase_clean) caml_ephe_clean(ar);
if (elt == caml_ephe_none){
CAMLreturn (res);
}
-#undef Setup_for_gc
-#undef Restore_after_gc
-
CAMLprim value caml_ephe_get_key_copy (value ar, value n)
{
CAMLparam2 (ar, n);
mlsize_t offset = Long_val (n) + 2;
CAMLlocal2 (res, elt);
value v; /* Caution: this is NOT a local root. */
- Assert (Is_in_heap (ar));
+ CAMLassert (Is_in_heap (ar));
if (offset < 1 || offset >= Wosize_val (ar)){
caml_invalid_argument ("Weak.get_copy");
}
mlsize_t offset = 1;
CAMLlocal2 (res, elt);
value v; /* Caution: this is NOT a local root. */
- Assert (Is_in_heap (ar));
+ CAMLassert (Is_in_heap (ar));
v = Field (ar, offset);
if (caml_gc_phase == Phase_clean) caml_ephe_clean(ar);
CAMLprim value caml_ephe_check_key (value ar, value n)
{
mlsize_t offset = Long_val (n) + 2;
- Assert (Is_in_heap (ar));
+ CAMLassert (Is_in_heap (ar));
if (offset < 2 || offset >= Wosize_val (ar)){
caml_invalid_argument ("Weak.check");
}
mlsize_t offset_d = Long_val (ofd) + 2;
mlsize_t length = Long_val (len);
long i;
- Assert (Is_in_heap (ars));
- Assert (Is_in_heap (ard));
+ CAMLassert (Is_in_heap (ars));
+ CAMLassert (Is_in_heap (ard));
if (offset_s < 1 || offset_s + length > Wosize_val (ars)){
caml_invalid_argument ("Weak.blit");
}
#define _UINTPTR_T_DEFINED
#endif
+unsigned short caml_win32_major = 0;
+unsigned short caml_win32_minor = 0;
+unsigned short caml_win32_build = 0;
+unsigned short caml_win32_revision = 0;
+
CAMLnoreturn_start
static void caml_win32_sys_error (int errnum)
CAMLnoreturn_end;
static void caml_win32_sys_error(int errnum)
{
- char buffer[512];
+ wchar_t buffer[512];
value msg;
if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
errnum,
0,
buffer,
- sizeof(buffer),
+ sizeof(buffer)/sizeof(wchar_t),
NULL)) {
- msg = caml_copy_string(buffer);
+ msg = caml_copy_string_of_utf16(buffer);
} else {
msg = caml_alloc_sprintf("unknown error #%d", errnum);
}
return retcode;
}
-char * caml_decompose_path(struct ext_table * tbl, char * path)
+wchar_t * caml_decompose_path(struct ext_table * tbl, wchar_t * path)
{
- char * p, * q;
+ wchar_t * p, * q;
int n;
if (path == NULL) return NULL;
- p = caml_strdup(path);
+ p = caml_stat_wcsdup(path);
q = p;
while (1) {
- for (n = 0; q[n] != 0 && q[n] != ';'; n++) /*nothing*/;
+ for (n = 0; q[n] != 0 && q[n] != L';'; n++) /*nothing*/;
caml_ext_table_add(tbl, q);
q = q + n;
if (*q == 0) break;
return p;
}
-char * caml_search_in_path(struct ext_table * path, char * name)
+wchar_t * caml_search_in_path(struct ext_table * path, const wchar_t * name)
{
- char * p, * dir, * fullname;
+ wchar_t * dir, * fullname;
+ char * u8;
+ const wchar_t * p;
int i;
- struct stat st;
+ struct _stati64 st;
for (p = name; *p != 0; p++) {
if (*p == '/' || *p == '\\') goto not_found;
dir = path->contents[i];
if (dir[0] == 0) continue;
/* not sure what empty path components mean under Windows */
- fullname = caml_strconcat(3, dir, "\\", name);
- caml_gc_message(0x100, "Searching %s\n", (uintnat) fullname);
- if (stat(fullname, &st) == 0 && S_ISREG(st.st_mode))
+ fullname = caml_stat_wcsconcat(3, dir, L"\\", name);
+ u8 = caml_stat_strdup_of_utf16(fullname);
+ caml_gc_message(0x100, "Searching %s\n", u8);
+ caml_stat_free(u8);
+ if (_wstati64(fullname, &st) == 0 && S_ISREG(st.st_mode))
return fullname;
caml_stat_free(fullname);
}
not_found:
- caml_gc_message(0x100, "%s not found in search path\n", (uintnat) name);
- return caml_strdup(name);
+ u8 = caml_stat_strdup_of_utf16(name);
+ caml_gc_message(0x100, "%s not found in search path\n", u8);
+ caml_stat_free(u8);
+ return caml_stat_wcsdup(name);
}
-CAMLexport char * caml_search_exe_in_path(char * name)
+CAMLexport wchar_t * caml_search_exe_in_path(const wchar_t * name)
{
- char * fullname, * filepart;
+ wchar_t * fullname, * filepart;
+ char * u8;
size_t fullnamelen;
DWORD retcode;
- fullnamelen = strlen(name) + 1;
+ fullnamelen = wcslen(name) + 1;
if (fullnamelen < 256) fullnamelen = 256;
while (1) {
- fullname = caml_stat_alloc(fullnamelen);
+ fullname = caml_stat_alloc(fullnamelen*sizeof(wchar_t));
retcode = SearchPath(NULL, /* use system search path */
name,
- ".exe", /* add .exe extension if needed */
+ L".exe", /* add .exe extension if needed */
fullnamelen,
fullname,
&filepart);
if (retcode == 0) {
- caml_gc_message(0x100, "%s not found in search path\n",
- (uintnat) name);
+ u8 = caml_stat_strdup_of_utf16(name);
+ caml_gc_message(0x100, "%s not found in search path\n", u8);
+ caml_stat_free(u8);
caml_stat_free(fullname);
- return caml_strdup(name);
+ return caml_stat_strdup_os(name);
}
if (retcode < fullnamelen)
return fullname;
}
}
-char * caml_search_dll_in_path(struct ext_table * path, char * name)
+wchar_t * caml_search_dll_in_path(struct ext_table * path, const wchar_t * name)
{
- char * dllname;
- char * res;
+ wchar_t * dllname;
+ wchar_t * res;
- dllname = caml_strconcat(2, name, ".dll");
+ dllname = caml_stat_wcsconcat(2, name, L".dll");
res = caml_search_in_path(path, dllname);
caml_stat_free(dllname);
return res;
#ifdef SUPPORT_DYNAMIC_LINKING
-void * caml_dlopen(char * libname, int for_execution, int global)
+void * caml_dlopen(wchar_t * libname, int for_execution, int global)
{
void *handle;
int flags = (global ? FLEXDLL_RTLD_GLOBAL : 0);
if (!for_execution) flags |= FLEXDLL_RTLD_NOEXEC;
- handle = flexdll_dlopen(libname, flags);
+ handle = flexdll_wdlopen(libname, flags);
if ((handle != NULL) && ((caml_verb_gc & 0x100) != 0)) {
flexdll_dump_exports(handle);
fflush(stdout);
flexdll_dlclose(handle);
}
-void * caml_dlsym(void * handle, char * name)
+void * caml_dlsym(void * handle, const char * name)
{
return flexdll_dlsym(handle, name);
}
-void * caml_globalsym(char * name)
+void * caml_globalsym(const char * name)
{
return flexdll_dlsym(flexdll_dlopen(NULL,0), name);
}
#else
-void * caml_dlopen(char * libname, int for_execution, int global)
+void * caml_dlopen(wchar_t * libname, int for_execution, int global)
{
return NULL;
}
{
}
-void * caml_dlsym(void * handle, char * name)
+void * caml_dlsym(void * handle, const char * name)
{
return NULL;
}
-void * caml_globalsym(char * name)
+void * caml_globalsym(const char * name)
{
return NULL;
}
/* Expansion of @responsefile and *? file patterns in the command line */
static int argc;
-static char ** argv;
+static wchar_t ** argv;
static int argvsize;
-static void store_argument(char * arg);
-static void expand_argument(char * arg);
-static void expand_pattern(char * arg);
+static void store_argument(wchar_t * arg);
+static void expand_argument(wchar_t * arg);
+static void expand_pattern(wchar_t * arg);
static void out_of_memory(void)
{
exit(2);
}
-static void store_argument(char * arg)
+static void store_argument(wchar_t * arg)
{
if (argc + 1 >= argvsize) {
argvsize *= 2;
- argv = (char **) realloc(argv, argvsize * sizeof(char *));
+ argv = (wchar_t **) caml_stat_resize_noexc(argv, argvsize * sizeof(wchar_t *));
if (argv == NULL) out_of_memory();
}
argv[argc++] = arg;
}
-static void expand_argument(char * arg)
+static void expand_argument(wchar_t * arg)
{
- char * p;
+ wchar_t * p;
for (p = arg; *p != 0; p++) {
- if (*p == '*' || *p == '?') {
+ if (*p == L'*' || *p == L'?') {
expand_pattern(arg);
return;
}
store_argument(arg);
}
-static void expand_pattern(char * pat)
+static void expand_pattern(wchar_t * pat)
{
- char * prefix, * p, * name;
+ wchar_t * prefix, * p, * name;
int handle;
- struct _finddata_t ffblk;
+ struct _wfinddata_t ffblk;
size_t i;
- handle = _findfirst(pat, &ffblk);
+ handle = _wfindfirst(pat, &ffblk);
if (handle == -1) {
store_argument(pat); /* a la Bourne shell */
return;
}
- prefix = caml_strdup(pat);
+ prefix = caml_stat_wcsdup(pat);
/* We need to stop at the first directory or drive boundary, because the
* _findata_t structure contains the filename, not the leading directory. */
- for (i = strlen(prefix); i > 0; i--) {
+ for (i = wcslen(prefix); i > 0; i--) {
char c = prefix[i - 1];
- if (c == '\\' || c == '/' || c == ':') { prefix[i] = 0; break; }
+ if (c == L'\\' || c == L'/' || c == L':') { prefix[i] = 0; break; }
}
/* No separator was found, it's a filename pattern without a leading directory. */
if (i == 0)
prefix[0] = 0;
do {
- name = caml_strconcat(2, prefix, ffblk.name);
+ name = caml_stat_wcsconcat(2, prefix, ffblk.name);
store_argument(name);
- } while (_findnext(handle, &ffblk) != -1);
+ } while (_wfindnext(handle, &ffblk) != -1);
_findclose(handle);
caml_stat_free(prefix);
}
-CAMLexport void caml_expand_command_line(int * argcp, char *** argvp)
+CAMLexport void caml_expand_command_line(int * argcp, wchar_t *** argvp)
{
int i;
argc = 0;
argvsize = 16;
- argv = (char **) malloc(argvsize * sizeof(char *));
+ argv = (wchar_t **) caml_stat_alloc_noexc(argvsize * sizeof(wchar_t *));
if (argv == NULL) out_of_memory();
for (i = 0; i < *argcp; i++) expand_argument((*argvp)[i]);
argv[argc] = NULL;
the directory named [dirname]. No entries are added for [.] and [..].
Return 0 on success, -1 on error; set errno in the case of error. */
-int caml_read_directory(char * dirname, struct ext_table * contents)
+int caml_read_directory(wchar_t * dirname, struct ext_table * contents)
{
size_t dirnamelen;
- char * template;
+ wchar_t * template;
#if _MSC_VER <= 1200
int h;
#else
intptr_t h;
#endif
- struct _finddata_t fileinfo;
+ struct _wfinddata_t fileinfo;
- dirnamelen = strlen(dirname);
+ dirnamelen = wcslen(dirname);
if (dirnamelen > 0 &&
- (dirname[dirnamelen - 1] == '/'
- || dirname[dirnamelen - 1] == '\\'
- || dirname[dirnamelen - 1] == ':'))
- template = caml_strconcat(2, dirname, "*.*");
+ (dirname[dirnamelen - 1] == L'/'
+ || dirname[dirnamelen - 1] == L'\\'
+ || dirname[dirnamelen - 1] == L':'))
+ template = caml_stat_wcsconcat(2, dirname, L"*.*");
else
- template = caml_strconcat(2, dirname, "\\*.*");
- h = _findfirst(template, &fileinfo);
+ template = caml_stat_wcsconcat(2, dirname, L"\\*.*");
+ h = _wfindfirst(template, &fileinfo);
if (h == -1) {
caml_stat_free(template);
return errno == ENOENT ? 0 : -1;
}
do {
- if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0) {
- caml_ext_table_add(contents, caml_strdup(fileinfo.name));
+ if (wcscmp(fileinfo.name, L".") != 0 && wcscmp(fileinfo.name, L"..") != 0) {
+ caml_ext_table_add(contents, caml_stat_strdup_of_utf16(fileinfo.name));
}
- } while (_findnext(h, &fileinfo) == 0);
+ } while (_wfindnext(h, &fileinfo) == 0);
_findclose(h);
caml_stat_free(template);
return 0;
void caml_signal_thread(void * lpParam)
{
- char *endptr;
+ wchar_t *endptr;
HANDLE h;
/* Get an hexa-code raw handle through the environment */
h = (HANDLE) (uintptr_t)
- strtol(caml_secure_getenv("CAMLSIGPIPE"), &endptr, 16);
+ wcstol(caml_secure_getenv(_T("CAMLSIGPIPE")), &endptr, 16);
while (1) {
DWORD numread;
BOOL ret;
#endif /* NATIVE_CODE */
-#if defined(NATIVE_CODE) && !defined(_WIN64)
+#if defined(NATIVE_CODE)
/* Handling of system stack overflow.
* Based on code provided by Olivier Andrieu.
* exception handler because at this point we are using the page that
* is to be protected.
*
- * A solution is to used an alternate stack when restoring the
+ * A solution is to use an alternate stack when restoring the
* protection. However it's not possible to use _resetstkoflw() then
* since it determines the stack pointer by calling alloca(): it would
* try to protect the alternate stack.
* caml_raise_exception which switches back to the normal stack, or
* call caml_fatal_uncaught_exception which terminates the program
* quickly.
- *
- * NB: The PAGE_GUARD protection is only available on WinNT, not
- * Win9x. There is an equivalent mechanism on Win9x with
- * PAGE_NOACCESS.
- *
- * Currently, does not work under Win64.
*/
-static uintnat win32_alt_stack[0x80];
+static uintnat win32_alt_stack[0x100];
static void caml_reset_stack (void *faulting_address)
{
- OSVERSIONINFO osi;
SYSTEM_INFO si;
DWORD page_size;
MEMORY_BASIC_INFORMATION mbi;
DWORD oldprot;
- /* get the os version (Win9x or WinNT ?) */
- osi.dwOSVersionInfoSize = sizeof osi;
- if (! GetVersionEx (&osi))
- goto failed;
-
/* get the system's page size. */
GetSystemInfo (&si);
page_size = si.dwPageSize;
if (! VirtualQuery (faulting_address, &mbi, sizeof mbi))
goto failed;
- /* restore the PAGE_GUARD protection on this page */
- switch (osi.dwPlatformId) {
- case VER_PLATFORM_WIN32_NT:
- VirtualProtect (mbi.BaseAddress, page_size,
- mbi.Protect | PAGE_GUARD, &oldprot);
- break;
- case VER_PLATFORM_WIN32_WINDOWS:
- VirtualProtect (mbi.BaseAddress, page_size,
- PAGE_NOACCESS, &oldprot);
- break;
- }
+ VirtualProtect (mbi.BaseAddress, page_size,
+ mbi.Protect | PAGE_GUARD, &oldprot);
failed:
caml_raise_stack_overflow();
}
-CAMLextern int caml_is_in_code(void *);
+#ifndef _WIN64
static LONG CALLBACK
- caml_UnhandledExceptionFilter (EXCEPTION_POINTERS* exn_info)
+ caml_stack_overflow_VEH (EXCEPTION_POINTERS* exn_info)
{
DWORD code = exn_info->ExceptionRecord->ExceptionCode;
CONTEXT *ctx = exn_info->ContextRecord;
return EXCEPTION_CONTINUE_SEARCH;
}
-void caml_win32_overflow_detection()
+#else
+extern char *caml_exception_pointer;
+extern value *caml_young_ptr;
+
+/* Do not use the macro from address_class.h here. */
+#undef Is_in_code_area
+#define Is_in_code_area(pc) \
+ ( ((char *)(pc) >= caml_code_area_start && \
+ (char *)(pc) <= caml_code_area_end) \
+|| ((char *)(pc) >= &caml_system__code_begin && \
+ (char *)(pc) <= &caml_system__code_end) \
+|| (Classify_addr(pc) & In_code_area) )
+extern char caml_system__code_begin, caml_system__code_end;
+
+
+static LONG CALLBACK
+ caml_stack_overflow_VEH (EXCEPTION_POINTERS* exn_info)
+{
+ DWORD code = exn_info->ExceptionRecord->ExceptionCode;
+ CONTEXT *ctx = exn_info->ContextRecord;
+
+ if (code == EXCEPTION_STACK_OVERFLOW && Is_in_code_area (ctx->Rip))
+ {
+ uintnat faulting_address;
+ uintnat * alt_rsp;
+
+ /* grab the address that caused the fault */
+ faulting_address = exn_info->ExceptionRecord->ExceptionInformation[1];
+
+ /* refresh runtime parameters from registers */
+ caml_exception_pointer = (char *) ctx->R14;
+ caml_young_ptr = (value *) ctx->R15;
+
+ /* call caml_reset_stack(faulting_address) using the alternate stack */
+ alt_rsp = win32_alt_stack + sizeof(win32_alt_stack) / sizeof(uintnat);
+ ctx->Rcx = faulting_address;
+ ctx->Rsp = (uintnat) (alt_rsp - 4 - 1);
+ ctx->Rip = (uintnat) &caml_reset_stack;
+
+ return EXCEPTION_CONTINUE_EXECUTION;
+ }
+
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+#endif /* _WIN64 */
+
+void caml_win32_overflow_detection(void)
{
- SetUnhandledExceptionFilter (caml_UnhandledExceptionFilter);
+ AddVectoredExceptionHandler(1, caml_stack_overflow_VEH);
}
-#endif
+#endif /* NATIVE_CODE */
/* Seeding of pseudo-random number generators */
/* Recover executable name */
-char * caml_executable_name(void)
+wchar_t * caml_executable_name(void)
{
- char * name;
+ wchar_t * name;
DWORD namelen, ret;
-
+
namelen = 256;
while (1) {
- name = caml_stat_alloc(namelen);
+ name = caml_stat_alloc(namelen*sizeof(wchar_t));
ret = GetModuleFileName(NULL, name, namelen);
if (ret == 0) { caml_stat_free(name); return NULL; }
if (ret < namelen) break;
}
#endif
-char *caml_secure_getenv (char const *var)
+wchar_t *caml_secure_getenv (wchar_t const *var)
{
/* Win32 doesn't have a notion of setuid bit, so getenv is safe. */
return CAML_SYS_GETENV (var);
}
+
+/* The rename() implementation in MSVC's CRT is based on MoveFile()
+ and therefore fails if the new name exists. This is inconsistent
+ with POSIX and a problem in practice. Here we reimplement
+ rename() using MoveFileEx() to make it more POSIX-like.
+ There are no official guarantee that the rename operation is atomic,
+ but it is widely believed to be atomic on NTFS. */
+
+int caml_win32_rename(const wchar_t * oldpath, const wchar_t * newpath)
+{
+ /* MOVEFILE_REPLACE_EXISTING: to be closer to POSIX
+ MOVEFILE_COPY_ALLOWED: MoveFile performs a copy if old and new
+ paths are on different devices, so we do the same here for
+ compatibility with the old rename()-based implementation.
+ MOVEFILE_WRITE_THROUGH: not sure it's useful; affects only
+ the case where a copy is done. */
+ if (MoveFileEx(oldpath, newpath,
+ MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH |
+ MOVEFILE_COPY_ALLOWED)) {
+ return 0;
+ }
+ /* Modest attempt at mapping Win32 error codes to POSIX error codes.
+ The __dosmaperr() function from the CRT does a better job but is
+ generally not accessible. */
+ switch (GetLastError()) {
+ case ERROR_FILE_NOT_FOUND: case ERROR_PATH_NOT_FOUND:
+ errno = ENOENT; break;
+ case ERROR_ACCESS_DENIED: case ERROR_WRITE_PROTECT: case ERROR_CANNOT_MAKE:
+ errno = EACCES; break;
+ case ERROR_CURRENT_DIRECTORY: case ERROR_BUSY:
+ errno = EBUSY; break;
+ case ERROR_NOT_SAME_DEVICE:
+ errno = EXDEV; break;
+ case ERROR_ALREADY_EXISTS:
+ errno = EEXIST; break;
+ default:
+ errno = EINVAL;
+ }
+ return -1;
+}
+
+/* Windows Unicode support */
+static uintnat windows_unicode_enabled = WINDOWS_UNICODE;
+
+/* If [windows_unicode_strict] is non-zero, then illegal UTF-8 characters (on
+ the OCaml side) or illegal UTF-16 characters (on the Windows side) cause an
+ error to be signaled. What happens then depends on the variable
+ [windows_unicode_fallback].
+
+ If [windows_unicode_strict] is zero, then illegal characters are silently
+ dropped. */
+static uintnat windows_unicode_strict = 1;
+
+/* If [windows_unicode_fallback] is non-zero, then if an error is signaled when
+ translating to UTF-16, the translation is re-done under the assumption that
+ the argument string is encoded in the local codepage. */
+static uintnat windows_unicode_fallback = 1;
+
+CAMLexport int win_multi_byte_to_wide_char(const char *s, int slen, wchar_t *out, int outlen)
+{
+ int retcode;
+
+ CAMLassert (s != NULL);
+
+ if (slen == 0)
+ return 0;
+
+ if (windows_unicode_enabled != 0) {
+ retcode = MultiByteToWideChar(CP_UTF8, windows_unicode_strict ? MB_ERR_INVALID_CHARS : 0, s, slen, out, outlen);
+ if (retcode == 0 && windows_unicode_fallback != 0)
+ retcode = MultiByteToWideChar(CP_THREAD_ACP, 0, s, slen, out, outlen);
+ } else {
+ retcode = MultiByteToWideChar(CP_THREAD_ACP, 0, s, slen, out, outlen);
+ }
+
+ if (retcode == 0)
+ caml_win32_sys_error(GetLastError());
+
+ return retcode;
+}
+
+#ifndef WC_ERR_INVALID_CHARS /* For old versions of Windows we simply ignore the flag */
+#define WC_ERR_INVALID_CHARS 0
+#endif
+
+CAMLexport int win_wide_char_to_multi_byte(const wchar_t *s, int slen, char *out, int outlen)
+{
+ int retcode;
+
+ CAMLassert(s != NULL);
+
+ if (slen == 0)
+ return 0;
+
+ if (windows_unicode_enabled != 0)
+ retcode = WideCharToMultiByte(CP_UTF8, windows_unicode_strict ? WC_ERR_INVALID_CHARS : 0, s, slen, out, outlen, NULL, NULL);
+ else
+ retcode = WideCharToMultiByte(CP_THREAD_ACP, 0, s, slen, out, outlen, NULL, NULL);
+
+ if (retcode == 0)
+ caml_win32_sys_error(GetLastError());
+
+ return retcode;
+}
+
+CAMLexport value caml_copy_string_of_utf16(const wchar_t *s)
+{
+ int retcode, slen;
+ value v;
+
+ slen = wcslen(s);
+ retcode = win_wide_char_to_multi_byte(s, slen, NULL, 0); /* Do not include final NULL */
+ v = caml_alloc_string(retcode);
+ win_wide_char_to_multi_byte(s, slen, String_val(v), retcode);
+
+ return v;
+}
+
+CAMLexport inline wchar_t* caml_stat_strdup_to_utf16(const char *s)
+{
+ wchar_t * ws;
+ int retcode;
+
+ retcode = win_multi_byte_to_wide_char(s, -1, NULL, 0);
+ ws = malloc(retcode * sizeof(*ws));
+ win_multi_byte_to_wide_char(s, -1, ws, retcode);
+
+ return ws;
+}
+
+CAMLexport caml_stat_string caml_stat_strdup_of_utf16(const wchar_t *s)
+{
+ caml_stat_string out;
+ int retcode;
+
+ retcode = win_wide_char_to_multi_byte(s, -1, NULL, 0);
+ out = caml_stat_alloc(retcode);
+ win_wide_char_to_multi_byte(s, -1, out, retcode);
+
+ return out;
+}
+
+void caml_probe_win32_version(void)
+{
+ /* Determine the version of Windows we're running, and cache it */
+ WCHAR fileName[MAX_PATH];
+ DWORD size =
+ GetModuleFileName(GetModuleHandle(L"kernel32"), fileName, MAX_PATH);
+ DWORD dwHandle = 0;
+ BYTE* versionInfo;
+ fileName[size] = 0;
+ size = GetFileVersionInfoSize(fileName, &dwHandle);
+ versionInfo = (BYTE*)malloc(size * sizeof(BYTE));
+ if (GetFileVersionInfo(fileName, 0, size, versionInfo)) {
+ UINT len = 0;
+ VS_FIXEDFILEINFO* vsfi = NULL;
+ VerQueryValue(versionInfo, L"\\", (void**)&vsfi, &len);
+ caml_win32_major = HIWORD(vsfi->dwProductVersionMS);
+ caml_win32_minor = LOWORD(vsfi->dwProductVersionMS);
+ caml_win32_build = HIWORD(vsfi->dwProductVersionLS);
+ caml_win32_revision = LOWORD(vsfi->dwProductVersionLS);
+ }
+ free(versionInfo);
+}
+
+static UINT startup_codepage = 0;
+
+void caml_setup_win32_terminal(void)
+{
+ if (caml_win32_major >= 10) {
+ startup_codepage = GetConsoleOutputCP();
+ if (startup_codepage != CP_UTF8)
+ SetConsoleOutputCP(CP_UTF8);
+ }
+}
+
+void caml_restore_win32_terminal(void)
+{
+ if (startup_codepage != 0)
+ SetConsoleOutputCP(startup_codepage);
+}
### Which C compiler to use for the bytecode interpreter.
### Performance of the bytecode interpreter is *much* improved
### if Gnu CC version 2 is used.
-#BYTECC=gcc
-#BYTECC=cc
+#CC=gcc
+#BYTECFLAGS=
### Additional compile-time options for $(BYTECC).
# If using gcc on Intel x86:
### Additional link-time options for $(BYTECC)
# To support dynamic loading of shared libraries (they need to look at
# our own symbols):
-#BYTECCLINKOPTS=-Wl,-E
+#LDFLAGS=-Wl,-E
# Otherwise:
-#BYTECCLINKOPTS=
+#LDFLAGS=
### Libraries needed
# On most platforms:
#MKSHAREDLIB=gcc -shared -o
# Compile-time option to $(BYTECC) to add a directory to be searched
# at run-time for shared libraries
-#BYTECCRPATH=-Wl,-rpath
+#RPATH=-Wl,-rpath
############# Configuration for the native-code compiler
### Currently supported:
###
### i386 Intel Pentium PCs under Linux, *BSD*, NextStep
-### sparc Sun Sparcstation under SunOS 4.1 or Solaris 2
### power Macintosh under Mac OS X and Linux
### arm ARM under Linux
###
### Set ARCH=none if your machine is not supported
#ARCH=i386
-#ARCH=sparc
#ARCH=power
#ARCH=arm
#ARCH=none
#SYSTEM=bsd
#SYSTEM=unknown
-### Which C compiler to use for the native-code compiler.
-#NATIVECC=cc
-#NATIVECC=gcc
+#NATIVECFLAGS=
-### Additional compile-time options for $(NATIVECC).
# For gcc if cautious:
#NATIVECCCOMPOPTS=-Wall
-### Additional link-time options for $(NATIVECC)
-#NATIVECCLINKOPTS=
-
# Compile-time option to $(NATIVECC) to add a directory to be searched
# at run-time for shared libraries
-#NATIVECCRPATH=-Wl,-rpath
+#RPATH=-Wl,-rpath
### Command and flags to use for assembling ocamlopt-generated code
#ASM=as
#ASPPPROFFLAGS=-DPROFILING
### Whether profiling with gprof is supported
-# If yes: (e.g. x86/Linux, Sparc/Solaris):
+# If yes: (e.g. x86/Linux):
#PROFILING=true
# If no:
#PROFILING=false
OTHERLIBRARIES=unix str num threads graph dynlink bigarray
-### Name of the target architecture for the "num" library
-# Known targets:
-# generic (portable C, works everywhere)
-# ia32 (Intel x86)
-# amd64 (AMD Opteron, Athlon64)
-# ppc (Power PC)
-# sparc
-# If you don't know, leave BNG_ARCH=generic, which selects a portable
-# C implementation of these routines.
-BNG_ARCH=generic
-BNG_ASM_LEVEL=1
-
### Link-time options to ocamlc or ocamlopt for linking with POSIX threads
# Needed for the "systhreads" package
# Usually:
S=s
SO=s.o
EXE=.exe
+EMPTY=
+OUTPUTEXE=-o $(EMPTY)
EXT_DLL=.dll
EXT_OBJ=.$(O)
+OUTPUTOBJ=-o $(EMPTY)
EXT_LIB=.$(A)
EXT_ASM=.$(S)
-MANEXT=1
+PROGRAMS_MAN_SECTION=1
+LIBRARIES_MAN_SECTION=3
HASHBANGSCRIPTS=false
PTHREAD_LINK=
PTHREAD_CAML_LINK=
X11_INCLUDES=
X11_LINK=
-BYTECCRPATH=
+RPATH=
SUPPORTS_SHARED_LIBRARIES=true
SHAREDCCCOMPOPTS=
MKSHAREDLIBRPATH=
NATIVECCPROFOPTS=
-NATIVECCRPATH=
ASM=$(TOOLPREF)as
ASPP=$(TOOLPREF)gcc -c
ASPPPROFFLAGS=
GRAPHLIB=win32graph
FLAMBDA=false
WITH_SPACETIME=false
+ENABLE_CALL_COUNTS=false
WITH_PROFINFO=false
LIBUNWIND_AVAILABLE=false
LIBUNWIND_LINK_FLAGS=
-PROFINFO_WIDTH=26
-SAFE_STRING=false
+PROFINFO_WIDTH=0
+FORCE_SAFE_STRING=false
+DEFAULT_SAFE_STRING=true
+WINDOWS_UNICODE=1
AFL_INSTRUMENT=false
########## Configuration for the bytecode compiler
### Which C compiler to use for the bytecode interpreter.
-BYTECC=$(TOOLPREF)gcc -O -mms-bitfields
-BYTECODE_C_COMPILER=$(BYTECC)
-
-### Additional compile-time options for $(BYTECC). (For static linking.)
+CC=$(TOOLPREF)gcc
+CFLAGS=-O -mms-bitfields -Wall -Wno-unused -fno-tree-vrp
# -fno-tree-vrp is here to try to work around the Skylake/Kaby lake bug,
# and only works on GCC 4.2 and later.
-BYTECCCOMPOPTS=-DCAML_NAME_SPACE -Wall -Wno-unused -fno-tree-vrp
+CPPFLAGS=-DCAML_NAME_SPACE -DUNICODE -D_UNICODE -DWINDOWS_UNICODE=$(WINDOWS_UNICODE)
+OCAMLC_CFLAGS=-O -mms-bitfields
-### Additional compile-time options for $(BYTECC). (For debug version.)
BYTECCDBGCOMPOPTS=-g
-### Flag to use to rename object files. (for debug version.)
-NAME_OBJ_FLAG=-o
-
-### Additional link-time options for $(BYTECC). (For static linking.)
-BYTECCLINKOPTS=
+LDFLAGS=-municode
### Libraries needed
-BYTECCLIBS=-lws2_32
-NATIVECCLIBS=-lws2_32
+BYTECCLIBS=-lws2_32 -lversion
+NATIVECCLIBS=-lws2_32 -lversion
### How to invoke the C preprocessor
-CPP=$(BYTECC) -E
+CPP=cpp
### Flexlink
FLEXLINK_CMD=flexlink
# $(FLEXLINK_CMD) $(FLEXLINK_FLAGS) [-exe|-maindll]
# or OCAML_FLEXLINK overriding will not work (see utils/config.mlp)
MKDLL=$(FLEXLINK)
-MKEXE=$(FLEXLINK) -exe
+MKEXE=$(MKEXE_ANSI) $(if $(LDFLAGS),-link "$(LDFLAGS)")
MKEXEDEBUGFLAG=-g
MKMAINDLL=$(FLEXLINK) -maindll
### Native command to build ocamlrun.exe without flexlink
-MKEXE_BOOT=$(BYTECC) -o $(1) $(2)
+MKEXE_BOOT=$(CC) $(CFLAGS) $(LDFLAGS) $(OUTPUTEXE)$(1) $(2)
+
+### Native command to build an ANSI executable
+MKEXE_ANSI=$(FLEXLINK) -exe
### How to build a static library
MKLIB=rm -f $(1); $(TOOLPREF)ar rc $(1) $(2); $(RANLIB) $(1)
### Name of operating system family for the native-code compiler.
SYSTEM=mingw
-### Which C compiler to use for the native-code compiler.
-NATIVECC=$(BYTECC)
-NATIVE_C_COMPILER=$(NATIVECC)
-
-### Additional compile-time options for $(NATIVECC).
-# -fno-tree-vrp is here to try to work around the Skylake/Kaby lake bug,
-# and only works on GCC 4.2 and later.
-NATIVECCCOMPOPTS=-DCAML_NAME_SPACE -Wall -Wno-unused -fno-tree-vrp
-
-### Additional link-time options for $(NATIVECC)
-NATIVECCLINKOPTS=
+OCAMLOPT_CFLAGS=-O -mms-bitfields
### Build partially-linked object file
-PACKLD=$(TOOLPREF)ld -r $(NATIVECCLINKOPTS) -o # must have a space after '-o'
+PACKLD=$(TOOLPREF)ld -r -o # must have a space after '-o'
############# Configuration for the contributed libraries
-OTHERLIBRARIES=win32unix str num win32graph dynlink bigarray systhreads
-
-### Name of the target architecture for the "num" library
-BNG_ARCH=ia32
-BNG_ASM_LEVEL=1
+OTHERLIBRARIES=win32unix str win32graph dynlink bigarray systhreads
############# for the testsuite makefiles
#ml let topdir = "" and wintopdir = "";;
DIFF=/usr/bin/diff -q --strip-trailing-cr
SET_LD_PATH=PATH="$(PATH):$(LD_PATH)"
MAX_TESTSUITE_DIR_RETRIES=1
+FLAT_FLOAT_ARRAY=true
S=s
SO=s.o
EXE=.exe
+EMPTY=
+OUTPUTEXE=-o $(EMPTY)
EXT_DLL=.dll
EXT_OBJ=.$(O)
+OUTPUTOBJ=-o $(EMPTY)
EXT_LIB=.$(A)
EXT_ASM=.$(S)
-MANEXT=1
+PROGRAMS_MAN_SECTION=1
+LIBRARIES_MAN_SECTION=3
HASHBANGSCRIPTS=false
PTHREAD_LINK=
PTHREAD_CAML_LINK=
X11_INCLUDES=
X11_LINK=
-BYTECCRPATH=
+RPATH=
SUPPORTS_SHARED_LIBRARIES=true
SHAREDCCCOMPOPTS=
MKSHAREDLIBRPATH=
NATIVECCPROFOPTS=
-NATIVECCRPATH=
ASM=$(TOOLPREF)as
ASPP=$(TOOLPREF)gcc -c
ASPPPROFFLAGS=
FLAMBDA=false
WITH_PROFINFO=false
WITH_SPACETIME=false
+ENABLE_CALL_COUNTS=false
LIBUNWIND_AVAILABLE=false
LIBUNWIND_LINK_FLAGS=
-PROFINFO_WIDTH=26
-SAFE_STRING=false
+PROFINFO_WIDTH=0
+FORCE_SAFE_STRING=false
+DEFAULT_SAFE_STRING=true
+WINDOWS_UNICODE=1
AFL_INSTRUMENT=false
########## Configuration for the bytecode compiler
### Which C compiler to use for the bytecode interpreter.
-BYTECC=$(TOOLPREF)gcc -O -mms-bitfields
-BYTECODE_C_COMPILER=$(BYTECC)
-
-### Additional compile-time options for $(BYTECC). (For static linking.)
+CC=$(TOOLPREF)gcc
+CFLAGS=-O -mms-bitfields -Wall -Wno-unused -fno-tree-vrp
# -fno-tree-vrp is here to try to work around the Skylake/Kaby lake bug,
# and only works on GCC 4.2 and later.
-BYTECCCOMPOPTS=-DCAML_NAME_SPACE -Wall -Wno-unused -fno-tree-vrp
+CPPFLAGS=-DCAML_NAME_SPACE -DUNICODE -D_UNICODE -DWINDOWS_UNICODE=$(WINDOWS_UNICODE)
+OCAMLC_CFLAGS=-O -mms-bitfields
-### Additional compile-time options for $(BYTECC). (For debug version.)
BYTECCDBGCOMPOPTS=-g
-### Flag to use to rename object files. (for debug version.)
-NAME_OBJ_FLAG=-o
-
-### Additional link-time options for $(BYTECC). (For static linking.)
-BYTECCLINKOPTS=
+LDFLAGS=-municode
### Libraries needed
-BYTECCLIBS=-lws2_32
-NATIVECCLIBS=-lws2_32
+BYTECCLIBS=-lws2_32 -lversion
+NATIVECCLIBS=-lws2_32 -lversion
### How to invoke the C preprocessor
-CPP=$(BYTECC) -E
+CPP=cpp
### Flexlink
FLEXLINK_CMD=flexlink
# $(FLEXLINK_CMD) $(FLEXLINK_FLAGS) [-exe|-maindll]
# or OCAML_FLEXLINK overriding will not work (see utils/config.mlp)
MKDLL=$(FLEXLINK)
-MKEXE=$(FLEXLINK) -exe
+MKEXE=$(MKEXE_ANSI) $(if $(LDFLAGS),-link "$(LDFLAGS)")
MKEXEDEBUGFLAG=-g
MKMAINDLL=$(FLEXLINK) -maindll
### Native command to build ocamlrun.exe without flexlink
-MKEXE_BOOT=$(BYTECC) -o $(1) $(2)
+MKEXE_BOOT=$(CC) $(CFLAGS) $(LDFLAGS) $(OUTPUTEXE)$(1) $(2)
+
+### Native command to build an ANSI executable
+MKEXE_ANSI=$(FLEXLINK) -exe
### How to build a static library
MKLIB=rm -f $(1); $(TOOLPREF)ar rc $(1) $(2); $(RANLIB) $(1)
### Name of operating system family for the native-code compiler.
SYSTEM=mingw64
-### Which C compiler to use for the native-code compiler.
-NATIVECC=$(BYTECC)
-NATIVE_C_COMPILER=$(NATIVECC)
-
-### Additional compile-time options for $(NATIVECC).
-# -fno-tree-vrp is here to try to work around the Skylake/Kaby lake bug,
-# and only works on GCC 4.2 and later.
-NATIVECCCOMPOPTS=-DCAML_NAME_SPACE -Wall -Wno-unused -fno-tree-vrp
-
-### Additional link-time options for $(NATIVECC)
-NATIVECCLINKOPTS=
+OCAMLOPT_CFLAGS=-O -mms-bitfields
### Build partially-linked object file
-PACKLD=$(TOOLPREF)ld -r $(NATIVECCLINKOPTS) -o # must have a space after '-o'
+PACKLD=$(TOOLPREF)ld -r -o # must have a space after '-o'
############# Configuration for the contributed libraries
-OTHERLIBRARIES=win32unix str num win32graph dynlink bigarray systhreads
-
-### Name of the target architecture for the "num" library
-BNG_ARCH=amd64
-BNG_ASM_LEVEL=1
+OTHERLIBRARIES=win32unix str win32graph dynlink bigarray systhreads
############# for the testsuite makefiles
#ml let topdir = "" and wintopdir = "";;
DIFF=/usr/bin/diff -q --strip-trailing-cr
SET_LD_PATH=PATH="$(PATH):$(LD_PATH)"
MAX_TESTSUITE_DIR_RETRIES=1
+FLAT_FLOAT_ARRAY=true
S=asm
SO=s.obj
EXE=.exe
+OUTPUTEXE=-Fe
EXT_DLL=.dll
EXT_OBJ=.$(O)
+OUTPUTOBJ=-Fo
EXT_LIB=.$(A)
EXT_ASM=.$(S)
-MANEXT=1
+PROGRAMS_MAN_SECTION=1
+LIBRARIES_MAN_SECTION=3
HASHBANGSCRIPTS=false
PTHREAD_LINK=
PTHREAD_CAML_LINK=
X11_INCLUDES=
X11_LINK=
-BYTECCRPATH=
+RPATH=
SUPPORTS_SHARED_LIBRARIES=true
SHAREDCCCOMPOPTS=
NATIVECCPROFOPTS=
-NATIVECCRPATH=
ASM=ml -nologo -coff -Cp -c -Fo
ASPP=
ASPPPROFFLAGS=
FLAMBDA=false
WITH_PROFINFO=false
WITH_SPACETIME=false
+ENABLE_CALL_COUNTS=false
LIBUNWIND_AVAILABLE=false
LIBUNWIND_LINK_FLAGS=
-PROFINFO_WIDTH=26
-SAFE_STRING=false
+PROFINFO_WIDTH=0
+FORCE_SAFE_STRING=false
+DEFAULT_SAFE_STRING=true
+WINDOWS_UNICODE=1
AFL_INSTRUMENT=false
########## Configuration for the bytecode compiler
### Which C compiler to use for the bytecode interpreter.
-BYTECC=cl -nologo -D_CRT_SECURE_NO_DEPRECATE -O2 -Gy- -MD
-BYTECODE_C_COMPILER=$(BYTECC)
-
-### Additional compile-time options for $(BYTECC). (For static linking.)
-BYTECCCOMPOPTS=-DCAML_NAME_SPACE
-
-### Additional compile-time options for $(BYTECC). (For debug version.)
+CC=cl
+CFLAGS=-nologo -O2 -Gy- -MD
+CPPFLAGS=-D_CRT_SECURE_NO_DEPRECATE -DCAML_NAME_SPACE -DUNICODE -D_UNICODE -DWINDOWS_UNICODE=$(WINDOWS_UNICODE)
+OCAMLC_CFLAGS=-nologo -O2 -Gy- -MD
+OCAMLC_CPPFLAGS=-D_CRT_SECURE_NO_DEPRECATE
BYTECCDBGCOMPOPTS=-Zi
-### Flag to use to rename object files. (for debug version.)
-NAME_OBJ_FLAG=-Fo
-
-### Additional link-time options for $(BYTECC). (For static linking.)
-BYTECCLINKOPTS=
+LDFLAGS=/ENTRY:wmainCRTStartup
### Libraries needed
-BYTECCLIBS=advapi32.lib ws2_32.lib
-NATIVECCLIBS=advapi32.lib ws2_32.lib
+BYTECCLIBS=advapi32.lib ws2_32.lib version.lib
+NATIVECCLIBS=advapi32.lib ws2_32.lib version.lib
### How to invoke the C preprocessor
CPP=cl -nologo -EP
# $(FLEXLINK_CMD) $(FLEXLINK_FLAGS) [-exe|-maindll]
# or OCAML_FLEXLINK overriding will not work (see utils/config.mlp)
MKDLL=$(FLEXLINK)
-MKEXE=$(FLEXLINK) -exe
+MKEXE=$(MKEXE_ANSI) $(if $(LDFLAGS),-link "$(LDFLAGS)")
MKEXEDEBUGFLAG=
MKMAINDLL=$(FLEXLINK) -maindll
MERGEMANIFESTEXE=test ! -f $(1).manifest \
|| mt -nologo -outputresource:$(1) -manifest $(1).manifest \
&& rm -f $(1).manifest
-MKEXE_BOOT=$(BYTECC) /Fe$(1) $(2) /link /subsystem:console \
+MKEXE_BOOT=$(CC) $(CFLAGS) $(OUTPUTEXE)$(1) $(2) /link /subsystem:console $(LDFLAGS) \
&& ($(MERGEMANIFESTEXE))
+### Native command to build an ANSI executable
+MKEXE_ANSI=$(FLEXLINK) -exe
+
### How to build a static library
MKLIB=link -lib -nologo -out:$(1) $(2)
#ml let mklib out files opts =
### Name of operating system family for the native-code compiler.
SYSTEM=win32
-### Which C compiler to use for the native-code compiler.
-NATIVECC=cl -nologo -D_CRT_SECURE_NO_DEPRECATE -O2 -Gy- -MD
-NATIVE_C_COMPILER=$(NATIVECC)
-### Additional compile-time options for $(NATIVECC).
-NATIVECCCOMPOPTS=-DCAML_NAME_SPACE
-
-### Additional link-time options for $(NATIVECC)
-NATIVECCLINKOPTS=
+OCAMLOPT_CFLAGS=-nologo -O2 -Gy- -MD
+OCAMLOPT_CPPFLAGS=-D_CRT_SECURE_NO_DEPRECATE
### Build partially-linked object file
PACKLD=link -lib -nologo -out:# there must be no space after this '-out:'
############# Configuration for the contributed libraries
-OTHERLIBRARIES=win32unix systhreads str num win32graph dynlink bigarray
-
-### Name of the target architecture for the "num" library
-BNG_ARCH=generic
-BNG_ASM_LEVEL=0
+OTHERLIBRARIES=win32unix systhreads str win32graph dynlink bigarray
############# for the testsuite makefiles
#ml let topdir = "" and wintopdir = "";;
SORT=/usr/bin/sort
SET_LD_PATH=PATH="$(PATH):$(LD_PATH)"
MAX_TESTSUITE_DIR_RETRIES=1
+FLAT_FLOAT_ARRAY=true
S=asm
SO=s.obj
EXE=.exe
+OUTPUTEXE=-Fe
EXT_DLL=.dll
EXT_OBJ=.$(O)
+OUTPUTOBJ=-Fo
EXT_LIB=.$(A)
EXT_ASM=.$(S)
-MANEXT=1
+PROGRAMS_MAN_SECTION=1
+LIBRARIES_MAN_SECTION=3
HASHBANGSCRIPTS=false
PTHREAD_LINK=
PTHREAD_CAML_LINK=
X11_INCLUDES=
X11_LINK=
-BYTECCRPATH=
+RPATH=
SUPPORTS_SHARED_LIBRARIES=true
SHAREDCCCOMPOPTS=
NATIVECCPROFOPTS=
-NATIVECCRPATH=
ASM=ml64 -nologo -Cp -c -Fo
ASPP=
ASPPPROFFLAGS=
FLAMBDA=false
WITH_PROFINFO=false
WITH_SPACETIME=false
+ENABLE_CALL_COUNTS=false
LIBUNWIND_AVAILABLE=false
LIBUNWIND_LINK_FLAGS=
-PROFINFO_WIDTH=26
-SAFE_STRING=false
+PROFINFO_WIDTH=0
+FORCE_SAFE_STRING=false
+DEFAULT_SAFE_STRING=true
+WINDOWS_UNICODE=1
AFL_INSTRUMENT=false
########## Configuration for the bytecode compiler
### Which C compiler to use for the bytecode interpreter.
-BYTECC=cl -nologo -D_CRT_SECURE_NO_DEPRECATE -O2 -Gy- -MD
-BYTECODE_C_COMPILER=$(BYTECC)
+CC=cl
+CFLAGS=-nologo -O2 -Gy- -MD
+CPPFLAGS=-D_CRT_SECURE_NO_DEPRECATE -DCAML_NAME_SPACE -DUNICODE -D_UNICODE -DWINDOWS_UNICODE=$(WINDOWS_UNICODE)
+OCAMLC_CFLAGS=-nologo -O2 -Gy- -MD
+OCAMLC_CPPFLAGS=-D_CRT_SECURE_NO_DEPRECATE
-### Additional compile-time options for $(BYTECC). (For static linking.)
-BYTECCCOMPOPTS=-DCAML_NAME_SPACE
-
-### Additional compile-time options for $(BYTECC). (For debug version.)
BYTECCDBGCOMPOPTS=-Zi
-### Flag to use to rename object files. (for debug version.)
-NAME_OBJ_FLAG=-Fo
-
-### Additional link-time options for $(BYTECC). (For static linking.)
-BYTECCLINKOPTS=
+LDFLAGS=/ENTRY:wmainCRTStartup
### Libraries needed
#EXTRALIBS=bufferoverflowu.lib # for the old PSDK compiler only
EXTRALIBS=
-BYTECCLIBS=advapi32.lib ws2_32.lib $(EXTRALIBS)
-NATIVECCLIBS=advapi32.lib ws2_32.lib $(EXTRALIBS)
+BYTECCLIBS=advapi32.lib ws2_32.lib version.lib
+NATIVECCLIBS=advapi32.lib ws2_32.lib version.lib
### How to invoke the C preprocessor
-CPP=cl -nologo -EP
+CPP=$(CC) -nologo -EP
### Flexlink
FLEXLINK_CMD=flexlink
# $(FLEXLINK_CMD) $(FLEXLINK_FLAGS) [-exe|-maindll]
# or OCAML_FLEXLINK overriding will not work (see utils/config.mlp)
MKDLL=$(FLEXLINK)
-MKEXE=$(FLEXLINK) -exe
+MKEXE=$(MKEXE_ANSI) $(if $(LDFLAGS),-link "$(LDFLAGS)")
MKEXEDEBUGFLAG=
MKMAINDLL=$(FLEXLINK) -maindll
MERGEMANIFESTEXE=test ! -f $(1).manifest \
|| mt -nologo -outputresource:$(1) -manifest $(1).manifest \
&& rm -f $(1).manifest
-MKEXE_BOOT=$(BYTECC) /Fe$(1) $(2) /link /subsystem:console \
+MKEXE_BOOT=$(CC) $(CFLAGS) $(OUTPUTEXE)$(1) $(2) /link /subsystem:console $(LDFLAGS) \
&& ($(MERGEMANIFESTEXE))
+### Native command to build an ANSI executable
+MKEXE_ANSI=$(FLEXLINK) -exe
+
### How to build a static library
MKLIB=link -lib -nologo -machine:AMD64 /out:$(1) $(2)
#ml let mklib out files opts =
### Name of operating system family for the native-code compiler.
SYSTEM=win64
-### Which C compiler to use for the native-code compiler.
-NATIVECC=cl -nologo -O2 -Gy- -MD
-NATIVE_C_COMPILER=$(NATIVECC)
-
-### Additional compile-time options for $(NATIVECC).
-NATIVECCCOMPOPTS=-DCAML_NAME_SPACE
-
-### Additional link-time options for $(NATIVECC)
-NATIVECCLINKOPTS=
+OCAMLOPT_CFLAGS=-nologo -O2 -Gy- -MD
+OCAMLOPT_CPPFLAGS=-D_CRT_SECURE_NO_DEPRECATE
### Build partially-linked object file
PACKLD=link -lib -nologo -machine:AMD64 -out:# must have no space after '-out:'
############# Configuration for the contributed libraries
-OTHERLIBRARIES=win32unix systhreads str num win32graph dynlink bigarray
-
-### Name of the target architecture for the "num" library
-BNG_ARCH=generic
-BNG_ASM_LEVEL=0
+OTHERLIBRARIES=win32unix systhreads str win32graph dynlink bigarray
############# for the testsuite makefiles
#ml let topdir = "" and wintopdir = "";;
SORT=/usr/bin/sort
SET_LD_PATH=PATH="$(PATH):$(LD_PATH)"
MAX_TESTSUITE_DIR_RETRIES=1
+FLAT_FLOAT_ARRAY=true
clang __clang_major__ __clang_minor__
#elif defined(__GNUC__) && defined(__GNUC_MINOR__)
gcc __GNUC__ __GNUC_MINOR__
+#elif defined(__xlc__) && (__xlC__)
+xlc __xlC__ __xlC_ver__
#else
unknown
#endif
for f in $*; do echo " $f();"; done
echo " return 0; }") >> hasgot.c
-if test "$verbose" = yes; then
- echo "hasgot $args: $cc $opts -o tst hasgot.c $libs" >&2
- exec $cc $opts -o tst hasgot.c $libs > /dev/null
+cmd="$cc $cflags $opts -o tst hasgot.c $ldflags $libs"
+
+if $verbose; then
+ echo "hasgot $args: $cmd" >&2
+ exec $cmd > /dev/null
else
- exec $cc $opts -o tst hasgot.c $libs > /dev/null 2>/dev/null
+ exec $cmd > /dev/null 2>/dev/null
fi
for f in $*; do echo " (void) & $f;"; done
echo " return 0; }") >> hasgot.c
-if test "$verbose" = yes; then
- echo "hasgot2 $args: $cc $opts -o tst hasgot.c $libs" >&2
- exec $cc $opts -o tst hasgot.c $libs > /dev/null
+cmd="$cc $cflags $opts -o tst hasgot.c $ldflags $libs"
+
+if $verbose; then
+ echo "hasgot2 $args: $cmd" >&2
+ exec $cmd > /dev/null
else
- exec $cc $opts -o tst hasgot.c $libs > /dev/null 2>/dev/null
+ exec $cmd > /dev/null 2>/dev/null
fi
#include "m.h"
#if defined(ARCH_INT64_TYPE)
-typedef ARCH_INT64_TYPE int64_t;
+typedef ARCH_INT64_TYPE myint64_t;
#elif SIZEOF_LONG == 8
-typedef long int64_t;
+typedef long myint64_t;
#elif SIZEOF_LONGLONG == 8
-typedef long long int64_t;
+typedef long long myint64_t;
#else
#error "No 64-bit integer type available"
#endif
-volatile int64_t foo;
+volatile myint64_t foo;
-void access_int64(volatile int64_t *p)
+void access_int64(volatile myint64_t *p)
{
foo = *p;
}
signal(SIGBUS, sig_handler);
#endif
if(setjmp(failure) == 0) {
- access_int64((volatile int64_t *) n);
- access_int64((volatile int64_t *) (n+1));
+ access_int64((volatile myint64_t *) n);
+ access_int64((volatile myint64_t *) (n+1));
res = 0;
} else {
res = 1;
#* *
#**************************************************************************
-if test "$verbose" = yes; then
-echo "runtest: $cc -o tst $* $cclibs" >&2
-$cc -o tst $* $cclibs || exit 100
+cmd="$cc $cflags -o tst $* $ldflags $cclibs"
+
+if $verbose; then
+ echo "runtest: $cmd" >&2
+ $cmd || exit 100
else
-$cc -o tst $* $cclibs 2> /dev/null || exit 100
+ $cmd 2> /dev/null || exit 100
fi
exec ./tst
# Exit code is 0 for Solaris ld, 1 for GNU ld
echo "int main() { return 0; }" > hasgot.c
-$cc -v -o tst hasgot.c 2>&1 | grep -s '^ld:' > /dev/null
+$cc $cflags -v -o tst hasgot.c $ldflags 2>&1 | grep -s '^ld:' > /dev/null
exit $?
#* *
#**************************************************************************
-if test "$verbose" = yes; then
-echo "tryassemble: $aspp -o tst $*" >&2
-$aspp -o tst $* || exit 100
+if $verbose; then
+ echo "tryassemble: $aspp -o tst $*" >&2
+ $aspp -o tst $* || exit 100
else
-$aspp -o tst $* 2> /dev/null || exit 100
+ $aspp -o tst $* 2> /dev/null || exit 100
fi
# test as also (if differs)
if test "$aspp" != "$as"; then
-if test "$verbose" = yes; then
-echo "tryassemble: $as -o tst $*" >&2
-$as -o tst $* || exit 100
-else
-$as -o tst $* 2> /dev/null || exit 100
-fi
+ if $verbose; then
+ echo "tryassemble: $as -o tst $*" >&2
+ $as -o tst $* || exit 100
+ else
+ $as -o tst $* 2> /dev/null || exit 100
+ fi
fi
#* *
#**************************************************************************
-if test "$verbose" = yes; then
-echo "trycompile: $cc -o tst $* $cclibs" >&2
-$cc -o tst $* $cclibs || exit 100
+cmd="$cc $cflags -o tst $* $ldflags $cclibs"
+
+if $verbose; then
+ echo "trycompile: $cmd" >&2
+ $cmd || exit 100
else
-$cc -o tst $* $cclibs 2> /dev/null || exit 100
+ $cmd 2> /dev/null || exit 100
fi
#define ARCH_UINT64_TYPE unsigned __int64
#endif
#define ARCH_INT64_PRINTF_FORMAT "I64"
+#if _MSC_VER >= 1800
+#define ARCH_SIZET_PRINTF_FORMAT "z"
+#else
+#define ARCH_SIZET_PRINTF_FORMAT "I"
+#endif
#if defined(_MSC_VER) && !defined(__cplusplus)
#define inline __inline
#else
#define INT64_LITERAL(s) s ## LL
#endif
+
+#define FLAT_FLOAT_ARRAY
#define HAS_IPV6
#define HAS_NICE
#define SUPPORT_DYNAMIC_LINKING
+#define HAS_EXECVPE
#if defined(_MSC_VER) && _MSC_VER < 1300
#define LACKS_SANE_NAN
#define LACKS_VSCPRINTF
/* Define HAS_MKFIFO if the library provides the mkfifo() function. */
#define HAS_GETCWD
-#define HAS_GETWD
/* Define HAS_GETCWD if the library provides the getcwd() function. */
-/* Define HAS_GETWD if the library provides the getwd() function. */
#define HAS_GETPRIORITY
target_bindir=''
libdir=''
mandir=''
-manext=1
+programs_man_section=1
+libraries_man_section=3
host_type=unknown
target_type=""
ccoption=''
+cpp='cpp'
asoption=''
asppoption=''
cclibs=''
graph_wanted=yes
pthread_wanted=yes
dl_defs=''
-verbose=no
+verbose=false
with_curses=yes
debugruntime=false
with_instrumented_runtime=false
-with_sharedlibs=yes
+with_sharedlibs=true
partialld="ld -r"
with_debugger=ocamldebugger
with_ocamldoc=ocamldoc
with_frame_pointers=false
with_spacetime=false
+enable_call_counts=true
with_profinfo=false
profinfo_width=0
no_naked_pointers=false
TOOLPREF=""
with_cfi=true
flambda=false
-safe_string=false
+force_safe_string=false
+default_safe_string=true
afl_instrument=false
max_testsuite_dir_retries=0
-with_cplugins=true
+with_cplugins=false
with_fpic=false
+flat_float_array=true
# Try to turn internationalization off, can cause config.guess to malfunction!
unset LANG
case "$2" in
*/man[1-9ln])
mandir=`echo $2 | sed -e 's|^\(.*\)/man.$|\1|'`
- manext=`echo $2 | sed -e 's/^.*\(.\)$/\1/'`;;
+ programs_man_section=`echo $2 | sed -e 's/^.*\(.\)$/\1/'`;;
*)
- mandir=$2
- manext=1;;
+ mandir=$2;;
esac
shift;;
-libunwinddir|--libunwinddir)
-no-curses|--no-curses)
with_curses=no;;
-no-shared-libs|--no-shared-libs)
- with_sharedlibs=no;;
+ with_sharedlibs=false;;
-x11include*|--x11include*)
x11_include_dir=$2; shift;;
-x11lib*|--x11lib*)
-dllibs*|--dllibs*)
dllib="$2"; shift;;
-verbose|--verbose)
- verbose=yes;;
+ verbose=true;;
-with-debug-runtime|--with-debug-runtime)
debugruntime=true;;
-with-instrumented-runtime|--with-instrumented-runtime)
no_naked_pointers=true;;
-spacetime|--spacetime)
with_spacetime=true; with_profinfo=true; profinfo_width=26;;
+ -disable-call-counts|--disable-call-counts)
+ enable_call_counts=false;;
-reserved-header-bits|--reserved-header-bits)
with_spacetime=false; with_profinfo=true; profinfo_width=$2;shift
case $profinfo_width in
native_compiler=false;;
-flambda|--flambda)
flambda=true;;
+ -with-cplugins|--with-cplugins)
+ with_cplugins=true;;
-no-cplugins|--no-cplugins)
- with_cplugins=false;;
+ ;; # Ignored for backward compatibility
-fPIC|--fPIC)
with_fpic=true;;
- -safe-string|--safe-string)
- safe_string=true;;
+
+ # There are two configure-time string safety options,
+ # -(no-)force-safe-string and -default-(un)safe-string that
+ # interact with a compile-time (un)safe-string option.
+ #
+ # If -force-safe-string is set at configure time, then the compiler
+ # will always enforce that string and bytes are distinct: the
+ # compile-time -unsafe-string option is disabled. This lets us
+ # assume pervasive string immutability, for code optimizations and
+ # in the C layer.
+ #
+ # If -no-force-safe-string is set at configure-time, the compiler
+ # will use the compile-time (un)safe-string option to decide whether
+ # string and bytes are compatible on a per-file basis. The
+ # configure-time options default-(un)safe-string decide which
+ # setting will be chosen by default, if no compile-time option is
+ # explicitly passed.
+ #
+ # The configure-time behavior of OCaml 4.05 and older was equivalent
+ # to -no-force-safe-string -default-unsafe-string. OCaml 4.06
+ # uses -no-force-safe-string -default-safe-string. We
+ # expect -force-safe-string to become the default in the future.
+ -force-safe-string|--force-safe-string)
+ force_safe_string=true;;
+ -no-force-safe-string|--no-force-safe-string)
+ force_safe_string=false;;
+ -default-safe-string|--default-safe-string)
+ default_safe_string=true;;
+ -default-unsafe-string|--default-unsafe-string)
+ default_safe_string=false;;
+ -flat-float-array|--flat-float-array)
+ flat_float_array=true;;
+ -no-flat-float-array|--no-flat-float-array)
+ flat_float_array=false;;
-afl-instrument)
afl_instrument=true;;
*) if echo "$1" | grep -q -e '^--\?[a-zA-Z0-9-]\+='; then
# Write options to Makefile
+config() {
+# This function hardens the generated Makefile against '#' symbols
+# present in a source path (opam-compiler-conf may pick such directory
+# names if working from a branch named 'PR#4242-answer-all-questions')
+# by escaping them into '\#'.
+
+# When injecting data in Makefiles, it is customary to also escape
+# '$', which get turned into '$$'. However, this transformation is
+# invalid here as some of the variables are meant to be code
+# interpreted by make: for example, passing
+# --bindir "$(PREFIX)/bin2"
+# is explicitly supported (see "or relative to $(PREFIX)" messages above).
+
+# Finally, it is also impossible for the user to escape the '#' signs
+# before calling this configure script, given that
+# $(PREFIX) is also injected in C code where this escape is invalid
+# -- see the definition of the OCAML_STDLIB_DIR macro below.
+
+ echo "$1=$2" | sed 's/#/\\#/g' >> Makefile
+}
+
echo "# generated by ./configure $configure_options" >> Makefile
-echo "CONFIGURE_ARGS=$configure_options" >> Makefile
+config CONFIGURE_ARGS "$configure_options"
# Where to install
-echo "PREFIX=$prefix" >> Makefile
+config PREFIX "$prefix"
case "$bindir" in
- "") echo 'BINDIR=$(PREFIX)/bin' >> Makefile
+ "") config BINDIR '$(PREFIX)/bin'
bindir="$prefix/bin";;
- *) echo "BINDIR=$bindir" >> Makefile;;
+ *) config BINDIR "$bindir";;
esac
-echo 'BYTERUN=$(BINDIR)/ocamlrun' >> Makefile
+config BYTERUN '$(BINDIR)/ocamlrun'
case "$libdir" in
- "") echo 'LIBDIR=$(PREFIX)/lib/ocaml' >> Makefile
+ "") config LIBDIR '$(PREFIX)/lib/ocaml'
libdir="$prefix/lib/ocaml";;
- *) echo "LIBDIR=$libdir" >> Makefile;;
+ *) config LIBDIR "$libdir";;
esac
-echo 'STUBLIBDIR=$(LIBDIR)/stublibs' >> Makefile
+config STUBLIBDIR '$(LIBDIR)/stublibs'
case "$mandir" in
- "") echo 'MANDIR=$(PREFIX)/man' >> Makefile
+ "") config MANDIR '$(PREFIX)/man'
mandir="$prefix/man";;
- *) echo "MANDIR=$mandir" >> Makefile;;
+ *) config MANDIR "$mandir";;
esac
-echo "MANEXT=$manext" >> Makefile
+config PROGRAMS_MAN_SECTION "$programs_man_section"
+config LIBRARIES_MAN_SECTION "$libraries_man_section"
# Determine the system type
inf "Using compiler $cc."
+# Configure compiler to use in further tests.
+
+export cc verbose
+
# Determine the C compiler family (GCC, Clang, etc)
ccfamily=`$cc -E cckind.c | grep '^[a-z]' | tr -s ' ' '-'`
"Make sure the C compiler $cc is properly installed.";;
esac
-# Configure the bytecode compiler
-
-# The BYTECC make variable defines which compiler and options to use
-# to compile C code intended to be used by OCaml bytecode programs.
-# It is used inside OCaml's build system.
-
# The BYTECODE_C_COMPILER make variable says how the C compiler should be
# invoked to process a third-party C source file passed to ocamlc
# when no -cc command-line option has been specified.
# in the OCaml distribution and third-party C source files compiled
# with ocamlc.
-bytecc="$cc"
-mkexe="\$(BYTECC)"
+mkexe="\$(CC) \$(CFLAGS) \$(CPPFLAGS) \$(LDFLAGS)"
mkexedebugflag="-g"
-bytecccompopts=""
-byteccprivatecompopts=""
-bytecclinkopts=""
+common_cflags=""
+common_cppflags=""
+internal_cflags=""
+internal_cppflags=""
+ocamlc_cflags=""
+ocamlc_cppflags=""
+ocamlopt_cflags=""
+ocamlopt_cppflags=""
+ldflags=""
ostype="Unix"
exe=""
iflexdir=""
case "$ccfamily" in
clang-*)
- bytecccompopts="-O2 -fno-strict-aliasing -fwrapv";
- byteccprivatecompopts="$gcc_warnings";;
+ common_cflags="-O2 -fno-strict-aliasing -fwrapv";
+ internal_cflags="$gcc_warnings";;
gcc-[012]-*)
# Some versions known to miscompile OCaml, e,g, 2.7.2.1, some 2.96.
# Plus: C99 support unknown.
# Known problems with -fwrapv fixed in 4.2 only.
wrn "This version of GCC is rather old. Reducing optimization level."
wrn "Consider using GCC version 4.2 or above."
- bytecccompopts="-std=gnu99 -O";
- byteccprivatecompopts="$gcc_warnings";;
+ common_cflags="-std=gnu99 -O";
+ internal_cflags="$gcc_warnings";;
gcc-4-*)
- bytecccompopts="-std=gnu99 -O2 -fno-strict-aliasing -fwrapv \
+ common_cflags="-std=gnu99 -O2 -fno-strict-aliasing -fwrapv \
-fno-builtin-memcmp";
- byteccprivatecompopts="$gcc_warnings";;
+ internal_cflags="$gcc_warnings";;
gcc-*)
- bytecccompopts="-O2 -fno-strict-aliasing -fwrapv";
- byteccprivatecompopts="$gcc_warnings";;
+ common_cflags="-O2 -fno-strict-aliasing -fwrapv";
+ internal_cflags="$gcc_warnings";;
*)
- bytecccompopts="-O";;
+ common_cflags="-O";;
esac
-byteccprivatecompopts="-DCAML_NAME_SPACE $byteccprivatecompopts"
+internal_cppflags="-DCAML_NAME_SPACE $internal_cppflags"
# Adjust according to target
-case "$bytecc,$target" in
- cc,*-*-nextstep*)
- # GNU C extensions disabled, but __GNUC__ still defined!
- bytecccompopts="$bytecccompopts -U__GNUC__ -posix"
- bytecclinkopts="-posix";;
+case "$cc,$target" in
*,*-*-rhapsody*)
- # Almost the same as NeXTStep
- bytecccompopts="$bytecccompopts -DSHRINKED_GNUC"
+ common_cppflags="-DSHRINKED_GNUC $common_cppflags"
mathlib="";;
*,*-*-darwin*)
mathlib=""
# No -lm library
mathlib="";;
*gcc,alpha*-*-osf*)
- if cc="$bytecc" sh ./hasgot -mieee; then
- bytecccompopts="-mieee $bytecccompopts";
+ if sh ./hasgot -mieee; then
+ common_cflags="-mieee $common_cflags";
fi
# Put code and static data in lower 4GB
- bytecclinkopts="-Wl,-T,12000000 -Wl,-D,14000000"
+ ldflags="-Wl,-T,12000000 -Wl,-D,14000000"
# Tell gcc that we can use 32-bit code addresses for threaded code
echo "#define ARCH_CODE32" >> m.h;;
cc,alpha*-*-osf*)
- bytecccompopts="-std1 -ieee";;
+ common_cflags="-std1 -ieee";;
*gcc*,alpha*-*-linux*)
- if cc="$bytecc" sh ./hasgot -mieee; then
- bytecccompopts="-mieee $bytecccompopts";
+ if sh ./hasgot -mieee; then
+ common_cflags="-mieee $common_cflags";
fi;;
*,mips-*-irix6*)
# Turn off warning "unused library"
- bytecclinkopts="-n32 -Wl,-woff,84";;
+ ldflags="-n32 -Wl,-woff,84";;
*,alpha*-*-unicos*)
# For the Cray T3E
- bytecccompopts="$bytecccompopts -DUMK";;
+ common_cppflags="$common_cppflags -DUMK";;
*,powerpc-*-aix*)
# Avoid name-space pollution by requiring Unix98-conformant includes
- bytecccompopts="$bytecccompopts -D_XOPEN_SOURCE=500 -D_ALL_SOURCE";;
+ common_cppflags="$common_cppflags -D_XOPEN_SOURCE=500 -D_ALL_SOURCE";;
*,*-*-cygwin*)
case $target in
i686-*) flavor=cygwin;;
x86_64-*) flavor=cygwin64;;
*) err "unknown cygwin variant";;
esac
- bytecccompopts="$bytecccompopts -U_WIN32"
- if test $with_sharedlibs = yes; then
+ common_cppflags="$common_cppflags -U_WIN32"
+ if $with_sharedlibs; then
flexlink="flexlink -chain $flavor -merge-manifest -stack 16777216"
flexdir=`$flexlink -where | tr -d '\015'`
if test -z "$flexdir"; then
wrn "flexlink not found: native shared libraries won't be available."
- with_sharedlibs=no
+ with_sharedlibs=false
else
iflexdir="-I\"$flexdir\""
mkexe="$flexlink -exe"
mkexedebugflag="-link -g"
fi
fi
- if test $with_sharedlibs = no; then
+ if ! $with_sharedlibs; then
mkexe="$mkexe -Wl,--stack,16777216"
- bytecclinkopts="-Wl,--stack,16777216"
+ ldflags="-Wl,--stack,16777216"
fi
exe=".exe"
ostype="Cygwin";;
*,*-*-mingw*)
dllccompopt="-DCAML_DLL"
- if test $with_sharedlibs = yes; then
+ if $with_sharedlibs; then
case "$target" in
i686-*-*) flexlink_chain="mingw";;
x86_64-*-*) flexlink_chain="mingw64";;
flexdir=`$flexlink -where`
if test -z "$flexdir"; then
wrn "flexlink not found: native shared libraries won't be available."
- with_sharedlibs=no
+ with_sharedlibs=false
else
iflexdir="-I\"$flexdir\""
mkexe="$flexlink -exe"
echo "#endif" >> m.h;;
esac
-# Configure compiler to use in further tests.
+# Configure compiler options to use in further tests.
-cc="$bytecc $bytecclinkopts"
-export cc cclibs verbose
+export cclibs ldflags
# Check C compiler.
-cc="$bytecc $bytecccompopts $byteccprivatecompopts $bytecclinkopts" sh ./runtest ansi.c
+cflags="$common_cflags $internal_cflags" sh ./runtest ansi.c
case $? in
0) inf "The C compiler is ISO C99 compliant." ;;
1) wrn "The C compiler is ANSI / ISO C90 compliant, but not ISO C99" \
"($ocaml_system_version) doesn't match the version of these\n" \
"sources ($ocaml_source_version)."
else
- echo "CAMLRUN=`./searchpath -p ocamlrun`" >> Makefile
+ config CAMLRUN "`./searchpath -p ocamlrun`"
fi
fi
err "While you have an ocamlyacc binary, it cannot be executed" \
"successfully."
else
- echo "CAMLYACC=`./searchpath -p ocamlyacc`" >> Makefile
+ config CAMLYACC "`./searchpath -p ocamlyacc`"
fi
fi
if [ -z "$target_bindir" ]; then
err "Cross-compilation requires -target-bindir."
else
- echo "TARGET_BINDIR=$target_bindir" >> Makefile
+ config TARGET_BINDIR "$target_bindir"
fi
fi # cross-compiler
"64-bit integers. I'm going to assume this architecture has\n" \
"alignment constraints. That's a safe bet: OCaml will work\n" \
"even if this architecture has actually no alignment\n" \
- "constraints." \
+ "constraints."
echo "#define ARCH_ALIGN_INT64" >> m.h;;
esac
esac
dl_needs_underscore=false
sharedcccompopts=''
mksharedlib='shared-libs-not-available'
-byteccrpath=''
+rpath=''
mksharedlibrpath=''
natdynlinkopts=""
-if test $with_sharedlibs = "yes"; then
+if $with_sharedlibs; then
case "$target" in
*-*-cygwin*)
mksharedlib="$flexlink"
mkmaindll="$flexlink -maindll"
shared_libraries_supported=true;;
alpha*-*-osf*)
- case "$bytecc" in
+ case "$cc" in
*gcc*)
sharedcccompopts="-fPIC"
- mksharedlib="$bytecc -shared"
- byteccrpath="-Wl,-rpath,"
+ mksharedlib="$cc -shared"
+ rpath="-Wl,-rpath,"
mksharedlibrpath="-Wl,-rpath,"
shared_libraries_supported=true;;
cc*)
sharedcccompopts=""
mksharedlib="ld -shared -expect_unresolved '*'"
- byteccrpath="-Wl,-rpath,"
+ rpath="-Wl,-rpath,"
mksharedlibrpath="-rpath "
shared_libraries_supported=true;;
esac;;
*-*-solaris2*)
- case "$bytecc" in
+ case "$cc" in
*gcc*)
sharedcccompopts="-fPIC"
if sh ./solaris-ld; then
mksharedlib="ld -G"
- byteccrpath="-R"
+ rpath="-R"
mksharedlibrpath="-R"
else
- mksharedlib="$bytecc -shared"
- bytecclinkopts="$bytecclinkopts -Wl,-E"
+ mksharedlib="$cc -shared"
+ ldflags="$ldflags -Wl,-E"
natdynlinkopts="-Wl,-E"
- byteccrpath="-Wl,-rpath,"
+ rpath="-Wl,-rpath,"
mksharedlibrpath="-Wl,-rpath,"
fi
shared_libraries_supported=true;;
*)
sharedcccompopts="-KPIC"
- byteccrpath="-R"
+ rpath="-R"
mksharedlibrpath="-R"
mksharedlib="/usr/ccs/bin/ld -G"
shared_libraries_supported=true;;
esac;;
mips*-*-irix[56]*)
- case "$bytecc" in
+ case "$cc" in
cc*) sharedcccompopts="";;
*gcc*) sharedcccompopts="-fPIC";;
esac
mksharedlib="ld -shared -rdata_shared"
- byteccrpath="-Wl,-rpath,"
+ rpath="-Wl,-rpath,"
mksharedlibrpath="-rpath "
shared_libraries_supported=true;;
i[3456]86-*-darwin[89].*)
- mksharedlib="$bytecc -bundle -flat_namespace -undefined suppress \
+ mksharedlib="$cc -shared -flat_namespace -undefined suppress \
-read_only_relocs suppress"
- bytecccompopts="$dl_defs $bytecccompopts"
+ common_cflags="$dl_defs $common_cflags"
dl_needs_underscore=false
shared_libraries_supported=true;;
*-apple-darwin*)
- mksharedlib="$bytecc -bundle -flat_namespace -undefined suppress \
+ mksharedlib="$cc -shared -flat_namespace -undefined suppress \
-Wl,-no_compact_unwind"
- bytecccompopts="$dl_defs $bytecccompopts"
+ common_cflags="$dl_defs $common_cflags"
dl_needs_underscore=false
shared_libraries_supported=true;;
- *-*-linux-gnu|*-*-linux|*-*-freebsd[3-9]*|*-*-freebsd[1-9][0-9]*\
+ *-*-linux*|*-*-freebsd[3-9]*|*-*-freebsd[1-9][0-9]*\
|*-*-openbsd*|*-*-netbsd*|*-*-dragonfly*|*-*-gnu*|*-*-haiku*)
sharedcccompopts="-fPIC"
- mksharedlib="$bytecc -shared"
- bytecclinkopts="$bytecclinkopts -Wl,-E"
- byteccrpath="-Wl,-rpath,"
+ mksharedlib="$cc -shared"
+ ldflags="$ldflags -Wl,-E"
+ rpath="-Wl,-rpath,"
mksharedlibrpath="-Wl,-rpath,"
natdynlinkopts="-Wl,-E"
shared_libraries_supported=true;;
+ powerpc-*-aix*)
+ case "$ccfamily" in
+ xlc-*)sharedcccompopts="-qpic"
+ mksharedlib="$cc -qmkshrobj -G"
+ mksharedlibrpath="-Wl,-blibpath,"
+ ldflags="$ldflags -brtl -bexpfull"
+ dl_needs_underscore=false
+ rpath="-Wl,-blibpath,"
+ shared_libraries_supported=true;;
+ esac
esac
fi
natdynlink=false
-if test $with_sharedlibs = "yes"; then
+if $with_sharedlibs; then
case "$target" in
*-*-cygwin*) natdynlink=true;;
*-*-mingw*) natdynlink=true;;
x86_64-*-darwin*) natdynlink=true;;
s390x*-*-linux*) natdynlink=true;;
powerpc*-*-linux*) natdynlink=true;;
- sparc*-*-linux*) natdynlink=true;;
i686-*-kfreebsd*) natdynlink=true;;
x86_64-*-kfreebsd*) natdynlink=true;;
x86_64-*-dragonfly*) natdynlink=true;;
# Try to work around the Skylake/Kaby Lake processor bug.
-case "$bytecc,$target" in
+case "$cc,$target" in
*gcc*,x86_64-*|*gcc*,i686-*)
if sh ./hasgot -Werror -fno-tree-vrp; then
- byteccprivatecompopts="$byteccprivatecompopts -fno-tree-vrp"
+ internal_cflags="$internal_cflags -fno-tree-vrp"
inf "Adding -fno-tree-vrp option to work around PR#7452"
fi;;
esac
# Configure the native-code compiler
-# The NATIVECC make variable defines which compiler and options to use
-# to compile C code intended to be used by OCaml native programs.
-# It is used inside OCaml's build system.
-
-# The NATIVE_C_COMPILER make variable says how the C compiler should be
-# invoked to process a third-party C source file passed to ocamlopt
-# when no -cc command-line option has been specified.
-
-# The NATIVECCCOMPOPTS make variable contains options to pass to the C
-# compiler, but only when compiling C files that belong to the OCaml
-# distribution.
-# In other words, when ocamlopt is called to compile a third-party C
-# source file, it will _not_ pass these options to the C compiler.
-
arch=none
model=default
system=unknown
case "$target" in
- sparc*-*-solaris2.*) arch=sparc; system=solaris;;
- sparc*-*-*bsd*) arch=sparc; system=bsd;;
- sparc*-*-linux*) arch=sparc; system=linux;;
- sparc*-*-gnu*) arch=sparc; system=gnu;;
i[3456]86-*-linux*) arch=i386; system=linux_`sh ./runtest elf.c`;;
i[3456]86-*-*bsd*) arch=i386; system=bsd_`sh ./runtest elf.c`;;
- i[3456]86-*-nextstep*) arch=i386; system=nextstep;;
i[3456]86-*-solaris*) if $arch64; then
arch=amd64; system=solaris
else
powerpc*-*-linux*) arch=power;
if $arch64; then model=ppc64; else model=ppc; fi
system=elf;;
- powerpc-*-netbsd*) arch=power; model=ppc; system=elf;;
+ powerpc-*-netbsd*) arch=power; model=ppc; system=netbsd;;
powerpc-*-openbsd*) arch=power; model=ppc; system=bsd_elf;;
s390x*-*-linux*) arch=s390x; model=z10; system=elf;;
armv6*-*-linux-gnueabihf) arch=arm; model=armv6; system=linux_eabihf;;
# Sometimes, it's 32-bit mode that is not supported (PR#6722).
case "$arch64,$arch,$model" in
- true,sparc,*|true,power,ppc|false,amd64,*)
+ true,power,ppc|false,amd64,*)
arch=none; model=default; system=unknown;;
esac
arch=none; model=default; system=unknown; natdynlink=false;;
esac
-if test -z "$ccoption"; then
- nativecc="$bytecc"
-else
- nativecc="$ccoption"
-fi
-
-nativecccompopts="$bytecccompopts"
-nativeccprivatecompopts="$byteccprivatecompopts"
nativeccprofopts=''
-nativecclinkopts=''
-# FIXME the naming of nativecclinkopts is broken: these are options for
-# ld (for shared libs), not for cc
-nativeccrpath="$byteccrpath"
-case "$arch,$nativecc,$system,$model" in
- *,*,nextstep,*) nativecclinkopts="-posix";;
+case "$arch,$cc,$system,$model" in
*,*,rhapsody,*) if $arch64; then partialld="ld -r -arch ppc64"; fi;;
amd64,gcc*,macosx,*) partialld="ld -r -arch x86_64";;
amd64,gcc*,solaris,*) partialld="ld -r -m elf_x86_64";;
case "$arch,$system" in
amd64,macosx) if sh ./searchpath clang; then
- as='clang -arch x86_64 -c'
- aspp='clang -arch x86_64 -c'
+ as='clang -arch x86_64 -Wno-trigraphs -c'
+ aspp='clang -arch x86_64 -Wno-trigraphs -c'
else
as="${TOOLPREF}as -arch x86_64"
aspp="${TOOLPREF}gcc -arch x86_64 -c"
fi;;
s390x,elf) as="${TOOLPREF}as -m 64 -march=$model"
aspp="${TOOLPREF}gcc -c -Wa,-march=$model";;
- sparc,solaris) as="${TOOLPREF}as"
- case "$cc" in
- *gcc*) aspp="${TOOLPREF}gcc -c";;
- *) aspp="${TOOLPREF}as -P";;
- esac;;
arm,freebsd) as="${TOOLPREF}cc -c"
aspp="${TOOLPREF}cc -c";;
*,dragonfly) as="${TOOLPREF}as"
aspp="${TOOLPREF}cc -c";;
*,freebsd) as="${TOOLPREF}as"
aspp="${TOOLPREF}cc -c";;
- amd64,*|arm,*|arm64,*|i386,*|power,bsd*|sparc,*)
+ amd64,*|arm,*|arm64,*|i386,*|power,bsd*|power,netbsd)
as="${TOOLPREF}as"
case "$ccfamily" in
clang-*)
- aspp="${TOOLPREF}clang -c"
+ aspp="${TOOLPREF}clang -c -Wno-trigraphs"
;;
*)
aspp="${TOOLPREF}gcc -c"
i386,bsd_elf) profiling='true';;
amd64,macosx) profiling='true';;
i386,macosx) profiling='true';;
- sparc,bsd) profiling='true';;
- sparc,solaris)
- profiling='true'
- case "$nativecc" in gcc*) ;; *) cc_profile='-xpg';; esac;;
amd64,linux) profiling='true';;
amd64,openbsd) profiling='true';;
amd64,freebsd) profiling='true';;
arm,linux*) profiling='true';;
power,elf) profiling='true';;
power,bsd*) profiling='true';;
+ power,netbsd) profiling='true';;
*) profiling='false';;
esac
if sh ./searchpath ${TOOLPREF}ranlib; then
inf "ranlib found"
- echo "RANLIB=${TOOLPREF}ranlib" >> Makefile
- echo "RANLIBCMD=${TOOLPREF}ranlib" >> Makefile
+ config RANLIB "${TOOLPREF}ranlib"
+ config RANLIBCMD "${TOOLPREF}ranlib"
else
inf "ranlib not used"
- echo "RANLIB=${TOOLPREF}ar rs" >> Makefile
- echo "RANLIBCMD=" >> Makefile
+ config RANLIB "${TOOLPREF}ar rs"
+ config RANLIBCMD ""
fi
-echo "ARCMD=${TOOLPREF}ar" >> Makefile
+config ARCMD "${TOOLPREF}ar"
# Write the OS type (Unix or Cygwin)
*-*-sunos*|*-*-unicos*)
wrn "We won't use it, though, because under SunOS and Unicos it breaks " \
"on pathnames longer than 30 characters"
- echo "HASHBANGSCRIPTS=false" >> Makefile;;
+ config HASHBANGSCRIPTS "false";;
*-*-cygwin*)
wrn "We won't use it, though, because of conflicts with .exe extension " \
"under Cygwin"
- echo "HASHBANGSCRIPTS=false" >> Makefile;;
+ config HASHBANGSCRIPTS "false";;
*-*-mingw*)
inf "We won't use it, though, because it's on the target platform " \
"it would be used and windows doesn't support it."
- echo "HASHBANGSCRIPTS=false" >> Makefile;;
+ config HASHBANGSCRIPTS "false";;
*)
- echo "HASHBANGSCRIPTS=true" >> Makefile;;
+ config HASHBANGSCRIPTS "true";;
esac
else
inf "No support for #! in shell scripts"
- echo "HASHBANGSCRIPTS=false" >> Makefile
+ config HASHBANGSCRIPTS "false"
fi
# Use 64-bit file offset if possible
-bytecccompopts="$bytecccompopts -D_FILE_OFFSET_BITS=64"
-nativecccompopts="$nativecccompopts -D_FILE_OFFSET_BITS=64"
+common_cppflags="$common_cppflags -D_FILE_OFFSET_BITS=64"
# Check the semantics of signal handlers
*) unix_or_win32="unix"; unixlib="unix"; graphlib="graph";;
esac
-echo "UNIX_OR_WIN32=$unix_or_win32" >> Makefile
-echo "UNIXLIB=$unixlib" >> Makefile
-echo "GRAPHLIB=$graphlib" >> Makefile
+config UNIX_OR_WIN32 "$unix_or_win32"
+config UNIXLIB "$unixlib"
+config GRAPHLIB "$graphlib"
-otherlibraries="$unixlib str num dynlink bigarray"
+otherlibraries="$unixlib str dynlink bigarray"
# Spacetime profiling is only available for native code on 64-bit targets.
-case "$native_compiler" in
- true)
+case "$arch" in
+ none) ;;
+ *)
if $arch64; then
otherlibraries="$otherlibraries raw_spacetime_lib"
fi
;;
- *) ;;
esac
# For the Unix library
echo "#define HAS_GETCWD" >> s.h
fi
-if sh ./hasgot getwd; then
- inf "getwd() found."
- echo "#define HAS_GETWD" >> s.h
-fi
-
if sh ./hasgot getpriority setpriority; then
inf "getpriority() found."
echo "#define HAS_GETPRIORITY" >> s.h
echo "#define HAS_ACCEPT4" >> s.h
fi
+if sh ./hasgot getauxval; then
+ inf "getauxval() found."
+ echo "#define HAS_GETAUXVAL" >> s.h
+fi
+
+if sh ./hasgot -i sys/shm.h; then
+ inf "sys/shm.h found."
+ echo "#define HAS_SYS_SHM_H" >> s.h
+fi
+
+if sh ./hasgot execvpe; then
+ inf "execvpe() found."
+ echo "#define HAS_EXECVPE" >> s.h
+fi
+
# Determine if the debugger is supported
if test -n "$with_debugger"; then
inf "Cannot detect system stack overflow.";;
esac
-# Determine the target architecture for the "num" library
-
-case "$arch" in
- i386) bng_arch=ia32
- if sh ./trycompile ia32sse2.c
- then bng_asm_level=2
- else bng_asm_level=1
- fi;;
- power) bng_arch=ppc; bng_asm_level=1;;
- amd64) bng_arch=amd64; bng_asm_level=1;;
- arm64) bng_arch=arm64; bng_asm_level=1;;
- *) bng_arch=generic; bng_asm_level=0;;
-esac
-
-echo "BNG_ARCH=$bng_arch" >> Makefile
-echo "BNG_ASM_LEVEL=$bng_asm_level" >> Makefile
-
# Determine if the POSIX threads library is supported
systhread_support=false
inf "POSIX threads library supported."
systhread_support=true
otherlibraries="$otherlibraries systhreads"
- bytecccompopts="$bytecccompopts -D_REENTRANT"
- nativecccompopts="$nativecccompopts -D_REENTRANT"
+ common_cppflags="$common_cppflags -D_REENTRANT"
case "$target" in
*-*-freebsd*|*-*-dragonfly*)
- bytecccompopts="$bytecccompopts -D_THREAD_SAFE"
- nativecccompopts="$nativecccompopts -D_THREAD_SAFE";;
+ common_cppflags="$common_cppflags -D_THREAD_SAFE";;
*-*-openbsd*)
- bytecccompopts="$bytecccompopts -pthread"
- asppflags="$asppflags -pthread"
- nativecccompopts="$nativecccompopts -pthread";;
+ common_cflags="$common_cflags -pthread";
+ asppflags="$asppflags -pthread";;
esac
inf "Options for linking with POSIX threads: $pthread_link"
if sh ./hasgot $pthread_link sigwait; then
else
pthread_link=""
fi
-echo "PTHREAD_LINK=$pthread_link" >> Makefile
-echo "PTHREAD_CAML_LINK=$pthread_caml_link" >> Makefile
+config PTHREAD_LINK "$pthread_link"
+config PTHREAD_CAML_LINK "$pthread_caml_link"
# Determine if the bytecode thread library is supported
# Look for BFD library
-if sh ./hasgot -DPACKAGE=ocaml -i bfd.h && \
- sh ./hasgot -DPACKAGE=ocaml -lbfd -ldl -liberty -lz bfd_openr; then
+if $shared_libraries_supported && ./hasgot -DPACKAGE=ocaml -i bfd.h ; then
inf "BFD library found."
- echo "#define HAS_LIBBFD" >> s.h
- echo "LIBBFD_LINK=-lbfd -ldl -liberty -lz" >> Makefile
+ if sh ./hasgot -DPACKAGE=ocaml -lbfd bfd_openr; then
+ LIBBFD_LINK="-lbfd"
+ inf "BFD links with $LIBBFD_LINK"
+ echo "#define HAS_LIBBFD" >> s.h
+ elif sh ./hasgot -DPACKAGE=ocaml -lbfd -ldl bfd_openr; then
+ LIBBFD_LINK="-lbfd -ldl"
+ inf "BFD links with $LIBBFD_LINK"
+ echo "#define HAS_LIBBFD" >> s.h
+ elif sh ./hasgot -DPACKAGE=ocaml -lbfd -ldl -liberty bfd_openr; then
+ LIBBFD_LINK="-lbfd -ldl -liberty"
+ inf "BFD links with $LIBBFD_LINK"
+ echo "#define HAS_LIBBFD" >> s.h
+ elif sh ./hasgot -DPACKAGE=ocaml -lbfd -ldl -liberty -lz bfd_openr; then
+ LIBBFD_LINK="-lbfd -ldl -liberty -lz"
+ inf "BFD links with $LIBBFD_LINK"
+ echo "#define HAS_LIBBFD" >> s.h
+ else
+ wrn "Could not determine link options for the BFD library"
+ LIBBFD_LINK=
+ fi
+ echo "LIBBFD_LINK=$LIBBFD_LINK" >> Makefile
echo LIBBFD_INCLUDE= >>Makefile
elif sh ./hasgot -DPACKAGE=ocaml -I/opt/local/include -i bfd.h && \
sh ./hasgot -DPACKAGE=ocaml -L/opt/local/lib -lbfd -ldl \
if test "$with_frame_pointers" = "true"; then
case "$target,$cc" in
x86_64-*-linux*,gcc*|x86_64-*-linux*,clang*)
- nativecccompopts="$nativecccompopts -g -fno-omit-frame-pointer"
- bytecccompopts="$bytecccompopts -g -fno-omit-frame-pointer"
- nativecclinkopts="$nativecclinkopts -g"
+ common_cflags="$common_cflags -g -fno-omit-frame-pointer"
echo "#define WITH_FRAME_POINTERS" >> m.h
;;
*) err "Unsupported architecture with frame pointers";;
if $spacetime_supported; then
echo "Spacetime profiling will be available."
echo "#define WITH_SPACETIME" >> m.h
+ if $enable_call_counts; then
+ echo "#define ENABLE_CALL_COUNTS" >> m.h
+ fi
if $disable_libunwind; then
has_libunwind=no
libunwind_available=false
fi
fi
else
- echo "Spacetime profiling is not available on 32-bit platforms."
+ echo "Spacetime profiling unavailable: it needs a 64-bit platform with"
+ echo " support for the native code OCaml compiler."
with_spacetime=false
libunwind_available=false
has_libunwind=no
fi
if $with_fpic; then
- bytecccompopts="$bytecccompopts $sharedcccompopts"
- nativecccompopts="$nativecccompopts $sharedcccompopts"
+ common_cflags="$common_cflags $sharedcccompopts"
aspp="$aspp $sharedcccompopts"
fi
echo "#define CAML_WITH_FPIC" >> m.h
fi
+if $force_safe_string; then
+ echo "#define CAML_SAFE_STRING" >> m.h
+fi
+
+if $flat_float_array; then
+ echo "#define FLAT_FLOAT_ARRAY" >> m.h
+fi
+
# Finish generated files
cclibs="$cclibs $mathlib"
-echo "BYTECC=$bytecc $bytecccompopts" >> Makefile
-echo "BYTECODE_C_COMPILER=$bytecc $bytecccompopts $sharedcccompopts" \
- >> Makefile
-echo "BYTECCCOMPOPTS=$byteccprivatecompopts" >> Makefile
-echo "BYTECCLINKOPTS=$bytecclinkopts" >> Makefile
-echo "BYTECCLIBS=$cclibs $dllib $curseslibs $pthread_link \
- $instrumented_runtime_libs" >> Makefile
-echo "BYTECCRPATH=$byteccrpath" >> Makefile
-echo "EXE=$exe" >> Makefile
-echo "SUPPORTS_SHARED_LIBRARIES=$shared_libraries_supported" >> Makefile
-echo "SHAREDCCCOMPOPTS=$sharedcccompopts" >> Makefile
-echo "MKSHAREDLIBRPATH=$mksharedlibrpath" >> Makefile
-echo "NATDYNLINKOPTS=$natdynlinkopts" >> Makefile
+config CC "$cc"
+config CPP "$cpp"
+config CFLAGS "$common_cflags $internal_cflags"
+config CPPFLAGS "$common_cppflags $internal_cppflags"
+config OCAMLC_CFLAGS "$common_cflags $sharedcccompopts"
+config OCAMLC_CPPFLAGS "$common_cppflags"
+config LDFLAGS "$ldflags"
+config BYTECCLIBS "$cclibs $dllib $curseslibs $pthread_link \
+ $instrumented_runtime_libs"
+config RPATH "$rpath"
+config EXE "$exe"
+config EMPTY ""
+config OUTPUTEXE "-o \$(EMPTY)"
+config SUPPORTS_SHARED_LIBRARIES "$shared_libraries_supported"
+config SHAREDCCCOMPOPTS "$sharedcccompopts"
+config MKSHAREDLIBRPATH "$mksharedlibrpath"
+config NATDYNLINKOPTS "$natdynlinkopts"
cat >> Makefile <<EOF
SYSLIB=-l\$(1)
#ml let syslib x = "-l"^x;;
#ml Printf.sprintf "${TOOLPREF}ar rc %s %s %s; ${TOOLPREF}ranlib %s"
#ml out opts files out;;
EOF
-echo "ARCH=$arch" >> Makefile
-echo "MODEL=$model" >> Makefile
-echo "SYSTEM=$system" >> Makefile
-echo "NATIVECC=$nativecc $nativecccompopts" >> Makefile
-echo "NATIVE_C_COMPILER=$nativecc $nativecccompopts" >> Makefile
-echo "NATIVECCCOMPOPTS=$nativeccprivatecompopts" >> Makefile
-echo "NATIVECCPROFOPTS=$nativeccprofopts" >> Makefile
-echo "NATIVECCLINKOPTS=$nativecclinkopts" >> Makefile
-echo "NATIVECCRPATH=$nativeccrpath" >> Makefile
-echo "NATIVECCLIBS=$cclibs $dllib" >> Makefile
-echo "ASM=$as" >> Makefile
-echo "ASPP=$aspp" >> Makefile
-echo "ASPPPROFFLAGS=$asppprofflags" >> Makefile
-echo "PROFILING=$profiling" >> Makefile
-echo "DYNLINKOPTS=$dllib" >> Makefile
-echo "OTHERLIBRARIES=$otherlibraries" >> Makefile
-echo "CC_PROFILE=$cc_profile" >> Makefile
-echo "SYSTHREAD_SUPPORT=$systhread_support" >> Makefile
-echo "PACKLD=$partialld $nativecclinkopts -o\\ " >> Makefile
-echo "IFLEXDIR=$iflexdir" >> Makefile
-echo "O=o" >> Makefile
-echo "A=a" >> Makefile
-echo "SO=$SO" >> Makefile
-echo "EXT_OBJ=.o" >> Makefile
-echo "EXT_ASM=.s" >> Makefile
-echo "EXT_LIB=.a" >> Makefile
-echo "EXT_DLL=.$SO" >> Makefile
-echo "EXTRALIBS=" >> Makefile
-echo "CCOMPTYPE=cc" >> Makefile
-echo "TOOLCHAIN=$TOOLCHAIN" >> Makefile
-echo "NATDYNLINK=$natdynlink" >> Makefile
-echo "CMXS=$cmxs" >> Makefile
-echo "MKEXE=$mkexe" >> Makefile
-echo "MKEXEDEBUGFLAG=$mkexedebugflag" >> Makefile
-echo "MKDLL=$mksharedlib" >> Makefile
-echo "MKMAINDLL=$mkmaindll" >> Makefile
-echo "RUNTIMED=${debugruntime}" >>Makefile
-echo "RUNTIMEI=${with_instrumented_runtime}" >>Makefile
-echo "WITH_DEBUGGER=${with_debugger}" >>Makefile
-echo "WITH_OCAMLDOC=${with_ocamldoc}" >>Makefile
-echo "ASM_CFI_SUPPORTED=$asm_cfi_supported" >> Makefile
-echo "WITH_FRAME_POINTERS=$with_frame_pointers" >> Makefile
-echo "WITH_SPACETIME=$with_spacetime" >> Makefile
-echo "WITH_PROFINFO=$with_profinfo" >> Makefile
-echo "LIBUNWIND_AVAILABLE=$libunwind_available" >> Makefile
-echo "LIBUNWIND_INCLUDE_FLAGS=$libunwind_include" >> Makefile
-echo "LIBUNWIND_LINK_FLAGS=$libunwind_lib" >> Makefile
-echo "PROFINFO_WIDTH=$profinfo_width" >> Makefile
-echo "WITH_CPLUGINS=$with_cplugins" >> Makefile
-echo "WITH_FPIC=$with_fpic" >> Makefile
-echo "TARGET=$target" >> Makefile
-echo "HOST=$host" >> Makefile
+config ARCH "$arch"
+config MODEL "$model"
+config SYSTEM "$system"
+config OCAMLOPT_CFLAGS "$common_cflags"
+config OCAMLOPT_CPPFLAGS "$common_cppflags"
+config NATIVECCPROFOPTS "$nativeccprofopts"
+config NATIVECCLIBS "$cclibs $dllib"
+config ASM "$as"
+config ASPP "$aspp"
+config ASPPPROFFLAGS "$asppprofflags"
+config PROFILING "$profiling"
+config DYNLINKOPTS "$dllib"
+config OTHERLIBRARIES "$otherlibraries"
+config CC_PROFILE "$cc_profile"
+config SYSTHREAD_SUPPORT "$systhread_support"
+config PACKLD "$partialld -o\\ \$(EMPTY)"
+config IFLEXDIR "$iflexdir"
+config O "o"
+config A "a"
+config SO "$SO"
+config EXT_OBJ ".o"
+config OUTPUTOBJ "-o \$(EMPTY)"
+config EXT_ASM ".s"
+config EXT_LIB ".a"
+config EXT_DLL ".$SO"
+config EXTRALIBS ""
+config CCOMPTYPE "cc"
+config TOOLCHAIN "$TOOLCHAIN"
+config NATDYNLINK "$natdynlink"
+config CMXS "$cmxs"
+config MKEXE "$mkexe"
+config MKEXEDEBUGFLAG "$mkexedebugflag"
+config MKDLL "$mksharedlib"
+config MKMAINDLL "$mkmaindll"
+config RUNTIMED "${debugruntime}"
+config RUNTIMEI "${with_instrumented_runtime}"
+config WITH_DEBUGGER "${with_debugger}"
+config WITH_OCAMLDOC "${with_ocamldoc}"
+config ASM_CFI_SUPPORTED "$asm_cfi_supported"
+config WITH_FRAME_POINTERS "$with_frame_pointers"
+config WITH_SPACETIME "$with_spacetime"
+config ENABLE_CALL_COUNTS "$enable_call_counts"
+config WITH_PROFINFO "$with_profinfo"
+config LIBUNWIND_AVAILABLE "$libunwind_available"
+config LIBUNWIND_INCLUDE_FLAGS "$libunwind_include"
+config LIBUNWIND_LINK_FLAGS "$libunwind_lib"
+config PROFINFO_WIDTH "$profinfo_width"
+config WITH_CPLUGINS "$with_cplugins"
+config WITH_FPIC "$with_fpic"
+config TARGET "$target"
+config HOST "$host"
if [ "$ostype" = Cygwin ]; then
- echo "DIFF=diff -q --strip-trailing-cr" >>Makefile
+ config DIFF "diff -q --strip-trailing-cr"
fi
-echo "FLAMBDA=$flambda" >> Makefile
-echo "SAFE_STRING=$safe_string" >> Makefile
-echo "AFL_INSTRUMENT=$afl_instrument" >> Makefile
-echo "MAX_TESTSUITE_DIR_RETRIES=$max_testsuite_dir_retries" >> Makefile
+config FLAMBDA "$flambda"
+config FORCE_SAFE_STRING "$force_safe_string"
+config DEFAULT_SAFE_STRING "$default_safe_string"
+config WINDOWS_UNICODE "0"
+config AFL_INSTRUMENT "$afl_instrument"
+config MAX_TESTSUITE_DIR_RETRIES "$max_testsuite_dir_retries"
+config FLAT_FLOAT_ARRAY "$flat_float_array"
rm -f tst hasgot.c
-rm -f ../m.h ../s.h ../Makefile
-mv m.h s.h Makefile ..
+rm -f ../../byterun/caml/m.h ../../byterun/caml/s.h ../Makefile
+mv m.h s.h ../../byterun/caml/
+mv Makefile ..
# Print a summary
inf "Directories where OCaml will be installed:"
inf " binaries.................. $bindir"
inf " standard library.......... $libdir"
-inf " manual pages.............. $mandir (with extension .$manext)"
+inf " manual pages.............. $mandir (with extension .$programs_man_section)"
inf "Configuration for the bytecode compiler:"
-inf " C compiler used........... $bytecc"
-inf " options for compiling..... $bytecccompopts"
-inf " options for linking....... $bytecclinkopts $cclibs $dllib" \
+inf " C compiler used........... $cc"
+inf " options for compiling..... $common_cflags"
+inf " options for linking....... $ldflags $cclibs $dllib" \
"$curseslibs $pthread_link"
if $shared_libraries_supported; then
inf " shared libraries are supported"
-inf " options for compiling..... $sharedcccompopts $bytecccompopts"
+inf " options for compiling..... $sharedcccompopts $common_cflags"
inf " command for building...... $mksharedlib -o lib.so" \
"$mksharedlibrpath/a/path objs"
else
if test "$system" = "unknown"; then : ; else
inf " OS variant................ $system"
fi
- inf " C compiler used........... $nativecc"
- inf " options for compiling..... $nativecccompopts"
- inf " options for linking....... $nativecclinkopts $cclibs"
+ inf " C compiler used........... $cc"
+ inf " options for compiling..... $common_cflags"
+ inf " options for linking....... $cclibs"
inf " assembler ................ $as"
inf " preprocessed assembler ... $aspp"
if test "$asm_cfi_supported" = "true"; then
fi
if $with_spacetime; then
inf " spacetime profiling....... yes"
+ if test "$with_spacetime_call_counts" = "true"; then
+ inf " ... with call counts.... yes"
+ else
+ inf " ... with call counts.... no"
+ fi
inf " ... with libunwind...... $has_libunwind"
else
inf " spacetime profiling....... no"
else
inf " using flambda middle-end . no"
fi
- if test "$safe_string" = "true"; then
- inf " safe strings ............. yes"
+ if $force_safe_string; then
+ inf " force safe strings ............. yes"
+ else
+ inf " force safe strings ............. no"
+ if $default_safe_string; then
+ inf " (-safe-string is the default per-file option)"
+ else
+ inf " (-unsafe-string is the default per-file option)"
+ fi
+ fi
+ if $flat_float_array; then
+ inf " flat float arrays ........ yes"
else
- inf " safe strings ............. no"
+ inf " flat float arrays ........ no"
fi
if test "$afl_instrument" = "true"; then
inf " afl-fuzz always enabled .. yes"
inf "Additional libraries supported:"
inf " $otherlibraries"
-inf "Configuration for the \"num\" library:"
-inf " target architecture ...... $bng_arch (asm level $bng_asm_level)"
-
if $has_graph; then
inf "Configuration for the \"graph\" library:"
inf " options for compiling .... $x11_include"
set_breakpoint pos)
pos
-(* Ensure the current version in installed in current checkpoint. *)
+(* Ensure the current version is installed in current checkpoint. *)
let update_breakpoints () =
if !debug_breakpoints then begin
prerr_string "Updating breakpoints... ";
(*** Set and remove breakpoints ***)
-(* Ensure the current version in installed in current checkpoint. *)
+(* Ensure the current version is installed in current checkpoint. *)
val update_breakpoints : unit -> unit
(* Execute given function with no breakpoint in current checkpoint. *)
struct
type t = Remote of string | Local of Obj.t
+ let repr x = Local (Obj.repr x)
+
let obj = function
| Local obj -> Obj.obj obj
| Remote v ->
Local(Obj.repr floatbuf)
end
+ let double_field v n =
+ match v with
+ | Local obj -> Obj.double_field obj n
+ | Remote v ->
+ output_char !conn.io_out 'F';
+ output_remote_value !conn.io_out v;
+ output_binary_int !conn.io_out n;
+ flush !conn.io_out;
+ if input_byte !conn.io_in = 0 then
+ raise Marshalling_error
+ else begin
+ let buf = really_input_string !conn.io_in 8 in
+ let floatbuf = float n (* force allocation of a new float *) in
+ String.unsafe_blit buf 0 (Obj.magic floatbuf) 0 8;
+ floatbuf
+ end
+
+ let double_array_tag = Obj.double_array_tag
+
let of_int n =
Local(Obj.repr n)
sig
type t
+ val repr : 'a -> t
val obj : t -> 'a
val is_block : t -> bool
val tag : t -> int
val size : t -> int
val field : t -> int -> t
+ val double_field : t -> int -> float
+ val double_array_tag : int
val same : t -> t -> bool
val of_int : int -> t
"Win32" -> false
| _ -> true)
-(*** Environment variables for debugee. ***)
+(*** Environment variables for debuggee. ***)
let environment = ref []
val history_size : int ref
val load_path_for : (string, string list) Hashtbl.t
-(*** Time travel paramaters. ***)
+(*** Time travel parameters. ***)
val checkpoint_big_step : int64 ref
val checkpoint_small_step : int64 ref
val checkpoint_max_count : int ref
val make_checkpoints : bool ref
-(*** Environment variables for debugee. ***)
+(*** Environment variables for debuggee. ***)
val environment : (string * string) list ref
(* *)
(* OCaml *)
(* *)
-(* Damien Doligez, projet Moscova, INRIA Rocqencourt *)
+(* Damien Doligez, projet Moscova, INRIA Rocquencourt *)
(* *)
(* Copyright 2002 Institut National de Recherche en Informatique et *)
(* en Automatique. *)
(* *)
(* OCaml *)
(* *)
-(* Damien Doligez, projet Moscova, INRIA Rocqencourt *)
+(* Damien Doligez, projet Moscova, INRIA Rocquencourt *)
(* *)
(* Copyright 2002 Institut National de Recherche en Informatique et *)
(* en Automatique. *)
(* Install, remove a printer (as in toplevel/topdirs) *)
(* since 4.00, "topdirs.cmi" is not in the same directory as the standard
- libray, so we load it beforehand as it cannot be found in the search path. *)
+ library, so we load it beforehand as it cannot be found in the search path. *)
let () =
let compiler_libs =
Filename.concat Config.standard_library "compiler-libs" in
| (_, []) -> []
| (n, (a::l)) -> a::(list_truncate (n - 1) l)
-(* Separe the `n' first elements of `l' and the others *)
+(* Separate the `n' first elements of `l' and the others *)
(* ### n list -> (first, last) *)
let rec list_truncate2 =
fun
(* ### n l -> l' *)
val list_truncate : int -> 'a list -> 'a list
-(* Separe the `n' first elements of `l' and the others. *)
+(* Separate the `n' first elements of `l' and the others. *)
(* ### n list -> (first, last) *)
val list_truncate2 : int -> 'a list -> 'a list * 'a list
(Filename.quote !program_name)
!arguments)
-(* Excute the program directly *)
+(* Execute the program directly *)
let exec_direct =
generic_exec
(function () ->
(*** Kill program. ***)
val kill_program : unit -> unit
-(* Ask wether to kill the program or not. *)
+(* Ask whether to kill the program or not. *)
(* If yes, kill it. *)
(* Return true iff the program has been killed. *)
val ask_kill_program : unit -> bool
(pos.Lexing.pos_cnum - pos.Lexing.pos_bol + 1)
(* Display information about the current frame. *)
-(* --- `select frame' must have succeded before calling this function. *)
+(* --- `select frame' must have succeeded before calling this function. *)
let show_current_frame ppf selected =
match !selected_event with
| None ->
val show_current_event : formatter -> unit;;
(* Display information about the current frame. *)
-(* --- `select frame' must have succeded before calling this function. *)
+(* --- `select frame' must have succeeded before calling this function. *)
val show_current_frame : formatter -> bool -> unit;;
(* Display short information about one frame. *)
let all_events_by_module =
(Hashtbl.create 17 : (string, debug_event list) Hashtbl.t)
+let partition_modules evl =
+ let rec partition_modules' ev evl =
+ match evl with
+ [] -> [ev],[]
+ | ev'::evl ->
+ let evl,evll = partition_modules' ev' evl in
+ if ev.ev_module = ev'.ev_module then ev::evl,evll else [ev],evl::evll
+ in
+ match evl with
+ [] -> []
+ | ev::evl -> let evl,evll = partition_modules' ev evl in evl::evll
+
let relocate_event orig ev =
ev.ev_pos <- orig + ev.ev_pos;
match ev.ev_repr with
let evl = (input_value ic : debug_event list) in
(* Relocate events in event list *)
List.iter (relocate_event orig) evl;
- eventlists := evl :: !eventlists;
+ let evll = partition_modules evl in
+ eventlists := evll @ !eventlists;
dirs :=
List.fold_left (fun s e -> StringSet.add e s) !dirs (input_value ic)
done;
(*** Cleaning the checkpoint list. ***)
-(* Separe checkpoints before (<=) and after (>) `t'. *)
+(* Separate checkpoints before (<=) and after (>) `t'. *)
(* ### t checkpoints -> (after, before) *)
let cut t =
let rec cut_t =
let (after, before) = cut (t0 -- _1) l in
after::(cut2_t0 t before)
-(* Separe first elements and last element of a list of checkpoint. *)
+(* Separate first elements and last element of a list of checkpoints. *)
let chk_merge2 cont =
let rec chk_merge2_cont =
function
(accepted, a::rejected)
in chk_merge2_cont
-(* Separe the checkpoint list. *)
+(* Separate the checkpoint list. *)
(* ### list -> accepted * rejected *)
let rec chk_merge =
function
in find !checkpoints
(* Make a copy of the current checkpoint and clean the checkpoint list. *)
-(* --- The new checkpoint in not put in the list. *)
+(* --- The new checkpoint is not put in the list. *)
let duplicate_current_checkpoint () =
let checkpoint = !current_checkpoint in
if not checkpoint.c_valid then
if not !interrupted then
run ()
-(* Run backward the program form current time. *)
+(* Run the program backward from current time. *)
(* Stop at the first breakpoint, or at the beginning of the program. *)
let back_run () =
if current_time () > _0 then
back_to _0 (current_time ())
(* Step in any direction. *)
-(* Stop at the first brakpoint, or after `duration' steps. *)
+(* Stop at the first breakpoint, or after `duration' steps. *)
let step duration =
if duration >= _0 then
step_forward duration
| "can-discard" ->
can_discard := v ::!can_discard
- | "timings" -> set "timings" [ print_timings ] v
+ | "timings" | "profile" ->
+ let if_on = if name = "timings" then [ `Time ] else Profile.all_columns in
+ profile_columns := if check_bool ppf name v then if_on else []
| "plugin" -> !load_plugin v
let tool_name = "ocamlc"
let interface ppf sourcefile outputprefix =
- Compmisc.init_path false;
- let modulename = module_of_filename ppf sourcefile outputprefix in
- Env.set_unit_name modulename;
- let initial_env = Compmisc.initial_env () in
- let ast = Pparse.parse_interface ~tool_name ppf sourcefile in
+ Profile.record_call sourcefile (fun () ->
+ Compmisc.init_path false;
+ let modulename = module_of_filename ppf sourcefile outputprefix in
+ Env.set_unit_name modulename;
+ let initial_env = Compmisc.initial_env () in
+ let ast = Pparse.parse_interface ~tool_name ppf sourcefile in
- if !Clflags.dump_parsetree then fprintf ppf "%a@." Printast.interface ast;
- if !Clflags.dump_source then fprintf ppf "%a@." Pprintast.signature ast;
- Timings.(time_call (Typing sourcefile)) (fun () ->
- let tsg = Typemod.type_interface sourcefile initial_env ast in
- if !Clflags.dump_typedtree then fprintf ppf "%a@." Printtyped.interface tsg;
- let sg = tsg.sig_type in
- if !Clflags.print_types then
- Printtyp.wrap_printing_env initial_env (fun () ->
- fprintf std_formatter "%a@."
- Printtyp.signature (Typemod.simplify_signature sg));
- ignore (Includemod.signatures initial_env sg sg);
- Typecore.force_delayed_checks ();
- Warnings.check_fatal ();
- if not !Clflags.print_types then begin
- let deprecated = Builtin_attributes.deprecated_of_sig ast in
- let sg =
- Env.save_signature ~deprecated sg modulename (outputprefix ^ ".cmi")
- in
- Typemod.save_signature modulename tsg outputprefix sourcefile
- initial_env sg ;
- end
+ if !Clflags.dump_parsetree then fprintf ppf "%a@." Printast.interface ast;
+ if !Clflags.dump_source then fprintf ppf "%a@." Pprintast.signature ast;
+ Profile.(record_call typing) (fun () ->
+ let tsg = Typemod.type_interface sourcefile initial_env ast in
+ if !Clflags.dump_typedtree then fprintf ppf "%a@." Printtyped.interface tsg;
+ let sg = tsg.sig_type in
+ if !Clflags.print_types then
+ Printtyp.wrap_printing_env initial_env (fun () ->
+ fprintf std_formatter "%a@."
+ Printtyp.signature (Typemod.simplify_signature sg));
+ ignore (Includemod.signatures initial_env sg sg);
+ Typecore.force_delayed_checks ();
+ Warnings.check_fatal ();
+ if not !Clflags.print_types then begin
+ let deprecated = Builtin_attributes.deprecated_of_sig ast in
+ let sg =
+ Env.save_signature ~deprecated sg modulename (outputprefix ^ ".cmi")
+ in
+ Typemod.save_signature modulename tsg outputprefix sourcefile
+ initial_env sg ;
+ end
+ )
)
(* Compile a .ml file *)
let (++) x f = f x
let implementation ppf sourcefile outputprefix =
- Compmisc.init_path false;
- let modulename = module_of_filename ppf sourcefile outputprefix in
- Env.set_unit_name modulename;
- let env = Compmisc.initial_env() in
- try
- let (typedtree, coercion) =
- Pparse.parse_implementation ~tool_name ppf sourcefile
- ++ print_if ppf Clflags.dump_parsetree Printast.implementation
- ++ print_if ppf Clflags.dump_source Pprintast.structure
- ++ Timings.(time (Typing sourcefile))
- (Typemod.type_implementation sourcefile outputprefix modulename env)
- ++ print_if ppf Clflags.dump_typedtree
- Printtyped.implementation_with_coercion
- in
- if !Clflags.print_types then begin
- Warnings.check_fatal ();
- Stypes.dump (Some (outputprefix ^ ".annot"))
- end else begin
- let bytecode, required_globals =
- (typedtree, coercion)
- ++ Timings.(time (Transl sourcefile))
- (Translmod.transl_implementation modulename)
- ++ Timings.(accumulate_time (Generate sourcefile))
- (fun { Lambda.code = lambda; required_globals } ->
- print_if ppf Clflags.dump_rawlambda Printlambda.lambda lambda
- ++ Simplif.simplify_lambda sourcefile
- ++ print_if ppf Clflags.dump_lambda Printlambda.lambda
- ++ Bytegen.compile_implementation modulename
- ++ print_if ppf Clflags.dump_instr Printinstr.instrlist
- ++ fun bytecode -> bytecode, required_globals)
- in
- let objfile = outputprefix ^ ".cmo" in
- let oc = open_out_bin objfile in
- try
- bytecode
- ++ Timings.(accumulate_time (Generate sourcefile))
- (Emitcode.to_file oc modulename objfile ~required_globals);
+ Profile.record_call sourcefile (fun () ->
+ Compmisc.init_path false;
+ let modulename = module_of_filename ppf sourcefile outputprefix in
+ Env.set_unit_name modulename;
+ let env = Compmisc.initial_env() in
+ try
+ let (typedtree, coercion) =
+ Pparse.parse_implementation ~tool_name ppf sourcefile
+ ++ print_if ppf Clflags.dump_parsetree Printast.implementation
+ ++ print_if ppf Clflags.dump_source Pprintast.structure
+ ++ Profile.(record typing)
+ (Typemod.type_implementation sourcefile outputprefix modulename env)
+ ++ print_if ppf Clflags.dump_typedtree
+ Printtyped.implementation_with_coercion
+ in
+ if !Clflags.print_types then begin
Warnings.check_fatal ();
- close_out oc;
Stypes.dump (Some (outputprefix ^ ".annot"))
- with x ->
- close_out oc;
- remove_file objfile;
- raise x
- end
- with x ->
- Stypes.dump (Some (outputprefix ^ ".annot"));
- raise x
+ end else begin
+ let bytecode, required_globals =
+ (typedtree, coercion)
+ ++ Profile.(record transl)
+ (Translmod.transl_implementation modulename)
+ ++ Profile.(record ~accumulate:true generate)
+ (fun { Lambda.code = lambda; required_globals } ->
+ print_if ppf Clflags.dump_rawlambda Printlambda.lambda lambda
+ ++ Simplif.simplify_lambda sourcefile
+ ++ print_if ppf Clflags.dump_lambda Printlambda.lambda
+ ++ Bytegen.compile_implementation modulename
+ ++ print_if ppf Clflags.dump_instr Printinstr.instrlist
+ ++ fun bytecode -> bytecode, required_globals)
+ in
+ let objfile = outputprefix ^ ".cmo" in
+ let oc = open_out_bin objfile in
+ try
+ bytecode
+ ++ Profile.(record ~accumulate:true generate)
+ (Emitcode.to_file oc modulename objfile ~required_globals);
+ Warnings.check_fatal ();
+ close_out oc;
+ Stypes.dump (Some (outputprefix ^ ".annot"))
+ with x ->
+ close_out oc;
+ remove_file objfile;
+ raise x
+ end
+ with x ->
+ Stypes.dump (Some (outputprefix ^ ".annot"));
+ raise x
+ )
let initial_env () =
Ident.reinit();
let initial =
- if !Clflags.unsafe_string then Env.initial_unsafe_string
+ if Config.safe_string then Env.initial_safe_string
+ else if !Clflags.unsafe_string then Env.initial_unsafe_string
else Env.initial_safe_string
in
let env =
let _drawlambda = set dump_rawlambda
let _dlambda = set dump_lambda
let _dinstr = set dump_instr
- let _dtimings = set print_timings
+ let _dtimings () = profile_columns := [ `Time ]
+ let _dprofile () = profile_columns := Profile.all_columns
let _args = Arg.read_arg
let _args0 = Arg.read_arg0
let main () =
Clflags.add_arguments __LOC__ Options.list;
+ Clflags.add_arguments __LOC__
+ ["-depend", Arg.Unit Makedepend.main_from_option,
+ "<options> Compute dependencies (use 'ocamlc -depend -help' for details)"];
try
readenv ppf Before_args;
Clflags.parse_arguments anonymous usage;
Location.report_exception ppf x;
exit 2
-let _ =
- Timings.(time All) main ();
- if !Clflags.print_timings then Timings.print Format.std_formatter;
+let () =
+ main ();
+ Profile.print Format.std_formatter !Clflags.profile_columns;
exit 0
;;
let mk_keep_locs f =
- "-keep-locs", Arg.Unit f, " Keep locations in .cmi files"
+ "-keep-locs", Arg.Unit f, " Keep locations in .cmi files (default)"
;;
let mk_no_keep_locs f =
- "-no-keep-locs", Arg.Unit f, " Do not keep locations in .cmi files (default)"
+ "-no-keep-locs", Arg.Unit f, " Do not keep locations in .cmi files"
;;
let mk_labels f =
"-linkall", Arg.Unit f, " Link all modules, even unused ones"
;;
+let mk_linscan f =
+ "-linscan", Arg.Unit f, " Use the linear scan register allocator"
+;;
+
let mk_make_runtime f =
"-make-runtime", Arg.Unit f,
" Build a runtime system with given C objects and libraries"
let mk_safe_string f =
"-safe-string", Arg.Unit f,
- if Config.safe_string then " Make strings immutable (default)"
+ if Config.safe_string then " (was set when configuring the compiler)"
+ else if Config.default_safe_string then " Make strings immutable (default)"
else " Make strings immutable"
;;
;;
let mk_dtimings f =
- "-dtimings", Arg.Unit f, " Print timings"
+ "-dtimings", Arg.Unit f, " Print timings information for each pass";
+;;
+
+let mk_dprofile f =
+ "-dprofile", Arg.Unit f, Profile.options_doc
;;
let mk_unbox_closures f =
let mk_unsafe_string f =
if Config.safe_string then
let err () =
- raise (Arg.Bad "OCaml has been configured with -safe-string: \
+ raise (Arg.Bad "OCaml has been configured with -force-safe-string: \
-unsafe-string is not available")
in
"-unsafe-string", Arg.Unit err, " (option not available)"
+ else if Config.default_safe_string then
+ "-unsafe-string", Arg.Unit f, " Make strings mutable"
else
"-unsafe-string", Arg.Unit f, " Make strings mutable (default)"
;;
"-dlive", Arg.Unit f, " (undocumented)"
;;
+let mk_davail f =
+ "-davail", Arg.Unit f, " Print register availability info when printing \
+ liveness"
+;;
+
+let mk_drunavail f =
+ "-drunavail", Arg.Unit f, " Run register availability pass (for testing \
+ only; needs -g)"
+;;
+
let mk_dspill f =
"-dspill", Arg.Unit f, " (undocumented)"
;;
"-dlinear", Arg.Unit f, " (undocumented)"
;;
+let mk_dinterval f =
+ "-dinterval", Arg.Unit f, " (undocumented)"
+;;
+
let mk_dstartup f =
"-dstartup", Arg.Unit f, " (undocumented)"
;;
val _nopervasives : unit -> unit
val _dtimings : unit -> unit
+ val _dprofile : unit -> unit
val _args: string -> string array
val _args0: string -> string array
val _no_version : unit -> unit
val _noprompt : unit -> unit
val _nopromptcont : unit -> unit
- val _plugin : string -> unit
val _stdin : unit -> unit
val _args : string -> string array
val _args0 : string -> string array
val _dcombine : unit -> unit
val _dcse : unit -> unit
val _dlive : unit -> unit
+ val _davail : unit -> unit
+ val _drunavail : unit -> unit
val _dspill : unit -> unit
val _dsplit : unit -> unit
val _dinterf : unit -> unit
include Common_options
include Compiler_options
include Optcommon_options
+ val _linscan : unit -> unit
val _no_float_const_prop : unit -> unit
val _nodynlink : unit -> unit
val _p : unit -> unit
val _shared : unit -> unit
val _afl_instrument : unit -> unit
val _afl_inst_ratio : int -> unit
+ val _dinterval : unit -> unit
end;;
module type Opttop_options = sig
mk_dlambda F._dlambda;
mk_dinstr F._dinstr;
mk_dtimings F._dtimings;
+ mk_dprofile F._dprofile;
mk_args F._args;
mk_args0 F._args0;
mk_nostdlib F._nostdlib;
mk_open F._open;
mk_ppx F._ppx;
- mk_plugin F._plugin;
mk_principal F._principal;
mk_no_principal F._no_principal;
mk_rectypes F._rectypes;
mk_inline_max_depth F._inline_max_depth;
mk_alias_deps F._alias_deps;
mk_no_alias_deps F._no_alias_deps;
+ mk_linscan F._linscan;
mk_app_funct F._app_funct;
mk_no_app_funct F._no_app_funct;
mk_no_float_const_prop F._no_float_const_prop;
mk_dcombine F._dcombine;
mk_dcse F._dcse;
mk_dlive F._dlive;
+ mk_davail F._davail;
+ mk_drunavail F._drunavail;
mk_dspill F._dspill;
mk_dsplit F._dsplit;
mk_dinterf F._dinterf;
mk_dreload F._dreload;
mk_dscheduling F._dscheduling;
mk_dlinear F._dlinear;
+ mk_dinterval F._dinterval;
mk_dstartup F._dstartup;
mk_dtimings F._dtimings;
+ mk_dprofile F._dprofile;
mk_dump_pass F._dump_pass;
mk_args F._args;
mk_o2 F._o2;
mk_o3 F._o3;
mk_open F._open;
- mk_plugin F._plugin;
mk_ppx F._ppx;
mk_principal F._principal;
mk_no_principal F._no_principal;
mk_dcombine F._dcombine;
mk_dcse F._dcse;
mk_dlive F._dlive;
+ mk_davail F._davail;
+ mk_drunavail F._drunavail;
mk_dspill F._dspill;
mk_dsplit F._dsplit;
mk_dinterf F._dinterf;
val _nopervasives : unit -> unit
val _dtimings : unit -> unit
+ val _dprofile : unit -> unit
val _args: string -> string array
val _args0: string -> string array
val _no_version : unit -> unit
val _noprompt : unit -> unit
val _nopromptcont : unit -> unit
- val _plugin : string -> unit
val _stdin : unit -> unit
val _args: string -> string array
val _args0: string -> string array
val _dcombine : unit -> unit
val _dcse : unit -> unit
val _dlive : unit -> unit
+ val _davail : unit -> unit
+ val _drunavail : unit -> unit
val _dspill : unit -> unit
val _dsplit : unit -> unit
val _dinterf : unit -> unit
include Common_options
include Compiler_options
include Optcommon_options
+ val _linscan : unit -> unit
val _no_float_const_prop : unit -> unit
val _nodynlink : unit -> unit
val _p : unit -> unit
val _shared : unit -> unit
val _afl_instrument : unit -> unit
val _afl_inst_ratio : int -> unit
+ val _dinterval : unit -> unit
end;;
module type Opttop_options = sig
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 1999 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+open Compenv
+open Parsetree
+module StringMap = Depend.StringMap
+
+let ppf = Format.err_formatter
+(* Print the dependencies *)
+
+type file_kind = ML | MLI;;
+
+let load_path = ref ([] : (string * string array) list)
+let ml_synonyms = ref [".ml"]
+let mli_synonyms = ref [".mli"]
+let shared = ref false
+let native_only = ref false
+let bytecode_only = ref false
+let error_occurred = ref false
+let raw_dependencies = ref false
+let sort_files = ref false
+let all_dependencies = ref false
+let one_line = ref false
+let files =
+ ref ([] : (string * file_kind * Depend.StringSet.t * string list) list)
+let allow_approximation = ref false
+let map_files = ref []
+let module_map = ref StringMap.empty
+let debug = ref false
+
+(* Fix path to use '/' as directory separator instead of '\'.
+ Only under Windows. *)
+
+let fix_slash s =
+ if Sys.os_type = "Unix" then s else begin
+ String.map (function '\\' -> '/' | c -> c) s
+ end
+
+(* Since we reinitialize load_path after reading OCAMLCOMP,
+ we must use a cache instead of calling Sys.readdir too often. *)
+let dirs = ref StringMap.empty
+let readdir dir =
+ try
+ StringMap.find dir !dirs
+ with Not_found ->
+ let contents =
+ try
+ Sys.readdir dir
+ with Sys_error msg ->
+ Format.fprintf Format.err_formatter "@[Bad -I option: %s@]@." msg;
+ error_occurred := true;
+ [||]
+ in
+ dirs := StringMap.add dir contents !dirs;
+ contents
+
+let add_to_list li s =
+ li := s :: !li
+
+let add_to_load_path dir =
+ try
+ let dir = Misc.expand_directory Config.standard_library dir in
+ let contents = readdir dir in
+ add_to_list load_path (dir, contents)
+ with Sys_error msg ->
+ Format.fprintf Format.err_formatter "@[Bad -I option: %s@]@." msg;
+ error_occurred := true
+
+let add_to_synonym_list synonyms suffix =
+ if (String.length suffix) > 1 && suffix.[0] = '.' then
+ add_to_list synonyms suffix
+ else begin
+ Format.fprintf Format.err_formatter "@[Bad suffix: '%s'@]@." suffix;
+ error_occurred := true
+ end
+
+(* Find file 'name' (capitalized) in search path *)
+let find_file name =
+ let uname = String.uncapitalize_ascii name in
+ let rec find_in_array a pos =
+ if pos >= Array.length a then None else begin
+ let s = a.(pos) in
+ if s = name || s = uname then Some s else find_in_array a (pos + 1)
+ end in
+ let rec find_in_path = function
+ [] -> raise Not_found
+ | (dir, contents) :: rem ->
+ match find_in_array contents 0 with
+ Some truename ->
+ if dir = "." then truename else Filename.concat dir truename
+ | None -> find_in_path rem in
+ find_in_path !load_path
+
+let rec find_file_in_list = function
+ [] -> raise Not_found
+| x :: rem -> try find_file x with Not_found -> find_file_in_list rem
+
+
+let find_dependency target_kind modname (byt_deps, opt_deps) =
+ try
+ let candidates = List.map ((^) modname) !mli_synonyms in
+ let filename = find_file_in_list candidates in
+ let basename = Filename.chop_extension filename in
+ let cmi_file = basename ^ ".cmi" in
+ let cmx_file = basename ^ ".cmx" in
+ let ml_exists =
+ List.exists (fun ext -> Sys.file_exists (basename ^ ext)) !ml_synonyms in
+ let new_opt_dep =
+ if !all_dependencies then
+ match target_kind with
+ | MLI -> [ cmi_file ]
+ | ML ->
+ cmi_file :: (if ml_exists then [ cmx_file ] else [])
+ else
+ (* this is a make-specific hack that makes .cmx to be a 'proxy'
+ target that would force the dependency on .cmi via transitivity *)
+ if ml_exists
+ then [ cmx_file ]
+ else [ cmi_file ]
+ in
+ ( cmi_file :: byt_deps, new_opt_dep @ opt_deps)
+ with Not_found ->
+ try
+ (* "just .ml" case *)
+ let candidates = List.map ((^) modname) !ml_synonyms in
+ let filename = find_file_in_list candidates in
+ let basename = Filename.chop_extension filename in
+ let cmi_file = basename ^ ".cmi" in
+ let cmx_file = basename ^ ".cmx" in
+ let bytenames =
+ if !all_dependencies then
+ match target_kind with
+ | MLI -> [ cmi_file ]
+ | ML -> [ cmi_file ]
+ else
+ (* again, make-specific hack *)
+ [basename ^ (if !native_only then ".cmx" else ".cmo")] in
+ let optnames =
+ if !all_dependencies
+ then match target_kind with
+ | MLI -> [ cmi_file ]
+ | ML -> [ cmi_file; cmx_file ]
+ else [ cmx_file ]
+ in
+ (bytenames @ byt_deps, optnames @ opt_deps)
+ with Not_found ->
+ (byt_deps, opt_deps)
+
+let (depends_on, escaped_eol) = (":", " \\\n ")
+
+let print_filename s =
+ let s = if !Clflags.force_slash then fix_slash s else s in
+ if not (String.contains s ' ') then begin
+ print_string s;
+ end else begin
+ let rec count n i =
+ if i >= String.length s then n
+ else if s.[i] = ' ' then count (n+1) (i+1)
+ else count n (i+1)
+ in
+ let spaces = count 0 0 in
+ let result = Bytes.create (String.length s + spaces) in
+ let rec loop i j =
+ if i >= String.length s then ()
+ else if s.[i] = ' ' then begin
+ Bytes.set result j '\\';
+ Bytes.set result (j+1) ' ';
+ loop (i+1) (j+2);
+ end else begin
+ Bytes.set result j s.[i];
+ loop (i+1) (j+1);
+ end
+ in
+ loop 0 0;
+ print_bytes result;
+ end
+;;
+
+let print_dependencies target_files deps =
+ let rec print_items pos = function
+ [] -> print_string "\n"
+ | dep :: rem ->
+ if !one_line || (pos + 1 + String.length dep <= 77) then begin
+ if pos <> 0 then print_string " "; print_filename dep;
+ print_items (pos + String.length dep + 1) rem
+ end else begin
+ print_string escaped_eol; print_filename dep;
+ print_items (String.length dep + 4) rem
+ end in
+ print_items 0 (target_files @ [depends_on] @ deps)
+
+let print_raw_dependencies source_file deps =
+ print_filename source_file; print_string depends_on;
+ Depend.StringSet.iter
+ (fun dep ->
+ (* filter out "*predef*" *)
+ if (String.length dep > 0)
+ && (match dep.[0] with
+ | 'A'..'Z' | '\128'..'\255' -> true
+ | _ -> false) then
+ begin
+ print_char ' ';
+ print_string dep
+ end)
+ deps;
+ print_char '\n'
+
+
+(* Process one file *)
+
+let report_err exn =
+ error_occurred := true;
+ Location.report_exception Format.err_formatter exn
+
+let tool_name = "ocamldep"
+
+let rec lexical_approximation lexbuf =
+ (* Approximation when a file can't be parsed.
+ Heuristic:
+ - first component of any path starting with an uppercase character is a
+ dependency.
+ - always skip the token after a dot, unless dot is preceded by a
+ lower-case identifier
+ - always skip the token after a backquote
+ *)
+ try
+ let rec process after_lident lexbuf =
+ match Lexer.token lexbuf with
+ | Parser.UIDENT name ->
+ Depend.free_structure_names :=
+ Depend.StringSet.add name !Depend.free_structure_names;
+ process false lexbuf
+ | Parser.LIDENT _ -> process true lexbuf
+ | Parser.DOT when after_lident -> process false lexbuf
+ | Parser.DOT | Parser.BACKQUOTE -> skip_one lexbuf
+ | Parser.EOF -> ()
+ | _ -> process false lexbuf
+ and skip_one lexbuf =
+ match Lexer.token lexbuf with
+ | Parser.DOT | Parser.BACKQUOTE -> skip_one lexbuf
+ | Parser.EOF -> ()
+ | _ -> process false lexbuf
+
+ in
+ process false lexbuf
+ with Lexer.Error _ -> lexical_approximation lexbuf
+
+let read_and_approximate inputfile =
+ error_occurred := false;
+ Depend.free_structure_names := Depend.StringSet.empty;
+ let ic = open_in_bin inputfile in
+ try
+ seek_in ic 0;
+ Location.input_name := inputfile;
+ let lexbuf = Lexing.from_channel ic in
+ Location.init lexbuf inputfile;
+ lexical_approximation lexbuf;
+ close_in ic;
+ !Depend.free_structure_names
+ with exn ->
+ close_in ic;
+ report_err exn;
+ !Depend.free_structure_names
+
+let read_parse_and_extract parse_function extract_function def ast_kind
+ source_file =
+ Depend.pp_deps := [];
+ Depend.free_structure_names := Depend.StringSet.empty;
+ try
+ let input_file = Pparse.preprocess source_file in
+ begin try
+ let ast =
+ Pparse.file ~tool_name Format.err_formatter
+ input_file parse_function ast_kind
+ in
+ let bound_vars =
+ List.fold_left
+ (fun bv modname ->
+ Depend.open_module bv (Longident.parse modname))
+ !module_map ((* PR#7248 *) List.rev !Clflags.open_modules)
+ in
+ let r = extract_function bound_vars ast in
+ Pparse.remove_preprocessed input_file;
+ (!Depend.free_structure_names, r)
+ with x ->
+ Pparse.remove_preprocessed input_file;
+ raise x
+ end
+ with x -> begin
+ report_err x;
+ if not !allow_approximation
+ then (Depend.StringSet.empty, def)
+ else (read_and_approximate source_file, def)
+ end
+
+let print_ml_dependencies source_file extracted_deps pp_deps =
+ let basename = Filename.chop_extension source_file in
+ let byte_targets = [ basename ^ ".cmo" ] in
+ let native_targets =
+ if !all_dependencies
+ then [ basename ^ ".cmx"; basename ^ ".o" ]
+ else [ basename ^ ".cmx" ] in
+ let shared_targets = [ basename ^ ".cmxs" ] in
+ let init_deps = if !all_dependencies then [source_file] else [] in
+ let cmi_name = basename ^ ".cmi" in
+ let init_deps, extra_targets =
+ if List.exists (fun ext -> Sys.file_exists (basename ^ ext))
+ !mli_synonyms
+ then (cmi_name :: init_deps, cmi_name :: init_deps), []
+ else (init_deps, init_deps),
+ (if !all_dependencies then [cmi_name] else [])
+ in
+ let (byt_deps, native_deps) =
+ Depend.StringSet.fold (find_dependency ML)
+ extracted_deps init_deps in
+ if not !native_only then
+ print_dependencies (byte_targets @ extra_targets) (byt_deps @ pp_deps);
+ if not !bytecode_only then
+ begin
+ print_dependencies (native_targets @ extra_targets)
+ (native_deps @ pp_deps);
+ if !shared then
+ print_dependencies (shared_targets @ extra_targets)
+ (native_deps @ pp_deps)
+ end
+
+let print_mli_dependencies source_file extracted_deps pp_deps =
+ let basename = Filename.chop_extension source_file in
+ let (byt_deps, _opt_deps) =
+ Depend.StringSet.fold (find_dependency MLI)
+ extracted_deps ([], []) in
+ print_dependencies [basename ^ ".cmi"] (byt_deps @ pp_deps)
+
+let print_file_dependencies (source_file, kind, extracted_deps, pp_deps) =
+ if !raw_dependencies then begin
+ print_raw_dependencies source_file extracted_deps
+ end else
+ match kind with
+ | ML -> print_ml_dependencies source_file extracted_deps pp_deps
+ | MLI -> print_mli_dependencies source_file extracted_deps pp_deps
+
+
+let ml_file_dependencies source_file =
+ let parse_use_file_as_impl lexbuf =
+ let f x =
+ match x with
+ | Ptop_def s -> s
+ | Ptop_dir _ -> []
+ in
+ List.flatten (List.map f (Parse.use_file lexbuf))
+ in
+ let (extracted_deps, ()) =
+ read_parse_and_extract parse_use_file_as_impl Depend.add_implementation ()
+ Pparse.Structure source_file
+ in
+ files := (source_file, ML, extracted_deps, !Depend.pp_deps) :: !files
+
+let mli_file_dependencies source_file =
+ let (extracted_deps, ()) =
+ read_parse_and_extract Parse.interface Depend.add_signature ()
+ Pparse.Signature source_file
+ in
+ files := (source_file, MLI, extracted_deps, !Depend.pp_deps) :: !files
+
+let process_file_as process_fun def source_file =
+ Compenv.readenv ppf (Before_compile source_file);
+ load_path := [];
+ List.iter add_to_load_path (
+ (!Compenv.last_include_dirs @
+ !Clflags.include_dirs @
+ !Compenv.first_include_dirs
+ ));
+ Location.input_name := source_file;
+ try
+ if Sys.file_exists source_file then process_fun source_file else def
+ with x -> report_err x; def
+
+let process_file source_file ~ml_file ~mli_file ~def =
+ if List.exists (Filename.check_suffix source_file) !ml_synonyms then
+ process_file_as ml_file def source_file
+ else if List.exists (Filename.check_suffix source_file) !mli_synonyms then
+ process_file_as mli_file def source_file
+ else def
+
+let file_dependencies source_file =
+ process_file source_file ~def:()
+ ~ml_file:ml_file_dependencies
+ ~mli_file:mli_file_dependencies
+
+let file_dependencies_as kind =
+ match kind with
+ | ML -> process_file_as ml_file_dependencies ()
+ | MLI -> process_file_as mli_file_dependencies ()
+
+let sort_files_by_dependencies files =
+ let h = Hashtbl.create 31 in
+ let worklist = ref [] in
+
+(* Init Hashtbl with all defined modules *)
+ let files = List.map (fun (file, file_kind, deps, pp_deps) ->
+ let modname =
+ String.capitalize_ascii (Filename.chop_extension (Filename.basename file))
+ in
+ let key = (modname, file_kind) in
+ let new_deps = ref [] in
+ Hashtbl.add h key (file, new_deps);
+ worklist := key :: !worklist;
+ (modname, file_kind, deps, new_deps, pp_deps)
+ ) files in
+
+(* Keep only dependencies to defined modules *)
+ List.iter (fun (modname, file_kind, deps, new_deps, _pp_deps) ->
+ let add_dep modname kind =
+ new_deps := (modname, kind) :: !new_deps;
+ in
+ Depend.StringSet.iter (fun modname ->
+ match file_kind with
+ ML -> (* ML depends both on ML and MLI *)
+ if Hashtbl.mem h (modname, MLI) then add_dep modname MLI;
+ if Hashtbl.mem h (modname, ML) then add_dep modname ML
+ | MLI -> (* MLI depends on MLI if exists, or ML otherwise *)
+ if Hashtbl.mem h (modname, MLI) then add_dep modname MLI
+ else if Hashtbl.mem h (modname, ML) then add_dep modname ML
+ ) deps;
+ if file_kind = ML then (* add dep from .ml to .mli *)
+ if Hashtbl.mem h (modname, MLI) then add_dep modname MLI
+ ) files;
+
+(* Print and remove all files with no remaining dependency. Iterate
+ until all files have been removed (worklist is empty) or
+ no file was removed during a turn (cycle). *)
+ let printed = ref true in
+ while !printed && !worklist <> [] do
+ let files = !worklist in
+ worklist := [];
+ printed := false;
+ List.iter (fun key ->
+ let (file, deps) = Hashtbl.find h key in
+ let set = !deps in
+ deps := [];
+ List.iter (fun key ->
+ if Hashtbl.mem h key then deps := key :: !deps
+ ) set;
+ if !deps = [] then begin
+ printed := true;
+ Printf.printf "%s " file;
+ Hashtbl.remove h key;
+ end else
+ worklist := key :: !worklist
+ ) files
+ done;
+
+ if !worklist <> [] then begin
+ Format.fprintf Format.err_formatter
+ "@[Warning: cycle in dependencies. End of list is not sorted.@]@.";
+ let sorted_deps =
+ let li = ref [] in
+ Hashtbl.iter (fun _ file_deps -> li := file_deps :: !li) h;
+ List.sort (fun (file1, _) (file2, _) -> String.compare file1 file2) !li
+ in
+ List.iter (fun (file, deps) ->
+ Format.fprintf Format.err_formatter "\t@[%s: " file;
+ List.iter (fun (modname, kind) ->
+ Format.fprintf Format.err_formatter "%s.%s " modname
+ (if kind=ML then "ml" else "mli");
+ ) !deps;
+ Format.fprintf Format.err_formatter "@]@.";
+ Printf.printf "%s " file) sorted_deps;
+ end;
+ Printf.printf "\n%!";
+ ()
+
+(* Map *)
+
+let rec dump_map s0 ppf m =
+ let open Depend in
+ StringMap.iter
+ (fun key (Node(s1,m')) ->
+ let s = StringSet.diff s1 s0 in
+ if StringSet.is_empty s then
+ Format.fprintf ppf "@ @[<hv2>module %s : sig%a@;<1 -2>end@]"
+ key (dump_map (StringSet.union s1 s0)) m'
+ else
+ Format.fprintf ppf "@ module %s = %s" key (StringSet.choose s))
+ m
+
+let process_ml_map =
+ read_parse_and_extract Parse.implementation Depend.add_implementation_binding
+ StringMap.empty Pparse.Structure
+
+let process_mli_map =
+ read_parse_and_extract Parse.interface Depend.add_signature_binding
+ StringMap.empty Pparse.Signature
+
+let parse_map fname =
+ map_files := fname :: !map_files ;
+ let old_transp = !Clflags.transparent_modules in
+ Clflags.transparent_modules := true;
+ let (deps, m) =
+ process_file fname ~def:(Depend.StringSet.empty, StringMap.empty)
+ ~ml_file:process_ml_map
+ ~mli_file:process_mli_map
+ in
+ Clflags.transparent_modules := old_transp;
+ let modname =
+ String.capitalize_ascii
+ (Filename.basename (Filename.chop_extension fname)) in
+ if StringMap.is_empty m then
+ report_err (Failure (fname ^ " : empty map file or parse error"));
+ let mm = Depend.make_node m in
+ if !debug then begin
+ Format.printf "@[<v>%s:%t%a@]@." fname
+ (fun ppf -> Depend.StringSet.iter (Format.fprintf ppf " %s") deps)
+ (dump_map deps) (StringMap.add modname mm StringMap.empty)
+ end;
+ let mm = Depend.(weaken_map (StringSet.singleton modname) mm) in
+ module_map := StringMap.add modname mm !module_map
+;;
+
+
+(* Entry point *)
+
+let print_version () =
+ Format.printf "ocamldep, version %s@." Sys.ocaml_version;
+ exit 0;
+;;
+
+let print_version_num () =
+ Format.printf "%s@." Sys.ocaml_version;
+ exit 0;
+;;
+
+let main () =
+ Clflags.classic := false;
+ add_to_list first_include_dirs Filename.current_dir_name;
+ Compenv.readenv ppf Before_args;
+ Clflags.reset_arguments (); (* reset arguments from ocamlc/ocamlopt *)
+ Clflags.add_arguments __LOC__ [
+ "-absname", Arg.Set Location.absname,
+ " Show absolute filenames in error messages";
+ "-all", Arg.Set all_dependencies,
+ " Generate dependencies on all files";
+ "-allow-approx", Arg.Set allow_approximation,
+ " Fallback to a lexer-based approximation on unparseable files";
+ "-as-map", Arg.Set Clflags.transparent_modules,
+ " Omit delayed dependencies for module aliases (-no-alias-deps -w -49)";
+ (* "compiler uses -no-alias-deps, and no module is coerced"; *)
+ "-debug-map", Arg.Set debug,
+ " Dump the delayed dependency map for each map file";
+ "-I", Arg.String (add_to_list Clflags.include_dirs),
+ "<dir> Add <dir> to the list of include directories";
+ "-impl", Arg.String (file_dependencies_as ML),
+ "<f> Process <f> as a .ml file";
+ "-intf", Arg.String (file_dependencies_as MLI),
+ "<f> Process <f> as a .mli file";
+ "-map", Arg.String parse_map,
+ "<f> Read <f> and propagate delayed dependencies to following files";
+ "-ml-synonym", Arg.String(add_to_synonym_list ml_synonyms),
+ "<e> Consider <e> as a synonym of the .ml extension";
+ "-mli-synonym", Arg.String(add_to_synonym_list mli_synonyms),
+ "<e> Consider <e> as a synonym of the .mli extension";
+ "-modules", Arg.Set raw_dependencies,
+ " Print module dependencies in raw form (not suitable for make)";
+ "-native", Arg.Set native_only,
+ " Generate dependencies for native-code only (no .cmo files)";
+ "-bytecode", Arg.Set bytecode_only,
+ " Generate dependencies for bytecode-code only (no .cmx files)";
+ "-one-line", Arg.Set one_line,
+ " Output one line per file, regardless of the length";
+ "-open", Arg.String (add_to_list Clflags.open_modules),
+ "<module> Opens the module <module> before typing";
+ "-plugin", Arg.String Compplugin.load,
+ "<plugin> Load dynamic plugin <plugin>";
+ "-pp", Arg.String(fun s -> Clflags.preprocessor := Some s),
+ "<cmd> Pipe sources through preprocessor <cmd>";
+ "-ppx", Arg.String (add_to_list first_ppx),
+ "<cmd> Pipe abstract syntax trees through preprocessor <cmd>";
+ "-shared", Arg.Set shared,
+ " Generate dependencies for native plugin files (.cmxs targets)";
+ "-slash", Arg.Set Clflags.force_slash,
+ " (Windows) Use forward slash / instead of backslash \\ in file paths";
+ "-sort", Arg.Set sort_files,
+ " Sort files according to their dependencies";
+ "-version", Arg.Unit print_version,
+ " Print version and exit";
+ "-vnum", Arg.Unit print_version_num,
+ " Print version number and exit";
+ "-args", Arg.Expand Arg.read_arg,
+ "<file> Read additional newline separated command line arguments \n\
+ \ from <file>";
+ "-args0", Arg.Expand Arg.read_arg0,
+ "<file> Read additional NUL separated command line arguments from \n\
+ \ <file>"
+ ];
+ let usage =
+ Printf.sprintf "Usage: %s [options] <source files>\nOptions are:"
+ (Filename.basename Sys.argv.(0))
+ in
+ Clflags.parse_arguments file_dependencies usage;
+ Compenv.readenv ppf Before_link;
+ if !sort_files then sort_files_by_dependencies !files
+ else List.iter print_file_dependencies (List.sort compare !files);
+ exit (if !error_occurred then 2 else 0)
+
+let main_from_option () =
+ if Sys.argv.(1) <> "-depend" then begin
+ Printf.eprintf
+ "Fatal error: argument -depend must be used as first argument.\n%!";
+ exit 2;
+ end;
+ incr Arg.current;
+ Sys.argv.(0) <- Sys.argv.(0) ^ " -depend";
+ Sys.argv.(!Arg.current) <- Sys.argv.(0);
+ main ()
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 1999 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+val main : unit -> unit
+
+(* entry point when called from the -depend option of ocamlc/ocamlopt *)
+val main_from_option : unit -> unit
let tool_name = "ocamlopt"
let interface ppf sourcefile outputprefix =
- Compmisc.init_path false;
- let modulename = module_of_filename ppf sourcefile outputprefix in
- Env.set_unit_name modulename;
- let initial_env = Compmisc.initial_env () in
- let ast = Pparse.parse_interface ~tool_name ppf sourcefile in
- if !Clflags.dump_parsetree then fprintf ppf "%a@." Printast.interface ast;
- if !Clflags.dump_source then fprintf ppf "%a@." Pprintast.signature ast;
- Timings.(time_call (Typing sourcefile)) (fun () ->
- let tsg = Typemod.type_interface sourcefile initial_env ast in
- if !Clflags.dump_typedtree then fprintf ppf "%a@." Printtyped.interface tsg;
- let sg = tsg.sig_type in
- if !Clflags.print_types then
- Printtyp.wrap_printing_env initial_env (fun () ->
- fprintf std_formatter "%a@."
- Printtyp.signature (Typemod.simplify_signature sg));
- ignore (Includemod.signatures initial_env sg sg);
- Typecore.force_delayed_checks ();
- Warnings.check_fatal ();
- if not !Clflags.print_types then begin
- let deprecated = Builtin_attributes.deprecated_of_sig ast in
- let sg =
- Env.save_signature ~deprecated sg modulename (outputprefix ^ ".cmi")
- in
- Typemod.save_signature modulename tsg outputprefix sourcefile
- initial_env sg ;
- end
+ Profile.record_call sourcefile (fun () ->
+ Compmisc.init_path false;
+ let modulename = module_of_filename ppf sourcefile outputprefix in
+ Env.set_unit_name modulename;
+ let initial_env = Compmisc.initial_env () in
+ let ast = Pparse.parse_interface ~tool_name ppf sourcefile in
+ if !Clflags.dump_parsetree then fprintf ppf "%a@." Printast.interface ast;
+ if !Clflags.dump_source then fprintf ppf "%a@." Pprintast.signature ast;
+ Profile.(record_call typing) (fun () ->
+ let tsg = Typemod.type_interface sourcefile initial_env ast in
+ if !Clflags.dump_typedtree then fprintf ppf "%a@." Printtyped.interface tsg;
+ let sg = tsg.sig_type in
+ if !Clflags.print_types then
+ Printtyp.wrap_printing_env initial_env (fun () ->
+ fprintf std_formatter "%a@."
+ Printtyp.signature (Typemod.simplify_signature sg));
+ ignore (Includemod.signatures initial_env sg sg);
+ Typecore.force_delayed_checks ();
+ Warnings.check_fatal ();
+ if not !Clflags.print_types then begin
+ let deprecated = Builtin_attributes.deprecated_of_sig ast in
+ let sg =
+ Env.save_signature ~deprecated sg modulename (outputprefix ^ ".cmi")
+ in
+ Typemod.save_signature modulename tsg outputprefix sourcefile
+ initial_env sg ;
+ end
+ )
)
(* Compile a .ml file *)
let (+++) (x, y) f = (x, f y)
let implementation ~backend ppf sourcefile outputprefix =
- let source_provenance = Timings.File sourcefile in
- Compmisc.init_path true;
- let modulename = module_of_filename ppf sourcefile outputprefix in
- Env.set_unit_name modulename;
- let env = Compmisc.initial_env() in
- Compilenv.reset ~source_provenance ?packname:!Clflags.for_package modulename;
- let cmxfile = outputprefix ^ ".cmx" in
- let objfile = outputprefix ^ ext_obj in
- let comp ast =
- let (typedtree, coercion) =
- ast
- ++ print_if ppf Clflags.dump_parsetree Printast.implementation
- ++ print_if ppf Clflags.dump_source Pprintast.structure
- ++ Timings.(time (Typing sourcefile))
- (Typemod.type_implementation sourcefile outputprefix modulename env)
- ++ print_if ppf Clflags.dump_typedtree
- Printtyped.implementation_with_coercion
- in
- if not !Clflags.print_types then begin
- if Config.flambda then begin
- if !Clflags.classic_inlining then begin
- Clflags.default_simplify_rounds := 1;
+ Profile.record_call sourcefile (fun () ->
+ Compmisc.init_path true;
+ let modulename = module_of_filename ppf sourcefile outputprefix in
+ Env.set_unit_name modulename;
+ let env = Compmisc.initial_env() in
+ Compilenv.reset ?packname:!Clflags.for_package modulename;
+ let cmxfile = outputprefix ^ ".cmx" in
+ let objfile = outputprefix ^ ext_obj in
+ let comp ast =
+ let (typedtree, coercion) =
+ ast
+ ++ print_if ppf Clflags.dump_parsetree Printast.implementation
+ ++ print_if ppf Clflags.dump_source Pprintast.structure
+ ++ Profile.(record typing)
+ (Typemod.type_implementation sourcefile outputprefix modulename env)
+ ++ print_if ppf Clflags.dump_typedtree
+ Printtyped.implementation_with_coercion
+ in
+ if not !Clflags.print_types then begin
+ if Config.flambda then begin
+ if !Clflags.classic_inlining then begin
+ Clflags.default_simplify_rounds := 1;
+ Clflags.use_inlining_arguments_set Clflags.classic_arguments;
+ Clflags.unbox_free_vars_of_closures := false;
+ Clflags.unbox_specialised_args := false
+ end;
+ (typedtree, coercion)
+ ++ Profile.(record transl)
+ (Translmod.transl_implementation_flambda modulename)
+ ++ Profile.(record generate)
+ (fun { Lambda.module_ident; main_module_block_size;
+ required_globals; code } ->
+ ((module_ident, main_module_block_size), code)
+ +++ print_if ppf Clflags.dump_rawlambda Printlambda.lambda
+ +++ Simplif.simplify_lambda sourcefile
+ +++ print_if ppf Clflags.dump_lambda Printlambda.lambda
+ ++ (fun ((module_ident, size), lam) ->
+ Middle_end.middle_end ppf
+ ~prefixname:outputprefix
+ ~size
+ ~filename:sourcefile
+ ~module_ident
+ ~backend
+ ~module_initializer:lam)
+ ++ Asmgen.compile_implementation_flambda
+ outputprefix ~required_globals ~backend ppf;
+ Compilenv.save_unit_info cmxfile)
+ end
+ else begin
Clflags.use_inlining_arguments_set Clflags.classic_arguments;
- Clflags.unbox_free_vars_of_closures := false;
- Clflags.unbox_specialised_args := false
- end;
- (typedtree, coercion)
- ++ Timings.(time (Timings.Transl sourcefile)
- (Translmod.transl_implementation_flambda modulename))
- ++ Timings.time (Timings.Generate sourcefile)
- (fun { Lambda.module_ident; main_module_block_size;
- required_globals; code } ->
- ((module_ident, main_module_block_size), code)
- +++ print_if ppf Clflags.dump_rawlambda Printlambda.lambda
- +++ Simplif.simplify_lambda sourcefile
- +++ print_if ppf Clflags.dump_lambda Printlambda.lambda
- ++ (fun ((module_ident, size), lam) ->
- Middle_end.middle_end ppf ~source_provenance
- ~prefixname:outputprefix
- ~size
- ~filename:sourcefile
- ~module_ident
- ~backend
- ~module_initializer:lam)
- ++ Asmgen.compile_implementation_flambda ~source_provenance
- outputprefix ~required_globals ~backend ppf;
- Compilenv.save_unit_info cmxfile)
- end
- else begin
- Clflags.use_inlining_arguments_set Clflags.classic_arguments;
- (typedtree, coercion)
- ++ Timings.(time (Transl sourcefile))
- (Translmod.transl_store_implementation modulename)
- ++ print_if ppf Clflags.dump_rawlambda Printlambda.program
- ++ Timings.(time (Generate sourcefile))
- (fun program ->
- { program with
- Lambda.code = Simplif.simplify_lambda sourcefile
- program.Lambda.code }
- ++ print_if ppf Clflags.dump_lambda Printlambda.program
- ++ Asmgen.compile_implementation_clambda ~source_provenance
- outputprefix ppf;
- Compilenv.save_unit_info cmxfile)
- end
- end;
- Warnings.check_fatal ();
- Stypes.dump (Some (outputprefix ^ ".annot"))
- in
- try comp (Pparse.parse_implementation ~tool_name ppf sourcefile)
- with x ->
- Stypes.dump (Some (outputprefix ^ ".annot"));
- remove_file objfile;
- remove_file cmxfile;
- raise x
+ (typedtree, coercion)
+ ++ Profile.(record transl)
+ (Translmod.transl_store_implementation modulename)
+ ++ print_if ppf Clflags.dump_rawlambda Printlambda.program
+ ++ Profile.(record generate)
+ (fun program ->
+ { program with
+ Lambda.code = Simplif.simplify_lambda sourcefile
+ program.Lambda.code }
+ ++ print_if ppf Clflags.dump_lambda Printlambda.program
+ ++ Asmgen.compile_implementation_clambda
+ outputprefix ppf;
+ Compilenv.save_unit_info cmxfile)
+ end
+ end;
+ Warnings.check_fatal ();
+ Stypes.dump (Some (outputprefix ^ ".annot"))
+ in
+ try comp (Pparse.parse_implementation ~tool_name ppf sourcefile)
+ with x ->
+ Stypes.dump (Some (outputprefix ^ ".annot"));
+ remove_file objfile;
+ remove_file cmxfile;
+ raise x
+ )
inline_max_depth
let _alias_deps = clear transparent_modules
let _no_alias_deps = set transparent_modules
+ let _linscan = set use_linscan
let _app_funct = set applicative_functors
let _no_app_funct = clear applicative_functors
let _no_float_const_prop = clear float_const_prop
let _dcombine = set dump_combine
let _dcse = set dump_cse
let _dlive () = dump_live := true; Printmach.print_live := true
+ let _davail () = dump_avail := true
+ let _drunavail () = debug_runavail := true
let _dspill = set dump_spill
let _dsplit = set dump_split
let _dinterf = set dump_interf
let _dreload = set dump_reload
let _dscheduling = set dump_scheduling
let _dlinear = set dump_linear
+ let _dinterval = set dump_interval
let _dstartup = set keep_startup_file
- let _dtimings = set print_timings
+ let _dtimings () = profile_columns := [ `Time ]
+ let _dprofile () = profile_columns := Profile.all_columns
let _opaque = set opaque
let _args = Arg.read_arg
try
readenv ppf Before_args;
Clflags.add_arguments __LOC__ (Arch.command_line_options @ Options.list);
+ Clflags.add_arguments __LOC__
+ ["-depend", Arg.Unit Makedepend.main_from_option,
+ "<options> Compute dependencies (use 'ocamlopt -depend -help' for details)"];
Clflags.parse_arguments anonymous usage;
Compmisc.read_color_env ppf;
if !gprofile && not Config.profiling then
Location.report_exception ppf x;
exit 2
-let _ =
- Timings.(time All) main ();
- if !Clflags.print_timings then Timings.print Format.std_formatter;
+let () =
+ main ();
+ Profile.print Format.std_formatter !Clflags.profile_columns;
exit 0
match !Clflags.preprocessor with
None -> sourcefile
| Some pp ->
- Timings.(time (Dash_pp sourcefile))
+ Profile.record "-pp"
(call_external_preprocessor sourcefile) pp
let file_aux ppf ~tool_name inputfile (type a) parse_fun invariant_fun
(kind : a ast_kind) =
let ast_magic = magic_of_kind kind in
- let source_file = !Location.input_name in
let (ic, is_ast_file) = open_and_check_magic inputfile ast_magic in
let ast =
try
(input_value ic : a)
end else begin
seek_in ic 0;
- Location.input_name := inputfile;
let lexbuf = Lexing.from_channel ic in
Location.init lexbuf inputfile;
- Timings.(time_call (Parser source_file)) (fun () ->
- parse_fun lexbuf)
+ Profile.record_call "parser" (fun () -> parse_fun lexbuf)
end
with x -> close_in ic; raise x
in
close_in ic;
let ast =
- Timings.(time_call (Dash_ppx source_file)) (fun () ->
+ Profile.record_call "-ppx" (fun () ->
apply_rewriters ~restore:false ~tool_name kind ast) in
if is_ast_file || !Clflags.all_ppx <> [] then invariant_fun ast;
ast
end)
let parse_implementation ppf ~tool_name sourcefile =
- Timings.(time_call (Parsing sourcefile)) (fun () ->
+ Profile.record_call "parsing" (fun () ->
parse_file ~tool_name Ast_invariants.structure
ImplementationHooks.apply_hooks Structure ppf sourcefile)
let parse_interface ppf ~tool_name sourcefile =
- Timings.(time_call (Parsing sourcefile)) (fun () ->
+ Profile.record_call "parsing" (fun () ->
parse_file ~tool_name Ast_invariants.signature
InterfaceHooks.apply_hooks Signature ppf sourcefile)
(* *)
(**************************************************************************)
+(** Driver for the parser, external preprocessors and ast plugin hooks *)
+
open Format
type error =
-;**************************************************************************
-;* *
-;* OCaml *
-;* *
-;* Jacques Garrigue and Ian T Zimmerman *
-;* *
-;* Copyright 1997 Institut National de Recherche en Informatique et *
-;* en Automatique. *
-;* *
-;* All rights reserved. This file is distributed under the terms of *
-;* the GNU General Public License. *
-;* *
-;**************************************************************************
-
;;; caml.el --- OCaml code editing commands for Emacs
-;; Xavier Leroy, july 1993.
+;; Copyright (C) 1997-2017 Institut National de Recherche en Informatique et en Automatique.
+
+;; Author: Jacques Garrigue <garrigue@kurims.kyoto-u.ac.jp>
+;; Ian T Zimmerman <itz@rahul.net>
+;; Maintainer: Damien Doligez <damien.doligez@inria.fr>
+;; Created: July 1993
+;; Keywords: OCaml
+;; Homepage: https://github.com/ocaml/ocaml/
+
+;; This file is not part of GNU Emacs.
+
+;; This file is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; This file is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; A major mode for editing OCaml code (see <http://ocaml.org/>) in Emacs.
-;;indentation code is Copyright (C) 1996 by Ian T Zimmerman <itz@rahul.net>
-;;copying: covered by the current FSF General Public License.
+;; Some of its major features include:
-;; indentation code adapted for OCaml by Jacques Garrigue,
-;; july 1997. <garrigue@kurims.kyoto-u.ac.jp>
+;; - syntax highlighting (font lock);
+;; - automatic indentation;
+;; - querying the type of expressions (using compiler generated annot files);
+;; - running an OCaml REPL within Emacs;
+;; - scans declarations and places them in a menu.
+
+
+;; The original indentation code was the work of Ian T Zimmerman and
+;; was adapted for OCaml by Jacques Garrigue in July 1997.
+
+;;; Code:
;;user customizable variables
(defvar caml-quote-char "'"
(defvar caml-shell-active nil
"Non nil when a subshell is running.")
-(defvar running-xemacs (string-match "XEmacs" emacs-version)
- "Non-nil if we are running in the XEmacs environment.")
-
(defvar caml-mode-map nil
"Keymap used in Caml mode.")
(if caml-mode-map
;that way we get out effect even when we do \C-x` in compilation buffer
; (define-key caml-mode-map "\C-x`" 'caml-next-error)
- (if running-xemacs
+ (if (featurep 'xemacs)
(define-key caml-mode-map 'backspace 'backward-delete-char-untabify)
(define-key caml-mode-map "\177" 'backward-delete-char-untabify))
(define-key caml-mode-map [?\C-c down-mouse-1] 'caml-types-explore)
;; caml-help
(define-key caml-mode-map [?\C-c?i] 'ocaml-add-path)
- (define-key caml-mode-map [?\C-c?]] 'ocaml-close-module)
- (define-key caml-mode-map [?\C-c?[] 'ocaml-open-module)
+ (define-key caml-mode-map [?\C-c?\]] 'ocaml-close-module)
+ (define-key caml-mode-map [?\C-c?\[] 'ocaml-open-module)
(define-key caml-mode-map [?\C-c?\C-h] 'caml-help)
(define-key caml-mode-map [?\C-c?\t] 'caml-complete)
;; others
(define-key caml-mode-map "\C-c\C-a" 'caml-find-alternate-file)
(define-key caml-mode-map "\C-c\C-c" 'compile)
(define-key caml-mode-map "\C-c\C-e" 'caml-eval-phrase)
- (define-key caml-mode-map "\C-c\C-\[" 'caml-backward-to-less-indent)
- (define-key caml-mode-map "\C-c\C-\]" 'caml-forward-to-less-indent)
+ (define-key caml-mode-map "\C-c\C-[" 'caml-backward-to-less-indent)
+ (define-key caml-mode-map "\C-c\C-]" 'caml-forward-to-less-indent)
(define-key caml-mode-map "\C-c\C-q" 'caml-indent-phrase)
(define-key caml-mode-map "\C-c\C-r" 'caml-eval-region)
(define-key caml-mode-map "\C-c\C-s" 'caml-show-subshell)
(define-key caml-mode-map "\M-\C-q" 'caml-indent-phrase)
(define-key caml-mode-map "\M-\C-x" 'caml-eval-phrase)
- (if running-xemacs nil ; if not running xemacs
+ (if (featurep 'xemacs) nil
(let ((map (make-sparse-keymap "Caml"))
(forms (make-sparse-keymap "Forms")))
(define-key caml-mode-map "\C-c\C-d" 'caml-show-imenu)
(define-key forms [begin] '("begin .. end" . caml-insert-begin-form)))))
(defvar caml-mode-xemacs-menu
- (if running-xemacs
+ (if (featurep 'xemacs)
'("Caml"
[ "Indent phrase" caml-indent-phrase :keys "C-M-q" ]
[ "Eval phrase" caml-eval-phrase
"Syntax table in use in Caml mode buffers.")
(if caml-mode-syntax-table
()
- (let ((n (if (string-match "XEmacs" (emacs-version)) "" "n")))
+ (let ((n (if (featurep 'xemacs) "" "n")))
(setq caml-mode-syntax-table (make-syntax-table))
; backslash is an escape sequence
(modify-syntax-entry ?\\ "\\" caml-mode-syntax-table)
(defvar caml-mode-abbrev-table nil
"Abbrev table used for Caml mode buffers.")
(if caml-mode-abbrev-table nil
- (setq caml-mode-abbrev-table (make-abbrev-table))
- (define-abbrev caml-mode-abbrev-table "and" "and" 'caml-abbrev-hook)
- (define-abbrev caml-mode-abbrev-table "do" "do" 'caml-abbrev-hook)
- (define-abbrev caml-mode-abbrev-table "done" "done" 'caml-abbrev-hook)
- (define-abbrev caml-mode-abbrev-table "else" "else" 'caml-abbrev-hook)
- (define-abbrev caml-mode-abbrev-table "end" "end" 'caml-abbrev-hook)
- (define-abbrev caml-mode-abbrev-table "in" "in" 'caml-abbrev-hook)
- (define-abbrev caml-mode-abbrev-table "then" "then" 'caml-abbrev-hook)
- (define-abbrev caml-mode-abbrev-table "with" "with" 'caml-abbrev-hook))
+ (define-abbrev-table 'caml-mode-abbrev-table
+ (mapcar (lambda (keyword)
+ `(,keyword ,keyword caml-abbrev-hook nil t))
+ '("and" "do" "done" "else" "end" "in" "then" "with"))))
;; Other internal variables
;;; The major mode
(eval-when-compile
- (if (and (boundp 'running-xemacs) running-xemacs) nil
+ (if (featurep 'xemacs) nil
(require 'imenu)))
;;
;garrigue 27-11-96
(setq case-fold-search nil)
;garrigue july 97
- (if running-xemacs ; from Xemacs lisp mode
+ (if (featurep 'xemacs)
(if (and (featurep 'menubar)
current-menubar)
(progn
(if (eq major-mode 'caml-mode)
(let (skip bol beg end)
(save-excursion
- (set-buffer
- (if (boundp 'compilation-last-buffer)
- compilation-last-buffer ;Emacs 19
- "*compilation*")) ;Emacs 18
- (save-excursion
- (goto-char (window-point (get-buffer-window (current-buffer))))
- (if (looking-at caml-error-chars-regexp)
- (setq beg
- (caml-string-to-int
- (buffer-substring (match-beginning 1) (match-end 1)))
- end
- (caml-string-to-int
- (buffer-substring (match-beginning 2) (match-end 2)))))
- (next-line)
- (beginning-of-line)
- (if (and (looking-at "Warning")
- caml-next-error-skip-warnings-flag)
- (setq skip 't))))
+ (with-current-buffer
+ (if (boundp 'compilation-last-buffer)
+ compilation-last-buffer ;Emacs 19
+ "*compilation*") ;Emacs 18
+ (save-excursion
+ (goto-char (window-point (get-buffer-window (current-buffer))))
+ (if (looking-at caml-error-chars-regexp)
+ (setq beg
+ (caml-string-to-int
+ (buffer-substring (match-beginning 1) (match-end 1)))
+ end
+ (caml-string-to-int
+ (buffer-substring (match-beginning 2) (match-end 2)))))
+ (forward-line 1)
+ (beginning-of-line)
+ (if (and (looking-at "Warning")
+ caml-next-error-skip-warnings-flag)
+ (setq skip 't)))))
(cond
(skip (next-error))
(beg
(defun caml-at-sexp-close-p ()
(or (char-equal ?\) (following-char))
(char-equal ?\] (following-char))
- (char-equal ?} (following-char))))
+ (char-equal ?\} (following-char))))
(defun caml-find-kwop (kwop-regexp &optional min-pos)
"Look back for a caml keyword or operator matching KWOP-REGEXP.
(defun caml-abbrev-hook ()
"If inserting a leading keyword at beginning of line, reindent the line."
;itz unfortunately we need a special case
- (if (and (not (caml-in-comment-p)) (not (= last-command-char ?_)))
+ (if (and (not (caml-in-comment-p)) (not (= last-command-event ?_)))
(let* ((bol (save-excursion (beginning-of-line) (point)))
(kw (save-excursion
(and (re-search-backward "^[ \t]*\\(\\sw+\\)\\=" bol t)
(goto-char (match-beginning 1))
(caml-indent-command)
(current-column)))
- (abbrev-correct (if (= last-command-char ?\ ) 1 0)))
+ (abbrev-correct (if (= last-command-event ?\ ) 1 0)))
(indent-to (- indent
(or
(symbol-value
(autoload 'ocaml-add-path "caml-help"
"Add search path for documentation." t)
-;;; caml.el ends here
-
(provide 'caml)
+
+;;; caml.el ends here
(*
Type of variables:
- A variable is bound to a char when all its occurences
+ A variable is bound to a char when all its occurrences
bind a pattern of length 1.
The typical case is:
(_ as x) -> char
| Star r -> firstpos r
-(* Berry-sethi followpos *)
+(* Berry-Sethi followpos *)
let followpos size entry_list =
let v = Array.make size TransSet.empty in
let rec fill s = function
let env1 =
MemMap.fold
(fun _ (tag,s) r ->
- try
- let ss = TagMap.find tag r in
- let r = TagMap.remove tag r in
- TagMap.add tag (StateSetSet.add s ss) r
- with
- | Not_found ->
- TagMap.add tag (StateSetSet.add s StateSetSet.empty) r)
+ TagMap.update tag (function
+ | None -> Some (StateSetSet.singleton s)
+ | Some ss -> Some (StateSetSet.add s ss)
+ ) r)
m TagMap.empty in
TagMap.fold
(fun tag ss r -> MemKey.add {tag=tag ; equiv=ss} r)
let inverse_mem_map trans m r =
TagMap.fold
(fun tag addr r ->
- try
- let otag,s = MemMap.find addr r in
- assert (tag = otag) ;
- let r = MemMap.remove addr r in
- MemMap.add addr (tag,StateSet.add trans s) r
- with
- | Not_found ->
- MemMap.add addr (tag,StateSet.add trans StateSet.empty) r)
+ MemMap.update addr (function
+ | None -> Some (tag, StateSet.singleton trans)
+ | Some (otag, s) ->
+ assert (tag = otag);
+ Some (tag, StateSet.add trans s)
+ ) r)
m r
let inverse_mem_map_other n (_,m) r = inverse_mem_map (OnChars n) m r
(* Reset state before processing a given automata.
We clear both the memory mapping and
- the state mapping, as state sharing beetween different
- automata may lead to incorret estimation of the cell memory size
+ the state mapping, as state sharing between different
+ automata may lead to incorrect estimation of the cell memory size
BUG ID 0004517 *)
let reachs chars follow st =
let gen = create_new_addr_gen () in
-(* build a association list (char set -> new state) *)
+(* build an association list (char set -> new state) *)
let env = comp_shift gen chars follow st in
(* change it into (char set -> new state_num) *)
let env =
include ../config/Makefile
-INSTALL_DIR=$(DESTDIR)$(MANDIR)/man$(MANEXT)
+INSTALL_DIR=$(DESTDIR)$(MANDIR)/man$(PROGRAMS_MAN_SECTION)
install:
- for i in *.m; do cp $$i $(INSTALL_DIR)/`basename $$i .m`.$(MANEXT); done
- echo '.so man$(MANEXT)/ocamlc.$(MANEXT)' \
- > $(INSTALL_DIR)/ocamlc.opt.$(MANEXT)
- echo '.so man$(MANEXT)/ocamlopt.$(MANEXT)' \
- > $(INSTALL_DIR)/ocamlopt.opt.$(MANEXT)
- echo '.so man$(MANEXT)/ocamlcp.$(MANEXT)' \
- > $(INSTALL_DIR)/ocamloptp.$(MANEXT)
+ for i in *.m; do cp \
+ $$i $(INSTALL_DIR)/`basename $$i .m`.$(PROGRAMS_MAN_SECTION); done
+ echo '.so man$(PROGRAMS_MAN_SECTION)/ocamlc.$(PROGRAMS_MAN_SECTION)' \
+ > $(INSTALL_DIR)/ocamlc.opt.$(PROGRAMS_MAN_SECTION)
+ echo '.so man$(PROGRAMS_MAN_SECTION)/ocamlopt.$(PROGRAMS_MAN_SECTION)' \
+ > $(INSTALL_DIR)/ocamlopt.opt.$(PROGRAMS_MAN_SECTION)
+ echo '.so man$(PROGRAMS_MAN_SECTION)/ocamlcp.$(PROGRAMS_MAN_SECTION)' \
+ > $(INSTALL_DIR)/ocamloptp.$(PROGRAMS_MAN_SECTION)
options are given, they are processed in order, just as if
the statements open! module1;; ... open! moduleN;; were input.
.TP
-.BI \-plugin \ plugin
-Dynamically load the code of the given
-.I plugin
-(a .cmo or .cma file) in the toplevel.
-.TP
.BI \-ppx \ command
After parsing, pipe the abstract syntax tree through the preprocessor
.IR command .
.SH ENVIRONMENT VARIABLES
.TP
-.B LC_CTYPE
-If set to iso_8859_1, accented characters (from the
-ISO Latin-1 character set) in string and character literals are
-printed as is; otherwise, they are printed as decimal escape sequences.
+.B OCAMLTOP_UTF_8
+When printing string values, non-ascii bytes (>0x7E) are printed as
+decimal escape sequence if
+.B OCAMLTOP_UTF_8
+is set to false. Otherwise they are printed unescaped.
.TP
.B TERM
When printing error messages, the toplevel system
.BR ocamlc\ \-custom ,
this would make them vulnerable to attacks.
.TP
+.BI \-depend\ ocamldep-args
+Compute dependencies, as ocamldep would do.
+.TP
.BI \-dllib\ \-l libname
Arrange for the C shared library
.BI dll libname .so
\ \ Bad module name: the source file name is not a valid OCaml module name.
25
-\ \ Pattern-matching with all clauses guarded.
+\ \ Deprecated: now part of warning 8.
26
\ \ Suspicious unused variable: unused variable that is bound with
.IP
The default setting is
-.BR \-w\ +a\-4\-6\-7\-9\-27\-29\-32..39\-41\-42\-44\-45\-48\-50\-60 .
+.BR \-w\ +a\-4\-6\-7\-9\-27\-29\-32..42\-44\-45\-48\-50\-60 .
Note that warnings
.BR 5 \ and \ 10
are not always triggered, depending on the internals of the type checker.
Pipe abstract syntax tree through preprocessor
.IR command .
.TP
+.B \-shared
+Generate dependencies for native plugin files (.cmxs) in addition to
+native compiled files (.cmx).
+.TP
.B \-slash
Under Unix, this option does nothing.
.TP
Pipe abstract syntax tree through preprocessor
.IR command .
.TP
+.BR \-show\-missed\-crossref
+Show missed cross-reference opportunities.
+.TP
.B \-sort
Sort the list of top-level modules before generating the documentation.
.TP
.I title
as the title for the generated documentation.
.TP
+.BI \-text \ file
+Consider \fIfile\fR as a .txt file.
+.TP
.BI \-intro \ file
Use content of
.I file
.B \-all\-params
Display the complete list of parameters for functions and methods.
.TP
+.BI \-charset \ s
+Add information about character encoding being \fIs\fR
+(default is \fBiso-8859-1\fR).
+.TP
.BI \-css\-style \ filename
Use
.I filename
.BR ocamlopt (1)
and a detailed summary of its configuration, then exit.
.TP
+.BI \-depend\ ocamldep-args
+Compute dependencies, as ocamldep would do.
+.TP
.BI \-for\-pack \ module\-path
Generate an object file (.cmx and .o files) that can later be included
as a sub-module (with the given access path) of a compilation unit
.I string
as interface files (instead of the default .mli).
.TP
-.B \-keep-locs
+.B \-keep-docs
Keep documentation strings in generated .cmi files.
.TP
.B \-keep-locs
.B \-fno\-PIC
Generate position-dependent machine code.
-.SH OPTIONS FOR THE SPARC ARCHITECTURE
-The Sparc code generator supports the following additional options:
-.TP
-.B \-march=v8
-Generate SPARC version 8 code.
-.TP
-.B \-march=v9
-Generate SPARC version 9 code.
-.P
-The default is to generate code for SPARC version 7, which runs on all
-SPARC processors.
-
.SH OPTIONS FOR THE ARM ARCHITECTURE
The ARM code generator supports the following additional options:
.TP
with
| exception Not_found -> assert false
| (function_decl : Flambda.function_declaration) ->
- let params = Variable.Set.of_list function_decl.params in
+ let params = Parameter.Set.vars function_decl.params in
let existing_specialised_args =
Variable.Map.filter (fun inner_var _spec_to ->
Variable.Set.mem inner_var params)
if function_decl.stub then
Definition.Set.empty
else
- let params = Variable.Set.of_list function_decl.params in
+ let params = Parameter.Set.vars function_decl.params in
Variable.Map.fold (fun inner_var
(spec_to : Flambda.specialised_to) definitions ->
if not (Variable.Set.mem inner_var params) then
if !Clflags.flambda_invariant_checks then begin
Variable.Map.iter (fun fun_var
(function_decl : Flambda.function_declaration) ->
- let params = Variable.Set.of_list function_decl.params in
+ let params = Parameter.Set.vars function_decl.params in
Variable.Map.iter (fun inner_var
(outer_var : Flambda.specialised_to) ->
if Variable.Set.mem inner_var params then begin
let rename_function_and_parameters ~fun_var
~(function_decl : Flambda.function_declaration) =
let new_fun_var = Variable.rename fun_var ~append:T.variable_suffix in
+ let params_renaming_list =
+ List.map (fun param ->
+ let new_param = Parameter.rename param ~append:T.variable_suffix in
+ param, new_param)
+ function_decl.params
+ in
+ let renamed_params = List.map snd params_renaming_list in
let params_renaming =
Variable.Map.of_list
- (List.map (fun param ->
- let new_param = Variable.rename param ~append:T.variable_suffix in
- param, new_param)
- function_decl.params)
- in
- let renamed_params =
- List.map (fun param -> Variable.Map.find param params_renaming)
- function_decl.params
+ (List.map (fun (param, new_param) ->
+ Parameter.var param, Parameter.var new_param)
+ params_renaming_list)
in
new_fun_var, params_renaming, renamed_params
definitions are called the "specialised args bound in the wrapper".
Note that the domain of [params_renaming] is a (non-strict) superset
of the "inner vars" of the original specialised args. *)
- let params = Variable.Set.of_list function_decl.params in
+ let params = Parameter.Set.vars function_decl.params in
let new_fun_var, params_renaming, wrapper_params =
rename_function_and_parameters ~fun_var ~function_decl
in
let apply : Flambda.expr =
Apply {
func = new_fun_var;
- args = wrapper_params @ spec_args_bound_in_the_wrapper;
+ args =
+ (Parameter.List.vars wrapper_params) @
+ spec_args_bound_in_the_wrapper;
kind = Direct (Closure_id.wrap new_fun_var);
dbg = Debuginfo.none;
inline = Default_inline;
assert (Variable.Map.mem projecting_from
set_of_closures.specialised_args);
assert (Variable.Set.mem projecting_from
- (Variable.Set.of_list function_decl.params));
+ (Parameter.Set.vars function_decl.params));
{ var = new_outer_var;
projection = Some projection;
})
Variable.Set.elements (Variable.Map.keys
for_one_function.new_inner_to_new_outer_vars)
in
+ let new_params =
+ List.map Parameter.wrap new_params
+ in
function_decl.params @ new_params
in
let rewritten_function_decl =
manner from the tuple. *)
let tupled_function_call_stub original_params unboxed_version
: Flambda.function_declaration =
- let tuple_param =
+ let tuple_param_var =
Variable.rename ~append:"tupled_stub_param" unboxed_version
in
let params = List.map (fun p -> Variable.rename p) original_params in
let _, body =
List.fold_left (fun (pos, body) param ->
let lam : Flambda.named =
- Prim (Pfield pos, [tuple_param], Debuginfo.none)
+ Prim (Pfield pos, [tuple_param_var], Debuginfo.none)
in
pos + 1, Flambda.create_let param lam body)
(0, call) params
in
+ let tuple_param = Parameter.wrap tuple_param_var in
Flambda.create_function_declaration ~params:[tuple_param]
~body ~stub:true ~dbg:Debuginfo.none ~inline:Default_inline
~specialise:Default_specialise ~is_a_functor:false
let arg2 = close t env arg2 in
let const_true = Variable.create "const_true" in
let cond = Variable.create "cond_sequor" in
- Flambda.create_let const_true (Const (Int 1))
+ Flambda.create_let const_true (Const (Const_pointer 1))
(Flambda.create_let cond (Expr arg1)
(If_then_else (cond, Var const_true, arg2)))
| Lprim (Psequand, [arg1; arg2], _) ->
let arg2 = close t env arg2 in
let const_false = Variable.create "const_false" in
let cond = Variable.create "cond_sequand" in
- Flambda.create_let const_false (Const (Int 0))
+ Flambda.create_let const_false (Const (Const_pointer 0))
(Flambda.create_let cond (Expr arg1)
(If_then_else (cond, arg2, Var const_false)))
| Lprim ((Psequand | Psequor), _, _) ->
~create_body:(fun args ->
name_expr (Prim (p, args, dbg))
~name)
- | Lswitch (arg, sw) ->
+ | Lswitch (arg, sw, _loc) ->
let scrutinee = Variable.create "switch" in
let aux (i, lam) = i, close t env lam in
let zero_to_n = Numbers.Int.zero_to_n in
CR-someday pchambart: eta-expansion wrapper for a primitive are
not marked as stub but certainly should *)
let stub = Function_decl.stub decl in
- let params = List.map (Env.find_var closure_env) params in
+ let param_vars = List.map (Env.find_var closure_env) params in
+ let params = List.map Parameter.wrap param_vars in
let closure_bound_var = Function_decl.closure_bound_var decl in
let body = close t closure_env body in
let fun_decl =
| Tupled ->
let unboxed_version = Variable.rename closure_bound_var in
let generic_function_stub =
- tupled_function_call_stub params unboxed_version
+ tupled_function_call_stub param_vars unboxed_version
in
Variable.Map.add unboxed_version fun_decl
(Variable.Map.add closure_bound_var generic_function_stub map)
}
and function_declaration = {
- params : Variable.t list;
+ params : Parameter.t list;
body : t;
free_variables : Variable.Set.t;
free_symbols : Symbol.Set.t;
(* lam ppf expr *)
and print_function_declaration ppf var (f : function_declaration) =
- let idents ppf =
- List.iter (fprintf ppf "@ %a" Variable.print) in
+ let param ppf p =
+ Variable.print ppf (Parameter.var p)
+ in
+ let params ppf =
+ List.iter (fprintf ppf "@ %a" param) in
let stub =
if f.stub then
" *stub*"
in
fprintf ppf "@[<2>(%a%s%s%s%s@ =@ fun@[<2>%a@] ->@ @[<2>%a@])@]@ "
Variable.print var stub is_a_functor inline specialise
- idents f.params lam f.body
+ params f.params lam f.body
and print_set_of_closures ppf (set_of_closures : set_of_closures) =
match set_of_closures with
Closure_id.print closure_id
let rec print_program_body ppf (program : program_body) =
+ let symbol_binding ppf (symbol, constant_defining_value) =
+ fprintf ppf "@[<2>(%a@ %a)@]"
+ Symbol.print symbol
+ print_constant_defining_value constant_defining_value
+ in
match program with
| Let_symbol (symbol, constant_defining_value, body) ->
- let rec letbody (ul : program_body) =
+ let rec extract acc (ul : program_body) =
match ul with
| Let_symbol (symbol, constant_defining_value, body) ->
- fprintf ppf "@ @[<2>(%a@ %a)@]" Symbol.print symbol
- print_constant_defining_value constant_defining_value;
- letbody body
- | _ -> ul
+ extract ((symbol, constant_defining_value) :: acc) body
+ | _ ->
+ List.rev acc, ul
in
- fprintf ppf "@[<2>let_symbol@ @[<hv 1>(@[<2>%a@ %a@])@]@ "
- Symbol.print symbol
- print_constant_defining_value constant_defining_value;
- let program = letbody body in
- fprintf ppf "@]@.";
+ let defs, program = extract [symbol, constant_defining_value] body in
+ fprintf ppf
+ "@[<2>let_symbol@ @[%a@]@]@."
+ (Format.pp_print_list symbol_binding) defs;
print_program_body ppf program
| Let_rec_symbol (defs, program) ->
- let bindings ppf id_arg_list =
- let spc = ref false in
- List.iter
- (fun (symbol, constant_defining_value) ->
- if !spc then fprintf ppf "@ " else spc := true;
- fprintf ppf "@[<2>%a@ %a@]"
- Symbol.print symbol
- print_constant_defining_value constant_defining_value)
- id_arg_list in
fprintf ppf
- "@[<2>let_rec_symbol@ (@[<hv 1>%a@])@]@."
- bindings defs;
+ "@[<2>let_rec_symbol@ @[%a@]@]@."
+ (Format.pp_print_list symbol_binding) defs;
print_program_body ppf program
| Initialize_symbol (symbol, tag, fields, program) ->
- fprintf ppf "@[<2>initialize_symbol@ @[<hv 1>(@[<2>%a@ %a@ %a@])@]@]@."
+ fprintf ppf "@[<2>initialize_symbol@ (@[<2>%a@ %a@ %a@])@]@."
Symbol.print symbol
Tag.print tag
(Format.pp_print_list lam) fields;
print_program_body ppf program
| Effect (expr, program) ->
- fprintf ppf "@[effect @[<hv 1>%a@]@]@."
+ fprintf ppf "@[<2>effect@ %a@]@."
lam expr;
print_program_body ppf program;
| End root -> fprintf ppf "End %a" Symbol.print root
Variable.Map.fold (fun _fun_var function_decl expected_free_vars ->
let free_vars =
Variable.Set.diff function_decl.free_variables
- (Variable.Set.union (Variable.Set.of_list function_decl.params)
+ (Variable.Set.union (Parameter.Set.vars function_decl.params)
all_fun_vars)
in
Variable.Set.union free_vars expected_free_vars)
end;
let all_params =
Variable.Map.fold (fun _fun_var function_decl all_params ->
- Variable.Set.union (Variable.Set.of_list function_decl.params)
+ Variable.Set.union (Parameter.Set.vars function_decl.params)
all_params)
function_decls.funs
Variable.Set.empty
let used_params function_decl =
Variable.Set.filter
(fun param -> Variable.Set.mem param function_decl.free_variables)
- (Variable.Set.of_list function_decl.params)
+ (Parameter.Set.vars function_decl.params)
let compare_const (c1:const) (c2:const) =
match c1, c2 with
}
and function_declaration = private {
- params : Variable.t list;
+ params : Parameter.t list;
body : t;
(* CR-soon mshinwell: inconsistent naming free_variables/free_vars here and
above *)
(** Create a function declaration. This calculates the free variables and
symbols occurring in the specified [body]. *)
val create_function_declaration
- : params:Variable.t list
+ : params:Parameter.t list
-> body:t
-> stub:bool
-> dbg:Debuginfo.t
let acceptable_free_variables =
Variable.Set.union
(Variable.Set.union variables_in_closure functions_in_closure)
- (Variable.Set.of_list params)
+ (Parameter.Set.vars params)
in
let bad =
Variable.Set.diff free_variables acceptable_free_variables
(* Check that parameters are unique across all functions in the
declaration. *)
let old_all_params_size = Variable.Set.cardinal all_params in
- let params = Variable.Set.of_list params in
+ let params = Parameter.Set.vars params in
let params_size = Variable.Set.cardinal params in
let all_params = Variable.Set.union all_params params in
let all_params_size = Variable.Set.cardinal all_params in
let variables_bound_by_the_closure cf
(decls : Flambda.function_declarations) =
let func = find_declaration cf decls in
- let params = Variable.Set.of_list func.params in
+ let params = Parameter.Set.vars func.params in
let functions = Variable.Map.keys decls.funs in
Variable.Set.diff
(Variable.Set.diff func.free_variables params)
and sameclosure (c1 : Flambda.function_declaration)
(c2 : Flambda.function_declaration) =
- Misc.Stdlib.List.equal Variable.equal c1.params c2.params
+ Misc.Stdlib.List.equal Parameter.equal c1.params c2.params
&& same c1.body c2.body
and same_set_of_closures (c1 : Flambda.set_of_closures)
let make_closure_declaration ~id ~body ~params ~stub : Flambda.t =
let free_variables = Flambda.free_variables body in
- let param_set = Variable.Set.of_list params in
+ let param_set = Parameter.Set.vars params in
if not (Variable.Set.subset param_set free_variables) then begin
Misc.fatal_error "Flambda_utils.make_closure_declaration"
end;
to do something similar to what happens in [Inlining_transforms] now. *)
let body = toplevel_substitution sb body in
let subst id = Variable.Map.find id sb in
+ let subst_param param = Parameter.map_var subst param in
let function_declaration =
- Flambda.create_function_declaration ~params:(List.map subst params)
+ Flambda.create_function_declaration ~params:(List.map subst_param params)
~body ~stub ~dbg:Debuginfo.none ~inline:Default_inline
~specialise:Default_specialise ~is_a_functor:false
in
in
Flambda_iterators.map_toplevel f (fun v -> v) expr
-(* CR-soon mshinwell: implement this so that sharing can occur in
- matches. Should probably leave this for the first release. *)
-type sharing_key = unit
-let make_key _ = None
+module Switch_storer = Switch.Store (struct
+ type t = Flambda.t
-module Switch_storer =
- Switch.Store
- (struct
- type t = Flambda.t
- type key = sharing_key
- let make_key = make_key
- end)
+ (* An easily-comparable subset of [Flambda.t]: currently this only
+ supports that required to share switch branches. *)
+ type key =
+ | Var of Variable.t
+ | Let of Variable.t * key_named * key
+ | Static_raise of Static_exception.t * Variable.t list
+ and key_named =
+ | Symbol of Symbol.t
+ | Const of Flambda.const
+ | Prim of Lambda.primitive * Variable.t list
+ | Expr of key
+
+ exception Not_comparable
+
+ let rec make_expr_key (expr : Flambda.t) : key =
+ match expr with
+ | Var v -> Var v
+ | Let { var; defining_expr; body; } ->
+ Let (var, make_named_key defining_expr, make_expr_key body)
+ | Static_raise (e, args) -> Static_raise (e, args)
+ | _ -> raise Not_comparable
+ and make_named_key (named:Flambda.named) : key_named =
+ match named with
+ | Symbol s -> Symbol s
+ | Const c -> Const c
+ | Expr e -> Expr (make_expr_key e)
+ | Prim (prim, args, _dbg) -> Prim (prim, args)
+ | _ -> raise Not_comparable
+
+ let make_key expr =
+ match make_expr_key expr with
+ | exception Not_comparable -> None
+ | key -> Some key
+
+ let compare_key e1 e2 =
+ (* The environment [env] maps variables bound in [e2] to the corresponding
+ bound variables in [e1]. Every variable to compare in [e2] must have an
+ equivalent in [e1], otherwise the comparison wouldn't have gone
+ past the [Let] binding. Hence [Variable.Map.find] is safe here. *)
+ let compare_var env v1 v2 =
+ match Variable.Map.find v2 env with
+ | exception Not_found ->
+ (* The variable is free in the expression [e2], hence we can
+ compare it with [v1] directly. *)
+ Variable.compare v1 v2
+ | bound ->
+ Variable.compare v1 bound
+ in
+ let rec compare_expr env (e1 : key) (e2 : key) : int =
+ match e1, e2 with
+ | Var v1, Var v2 ->
+ compare_var env v1 v2
+ | Var _, (Let _| Static_raise _) -> -1
+ | (Let _| Static_raise _), Var _ -> 1
+ | Let (v1, n1, b1), Let (v2, n2, b2) ->
+ let comp_named = compare_named env n1 n2 in
+ if comp_named <> 0 then comp_named
+ else
+ let env = Variable.Map.add v2 v1 env in
+ compare_expr env b1 b2
+ | Let _, Static_raise _ -> -1
+ | Static_raise _, Let _ -> 1
+ | Static_raise (sexn1, args1), Static_raise (sexn2, args2) ->
+ let comp_sexn = Static_exception.compare sexn1 sexn2 in
+ if comp_sexn <> 0 then comp_sexn
+ else Misc.Stdlib.List.compare (compare_var env) args1 args2
+ and compare_named env (n1:key_named) (n2:key_named) : int =
+ match n1, n2 with
+ | Symbol s1, Symbol s2 -> Symbol.compare s1 s2
+ | Symbol _, (Const _ | Expr _ | Prim _) -> -1
+ | (Const _ | Expr _ | Prim _), Symbol _ -> 1
+ | Const c1, Const c2 -> compare c1 c2
+ | Const _, (Expr _ | Prim _) -> -1
+ | (Expr _ | Prim _), Const _ -> 1
+ | Expr e1, Expr e2 -> compare_expr env e1 e2
+ | Expr _, Prim _ -> -1
+ | Prim _, Expr _ -> 1
+ | Prim (prim1, args1), Prim (prim2, args2) ->
+ let comp_prim = Pervasives.compare prim1 prim2 in
+ if comp_prim <> 0 then comp_prim
+ else Misc.Stdlib.List.compare (compare_var env) args1 args2
+ in
+ compare_expr Variable.Map.empty e1 e2
+end)
let fun_vars_referenced_in_decls
(function_decls : Flambda.function_declarations) ~backend =
let all_functions_parameters (function_decls : Flambda.function_declarations) =
Variable.Map.fold (fun _ ({ params } : Flambda.function_declaration) set ->
- Variable.Set.union set (Variable.Set.of_list params))
+ Variable.Set.union set (Parameter.Set.vars params))
function_decls.funs Variable.Set.empty
let all_free_symbols (function_decls : Flambda.function_declarations) =
in
Variable.Map.map (fun ({ params; _ } : Flambda.function_declaration) ->
List.map (fun param ->
- match Variable.Map.find param specialised_args with
+ match Variable.Map.find (Parameter.var param) specialised_args with
| exception Not_found -> Not_specialised
| { var; _ } ->
Specialised_and_aliased_to
val description_of_toplevel_node : Flambda.t -> string
-(** Sharing key, used for coalescing switch cases. *)
-type sharing_key
-val make_key : Flambda.t -> sharing_key option
-
(* Given an expression, freshen all variables within it, and form a function
whose body is the resulting expression. The variables specified by
[params] will become the parameters of the function; the closure will be
val make_closure_declaration
: id:Variable.t
-> body:Flambda.t
- -> params:Variable.t list
+ -> params:Parameter.t list
-> stub:bool
-> Flambda.t
let t = add_sb_var t id id' in
id', t
+let active_add_parameter t param =
+ let param' = Parameter.rename param in
+ let t = add_sb_var t (Parameter.var param) (Parameter.var param') in
+ param', t
+
let add_variable t id =
match t with
| Inactive -> id, t
let id', t = active_add_variable t id in
id', Active t
-let active_add_variables' t ids =
- List.fold_right (fun id (ids, t) ->
- let id', t = active_add_variable t id in
- id' :: ids, t) ids ([], t)
+let active_add_parameters' t (params:Parameter.t list) =
+ List.fold_right (fun param (params, t) ->
+ let param', t = active_add_parameter t param in
+ param' :: params, t)
+ params ([], t)
let add_variables t defs =
List.fold_right (fun (id, data) (defs, t) ->
| Inactive -> func_decls, subst, t
| Active subst ->
let subst_func_decl _fun_id (func_decl : Flambda.function_declaration)
- subst =
- let params, subst = active_add_variables' subst func_decl.params in
+ subst =
+ let params, subst = active_add_parameters' subst func_decl.params in
(* Since all parameters are distinct, even between functions, we can
just use a single substitution. *)
let body =
| outer_var ->
register_implication ~in_nc:(Var outer_var.var)
~implies_in_nc:[Var param])
- ffunc.params;
+ (Parameter.List.vars ffunc.params);
mark_loop ~toplevel:false [] ffunc.body)
function_decls.funs
| Default_specialise -> ()
end;
let freshened_params =
- List.map (fun id -> Variable.rename id) function_decl.Flambda.params
+ List.map (fun p -> Parameter.rename p) function_decl.Flambda.params
in
let applied_args, remaining_args =
Misc.Stdlib.List.map2_prefix (fun arg id' -> id', arg)
let body : Flambda.t =
Apply {
func = lhs_of_application;
- args = freshened_params;
+ args = Parameter.List.vars freshened_params;
kind = Direct closure_id_being_applied;
dbg;
inline = Default_inline;
in
let with_known_args =
Flambda_utils.bind
- ~bindings:(List.map (fun (var, arg) ->
- var, Flambda.Expr (Var arg)) applied_args)
+ ~bindings:(List.map (fun (param, arg) ->
+ Parameter.var param, Flambda.Expr (Var arg)) applied_args)
~body:wrapper_accepting_remaining_args
in
simplify env r with_known_args
| (Parraysetu kind | Parraysets kind),
[_block; _field; _value],
[block_approx; _field_approx; value_approx] ->
- if A.is_definitely_immutable block_approx then begin
+ if A.warn_on_mutation block_approx then begin
Location.prerr_warning (Debuginfo.to_location dbg)
Warnings.Assignment_to_non_mutable_value
end;
- let kind = match A.descr block_approx, A.descr value_approx with
- | (Value_float_array _, _)
- | (_, Value_float _) ->
- begin match kind with
+ let kind =
+ let check () =
+ match kind with
| Pfloatarray | Pgenarray -> ()
| Paddrarray | Pintarray ->
(* CR pchambart: Do a proper warning here *)
Misc.fatal_errorf "Assignment of a float to a specialised \
non-float array: %a"
Flambda.print_named tree
- end;
- Lambda.Pfloatarray
+ in
+ match A.descr block_approx, A.descr value_approx with
+ | (Value_float_array _, _) -> check (); Lambda.Pfloatarray
+ | (_, Value_float _) when Config.flat_float_array ->
+ check (); Lambda.Pfloatarray
(* CR pchambart: This should be accounted by the benefit *)
| _ ->
kind
in
Prim (prim, args, dbg), ret r (A.value_unknown Other)
| Psetfield _, _block::_, block_approx::_ ->
- if A.is_definitely_immutable block_approx then begin
+ if A.warn_on_mutation block_approx then begin
Location.prerr_warning (Debuginfo.to_location dbg)
Warnings.Assignment_to_non_mutable_value
end;
env
else
let env =
- List.fold_left (fun env (symbol, constant_defining_value) ->
+ List.fold_left (fun newenv (symbol, constant_defining_value) ->
let approx =
constant_defining_value_approx env constant_defining_value
in
- E.redefine_symbol env symbol approx)
+ let approx = A.augment_with_symbol approx symbol in
+ E.redefine_symbol newenv symbol approx)
env defs
in
loop (times-1) env
| Let_rec_symbol (defs, program) ->
let env = define_let_rec_symbol_approx env defs in
let env, r, defs =
- List.fold_left (fun (env, r, defs) (symbol, def) ->
+ List.fold_left (fun (newenv, r, defs) (symbol, def) ->
let r, def, approx =
simplify_constant_defining_value env r symbol def
in
let approx = A.augment_with_symbol approx symbol in
- let env = E.redefine_symbol env symbol approx in
- (env, r, (symbol, def) :: defs))
+ let newenv = E.redefine_symbol newenv symbol approx in
+ (newenv, r, (symbol, def) :: defs))
(env, r, []) defs
in
let program, r = simplify_program_body env r program in
try
Set_of_closures_origin.Map.find origin t.actively_unrolling
with Not_found ->
- Misc.fatal_error "Unexpected actively unrolled function";
+ Misc.fatal_error "Unexpected actively unrolled function"
in
let actively_unrolling =
Set_of_closures_origin.Map.add origin (unrolling - 1) t.actively_unrolling
match only_for_function_decl with
| None -> true
| Some function_decl ->
- Variable.Set.mem param (Variable.Set.of_list function_decl.params)
+ Variable.Set.mem param (Parameter.Set.vars function_decl.params)
in
if not keep then None
else
with Not_found -> (A.value_unknown Other)
in
E.add env id approx)
- env function_decl.params
+ env (Parameter.List.vars function_decl.params)
in
env
val set_approx : t -> Simple_value_approx.t -> t
(** Set the approximation of the subexpression to the meet of the
- current return aprroximation and the provided one. Typically
+ current return approximation and the provided one. Typically
used just before returning from a branch case of the
simplification algorithm. *)
val meet_approx : t -> Env.t -> Simple_value_approx.t -> t
let estimate = if t.estimate then "<" else "=" in
Printf.sprintf "{benefit%s{call=%d,alloc=%d,prim=%i,branch=%i,\
indirect=%i,req=%i,\
- lifting=%b}, orig_size=%d,new_size=%d,eval_size=%d,\
+ lifting=%B}, orig_size=%d,new_size=%d,eval_size=%d,\
eval_benefit%s%d,\
branch_depth=%d}=%s"
estimate
(fun id approx ->
not ((A.useful approx)
&& Variable.Map.mem id (Lazy.force invariant_params)))
- function_decl.params args_approxs)
+ (Parameter.List.vars function_decl.params) args_approxs)
in
let always_specialise, never_specialise =
(* Merge call site annotation and function annotation.
let copy_of_function's_body_with_freshened_params env
~(function_decl : Flambda.function_declaration) =
let params = function_decl.params in
+ let param_vars = Parameter.List.vars params in
(* We cannot avoid the substitution in the case where we are inlining
inside the function itself. This can happen in two ways: either
(a) we are inlining the function itself directly inside its declaration;
original [params] may still be referenced; for (b) we cannot do it
either since the freshening may already be renaming the parameters for
the first inlining of the function. *)
- if E.does_not_bind env params
- && E.does_not_freshen env params
+ if E.does_not_bind env param_vars
+ && E.does_not_freshen env param_vars
then
params, function_decl.body
else
- let freshened_params = List.map (fun var -> Variable.rename var) params in
- let subst = Variable.Map.of_list (List.combine params freshened_params) in
+ let freshened_params = List.map (fun p -> Parameter.rename p) params in
+ let subst =
+ Variable.Map.of_list
+ (List.combine param_vars (Parameter.List.vars freshened_params))
+ in
let body = Flambda_utils.toplevel_substitution subst function_decl.body in
freshened_params, body
let bindings_for_params_to_args =
(* Bind the function's parameters to the arguments from the call site. *)
let args = List.map (fun arg -> Flambda.Expr (Var arg)) args in
- Flambda_utils.bind ~body ~bindings:(List.combine freshened_params args)
+ Flambda_utils.bind ~body
+ ~bindings:(List.combine (Parameter.List.vars freshened_params) args)
in
(* Add bindings for the variables bound by the closure. *)
let bindings_for_vars_bound_by_closure_and_params_to_args =
let specialised_args_set = Variable.Map.keys specialised_args in
let worth_specialising_args, specialisable_args, args, args_decl =
which_function_parameters_can_we_specialise
- ~params:function_decl.params ~args ~args_approxs
+ ~params:(Parameter.List.vars function_decl.params) ~args ~args_approxs
~invariant_params
~specialised_args:specialised_args_set
in
let function_variable_alias = function_variable_alias ~backend decls in
let param_indexes_by_fun_vars =
Variable.Map.map (fun (decl : Flambda.function_declaration) ->
- Array.of_list decl.params)
+ Array.of_list (Parameter.List.vars decl.params))
decls.funs
in
let find_callee_arg ~callee ~callee_pos =
let new_relation =
(* We only track dataflow for parameters of functions, not
arbitrary variables. *)
- if List.mem caller_arg params then
+ if List.exists
+ (fun param -> Variable.equal (Parameter.var param) caller_arg)
+ params
+ then
param_to_param ~caller ~caller_arg ~callee ~callee_arg !relation
else begin
used_variable caller_arg;
Variable.Map.iter
(fun func_var ({ params } : Flambda.function_declaration) ->
List.iter
- (fun param ->
- if Variable.Tbl.mem used_variables param then
+ (fun (param : Parameter.t) ->
+ if Variable.Tbl.mem used_variables (Parameter.var param) then
relation :=
- param_to_anywhere ~caller:func_var ~caller_arg:param !relation;
+ param_to_anywhere ~caller:func_var
+ ~caller_arg:(Parameter.var param) !relation;
if Variable.Tbl.mem escaping_functions func_var then
relation :=
- anything_to_param ~callee:func_var ~callee_arg:param !relation)
+ anything_to_param ~callee:func_var
+ ~callee_arg:(Parameter.var param) !relation)
params)
decls.funs;
transitive_closure !relation
in
let params = Variable.Map.fold (fun _
({ params } : Flambda.function_declaration) set ->
- Variable.Set.union (Variable.Set.of_list params) set)
+ Variable.Set.union (Parameter.Set.vars params) set)
decls.funs Variable.Set.empty
in
let unchanging = Variable.Set.diff params not_unchanging in
| exception Not_found -> Variable.Set.add param acc
| Implication _ -> Variable.Set.add param acc
| Top -> acc)
- acc decl.Flambda.params)
+ acc (Parameter.List.vars decl.Flambda.params))
decls.funs Variable.Set.empty
in
if dump then begin
[Inconstant_idents] is a "backwards" analysis that propagates implications
about inconstantness of variables and set of closures IDs.
- [Alias_analysis] is a "forwards" analysis that is analagous to the
+ [Alias_analysis] is a "forwards" analysis that is analogous to the
propagation of [Simple_value_approx.t] values during [Inline_and_simplify].
It gives us information about relationships between values but not actually
about their constantness.
[Let]-expressions typically come from the compilation of modules (using
the bytecode strategy) in [Translmod].
- This means of compilation supercedes the old "transl_store_" methodology
+ This means of compilation supersedes the old "transl_store_" methodology
for native code.
An [Initialize_symbol] construction generated by this pass may be
| None -> assert false)
set_of_closures.function_decls.funs)
-let middle_end ppf ~source_provenance ~prefixname ~backend
+let middle_end ppf ~prefixname ~backend
~size
~filename
~module_ident
~module_initializer =
- let pass_number = ref 0 in
- let round_number = ref 0 in
- let check flam =
- if !Clflags.flambda_invariant_checks then begin
- try Flambda_invariants.check_exn flam
- with exn ->
- Misc.fatal_errorf "After Flambda pass %d, round %d:@.%s:@.%a"
- !pass_number !round_number (Printexc.to_string exn)
- Flambda.print_program flam
- end
- in
- let (+-+) flam (name, pass) =
- incr pass_number;
- if !Clflags.dump_flambda_verbose then begin
- Format.fprintf ppf "@.PASS: %s@." name;
- Format.fprintf ppf "Before pass %d, round %d:@ %a@." !pass_number
- !round_number Flambda.print_program flam;
- Format.eprintf "\n@?"
- end;
- let timing_pass = (Timings.Flambda_pass (name, source_provenance)) in
- let flam = Timings.accumulate_time timing_pass pass flam in
- if !Clflags.flambda_invariant_checks then begin
- Timings.accumulate_time (Flambda_pass ("check", source_provenance))
- check flam
- end;
- flam
- in
- Timings.accumulate_time
- (Flambda_pass ("middle_end", source_provenance)) (fun () ->
- let flam =
- let timing_pass =
- Timings.Flambda_pass ("closure_conversion", source_provenance)
- in
- Timings.accumulate_time timing_pass (fun () ->
- module_initializer
- |> Closure_conversion.lambda_to_flambda ~backend ~module_ident
- ~size ~filename)
- ()
+ Profile.record_call "flambda" (fun () ->
+ let previous_warning_printer = !Location.warning_printer in
+ let module WarningSet =
+ Set.Make (struct
+ type t = Location.t * Warnings.t
+ let compare = Pervasives.compare
+ end)
in
- if !Clflags.dump_rawflambda
- then
- Format.fprintf ppf "After closure conversion:@ %a@."
- Flambda.print_program flam;
- check flam;
- let fast_mode flam =
- pass_number := 0;
- let round = 0 in
- flam
- +-+ ("lift_lets 1", Lift_code.lift_lets)
- +-+ ("Lift_constants", Lift_constants.lift_constants ~backend)
- +-+ ("Share_constants", Share_constants.share_constants)
- +-+ ("Lift_let_to_initialize_symbol",
- Lift_let_to_initialize_symbol.lift ~backend)
- +-+ ("Inline_and_simplify",
- Inline_and_simplify.run ~never_inline:false ~backend
- ~prefixname ~round)
- +-+ ("Remove_unused_closure_vars 2",
- Remove_unused_closure_vars.remove_unused_closure_variables
- ~remove_direct_call_surrogates:false)
- +-+ ("Ref_to_variables",
- Ref_to_variables.eliminate_ref)
- +-+ ("Initialize_symbol_to_let_symbol",
- Initialize_symbol_to_let_symbol.run)
+ let warning_set = ref WarningSet.empty in
+ let flambda_warning_printer loc _fmt w =
+ let elt = loc, w in
+ if not (WarningSet.mem elt !warning_set) then begin
+ warning_set := WarningSet.add elt !warning_set;
+ previous_warning_printer loc !Location.formatter_for_warnings w
+ end;
in
- let rec loop flam =
- pass_number := 0;
- let round = !round_number in
- incr round_number;
- if !round_number > (Clflags.rounds ()) then flam
- else
- flam
- (* Beware: [Lift_constants] must be run before any pass that might
- duplicate strings. *)
- +-+ ("lift_lets 1", Lift_code.lift_lets)
- +-+ ("Lift_constants", Lift_constants.lift_constants ~backend)
- +-+ ("Share_constants", Share_constants.share_constants)
- +-+ ("Remove_unused_program_constructs",
- Remove_unused_program_constructs.remove_unused_program_constructs)
- +-+ ("Lift_let_to_initialize_symbol",
- Lift_let_to_initialize_symbol.lift ~backend)
- +-+ ("lift_lets 2", Lift_code.lift_lets)
- +-+ ("Remove_unused_closure_vars 1",
- Remove_unused_closure_vars.remove_unused_closure_variables
- ~remove_direct_call_surrogates:false)
- +-+ ("Inline_and_simplify",
- Inline_and_simplify.run ~never_inline:false ~backend
- ~prefixname ~round)
- +-+ ("Remove_unused_closure_vars 2",
- Remove_unused_closure_vars.remove_unused_closure_variables
- ~remove_direct_call_surrogates:false)
- +-+ ("lift_lets 3", Lift_code.lift_lets)
- +-+ ("Inline_and_simplify noinline",
- Inline_and_simplify.run ~never_inline:true ~backend
- ~prefixname ~round)
- +-+ ("Remove_unused_closure_vars 3",
- Remove_unused_closure_vars.remove_unused_closure_variables
- ~remove_direct_call_surrogates:false)
- +-+ ("Ref_to_variables",
- Ref_to_variables.eliminate_ref)
- +-+ ("Initialize_symbol_to_let_symbol",
- Initialize_symbol_to_let_symbol.run)
- |> loop
- in
- let back_end flam =
- flam
- +-+ ("Remove_unused_closure_vars",
- Remove_unused_closure_vars.remove_unused_closure_variables
- ~remove_direct_call_surrogates:true)
- +-+ ("Lift_constants", Lift_constants.lift_constants ~backend)
- +-+ ("Share_constants", Share_constants.share_constants)
- +-+ ("Remove_unused_program_constructs",
- Remove_unused_program_constructs.remove_unused_program_constructs)
- in
- let flam =
- if !Clflags.classic_inlining then
- fast_mode flam
- else
- loop flam
- in
- let flam = back_end flam in
- (* Check that there aren't any unused "always inline" attributes. *)
- Flambda_iterators.iter_apply_on_program flam ~f:(fun apply ->
- match apply.inline with
- | Default_inline | Never_inline -> ()
- | Always_inline ->
- (* CR-someday mshinwell: consider a different error message if
- this triggers as a result of the propagation of a user's
- attribute into the second part of an over application
- (inline_and_simplify.ml line 710). *)
- Location.prerr_warning (Debuginfo.to_location apply.dbg)
- (Warnings.Inlining_impossible "[@inlined] attribute was not \
- used on this function application (the optimizer did not \
- know what function was being applied)")
- | Unroll _ ->
- Location.prerr_warning (Debuginfo.to_location apply.dbg)
- (Warnings.Inlining_impossible "[@unroll] attribute was not \
- used on this function application (the optimizer did not \
- know what function was being applied)"));
- if !Clflags.dump_flambda
- then
- Format.fprintf ppf "End of middle end:@ %a@."
- Flambda.print_program flam;
- check flam;
- (* CR-someday mshinwell: add -d... option for this *)
- (* dump_function_sizes flam ~backend; *)
- flam) ();
+ Misc.protect_refs
+ [Misc.R (Location.warning_printer, flambda_warning_printer)]
+ (fun () ->
+ let pass_number = ref 0 in
+ let round_number = ref 0 in
+ let check flam =
+ if !Clflags.flambda_invariant_checks then begin
+ try Flambda_invariants.check_exn flam
+ with exn ->
+ Misc.fatal_errorf "After Flambda pass %d, round %d:@.%s:@.%a"
+ !pass_number !round_number (Printexc.to_string exn)
+ Flambda.print_program flam
+ end
+ in
+ let (+-+) flam (name, pass) =
+ incr pass_number;
+ if !Clflags.dump_flambda_verbose then begin
+ Format.fprintf ppf "@.PASS: %s@." name;
+ Format.fprintf ppf "Before pass %d, round %d:@ %a@." !pass_number
+ !round_number Flambda.print_program flam;
+ Format.eprintf "\n@?"
+ end;
+ let flam = Profile.record ~accumulate:true name pass flam in
+ if !Clflags.flambda_invariant_checks then begin
+ Profile.record ~accumulate:true "check" check flam
+ end;
+ flam
+ in
+ Profile.record_call ~accumulate:true "middle_end" (fun () ->
+ let flam =
+ Profile.record_call ~accumulate:true "closure_conversion"
+ (fun () ->
+ module_initializer
+ |> Closure_conversion.lambda_to_flambda ~backend
+ ~module_ident ~size ~filename)
+ in
+ if !Clflags.dump_rawflambda
+ then
+ Format.fprintf ppf "After closure conversion:@ %a@."
+ Flambda.print_program flam;
+ check flam;
+ let fast_mode flam =
+ pass_number := 0;
+ let round = 0 in
+ flam
+ +-+ ("lift_lets 1", Lift_code.lift_lets)
+ +-+ ("Lift_constants", Lift_constants.lift_constants ~backend)
+ +-+ ("Share_constants", Share_constants.share_constants)
+ +-+ ("Lift_let_to_initialize_symbol",
+ Lift_let_to_initialize_symbol.lift ~backend)
+ +-+ ("Inline_and_simplify",
+ Inline_and_simplify.run ~never_inline:false ~backend
+ ~prefixname ~round)
+ +-+ ("Remove_unused_closure_vars 2",
+ Remove_unused_closure_vars.remove_unused_closure_variables
+ ~remove_direct_call_surrogates:false)
+ +-+ ("Ref_to_variables",
+ Ref_to_variables.eliminate_ref)
+ +-+ ("Initialize_symbol_to_let_symbol",
+ Initialize_symbol_to_let_symbol.run)
+ in
+ let rec loop flam =
+ pass_number := 0;
+ let round = !round_number in
+ incr round_number;
+ if !round_number > (Clflags.rounds ()) then flam
+ else
+ flam
+ (* Beware: [Lift_constants] must be run before any pass that
+ might duplicate strings. *)
+ +-+ ("lift_lets 1", Lift_code.lift_lets)
+ +-+ ("Lift_constants", Lift_constants.lift_constants ~backend)
+ +-+ ("Share_constants", Share_constants.share_constants)
+ +-+ ("Remove_unused_program_constructs",
+ Remove_unused_program_constructs.remove_unused_program_constructs)
+ +-+ ("Lift_let_to_initialize_symbol",
+ Lift_let_to_initialize_symbol.lift ~backend)
+ +-+ ("lift_lets 2", Lift_code.lift_lets)
+ +-+ ("Remove_unused_closure_vars 1",
+ Remove_unused_closure_vars.remove_unused_closure_variables
+ ~remove_direct_call_surrogates:false)
+ +-+ ("Inline_and_simplify",
+ Inline_and_simplify.run ~never_inline:false ~backend
+ ~prefixname ~round)
+ +-+ ("Remove_unused_closure_vars 2",
+ Remove_unused_closure_vars.remove_unused_closure_variables
+ ~remove_direct_call_surrogates:false)
+ +-+ ("lift_lets 3", Lift_code.lift_lets)
+ +-+ ("Inline_and_simplify noinline",
+ Inline_and_simplify.run ~never_inline:true ~backend
+ ~prefixname ~round)
+ +-+ ("Remove_unused_closure_vars 3",
+ Remove_unused_closure_vars.remove_unused_closure_variables
+ ~remove_direct_call_surrogates:false)
+ +-+ ("Ref_to_variables",
+ Ref_to_variables.eliminate_ref)
+ +-+ ("Initialize_symbol_to_let_symbol",
+ Initialize_symbol_to_let_symbol.run)
+ |> loop
+ in
+ let back_end flam =
+ flam
+ +-+ ("Remove_unused_closure_vars",
+ Remove_unused_closure_vars.remove_unused_closure_variables
+ ~remove_direct_call_surrogates:true)
+ +-+ ("Lift_constants", Lift_constants.lift_constants ~backend)
+ +-+ ("Share_constants", Share_constants.share_constants)
+ +-+ ("Remove_unused_program_constructs",
+ Remove_unused_program_constructs.remove_unused_program_constructs)
+ in
+ let flam =
+ if !Clflags.classic_inlining then
+ fast_mode flam
+ else
+ loop flam
+ in
+ let flam = back_end flam in
+ (* Check that there aren't any unused "always inline" attributes. *)
+ Flambda_iterators.iter_apply_on_program flam ~f:(fun apply ->
+ match apply.inline with
+ | Default_inline | Never_inline -> ()
+ | Always_inline ->
+ (* CR-someday mshinwell: consider a different error message if
+ this triggers as a result of the propagation of a user's
+ attribute into the second part of an over application
+ (inline_and_simplify.ml line 710). *)
+ Location.prerr_warning (Debuginfo.to_location apply.dbg)
+ (Warnings.Inlining_impossible
+ "[@inlined] attribute was not used on this function \
+ application (the optimizer did not know what function \
+ was being applied)")
+ | Unroll _ ->
+ Location.prerr_warning (Debuginfo.to_location apply.dbg)
+ (Warnings.Inlining_impossible
+ "[@unroll] attribute was not used on this function \
+ application (the optimizer did not know what function \
+ was being applied)"));
+ if !Clflags.dump_flambda
+ then
+ Format.fprintf ppf "End of middle end:@ %a@."
+ Flambda.print_program flam;
+ check flam;
+ (* CR-someday mshinwell: add -d... option for this *)
+ (* dump_function_sizes flam ~backend; *)
+ flam))
+ )
val middle_end
: Format.formatter
- -> source_provenance:Timings.source_provenance
-> prefixname:string
-> backend:(module Backend_intf.S)
-> size:int
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Pierre Chambart, OCamlPro *)
+(* Mark Shinwell and Leo White, Jane Street Europe *)
+(* *)
+(* Copyright 2013--2016 OCamlPro SAS *)
+(* Copyright 2014--2016 Jane Street Group LLC *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+[@@@ocaml.warning "+a-4-9-30-40-41-42"]
+
+[@@@ocaml.warning "+9"]
+(* Warning 9 is enabled to ensure correct update of each function when
+ a field is added to type parameter *)
+
+type parameter = {
+ var : Variable.t;
+}
+
+let wrap var = { var }
+
+let var p = p.var
+
+module M =
+ Identifiable.Make (struct
+ type t = parameter
+
+ let compare { var = var1 } { var = var2 } =
+ Variable.compare var1 var2
+
+ let equal { var = var1 } { var = var2 } =
+ Variable.equal var1 var2
+
+ let hash { var } =
+ Variable.hash var
+
+ let print ppf { var } =
+ Variable.print ppf var
+
+ let output o { var } =
+ Variable.output o var
+ end)
+
+module T = M.T
+include T
+
+module Map = M.Map
+module Tbl = M.Tbl
+module Set = struct
+ include M.Set
+ let vars l = Variable.Set.of_list (List.map var l)
+end
+
+let rename ?current_compilation_unit ?append p =
+ { var = Variable.rename ?current_compilation_unit ?append p.var }
+
+let map_var f { var } = { var = f var }
+
+module List = struct
+ let vars params = List.map (fun { var } -> var) params
+end
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Pierre Chambart, OCamlPro *)
+(* Mark Shinwell and Leo White, Jane Street Europe *)
+(* *)
+(* Copyright 2013--2016 OCamlPro SAS *)
+(* Copyright 2014--2016 Jane Street Group LLC *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+[@@@ocaml.warning "+a-4-9-30-40-41-42"]
+
+(** [Parameter.t] carries a unique [Variable.t] used as function parameter.
+ It can also carry annotations about the usage of the variable. *)
+
+type t
+type parameter = t
+
+(** Make a parameter from a variable with default attributes *)
+val wrap : Variable.t -> t
+
+val var : t -> Variable.t
+
+(** Rename the inner variable of the parameter *)
+val rename
+ : ?current_compilation_unit:Compilation_unit.t
+ -> ?append:string
+ -> t
+ -> t
+
+val map_var : (Variable.t -> Variable.t) -> t -> t
+
+module T : Identifiable.Thing with type t = t
+
+module Set : sig
+ include Identifiable.Set with module T := T
+ val vars : parameter list -> Variable.Set.t
+end
+
+include Identifiable.S with type t := t
+ and module T := T
+ and module Set := Set
+
+module List : sig
+ (** extract variables from a list of parameters, preserving the order *)
+ val vars : t list -> Variable.t list
+end
Variable.Set.fold (fun free_var subst ->
Variable.Map.add free_var param subst)
set subst)
- Variable.Map.empty function_decl.params
+ Variable.Map.empty (Parameter.List.vars function_decl.params)
in
if Variable.Map.is_empty params_for_equal_free_vars then
function_decl
let remove_params unused (fun_decl: Flambda.function_declaration) =
let unused_params, used_params =
- List.partition (fun v -> Variable.Set.mem v unused) fun_decl.params
+ List.partition (fun v -> Variable.Set.mem (Parameter.var v) unused)
+ fun_decl.params
in
let unused_params = List.filter (fun v ->
- Variable.Set.mem v fun_decl.free_variables) unused_params
+ Variable.Set.mem (Parameter.var v) fun_decl.free_variables) unused_params
in
let body =
- List.fold_left (fun body var ->
- Flambda.create_let var (Const (Const_pointer 0)) body)
+ List.fold_left (fun body param ->
+ Flambda.create_let (Parameter.var param) (Const (Const_pointer 0)) body)
fun_decl.body
unused_params
in
~specialised_args ~additional_specialised_args =
let renamed = rename_var var in
let args' =
- List.map (fun var -> var, rename_var var) fun_decl.params
+ List.map (fun param -> param, Parameter.rename param) fun_decl.params
in
let used_args' =
- List.filter (fun (var, _) -> not (Variable.Set.mem var unused)) args'
+ List.filter (fun (param, _) ->
+ not (Variable.Set.mem (Parameter.var param) unused)) args'
in
- let args_renaming = Variable.Map.of_list args' in
+ let args'_var =
+ List.map (fun (p1, p2) -> Parameter.var p1, Parameter.var p2) args'
+ in
+ let args_renaming = Variable.Map.of_list args'_var in
let additional_specialised_args =
List.fold_left (fun additional_specialised_args (original_arg,arg) ->
match Variable.Map.find original_arg specialised_args with
}
in
Variable.Map.add arg outer_var additional_specialised_args)
- additional_specialised_args args'
+ additional_specialised_args args'_var
in
let args = List.map (fun (_, var) -> var) used_args' in
let kind = Flambda.Direct (Closure_id.wrap renamed) in
let body : Flambda.t =
Apply {
func = renamed;
- args;
+ args = Parameter.List.vars args;
kind;
dbg = fun_decl.dbg;
inline = Default_inline;
if decl.stub then
acc
else
- Variable.Set.union acc (Variable.Set.of_list decl.Flambda.params))
+ Variable.Set.union acc (Parameter.Set.vars decl.Flambda.params))
function_decls.funs Variable.Set.empty
in
let unused = Variable.Set.inter non_stub_arguments unused in
let funs, additional_specialised_args =
Variable.Map.fold (fun fun_id (fun_decl : Flambda.function_declaration)
(funs, additional_specialised_args) ->
- if List.exists (fun v -> Variable.Set.mem v unused) fun_decl.params
+ if List.exists (fun v -> Variable.Set.mem (Parameter.var v) unused)
+ fun_decl.params
then begin
let stub, renamed_fun_id, additional_specialised_args =
make_stub unused fun_id fun_decl
(* Remove specialised args that are used by removed functions *)
let all_remaining_arguments =
Variable.Map.fold (fun _ { Flambda.params } set ->
- Variable.Set.union set (Variable.Set.of_list params))
+ Variable.Set.union set (Parameter.Set.vars params))
funs Variable.Set.empty
in
Variable.Map.filter (fun arg _ ->
lazy (
let functions = Variable.Map.keys function_decls.funs in
Variable.Map.map (fun (function_decl : Flambda.function_declaration) ->
- let params = Variable.Set.of_list function_decl.params in
+ let params = Parameter.Set.vars function_decl.params in
let free_vars =
Variable.Set.diff
(Variable.Set.diff function_decl.free_variables params)
let all_not_useful ts = List.for_all (fun t -> not (useful t)) ts
-let is_definitely_immutable t =
+let warn_on_mutation t =
match t.descr with
+ | Value_block(_, fields) -> Array.length fields > 0
| Value_string { contents = Some _ }
- | Value_block _ | Value_int _ | Value_char _ | Value_constptr _
+ | Value_int _ | Value_char _ | Value_constptr _
| Value_set_of_closures _ | Value_float _ | Value_boxed_int _
| Value_closure _ -> true
| Value_string { contents = None } | Value_float_array _
(** Whether all approximations in the given list do *not* satisfy [useful]. *)
val all_not_useful : t list -> bool
-(** A value is certainly immutable if its approximation is known and not bottom.
+(** Whether to warn on attempts to mutate a value.
It must have been resolved (it cannot be [Value_extern] or
[Value_symbol]). (See comment above for further explanation.) *)
-val is_definitely_immutable : t -> bool
+val warn_on_mutation : t -> bool
type simplification_summary =
| Nothing_done
| Some (s1, Some f1), Some (s2, Some f2) -> Symbol.equal s1 s2 && f1 = f2
| _ -> false
+let is_known_to_be_some_kind_of_int (arg:A.descr) =
+ match arg with
+ | Value_int _ | Value_char _ | Value_constptr _ -> true
+ | Value_block (_, _) | Value_float _ | Value_set_of_closures _
+ | Value_closure _ | Value_string _ | Value_float_array _
+ | A.Value_boxed_int _ | Value_unknown _ | Value_extern _
+ | Value_symbol _ | Value_unresolved _ | Value_bottom -> false
+
+let is_known_to_be_some_kind_of_block (arg:A.descr) =
+ match arg with
+ | Value_block _ | Value_float _ | Value_float_array _ | A.Value_boxed_int _
+ | Value_closure _ | Value_string _ -> true
+ | Value_set_of_closures _ | Value_int _ | Value_char _ | Value_constptr _
+ | Value_unknown _ | Value_extern _ | Value_symbol _
+ | Value_unresolved _ | Value_bottom -> false
+
+let rec structurally_different (arg1:A.t) (arg2:A.t) =
+ match arg1.descr, arg2.descr with
+ | (Value_int n1 | Value_constptr n1), (Value_int n2 | Value_constptr n2)
+ when n1 <> n2 ->
+ true
+ | Value_block (tag1, fields1), Value_block (tag2, fields2) ->
+ not (Tag.equal tag1 tag2)
+ || (Array.length fields1 <> Array.length fields2)
+ || Misc.Stdlib.Array.exists2 structurally_different fields1 fields2
+ | descr1, descr2 ->
+ (* This is not very precise as this won't allow to distinguish
+ blocks from strings for instance. This can be improved if it
+ is deemed valuable. *)
+ (is_known_to_be_some_kind_of_int descr1
+ && is_known_to_be_some_kind_of_block descr2)
+ || (is_known_to_be_some_kind_of_block descr1
+ && is_known_to_be_some_kind_of_int descr2)
+
+let phys_different (approxs:A.t list) =
+ match approxs with
+ | [] | [_] | _ :: _ :: _ :: _ ->
+ Misc.fatal_error "wrong number of arguments for equality"
+ | [a1; a2] ->
+ structurally_different a1 a2
+
let primitive (p : Lambda.primitive) (args, approxs) expr dbg ~size_int
~big_endian : Flambda.named * A.t * Inlining_cost.Benefit.t =
let fpc = !Clflags.float_const_prop in
S.const_ptr_expr (Flambda.Expr (Var arg)) 0
| _ -> S.const_ptr_expr expr 0
end
+ | Pmakearray(_, _) when approxs = [] ->
+ Prim (Pmakeblock(0, Asttypes.Immutable, Some []), [], dbg),
+ A.value_block (Tag.create_exn 0) [||], C.Benefit.zero
| Pmakearray (Pfloatarray, Mutable) ->
let approx =
A.value_mutable_float_array ~size:(List.length args)
inlined later, [a] and [b] could be shared and thus [c] and [d] could
be too. As such, any intermediate non-aliasing judgement would be
invalid. *)
+ | Pintcomp Ceq when phys_different approxs ->
+ S.const_bool_expr expr false
+ | Pintcomp Cneq when phys_different approxs ->
+ S.const_bool_expr expr true
+ (* If two values are structurally different we are certain they can never
+ be shared*)
| _ ->
match A.descrs approxs with
| [Value_int x] ->
-generators/odoc_literate.cmo : odoc_info.cmi odoc_html.cmo odoc_gen.cmi \
- odoc_args.cmi
-generators/odoc_literate.cmx : odoc_info.cmx odoc_html.cmx odoc_gen.cmx \
- odoc_args.cmx
-generators/odoc_todo.cmo : odoc_module.cmo odoc_info.cmi odoc_html.cmo \
- odoc_gen.cmi odoc_args.cmi
-generators/odoc_todo.cmx : odoc_module.cmx odoc_info.cmx odoc_html.cmx \
- odoc_gen.cmx odoc_args.cmx
odoc.cmo : odoc_messages.cmo odoc_info.cmi odoc_global.cmi odoc_gen.cmi \
odoc_config.cmi odoc_args.cmi odoc_analyse.cmi
odoc.cmx : odoc_messages.cmx odoc_info.cmx odoc_global.cmx odoc_gen.cmx \
../driver/pparse.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/longident.cmi ../parsing/location.cmi ../parsing/lexer.cmi \
- ../typing/env.cmi ../utils/config.cmi ../utils/clflags.cmi \
- ../parsing/asttypes.cmi odoc_analyse.cmi
+ odoc_comments.cmi odoc_class.cmo odoc_ast.cmi ../parsing/longident.cmi \
+ ../parsing/location.cmi ../parsing/lexer.cmi ../typing/env.cmi \
+ ../utils/config.cmi ../utils/clflags.cmi ../parsing/asttypes.cmi \
+ odoc_analyse.cmi
odoc_analyse.cmx : ../utils/warnings.cmx ../typing/types.cmx \
../typing/typemod.cmx ../typing/typedtree.cmx ../parsing/syntaxerr.cmx \
../driver/pparse.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/longident.cmx ../parsing/location.cmx ../parsing/lexer.cmx \
- ../typing/env.cmx ../utils/config.cmx ../utils/clflags.cmx \
- ../parsing/asttypes.cmi odoc_analyse.cmi
+ odoc_comments.cmx odoc_class.cmx odoc_ast.cmx ../parsing/longident.cmx \
+ ../parsing/location.cmx ../parsing/lexer.cmx ../typing/env.cmx \
+ ../utils/config.cmx ../utils/clflags.cmx ../parsing/asttypes.cmi \
+ odoc_analyse.cmi
odoc_analyse.cmi : odoc_module.cmo odoc_global.cmi
odoc_args.cmo : ../utils/warnings.cmi odoc_types.cmi odoc_texi.cmo \
odoc_messages.cmo odoc_man.cmo odoc_latex.cmo odoc_html.cmo \
../parsing/parsetree.cmi odoc_value.cmo odoc_types.cmi odoc_type.cmo \
odoc_parameter.cmo odoc_module.cmo odoc_misc.cmi odoc_messages.cmo \
odoc_merge.cmi odoc_global.cmi odoc_extension.cmo odoc_exception.cmo \
- odoc_env.cmi odoc_class.cmo ../utils/misc.cmi ../parsing/location.cmi \
- ../typing/ident.cmi ../typing/ctype.cmi ../typing/btype.cmi \
- ../parsing/asttypes.cmi odoc_sig.cmi
+ odoc_env.cmi odoc_class.cmo ../utils/misc.cmi ../parsing/longident.cmi \
+ ../parsing/location.cmi ../typing/ident.cmi ../typing/ctype.cmi \
+ ../typing/btype.cmi ../parsing/asttypes.cmi odoc_sig.cmi
odoc_sig.cmx : ../typing/types.cmx ../typing/typedtree.cmx \
../parsing/parsetree.cmi odoc_value.cmx odoc_types.cmx odoc_type.cmx \
odoc_parameter.cmx odoc_module.cmx odoc_misc.cmx odoc_messages.cmx \
odoc_merge.cmx odoc_global.cmx odoc_extension.cmx odoc_exception.cmx \
- odoc_env.cmx odoc_class.cmx ../utils/misc.cmx ../parsing/location.cmx \
- ../typing/ident.cmx ../typing/ctype.cmx ../typing/btype.cmx \
- ../parsing/asttypes.cmi odoc_sig.cmi
+ odoc_env.cmx odoc_class.cmx ../utils/misc.cmx ../parsing/longident.cmx \
+ ../parsing/location.cmx ../typing/ident.cmx ../typing/ctype.cmx \
+ ../typing/btype.cmx ../parsing/asttypes.cmi odoc_sig.cmi
odoc_sig.cmi : ../typing/types.cmi ../typing/typedtree.cmi \
../parsing/parsetree.cmi odoc_types.cmi odoc_type.cmo odoc_name.cmi \
- odoc_module.cmo odoc_env.cmi odoc_class.cmo
+ odoc_module.cmo odoc_env.cmi odoc_class.cmo ../parsing/location.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_extension.cmo odoc_exception.cmo odoc_class.cmo \
odoc_parameter.cmo odoc_name.cmi odoc_misc.cmi ../parsing/asttypes.cmi
odoc_value.cmx : ../typing/types.cmx ../typing/printtyp.cmx odoc_types.cmx \
odoc_parameter.cmx odoc_name.cmx odoc_misc.cmx ../parsing/asttypes.cmi
+generators/odoc_literate.cmo : odoc_info.cmi odoc_html.cmo odoc_gen.cmi \
+ odoc_args.cmi
+generators/odoc_literate.cmx : odoc_info.cmx odoc_html.cmx odoc_gen.cmx \
+ odoc_args.cmx
+generators/odoc_literate.cmxs : odoc_info.cmx odoc_html.cmx odoc_gen.cmx \
+ odoc_args.cmx
+generators/odoc_todo.cmo : odoc_module.cmo odoc_info.cmi odoc_html.cmo \
+ odoc_gen.cmi odoc_args.cmi
+generators/odoc_todo.cmx : odoc_module.cmx odoc_info.cmx odoc_html.cmx \
+ odoc_gen.cmx odoc_args.cmx
+generators/odoc_todo.cmxs : odoc_module.cmx odoc_info.cmx odoc_html.cmx \
+ odoc_gen.cmx odoc_args.cmx
-I $(ROOTDIR)/otherlibs/str \
-I $(ROOTDIR)/otherlibs/dynlink \
-I $(ROOTDIR)/otherlibs/$(UNIXLIB) \
- -I $(ROOTDIR)/otherlibs/num \
-I $(ROOTDIR)/otherlibs/$(GRAPHLIB)
INCLUDES=$(INCLUDES_DEP) $(INCLUDES_NODEP)
../parsing/*.mli \
../otherlibs/$(UNIXLIB)/unix.mli \
../otherlibs/str/str.mli \
- ../otherlibs/bigarray/bigarray.mli \
- ../otherlibs/num/num.mli
+ ../otherlibs/bigarray/bigarray.mli
.PHONY: all
all: lib exe generators manpages
$(OCAMLLEX) odoc_lexer.mll
$(OCAMLLEX) odoc_ocamlhtml.mll
$(OCAMLLEX) odoc_see_lexer.mll
- $(OCAMLDEP) $(INCLUDES_DEP) *.mll *.mly *.ml *.mli generators/*.ml > .depend
+ $(OCAMLDEP) $(INCLUDES_DEP) *.mll *.mly *.ml *.mli > .depend
+ $(OCAMLDEP) $(INCLUDES_DEP) -shared generators/*.ml >> .depend
include .depend
List.iter
(fun (n, e) ->
Printf.bprintf b "<span style=\"color: %s\">" (col n);
- html#html_of_text b e;
+ html#html_of_text ?with_p:(Some false) b e;
p b "</span><br/>\n";
)
l;
(Odoc_html.Naming.complete_method_target m)
m.met_value.val_info
- (** This method scan the elements of the given module. *)
+ (** This method scans the elements of the given module. *)
method! scan_module_elements m =
List.iter
(fun ele ->
(** Return the initial environment in which compilation proceeds. *)
let initial_env () =
let initial =
- if !Clflags.unsafe_string then Env.initial_unsafe_string
+ if Config.safe_string then Env.initial_safe_string
+ else if !Clflags.unsafe_string then Env.initial_unsafe_string
else Env.initial_safe_string
in
- let initial =
- (* Open the Pervasives module by reading directly the corresponding cmi
- file to avoid troubles when building the documentation for the
- Pervasives modules.
- Another option might be to add a -nopervasives option to ocamldoc and update
- stdlib documentation's build process. *)
- try
- Env.open_pers_signature "Pervasives" initial
- with Not_found ->
- Misc.fatal_error @@ Printf.sprintf "cannot open pervasives.cmi" in
let open_mod env m =
let open Asttypes in
let lid = {loc = Location.in_file "ocamldoc command line";
snd (Typemod.type_open_ Override env lid.loc lid) in
(* Open the list of modules given as arguments of the "-open" flag
The list is reversed to open the modules in the left-to-right order *)
- List.fold_left open_mod initial (List.rev !Clflags.open_modules)
+ let to_open = List.rev !Clflags.open_modules in
+ let to_open =
+ if Env.get_unit_name () = "Pervasives"
+ then to_open
+ else "Pervasives" :: to_open
+ in
+ List.fold_left open_mod initial to_open
(** Optionally preprocess a source file *)
let preprocess sourcefile =
exit 2
(** Analysis of an implementation file. Returns (Some typedtree) if
- no error occured, else None and an error message is printed.*)
+ no error occurred, else None and an error message is printed.*)
let tool_name = "ocamldoc"
raise e
(** Analysis of an interface file. Returns (Some signature) if
- no error occured, else None and an error message is printed.*)
+ no error occurred, else None and an error message is printed.*)
let process_interface_file sourcefile =
init_path ();
let prefixname = Filename.chop_extension sourcefile in
(** Handle an error. *)
let process_error exn =
- match Location.error_of_exn exn with
- | Some err ->
- fprintf Format.err_formatter "@[%a@]@." Location.report_error err
- | None ->
- fprintf Format.err_formatter
- "Compilation error(%s). Use the OCaml compiler to get more details.@."
- (Printexc.to_string exn)
+ try Location.report_exception Format.err_formatter exn
+ with exn ->
+ fprintf Format.err_formatter
+ "Compilation error(%s). Use the OCaml compiler to get more details.@."
+ (Printexc.to_string exn)
(** Process the given file, according to its extension. Return the Module.t created, if any.*)
let process_file sourcefile =
None
| Some (parsetree, typedtree) ->
let file_module = Ast_analyser.analyse_typed_tree file
- !Location.input_name parsetree typedtree
+ input_file parsetree typedtree
in
file_module.Odoc_module.m_top_deps <- Odoc_dep.impl_dependencies parsetree ;
try
let (ast, signat, input_file) = process_interface_file file in
let file_module = Sig_analyser.analyse_signature file
- !Location.input_name ast signat.sig_type
+ input_file ast signat.sig_type
in
file_module.Odoc_module.m_top_deps <- Odoc_dep.intf_dependencies ast ;
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. *)
+(** Remove the class elements between 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) ->
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 _ ->
+ match String.split_on_char ',' s with
+ | [n;command] ->
+ let n = int_of_string n in
+ Odoc_latex.latex_titles := List.remove_assoc n !Odoc_latex.latex_titles ;
+ Odoc_latex.latex_titles := (n, command) :: !Odoc_latex.latex_titles
+ | _ ->
+ incr Odoc_global.errors ;
+ prerr_endline (M.wrong_format s)
+
+let f_texinfo_title s =
+ match String.split_on_char ',' s with
+ | [n;title;heading] ->
+ let n = int_of_string n in
+ Odoc_texi.titles_and_headings :=
+ (n, (title,heading) ) :: List.remove_assoc n !Odoc_texi.titles_and_headings;
+ | _ ->
incr Odoc_global.errors ;
prerr_endline (M.wrong_format s)
(* texi only options *)
"-noindex", Arg.Clear Odoc_global.with_index, M.no_index ;
"-esc8", Arg.Set Odoc_texi.esc_8bits, M.esc_8bits ;
+ "-texinfotitle", Arg.String f_texinfo_title,
+ M.texinfo_title Odoc_texi.titles_and_headings ;
+
"-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 ^
(** The name of the analysed file. *)
let file_name = Sig.file_name
- (** This function takes two indexes (start and end) and return the string
+ (** This function takes two indexes (start and end) and returns 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.
+ (** This function loads the given file in the file global variable
and sets file_name.*)
let prepare_file = Sig.prepare_file
in
iter [] [] last_pos (p_cls.Parsetree.pcstr_fields)
- (** Analysis of a [Parsetree.class_expr] and a [Typedtree.class_expr] to get a a couple (class parameters, class kind). *)
+ (** Analysis of a [Parsetree.class_expr] and a [Typedtree.class_expr] to get a pair (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 new_env = Odoc_env.add_module env new_module.m_name in
let new_env2 =
match new_module.m_type with
- (* FIXME : can this be Tmty_ident? In this case, we would'nt have the signature *)
+ (* FIXME : can this be Tmty_ident? In this case, we wouldn't have the signature *)
Types.Mty_signature s ->
Odoc_env.add_signature new_env new_module.m_name
~rel: (Name.simple new_module.m_name) s
let new_env = Odoc_env.add_module_type env mt.mt_name in
let new_env2 =
match sig_mtype with
- (* FIXME : can this be Tmty_ident? In this case, we would'nt have the signature *)
+ (* FIXME : can this be Tmty_ident? In this case, we wouldn't have the signature *)
Some (Types.Mty_signature s) ->
Odoc_env.add_signature new_env mt.mt_name ~rel: (Name.simple mt.mt_name) s
| _ ->
prepare_file source_file input_file;
(* We create the t_module for this file. *)
let mod_name = String.capitalize_ascii (Filename.basename (Filename.chop_extension source_file)) in
- let (len,info_opt) = My_ir.first_special !file_name !file in
-
+ let len, info_opt = Sig.preamble !file_name !file
+ (fun x -> x.Parsetree.pstr_loc) parsetree 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
module Analyser :
functor (My_ir : Odoc_sig.Info_retriever) ->
sig
- (** This function takes a file name, a file containg the code and
+ (** This function takes a file name, a file containing 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.*)
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 *)
+ mutable cco_class : cct option; (** The associated class of the class type if we found it *)
cco_type_parameters : Types.type_expr list; (** The type parameters of the class, if needed *)
}
| 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 :
+ when the class toto is defined like this :
class toto : int -> tutu *)
| Class_constraint of class_kind * class_type_kind
(** A class definition with a constraint. *)
}
-(** {2 Functions} *)
+(** {1 Functions} *)
(** Returns the text associated to the given parameter label
in the given class, or None. *)
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
+ @raise Failure if the file could not be opened or there is a
syntax error.
*)
val info_of_comment_file :
(* *)
(**************************************************************************)
-(** Ocamldoc configuration contants. *)
+(** Ocamldoc configuration constants. *)
(** Default path to search for custom generators and to install them. *)
val custom_generators_path : string
- if name = parent_name: we are using the name of an element
or module in its definition, no need of cross_reference
- if the path of name is a suffix of the parent path, we
- are in the same module, maybe the same function. To decreace
+ are in the same module, maybe the same function. To decrease
the false positive rate, we stop here *)
if name = parent_name || is_path_suffix () then
t_ele
let get_children d parents =
(* XXXX merge_children used to be declared as a recursive function,
- but it was not. I've not idea if it a bug or not. One should
+ but it was not. I've no idea if it is a bug or not. One should
either fix it (if this is a bug), or simplify the code otherwise. *)
let merge_children children el =
!l
-(** Modify the modules depencies of the given list of modules,
+(** Modify the module dependencies of the given list of modules,
to get the minimum transitivity kernel. *)
let kernel_deps_of_modules modules =
let graph = List.map
(** 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 '*'. *)
+(** We must remove 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. *)
(** The functions used for naming files and html marks.*)
module Naming =
struct
+ (** The prefix for modules marks. *)
+ let mark_module = "MODULE"
+
+ (** The prefix for module type marks. *)
+ let mark_module_type = "MODULETYPE"
+
(** The prefix for types marks. *)
let mark_type = "TYPE"
(** The prefix for methods marks. *)
let mark_method = "METHOD"
- (** The prefix for code files.. *)
+ (** The prefix for code files. *)
let code_prefix = "code_"
- (** The prefix for type files.. *)
+ (** The prefix for type files. *)
let type_prefix = "type_"
(** Return the two html files names for the given module or class name.*)
let (html_file, _) = html_files module_name in
html_file^"#"^(target pref simple_name)
+ (**return the link target for the given module. *)
+ let module_target m = target mark_module (Name.simple m.m_name)
+
+ (**return the link target for the given module type. *)
+ let module_type_target mt = target mark_module_type (Name.simple mt.mt_name)
+
(** Return the link target for the given type. *)
let type_target t = target mark_type (Name.simple t.ty_name)
| 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
+ method html_of_text ?(with_p=false) b t =
+ if not with_p then
+ List.iter (self#html_of_text_element b) t
+ else
+ self#html_of_text_with_p b t
+
+ method html_of_text_with_p b t =
+ (* In order to enclose the generated text in <p> </p>, we first
+ output the content inside a inner buffer b', and then generate
+ the whole paragraph, if the content is not empty,
+ either at the end of the text, at a Newline element or when
+ encountering an element that cannot be part of a paragraph element
+ *)
+ let b' = Buffer.create 17 (* paragraph buffer *) in
+ let flush b' =
+ (* trim the inner string to avoid outputting empty <p></p> *)
+ let s = String.trim @@ Buffer.contents b' in
+ if s <> "" then
+ begin
+ bp b "<p>";
+ bs b s;
+ bp b "</p>\n"
+ end;
+ Buffer.clear b' in
+ let rec iter txt =
+ match txt with
+ | [] ->
+ flush b' (* flush b' at the end of the text *)
+ | (List _ | Enum _ | Title _ | CodePre _ | Verbatim _ | Center _
+ | Left _ | Right _ | Newline | Index_list ) as a :: q
+ (* these elements cannot be part of <p> element *)
+ ->
+ flush b'; (* stop the current paragraph *)
+ self#html_of_text_element b a; (*output [a] directly on [b] *)
+ iter q
+ | a :: q -> self#html_of_text_element b' a; iter q
+ in
+ iter t
(** Print the html code for the [text_element] in parameter. *)
method html_of_text_element b txt =
tl;
bs b "</OL>\n"
- method html_of_Newline b = bs b "\n<p>\n"
+ method html_of_Newline b = bs b "\n"
method html_of_Block b t =
bs b "<blockquote>\n";
let label1 = self#create_title_label (n, label_opt, t) in
let (tag_o, tag_c) =
if n > 6 then
- (Printf.sprintf "div class=\"h%d\"" n, "div")
+ (Printf.sprintf "div class=\"h%d\"" (n+1), "div")
else
- let t = Printf.sprintf "h%d" n in (t, t)
+ let t = Printf.sprintf "h%d" (n+1) in (t, t)
in
bs b "<";
bp b "%s id=\"%s\"" tag_o (Naming.label_target label1);
method virtual html_of_info_first_sentence : _
method html_of_Module_list b l =
- bs b "<br>\n<table class=\"indextable\">\n";
+ bs b "\n<table class=\"indextable module-list\">\n";
List.iter
(fun name ->
bs b "<tr><td class=\"module\">";
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
+ method virtual html_of_text :
+ ?with_p:bool -> 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> " Odoc_messages.authors;
+ bp b "<li><b>%s:</b> " Odoc_messages.authors;
self#html_of_text b [Raw (String.concat ", " l)];
- bs b "<br>\n"
+ bs b "</li>\n"
(** 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> " Odoc_messages.version;
+ bp b "<li><b>%s:</b> " Odoc_messages.version;
self#html_of_text b [Raw v];
- bs b "<br>\n"
+ bs b "</li>\n"
(** 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> " Odoc_messages.since;
+ bp b "<li><b>%s</b> " Odoc_messages.since;
self#html_of_text b [Raw s];
- bs b "<br>\n"
+ bs b "</li>\n"
(** Print html code for the given "before" information.*)
method html_of_before b l =
let f (v, text) =
- bp b "<b>%s " Odoc_messages.before;
+ bp b "<li><b>%s " Odoc_messages.before;
self#html_of_text b [Raw v];
bs b " </b> ";
self#html_of_text b text;
- bs b "<br>\n"
+ bs b "</li>\n"
in
List.iter f l
match l with
[] -> ()
| (s, t) :: [] ->
- bp b "<b>%s</b> <code>%s</code> "
+ bp b "<li><b>%s</b> <code>%s</code> "
Odoc_messages.raises
s;
self#html_of_text b t;
- bs b "<br>\n"
+ bs b "</li>\n"
| _ ->
- bp b "<b>%s</b><ul>" Odoc_messages.raises;
+ bp b "<li><b>%s</b><ul>" Odoc_messages.raises;
List.iter
(fun (ex, desc) ->
bp b "<li><code>%s</code> " ex ;
bs b "</li>\n"
)
l;
- bs b "</ul>\n"
+ bs b "</ul></li>\n"
(** Print html code for the given "see also" reference. *)
method html_of_see b (see_ref, t) =
match l with
[] -> ()
| see :: [] ->
- bp b "<b>%s</b> " Odoc_messages.see_also;
+ bp b "<li><b>%s</b> " Odoc_messages.see_also;
self#html_of_see b see;
- bs b "<br>\n"
+ bs b "</li>\n"
| _ ->
- bp b "<b>%s</b><ul>" Odoc_messages.see_also;
+ bp b "<li><b>%s</b><ul>" Odoc_messages.see_also;
List.iter
(fun see ->
bs b "<li>" ;
bs b "</li>\n"
)
l;
- bs b "</ul>\n"
+ bs b "</ul></li>\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;
+ bp b "<li><b>%s</b> " Odoc_messages.returns;
self#html_of_text b s;
- bs b "<br>\n"
+ bs b "</li>\n"
(** Print html code for the given list of custom tagged texts. *)
method html_of_custom b l =
(
match info.M.i_deprecated with
None -> ()
- | Some d ->
+ | Some d ->
+ bs b "<div class=\"info-deprecated\">\n";
bs b "<span class=\"warning\">";
bs b Odoc_messages.deprecated ;
bs b "</span>" ;
self#html_of_text b d;
- bs b "<br>\n"
+ bs b "</div>\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"
+ | Some d ->
+ bs b "<div class=\"info-desc\">\n";
+ self#html_of_text ~with_p:true b d;
+ bs b "</div>\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;
+
+ let b' = Buffer.create 17 in
+ 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 Buffer.length b' > 0 then
+ begin
+ bs b "<ul class=\"info-attributes\">\n";
+ Buffer.add_buffer b b';
+ bs b "</ul>\n"
+ end;
if indent then bs b "</div>\n"
(** Print html code for the first sentence of a description.
None -> ()
| Some d when d = [Odoc_info.Raw ""] -> ()
| Some d ->
- self#html_of_text b
+ self#html_of_text ~with_p:true b
(Odoc_info.text_no_title_no_list
(Odoc_info.first_sentence_of_text d));
bs b "\n"
"h1 { font-size : 20pt ; text-align: center; }" ;
- "h2 { font-size : 20pt ; border: 1px solid #000000; "^
+ "h2 { font-size : 20pt ; text-align: center; }" ;
+
+ "h3 { 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; "^
+ "h4 { 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; "^
+ "h5 { 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; "^
+ "h6 { 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; "^
+ "div.h7 { font-size : 20pt ; border: 1px solid #000000; "^
"margin-top: 5px; margin-bottom: 2px;"^
"text-align: center; background-color: #90BDFF ; "^
"padding: 2px; }" ;
- "div.h7 { font-size : 20pt ; border: 1px solid #000000; "^
+ "div.h8 { 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; "^
+ "div.h9 { 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; "^
+ "div.h10 { font-size : 20pt ; border: 1px solid #000000; "^
"margin-top: 5px; margin-bottom: 2px;"^
"text-align: center; background-color: #FFFFFF ; "^
"padding: 2px; }" ;
"ul.indexlist { margin-left: 0; padding-left: 0;}";
"ul.indexlist li { list-style-type: none ; margin-left: 0; padding-left: 0; }";
+ "ul.info-attributes {list-style: none; margin: 0; padding: 0; }";
+ "div.info > p:first-child { margin-top:0; }";
+ "div.info-desc > p:first-child { margin-top:0; margin-bottom:0; }"
]
(** The style file for all pages. *)
match Parameter.desc_by_name p n with
None -> ()
| Some t ->
+ bs b "<div class=\"parameter-desc\">\n";
bs b "<code>";
bs b n;
bs b "</code> : ";
- self#html_of_text b t
+ self#html_of_text b t;
+ bs b "</div>\n"
in
- print_concat b "<br>\n" print_one l2
+ List.iter print_one l2
(** Print html code for a list of parameters. *)
method html_of_parameter_list b m_name l =
);
bs b "</td>\n<td align=\"center\" valign=\"top\">:</td>\n";
bs b "<td>";
+ bs b "<div class=\"paramer-type\">\n";
self#html_of_type_expr b m_name (Parameter.typ p);
- bs b "<br>\n";
+ bs b "<div>\n";
self#html_of_parameter_description b p;
bs b "\n</tr>\n";
in
match desc_opt with
None -> ()
| Some t ->
- bs b "<br>";
+ bs b "<div class=\"parameter-desc\" >";
self#html_of_text b t;
+ bs b "\n</div>\n";
bs b "\n</tr>\n" ;
)
)
let (html_file, _) = Naming.html_files m.m_name in
let father = Name.father m.m_name in
bs b "\n<pre>";
+ bp b "<span id=\"%s\">" (Naming.module_target m);
bs b ((self#keyword "module")^" ");
(
if with_link then
else
bs b (Name.simple m.m_name)
);
+ bs b "</span>" ;
(
match m.m_kind with
Module_functor _ when !html_short_functors ->
let (html_file, _) = Naming.html_files mt.mt_name in
let father = Name.father mt.mt_name in
bs b "\n<pre>";
- bs b ((self#keyword "module type")^" ");
+ bp b "<span id=\"%s\">" (Naming.module_type_target mt);
+ 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)
);
+ bs b "</span>";
(match mt.mt_kind with
None -> ()
| Some k ->
bs b "\n<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\">"
+ bp b "<span id=\"%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_kind = Type_abstract ; ty_private = Asttypes.Public;
+ ty_manifest = None ;
ty_loc = Odoc_info.dummy_loc ;
ty_code = None ;
}
(** 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"
+ self#html_of_text ~with_p:true b text
(** Print html code for a class comment.*)
method html_of_class_comment b text =
let text2 =
match text with
| (Odoc_info.Raw s) :: q ->
- (Odoc_info.Title (2, None, [Odoc_info.Raw s])) :: q
+ (Odoc_info.Title (1, None, [Odoc_info.Raw s])) :: q
| _ -> text
in
- self#html_of_text b text2
+ self#html_of_text ~with_p:true b text2
(** Generate html code for the given list of inherited classes.*)
method generate_inheritance_info b inher_l =
'A'..'Z' as c -> String.make 1 c
| _ -> ""
in
- bs b "<tr><td align=\"left\"><br>";
+ bs b "<tr><td align=\"left\"><div>";
bs b s ;
- bs b "</td></tr>\n" ;
+ bs b "</div></td></tr>\n" ;
List.iter f_ele l
in
bs b "<table>\n";
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 "<h1>";
- bs b title;
- bs b "</h1>\n" ;
+ (
+ match !Global.title with
+ | None -> ()
+ | Some t ->
+ bs b "<h1>";
+ bs b (self#escape t);
+ bs b "</h1>\n"
+ );
+
let info = Odoc_info.apply_opt
(Odoc_info.info_of_comment_file module_list)
!Odoc_info.Global.intro_file
(
match info with
None ->
+ bs b "<div class = \"index-list\">\n";
self#html_of_Index_list b;
- bs b "<br/>";
+ bs b "</div>\n";
self#html_of_Module_list b
(List.map (fun m -> m.m_name) module_list);
| Some _ -> self#html_of_info ~indent: false b info
(** Interface to the information collected in source files. *)
-(** The differents kinds of element references. *)
+(** The different kinds of element references. *)
type ref_kind = Odoc_types.ref_kind =
RK_module
| RK_module_type
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_deprecated : text option; (** The description text 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. *)
(** [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.
+ (** Return the depth of the name, i.e. the number of levels to the root.
Example : [depth "Toto.Tutu.name"] = [3]. *)
val depth : t -> int
(** Representation and manipulation of method / function / class / module parameters.*)
module Parameter :
sig
- (** {3 Types} *)
+ (** {1 Types} *)
(** Representation of a simple parameter name *)
type simple_name = Odoc_parameter.simple_name =
(** A parameter is just a param_info.*)
type parameter = param_info
- (** {3 Functions} *)
+ (** {1 Functions} *)
- (** Acces to the name as a string. For tuples, parenthesis and commas are added. *)
+ (** Access to the name as a string. For tuples, parentheses and commas are added. *)
val complete_name : parameter -> string
(** Access to the complete type. *)
ex_name : Name.t ;
mutable ex_info : info option ; (** Information found in the optional associated comment. *)
ex_args : Odoc_type.constructor_args;
- ex_ret : Types.type_expr option ; (** The the optional return type of the exception. *)
+ ex_ret : Types.type_expr option ; (** The optional return type of the exception. *)
ex_alias : exception_alias option ; (** [None] when the exception is not a rebind. *)
mutable ex_loc : location ;
mutable ex_code : string option ;
}
type type_manifest = Odoc_type.type_manifest =
- | Other of Types.type_expr (** Type manifest directly taken from Typedtre. *)
+ | Other of Types.type_expr (** Type manifest directly taken from Typedtree. *)
| Object_type of object_field list
(** Representation of a type. *)
(** Representation and manipulation of classes and class types.*)
module Class :
sig
- (** {3 Types} *)
+ (** {1 Types} *)
(** To keep the order of elements in a class. *)
type class_element = Odoc_class.class_element =
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. *)
+ capp_params_code : string list ; (** The code of these expressions. *)
}
and class_constr = Odoc_class.class_constr =
mutable clt_loc : location ;
}
- (** {3 Functions} *)
+ (** {1 Functions} *)
(** Access to the elements of a class. *)
val class_elements : ?trans:bool -> t_class -> class_element list
(** Representation and manipulation of modules and module types. *)
module Module :
sig
- (** {3 Types} *)
+ (** {1 Types} *)
(** To keep the order of elements in a module. *)
type module_element = Odoc_module.module_element =
{
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 *)
+ mutable im_info : Odoc_types.info option ; (** comment associated with the include directive *)
}
and module_alias = Odoc_module.module_alias =
mutable mt_loc : location ;
}
- (** {3 Functions for modules} *)
+ (** {1 Functions for modules} *)
(** Access to the elements of a module. *)
val module_elements : ?trans:bool -> t_module -> module_element list
(** The list of module comments. *)
val module_comments : ?trans:bool-> t_module -> text list
- (** {3 Functions for module types} *)
+ (** {1 Functions for module types} *)
(** Access to the elements of a module type. *)
val module_type_elements : ?trans:bool-> t_module_type -> module_element list
end
-(** {3 Getting strings from values} *)
+(** {2 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,
val reset_type_names : unit -> unit
(** [string_of_variance t (covariant, invariant)] returns ["+"] if
- the given information means "covariant", ["-"] if the it means
+ the given information means "covariant", ["-"] if 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.*)
+ 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. *)
(** 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].
+ or just [sig end]. Default is [false].
@param code if [complete = false] and the type contains something else
than identificators and functors, then the given code is used.
*)
(** 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].
+ or just [object end]. Default is [false].
*)
val string_of_class_type : ?complete: bool -> Types.class_type -> string
(** @return a string to describe the given method. *)
val string_of_method : Value.t_method -> string
-(** {3 Miscelaneous functions} *)
+(** {2 Miscellaneous functions} *)
(** Return the first sentence (until the first dot followed by a blank
or the first blank line) of a text.
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
+ useful when printing labels, we then remove the top option constructor
for optional labels.*)
val remove_option : Types.type_expr -> Types.type_expr
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
+ @raise Failure if the file could not be opened or there is a
syntax error.
*)
val info_of_comment_file : Module.t_module list -> string -> info
(** Scan of a type extension *)
- (** Overide this method to perform controls on the extension's type,
+ (** Override this method to perform controls on the extension's type,
private and info. This method is called before scanning the
extension's constructors.
@return true if the extension's constructors must be scanned.*)
@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. *)
+ (** This method scans 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]
@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. *)
+ (** This method scans 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]
@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. *)
+ (** This method scans 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]
@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. *)
+ (** This method scans 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]
(** Computation of dependencies. *)
module Dep :
sig
- (** Modify the modules depencies of the given list of modules,
+ (** Modify the module dependencies of the given list of modules,
to get the minimum transitivity kernel. *)
val kernel_deps_of_modules : Module.t_module list -> unit
val deps_of_types : ?kernel: bool -> Type.t_type list -> (Type.t_type * (Name.t list)) list
end
-(** {2 Some global variables} *)
+(** {1 Some global variables} *)
module Global :
sig
let separate_files = ref false
let latex_titles = ref [
+ 0, "section" ;
1, "section" ;
2, "subsection" ;
3, "subsubsection" ;
(** Generation of LaTeX code from text structures. *)
class text =
object (self)
- (** Return latex code to make a sectionning according to the given level,
+ (** Return latex code to make a section according to the given level,
and with the given latex code. *)
method section_style level s =
try
"}", "\\\\}";
"\\$", "\\\\$";
"\\^", "{\\\\textasciicircum}";
- "\xE0", "\\\\`a";
- "\xE2", "\\\\^a";
- "\xE9", "\\\\'e";
- "\xE8", "\\\\`e";
- "\xEA", "\\\\^e";
- "\xEB", "\\\\\"e";
- "\xE7", "\\\\c{c}";
- "\xF4", "\\\\^o";
- "\xF6", "\\\\\"o";
- "\xEE", "\\\\^i";
- "\xEF", "\\\\\"i";
- "\xF9", "\\\\`u";
- "\xFB", "\\\\^u";
"%", "\\\\%";
"_", "\\\\_";
"~", "\\\\~{}";
(** 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. *)
+ (** The method used to get a [text] from an optional 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. *)
);
[CodePre (flush2 ())]
in
+ Latex ( self#make_label (self#exception_label e.ex_name) ) ::
merge_codepre (l @ s ) @
[Latex ("\\index{"^(self#label s_name)^"@\\verb`"^(self#label ~no_:false s_name)^"`}\n")]
@ (self#text_of_info e.ex_info) in
self#latex_of_module_kind fmt father k2;
self#latex_of_text fmt [Code ")"]
| Module_with (k, s) ->
- (* TODO: modify when Module_with will be more detailled *)
+ (* TODO: modify when Module_with will be more detailed *)
self#latex_of_module_type_kind fmt father k;
self#latex_of_text fmt
[ Code " ";
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 *)
+ (* avoid a big gap if the kind is a constr *)
(
match c.cl_kind with
Class.Class_constr _ ->
let subtitle = match first_t with
| [] -> []
| t -> (Raw " : ") :: t in
- [ Title (1, None, title @ subtitle ) ]
+ [ Title (0, None, title @ subtitle ) ]
in
self#latex_of_text fmt text;
self#latex_for_module_label fmt m;
)
- (** Generate the LaTeX style file, if it does not exists. *)
+ (** Generate the LaTeX style file, if it does not exist. *)
method generate_style_file =
try
let dir = Filename.dirname !Global.out_file in
self#generate_for_top_module fmt m
)
module_list ;
- if !Global.with_trailer then ps fmt "\\end{document}";
+ if !Global.with_trailer then ps fmt "\\end{document}\n";
Format.pp_print_flush fmt ();
close_out chanout
with
let b = new_buf () in
bs b (".TH \""^cl.cl_name^"\" ");
bs b !man_section ;
- bs b (" source: "^Odoc_misc.current_date^" ");
+ bs b (" "^Odoc_misc.current_date^" ");
bs b "OCamldoc ";
bs b ("\""^(match !Global.title with Some t -> t | None -> "")^"\"\n");
let b = new_buf () in
bs b (".TH \""^ct.clt_name^"\" ");
bs b !man_section ;
- bs b (" source: "^Odoc_misc.current_date^" ");
+ bs b (" "^Odoc_misc.current_date^" ");
bs b "OCamldoc ";
bs b ("\""^(match !Global.title with Some t -> t | None -> "")^"\"\n");
let b = new_buf () in
bs b (".TH \""^mt.mt_name^"\" ");
bs b !man_section ;
- bs b (" source: "^Odoc_misc.current_date^" ");
+ bs b (" "^Odoc_misc.current_date^" ");
bs b "OCamldoc ";
bs b ("\""^(match !Global.title with Some t -> t | None -> "")^"\"\n");
let b = new_buf () in
bs b (".TH \""^m.m_name^"\" ");
bs b !man_section ;
- bs b (" source: "^Odoc_misc.current_date^" ");
+ bs b (" "^Odoc_misc.current_date^" ");
bs b "OCamldoc ";
bs b ("\""^(match !Global.title with Some t -> t | None -> "")^"\"\n");
let b = new_buf () in
bs b (".TH \""^name^"\" ");
bs b !man_section ;
- bs b (" source: "^Odoc_misc.current_date^" ");
+ bs b (" "^Odoc_misc.current_date^" ");
bs b "OCamldoc ";
bs b ("\""^(match !Global.title with Some t -> t | None -> "")^"\"\n");
bs b ".SH NAME\n";
self#man_of_module_type_body b mt
| Res_section _ ->
- (* normaly, we cannot have modules here. *)
+ (* normally, we cannot have modules here. *)
()
in
List.iter f l;
let version_separators = Str.regexp "[\\.\\+]";;
-(** Merge two Odoctypes.info struture, completing the information of
+(** Merge two Odoctypes.info structures, 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.*)
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.*)
+ The parameters 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
([], []) -> []
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.*)
+ (* 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_class.class_update_parameters_text mli;
(* merge values *)
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.*)
+ (* 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
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.*)
+ (* 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 v;
if !Odoc_global.keep_code then
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.*)
+ (* 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 v;
if !Odoc_global.keep_code then
let no_index = " Do not build index for Info files "^texi_only
let esc_8bits = " Escape accentuated characters in Info files "^texi_only
+let texinfo_title r=
+ "n,style Associate {n } to the given sectionning style\n"^
+ "\t\t(e.g. 'section') in the texInfo output "^texi_only^"\n"^
+ "\t\tDefault sectionning is:\n\t\t"^
+ (String.concat "\n\t\t"
+ (List.map (fun (n,(t,h)) ->
+ Printf.sprintf " %d -> %s, %s " n t h) !r))
+
let info_section = " Specify section of Info directory "^texi_only
let info_entry = " Specify Info directory entry "^texi_only
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. *)
+ since 1970. The hour is optionally displayed. *)
val string_of_date : ?absolute:bool -> ?hour:bool -> float -> string
(* Value returned by string_of_date for current time.
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
+ useful when printing labels, we then remove the top option constructor
for optional labels.*)
val remove_option : Types.type_expr -> Types.type_expr
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 *)
+ mutable im_info : Odoc_types.info option ; (** comment associated to the include directive *)
}
and module_alias = {
}
-(** {2 Functions} *)
+(** {1 Functions} *)
(** Returns the list of values from a list of module_element. *)
let values l =
in
iter m.m_kind
-(** access to all submodules and sudmobules of submodules ... of the given module.
+(** access to all submodules and submodules 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
l
l
-(** The module type is a functor if is defined as a functor or if it is an alias for a functor. *)
+(** The module type is a functor if it 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
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. *)
+(** The module is a functor if it is defined as a functor or if it is an alias for a functor. *)
let module_is_functor m =
let rec iter visited = function
Module_functor _ -> true
(fun v -> not (Odoc_value.is_function v))
(values (module_type_elements ~trans mt))
-(** {2 Functions for modules and module types} *)
+(** {1 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 from_longident = Odoc_misc.string_of_longident
-module Set = Set.Make (struct
- type z = t
- type t = z
- let compare = String.compare
-end)
+module Map = Map.Make(String)
(** 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.
+(** Returns the depth of the name, i.e. the number 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).*)
+ If the two names are equal, then it 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. *)
(** Get a name from a [Longident.t].*)
val from_longident : Longident.t -> t
-(** Set of Name.t *)
-module Set : Set.S with type elt = t
+module Map : Map.S with type key = t
(** Functions *)
-(** acces to the name as a string. For tuples, parenthesis and commas are added. *)
+(** access to the name as a string. For tuples, parentheses and commas are added. *)
let complete_name p =
let rec iter pi =
match pi with
List.assoc name l
-(** acces to the list of names ; only one for a simple parameter, or
+(** access to the list of names ; only one for a simple parameter, or
a list for tuples. *)
let names pi =
let rec iter acc pi =
raise_exc:
T_RAISES Desc
{
- (* isolate the exception construtor name *)
+ (* isolate the exception constructor name *)
let s = $2 in
match Str.split (Str.regexp (blank^"+")) s with
[]
(** 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
+ @param code when the code is given, we raise the [Use_code] exception if we
+ encounter a signature, so that the calling function can use the code rather
than the "emptied" type.
*)
let simpl_module_type ?code t =
(** 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].
+ or just [sig end]. Default is [false].
@param code if [complete = false] and the type contains something else
than identificators and functors, then the given code is used.
*)
(** 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].
+ or just [object end]. Default is [false].
*)
val string_of_class_type : ?complete: bool -> Types.class_type -> string
(** Scan of a type extension *)
- (** Overide this method to perform controls on the extension's type,
+ (** Override this method to perform controls on the extension's type,
private and info. This method is called before scanning the
extensions's constructors.
@return true if the extension's constructors must be scanned.*)
@return true if the class elements must be scanned.*)
method scan_class_pre (_ : Odoc_class.t_class) = true
- (** This method scan the elements of the given class.
+ (** This method scans the elements of the given class.
A VOIR : scan des classes heritees.*)
method scan_class_elements c =
List.iter
@return true if the class type elements must be scanned.*)
method scan_class_type_pre (_ : Odoc_class.t_class_type) = true
- (** This method scan the elements of the given class type.
+ (** This method scans the elements of the given class type.
A VOIR : scan des classes heritees.*)
method scan_class_type_elements ct =
List.iter
@return true if the module elements must be scanned.*)
method scan_module_pre (_ : Odoc_module.t_module) = true
- (** This method scan the elements of the given module. *)
+ (** This method scans the elements of the given module. *)
method scan_module_elements m =
List.iter
(fun ele ->
@return true if the module type elements must be scanned. *)
method scan_module_type_pre (_ : Odoc_module.t_module_type) = true
- (** This method scan the elements of the given module type. *)
+ (** This method scans the elements of the given module type. *)
method scan_module_type_elements mt =
List.iter
(fun ele ->
(** The name of the analysed file. *)
let file_name = ref ""
- (** This function takes two indexes (start and end) and return the string
+ (** This function takes two indexes (start and end) and returns 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 =
!file_name
(get_string_of_file pos_start pos_end)
+ let preamble filename file proj ast =
+ let info = My_ir.first_special filename file in
+ (* Only use as module preamble documentation comments that occur before
+ any module elements *)
+ match ast with
+ | a :: _ when Loc.start (proj a) < fst info -> (0,None)
+ | _ -> info
+
let merge_infos = Odoc_merge.merge_info_opt Odoc_types.all_merge_options
(** Module for extracting documentation comments for record from different
end_ = (fun ld -> Loc.start ld.ld_loc);
(* Beware, Loc.start is correct in the code above:
type_expr's do not hold location information, and ld.ld_loc
- ends after the documentation comment, sow e use Loc.start as
+ ends after the documentation comment, so we use Loc.start as
the least problematic approximation for end_. *)
inline_record = begin
fun c -> match c.cd_args with
| Ptyp_object (fields, _) ->
let rec f = function
| [] -> []
- | ({txt=""},_,_) :: _ ->
+ | Otag ({txt=""},_,_) :: _ ->
(* Fields with no name have been eliminated previously. *)
assert false
-
- | ({txt=name}, _atts, ct) :: [] ->
+ | Otag ({txt=name}, _atts, ct) :: [] ->
let pos = Loc.ptyp_end ct in
let (_,comment_opt) = just_after_special pos pos_end in
[name, comment_opt]
- | ({txt=name}, _atts, ct) :: ((_name2, _atts2, ct2) as ele2) :: q ->
+ | Otag ({txt=name}, _, ct) ::
+ ((Oinherit ct2 | Otag (_, _, ct2)) as ele2) :: q ->
let pos = Loc.ptyp_end ct in
let pos2 = Loc.ptyp_start ct2 in
let (_,comment_opt) = just_after_special pos pos2 in
(name, comment_opt) :: (f (ele2 :: q))
+ | _ :: q -> f q
in
let is_named_field field =
match field with
- | ({txt=""},_,_) -> false
+ | Otag ({txt=""},_,_) -> false
| _ -> true
in
(0, f @@ List.filter is_named_field fields)
let comments = Record.(doc typedtree) pos_end l in
Odoc_type.Cstr_record (List.map (record comments) l)
+ (* Given a constraint "with type M.N.t := foo", this function adds "M" ->
+ "with type N.t := foo" to acc, ie it build the constraint to put on the
+ first element of the path being modified.
+ When filter_out_erased_items_from_signature finds "M", it applies the
+ constraint on its module type. *)
+ let constraint_for_subitem =
+ let split_longident p =
+ match Longident.flatten p with
+ | [] -> assert false
+ | hd :: tl -> hd, Longident.unflatten tl
+ in
+ fun acc s rebuild_constraint ->
+ match split_longident s.txt with
+ | hd, None -> Name.Map.add hd `Removed acc
+ | hd, Some p ->
+ let constraint_ = rebuild_constraint { s with txt = p } in
+ match Name.Map.find hd acc with
+ | exception Not_found ->
+ Name.Map.add hd (`Constrained [constraint_]) acc
+ | `Constrained old ->
+ Name.Map.add hd (`Constrained (constraint_ :: old)) acc
+ | `Removed -> acc
+
let erased_names_of_constraints constraints acc =
List.fold_right (fun constraint_ acc ->
match constraint_ with
| Parsetree.Pwith_type _ | Parsetree.Pwith_module _ -> acc
- | Parsetree.Pwith_typesubst {Parsetree.ptype_name=s}
- | Parsetree.Pwith_modsubst (s, _) ->
- Name.Set.add s.txt acc)
+ | Parsetree.Pwith_typesubst (s, typedecl) ->
+ constraint_for_subitem acc s (fun s -> Parsetree.Pwith_typesubst (s, typedecl))
+ | Parsetree.Pwith_modsubst (s, modpath) ->
+ constraint_for_subitem acc s (fun s -> Parsetree.Pwith_modsubst (s, modpath)))
constraints acc
+ let is_erased ident map =
+ match Name.Map.find ident map with
+ | exception Not_found -> false
+ | `Removed -> true
+ | `Constrained _ -> false
+
+ let apply_constraint module_type constraints =
+ match module_type.Parsetree.pmty_desc with
+ | Parsetree.Pmty_alias _ -> module_type
+ | _ ->
+ { Parsetree.
+ pmty_desc = Parsetree.Pmty_with (module_type, List.rev constraints);
+ pmty_loc = module_type.Parsetree.pmty_loc;
+ pmty_attributes = []
+ }
+
let filter_out_erased_items_from_signature erased signature =
- if Name.Set.is_empty erased then signature
+ if Name.Map.is_empty erased then signature
else List.fold_right (fun sig_item acc ->
let take_item psig_desc = { sig_item with Parsetree.psig_desc } :: acc in
match sig_item.Parsetree.psig_desc with
| Parsetree.Psig_class _
| Parsetree.Psig_class_type _ as tp -> take_item tp
| Parsetree.Psig_type (rf, types) ->
- (match List.filter (fun td -> not (Name.Set.mem td.Parsetree.ptype_name.txt erased)) types with
+ (match List.filter (fun td -> not (is_erased td.Parsetree.ptype_name.txt erased)) types with
| [] -> acc
| types -> take_item (Parsetree.Psig_type (rf, types)))
- | Parsetree.Psig_module {Parsetree.pmd_name=name}
+ | Parsetree.Psig_module ({Parsetree.pmd_name=name;
+ pmd_type=module_type} as r) as m ->
+ begin match Name.Map.find name.txt erased with
+ | exception Not_found -> take_item m
+ | `Removed -> acc
+ | `Constrained constraints ->
+ take_item
+ (Parsetree.Psig_module
+ { r with Parsetree.pmd_type =
+ apply_constraint module_type constraints })
+ end
| Parsetree.Psig_modtype {Parsetree.pmtd_name=name} as m ->
- if Name.Set.mem name.txt erased then acc else take_item m
+ if is_erased name.txt erased then acc else take_item m
| Parsetree.Psig_recmodule mods ->
- (match List.filter (fun pmd -> not (Name.Set.mem pmd.Parsetree.pmd_name.txt erased)) mods with
+ (match List.filter (fun pmd -> not (is_erased pmd.Parsetree.pmd_name.txt erased)) mods with
| [] -> acc
| mods -> take_item (Parsetree.Psig_recmodule mods)))
signature []
ic_text = text_opt ;
}
+ | Parsetree.Pcty_open _ (* one could also traverse the open *)
| Parsetree.Pcty_signature _
| Parsetree.Pcty_arrow _ ->
(* we don't have a name for the class signature, so we call it "object ... end" *)
| Parsetree.Psig_module {Parsetree.pmd_name=name; pmd_type=module_type} ->
let complete_name = Name.concat current_module_name name.txt in
- (* get the the module type in the signature by the module name *)
+ (* get the module type in the signature by the module name *)
let sig_module_type =
try Signature_search.search_module table name.txt
with Not_found ->
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 (* FIXME : can this be a Tmty_ident? in this case, we would'nt have the signature *)
+ match new_module.m_type with (* FIXME : can this be a Tmty_ident? in this case, we wouldn't have the signature *)
Types.Mty_signature s -> Odoc_env.add_signature new_env new_module.m_name ~rel: (Name.simple new_module.m_name) s
| _ -> new_env
in
raise (Failure (Odoc_messages.module_not_found current_module_name name))
in
match sig_module_type with
- (* FIXME : can this be a Tmty_ident? in this case, we would'nt have the signature *)
+ (* FIXME : can this be a Tmty_ident? in this case, we wouldn't have the signature *)
Types.Mty_signature s ->
Odoc_env.add_signature e complete_name ~rel: name s
| _ ->
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 (* FIXME : can this be a Tmty_ident? in this case, we would'nt have the signature *)
+ match sig_mtype with (* FIXME : can this be a Tmty_ident? in this case, we wouldn't have the signature *)
Some (Types.Mty_signature s) -> Odoc_env.add_signature new_env mt.mt_name ~rel: (Name.simple mt.mt_name) s
| _ -> new_env
in
(** Return a module_type_kind from a Parsetree.module_type and a Types.module_type *)
and analyse_module_type_kind
- ?(erased = Name.Set.empty) env current_module_name module_type sig_module_type =
+ ?(erased = Name.Map.empty) env current_module_name module_type sig_module_type =
match module_type.Parsetree.pmty_desc with
Parsetree.Pmty_ident longident ->
let name =
(** analyse of a Parsetree.module_type and a Types.module_type.*)
and analyse_module_kind
- ?(erased = Name.Set.empty) env current_module_name module_type sig_module_type =
+ ?(erased = Name.Map.empty) 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
raise (Failure "Parsetree.Pmty_functor _ but not Types.Mty_functor _")
)
| Parsetree.Pmty_with (module_type2, constraints) ->
- (*of module_type * (Longident.t * with_constraint) list*)
+ (* of module_type * (Longident.t * with_constraint) list*)
(
let loc_start = Loc.end_ module_type2.Parsetree.pmty_loc in
let loc_end = Loc.end_ module_type.Parsetree.pmty_loc in
(*
| (Parsetree.Pcty_constr (longident, _) (*of Longident.t * core_type list *),
Types.Cty_signature class_signature) ->
- (* FIXME : this for the case of class contraints :
+ (* FIXME : this for the case of class constraints :
class type cons = object
method m : int
end
let mod_name = String.capitalize_ascii
(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 len, info_opt = preamble !file_name !file
+ (fun x -> x.Parsetree.psig_loc) ast in
let elements =
analyse_parsetree Odoc_env.empty signat mod_name len (String.length !file) ast
in
(** The name of the analysed file. *)
val file_name : string ref
- (** This function takes two indexes (start and end) and return the string
+ (** This function takes two indexes (start and end) and returns 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
[input_f] into [file].*)
val prepare_file : string -> string -> unit
+ (** [preamble f input_f loc ast ] retrieves the position and contents of
+ the preamble for the file [f]: i.e, the first documentation comment
+ before any elements in [ast].
+ If there is no such preamble, [0,None] is returned.
+ The function [loc] is used to obtain the location of this
+ first element of [ast].*)
+ val preamble: string -> string -> ('a -> Location.t) -> 'a list
+ -> int * Odoc_types.info option
+
(** 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)
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.*)
+ i.e. usually the beginning of the next element.*)
val name_comment_from_type_decl :
int -> int -> Parsetree.type_declaration -> int * (string * Odoc_types.info option) list
(** This function converts a [Types.type_expr] into a [Odoc_type.type_kind],
- by associating the comment found in the parstree of each object field, if any. *)
+ by associating the comment found in the parsetree of each object field, if any. *)
val manifest_structure :
Odoc_env.env -> (string * Odoc_types.info option) list ->
Types.type_expr -> Odoc_type.type_manifest
Odoc_env.env -> int -> Typedtree.constructor_arguments ->
Odoc_type.constructor_args
- (** This function merge two optional info structures. *)
+ (** This function merges 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 :
- ?erased:Odoc_name.Set.t -> Odoc_env.env -> Odoc_name.t ->
+ ?erased:[ `Constrained of Parsetree.with_constraint list
+ | `Removed ] Odoc_name.Map.t
+ -> Odoc_env.env -> Odoc_name.t ->
Parsetree.module_type -> Types.module_type ->
Odoc_module.module_type_kind
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
+ (** This function takes an interface file name, a file containing 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,
)
| M.Type_open ->
- "= .." (* FIXME MG: when introducing new constuctors next time,
+ "= .." (* FIXME MG: when introducing new constructors next time,
thanks to setup a minimal correct output *)
| M.Type_record l ->
P.sprintf "= %s{\n%s\n}\n" (if priv then "private " else "")
let info_entry = ref []
-(** {2 Some small helper functions} *)
+(** {1 Some small helper functions} *)
let puts_nl chan s =
output_string chan s ;
(** Module for generating various Texinfo things (menus, xrefs, ...) *)
module Texi =
struct
- (** Associations of strings to subsitute in Texinfo code. *)
+ (** Associations of strings to substitute in Texinfo code. *)
let subst_strings = [
(Str.regexp "@", "@@") ;
(Str.regexp "{", "@{") ;
-(** {2 Generation of Texinfo code} *)
+(** {1 Generation of Texinfo code} *)
-(** This class generates Texinfo code from text structures *)
-class text =
- object(self)
+(** {2 Associations between a title number and texinfo code.} *)
+let titles_and_headings = ref [
+ 0, ("@chapter ", "@majorheading ") ;
+ 1, ("@chapter ", "@majorheading ") ;
+ 2, ("@section ", "@heading ") ;
+ 3, ("@subsection ", "@subheading ") ;
+ 4, ("@subsubsection ", "@subsubheading ") ;
+ ]
- (** Associations between a title number and texinfo code. *)
- val titles = [
- 1, "@chapter " ;
- 2, "@section " ;
- 3, "@subsection " ;
- 4, "@subsubsection " ;
- ]
+let title = fst
+let heading = snd
- val fallback_title =
- "@unnumberedsubsubsec "
+let fallback_title =
+ "@unnumberedsubsubsec "
- val headings = [
- 1, "@majorheading " ;
- 2, "@heading " ;
- 3, "@subheading " ;
- 4, "@subsubheading " ;
- ]
+let fallback_heading =
+ "@subsubheading "
- val fallback_heading =
- "@subsubheading "
+(** This class generates Texinfo code from text structures *)
+class text =
+ object(self)
method escape =
Texi.escape
(List.map self#texi_of_text_element t)
- (** {3 Conversion methods}
+ (** {2 Conversion methods}
[texi_of_????] converts a [text_element] to a Texinfo string. *)
(** Return the Texinfo code for the [text_element] in parameter. *)
[ "@format" ; self#texi_of_text t ; "@end format" ; "" ]
method texi_of_Title n t =
let t_begin =
- try List.assoc n titles
+ try title @@ List.assoc n !titles_and_headings
with Not_found -> fallback_title in
t_begin ^ (self#texi_of_text t) ^ "\n"
method texi_of_Link s t =
method heading n t =
let f =
- try List.assoc n headings
+ try heading @@ List.assoc n !titles_and_headings
with Not_found -> fallback_heading
in
f ^ (self#texi_of_text t) ^ "\n"
inherit text
inherit Odoc_to_text.to_text as to_text
- (** {3 Small helper stuff.} *)
+ (** {2 Small helper stuff.} *)
val maxdepth = 4
| Raw s -> Raw (Str.global_replace re rep s)
| txt -> txt) t
- (** {3 [text] values generation}
+ (** {2 [text] values generation}
Generates [text] values out of description parts.
Redefines some of methods of {! Odoc_to_text.to_text}. *)
method texi_of_info i =
self#texi_of_text (self#text_of_info i)
- (** {3 Conversion of [module_elements] into Texinfo strings}
+ (** {2 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. *)
self#texi_of_text (Newline :: t @ [Newline])
)
- (** {3 Generating methods }
+ (** {2 Generating methods }
These methods write Texinfo code to an [out_channel] *)
(** Generate the Texinfo code for the given list of inherited classes.*)
else
let s = Lexing.lexeme lexbuf in
try
- (* chech if the "{..." or html_title mark was used. *)
+ (* check 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
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. *)
+ (** @return [text] value for an authors list. *)
method text_of_author_list l =
match l with
[] ->
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).*)
+ (** @return [text] value to represent parameters of a class (with arrows).*)
method text_of_class_params module_name c =
Odoc_info.text_concat
[Newline]
}
type type_manifest =
- | Other of Types.type_expr (** Type manifest directly taken from Typedtre. *)
+ | Other of Types.type_expr (** Type manifest directly taken from Typedtree. *)
| Object_type of object_field list
(** Representation of a type. *)
(** Types for the information collected in comments. *)
-(** The differents kinds of element references. *)
+(** The different kinds of element references. *)
type ref_kind =
RK_module
| RK_module_type
| Superscript of text (** Superscripts. *)
| Subscript of text (** Subscripts. *)
| Module_list of string list
- (** The table of the given modules with their abstract; *)
+ (** The table of the given modules with their abstracts. *)
| 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 *)
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_deprecated : text option; (** The textual description 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. *)
--- /dev/null
+run_unix.$(O): run_unix.c run.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ run_common.h
+run_stubs.$(O): run_stubs.c run.h ../byterun/caml/misc.h \
+ ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
+ ../byterun/caml/mlvalues.h ../byterun/caml/memory.h \
+ ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
+ ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
+ ../byterun/caml/address_class.h ../byterun/caml/io.h \
+ ../byterun/caml/osdeps.h
+actions.cmo : environments.cmi actions.cmi
+actions.cmx : environments.cmx actions.cmi
+actions.cmi : environments.cmi
+backends.cmo : backends.cmi
+backends.cmx : backends.cmi
+backends.cmi :
+builtin_actions.cmo : variables.cmi testlib.cmi run_command.cmi \
+ ocamltest_config.cmi filetype.cmi filecompare.cmi environments.cmi \
+ builtin_variables.cmi builtin_modifiers.cmi backends.cmi actions.cmi \
+ builtin_actions.cmi
+builtin_actions.cmx : variables.cmx testlib.cmx run_command.cmx \
+ ocamltest_config.cmx filetype.cmx filecompare.cmx environments.cmx \
+ builtin_variables.cmx builtin_modifiers.cmx backends.cmx actions.cmx \
+ builtin_actions.cmi
+builtin_actions.cmi : actions.cmi
+builtin_modifiers.cmo : ocamltest_config.cmi environments.cmi \
+ builtin_variables.cmi builtin_modifiers.cmi
+builtin_modifiers.cmx : ocamltest_config.cmx environments.cmx \
+ builtin_variables.cmx builtin_modifiers.cmi
+builtin_modifiers.cmi : environments.cmi
+builtin_tests.cmo : tests.cmi ocamltest_config.cmi builtin_actions.cmi \
+ builtin_tests.cmi
+builtin_tests.cmx : tests.cmx ocamltest_config.cmx builtin_actions.cmx \
+ builtin_tests.cmi
+builtin_tests.cmi : tests.cmi
+builtin_variables.cmo : variables.cmi builtin_variables.cmi
+builtin_variables.cmx : variables.cmx builtin_variables.cmi
+builtin_variables.cmi : variables.cmi
+environments.cmo : variables.cmi environments.cmi
+environments.cmx : variables.cmx environments.cmi
+environments.cmi : variables.cmi
+filecompare.cmo : testlib.cmi run_command.cmi filecompare.cmi
+filecompare.cmx : testlib.cmx run_command.cmx filecompare.cmi
+filecompare.cmi :
+filetype.cmo : filetype.cmi
+filetype.cmx : filetype.cmi
+filetype.cmi :
+main.cmo : tsl_semantics.cmi tsl_parser.cmi tsl_lexer.cmi tests.cmi \
+ testlib.cmi options.cmi ocamltest_config.cmi environments.cmi \
+ builtin_variables.cmi actions.cmi main.cmi
+main.cmx : tsl_semantics.cmx tsl_parser.cmx tsl_lexer.cmx tests.cmx \
+ testlib.cmx options.cmx ocamltest_config.cmx environments.cmx \
+ builtin_variables.cmx actions.cmx main.cmi
+main.cmi :
+ocamltest_config.cmo : ocamltest_config.cmi
+ocamltest_config.cmx : ocamltest_config.cmi
+ocamltest_config.cmi :
+options.cmo : tests.cmi actions.cmi options.cmi
+options.cmx : tests.cmx actions.cmx options.cmi
+options.cmi :
+run_command.cmo : testlib.cmi run_command.cmi
+run_command.cmx : testlib.cmx run_command.cmi
+run_command.cmi :
+testlib.cmo : testlib.cmi
+testlib.cmx : testlib.cmi
+testlib.cmi :
+tests.cmo : actions.cmi tests.cmi
+tests.cmx : actions.cmx tests.cmi
+tests.cmi : environments.cmi actions.cmi
+tsl_ast.cmo : tsl_ast.cmi
+tsl_ast.cmx : tsl_ast.cmi
+tsl_ast.cmi :
+tsl_lexer.cmo : tsl_parser.cmi tsl_lexer.cmi
+tsl_lexer.cmx : tsl_parser.cmx tsl_lexer.cmi
+tsl_lexer.cmi : tsl_parser.cmi
+tsl_parser.cmo : tsl_ast.cmi tsl_parser.cmi
+tsl_parser.cmx : tsl_ast.cmx tsl_parser.cmi
+tsl_parser.cmi : tsl_ast.cmi
+tsl_semantics.cmo : variables.cmi tsl_ast.cmi tests.cmi testlib.cmi \
+ environments.cmi actions.cmi tsl_semantics.cmi
+tsl_semantics.cmx : variables.cmx tsl_ast.cmx tests.cmx testlib.cmx \
+ environments.cmx actions.cmx tsl_semantics.cmi
+tsl_semantics.cmi : tsl_ast.cmi tests.cmi environments.cmi actions.cmi
+variables.cmo : variables.cmi
+variables.cmx : variables.cmi
+variables.cmi :
--- /dev/null
+#**************************************************************************
+#* *
+#* OCaml *
+#* *
+#* Sebastien Hinderer, projet Gallium, INRIA Paris *
+#* *
+#* Copyright 2016 Institut National de Recherche en Informatique et *
+#* en Automatique. *
+#* *
+#* All rights reserved. This file is distributed under the terms of *
+#* the GNU Lesser General Public License version 2.1, with the *
+#* special exception on linking described in the file LICENSE. *
+#* *
+#**************************************************************************
+
+# The Makefile for ocamltest
+
+include ../config/Makefile
+
+ifeq "$(UNIX_OR_WIN32)" "win32"
+ ocamlsrcdir := $(shell echo "$(abspath $(shell pwd)/..)"|cygpath -m -f -)
+else
+ ocamlsrcdir := $(abspath $(shell pwd)/..)
+endif
+
+CPPFLAGS += -I../byterun -DCAML_INTERNALS
+
+run := run_$(UNIX_OR_WIN32)
+
+# List of source files from which ocamltest is compiled
+# (all the different sorts of files are derived from this)
+
+sources := \
+ $(run).c \
+ run_stubs.c \
+ ocamltest_config.mli ocamltest_config.ml.in \
+ testlib.mli testlib.ml \
+ run_command.mli run_command.ml \
+ filetype.mli filetype.ml \
+ filecompare.mli filecompare.ml \
+ backends.mli backends.ml \
+ variables.mli variables.ml \
+ environments.mli environments.ml \
+ builtin_variables.mli builtin_variables.ml \
+ builtin_modifiers.mli builtin_modifiers.ml \
+ actions.mli actions.ml \
+ builtin_actions.mli builtin_actions.ml \
+ tests.mli tests.ml \
+ builtin_tests.mli builtin_tests.ml \
+ tsl_ast.mli tsl_ast.ml \
+ tsl_parser.mly \
+ tsl_lexer.mli tsl_lexer.mll \
+ tsl_semantics.mli tsl_semantics.ml \
+ options.mli options.ml \
+ main.mli main.ml
+
+# List of .ml files used for ocamldep and to get the list of modules
+
+ml_files := \
+ $(filter %.ml, \
+ $(subst .ml.in,.ml,$(subst .mll,.ml,$(subst .mly,.ml,$(sources)))) \
+ )
+
+cmo_files := $(ml_files:.ml=.cmo)
+
+cmx_files := $(ml_files:.ml=.cmx)
+
+ocaml_objects := $(ml_files:.ml=.$(O))
+
+# List of .mli files for ocamldep
+mli_files := \
+ $(filter %.mli,$(subst .mly,.mli,$(sources)))
+
+cmi_files := $(mli_files:.mli=.cmi)
+
+c_files := $(filter %.c, $(sources))
+
+o_files := $(c_files:.c=.$(O))
+
+lexers := $(filter %.mll,$(sources))
+
+parsers := $(filter %.mly,$(sources))
+
+config_files := $(filter %.ml.in,$(sources))
+
+dependencies_generated_prereqs := \
+ $(config_files:.ml.in=.ml) \
+ $(lexers:.mll=.ml) \
+ $(parsers:.mly=.mli) $(parsers:.mly=.ml)
+
+generated := $(dependencies_generated_prereqs) $(parsers:.mly=.output)
+
+bytecode_modules := $(o_files) $(cmo_files)
+
+native_modules := $(o_files) $(cmx_files)
+
+directories = ../utils ../parsing ../stdlib ../compilerlibs
+
+include_directories = $(addprefix -I , $(directories))
+
+flags = -g -nostdlib $(include_directories) \
+ -strict-sequence -safe-string -strict-formats \
+ -w +a-4-9-41-42-44-45-48 -warn-error A
+
+ifeq "$(UNIX_OR_WIN32)" "unix"
+FLEXLINK_ENV=
+else # Windows
+ ifeq "$(wildcard ../flexdll/Makefile)" ""
+ FLEXLINK_ENV=
+ else
+ FLEXLINK_ENV=OCAML_FLEXLINK="../boot/ocamlrun ../flexdll/flexlink.exe"
+ endif
+endif
+
+ocamlc := $(FLEXLINK_ENV) ../byterun/ocamlrun ../ocamlc $(flags)
+
+ocamlopt := $(FLEXLINK_ENV) ../byterun/ocamlrun ../ocamlopt $(flags)
+
+ocamldep := ../byterun/ocamlrun ../tools/ocamldep -slash
+
+ocamllex := ../byterun/ocamlrun ../lex/ocamllex
+
+ocamlyacc := ../yacc/ocamlyacc
+
+ocamlcdefaultflags :=
+
+ocamloptdefaultflags := $(shell ./getocamloptdefaultflags $(TARGET))
+
+ocamltest$(EXE): $(bytecode_modules)
+ $(ocamlc) -custom ocamlcommon.cma -o $@ $^
+
+%.cmo: %.ml
+ $(ocamlc) -c $<
+
+ocamltest.opt$(EXE): $(native_modules)
+ $(ocamlopt) ocamlcommon.cmxa -o $@ $^
+
+%.cmx: %.ml
+ $(ocamlopt) -c $<
+
+%.cmi: %.mli
+ $(ocamlc) -c $<
+
+%.ml %.mli: %.mly
+ $(ocamlyacc) $<
+
+%.ml: %.mll
+ $(ocamllex) -q $<
+
+%.$(O): %.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) $(BYTECCCOMPOPTS) -c $<
+
+ocamltest_config.ml: ocamltest_config.ml.in
+ sed \
+ -e 's|@@ARCH@@|$(ARCH)|' \
+ -e 's|@@CPP@@|$(CPP)|' \
+ -e 's|@@OCAMLCDEFAULTFLAGS@@|$(ocamlcdefaultflags)|' \
+ -e 's|@@OCAMLOPTDEFAULTFLAGS@@|$(ocamloptdefaultflags)|' \
+ -e 's|@@OCAMLSRCDIR@@|$(ocamlsrcdir)|' \
+ -e 's|@@FLAMBDA@@|$(FLAMBDA)|' \
+ -e 's|@@FORCE_SAFE_STRING@@|$(FORCE_SAFE_STRING)|' \
+ $< > $@
+
+.PHONY: clean
+clean:
+ rm -rf ocamltest$(EXE) ocamltest.opt$(EXE)
+ rm -rf $(o_files) $(ocaml_objects)
+ rm -rf $(cmi_files)
+ rm -rf $(cmo_files)
+ rm -rf $(cmx_files)
+ rm -rf $(generated)
+
+ifneq "$(TOOLCHAIN)" "msvc"
+.PHONY: depend
+depend: $(dependencies_generated_prereqs)
+ $(CC) -MM $(CPPFLAGS) $(c_files) \
+ | sed -e 's/\.o/.$$(O)/' > .depend
+ $(ocamldep) $(mli_files) $(ml_files) >> .depend
+endif
+
+-include .depend
--- /dev/null
+# Introduction
+
+## Context
+
+The testsuite of the OCaml compiler consists of a series of programs
+that are compiled and executed. The output of their compilation and
+execution is compared to expected outputs.
+
+Before the introduction of ocamltest, the tests were driven by a set of
+makefiles which were responsible for compiling and running the test
+programs, and verifying that the compilation and execution outputs were
+matching the expected ones.
+
+In this set-up, the precise information about how exactly one test
+should be compiled was separated from the test itself. It was stored
+somewhere in the makefiles, interleaved with the recipes to actually
+compile and run the test. Thus, given one test, it was not easy to
+determine exactly how this test was supposed to be compiled and run.
+
+## Purpose
+
+The ocamltest tool has been introduced to replace most of the makefiles
+logic. It takes a test program as its input and derives from annotations
+stored as a special comment at the beginning of the program the exact
+way to compile and run it. Thus the test-specific metadata are stored in
+the test file itself and clearly separated from the machinery required
+to perform the actual tasks, which is centralized in the ocamltest tool.
+
+## Constraints
+
+It may look odd at first glance to write the tool used to test the
+compiler in its target language. There are, however, parts of the
+compiler and the standard library that are already tested in a way,
+namely those used to compile the compiler itself. Therefore, these
+components can be considered more trustworthy than those that have
+not yet been used and that's
+why ocamltest relies only on the part of the standard library that has been
+used to develop the compiler itself.
+
+This excludes for instance the use of the Unix and Str libraries.
+
+# Initial set-up
+
+ocamltest needs to know two things:
+
+1. Where the sources of the OCaml compiler to test are located.
+This is determined while OCaml is built. The default location can be
+overriden by defining the OCAMLSRCDIR environment variable.
+
+2. Which directory to use to build tests. The default value for this is
+"ocamltest" under Filename.get_temp_dir_name(). This value can be
+overriden by defining the OCAMLTESTDIR environemnt variable.
+
+# Running tests
+
+(all the commands below are assumed to be run from OCAMLSRCDIR/testsuite)
+
+From here, one can:
+
+## Run all tests: make all
+
+This runs the complete testsuite. This includes the "legacy" tests
+that still use the makefile-based infrastructure and the "new" tests
+that have been migrated to use ocamltest.
+
+## Run legacy tests: make legacy
+
+## Run new tests: make new
+
+## Run tests manually
+
+It is convenient to have the following ocamltest script in a directory
+appearing in PATH, like ~/bin:
+
+#!/bin/sh
+TERM=dumb OCAMLRUNPARAM= /path/to/ocaml/sources/ocamltest/ocamltest $*
+
+Once this file has been made executable, one can for instance run:
+
+ocamltest tests/basic-io/wc.ml
+
+As can be seen, ocamltest's output looks similar to the legacy format.
+
+This is to make the transition between the makefile-based
+infrastructure and ocamltest as smooth as possible. Once all the
+tests will have been migrated to ocamltest, it will become possible to
+change this output format.
+
+The details of what exactly has been tested can be found in
+${OCAMLTESTDIR}/tests/basic-io/wc/wc.log
+
+One can then examine tests/basic-io/wc.ml to see how the file
+had to be annotated to produce such a result.
+
+Many other tests have already been migrated and it may be useful to see
+how the test files have been annotated. the command
+
+find tests -name '*ocamltests*' | xargs cat
+
+gives a list of tests that have been modified and can therefore be used
+as starting points to understand what ocamltest can do.
+
+# Migrating tests from makefiles to ocamltest
+
+It may be a good idea to run make new from the testsuite directory before
+starting to migrate tests. This will show how many "new" tests there
+already are.
+
+Then, when running make new after migrating n tests,
+the number of new tests reported by make new should have increased by n.
+
+OCaml's testsuite is divided into directories, each of them
+containing one or several tests, which can each consist of one or
+several files.
+
+Thus, the directory is the smallest unit that can be migrated.
+
+To see which directories still need to be migrated, do:
+
+find tests -name 'Makefile'
+
+In other words, the directories that still need to be migrated are
+the subdirectories of testsuite/tests that still contain a Makefile.
+
+Once you knwo which directory you want to migrate, say foo, here is
+what you should do:
+
+Read foo/Makefile to see how many tests the directory contains and how
+they are compiled. If the makefile only includes other makefiles and
+does not define any variable, then it means that nothing special
+has to be done to compile or run the tests.
+
+You can also run the tests of this directory with the legacy framework,
+to see exactly how they are compiled and executed. To do so, use the
+following command from the testsuite directory:
+
+make --trace DIR=tests/foo
+
+(You may want to log the output of this command for future reference.)
+
+For each test, annotate its main file with a test block, i.e. a
+comment that looks like this:
+
+(* TEST
+ Optional variable assignments and tests
+*)
+
+In particular, if the test's main file is foo.ml and the test uses
+modules m1.ml and m2.ml, the test block will look like ths:
+
+(* TEST
+ modules = "m1.ml m2.ml"
+*)
+
+And if the test consists of a single file foo.ml that needs to be
+run under the top-level, then its test block will look like this:
+
+(* TEST
+ * toplevel
+*)
+
+Or, if there are two reference files for that test and the name
+of one of them contains "principal", then it means the file should
+be tested with the top-level, without and with the -principal option.
+This is expressed as follows:
+
+(* TEST
+ * toplevel
+ * toplevel
+ include principal
+*)
+
+Lines starting with stars indicate which tests to run. If no test is
+specified, then the tests that are enabled by default are used,
+namely to compile and run the test program in both bytecode and native
+code (roughly speaking).
+
+Once your test has been annotated, run ocamltest on it and see
+whether it passes or fails. If it fails, see the log file to understand why
+and make the necessary adjustments until all the tests pass.
+
+The adjustments will mostly consist in renaming reference files and
+updating their content.
+
+Note that there are different types of reference files, those for
+compiler output and those for program output.
+
+To make sure the migration has been done correctly, you can compare the
+commands used to compile the programs in ocamltest's log file to those
+obtained with make --trace. Beware that the commands used to compare an
+obtained result to an expected one will not show up in ocamltest's log
+file.
+
+Once this has been done for all tests, create a file called "ocamltests"
+(mark the final s!) with the names of all the files that
+have been annotated for ocamltest, one per line.
+
+Finally, git rm the Makefile and run make new from the testsuite directory
+to make sure the number of new tests has increased as expected.
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Definition of actions, basic blocks for tests *)
+
+type result =
+ | Pass of Environments.t
+ | Fail of string
+ | Skip of string
+
+let string_of_reason prefix reason =
+ if reason="" then prefix
+ else prefix ^ " (" ^ reason ^ ")"
+
+let string_of_result = function
+ | Pass _ -> "Pass"
+ | Fail reason -> string_of_reason "Fail" reason
+ | Skip reason -> string_of_reason "Skip" reason
+
+type body = out_channel -> Environments.t -> result
+
+type t = {
+ action_name : string;
+ action_environment : Environments.t -> Environments.t;
+ action_body : body
+}
+
+let compare a1 a2 = String.compare a1.action_name a2.action_name
+
+let (actions : (string, t) Hashtbl.t) = Hashtbl.create 10
+
+let register action =
+ Hashtbl.add actions action.action_name action
+
+let get_registered_actions () =
+ let f _action_name action acc = action::acc in
+ let unsorted_actions = Hashtbl.fold f actions [] in
+ List.sort compare unsorted_actions
+
+let lookup name =
+ try Some (Hashtbl.find actions name)
+ with Not_found -> None
+
+let run log env action =
+ action.action_body log env
+
+module ActionSet = Set.Make
+(struct
+ type nonrec t = t
+ let compare = compare
+end)
+
+let update_environment initial_env actions =
+ let f act env = act.action_environment env in
+ ActionSet.fold f actions initial_env
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Definition of actions, basic blocks for tests *)
+
+type result =
+ | Pass of Environments.t
+ | Fail of string
+ | Skip of string
+
+val string_of_result : result -> string
+
+type body = out_channel -> Environments.t -> result
+
+type t = {
+ action_name : string;
+ action_environment : Environments.t -> Environments.t;
+ action_body : body
+}
+
+val compare : t -> t -> int
+
+val register : t -> unit
+
+val get_registered_actions : unit -> t list
+
+val lookup : string -> t option
+
+val run : out_channel -> Environments.t -> t -> result
+
+module ActionSet : Set.S with type elt = t
+
+val update_environment : Environments.t -> ActionSet.t -> Environments.t
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Backends of the OCaml compiler and their properties *)
+
+type t = Sys.backend_type
+
+let string_of_backend = function
+ | Sys.Bytecode -> "bytecode"
+ | Sys.Native -> "native"
+ | Sys.Other backend_name -> backend_name
+
+(* Creates a function that returns its first argument for Bytecode, *)
+(* its second argument for Native code and fails for other backends *)
+let make_backend_function bytecode_value native_value = function
+ | Sys.Bytecode -> bytecode_value
+ | Sys.Native -> native_value
+ | Sys.Other backend_name ->
+ let error_message =
+ ("Other backend " ^ backend_name ^ " not supported") in
+ raise (Invalid_argument error_message)
+
+let module_extension = make_backend_function "cmo" "cmx"
+
+let library_extension = make_backend_function "cma" "cmxa"
+
+let executable_extension = make_backend_function "byte" "opt"
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Backends of the OCaml compiler and their properties *)
+
+type t = Sys.backend_type
+
+val string_of_backend : t -> string
+
+val make_backend_function : 'a -> 'a -> t -> 'a
+
+val module_extension : t -> string
+
+val library_extension : t -> string
+
+val executable_extension : t -> string
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Definition of a few built-in actions *)
+
+open Actions
+
+(* Miscellaneous functions *)
+
+let env_id env = env
+
+let run_command
+ ?(stdin_variable=Builtin_variables.stdin)
+ ?(stdout_variable=Builtin_variables.stdout)
+ ?(stderr_variable=Builtin_variables.stderr)
+ ?(append=false)
+ ?(timeout=0)
+ log env cmd
+ =
+ let log_redirection std filename =
+ if filename<>"" then
+ begin
+ Printf.fprintf log " Redirecting %s to %s \n%!" std filename
+ end in
+ let lst = List.concat (List.map Testlib.words cmd) in
+ let quoted_lst =
+ if Sys.os_type="Win32"
+ then List.map Testlib.maybe_quote lst
+ else lst in
+ let cmd' = String.concat " " quoted_lst in
+ Printf.fprintf log "Commandline: %s\n" cmd';
+ let progname = List.hd quoted_lst in
+ let arguments = Array.of_list quoted_lst in
+ (*
+ let environment =
+ try [|Sys.getenv "PATH" |]
+ with Not_found -> [| |] in
+ *)
+ let stdin_filename = Environments.safe_lookup stdin_variable env in
+ let stdout_filename = Environments.safe_lookup stdout_variable env in
+ let stderr_filename = Environments.safe_lookup stderr_variable env in
+ log_redirection "stdin" stdin_filename;
+ log_redirection "stdout" stdout_filename;
+ log_redirection "stderr" stderr_filename;
+ Run_command.run {
+ Run_command.progname = progname;
+ Run_command.argv = arguments;
+ (* Run_command.envp = environment; *)
+ Run_command.stdin_filename = stdin_filename;
+ Run_command.stdout_filename = stdout_filename;
+ Run_command.stderr_filename = stderr_filename;
+ Run_command.append = append;
+ Run_command.timeout = timeout;
+ Run_command.log = log
+ }
+
+let mkreason what commandline exitcode =
+ Printf.sprintf "%s: command\n%s\nfailed with exit code %d"
+ what commandline exitcode
+
+let make_file_name name ext = String.concat "." [name; ext]
+
+let make_path components = List.fold_left Filename.concat "" components
+
+(*
+let rec map_reduce_result f g init = function
+ | [] -> Ok init
+ | x::xs ->
+ (match f x with
+ | Ok fx ->
+ (match map_reduce_result f g init xs with
+ | Ok fxs -> Ok (g fx fxs)
+ | Error _ as e -> e
+ )
+ | Error _ as e -> e
+ )
+*)
+
+let setup_symlinks test_source_directory build_directory files =
+ let symlink filename =
+ let src = Filename.concat test_source_directory filename in
+ let cmd = "ln -sf " ^ src ^" " ^ build_directory in
+ Testlib.run_system_command cmd in
+ let copy filename =
+ let src = Filename.concat test_source_directory filename in
+ let dst = Filename.concat build_directory filename in
+ Testlib.copy_file src dst in
+ let f = if Sys.os_type="Win32" then copy else symlink in
+ List.iter f files
+
+let mkexe =
+ if Sys.os_type="Win32"
+ then fun name -> make_file_name name "exe"
+ else fun name -> name
+
+(* Compilers and flags *)
+
+let ocamlsrcdir () =
+ try Sys.getenv "OCAMLSRCDIR"
+ with Not_found -> Ocamltest_config.ocamlsrcdir
+
+let ocamlrun ocamlsrcdir =
+ let ocamlrunfile = mkexe "ocamlrun" in
+ make_path [ocamlsrcdir; "byterun"; ocamlrunfile]
+
+let ocamlc ocamlsrcdir =
+ make_path [ocamlsrcdir; "ocamlc"]
+
+let ocaml ocamlsrcdir =
+ make_path [ocamlsrcdir; "ocaml"]
+
+let ocamlc_dot_byte ocamlsrcdir =
+ let ocamlrun = ocamlrun ocamlsrcdir in
+ let ocamlc = ocamlc ocamlsrcdir in
+ ocamlrun ^ " " ^ ocamlc
+
+let ocamlc_dot_opt ocamlsrcdir =
+ make_path [ocamlsrcdir; "ocamlc.opt"]
+
+let ocamlopt ocamlsrcdir =
+ make_path [ocamlsrcdir; "ocamlopt"]
+
+let ocamlopt_dot_byte ocamlsrcdir =
+ let ocamlrun = ocamlrun ocamlsrcdir in
+ let ocamlopt = ocamlopt ocamlsrcdir in
+ ocamlrun ^ " " ^ ocamlopt
+
+let ocamlopt_dot_opt ocamlsrcdir =
+ make_path [ocamlsrcdir; "ocamlopt.opt"]
+
+let ocaml_dot_byte ocamlsrcdir =
+ let ocamlrun = ocamlrun ocamlsrcdir in
+ let ocaml = ocaml ocamlsrcdir in
+ ocamlrun ^ " " ^ ocaml
+
+let ocaml_dot_opt ocamlsrcdir =
+ make_path [ocamlsrcdir; mkexe "ocamlnat"]
+
+let cmpbyt ocamlsrcdir =
+ make_path [ocamlsrcdir; "tools"; "cmpbyt"]
+
+let stdlib ocamlsrcdir =
+ make_path [ocamlsrcdir; "stdlib"]
+
+let stdlib_flags ocamlsrcdir =
+ let stdlib_path = stdlib ocamlsrcdir in
+ "-nostdlib -I " ^ stdlib_path
+
+let c_includes ocamlsrcdir =
+ make_path [ocamlsrcdir; "byterun"]
+
+let c_includes_flags ocamlsrcdir =
+ let dir = c_includes ocamlsrcdir in
+ "-ccopt -I" ^ dir
+
+let use_runtime backend ocamlsrcdir = match backend with
+ | Sys.Bytecode ->
+ let ocamlrun = ocamlrun ocamlsrcdir in
+ "-use-runtime " ^ ocamlrun
+ | _ -> ""
+
+(* Compiler descriptions *)
+
+type compiler_info = {
+ compiler_name : string -> string;
+ compiler_flags : string;
+ compiler_directory : string;
+ compiler_backend : Sys.backend_type;
+ compiler_exit_status_variabe : Variables.t;
+ compiler_reference_variable : Variables.t;
+ compiler_output_variable : Variables.t
+}
+
+(* Compilers compiling byte-code programs *)
+
+let bytecode_bytecode_compiler =
+{
+ compiler_name = ocamlc_dot_byte;
+ compiler_flags = "";
+ compiler_directory = "ocamlc.byte";
+ compiler_backend = Sys.Bytecode;
+ compiler_exit_status_variabe = Builtin_variables.ocamlc_byte_exit_status;
+ compiler_reference_variable = Builtin_variables.compiler_reference;
+ compiler_output_variable = Builtin_variables.compiler_output;
+}
+
+let bytecode_native_compiler =
+{
+ compiler_name = ocamlc_dot_opt;
+ compiler_flags = "";
+ compiler_directory = "ocamlc.opt";
+ compiler_backend = Sys.Bytecode;
+ compiler_exit_status_variabe = Builtin_variables.ocamlc_opt_exit_status;
+ compiler_reference_variable = Builtin_variables.compiler_reference2;
+ compiler_output_variable = Builtin_variables.compiler_output2;
+}
+
+(* Compilers compiling native-code programs *)
+
+let native_bytecode_compiler =
+{
+ compiler_name = ocamlopt_dot_byte;
+ compiler_flags = "";
+ compiler_directory = "ocamlopt.byte";
+ compiler_backend = Sys.Native;
+ compiler_exit_status_variabe = Builtin_variables.ocamlopt_byte_exit_status;
+ compiler_reference_variable = Builtin_variables.compiler_reference;
+ compiler_output_variable = Builtin_variables.compiler_output;
+}
+
+let native_native_compiler =
+{
+ compiler_name = ocamlopt_dot_opt;
+ compiler_flags = "";
+ compiler_directory = "ocamlopt.opt";
+ compiler_backend = Sys.Native;
+ compiler_exit_status_variabe = Builtin_variables.ocamlopt_opt_exit_status;
+ compiler_reference_variable = Builtin_variables.compiler_reference2;
+ compiler_output_variable = Builtin_variables.compiler_output2;
+}
+
+(* Top-levels *)
+
+let ocaml = {
+ compiler_name = ocaml_dot_byte;
+ compiler_flags = "";
+ compiler_directory = "ocaml";
+ compiler_backend = Sys.Bytecode;
+ compiler_exit_status_variabe = Builtin_variables.ocaml_byte_exit_status;
+ compiler_reference_variable = Builtin_variables.compiler_reference;
+ compiler_output_variable = Builtin_variables.compiler_output;
+}
+
+let ocamlnat = {
+ compiler_name = ocaml_dot_opt;
+ compiler_flags = "-S"; (* Keep intermediate assembly files *)
+ compiler_directory = "ocamlnat";
+ compiler_backend = Sys.Native;
+ compiler_exit_status_variabe = Builtin_variables.ocaml_opt_exit_status;
+ compiler_reference_variable = Builtin_variables.compiler_reference2;
+ compiler_output_variable = Builtin_variables.compiler_output2;
+}
+
+let expected_compiler_exit_status env compiler =
+ try int_of_string
+ (Environments.safe_lookup compiler.compiler_exit_status_variabe env)
+ with _ -> 0
+
+let compiler_reference_filename env prefix compiler =
+ let compiler_reference_suffix =
+ Environments.safe_lookup Builtin_variables.compiler_reference_suffix env in
+ let suffix =
+ if compiler_reference_suffix<>""
+ then compiler_reference_suffix ^ ".reference"
+ else ".reference" in
+ let mk s = (make_file_name prefix s) ^suffix in
+ let filename = mk compiler.compiler_directory in
+ if Sys.file_exists filename then filename else
+ let filename = mk (Backends.string_of_backend compiler.compiler_backend) in
+ if Sys.file_exists filename then filename else
+ mk "compilers"
+
+(* Extracting information from environment *)
+
+let get_backend_value_from_env env bytecode_var native_var =
+ Backends.make_backend_function
+ (Environments.safe_lookup bytecode_var env)
+ (Environments.safe_lookup native_var env)
+
+let testfile env =
+ match Environments.lookup Builtin_variables.test_file env with
+ | None -> assert false
+ | Some t -> t
+
+let words_of_variable variable env =
+ Testlib.words (Environments.safe_lookup variable env)
+
+let modules env = words_of_variable Builtin_variables.modules env
+
+let files env = words_of_variable Builtin_variables.files env
+
+let flags env = Environments.safe_lookup Builtin_variables.flags env
+
+let libraries backend env =
+ let value = Environments.safe_lookup Builtin_variables.libraries env in
+ let libs = Testlib.words value in
+ let extension = Backends.library_extension backend in
+ let add_extension lib = make_file_name lib extension in
+ String.concat " " (List.map add_extension libs)
+
+let backend_default_flags env =
+ get_backend_value_from_env env
+ Builtin_variables.ocamlc_default_flags
+ Builtin_variables.ocamlopt_default_flags
+
+let backend_flags env =
+ get_backend_value_from_env env
+ Builtin_variables.ocamlc_flags
+ Builtin_variables.ocamlopt_flags
+
+let test_source_directory env =
+ Environments.safe_lookup Builtin_variables.test_source_directory env
+
+let test_build_directory env =
+ Environments.safe_lookup Builtin_variables.test_build_directory env
+
+(*
+let action_of_filetype = function
+ | Filetype.Implementation -> "Compiling implementation"
+ | Filetype.Interface -> "Compiling interface"
+ | Filetype.C -> "Compiling C source file"
+ | Filetype.C_minus_minus -> "Processing C minus minus file"
+ | Filetype.Lexer -> "Generating lexer"
+ | Filetype.Grammar -> "Generating parser"
+*)
+
+let link_modules
+ ocamlsrcdir compiler compilername compileroutput program_variable
+ custom c_headers_flags log env modules
+ =
+ let backend = compiler.compiler_backend in
+ let expected_exit_status = expected_compiler_exit_status env compiler in
+ let executable_name = match Environments.lookup program_variable env with
+ | None -> assert false
+ | Some program -> program in
+ let module_names =
+ String.concat " " (List.map Filetype.make_filename modules) in
+ let what = Printf.sprintf "Linking modules %s into %s"
+ module_names executable_name in
+ Printf.fprintf log "%s\n%!" what;
+ let output = "-o " ^ executable_name in
+ let customstr = if custom then "-custom" else "" in
+ let commandline =
+ [
+ compilername;
+ customstr;
+ c_headers_flags;
+ use_runtime backend ocamlsrcdir;
+ stdlib_flags ocamlsrcdir;
+ "-linkall";
+ flags env;
+ libraries backend env;
+ backend_default_flags env backend;
+ backend_flags env backend;
+ output;
+ module_names
+ ] in
+ let exit_status =
+ run_command
+ ~stdout_variable:compileroutput
+ ~stderr_variable:compileroutput
+ ~append:true
+ log env commandline in
+ if exit_status=expected_exit_status
+ then Pass env
+ else Fail (mkreason what (String.concat " " commandline) exit_status)
+
+let compile_program
+ ocamlsrcdir compiler compilername compileroutput program_variable
+ log env modules
+ =
+ let is_c_file (_filename, filetype) = filetype=Filetype.C in
+ let has_c_file = List.exists is_c_file modules in
+ let backend = compiler.compiler_backend in
+ let custom = (backend = Sys.Bytecode) && has_c_file in
+ let c_headers_flags =
+ if has_c_file then c_includes_flags ocamlsrcdir else "" in
+ link_modules
+ ocamlsrcdir compiler compilername compileroutput
+ program_variable custom c_headers_flags log env modules
+
+let module_has_interface directory module_name =
+ let interface_name =
+ Filetype.make_filename (module_name, Filetype.Interface) in
+ let interface_fullpath = make_path [directory;interface_name] in
+ Sys.file_exists interface_fullpath
+
+let add_module_interface directory module_description =
+ match module_description with
+ | (filename, Filetype.Implementation) when
+ module_has_interface directory filename ->
+ [(filename, Filetype.Interface); module_description]
+ | _ -> [module_description]
+
+let print_module_names log description modules =
+ Printf.fprintf log "%s modules: %s\n%!"
+ description
+ (String.concat " " (List.map Filetype.make_filename modules))
+
+let setup_build_environment
+ testfile source_directory build_directory log env
+ =
+ let specified_modules =
+ List.map Filetype.filetype ((modules env) @ [testfile]) in
+ print_module_names log "Specified" specified_modules;
+ let source_modules =
+ Testlib.concatmap
+ (add_module_interface source_directory)
+ specified_modules in
+ print_module_names log "Source" source_modules;
+ Testlib.make_directory build_directory;
+ setup_symlinks
+ source_directory
+ build_directory
+ (List.map Filetype.make_filename source_modules);
+ setup_symlinks source_directory build_directory (files env);
+ Sys.chdir build_directory;
+ source_modules
+
+let prepare_module (module_name, module_type) =
+ match module_type with
+ | Filetype.Implementation | Filetype.Interface | Filetype.C ->
+ [(module_name, module_type)]
+ | Filetype.C_minus_minus -> assert false
+ | Filetype.Lexer -> assert false
+ | Filetype.Grammar -> assert false
+
+let compile_test_program program_variable compiler log env =
+ let backend = compiler.compiler_backend in
+ let testfile = testfile env in
+ let testfile_basename = Filename.chop_extension testfile in
+ let source_directory = test_source_directory env in
+ let compiler_directory_suffix =
+ Environments.safe_lookup Builtin_variables.compiler_directory_suffix env in
+ let compiler_directory_name =
+ compiler.compiler_directory ^ compiler_directory_suffix in
+ let build_directory =
+ make_path [test_build_directory env; compiler_directory_name] in
+ let compilerreference_prefix =
+ make_path [source_directory; testfile_basename] in
+ let compilerreference_filename =
+ compiler_reference_filename env compilerreference_prefix compiler in
+ let compiler_reference_variable = compiler.compiler_reference_variable in
+ let executable_filename =
+ mkexe
+ (make_file_name
+ testfile_basename (Backends.executable_extension backend)) in
+ let executable_path = make_path [build_directory; executable_filename] in
+ let compiler_output_filename =
+ make_file_name compiler.compiler_directory "output" in
+ let compiler_output =
+ make_path [build_directory; compiler_output_filename] in
+ let compiler_output_variable = compiler.compiler_output_variable in
+ let newenv = Environments.add_bindings
+ [
+ (program_variable, executable_path);
+ (compiler_reference_variable, compilerreference_filename);
+ (compiler_output_variable, compiler_output);
+ ] env in
+ if Sys.file_exists compiler_output_filename then
+ Sys.remove compiler_output_filename;
+ let ocamlsrcdir = ocamlsrcdir () in
+ let compilername = compiler.compiler_name ocamlsrcdir in
+ let source_modules =
+ setup_build_environment
+ testfile source_directory build_directory log env in
+ let prepared_modules =
+ Testlib.concatmap prepare_module source_modules in
+ compile_program
+ ocamlsrcdir
+ compiler
+ compilername
+ compiler_output_variable
+ program_variable log newenv prepared_modules
+
+(* Compile actions *)
+
+let compile_bytecode_with_bytecode_compiler = {
+ action_name = "compile-bytecode-with-bytecode-compiler";
+ action_environment = env_id;
+ action_body =
+ compile_test_program
+ Builtin_variables.program bytecode_bytecode_compiler
+}
+
+let compile_bytecode_with_native_compiler = {
+ action_name = "compile-bytecode-with-native-compiler";
+ action_environment = env_id;
+ action_body =
+ compile_test_program
+ Builtin_variables.program2 bytecode_native_compiler
+}
+
+let compile_native_with_bytecode_compiler = {
+ action_name = "compile-native-with-bytecode-compiler";
+ action_environment = env_id;
+ action_body =
+ compile_test_program
+ Builtin_variables.program native_bytecode_compiler
+}
+
+let compile_native_with_native_compiler = {
+ action_name = "compile-native-with-native-compiler";
+ action_environment = env_id;
+ action_body =
+ compile_test_program
+ Builtin_variables.program2 native_native_compiler
+}
+
+let exec log_message redirect_output prog_variable args_variable log env =
+ match Environments.lookup prog_variable env with
+ | None ->
+ let msg = Printf.sprintf "%s: variable %s is undefined"
+ log_message (Variables.name_of_variable prog_variable) in
+ Fail msg
+ | Some program ->
+ let arguments = Environments.safe_lookup args_variable env in
+ let commandline = [program; arguments] in
+ let what = log_message ^ " " ^ program ^ " " ^
+ begin if arguments="" then "without any argument"
+ else "with arguments " ^ arguments
+ end in
+ let output = program ^ ".output" in
+ let bindings =
+ [
+ Builtin_variables.stdout, output;
+ Builtin_variables.stderr, output
+ ] in
+ let execution_env =
+ if redirect_output then Environments.add_bindings bindings env
+ else env in
+ match run_command log execution_env commandline with
+ | 0 ->
+ let newenv =
+ if redirect_output
+ then Environments.add Builtin_variables.output output env
+ else env in
+ Pass newenv
+ | _ as exitcode ->
+ if exitcode = 125
+ then Skip (mkreason what (String.concat " " commandline) exitcode)
+ else Fail (mkreason what (String.concat " " commandline) exitcode)
+
+let execute_program =
+ exec
+ "Executing program"
+ true
+ Builtin_variables.program
+ Builtin_variables.arguments
+
+let execute = {
+ action_name = "execute-program";
+ action_environment = env_id;
+ action_body = execute_program
+}
+
+let run_script log env =
+ let testfile = testfile env in
+ (* let testfile_basename = Filename.chop_extension testfile in *)
+ let source_directory = test_source_directory env in
+ let build_directory = test_build_directory env in
+ let _modules =
+ setup_build_environment
+ testfile source_directory build_directory log env in
+ exec
+ "Running script"
+ false
+ Builtin_variables.script
+ Builtin_variables.test_file
+ log env
+
+let script = {
+ action_name = "run-script";
+ action_environment = env_id;
+ action_body = run_script
+}
+
+let run_expect log env =
+ let newenv = Environments.apply_modifiers env Builtin_modifiers.expect in
+ run_script log newenv
+
+let expect = {
+ action_name = "run-expect";
+ action_environment = env_id;
+ action_body = run_expect
+}
+
+let check_output kind_of_output output_variable reference_variable log env =
+ let reference_filename = Environments.safe_lookup reference_variable env in
+ let output_filename = Environments.safe_lookup output_variable env in
+ Printf.fprintf log "Comparing %s output %s to reference %s\n%!"
+ kind_of_output output_filename reference_filename;
+ let files =
+ {
+ Filecompare.filetype = Filecompare.Text;
+ Filecompare.reference_filename = reference_filename;
+ Filecompare.output_filename = output_filename
+ } in
+ match Filecompare.check_file files with
+ | Filecompare.Same -> Pass env
+ | Filecompare.Different ->
+ let diff = Filecompare.diff files in
+ let diffstr = match diff with
+ | Ok difference -> difference
+ | Error diff_file -> ("See " ^ diff_file) in
+ let reason =
+ Printf.sprintf "%s output %s differs from reference %s: \n%s\n"
+ kind_of_output output_filename reference_filename diffstr in
+ (Actions.Fail reason)
+ | Filecompare.Unexpected_output ->
+ let banner = String.make 40 '=' in
+ let unexpected_output = Testlib.string_of_file output_filename in
+ let unexpected_output_with_banners = Printf.sprintf
+ "%s\n%s%s\n" banner unexpected_output banner in
+ let reason = Printf.sprintf
+ "The file %s was expected to be empty because there is no \
+ reference file %s but it is not:\n%s\n"
+ output_filename reference_filename unexpected_output_with_banners in
+ (Actions.Fail reason)
+ | Filecompare.Error (commandline, exitcode) ->
+ let reason = Printf.sprintf "The command %s failed with status %d"
+ commandline exitcode in
+ (Actions.Fail reason)
+
+let make_check_compiler_output name compiler = {
+ action_name = name;
+ action_environment = env_id;
+ action_body =
+ check_output
+ "compiler"
+ compiler.compiler_output_variable
+ compiler.compiler_reference_variable
+}
+
+let check_ocamlc_dot_byte_output = make_check_compiler_output
+ "check-ocamlc-byte-output" bytecode_bytecode_compiler
+
+let check_ocamlc_dot_opt_output = make_check_compiler_output
+ "check-ocamlc-opt-output" bytecode_native_compiler
+
+let check_ocamlopt_dot_byte_output = make_check_compiler_output
+ "check-ocamlopt-byte-output" native_bytecode_compiler
+
+let check_ocamlopt_dot_opt_output = make_check_compiler_output
+ "check-ocamlopt-opt-output" native_native_compiler
+
+let check_program_output = {
+ action_name = "check-program-output";
+ action_environment = env_id;
+ action_body = check_output "program"
+ Builtin_variables.output
+ Builtin_variables.reference
+}
+
+(*
+let comparison_start_address portable_executable_filename =
+ let portable_executalbe_signature = "PE\000\000" in
+ let signature_length = String.length portable_executalbe_signature in
+ let address_length = 4 in
+ let start_address = 0x3c in
+ let ic = open_in portable_executable_filename in
+ seek_in ic start_address;
+ let portable_executable_signature_address_str =
+ really_input_string ic address_length in
+ let b0 = int_of_char portable_executable_signature_address_str.[0] in
+ let b1 = int_of_char portable_executable_signature_address_str.[1] in
+ let b2 = int_of_char portable_executable_signature_address_str.[2] in
+ let b3 = int_of_char portable_executable_signature_address_str.[3] in
+ let signature_address =
+ b0 +
+ b1 * 256 +
+ b2 * 256 * 256 +
+ b3 * 256 * 256 * 256 in
+ seek_in ic signature_address;
+ let signature =
+ really_input_string ic signature_length in
+ if signature<>portable_executalbe_signature
+ then failwith
+ (portable_executable_filename ^ " does not contain the PE signature");
+ let result = signature_address + 12 in
+ (* 12 is 4-bytes signature, 2-bytes machine type, *)
+ (* 2-bytes number of sections, 4-bytes timestamp *)
+ close_in ic;
+ result
+*)
+
+let compare_programs backend comparison_tool log env =
+ let program = Environments.safe_lookup Builtin_variables.program env in
+ let program2 = Environments.safe_lookup Builtin_variables.program2 env in
+ let what = Printf.sprintf "Comparing %s programs %s and %s"
+ (Backends.string_of_backend backend) program program2 in
+ Printf.fprintf log "%s\n%!" what;
+ let files = {
+ Filecompare.filetype = Filecompare.Binary;
+ Filecompare.reference_filename = program;
+ Filecompare.output_filename = program2
+ } in
+ if Ocamltest_config.flambda && backend = Sys.Native
+ then begin
+ Printf.fprintf log
+ "flambda temporarily disables comparison of native programs";
+ Pass env
+ end else if backend = Sys.Native && (Sys.os_type="Win32" || Sys.os_type="Cygwin")
+ then begin
+ Printf.fprintf log
+ "comparison of native programs temporarily disabled under Windows";
+ Pass env
+ end else begin
+ let comparison_tool =
+ if backend=Sys.Native && (Sys.os_type="Win32" || Sys.os_type="Cygwin")
+ then
+ let bytes_to_ignore = 512 (* comparison_start_address program *) in
+ Filecompare.make_cmp_tool bytes_to_ignore
+ else comparison_tool in
+ match Filecompare.compare_files ~tool:comparison_tool files with
+ | Filecompare.Same -> Pass env
+ | Filecompare.Different ->
+ let reason = Printf.sprintf "Files %s and %s are different"
+ program program2 in
+ Fail reason
+ | Filecompare.Unexpected_output -> assert false
+ | Filecompare.Error (commandline, exitcode) ->
+ let reason = mkreason what commandline exitcode in
+ Fail reason
+ end
+
+let make_bytecode_programs_comparison_tool ocamlsrcdir =
+ let ocamlrun = ocamlrun ocamlsrcdir in
+ let cmpbyt = cmpbyt ocamlsrcdir in
+ let tool_name = ocamlrun ^ " " ^ cmpbyt in
+ Filecompare.make_comparison_tool tool_name ""
+
+let native_programs_comparison_tool = Filecompare.default_comparison_tool
+
+let compare_bytecode_programs_body log env =
+ let ocamlsrcdir = ocamlsrcdir () in
+ let bytecode_programs_comparison_tool =
+ make_bytecode_programs_comparison_tool ocamlsrcdir in
+ compare_programs Sys.Bytecode bytecode_programs_comparison_tool log env
+
+let compare_bytecode_programs = {
+ action_name = "compare-bytecode-programs";
+ action_environment = env_id;
+ action_body = compare_bytecode_programs_body
+}
+
+let compare_native_programs = {
+ action_name = "compare-native-programs";
+ action_environment = env_id;
+ action_body = compare_programs Sys.Native native_programs_comparison_tool
+}
+
+let run_test_program_in_toplevel toplevel log env =
+ let testfile = testfile env in
+ let testfile_basename = Filename.chop_extension testfile in
+ let expected_exit_status = expected_compiler_exit_status env toplevel in
+ let what =
+ Printf.sprintf "Running %s in %s toplevel (expected exit status: %d)"
+ testfile
+ (Backends.string_of_backend toplevel.compiler_backend)
+ expected_exit_status in
+ Printf.fprintf log "%s\n%!" what;
+ let source_directory = test_source_directory env in
+ let compiler_directory_suffix =
+ Environments.safe_lookup Builtin_variables.compiler_directory_suffix env in
+ let compiler_directory_name =
+ toplevel.compiler_directory ^ compiler_directory_suffix in
+ let build_directory =
+ make_path [test_build_directory env; compiler_directory_name] in
+ let _modules =
+ setup_build_environment
+ testfile source_directory build_directory log env in
+ let compilerreference_prefix =
+ make_path [source_directory; testfile_basename] in
+ let compilerreference_filename =
+ compiler_reference_filename env compilerreference_prefix toplevel in
+ let compiler_reference_variable = toplevel.compiler_reference_variable in
+ let compiler_output_filename =
+ make_file_name toplevel.compiler_directory "output" in
+ let compiler_output =
+ make_path [build_directory; compiler_output_filename] in
+ let compiler_output_variable = toplevel.compiler_output_variable in
+ let newenv = Environments.add_bindings
+ [
+ (compiler_reference_variable, compilerreference_filename);
+ (compiler_output_variable, compiler_output);
+ ] env in
+ if Sys.file_exists compiler_output_filename then
+ Sys.remove compiler_output_filename;
+ let ocamlsrcdir = ocamlsrcdir () in
+ let toplevel_name = toplevel.compiler_name ocamlsrcdir in
+ let toplevel_default_flags = "-noinit -no-version -noprompt" in
+ let commandline =
+ [
+ toplevel_name;
+ toplevel_default_flags;
+ toplevel.compiler_flags;
+ stdlib_flags ocamlsrcdir;
+ flags env;
+ ] in
+ let exit_status =
+ run_command
+ ~stdin_variable:Builtin_variables.test_file
+ ~stdout_variable:compiler_output_variable
+ ~stderr_variable:compiler_output_variable
+ log newenv commandline in
+ if exit_status=expected_exit_status
+ then Pass newenv
+ else Fail (mkreason what (String.concat " " commandline) exit_status)
+
+let run_in_ocaml =
+{
+ action_name = "run-in-bytecode-toplevel";
+ action_environment = env_id;
+ action_body = run_test_program_in_toplevel ocaml;
+}
+
+let run_in_ocamlnat =
+{
+ action_name = "run-in-native-toplevel";
+ action_environment = env_id;
+ action_body = run_test_program_in_toplevel ocamlnat;
+}
+
+let check_ocaml_output = make_check_compiler_output
+ "check-bytecode-toplevel-output" ocaml
+
+let check_ocamlnat_output = make_check_compiler_output
+ "check-native-toplevel-output" ocamlnat
+
+let if_not_safe_string = {
+ action_name = "if_not_safe_string";
+ action_environment = env_id;
+ action_body = fun _log env ->
+ if Ocamltest_config.safe_string
+ then Skip "safe strings enabled"
+ else Pass env
+}
+
+let _ =
+ List.iter register
+ [
+ compile_bytecode_with_bytecode_compiler;
+ compile_bytecode_with_native_compiler;
+ compile_native_with_bytecode_compiler;
+ compile_native_with_native_compiler;
+ execute;
+ script;
+ check_program_output;
+ compare_bytecode_programs;
+ compare_native_programs;
+ check_ocamlc_dot_byte_output;
+ check_ocamlc_dot_opt_output;
+ check_ocamlopt_dot_byte_output;
+ check_ocamlopt_dot_opt_output;
+ run_in_ocaml;
+ run_in_ocamlnat;
+ check_ocaml_output;
+ check_ocamlnat_output;
+ if_not_safe_string;
+ ]
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Definition of a few built-in actions *)
+
+val compile_bytecode_with_bytecode_compiler : Actions.t
+val compile_bytecode_with_native_compiler : Actions.t
+val compile_native_with_bytecode_compiler : Actions.t
+val compile_native_with_native_compiler : Actions.t
+
+val execute : Actions.t
+val expect : Actions.t
+val script : Actions.t
+val check_program_output : Actions.t
+
+val compare_bytecode_programs : Actions.t
+val compare_native_programs : Actions.t
+
+val check_ocamlc_dot_byte_output : Actions.t
+val check_ocamlc_dot_opt_output : Actions.t
+val check_ocamlopt_dot_byte_output : Actions.t
+val check_ocamlopt_dot_opt_output : Actions.t
+
+val run_in_ocaml : Actions.t
+
+val run_in_ocamlnat : Actions.t
+
+val check_ocaml_output : Actions.t
+
+val check_ocamlnat_output : Actions.t
+val if_not_safe_string : Actions.t
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Definition of a few built-in environment modifiers *)
+
+open Environments
+open Builtin_variables
+
+let expect =
+[
+ Replace (script, "bash ${OCAMLSRCDIR}/testsuite/tools/expect");
+]
+
+let principal =
+[
+ Append (flags, " -principal ");
+ Add (compiler_directory_suffix, ".principal");
+ Add (compiler_reference_suffix, ".principal");
+]
+
+let testinglib_directory = Ocamltest_config.ocamlsrcdir ^ "/testsuite/lib"
+
+let testing =
+[
+ Append (flags, (" -I " ^ testinglib_directory ^ " "));
+ Append (libraries, " testing ");
+]
+
+let _ =
+ register expect "expect";
+ register principal "principal";
+ register testing "testing"
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Definition of a few built-in environment modifiers *)
+
+val expect : Environments.modifiers
+
+val principal : Environments.modifiers
+
+val testing : Environments.modifiers
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Definitions of built-in tests *)
+
+open Tests
+open Builtin_actions
+
+let bytecode =
+ let opt_actions =
+ [
+ compile_bytecode_with_native_compiler;
+ check_ocamlc_dot_opt_output;
+ compare_bytecode_programs
+ ] in
+{
+ test_name = "bytecode";
+ test_run_by_default = true;
+ test_actions =
+ [
+ compile_bytecode_with_bytecode_compiler;
+ check_ocamlc_dot_byte_output;
+ execute;
+ check_program_output
+ ] @ (if Ocamltest_config.arch<>"none" then opt_actions else [])
+}
+
+let expect = {
+ test_name = "expect";
+ test_run_by_default = false;
+ test_actions = [expect];
+}
+
+let native = {
+ test_name = "native";
+ test_run_by_default = true;
+ test_actions =
+ [
+ compile_native_with_bytecode_compiler;
+ check_ocamlopt_dot_byte_output;
+ execute;
+ check_program_output;
+ compile_native_with_native_compiler;
+ check_ocamlopt_dot_opt_output;
+ compare_native_programs;
+ ]
+}
+
+let script = {
+ test_name = "script";
+ test_run_by_default = false;
+ test_actions = [script];
+}
+
+let toplevel = {
+ test_name = "toplevel";
+ test_run_by_default = false;
+ test_actions =
+ [
+ run_in_ocaml;
+ check_ocaml_output;
+(*
+ run_in_ocamlnat;
+ check_ocamlnat_output;
+*)
+ ]
+}
+
+let _ =
+ List.iter register
+ [
+ bytecode;
+ expect;
+ script;
+ toplevel;
+ ];
+ if (Ocamltest_config.arch <> "none") then register native
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Definitions of built-in tests *)
+
+val bytecode : Tests.t
+
+val expect : Tests.t
+
+val native : Tests.t
+
+val script : Tests.t
+
+val toplevel : Tests.t
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Definition of variables used by built-in actions *)
+
+(* The variables are listed in alphabetical order *)
+
+(*
+ The name of the identifier representing a variable and its string name
+ should be similar. Is there a way to enforce this?
+*)
+
+open Variables (* Should not be necessary with a ppx *)
+
+let arguments = make ("arguments",
+ "Arguments passed to executed programs and scripts")
+
+let c_preprocessor = make ("c_preprocessor",
+ "Command to use to invoke the C preprocessor")
+
+let compiler_directory_suffix = make ("compiler_directory_suffix",
+ "Suffix to add to the directory where the test will be compiled")
+
+let compiler_reference = make ("compiler_reference",
+ "Reference file for compiler output for ocamlc.byte and ocamlopt.byte")
+
+let compiler_reference2 = make ("compiler_reference2",
+ "Reference file for compiler output for ocamlc.opt and ocamlopt.opt")
+
+let compiler_reference_suffix = make ("compiler_reference_suffix",
+ "Suffix to add to the file name containing the reference for compiler output")
+
+let compiler_output = make ("compiler_output",
+ "Where to log output of bytecode compilers")
+
+let compiler_output2 = make ("compiler_output2",
+ "Where to log output of native compilers")
+
+let ocamlc_flags = make ("ocamlc_flags",
+ "Flags passed to ocamlc.byte and ocamlc.opt")
+
+let ocamlc_default_flags = make ("ocamlc_default_flags",
+ "Flags passed by default to ocamlc.byte and ocamlc.opt")
+
+let files = make ("files",
+ "Files used by the tests")
+
+let flags = make ("flags",
+ "Flags passed to all the compilers")
+
+let libraries = make ("libraries",
+ "Libraries the program should be linked with")
+
+let modules = make ("modules",
+ "Other modules of the test")
+
+let ocamlopt_flags = make ("ocamlopt_flags",
+ "Flags passed to ocamlopt.byte and ocamlopt.opt")
+
+let ocamlopt_default_flags = make ("ocamlopt_default_flags",
+ "Flags passed by default to ocamlopt.byte and ocamlopt.opt")
+
+let ocaml_byte_exit_status = make ("ocaml_byte_exit_status",
+ "Expected exit status of ocaml.byte")
+
+let ocamlc_byte_exit_status = make ("ocamlc_byte_exit_status",
+ "Expected exit status of ocac.byte")
+
+let ocamlopt_byte_exit_status = make ("ocamlopt_byte_exit_status",
+ "Expected exit status of ocamlopt.byte")
+
+let ocaml_opt_exit_status = make ("ocaml_opt_exit_status",
+ "Expected exit status of ocaml.opt")
+
+let ocamlc_opt_exit_status = make ("ocamlc_opt_exit_status",
+ "Expected exit status of ocac.opt")
+
+let ocamlopt_opt_exit_status = make ("ocamlopt_opt_exit_status",
+ "Expected exit status of ocamlopt.opt")
+
+let output = make ("output",
+ "Where the output of executing the program is saved")
+
+let program = make ("program",
+ "Name of program produced by ocamlc.byte and ocamlopt.byte")
+let program2 = make ("program2",
+ "Name of program produced by ocamlc.opt and ocamlopt.opt")
+
+let reference = make ("reference",
+ "Path of file to which program output should be compared")
+
+let script = make ("script",
+ "External script to run")
+
+let stdin = make ("stdin", "Default standard input")
+let stdout = make ("stdout", "Default standard output")
+let stderr = make ("stderr", "Default standard error")
+
+let test_build_directory = make ("test_build_directory",
+ "Directory for files produced during a test")
+
+let test_file = make ("test_file",
+ "Name of file containing the specification of which tests to run")
+
+let test_source_directory = make ("test_source_directory",
+ "Directory containing the test source files")
+
+let _ = List.iter register_variable
+ [
+ c_preprocessor;
+ ocamlc_default_flags;
+ ocamlopt_default_flags
+ ]
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Definition of variables used by built-in actions *)
+
+(* The variables are listed in alphabetical order *)
+
+val arguments : Variables.t
+
+val c_preprocessor : Variables.t
+
+val compiler_directory_suffix : Variables.t
+
+val compiler_reference : Variables.t
+
+val compiler_reference2 : Variables.t
+
+val compiler_reference_suffix : Variables.t
+
+val compiler_output : Variables.t
+
+val compiler_output2 : Variables.t
+
+val files : Variables.t
+
+val flags : Variables.t
+
+val libraries : Variables.t
+
+val modules : Variables.t
+
+val ocamlc_flags : Variables.t
+val ocamlc_default_flags : Variables.t
+
+val ocamlopt_flags : Variables.t
+val ocamlopt_default_flags : Variables.t
+
+val ocaml_byte_exit_status : Variables.t
+
+val ocamlc_byte_exit_status : Variables.t
+
+val ocamlopt_byte_exit_status : Variables.t
+
+val ocaml_opt_exit_status : Variables.t
+
+val ocamlc_opt_exit_status : Variables.t
+
+val ocamlopt_opt_exit_status : Variables.t
+
+val output : Variables.t
+
+val program : Variables.t
+val program2 : Variables.t
+
+val reference : Variables.t
+
+val script : Variables.t
+
+val stdin : Variables.t
+val stdout : Variables.t
+val stderr : Variables.t
+
+val test_build_directory : Variables.t
+
+val test_file : Variables.t
+
+val test_source_directory : Variables.t
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Definition of environments, used to pass parameters to tests and actions *)
+
+exception Variable_already_defined of Variables.t
+
+module VariableMap = Map.Make (Variables)
+
+type t = string VariableMap.t
+
+let empty = VariableMap.empty
+
+let to_bindings env =
+ let f variable value lst = (variable, value) :: lst in
+ VariableMap.fold f env []
+
+let expand env value =
+
+ let bindings = to_bindings env in
+ let f (variable, value) = ((Variables.name_of_variable variable), value) in
+ let simple_bindings = List.map f bindings in
+ let subst s = try (List.assoc s simple_bindings) with Not_found -> "" in
+ let b = Buffer.create 100 in
+ try Buffer.add_substitute b subst value; Buffer.contents b with _ -> value
+
+let lookup variable env =
+ try Some (expand env (VariableMap.find variable env)) with Not_found -> None
+
+let safe_lookup variable env = match lookup variable env with
+ | None -> ""
+ | Some value -> value
+
+let is_variable_defined variable env =
+ VariableMap.mem variable env
+
+let add variable value env =
+ if VariableMap.mem variable env
+ then raise (Variable_already_defined variable)
+ else VariableMap.add variable value env
+
+let replace variable value environment =
+ VariableMap.add variable value environment
+
+let append variable appened_value environment =
+ let previous_value = safe_lookup variable environment in
+ let new_value = previous_value ^ appened_value in
+ VariableMap.add variable new_value environment
+
+let add_bindings bindings env =
+ let f env (variable, value) = add variable value env in
+ List.fold_left f env bindings
+
+let from_bindings bindings = add_bindings bindings empty
+
+let dump_assignment log (variable, value) =
+ Printf.fprintf log "%s = %s\n%!" (Variables.name_of_variable variable) value
+
+let dump log environment =
+ List.iter (dump_assignment log) (VariableMap.bindings environment);
+
+(* Environment modifiers *)
+
+type modifier =
+ | Include of string
+ | Add of Variables.t * string
+ | Replace of Variables.t * string
+ | Append of Variables.t * string
+
+type modifiers = modifier list
+
+exception Empty_modifiers_name
+exception Modifiers_name_already_registered of string
+exception Modifiers_name_not_found of string
+
+let (registered_modifiers : (string, modifiers) Hashtbl.t) = Hashtbl.create 20
+
+let register modifiers name =
+ if name="" then raise Empty_modifiers_name
+ else if Hashtbl.mem registered_modifiers name
+ then raise (Modifiers_name_already_registered name)
+ else Hashtbl.add registered_modifiers name modifiers
+
+let find_modifiers name =
+ try Hashtbl.find registered_modifiers name
+ with Not_found -> raise (Modifiers_name_not_found name)
+
+let rec apply_modifier environment = function
+ | Include modifiers_name ->
+ apply_modifiers environment (find_modifiers modifiers_name)
+ | Add (variable, value) -> add variable value environment
+ | Replace (variable, value) -> replace variable value environment
+ | Append (variable, value) -> append variable value environment
+and apply_modifiers environment modifiers =
+ List.fold_left apply_modifier environment modifiers
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Definition of environments, used to pass parameters to tests and actions *)
+
+exception Variable_already_defined of Variables.t
+
+type t
+
+val empty : t
+
+val from_bindings : (Variables.t * string) list -> t
+val to_bindings : t -> (Variables.t * string) list
+
+val lookup : Variables.t -> t -> string option
+val safe_lookup : Variables.t -> t -> string
+val is_variable_defined : Variables.t -> t -> bool
+
+val add : Variables.t -> string -> t -> t
+val add_bindings : (Variables.t * string) list -> t -> t
+
+val dump : out_channel -> t -> unit
+
+(* Environment modifiers *)
+
+type modifier =
+ | Include of string
+ | Add of Variables.t * string
+ | Replace of Variables.t * string
+ | Append of Variables.t * string
+
+type modifiers = modifier list
+
+val apply_modifier : t -> modifier -> t
+val apply_modifiers : t -> modifiers -> t
+
+exception Empty_modifiers_name
+exception Modifiers_name_already_registered of string
+exception Modifiers_name_not_found of string
+
+val register : modifiers -> string -> unit
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* File comparison tools *)
+
+type result =
+ | Same
+ | Different
+ | Unexpected_output
+ | Error of string * int
+
+type tool =
+ | External of {
+ tool_name : string;
+ tool_flags : string;
+ result_of_exitcode : string -> int -> result
+ }
+ | Internal of int
+
+let cmp_result_of_exitcode commandline = function
+ | 0 -> Same
+ | 1 -> Different
+ | exit_code -> (Error (commandline, exit_code))
+
+let make_cmp_tool bytes_to_ignore =
+ Internal bytes_to_ignore
+
+let make_comparison_tool ?(result_of_exitcode = cmp_result_of_exitcode)
+ name flags =
+ External
+ {
+ tool_name = name;
+ tool_flags = flags;
+ result_of_exitcode
+ }
+
+let default_comparison_tool = make_cmp_tool 0
+
+type filetype = Binary | Text
+
+type files = {
+ filetype : filetype;
+ reference_filename : string;
+ output_filename : string;
+}
+
+let read_text_file fn =
+ let ic = open_in_bin fn in
+ let drop_cr s =
+ let l = String.length s in
+ if l > 0 && s.[l - 1] = '\r' then String.sub s 0 (l - 1)
+ else raise Exit
+ in
+ let rec loop acc =
+ match input_line ic with
+ | s -> loop (s :: acc)
+ | exception End_of_file ->
+ close_in ic;
+ try List.rev_map drop_cr acc
+ with Exit -> List.rev acc
+ in
+ loop []
+
+let compare_text_files file1 file2 =
+ if read_text_file file1 = read_text_file file2 then
+ Same
+ else
+ Different
+
+(* Version of Pervasives.really_input which stops at EOF, rather than raising
+ an exception. *)
+let really_input_up_to ic =
+ let block_size = 8192 in
+ let buf = Bytes.create block_size in
+ let rec read pos =
+ let bytes_read = input ic buf pos (block_size - pos) in
+ let new_pos = pos + bytes_read in
+ if bytes_read = 0 || new_pos = block_size then
+ new_pos
+ else
+ read new_pos
+ in
+ let bytes_read = read 0 in
+ if bytes_read = block_size then
+ buf
+ else
+ Bytes.sub buf 0 bytes_read
+
+let compare_binary_files bytes_to_ignore file1 file2 =
+ let ic1 = open_in_bin file1 in
+ let ic2 = open_in_bin file2 in
+ seek_in ic1 bytes_to_ignore;
+ seek_in ic2 bytes_to_ignore;
+ let rec compare () =
+ let block1 = really_input_up_to ic1 in
+ let block2 = really_input_up_to ic2 in
+ if block1 = block2 then
+ if Bytes.length block1 > 0 then
+ compare ()
+ else
+ Same
+ else
+ Different
+ in
+ let result = compare () in
+ close_in ic1;
+ close_in ic2;
+ result
+
+let compare_files ?(tool = default_comparison_tool) files =
+ match tool with
+ | External {tool_name; tool_flags; result_of_exitcode} ->
+ let commandline = String.concat " "
+ [
+ tool_name;
+ tool_flags;
+ files.reference_filename;
+ files.output_filename
+ ] in
+ let dev_null = match Sys.os_type with
+ | "Win32" -> "NUL"
+ | _ -> "/dev/null" in
+ let settings = Run_command.settings_of_commandline
+ ~stdout_fname:dev_null ~stderr_fname:dev_null commandline in
+ let status = Run_command.run settings in
+ result_of_exitcode commandline status
+ | Internal bytes_to_ignore ->
+ match files.filetype with
+ | Text ->
+ (* bytes_to_ignore is silently ignored for text files *)
+ compare_text_files files.reference_filename files.output_filename
+ | Binary ->
+ compare_binary_files bytes_to_ignore
+ files.reference_filename files.output_filename
+
+let check_file ?(tool = default_comparison_tool) files =
+ if Sys.file_exists files.reference_filename
+ then compare_files ~tool:tool files
+ else begin
+ if Testlib.file_is_empty files.output_filename
+ then Same
+ else Unexpected_output
+ end
+
+let diff files =
+ let temporary_file = Filename.temp_file "ocamltest" "diff" in
+ let diff_commandline = String.concat " "
+ [
+ "diff -u";
+ files.reference_filename;
+ files.output_filename;
+ "> " ^ temporary_file
+ ] in
+ if (Sys.command diff_commandline) = 2 then Pervasives.Error "diff"
+ else Ok (Testlib.string_of_file temporary_file)
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* File comparison tools *)
+
+type result =
+ | Same
+ | Different
+ | Unexpected_output
+ | Error of string * int
+
+type tool
+
+val make_cmp_tool : int -> tool
+
+val make_comparison_tool :
+ ?result_of_exitcode:(string -> int -> result) -> string -> string -> tool
+
+val default_comparison_tool : tool
+
+type filetype = Binary | Text
+
+type files = {
+ filetype : filetype;
+ reference_filename : string;
+ output_filename : string;
+}
+
+val compare_files : ?tool:tool -> files -> result
+
+val check_file : ?tool:tool -> files -> result
+
+val cmp_result_of_exitcode : string -> int -> result
+
+val diff : files -> (string, string) Pervasives.result
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Types of input files involved in an OCaml project and related functions *)
+
+type t =
+ | Implementation
+ | Interface
+ | C
+ | C_minus_minus
+ | Lexer
+ | Grammar
+
+let string_of_filetype = function
+ | Implementation -> "implementation"
+ | Interface -> "interface"
+ | C -> "C source file"
+ | C_minus_minus -> "C minus minus source file"
+ | Lexer -> "lexer"
+ | Grammar -> "grammar"
+
+let extension_of_filetype = function
+ | Implementation -> "ml"
+ | Interface -> "mli"
+ | C -> "c"
+ | C_minus_minus -> "cmm"
+ | Lexer -> "mll"
+ | Grammar -> "mly"
+
+let filetype_of_extension = function
+ | "ml" -> Implementation
+ | "mli" -> Interface
+ | "c" -> C
+ | "cmm" -> C_minus_minus
+ | "mll" -> Lexer
+ | "mly" -> Grammar
+ | _ -> raise Not_found
+
+let split_filename name =
+ let l = String.length name in
+ let is_dir_sep name i = name.[i] = Filename.dir_sep.[0] in
+ let rec search_dot i =
+ if i < 0 || is_dir_sep name i then (name, "")
+ else if name.[i] = '.' then
+ let basename = String.sub name 0 i in
+ let extension = String.sub name (i+1) (l-i-1) in
+ (basename, extension)
+ else search_dot (i - 1) in
+ search_dot (l - 1)
+
+let filetype filename =
+ let (basename, extension) = split_filename filename in
+ (basename, filetype_of_extension extension)
+
+let make_filename (basename, filetype) =
+ let extension = extension_of_filetype filetype in
+ basename ^ "." ^ extension
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Types of input files involved in an OCaml project and related functions *)
+
+type t =
+ | Implementation
+ | Interface
+ | C
+ | C_minus_minus
+ | Lexer
+ | Grammar
+
+val string_of_filetype : t -> string
+
+val extension_of_filetype : t -> string
+
+val filetype_of_extension : string -> t
+
+val split_filename : string -> string * string
+
+val filetype : string -> string * t
+
+val make_filename : string * t -> string
--- /dev/null
+#!/bin/sh
+#**************************************************************************
+#* *
+#* OCaml *
+#* *
+#* Sebastien Hinderer, projet Gallium, INRIA Paris *
+#* *
+#* Copyright 2016 Institut National de Recherche en Informatique et *
+#* en Automatique. *
+#* *
+#* All rights reserved. This file is distributed under the terms of *
+#* the GNU Lesser General Public License version 2.1, with the *
+#* special exception on linking described in the file LICENSE. *
+#* *
+#**************************************************************************
+
+# This script provides command-line options to use by default
+# when invoking ocamlopt
+
+# It is used to add that disable annoying linker warnings on some versions
+# of OpenBSD
+
+case "$1" in
+ i386-*-openbsd5.[5-9]*|i386-*-openbsd[6-9].*)
+ echo "-ccopt -nopie";;
+esac
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Main program of the ocamltest test driver *)
+
+open Tsl_semantics
+
+(*
+let first_token filename =
+ let input_channel = open_in filename in
+ let lexbuf = Lexing.from_channel input_channel in
+ Location.init lexbuf filename;
+ let token =
+ try Tsl_lexer.token lexbuf with e -> close_in input_channel; raise e
+ in close_in input_channel; token
+
+let is_test filename =
+ match first_token filename with
+ | exception _ -> false
+ | Tsl_parser.TSL_BEGIN -> true
+ | _ -> false
+*)
+
+let tsl_block_of_file test_filename =
+ let input_channel = open_in test_filename in
+ let lexbuf = Lexing.from_channel input_channel in
+ Location.init lexbuf test_filename;
+ match Tsl_parser.tsl_block Tsl_lexer.token lexbuf with
+ | exception e -> close_in input_channel; raise e
+ | _ as tsl_block -> close_in input_channel; tsl_block
+
+let tsl_block_of_file_safe test_filename =
+ try tsl_block_of_file test_filename with
+ | Sys_error message ->
+ Printf.eprintf "%s\n" message;
+ exit 1
+ | Parsing.Parse_error ->
+ Printf.eprintf "Could not read test block in %s\n" test_filename;
+ exit 1
+
+let print_usage () =
+ Printf.printf "%s\n%!" Options.usage
+
+let rec run_test log common_prefix path ancestor_result = function
+ Node (testenvspec, test, env_modifiers, subtrees) ->
+ Printf.printf "%s %s (%s) => %!" common_prefix path test.Tests.test_name;
+ let print_test_result str = Printf.printf "%s\n%!" str in
+ let test_result = match ancestor_result with
+ | Actions.Pass env -> (* Ancestor succeded, really run the test *)
+ let testenv0 = interprete_environment_statements env testenvspec in
+ let testenv = List.fold_left apply_modifiers testenv0 env_modifiers in
+ Tests.run log testenv test
+ | Actions.Skip _ -> (Actions.Skip "ancestor test skipped")
+ | Actions.Fail _ -> (Actions.Skip "ancestor test failed") in
+ let result_to_pass = match test_result with
+ | Actions.Pass _ ->
+ print_test_result "passed";
+ test_result
+ | Actions.Fail _ ->
+ print_test_result "failed";
+ ancestor_result
+ | Actions.Skip _ ->
+ print_test_result "skipped";
+ ancestor_result in
+ List.iteri (run_test_i log common_prefix path result_to_pass) subtrees
+and run_test_i log common_prefix path ancestor_result i test_tree =
+ let path_prefix = if path="" then "" else path ^ "." in
+ let new_path = Printf.sprintf "%s%d" path_prefix (i+1) in
+ run_test log common_prefix new_path ancestor_result test_tree
+
+let get_test_source_directory test_dirname =
+ if not (Filename.is_relative test_dirname) then test_dirname
+ else let pwd = Sys.getcwd() in
+ Filename.concat pwd test_dirname
+
+let get_test_build_directory test_dirname =
+ let ocamltestdir_variable = "OCAMLTESTDIR" in
+ let root = try Sys.getenv ocamltestdir_variable with
+ | Not_found -> (Filename.concat (Sys.getcwd ()) "_ocamltest") in
+ if test_dirname = "." then root
+ else Filename.concat root test_dirname
+
+let main () =
+ if !Options.testfile = "" then begin
+ print_usage();
+ exit 1
+ end;
+ let test_filename = !Options.testfile in
+ (* Printf.printf "# reading test file %s\n%!" test_filename; *)
+ let tsl_block = tsl_block_of_file_safe test_filename in
+ let (rootenv_statements, test_trees) = test_trees_of_tsl_block tsl_block in
+ let test_trees = match test_trees with
+ | [] ->
+ let default_tests = Tests.default_tests() in
+ let make_tree test = Node ([], test, [], []) in
+ List.map make_tree default_tests
+ | _ -> test_trees in
+ let actions = actions_in_tests (tests_in_trees test_trees) in
+ let test_dirname = Filename.dirname test_filename in
+ let test_basename = Filename.basename test_filename in
+ let test_prefix = Filename.chop_extension test_basename in
+ let test_directory =
+ if test_dirname="." then test_prefix
+ else Filename.concat test_dirname test_prefix in
+ let test_source_directory = get_test_source_directory test_dirname in
+ let test_build_directory = get_test_build_directory test_directory in
+ let reference_filename = Filename.concat
+ test_source_directory (test_prefix ^ ".reference") in
+ let initial_environment = Environments.from_bindings
+ [
+ Builtin_variables.c_preprocessor, Ocamltest_config.c_preprocessor;
+ Builtin_variables.ocamlc_default_flags,
+ Ocamltest_config.ocamlc_default_flags;
+ Builtin_variables.ocamlopt_default_flags,
+ Ocamltest_config.ocamlopt_default_flags;
+ Builtin_variables.test_file, test_basename;
+ Builtin_variables.reference, reference_filename;
+ Builtin_variables.test_source_directory, test_source_directory;
+ Builtin_variables.test_build_directory, test_build_directory;
+ ] in
+ let root_environment =
+ interprete_environment_statements initial_environment rootenv_statements in
+ let rootenv = Actions.update_environment root_environment actions in
+ Testlib.make_directory test_build_directory;
+ Sys.chdir test_build_directory;
+ let log_filename = test_prefix ^ ".log" in
+ let log = open_out log_filename in
+ let common_prefix = " ... testing '" ^ test_basename ^ "' with" in
+ List.iteri
+ (run_test_i log common_prefix "" (Actions.Pass rootenv))
+ test_trees;
+ close_out log
+
+let _ = main()
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Interface for the main program of the test driver *)
+
+(* Nothing is exported. This file exists merely so that every
+ * .ml has a corresponding interface *)
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* The configuration module for ocamltest *)
+
+let arch = "@@ARCH@@"
+
+let c_preprocessor = "@@CPP@@"
+
+let ocamlsrcdir = "@@OCAMLSRCDIR@@"
+
+let flambda = @@FLAMBDA@@
+
+let ocamlc_default_flags = "@@OCAMLCDEFAULTFLAGS@@"
+let ocamlopt_default_flags = "@@OCAMLOPTDEFAULTFLAGS@@"
+
+let safe_string = @@FORCE_SAFE_STRING@@
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2017 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Interface for ocamltest's configuration module *)
+
+val arch : string
+(** Architecture for the native compiler, "none" if it is disabled *)
+
+val c_preprocessor : string
+(** Command to use to invoke the C preprocessor *)
+
+
+val ocamlc_default_flags : string
+(** Flags passed by default to ocamlc.byte and ocamlc.opt *)
+
+val ocamlopt_default_flags : string
+(** Flags passed by default to ocamlopt.byte and ocamlopt.opt *)
+
+val ocamlsrcdir : string
+(** The absolute path of the directory containing the sources of OCaml *)
+
+val flambda : bool
+(** Whether flambda has been enabled at configure time *)
+
+val safe_string : bool
+(** Whether the compiler was configured with -safe-string *)
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Description of ocamltest's command-line options *)
+
+let show_objects title string_of_object objects =
+ let print_object o = print_endline (" " ^ (string_of_object o)) in
+ print_endline title;
+ List.iter print_object objects;
+ exit 0
+
+let string_of_action action = action.Actions.action_name
+
+let string_of_test test =
+ if test.Tests.test_run_by_default
+ then (test.Tests.test_name ^ " (run by default)")
+ else test.Tests.test_name
+
+let show_actions () =
+ let actions = Actions.get_registered_actions () in
+ show_objects "Available actions are:" string_of_action actions
+
+let show_tests () =
+ let tests = Tests.get_registered_tests () in
+ show_objects "Available tests are:" string_of_test tests
+
+let commandline_options =
+[
+ ("-show-actions", Arg.Unit show_actions, "Show available actions.");
+ ("-show-tests", Arg.Unit show_tests, "Show available tests.");
+]
+
+let testfile = ref ""
+
+let set_testfile name =
+ if !testfile<> "" then
+ begin
+ Printf.eprintf "Can't deal with more than one test file at the moment\n%!";
+ exit 1
+ end else testfile := name
+
+let usage = "Usage: " ^ Sys.argv.(0) ^ " options testfile"
+
+let _ =
+ Arg.parse commandline_options set_testfile usage
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Description of ocamltest's command-line options *)
+
+val testfile : string ref
+
+val usage : string
--- /dev/null
+/**************************************************************************/
+/* */
+/* OCaml */
+/* */
+/* Sebastien Hinderer, projet Gallium, INRIA Paris */
+/* */
+/* Copyright 2016 Institut National de Recherche en Informatique et */
+/* en Automatique. */
+/* */
+/* All rights reserved. This file is distributed under the terms of */
+/* the GNU Lesser General Public License version 2.1, with the */
+/* special exception on linking described in the file LICENSE. */
+/* */
+/**************************************************************************/
+
+/* Header file for the run library */
+
+#ifndef __RUN_H__
+
+#define __RUN_H__
+
+#include <stdarg.h>
+#include <caml/misc.h>
+
+typedef char_os **array;
+
+typedef void Logger(void *, const char *, va_list ap);
+
+typedef struct {
+ char_os *program;
+ array argv;
+ /* array envp; */
+ char_os *stdin_filename;
+ char_os *stdout_filename;
+ char_os *stderr_filename;
+ int append;
+ int timeout;
+ Logger *logger;
+ void *loggerData;
+} command_settings;
+
+extern int run_command(const command_settings *settings);
+
+#endif /* __RUN_H__ */
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Run programs and log their stdout/stderr, with a timer... *)
+
+type settings = {
+ progname : string;
+ argv : string array;
+ (* envp : string array; *)
+ stdin_filename : string;
+ stdout_filename : string;
+ stderr_filename : string;
+ append : bool;
+ timeout : int;
+ log : out_channel;
+}
+
+let settings_of_commandline ?(stdout_fname="") ?(stderr_fname="") commandline =
+ let words = Testlib.words commandline in
+ let quoted_words =
+ if Sys.os_type="Win32"
+ then List.map Testlib.maybe_quote words
+ else words in
+ {
+ progname = List.hd quoted_words;
+ argv = Array.of_list quoted_words;
+ stdin_filename = "";
+ stdout_filename = stdout_fname;
+ stderr_filename = stderr_fname;
+ append = false;
+ timeout = 0;
+ log = stderr
+ }
+
+external run : settings -> int = "caml_run_command"
+
+let run_commandline commandline = run (settings_of_commandline commandline)
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Run programs and log their stdout/stderr, with a timer... *)
+
+type settings = {
+ progname : string;
+ argv : string array;
+ (* envp : string array; *)
+ stdin_filename : string;
+ stdout_filename : string;
+ stderr_filename : string;
+ append : bool;
+ timeout : int;
+ log : out_channel;
+}
+
+val settings_of_commandline :
+ ?stdout_fname:string ->
+ ?stderr_fname:string ->
+ string -> settings
+
+val run : settings -> int
+
+val run_commandline : string -> int
--- /dev/null
+/**************************************************************************/
+/* */
+/* OCaml */
+/* */
+/* Sebastien Hinderer, projet Gallium, INRIA Paris */
+/* */
+/* Copyright 2016 Institut National de Recherche en Informatique et */
+/* en Automatique. */
+/* */
+/* All rights reserved. This file is distributed under the terms of */
+/* the GNU Lesser General Public License version 2.1, with the */
+/* special exception on linking described in the file LICENSE. */
+/* */
+/**************************************************************************/
+
+/* Private definitions shared by both Unix and Windows process runners */
+
+#ifndef __RUN_COMMON_H__
+#define __RUN_COMMON_H__
+
+/* is_defined(str) returns 1 iff str points to a non-empty string */
+/* Otherwise returns 0 */
+static int is_defined(const char_os *str)
+{
+ return (str != NULL) && (*str != 0);
+}
+
+static void defaultLogger(void *where, const char *format, va_list ap)
+{
+ vfprintf(stderr, format, ap);
+}
+
+static void mylog(Logger *logger, void *loggerData, char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ logger(loggerData, fmt, ap);
+ va_end(ap);
+}
+
+static void error_with_location(
+ const char *file, int line,
+ const command_settings *settings,
+ const char *msg, ...)
+{
+ va_list ap;
+ Logger *logger = (settings->logger != NULL) ? settings->logger
+ : defaultLogger;
+ void *loggerData = settings->loggerData;
+ va_start(ap, msg);
+ mylog(logger, loggerData, "%s:%d: ", file, line);
+ logger(loggerData, msg, ap);
+ mylog(logger, loggerData, "\n");
+ va_end(ap);
+}
+
+
+
+#endif /* __RUN_COMMON_H__ */
--- /dev/null
+/**************************************************************************/
+/* */
+/* OCaml */
+/* */
+/* Sebastien Hinderer, projet Gallium, INRIA Paris */
+/* */
+/* Copyright 2016 Institut National de Recherche en Informatique et */
+/* en Automatique. */
+/* */
+/* All rights reserved. This file is distributed under the terms of */
+/* the GNU Lesser General Public License version 2.1, with the */
+/* special exception on linking described in the file LICENSE. */
+/* */
+/**************************************************************************/
+
+/* Stubs to let OCaml programs use the run library */
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <string.h>
+
+#include "run.h"
+
+#include "caml/mlvalues.h"
+#include "caml/memory.h"
+#include "caml/io.h"
+#include "caml/osdeps.h"
+
+/* cstringvect: inspired by similar function in otherlibs/unix/cstringv.c */
+static array cstringvect(value arg)
+{
+ array res;
+ mlsize_t size, i;
+
+ size = Wosize_val(arg);
+ res = (array) caml_stat_alloc((size + 1) * sizeof(char_os *));
+ for (i = 0; i < size; i++)
+ res[i] = caml_stat_strdup_to_os(String_val(Field(arg, i)));
+ res[size] = NULL;
+ return res;
+}
+
+static void free_cstringvect(array v)
+{
+ char_os **p;
+ for (p = v; *p != NULL; p++)
+ caml_stat_free(*p);
+ caml_stat_free(v);
+}
+
+static void logToChannel(void *voidchannel, const char *fmt, va_list ap)
+{
+ struct channel *channel = (struct channel *) voidchannel;
+ int length, initialTextLength = 512;
+ char *text = malloc(512);
+ if (text == NULL) return;
+ length = vsnprintf(text, initialTextLength, fmt, ap);
+ if (length <= 0)
+ {
+ free(text);
+ return;
+ }
+ if (length > initialTextLength)
+ {
+ free(text);
+ text = malloc(length);
+ if (text == NULL) return;
+ if (vsnprintf(text, length, fmt, ap) != length) goto end;
+ }
+ caml_putblock(channel, text, length);
+ caml_flush(channel);
+end:
+ free(text);
+}
+
+CAMLprim value caml_run_command(value caml_settings)
+{
+ int res;
+ command_settings settings;
+
+ CAMLparam1(caml_settings);
+ settings.program = caml_stat_strdup_to_os(String_val(Field(caml_settings, 0)));
+ settings.argv = cstringvect(Field(caml_settings, 1));
+ /* settings.envp = cstringvect(Field(caml_settings, 2)); */
+ settings.stdin_filename = caml_stat_strdup_to_os(String_val(Field(caml_settings, 2)));
+ settings.stdout_filename = caml_stat_strdup_to_os(String_val(Field(caml_settings, 4)));
+ settings.stderr_filename = caml_stat_strdup_to_os(String_val(Field(caml_settings, 4)));
+ settings.append = Bool_val(Field(caml_settings, 5));
+ settings.timeout = Int_val(Field(caml_settings, 6));
+ settings.logger = logToChannel;
+ settings.loggerData = Channel(Field(caml_settings, 7));
+ res = run_command(&settings);
+ caml_stat_free(settings.program);
+ free_cstringvect(settings.argv);
+ caml_stat_free(settings.stdin_filename);
+ caml_stat_free(settings.stdout_filename);
+ caml_stat_free(settings.stderr_filename);
+ CAMLreturn(Val_int(res));
+}
--- /dev/null
+/**************************************************************************/
+/* */
+/* OCaml */
+/* */
+/* Sebastien Hinderer, projet Gallium, INRIA Paris */
+/* */
+/* Copyright 2016 Institut National de Recherche en Informatique et */
+/* en Automatique. */
+/* */
+/* All rights reserved. This file is distributed under the terms of */
+/* the GNU Lesser General Public License version 2.1, with the */
+/* special exception on linking described in the file LICENSE. */
+/* */
+/**************************************************************************/
+
+/* Run programs with rediretions and timeouts under Unix */
+
+#include <stdio.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <signal.h>
+
+#include "run.h"
+#include "run_common.h"
+
+#define COREFILENAME "core"
+
+static volatile int timeout_expired = 0;
+
+#define error(msg, ...) \
+error_with_location(__FILE__, __LINE__, settings, msg, ## __VA_ARGS__)
+
+/*
+ Note: the ## __VA_ARGS__ construct is gcc specific.
+ For a more portable (but also more complex) solution, see
+ http://stackoverflow.com/questions/20818800/variadic-macro-and-trailing-comma
+*/
+
+static void myperror_with_location(
+ const char *file, int line,
+ const command_settings *settings,
+ const char *msg, ...)
+{
+ va_list ap;
+ Logger *logger = (settings->logger != NULL) ? settings->logger
+ : defaultLogger;
+ void *loggerData = settings->loggerData;
+ va_start(ap, msg);
+ mylog(logger, loggerData, "%s:%d: ", file, line);
+ logger(loggerData, msg, ap);
+ mylog(logger, loggerData, ": %s\n", strerror(errno));
+ va_end(ap);
+}
+
+#define myperror(msg, ...) \
+myperror_with_location(__FILE__, __LINE__, settings, msg, ## __VA_ARGS__)
+
+/* Same remark as for the error macro. */
+
+static void open_error_with_location(
+ const char *file, int line,
+ const command_settings *settings,
+ const char *msg)
+{
+ myperror_with_location(file, line, settings, "Can not open %s", msg);
+}
+
+#define open_error(filename) \
+open_error_with_location(__FILE__, __LINE__, settings, filename)
+
+static void realpath_error_with_location(
+ const char *file, int line,
+ const command_settings *settings,
+ const char *msg)
+{
+ myperror_with_location(file, line, settings, "realpath(\"%s\") failed", msg);
+}
+
+#define realpath_error(filename) \
+realpath_error_with_location(__FILE__, __LINE__, settings, filename)
+
+static void handle_alarm(int sig)
+{
+ timeout_expired = 1;
+}
+
+static int paths_same_file(
+ const command_settings *settings, const char * path1, const char * path2)
+{
+ int same_file = 0;
+#ifdef __GLIBC__
+ char *realpath1, *realpath2;
+ realpath1 = realpath(path1, NULL);
+ if (realpath1 == NULL)
+ realpath_error(path1);
+ realpath2 = realpath(path2, NULL);
+ if ( (realpath2 == NULL) && (errno != ENOENT) )
+ {
+ free(realpath1);
+ realpath_error(path2);
+ }
+#else
+ char realpath1[PATH_MAX], realpath2[PATH_MAX];
+ if (realpath(path1, realpath1) == NULL)
+ realpath_error(path1);
+ if ((realpath(path2, realpath2) == NULL) && (errno != ENOENT))
+ realpath_error(path2);
+#endif /* __GLIBC__ */
+ if (strcmp(realpath1, realpath2) == 0)
+ same_file = 1;
+#ifdef __GLIBC__
+ free(realpath1);
+ free(realpath2);
+#endif /* __GLIBC__ */
+ return same_file;
+}
+
+static int run_command_child(const command_settings *settings)
+{
+ int res;
+ int stdin_fd = -1, stdout_fd = -1, stderr_fd = -1; /* -1 = no redir */
+ int inputFlags = O_RDONLY;
+ int outputFlags =
+ O_CREAT | O_WRONLY | (settings->append ? O_APPEND : O_TRUNC);
+ int inputMode = 0400, outputMode = 0666;
+
+ if (setpgid(0, 0) == -1) myperror("setpgid");
+
+ if (is_defined(settings->stdin_filename))
+ {
+ stdin_fd = open(settings->stdin_filename, inputFlags, inputMode);
+ if (stdin_fd < 0)
+ open_error(settings->stdin_filename);
+ if ( dup2(stdin_fd, STDIN_FILENO) == -1 )
+ myperror("dup2 for stdin");
+ }
+
+ if (is_defined(settings->stdout_filename))
+ {
+ stdout_fd = open(settings->stdout_filename, outputFlags, outputMode);
+ if (stdout_fd < 0)
+ open_error(settings->stdout_filename);
+ if ( dup2(stdout_fd, STDOUT_FILENO) == -1 )
+ myperror("dup2 for stdout");
+ }
+
+ if (is_defined(settings->stderr_filename))
+ {
+ if (stdout_fd != -1)
+ {
+ if (paths_same_file(
+ settings, settings->stdout_filename,settings->stderr_filename))
+ stderr_fd = stdout_fd;
+ }
+ if (stderr_fd == -1)
+ {
+ stderr_fd = open(settings->stderr_filename, outputFlags, outputMode);
+ if (stderr_fd == -1) open_error(settings->stderr_filename);
+ }
+ if ( dup2(stderr_fd, STDERR_FILENO) == -1 )
+ myperror("dup2 for stderr");
+ }
+
+ res = execvp(settings->program, settings->argv); /* , settings->envp); */
+
+ myperror("Cannot execute %s", settings->program);
+ return res;
+}
+
+/* Handles the termination of a process. Arguments:
+ * The pid of the terminated process
+ * Its termination status as returned by wait(2)
+ * A string giving a prefix for the core file name.
+ (the file will be called prefix.pid.core but may come from a
+ diffferent process)
+ * Returns the code to return if this is the child process
+ */
+static int handle_process_termination(
+ const command_settings *settings,
+ pid_t pid, int status, const char *corefilename_prefix)
+{
+ int signal, core = 0;
+ char *corestr;
+
+ if (WIFEXITED(status)) return WEXITSTATUS(status);
+
+ if ( !WIFSIGNALED(status) )
+ error("Process %d neither terminated normally nor received a" \
+ "signal!?", pid);
+
+ /* From here we know that the process terminated due to a signal */
+ signal = WTERMSIG(status);
+#ifdef WCOREDUMP
+ core = WCOREDUMP(status);
+#endif /* WCOREDUMP */
+ corestr = core ? "" : "no ";
+ fprintf(stderr,
+ "Process %d got signal %d(%s), %score dumped\n",
+ pid, signal, strsignal(signal), corestr
+ );
+
+ if (core)
+ {
+ if ( access(COREFILENAME, F_OK) == -1)
+ fprintf(stderr, "Could not find core file.\n");
+ else {
+ char corefile[strlen(corefilename_prefix) + 128];
+ snprintf(corefile, sizeof(corefile),
+ "%s.%d.core", corefilename_prefix, pid);
+ if ( rename(COREFILENAME, corefile) == -1)
+ fprintf(stderr, "The core file exists but could not be renamed.\n");
+ else
+ fprintf(stderr,"The core file has been renamed to %s\n", corefile);
+ }
+ }
+
+ return -signal;
+}
+
+static int run_command_parent(const command_settings *settings, pid_t child_pid)
+{
+ int waiting = 1, status, code, child_code = 0;
+ pid_t pid;
+
+ if (settings->timeout>0)
+ {
+ struct sigaction action;
+ action.sa_handler = handle_alarm;
+ sigemptyset(&action.sa_mask);
+ action.sa_flags = SA_RESETHAND;
+ if (sigaction(SIGALRM, &action, NULL) == -1) myperror("sigaction");
+ if (alarm(settings->timeout) == -1) myperror("alarm");
+ }
+
+ while (waiting)
+ {
+ pid = wait(&status);
+ if (pid == -1)
+ {
+ switch (errno)
+ {
+ case EINTR:
+ if ((settings->timeout > 0) && (timeout_expired))
+ {
+ timeout_expired = 0;
+ fprintf(stderr, "Timeout expired, killing all child processes");
+ if (kill(-child_pid, SIGKILL) == -1) myperror("kill");
+ };
+ break;
+ case ECHILD:
+ waiting = 0;
+ break;
+ default:
+ myperror("wait");
+ }
+ } else { /* Got a pid */
+ code = handle_process_termination(
+ settings, pid, status, settings->program);
+ if (pid == child_pid) child_code = code;
+ }
+ }
+
+ return child_code;
+}
+
+int run_command(const command_settings *settings)
+{
+ pid_t child_pid = fork();
+ if (child_pid == -1) myperror("fork");
+ if (child_pid == 0) return run_command_child(settings);
+ else return run_command_parent(settings, child_pid);
+}
--- /dev/null
+/**************************************************************************/
+/* */
+/* OCaml */
+/* */
+/* Sebastien Hinderer, projet Gallium, INRIA Paris */
+/* */
+/* Copyright 2016 Institut National de Recherche en Informatique et */
+/* en Automatique. */
+/* */
+/* All rights reserved. This file is distributed under the terms of */
+/* the GNU Lesser General Public License version 2.1, with the */
+/* special exception on linking described in the file LICENSE. */
+/* */
+/**************************************************************************/
+
+/* Run programs with rediretions and timeouts under Windows */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <wtypes.h>
+#include <winbase.h>
+#include <windows.h>
+#include <process.h>
+#include <string.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <sys/types.h>
+
+#include "caml/osdeps.h"
+
+#include "run.h"
+#include "run_common.h"
+
+static void report_error(
+ const char *file, int line,
+ const command_settings *settings,
+ const char *message, const WCHAR *argument)
+{
+ WCHAR error_message[1024];
+ DWORD error = GetLastError();
+ char *error_message_c;
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0,
+ error_message, sizeof(error_message)/sizeof(WCHAR), NULL);
+ error_message_c = caml_stat_strdup_of_utf16(error_message);
+ if ( is_defined(argument) )
+ error_with_location(file, line,
+ settings, "%s %s: %s", message, argument, error_message_c);
+ else
+ error_with_location(file, line,
+ settings, "%s: %s", message, error_message_c);
+ caml_stat_free(error_message_c);
+}
+
+static WCHAR *find_program(const WCHAR *program_name)
+{
+ int max_path_length = 512;
+ DWORD result;
+ LPCWSTR searchpath = NULL, extension = L".exe";
+ WCHAR **filepart = NULL;
+ WCHAR *fullpath = malloc(max_path_length*sizeof(WCHAR));
+ if (fullpath == NULL) return NULL;
+
+ result = SearchPath
+ (
+ searchpath,
+ program_name,
+ extension,
+ max_path_length,
+ fullpath,
+ filepart
+ );
+ if (result == 0)
+ {
+ /* It may be an absolute path, return a copy of it */
+ int l = wcslen(program_name) + 1;
+ free(fullpath);
+ fullpath = malloc(l*sizeof(WCHAR));
+ if (fullpath != NULL) wcscpy(fullpath, program_name);
+ return fullpath;
+ }
+ if (result <= max_path_length) return fullpath;
+
+ /* fullpath was too small, allocate a bigger one */
+ free(fullpath);
+
+ result++; /* Take '\0' into account */
+
+ fullpath = malloc(result*sizeof(WCHAR));
+ if (fullpath == NULL) return NULL;
+ SearchPath
+ (
+ searchpath,
+ program_name,
+ extension,
+ result,
+ fullpath,
+ filepart
+ );
+ return fullpath;
+}
+
+static WCHAR *commandline_of_arguments(WCHAR **arguments)
+{
+ WCHAR *commandline = NULL, **arguments_p, *commandline_p;
+ int args = 0; /* Number of arguments */
+ int commandline_length = 0;
+
+ if (*arguments == NULL) return NULL;
+ /* From here we know there is at least one argument */
+
+ /* First compute number of arguments and commandline length */
+ for (arguments_p = arguments; *arguments_p != NULL; arguments_p++)
+ {
+ args++;
+ commandline_length += wcslen(*arguments_p);
+ }
+ commandline_length += args; /* args-1 ' ' between arguments + final '\0' */
+
+ /* Allocate memory and accumulate arguments separated by spaces */
+ commandline = malloc(commandline_length*sizeof(WCHAR));
+ if (commandline == NULL) return NULL;
+ commandline_p = commandline;
+ for (arguments_p = arguments; *arguments_p!=NULL; arguments_p++)
+ {
+ int l = wcslen(*arguments_p);
+ memcpy(commandline_p, *arguments_p, l*sizeof(WCHAR));
+ commandline_p += l;
+ *commandline_p = L' ';
+ commandline_p++;
+ }
+ commandline[commandline_length-1] = 0;
+ return commandline;
+}
+
+static SECURITY_ATTRIBUTES security_attributes = {
+ sizeof(SECURITY_ATTRIBUTES), /* nLength */
+ NULL, /* lpSecurityDescriptor */
+ TRUE /* bInheritHandle */
+};
+
+static HANDLE create_input_handle(const WCHAR *filename)
+{
+ return CreateFile
+ (
+ filename,
+ GENERIC_READ, /* DWORD desired_access */
+ FILE_SHARE_READ, /* DWORD share_mode */
+ &security_attributes,
+ OPEN_EXISTING, /* DWORD creation_disposition */
+ FILE_ATTRIBUTE_NORMAL, /* DWORD flags_and_attributes */
+ NULL /* HANDLE template_file */
+ );
+}
+
+static HANDLE create_output_handle(const WCHAR *filename, int append)
+{
+ DWORD desired_access = append ? FILE_APPEND_DATA : GENERIC_WRITE;
+ DWORD share_mode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
+ DWORD creation_disposition = append ? OPEN_ALWAYS : CREATE_ALWAYS;
+ return CreateFile
+ (
+ filename,
+ desired_access,
+ share_mode,
+ &security_attributes,
+ creation_disposition,
+ FILE_ATTRIBUTE_NORMAL, /* DWORD flags_and_attributes */
+ NULL /* HANDLE template_file */
+ );
+}
+
+#define checkerr(condition, message, argument) \
+if ( (condition) ) \
+{ \
+ report_error(__FILE__, __LINE__, settings, message, argument); \
+ status = -1; \
+ goto cleanup; \
+} else { }
+
+int run_command(const command_settings *settings)
+{
+ BOOL process_created = FALSE;
+ int stdin_redirected = 0, stdout_redirected = 0, stderr_redirected = 0;
+ int combined = 0; /* 1 if stdout and stderr are redirected to the same file */
+ int wait_again = 0;
+ WCHAR *program = NULL;
+ WCHAR *commandline = NULL;
+
+ LPVOID environment = NULL;
+ LPCWSTR current_directory = NULL;
+ STARTUPINFO startup_info;
+ PROCESS_INFORMATION process_info;
+ DWORD wait_result, status;
+ DWORD timeout = (settings->timeout > 0) ? settings->timeout * 1000 : INFINITE;
+
+ ZeroMemory(&startup_info, sizeof(STARTUPINFO));
+ startup_info.cb = sizeof(STARTUPINFO);
+ startup_info.dwFlags = STARTF_USESTDHANDLES;
+
+ program = find_program(settings->program);
+ checkerr(
+ (program == NULL),
+ "Could not find program to execute",
+ settings->program
+ );
+
+ commandline = commandline_of_arguments(settings->argv);
+
+ if (is_defined(settings->stdin_filename))
+ {
+ startup_info.hStdInput = create_input_handle(settings->stdin_filename);
+ checkerr( (startup_info.hStdInput == INVALID_HANDLE_VALUE),
+ "Could not redirect standard input",
+ settings->stdin_filename);
+ stdin_redirected = 1;
+ } else startup_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
+
+ if (is_defined(settings->stdout_filename))
+ {
+ startup_info.hStdOutput = create_output_handle(
+ settings->stdout_filename, settings->append
+ );
+ checkerr( (startup_info.hStdOutput == INVALID_HANDLE_VALUE),
+ "Could not redirect standard output",
+ settings->stdout_filename);
+ stdout_redirected = 1;
+ } else startup_info.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
+
+ if (is_defined(settings->stderr_filename))
+ {
+ if (stdout_redirected)
+ {
+ if (wcscmp(settings->stdout_filename, settings->stderr_filename) == 0)
+ {
+ startup_info.hStdError = startup_info.hStdOutput;
+ stderr_redirected = 1;
+ combined = 1;
+ }
+ }
+
+ if (! stderr_redirected)
+ {
+ startup_info.hStdError = create_output_handle
+ (
+ settings->stderr_filename, settings->append
+ );
+ checkerr( (startup_info.hStdError == INVALID_HANDLE_VALUE),
+ "Could not redirect standard error",
+ settings->stderr_filename);
+ stderr_redirected = 1;
+ }
+ } else startup_info.hStdError = GetStdHandle(STD_ERROR_HANDLE);
+
+ process_created = CreateProcess(
+ program,
+ commandline,
+ NULL, /* SECURITY_ATTRIBUTES process_attributes */
+ NULL, /* SECURITY_ATTRIBUTES thread_attributes */
+ TRUE, /* BOOL inherit_handles */
+ CREATE_UNICODE_ENVIRONMENT, /* DWORD creation_flags */
+ NULL, /* LPVOID environment */
+ NULL, /* LPCSTR current_directory */
+ &startup_info,
+ &process_info
+ );
+ checkerr( (! process_created), "CreateProcess failed", NULL);
+
+ CloseHandle(process_info.hThread); /* Not needed so closed ASAP */
+
+ wait_result = WaitForSingleObject(process_info.hProcess, timeout);
+ if (wait_result == WAIT_OBJECT_0)
+ {
+ /* The child has terminated before the timeout has expired */
+ checkerr( (! GetExitCodeProcess(process_info.hProcess, &status)),
+ "GetExitCodeProcess failed", NULL);
+ } else if (wait_result == WAIT_TIMEOUT) {
+ /* The timeout has expired, terminate the process */
+ checkerr( (! TerminateProcess(process_info.hProcess, 0)),
+ "TerminateProcess failed", NULL);
+ status = -1;
+ wait_again = 1;
+ } else {
+ error_with_location(__FILE__, __LINE__, settings,
+ "WaitForSingleObject failed\n");
+ report_error(__FILE__, __LINE__,
+ settings, "Failure while waiting for process termination", NULL);
+ status = -1;
+ }
+
+cleanup:
+ free(program);
+ free(commandline);
+ if (stdin_redirected) CloseHandle(startup_info.hStdInput);
+ if (stdout_redirected) CloseHandle(startup_info.hStdOutput);
+ if (stderr_redirected && !combined) CloseHandle(startup_info.hStdError);
+ if (wait_again)
+ {
+ /* Wait again but this time just 1sec to avoid being blocked */
+ WaitForSingleObject(process_info.hProcess, 1000);
+ }
+ if (process_created) CloseHandle(process_info.hProcess);
+ return status;
+}
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Miscellaneous library functions *)
+
+let rec concatmap f = function
+ | [] -> []
+ | x::xs -> (f x) @ (concatmap f xs)
+
+let is_blank c =
+ c = ' ' || c = '\012' || c = '\n' || c = '\r' || c = '\t'
+
+let string_of_char = String.make 1
+
+(* This function comes from otherlibs/win32unix/unix.ml *)
+let maybe_quote f =
+ if String.contains f ' ' ||
+ String.contains f '\"' ||
+ String.contains f '\t' ||
+ f = ""
+ then Filename.quote f
+ else f
+
+let words s =
+ let l = String.length s in
+ let rec f quote w ws i =
+ if i>=l then begin
+ if w<>"" then List.rev (w::ws)
+ else List.rev ws
+ end else begin
+ let j = i+1 in
+ match s.[i] with
+ | '\'' -> f (not quote) w ws j
+ | ' ' ->
+ begin
+ if quote
+ then f true (w ^ (string_of_char ' ')) ws j
+ else begin
+ if w=""
+ then f false w ws j
+ else f false "" (w::ws) j
+ end
+ end
+ | _ as c -> f quote (w ^ (string_of_char c)) ws j
+ end in
+ if l=0 then [] else f false "" [] 0
+
+let file_is_empty filename =
+ let ic = open_in filename in
+ let filesize = in_channel_length ic in
+ close_in ic;
+ filesize = 0
+
+let string_of_location loc =
+ let buf = Buffer.create 64 in
+ let fmt = Format.formatter_of_buffer buf in
+ Location.print_loc fmt loc;
+ Format.pp_print_flush fmt ();
+ Buffer.contents buf
+
+let run_system_command command = match Sys.command command with
+ | 0 -> ()
+ | _ as exitcode ->
+ Printf.eprintf "Sysem command %s failed with status %d\n%!"
+ command exitcode;
+ exit 3
+
+let mkdir dir =
+ if not (Sys.file_exists dir) then
+ let quoted_dir = "\"" ^ dir ^ "\"" in
+ run_system_command ("mkdir " ^ quoted_dir)
+
+let rec make_directory dir =
+ if Sys.file_exists dir then ()
+ else (make_directory (Filename.dirname dir); mkdir dir)
+
+let string_of_file filename =
+ let chan = open_in_bin filename in
+ let filesize = in_channel_length chan in
+ if filesize > Sys.max_string_length then
+ begin
+ close_in chan;
+ failwith
+ ("The file " ^ filename ^ " is too large to be loaded into a string")
+ end else begin
+ let result =
+ try really_input_string chan filesize
+ with End_of_file ->
+ close_in chan;
+ failwith ("Got unexpected end of file while reading " ^ filename) in
+ close_in chan;
+ result
+ end
+
+let with_input_file ?(bin=false) x f =
+ let ic = (if bin then open_in_bin else open_in) x in
+ try let res = f ic in close_in ic; res with e -> (close_in ic; raise e)
+
+let with_output_file ?(bin=false) x f =
+ let oc = (if bin then open_out_bin else open_out) x in
+ try let res = f oc in close_out oc; res with e -> (close_out oc; raise e)
+
+
+let copy_chan ic oc =
+ let m = in_channel_length ic in
+ let m = (m lsr 12) lsl 12 in
+ let m = max 16384 (min Sys.max_string_length m) in
+ let buf = Bytes.create m in
+ let rec loop () =
+ let len = input ic buf 0 m in
+ if len > 0 then begin
+ output oc buf 0 len;
+ loop ()
+ end
+ in loop ()
+
+let copy_file src dest =
+ with_input_file ~bin:true src begin fun ic ->
+ with_output_file ~bin:true dest begin fun oc ->
+ copy_chan ic oc
+ end
+ end
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Miscellaneous library functions *)
+
+val concatmap : ('a -> 'b list) -> 'a list -> 'b list
+
+val is_blank : char -> bool
+
+val maybe_quote : string -> string
+
+val words : string -> string list
+
+val file_is_empty : string -> bool
+
+val string_of_location: Location.t -> string
+
+val run_system_command : string -> unit
+
+val make_directory : string -> unit
+
+val string_of_file : string -> string
+
+val copy_file : string -> string -> unit
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Definition of tests, built from actions *)
+
+type t = {
+ test_name : string;
+ test_run_by_default : bool;
+ test_actions : Actions.t list
+}
+
+let compare t1 t2 = String.compare t1.test_name t2.test_name
+
+let (tests: (string, t) Hashtbl.t) = Hashtbl.create 20
+
+let register test = Hashtbl.add tests test.test_name test
+
+let get_registered_tests () =
+ let f _test_name test acc = test::acc in
+ let unsorted_tests = Hashtbl.fold f tests [] in
+ List.sort compare unsorted_tests
+
+let default_tests () =
+ let f _test_name test acc =
+ if test.test_run_by_default then test::acc else acc in
+ Hashtbl.fold f tests []
+
+let lookup name =
+ try Some (Hashtbl.find tests name)
+ with Not_found -> None
+
+let test_of_action action =
+{
+ test_name = action.Actions.action_name;
+ test_run_by_default = false;
+ test_actions = [action]
+}
+
+let run_actions log testenv actions =
+ let total = List.length actions in
+ let rec run_actions_aux action_number env = function
+ | [] -> Actions.Pass env
+ | action::remaining_actions ->
+ begin
+ Printf.fprintf log "Running action %d/%d (%s)\n%!"
+ action_number total action.Actions.action_name;
+ let result = Actions.run log env action in
+ let report = match result with
+ | Actions.Pass _ -> "succeded."
+ | Actions.Fail reason ->
+ ("failed for the following reason:\n" ^ reason)
+ | Actions.Skip reason ->
+ ("has been skipped for the following reason:\n" ^ reason) in
+ Printf.fprintf log "Action %d/%d (%s) %s\n%!"
+ action_number total action.Actions.action_name
+ report;
+ match result with
+ | Actions.Pass env' ->
+ run_actions_aux (action_number+1) env' remaining_actions
+ | _ -> result
+ end in
+ run_actions_aux 1 testenv actions
+
+let run log env test =
+ Printf.fprintf log "Running test %s with %d actions\n%!"
+ test.test_name
+ (List.length test.test_actions);
+ run_actions log env test.test_actions
+
+module TestSet = Set.Make
+(struct
+ type nonrec t = t
+ let compare = compare
+end)
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Definition of tests, built from actions *)
+
+type t = {
+ test_name : string;
+ test_run_by_default : bool;
+ test_actions : Actions.t list
+}
+
+val compare : t -> t -> int
+
+val register : t -> unit
+
+val get_registered_tests : unit -> t list
+
+val default_tests : unit -> t list
+
+val lookup : string -> t option
+
+val run : out_channel -> Environments.t -> t -> Actions.result
+
+val test_of_action : Actions.t -> t
+
+module TestSet : Set.S with type elt = t
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Abstract Syntax Tree for the Tests Specification Language *)
+
+type 'a located = {
+ node : 'a;
+ loc : Location.t
+}
+
+type environment_statement =
+ | Assignment of string located * string located (* variable = value *)
+ | Include of string located (* include named environemnt *)
+
+type tsl_item =
+ | Environment_statement of environment_statement located
+ | Test of
+ int (* test depth *) *
+ string located (* test name *) *
+ string located list (* environment modifiers *)
+
+type tsl_block = tsl_item list
+
+let make ?(loc = Location.none) foo = { node = foo; loc = loc }
+
+let make_identifier = make
+let make_string = make
+let make_environment_statement = make
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Abstract Syntax Tree for the Tests Specification Language *)
+
+type 'a located = {
+ node : 'a;
+ loc : Location.t
+}
+
+type environment_statement =
+ | Assignment of string located * string located (* variable = value *)
+ | Include of string located (* include named environemnt *)
+
+type tsl_item =
+ | Environment_statement of environment_statement located
+ | Test of
+ int (* test depth *) *
+ string located (* test name *) *
+ string located list (* environment modifiers *)
+
+type tsl_block = tsl_item list
+
+val make_identifier : ?loc:Location.t -> string -> string located
+val make_string : ?loc:Location.t -> string -> string located
+val make_environment_statement :
+ ?loc:Location.t -> environment_statement -> environment_statement located
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2017 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Interface to the Tsl_lexer module *)
+
+val token : Lexing.lexbuf -> Tsl_parser.token
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Lexer definitions for the Tests Specification Language *)
+
+{
+open Tsl_parser
+
+let comment_start_pos = ref []
+
+let lexer_error message =
+ Printf.eprintf "%s\n%!" message;
+ exit 2
+
+}
+
+let newline = ('\013'* '\010')
+let blank = [' ' '\009' '\012']
+let identchar = ['A'-'Z' 'a'-'z' '_' '\'' '0'-'9']
+
+rule token = parse
+ | blank * { token lexbuf }
+ | newline { Lexing.new_line lexbuf; token lexbuf }
+ | "/*" blank* "TEST" { TSL_BEGIN_C_STYLE }
+ | "*/" { TSL_END_C_STYLE }
+ | "(*" blank* "TEST" { TSL_BEGIN_OCAML_STYLE }
+ | "*)" { TSL_END_OCAML_STYLE }
+ | "," { COMA }
+ | '*'+ { TEST_DEPTH (String.length (Lexing.lexeme lexbuf)) }
+ | "=" { EQUAL }
+ | identchar *
+ { let s = Lexing.lexeme lexbuf in
+ match s with
+ | "include" -> INCLUDE
+ | "with" -> WITH
+ | _ -> IDENTIFIER s
+ }
+ | "(*"
+ {
+ comment_start_pos := [Lexing.lexeme_start_p lexbuf];
+ comment lexbuf
+ }
+ | "\"" [^'"']* "\""
+ { let s = Lexing.lexeme lexbuf in
+ let string_length = (String.length s) -2 in
+ let s' = String.sub s 1 string_length in
+ STRING s'
+ }
+ | _
+ {
+ let pos = Lexing.lexeme_start_p lexbuf in
+ let file = pos.Lexing.pos_fname in
+ let line = pos.Lexing.pos_lnum in
+ let column = pos.Lexing.pos_cnum - pos.Lexing.pos_bol in
+ let message = Printf.sprintf "%s:%d:%d: unexpected character %s"
+ file line column (Lexing.lexeme lexbuf) in
+ lexer_error message
+ }
+and comment = parse
+ | "(*"
+ {
+ comment_start_pos :=
+ (Lexing.lexeme_start_p lexbuf) :: !comment_start_pos;
+ comment lexbuf
+ }
+ | "*)"
+ {
+ comment_start_pos := List.tl !comment_start_pos;
+ if !comment_start_pos = [] then token lexbuf else comment lexbuf
+ }
+ | eof
+ {
+ let pos = List.hd !comment_start_pos in
+ let file = pos.Lexing.pos_fname in
+ let line = pos.Lexing.pos_lnum in
+ let column = pos.Lexing.pos_cnum - pos.Lexing.pos_bol in
+ let message = Printf.sprintf "%s:%d:%d: unterminated comment"
+ file line column in
+ lexer_error message
+ }
+ | _
+ {
+ comment lexbuf
+ }
--- /dev/null
+/**************************************************************************/
+/* */
+/* OCaml */
+/* */
+/* Sebastien Hinderer, projet Gallium, INRIA Paris */
+/* */
+/* Copyright 2016 Institut National de Recherche en Informatique et */
+/* en Automatique. */
+/* */
+/* All rights reserved. This file is distributed under the terms of */
+/* the GNU Lesser General Public License version 2.1, with the */
+/* special exception on linking described in the file LICENSE. */
+/* */
+/**************************************************************************/
+
+/* Parser for the Tests Specification Language */
+
+%{
+
+open Location
+open Tsl_ast
+
+let mkstring s = make_string ~loc:(symbol_rloc()) s
+
+let mkidentifier id = make_identifier ~loc:(symbol_rloc()) id
+
+let mkenvstmt envstmt =
+ let located_env_statement =
+ make_environment_statement ~loc:(symbol_rloc()) envstmt in
+ Environment_statement located_env_statement
+
+%}
+
+%token TSL_BEGIN_C_STYLE TSL_END_C_STYLE
+%token TSL_BEGIN_OCAML_STYLE TSL_END_OCAML_STYLE
+%token COMA
+%token <int> TEST_DEPTH
+%token EQUAL
+/* %token COLON */
+%token INCLUDE WITH
+%token <string> IDENTIFIER
+%token <string> STRING
+
+%start tsl_block
+%type <Tsl_ast.tsl_block> tsl_block
+
+%%
+
+tsl_block:
+| TSL_BEGIN_C_STYLE tsl_items TSL_END_C_STYLE { $2 }
+| TSL_BEGIN_OCAML_STYLE tsl_items TSL_END_OCAML_STYLE { $2 }
+
+tsl_items:
+| { [] }
+| tsl_item tsl_items { $1 :: $2 }
+
+tsl_item:
+| test_item { $1 }
+| env_item { $1 }
+
+test_item:
+ TEST_DEPTH identifier with_environment_modifiers { (Test ($1, $2, $3)) }
+
+with_environment_modifiers:
+| { [] }
+| WITH identifier opt_environment_modifiers { $2::(List.rev $3) }
+
+opt_environment_modifiers:
+| { [] }
+| opt_environment_modifiers COMA identifier { $3::$1 }
+
+env_item:
+| identifier EQUAL string
+ { mkenvstmt (Assignment ($1, $3)) }
+| INCLUDE identifier
+ { mkenvstmt (Include $2) }
+
+identifier: IDENTIFIER { mkidentifier $1 }
+
+string: STRING { mkstring $1 }
+
+%%
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Interpretation of TSL blocks and operations on test trees *)
+
+open Tsl_ast
+
+let variable_already_defined loc variable context =
+ let ctxt = match context with
+ | None -> ""
+ | Some envname -> " while including environment " ^ envname in
+ let locstr = Testlib.string_of_location loc in
+ Printf.eprintf "%s\nVariable %s already defined%s\n%!" locstr variable ctxt;
+ exit 2
+
+let no_such_modifiers loc name =
+ let locstr = Testlib.string_of_location loc in
+ Printf.eprintf "%s\nNo such modifiers %s\n%!" locstr name;
+ exit 2
+
+let apply_modifiers env modifiers_name =
+ let name = modifiers_name.node in
+ let modifier = Environments.Include name in
+ try Environments.apply_modifier env modifier with
+ | Environments.Modifiers_name_not_found name ->
+ no_such_modifiers modifiers_name.loc name
+ | Environments.Variable_already_defined variable ->
+ variable_already_defined modifiers_name.loc
+ (Variables.name_of_variable variable) (Some name)
+
+let interprete_environment_statement env statement = match statement.node with
+ | Assignment (var, value) ->
+ begin
+ let variable_name = var.node in
+ let variable = match Variables.find_variable variable_name with
+ | None -> Variables.make (variable_name, "User variable")
+ | Some variable -> variable in
+ try Environments.add variable value.node env with
+ Environments.Variable_already_defined variable ->
+ variable_already_defined statement.loc
+ (Variables.name_of_variable variable) None
+ end
+ | Include modifiers_name -> apply_modifiers env modifiers_name
+
+let interprete_environment_statements env l =
+ List.fold_left interprete_environment_statement env l
+
+type test_tree =
+ | Node of
+ (Tsl_ast.environment_statement located list) *
+ Tests.t *
+ string located list *
+ (test_tree list)
+
+let too_deep testname max_level real_level =
+ Printf.eprintf "Test %s should have depth atmost %d but has depth %d\n%!"
+ testname max_level real_level;
+ exit 2
+
+let unexpected_environment_statement s =
+ let locstr = Testlib.string_of_location s.loc in
+ Printf.eprintf "%s\nUnexpected environment statement\n%!" locstr;
+ exit 2
+
+let no_such_test_or_action t =
+ let locstr = Testlib.string_of_location t.loc in
+ Printf.eprintf "%s\nNo such test or action: %s\n%!" locstr t.node;
+ exit 2
+
+let test_trees_of_tsl_block tsl_block =
+ let rec env_of_lines = function
+ | [] -> ([], [])
+ | Environment_statement s :: lines ->
+ let (env', remaining_lines) = env_of_lines lines in
+ (s :: env', remaining_lines)
+ | lines -> ([], lines)
+ and tree_of_lines depth = function
+ | [] -> (None, [])
+ | line::remaining_lines as l ->
+ begin match line with
+ | Environment_statement s -> unexpected_environment_statement s
+ | Test (test_depth, located_name, env_modifiers) ->
+ begin
+ let name = located_name.node in
+ if test_depth > depth then too_deep name depth test_depth
+ else if test_depth < depth then (None, l)
+ else
+ let (env, rem) = env_of_lines remaining_lines in
+ let (trees, rem) = trees_of_lines (depth+1) rem in
+ match Tests.lookup name with
+ | None ->
+ begin match Actions.lookup name with
+ | None -> no_such_test_or_action located_name
+ | Some action ->
+ let test = Tests.test_of_action action in
+ (Some (Node (env, test, env_modifiers, trees)), rem)
+ end
+ | Some test ->
+ (Some (Node (env, test, env_modifiers, trees)), rem)
+ end
+ end
+ and trees_of_lines depth lines =
+ let remaining_lines = ref lines in
+ let trees = ref [] in
+ let continue = ref true in
+ while !continue; do
+ let (tree, rem) = tree_of_lines depth !remaining_lines in
+ remaining_lines := rem;
+ match tree with
+ | None -> continue := false
+ | Some t -> trees := t :: !trees
+ done;
+ (List.rev !trees, !remaining_lines) in
+ let (env, rem) = env_of_lines tsl_block in
+ let (trees, rem) = trees_of_lines 1 rem in
+ match rem with
+ | [] -> (env, trees)
+ | (Environment_statement s)::_ -> unexpected_environment_statement s
+ | _ -> assert false
+
+let rec tests_in_tree_aux set = function Node (_, test, _, subtrees) ->
+ let set' = List.fold_left tests_in_tree_aux set subtrees in
+ Tests.TestSet.add test set'
+
+let tests_in_tree t = tests_in_tree_aux Tests.TestSet.empty t
+
+let tests_in_trees subtrees =
+ List.fold_left tests_in_tree_aux Tests.TestSet.empty subtrees
+
+let actions_in_test test =
+ let add action_set action = Actions.ActionSet.add action action_set in
+ List.fold_left add Actions.ActionSet.empty test.Tests.test_actions
+
+let actions_in_tests tests =
+ let f test action_set =
+ Actions.ActionSet.union (actions_in_test test) action_set in
+ Tests.TestSet.fold f tests Actions.ActionSet.empty
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Interpretation of TSL blocks and operations on test trees *)
+
+open Tsl_ast
+
+val apply_modifiers : Environments.t -> string located -> Environments.t
+
+val interprete_environment_statement :
+ Environments.t -> Tsl_ast.environment_statement Tsl_ast.located ->
+ Environments.t
+
+val interprete_environment_statements :
+ Environments.t -> Tsl_ast.environment_statement Tsl_ast.located list ->
+ Environments.t
+
+type test_tree =
+ | Node of
+ (Tsl_ast.environment_statement located list) *
+ Tests.t *
+ string located list *
+ (test_tree list)
+
+val test_trees_of_tsl_block :
+ Tsl_ast.tsl_block ->
+ Tsl_ast.environment_statement located list * test_tree list
+
+val tests_in_tree : test_tree -> Tests.TestSet.t
+
+val tests_in_trees : test_tree list -> Tests.TestSet.t
+
+val actions_in_test : Tests.t -> Actions.ActionSet.t
+
+val actions_in_tests : Tests.TestSet.t -> Actions.ActionSet.t
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Definition of environment variabless *)
+
+type t = {
+ variable_name : string;
+ variable_description : string
+}
+
+let compare v1 v2 = String.compare v1.variable_name v2.variable_name
+
+exception Empty_variable_name
+
+exception Variable_already_registered
+
+let make (name, description) =
+ if name="" then raise Empty_variable_name else {
+ variable_name = name;
+ variable_description = description
+ }
+
+let name_of_variable v = v.variable_name
+
+let description_of_variable v = v.variable_description
+
+let (variables : (string, t) Hashtbl.t) = Hashtbl.create 10
+
+let register_variable variable =
+ if Hashtbl.mem variables variable.variable_name
+ then raise Variable_already_registered
+ else Hashtbl.add variables variable.variable_name variable
+
+let find_variable variable_name =
+ try Some (Hashtbl.find variables variable_name)
+ with Not_found -> None
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Sebastien Hinderer, projet Gallium, INRIA Paris *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Definition of environment variabless *)
+
+type t
+
+val compare : t -> t -> int
+
+exception Empty_variable_name
+
+exception Variable_already_registered
+
+val make : string * string -> t
+
+val name_of_variable : t -> string
+
+val description_of_variable : t -> string
+
+val register_variable : t -> unit
+
+val find_variable : string -> t option
CAMLC=$(CAMLRUN) $(ROOTDIR)/ocamlc -nostdlib -I $(ROOTDIR)/stdlib
CAMLOPT=$(CAMLRUN) $(ROOTDIR)/ocamlopt -nostdlib \
-I $(ROOTDIR)/stdlib
-CFLAGS=-I$(ROOTDIR)/byterun $(SHAREDCCCOMPOPTS) $(EXTRACFLAGS)
+CFLAGS += $(SHAREDCCCOMPOPTS) $(EXTRACFLAGS)
+CPPFLAGS += -I$(ROOTDIR)/byterun
# Compilation options
-CC=$(BYTECC)
COMPFLAGS=-absname -w +a-4-9-41-42-44-45-48 -warn-error A -bin-annot -g \
-safe-string -strict-sequence -strict-formats $(EXTRACAMLFLAGS)
ifeq "$(FLAMBDA)" "true"
$(CAMLOPT) -c $(COMPFLAGS) $(OPTCOMPFLAGS) $<
.c.$(O):
- $(BYTECC) $(BYTECCCOMPOPTS) $(CFLAGS) -c $<
+ $(CC) -c $(CFLAGS) $(CPPFLAGS) $(OUTPUTOBJ)$@ $<
-bigarray_stubs.o: bigarray_stubs.c ../../byterun/caml/alloc.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/misc.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/mlvalues.h \
- bigarray.h ../../byterun/caml/custom.h ../../byterun/caml/fail.h \
+bigarray_stubs.$(O): bigarray_stubs.c ../../byterun/caml/alloc.h \
+ ../../byterun/caml/misc.h ../../byterun/caml/config.h \
+ ../../byterun/caml/m.h ../../byterun/caml/s.h \
+ ../../byterun/caml/mlvalues.h ../../byterun/caml/bigarray.h \
+ ../../byterun/caml/custom.h ../../byterun/caml/fail.h \
../../byterun/caml/intext.h ../../byterun/caml/io.h \
../../byterun/caml/hash.h ../../byterun/caml/memory.h \
../../byterun/caml/gc.h ../../byterun/caml/major_gc.h \
../../byterun/caml/freelist.h ../../byterun/caml/minor_gc.h \
../../byterun/caml/address_class.h ../../byterun/caml/signals.h
-mmap_unix.o: mmap_unix.c bigarray.h ../../byterun/caml/compatibility.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/misc.h ../../byterun/caml/custom.h \
- ../../byterun/caml/fail.h ../../byterun/caml/io.h \
- ../../byterun/caml/sys.h ../../byterun/caml/signals.h
-mmap_win32.o: mmap_win32.c bigarray.h ../../byterun/caml/compatibility.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/misc.h ../../byterun/caml/alloc.h \
- ../../byterun/caml/custom.h ../../byterun/caml/fail.h \
- ../../byterun/caml/sys.h ../unix/unixsupport.h
bigarray.cmo : bigarray.cmi
bigarray.cmx : bigarray.cmi
bigarray.cmi :
LIBNAME=bigarray
EXTRACFLAGS=-I../$(UNIXLIB) -DIN_OCAML_BIGARRAY
EXTRACAMLFLAGS=-I ../$(UNIXLIB)
-COBJS=bigarray_stubs.$(O) mmap_$(UNIX_OR_WIN32).$(O)
+COBJS=bigarray_stubs.$(O) mmap_ba.$(O) mmap.$(O)
CAMLOBJS=bigarray.cmo
-HEADERS=bigarray.h
include ../Makefile
-depend:
- $(CC) -MM $(CFLAGS) *.c > .depend
- $(CAMLRUN) $(ROOTDIR)/tools/ocamldep -slash *.mli *.ml >> .depend
+mmap.$(O): ../$(UNIXLIB)/mmap.c
+ $(CC) -c $(CFLAGS) $(CPPFLAGS) $(OUTPUTOBJ)$@ $<
+mmap_ba.$(O): ../unix/mmap_ba.c
+ $(CC) -c $(CFLAGS) $(CPPFLAGS) $(OUTPUTOBJ)$@ $<
-ifeq "$(TOOLCHAIN)" "msvc"
-.depend.nt: .depend
- sed -e 's/\.o/.$(O)/g' $< > $@
-
-include .depend.nt
+.PHONY: depend
+depend:
+ifeq "$(TOOLCHAIN)" "msvc"
+ $(error Dependencies cannot be regenerated using the MSVC ports)
else
-include .depend
+ $(CC) -MM $(CFLAGS) $(CPPFLAGS) *.c | sed -e 's/\.o/.$$(O)/g' > .depend
+ $(CAMLRUN) $(ROOTDIR)/tools/ocamldep -slash *.mli *.ml >> .depend
endif
+
+include .depend
+++ /dev/null
-/**************************************************************************/
-/* */
-/* OCaml */
-/* */
-/* Manuel Serrano and Xavier Leroy, INRIA Rocquencourt */
-/* */
-/* Copyright 2000 Institut National de Recherche en Informatique et */
-/* en Automatique. */
-/* */
-/* All rights reserved. This file is distributed under the terms of */
-/* the GNU Lesser General Public License version 2.1, with the */
-/* special exception on linking described in the file LICENSE. */
-/* */
-/**************************************************************************/
-
-#ifndef CAML_BIGARRAY_H
-#define CAML_BIGARRAY_H
-
-#ifndef CAML_NAME_SPACE
-#include "caml/compatibility.h"
-#endif
-#include "caml/config.h"
-#include "caml/mlvalues.h"
-
-typedef signed char caml_ba_int8;
-typedef unsigned char caml_ba_uint8;
-#if SIZEOF_SHORT == 2
-typedef short caml_ba_int16;
-typedef unsigned short caml_ba_uint16;
-#else
-#error "No 16-bit integer type available"
-#endif
-
-#define CAML_BA_MAX_NUM_DIMS 16
-
-enum caml_ba_kind {
- CAML_BA_FLOAT32, /* Single-precision floats */
- CAML_BA_FLOAT64, /* Double-precision floats */
- CAML_BA_SINT8, /* Signed 8-bit integers */
- CAML_BA_UINT8, /* Unsigned 8-bit integers */
- CAML_BA_SINT16, /* Signed 16-bit integers */
- CAML_BA_UINT16, /* Unsigned 16-bit integers */
- CAML_BA_INT32, /* Signed 32-bit integers */
- CAML_BA_INT64, /* Signed 64-bit integers */
- CAML_BA_CAML_INT, /* OCaml-style integers (signed 31 or 63 bits) */
- CAML_BA_NATIVE_INT, /* Platform-native long integers (32 or 64 bits) */
- CAML_BA_COMPLEX32, /* Single-precision complex */
- CAML_BA_COMPLEX64, /* Double-precision complex */
- CAML_BA_CHAR, /* Characters */
- CAML_BA_KIND_MASK = 0xFF /* Mask for kind in flags field */
-};
-
-#define Caml_ba_kind_val(v) Int_val(v)
-
-#define Val_caml_ba_kind(k) Val_int(k)
-
-enum caml_ba_layout {
- CAML_BA_C_LAYOUT = 0, /* Row major, indices start at 0 */
- CAML_BA_FORTRAN_LAYOUT = 0x100, /* Column major, indices start at 1 */
- CAML_BA_LAYOUT_MASK = 0x100, /* Mask for layout in flags field */
- CAML_BA_LAYOUT_SHIFT = 8 /* Bit offset of layout flag */
-};
-
-#define Caml_ba_layout_val(v) (Int_val(v) << CAML_BA_LAYOUT_SHIFT)
-
-#define Val_caml_ba_layout(l) Val_int(l >> CAML_BA_LAYOUT_SHIFT)
-
-enum caml_ba_managed {
- CAML_BA_EXTERNAL = 0, /* Data is not allocated by OCaml */
- CAML_BA_MANAGED = 0x200, /* Data is allocated by OCaml */
- CAML_BA_MAPPED_FILE = 0x400, /* Data is a memory mapped file */
- CAML_BA_MANAGED_MASK = 0x600 /* Mask for "managed" bits in flags field */
-};
-
-struct caml_ba_proxy {
- intnat refcount; /* Reference count */
- void * data; /* Pointer to base of actual data */
- uintnat size; /* Size of data in bytes (if mapped file) */
-};
-
-struct caml_ba_array {
- void * data; /* Pointer to raw data */
- intnat num_dims; /* Number of dimensions */
- intnat flags; /* Kind of element array + memory layout + allocation status */
- struct caml_ba_proxy * proxy; /* The proxy for sub-arrays, or NULL */
- /* PR#5516: use C99's flexible array types if possible */
-#if (__STDC_VERSION__ >= 199901L)
- intnat dim[] /*[num_dims]*/; /* Size in each dimension */
-#else
- intnat dim[1] /*[num_dims]*/; /* Size in each dimension */
-#endif
-};
-
-/* Size of struct caml_ba_array, in bytes, without dummy first dimension */
-#if (__STDC_VERSION__ >= 199901L)
-#define SIZEOF_BA_ARRAY sizeof(struct caml_ba_array)
-#else
-#define SIZEOF_BA_ARRAY (sizeof(struct caml_ba_array) - sizeof(intnat))
-#endif
-
-#define Caml_ba_array_val(v) ((struct caml_ba_array *) Data_custom_val(v))
-
-#define Caml_ba_data_val(v) (Caml_ba_array_val(v)->data)
-
-#if defined(IN_OCAML_BIGARRAY)
-#define CAMLBAextern CAMLexport
-#else
-#define CAMLBAextern CAMLextern
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-CAMLBAextern value
- caml_ba_alloc(int flags, int num_dims, void * data, intnat * dim);
-CAMLBAextern value caml_ba_alloc_dims(int flags, int num_dims, void * data,
- ... /*dimensions, with type intnat */);
-CAMLBAextern uintnat caml_ba_byte_size(struct caml_ba_array * b);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* CAML_BIGARRAY_H */
(* Module [Bigarray]: large, multi-dimensional, numerical arrays *)
-external init : unit -> unit = "caml_ba_init"
-
-let _ = init()
-
-type float32_elt = Float32_elt
-type float64_elt = Float64_elt
-type int8_signed_elt = Int8_signed_elt
-type int8_unsigned_elt = Int8_unsigned_elt
-type int16_signed_elt = Int16_signed_elt
-type int16_unsigned_elt = Int16_unsigned_elt
-type int32_elt = Int32_elt
-type int64_elt = Int64_elt
-type int_elt = Int_elt
-type nativeint_elt = Nativeint_elt
-type complex32_elt = Complex32_elt
-type complex64_elt = Complex64_elt
-
-type ('a, 'b) kind =
- Float32 : (float, float32_elt) kind
- | Float64 : (float, float64_elt) kind
- | Int8_signed : (int, int8_signed_elt) kind
- | Int8_unsigned : (int, int8_unsigned_elt) kind
- | Int16_signed : (int, int16_signed_elt) kind
- | Int16_unsigned : (int, int16_unsigned_elt) kind
- | Int32 : (int32, int32_elt) kind
- | Int64 : (int64, int64_elt) kind
- | Int : (int, int_elt) kind
- | Nativeint : (nativeint, nativeint_elt) kind
- | Complex32 : (Complex.t, complex32_elt) kind
- | Complex64 : (Complex.t, complex64_elt) kind
- | Char : (char, int8_unsigned_elt) kind
+include CamlinternalBigarray
(* Keep those constants in sync with the caml_ba_kind enumeration
in bigarray.h *)
| Complex64 -> 16
| Char -> 1
-type c_layout = C_layout_typ
-type fortran_layout = Fortran_layout_typ
-
-type 'a layout =
- C_layout: c_layout layout
- | Fortran_layout: fortran_layout layout
-
(* Keep those constants in sync with the caml_ba_layout enumeration
in bigarray.h *)
let fortran_layout = Fortran_layout
module Genarray = struct
- type ('a, 'b, 'c) t
+ type ('a, 'b, 'c) t = ('a, 'b, 'c) genarray
external create: ('a, 'b) kind -> 'c layout -> int array -> ('a, 'b, 'c) t
= "caml_ba_create"
external get: ('a, 'b, 'c) t -> int array -> 'a
external kind: ('a, 'b, 'c) t -> ('a, 'b) kind = "caml_ba_kind"
external layout: ('a, 'b, 'c) t -> 'c layout = "caml_ba_layout"
+ external change_layout: ('a, 'b, 'c) t -> 'd layout -> ('a, 'b, 'd) t
+ = "caml_ba_change_layout"
+
let size_in_bytes arr = kind_size_in_bytes (kind arr)
external blit: ('a, 'b, 'c) t -> ('a, 'b, 'c) t -> unit = "caml_ba_blit"
external kind: ('a, 'b, 'c) t -> ('a, 'b) kind = "caml_ba_kind"
external layout: ('a, 'b, 'c) t -> 'c layout = "caml_ba_layout"
+ external change_layout: ('a, 'b, 'c) t -> 'd layout -> ('a, 'b, 'd) t
+ = "caml_ba_change_layout"
+
let size_in_bytes arr =
(kind_size_in_bytes (kind arr)) * (dim arr)
external kind: ('a, 'b, 'c) t -> ('a, 'b) kind = "caml_ba_kind"
external layout: ('a, 'b, 'c) t -> 'c layout = "caml_ba_layout"
+ external change_layout: ('a, 'b, 'c) t -> 'd layout -> ('a, 'b, 'd) t
+ = "caml_ba_change_layout"
+
let size_in_bytes arr =
(kind_size_in_bytes (kind arr)) * (dim1 arr) * (dim2 arr)
external kind: ('a, 'b, 'c) t -> ('a, 'b) kind = "caml_ba_kind"
external layout: ('a, 'b, 'c) t -> 'c layout = "caml_ba_layout"
+ external change_layout: ('a, 'b, 'c) t -> 'd layout -> ('a, 'b, 'd) t
+ = "caml_ba_change_layout"
+
let size_in_bytes arr =
(kind_size_in_bytes (kind arr)) * (dim1 arr) * (dim2 arr) * (dim3 arr)
and {!Pervasives.input_value}).
*)
-(** {6 Element kinds} *)
+(** {1 Element kinds} *)
(** Big arrays can contain elements of the following kinds:
- IEEE single precision (32 bits) floating-point numbers
of abstract types for technical injectivity reasons).
*)
-type float32_elt = Float32_elt
-type float64_elt = Float64_elt
-type int8_signed_elt = Int8_signed_elt
-type int8_unsigned_elt = Int8_unsigned_elt
-type int16_signed_elt = Int16_signed_elt
-type int16_unsigned_elt = Int16_unsigned_elt
-type int32_elt = Int32_elt
-type int64_elt = Int64_elt
-type int_elt = Int_elt
-type nativeint_elt = Nativeint_elt
-type complex32_elt = Complex32_elt
-type complex64_elt = Complex64_elt
-
-type ('a, 'b) kind =
+type float32_elt = CamlinternalBigarray.float32_elt = Float32_elt
+type float64_elt = CamlinternalBigarray.float64_elt = Float64_elt
+type int8_signed_elt = CamlinternalBigarray.int8_signed_elt = Int8_signed_elt
+type int8_unsigned_elt = CamlinternalBigarray.int8_unsigned_elt =
+ Int8_unsigned_elt
+type int16_signed_elt = CamlinternalBigarray.int16_signed_elt =
+ Int16_signed_elt
+type int16_unsigned_elt = CamlinternalBigarray.int16_unsigned_elt =
+ Int16_unsigned_elt
+type int32_elt = CamlinternalBigarray.int32_elt = Int32_elt
+type int64_elt = CamlinternalBigarray.int64_elt = Int64_elt
+type int_elt = CamlinternalBigarray.int_elt = Int_elt
+type nativeint_elt = CamlinternalBigarray.nativeint_elt = Nativeint_elt
+type complex32_elt = CamlinternalBigarray.complex32_elt = Complex32_elt
+type complex64_elt = CamlinternalBigarray.complex64_elt = Complex64_elt
+
+type ('a, 'b) kind = ('a, 'b) CamlinternalBigarray.kind =
Float32 : (float, float32_elt) kind
| Float64 : (float, float64_elt) kind
| Int8_signed : (int, int8_signed_elt) kind
@since 4.03.0 *)
-(** {6 Array layouts} *)
+(** {1 Array layouts} *)
-type c_layout = C_layout_typ (**)
+type c_layout = CamlinternalBigarray.c_layout = C_layout_typ (**)
(** See {!Bigarray.fortran_layout}.*)
-type fortran_layout = Fortran_layout_typ (**)
+type fortran_layout = CamlinternalBigarray.fortran_layout =
+ Fortran_layout_typ (**)
(** To facilitate interoperability with existing C and Fortran code,
this library supports two different memory layouts for big arrays,
one compatible with the C conventions,
re-exported as values below for backward-compatibility reasons.
*)
-type 'a layout =
+type 'a layout = 'a CamlinternalBigarray.layout =
C_layout: c_layout layout
| Fortran_layout: fortran_layout layout
val fortran_layout : fortran_layout layout
-(** {6 Generic arrays (of arbitrarily many dimensions)} *)
+(** {1 Generic arrays (of arbitrarily many dimensions)} *)
module Genarray :
sig
- type ('a, 'b, 'c) t
+ type ('a, 'b, 'c) t = ('a, 'b, 'c) CamlinternalBigarray.genarray
(** The type [Genarray.t] is the type of big arrays with variable
numbers of dimensions. Any number of dimensions between 0 and 16
is supported.
val map_file:
Unix.file_descr -> ?pos:int64 -> ('a, 'b) kind -> 'c layout ->
bool -> int array -> ('a, 'b, 'c) t
- (** Memory mapping of a file as a big array.
- [Genarray.map_file fd kind layout shared dims]
- returns a big array of kind [kind], layout [layout],
- and dimensions as specified in [dims]. The data contained in
- this big array are the contents of the file referred to by
- the file descriptor [fd] (as opened previously with
- [Unix.openfile], for example). The optional [pos] parameter
- is the byte offset in the file of the data being mapped;
- it defaults to 0 (map from the beginning of the file).
-
- If [shared] is [true], all modifications performed on the array
- are reflected in the file. This requires that [fd] be opened
- with write permissions. If [shared] is [false], modifications
- performed on the array are done in memory only, using
- copy-on-write of the modified pages; the underlying file is not
- affected.
-
- [Genarray.map_file] is much more efficient than reading
- the whole file in a big array, modifying that big array,
- and writing it afterwards.
-
- To adjust automatically the dimensions of the big array to
- the actual size of the file, the major dimension (that is,
- the first dimension for an array with C layout, and the last
- dimension for an array with Fortran layout) can be given as
- [-1]. [Genarray.map_file] then determines the major dimension
- from the size of the file. The file must contain an integral
- number of sub-arrays as determined by the non-major dimensions,
- otherwise [Failure] is raised.
-
- If all dimensions of the big array are given, the file size is
- matched against the size of the big array. If the file is larger
- than the big array, only the initial portion of the file is
- mapped to the big array. If the file is smaller than the big
- array, the file is automatically grown to the size of the big array.
- This requires write permissions on [fd].
-
- Array accesses are bounds-checked, but the bounds are determined by
- the initial call to [map_file]. Therefore, you should make sure no
- other process modifies the mapped file while you're accessing it,
- or a SIGBUS signal may be raised. This happens, for instance, if the
- file is shrunk.
-
- This function raises [Sys_error] in the case of any errors from the
- underlying system calls. [Invalid_argument] or [Failure] may be
- raised in cases where argument validation fails. *)
-
+ [@@ocaml.deprecated "\
+Use Unix.map_file instead.\n\
+Note that Bigarray.Genarray.map_file raises Sys_error while\n\
+Unix.map_file raises Unix_error."]
end
-(** {6 Zero-dimensional arrays} *)
+(** {1 Zero-dimensional arrays} *)
(** Zero-dimensional arrays. The [Array0] structure provides operations
similar to those of {!Bigarray.Genarray}, but specialized to the case
external layout: ('a, 'b, 'c) t -> 'c layout = "caml_ba_layout"
(** Return the layout of the given big array. *)
+ val change_layout: ('a, 'b, 'c) t -> 'd layout -> ('a, 'b, 'd) t
+ (** [Array0.change_layout a layout] returns a big array with the
+ specified [layout], sharing the data with [a]. No copying of elements
+ is involved: the new array and the original array share the same
+ storage space.
+
+ @since 4.06.0
+ *)
+
val size_in_bytes : ('a, 'b, 'c) t -> int
(** [size_in_bytes a] is [a]'s {!kind_size_in_bytes}. *)
end
-(** {6 One-dimensional arrays} *)
+(** {1 One-dimensional arrays} *)
(** One-dimensional arrays. The [Array1] structure provides operations
similar to those of
external layout: ('a, 'b, 'c) t -> 'c layout = "caml_ba_layout"
(** Return the layout of the given big array. *)
+ val change_layout: ('a, 'b, 'c) t -> 'd layout -> ('a, 'b, 'd) t
+ (** [Array1.change_layout a layout] returns a bigarray with the
+ specified [layout], sharing the data with [a] (and hence having
+ the same dimension as [a]). No copying of elements is involved: the
+ new array and the original array share the same storage space.
+
+ @since 4.06.0
+ *)
+
+
val size_in_bytes : ('a, 'b, 'c) t -> int
(** [size_in_bytes a] is the number of elements in [a]
multiplied by [a]'s {!kind_size_in_bytes}.
val map_file: Unix.file_descr -> ?pos:int64 -> ('a, 'b) kind -> 'c layout ->
bool -> int -> ('a, 'b, 'c) t
- (** Memory mapping of a file as a one-dimensional big array.
- See {!Bigarray.Genarray.map_file} for more details. *)
+ [@@ocaml.deprecated "\
+Use [array1_of_genarray (Unix.map_file ...)] instead.\n\
+Note that Bigarray.Array1.map_file raises Sys_error while\n\
+Unix.map_file raises Unix_error."]
external unsafe_get: ('a, 'b, 'c) t -> int -> 'a = "%caml_ba_unsafe_ref_1"
(** Like {!Bigarray.Array1.get}, but bounds checking is not always performed.
end
-(** {6 Two-dimensional arrays} *)
+(** {1 Two-dimensional arrays} *)
(** Two-dimensional arrays. The [Array2] structure provides operations
similar to those of {!Bigarray.Genarray}, but specialized to the
external layout: ('a, 'b, 'c) t -> 'c layout = "caml_ba_layout"
(** Return the layout of the given big array. *)
+ val change_layout: ('a, 'b, 'c) t -> 'd layout -> ('a, 'b, 'd) t
+ (** [Array2.change_layout a layout] returns a bigarray with the
+ specified [layout], sharing the data with [a] (and hence having
+ the same dimensions as [a]). No copying of elements is involved: the
+ new array and the original array share the same storage space.
+ The dimensions are reversed, such that [get v [| a; b |]] in
+ C layout becomes [get v [| b+1; a+1 |]] in Fortran layout.
+
+ @since 4.06.0
+ *)
+
+
val size_in_bytes : ('a, 'b, 'c) t -> int
(** [size_in_bytes a] is the number of elements in [a]
multiplied by [a]'s {!kind_size_in_bytes}.
val map_file: Unix.file_descr -> ?pos:int64 -> ('a, 'b) kind -> 'c layout ->
bool -> int -> int -> ('a, 'b, 'c) t
- (** Memory mapping of a file as a two-dimensional big array.
- See {!Bigarray.Genarray.map_file} for more details. *)
+ [@@ocaml.deprecated "\
+Use [array2_of_genarray (Unix.map_file ...)] instead.\n\
+Note that Bigarray.Array2.map_file raises Sys_error while\n\
+Unix.map_file raises Unix_error."]
external unsafe_get: ('a, 'b, 'c) t -> int -> int -> 'a
= "%caml_ba_unsafe_ref_2"
end
-(** {6 Three-dimensional arrays} *)
+(** {1 Three-dimensional arrays} *)
(** Three-dimensional arrays. The [Array3] structure provides operations
similar to those of {!Bigarray.Genarray}, but specialized to the case
external layout: ('a, 'b, 'c) t -> 'c layout = "caml_ba_layout"
(** Return the layout of the given big array. *)
+
+ val change_layout: ('a, 'b, 'c) t -> 'd layout -> ('a, 'b, 'd) t
+ (** [Array3.change_layout a layout] returns a bigarray with the
+ specified [layout], sharing the data with [a] (and hence having
+ the same dimensions as [a]). No copying of elements is involved: the
+ new array and the original array share the same storage space.
+ The dimensions are reversed, such that [get v [| a; b; c |]] in
+ C layout becomes [get v [| c+1; b+1; a+1 |]] in Fortran layout.
+
+ @since 4.06.0
+ *)
+
val size_in_bytes : ('a, 'b, 'c) t -> int
(** [size_in_bytes a] is the number of elements in [a]
multiplied by [a]'s {!kind_size_in_bytes}.
val map_file: Unix.file_descr -> ?pos:int64 -> ('a, 'b) kind -> 'c layout ->
bool -> int -> int -> int -> ('a, 'b, 'c) t
- (** Memory mapping of a file as a three-dimensional big array.
- See {!Bigarray.Genarray.map_file} for more details. *)
+ [@@ocaml.deprecated "\
+Use [array3_of_genarray (Unix.map_file ...)] instead.\n\
+Note that Bigarray.Array3.map_file raises Sys_error while\n\
+Unix.map_file raises Unix_error."]
external unsafe_get: ('a, 'b, 'c) t -> int -> int -> int -> 'a
= "%caml_ba_unsafe_ref_3"
end
-(** {6 Coercions between generic big arrays and fixed-dimension big arrays} *)
+(** {1 Coercions between generic big arrays and fixed-dimension big arrays} *)
external genarray_of_array0 :
('a, 'b, 'c) Array0.t -> ('a, 'b, 'c) Genarray.t = "%identity"
does not have exactly three dimensions. *)
-(** {6 Re-shaping big arrays} *)
+(** {1 Re-shaping big arrays} *)
val reshape : ('a, 'b, 'c) Genarray.t -> int array -> ('a, 'b, 'c) Genarray.t
(** [reshape b [|d1;...;dN|]] converts the big array [b] to a
#include <stdarg.h>
#include <string.h>
#include "caml/alloc.h"
-#include "bigarray.h"
+#include "caml/bigarray.h"
#include "caml/custom.h"
#include "caml/fail.h"
#include "caml/intext.h"
#define int16 caml_ba_int16
#define uint16 caml_ba_uint16
-extern void caml_ba_unmap_file(void * addr, uintnat len);
- /* from mmap_xxx.c */
-
-/* Compute the number of elements of a big array */
-
-static uintnat caml_ba_num_elts(struct caml_ba_array * b)
-{
- uintnat num_elts;
- int i;
- num_elts = 1;
- for (i = 0; i < b->num_dims; i++) num_elts = num_elts * b->dim[i];
- return num_elts;
-}
-
-/* Size in bytes of a bigarray element, indexed by bigarray kind */
-
-int caml_ba_element_size[] =
-{ 4 /*FLOAT32*/, 8 /*FLOAT64*/,
- 1 /*SINT8*/, 1 /*UINT8*/,
- 2 /*SINT16*/, 2 /*UINT16*/,
- 4 /*INT32*/, 8 /*INT64*/,
- sizeof(value) /*CAML_INT*/, sizeof(value) /*NATIVE_INT*/,
- 8 /*COMPLEX32*/, 16 /*COMPLEX64*/,
- 1 /*CHAR*/
-};
-
-/* Compute the number of bytes for the elements of a big array */
-
-CAMLexport uintnat caml_ba_byte_size(struct caml_ba_array * b)
-{
- return caml_ba_num_elts(b)
- * caml_ba_element_size[b->flags & CAML_BA_KIND_MASK];
-}
-
-/* Operation table for bigarrays */
-
-static void caml_ba_finalize(value v);
-static int caml_ba_compare(value v1, value v2);
-static intnat caml_ba_hash(value v);
-static void caml_ba_serialize(value, uintnat *, uintnat *);
-uintnat caml_ba_deserialize(void * dst);
-static struct custom_operations caml_ba_ops = {
- "_bigarray",
- caml_ba_finalize,
- caml_ba_compare,
- caml_ba_hash,
- caml_ba_serialize,
- caml_ba_deserialize,
- custom_compare_ext_default
-};
-
-/* Multiplication of unsigned longs with overflow detection */
-
-static uintnat
-caml_ba_multov(uintnat a, uintnat b, int * overflow)
-{
-#define HALF_SIZE (sizeof(uintnat) * 4)
-#define HALF_MASK (((uintnat)1 << HALF_SIZE) - 1)
-#define LOW_HALF(x) ((x) & HALF_MASK)
-#define HIGH_HALF(x) ((x) >> HALF_SIZE)
- /* Cut in half words */
- uintnat al = LOW_HALF(a);
- uintnat ah = HIGH_HALF(a);
- uintnat bl = LOW_HALF(b);
- uintnat bh = HIGH_HALF(b);
- /* Exact product is:
- al * bl
- + ah * bl << HALF_SIZE
- + al * bh << HALF_SIZE
- + ah * bh << 2*HALF_SIZE
- Overflow occurs if:
- ah * bh is not 0, i.e. ah != 0 and bh != 0
- OR ah * bl has high half != 0
- OR ah * bl has high half != 0
- OR the sum al * bl + LOW_HALF(ah * bl) << HALF_SIZE
- + LOW_HALF(al * bh) << HALF_SIZE overflows.
- This sum is equal to p = (a * b) modulo word size. */
- uintnat p1 = al * bh;
- uintnat p2 = ah * bl;
- uintnat p = a * b;
- if (ah != 0 && bh != 0) *overflow = 1;
- if (HIGH_HALF(p1) != 0 || HIGH_HALF(p2) != 0) *overflow = 1;
- p1 <<= HALF_SIZE;
- p2 <<= HALF_SIZE;
- p1 += p2;
- if (p < p1 || p1 < p2) *overflow = 1; /* overflow in sums */
- return p;
-#undef HALF_SIZE
-#undef LOW_HALF
-#undef HIGH_HALF
-}
-
-/* Allocation of a big array */
-
-#define CAML_BA_MAX_MEMORY 1024*1024*1024
-/* 1 Gb -- after allocating that much, it's probably worth speeding
- up the major GC */
-
-/* [caml_ba_alloc] will allocate a new bigarray object in the heap.
- If [data] is NULL, the memory for the contents is also allocated
- (with [malloc]) by [caml_ba_alloc].
- [data] cannot point into the OCaml heap.
- [dim] may point into an object in the OCaml heap.
-*/
-CAMLexport value
-caml_ba_alloc(int flags, int num_dims, void * data, intnat * dim)
-{
- uintnat num_elts, asize, size;
- int overflow, i;
- value res;
- struct caml_ba_array * b;
- intnat dimcopy[CAML_BA_MAX_NUM_DIMS];
-
- Assert(num_dims >= 0 && num_dims <= CAML_BA_MAX_NUM_DIMS);
- Assert((flags & CAML_BA_KIND_MASK) <= CAML_BA_CHAR);
- for (i = 0; i < num_dims; i++) dimcopy[i] = dim[i];
- size = 0;
- if (data == NULL) {
- overflow = 0;
- num_elts = 1;
- for (i = 0; i < num_dims; i++) {
- num_elts = caml_ba_multov(num_elts, dimcopy[i], &overflow);
- }
- size = caml_ba_multov(num_elts,
- caml_ba_element_size[flags & CAML_BA_KIND_MASK],
- &overflow);
- if (overflow) caml_raise_out_of_memory();
- data = malloc(size);
- if (data == NULL && size != 0) caml_raise_out_of_memory();
- flags |= CAML_BA_MANAGED;
- }
- asize = SIZEOF_BA_ARRAY + num_dims * sizeof(intnat);
- res = caml_alloc_custom(&caml_ba_ops, asize, size, CAML_BA_MAX_MEMORY);
- b = Caml_ba_array_val(res);
- b->data = data;
- b->num_dims = num_dims;
- b->flags = flags;
- b->proxy = NULL;
- for (i = 0; i < num_dims; i++) b->dim[i] = dimcopy[i];
- return res;
-}
-
-/* Same as caml_ba_alloc, but dimensions are passed as a list of
- arguments */
-
-CAMLexport value caml_ba_alloc_dims(int flags, int num_dims, void * data, ...)
-{
- va_list ap;
- intnat dim[CAML_BA_MAX_NUM_DIMS];
- int i;
- value res;
-
- Assert(num_dims <= CAML_BA_MAX_NUM_DIMS);
- va_start(ap, data);
- for (i = 0; i < num_dims; i++) dim[i] = va_arg(ap, intnat);
- va_end(ap);
- res = caml_ba_alloc(flags, num_dims, data, dim);
- return res;
-}
-
/* Allocate a bigarray from OCaml */
CAMLprim value caml_ba_create(value vkind, value vlayout, value vdim)
/* Perform read */
switch ((b->flags) & CAML_BA_KIND_MASK) {
default:
- Assert(0);
+ CAMLassert(0);
case CAML_BA_FLOAT32:
return caml_copy_double(((float *) b->data)[offset]);
case CAML_BA_FLOAT64:
/* Perform write */
switch (b->flags & CAML_BA_KIND_MASK) {
default:
- Assert(0);
+ CAMLassert(0);
case CAML_BA_FLOAT32:
((float *) b->data)[offset] = Double_val(newval); break;
case CAML_BA_FLOAT64:
return Val_caml_ba_layout(layout);
}
-/* Finalization of a big array */
-
-static void caml_ba_finalize(value v)
-{
- struct caml_ba_array * b = Caml_ba_array_val(v);
-
- switch (b->flags & CAML_BA_MANAGED_MASK) {
- case CAML_BA_EXTERNAL:
- break;
- case CAML_BA_MANAGED:
- if (b->proxy == NULL) {
- free(b->data);
- } else {
- if (-- b->proxy->refcount == 0) {
- free(b->proxy->data);
- caml_stat_free(b->proxy);
- }
- }
- break;
- case CAML_BA_MAPPED_FILE:
- if (b->proxy == NULL) {
- caml_ba_unmap_file(b->data, caml_ba_byte_size(b));
- } else {
- if (-- b->proxy->refcount == 0) {
- caml_ba_unmap_file(b->proxy->data, b->proxy->size);
- caml_stat_free(b->proxy);
- }
- }
- break;
- }
-}
-
-/* Comparison of two big arrays */
-
-static int caml_ba_compare(value v1, value v2)
-{
- struct caml_ba_array * b1 = Caml_ba_array_val(v1);
- struct caml_ba_array * b2 = Caml_ba_array_val(v2);
- uintnat n, num_elts;
- intnat flags1, flags2;
- int i;
-
- /* Compare kind & layout in case the arguments are of different types */
- flags1 = b1->flags & (CAML_BA_KIND_MASK | CAML_BA_LAYOUT_MASK);
- flags2 = b2->flags & (CAML_BA_KIND_MASK | CAML_BA_LAYOUT_MASK);
- if (flags1 != flags2) return flags2 - flags1;
- /* Compare number of dimensions */
- if (b1->num_dims != b2->num_dims) return b2->num_dims - b1->num_dims;
- /* Same number of dimensions: compare dimensions lexicographically */
- for (i = 0; i < b1->num_dims; i++) {
- intnat d1 = b1->dim[i];
- intnat d2 = b2->dim[i];
- if (d1 != d2) return d1 < d2 ? -1 : 1;
- }
- /* Same dimensions: compare contents lexicographically */
- num_elts = caml_ba_num_elts(b1);
-
-#define DO_INTEGER_COMPARISON(type) \
- { type * p1 = b1->data; type * p2 = b2->data; \
- for (n = 0; n < num_elts; n++) { \
- type e1 = *p1++; type e2 = *p2++; \
- if (e1 < e2) return -1; \
- if (e1 > e2) return 1; \
- } \
- return 0; \
- }
-#define DO_FLOAT_COMPARISON(type) \
- { type * p1 = b1->data; type * p2 = b2->data; \
- for (n = 0; n < num_elts; n++) { \
- type e1 = *p1++; type e2 = *p2++; \
- if (e1 < e2) return -1; \
- if (e1 > e2) return 1; \
- if (e1 != e2) { \
- caml_compare_unordered = 1; \
- if (e1 == e1) return 1; \
- if (e2 == e2) return -1; \
- } \
- } \
- return 0; \
- }
-
- switch (b1->flags & CAML_BA_KIND_MASK) {
- case CAML_BA_COMPLEX32:
- num_elts *= 2; /*fallthrough*/
- case CAML_BA_FLOAT32:
- DO_FLOAT_COMPARISON(float);
- case CAML_BA_COMPLEX64:
- num_elts *= 2; /*fallthrough*/
- case CAML_BA_FLOAT64:
- DO_FLOAT_COMPARISON(double);
- case CAML_BA_CHAR:
- DO_INTEGER_COMPARISON(uint8);
- case CAML_BA_SINT8:
- DO_INTEGER_COMPARISON(int8);
- case CAML_BA_UINT8:
- DO_INTEGER_COMPARISON(uint8);
- case CAML_BA_SINT16:
- DO_INTEGER_COMPARISON(int16);
- case CAML_BA_UINT16:
- DO_INTEGER_COMPARISON(uint16);
- case CAML_BA_INT32:
- DO_INTEGER_COMPARISON(int32_t);
- case CAML_BA_INT64:
- DO_INTEGER_COMPARISON(int64_t);
- case CAML_BA_CAML_INT:
- case CAML_BA_NATIVE_INT:
- DO_INTEGER_COMPARISON(intnat);
- default:
- Assert(0);
- return 0; /* should not happen */
- }
-#undef DO_INTEGER_COMPARISON
-#undef DO_FLOAT_COMPARISON
-}
-
-/* Hashing of a bigarray */
-
-static intnat caml_ba_hash(value v)
-{
- struct caml_ba_array * b = Caml_ba_array_val(v);
- intnat num_elts, n;
- uint32_t h, w;
- int i;
-
- num_elts = 1;
- for (i = 0; i < b->num_dims; i++) num_elts = num_elts * b->dim[i];
- h = 0;
-
- switch (b->flags & CAML_BA_KIND_MASK) {
- case CAML_BA_CHAR:
- case CAML_BA_SINT8:
- case CAML_BA_UINT8: {
- uint8 * p = b->data;
- if (num_elts > 256) num_elts = 256;
- for (n = 0; n + 4 <= num_elts; n += 4, p += 4) {
- w = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
- h = caml_hash_mix_uint32(h, w);
- }
- w = 0;
- switch (num_elts & 3) {
- case 3: w = p[2] << 16; /* fallthrough */
- case 2: w |= p[1] << 8; /* fallthrough */
- case 1: w |= p[0];
- h = caml_hash_mix_uint32(h, w);
- }
- break;
- }
- case CAML_BA_SINT16:
- case CAML_BA_UINT16: {
- uint16 * p = b->data;
- if (num_elts > 128) num_elts = 128;
- for (n = 0; n + 2 <= num_elts; n += 2, p += 2) {
- w = p[0] | (p[1] << 16);
- h = caml_hash_mix_uint32(h, w);
- }
- if ((num_elts & 1) != 0)
- h = caml_hash_mix_uint32(h, p[0]);
- break;
- }
- case CAML_BA_INT32:
- {
- uint32_t * p = b->data;
- if (num_elts > 64) num_elts = 64;
- for (n = 0; n < num_elts; n++, p++) h = caml_hash_mix_uint32(h, *p);
- break;
- }
- case CAML_BA_CAML_INT:
- case CAML_BA_NATIVE_INT:
- {
- intnat * p = b->data;
- if (num_elts > 64) num_elts = 64;
- for (n = 0; n < num_elts; n++, p++) h = caml_hash_mix_intnat(h, *p);
- break;
- }
- case CAML_BA_INT64:
- {
- int64_t * p = b->data;
- if (num_elts > 32) num_elts = 32;
- for (n = 0; n < num_elts; n++, p++) h = caml_hash_mix_int64(h, *p);
- break;
- }
- case CAML_BA_COMPLEX32:
- num_elts *= 2; /* fallthrough */
- case CAML_BA_FLOAT32:
- {
- float * p = b->data;
- if (num_elts > 64) num_elts = 64;
- for (n = 0; n < num_elts; n++, p++) h = caml_hash_mix_float(h, *p);
- break;
- }
- case CAML_BA_COMPLEX64:
- num_elts *= 2; /* fallthrough */
- case CAML_BA_FLOAT64:
- {
- double * p = b->data;
- if (num_elts > 32) num_elts = 32;
- for (n = 0; n < num_elts; n++, p++) h = caml_hash_mix_double(h, *p);
- break;
- }
- }
- return h;
-}
-
-static void caml_ba_serialize_longarray(void * data,
- intnat num_elts,
- intnat min_val, intnat max_val)
-{
-#ifdef ARCH_SIXTYFOUR
- int overflow_32 = 0;
- intnat * p, n;
- for (n = 0, p = data; n < num_elts; n++, p++) {
- if (*p < min_val || *p > max_val) { overflow_32 = 1; break; }
- }
- if (overflow_32) {
- caml_serialize_int_1(1);
- caml_serialize_block_8(data, num_elts);
- } else {
- caml_serialize_int_1(0);
- for (n = 0, p = data; n < num_elts; n++, p++)
- caml_serialize_int_4((int32_t) *p);
- }
-#else
- caml_serialize_int_1(0);
- caml_serialize_block_4(data, num_elts);
-#endif
-}
-
-static void caml_ba_serialize(value v,
- uintnat * wsize_32,
- uintnat * wsize_64)
-{
- struct caml_ba_array * b = Caml_ba_array_val(v);
- intnat num_elts;
- int i;
-
- /* Serialize header information */
- caml_serialize_int_4(b->num_dims);
- caml_serialize_int_4(b->flags & (CAML_BA_KIND_MASK | CAML_BA_LAYOUT_MASK));
- /* On a 64-bit machine, if any of the dimensions is >= 2^32,
- the size of the marshaled data will be >= 2^32 and
- extern_value() will fail. So, it is safe to write the dimensions
- as 32-bit unsigned integers. */
- for (i = 0; i < b->num_dims; i++) caml_serialize_int_4(b->dim[i]);
- /* Compute total number of elements */
- num_elts = 1;
- for (i = 0; i < b->num_dims; i++) num_elts = num_elts * b->dim[i];
- /* Serialize elements */
- switch (b->flags & CAML_BA_KIND_MASK) {
- case CAML_BA_CHAR:
- case CAML_BA_SINT8:
- case CAML_BA_UINT8:
- caml_serialize_block_1(b->data, num_elts); break;
- case CAML_BA_SINT16:
- case CAML_BA_UINT16:
- caml_serialize_block_2(b->data, num_elts); break;
- case CAML_BA_FLOAT32:
- case CAML_BA_INT32:
- caml_serialize_block_4(b->data, num_elts); break;
- case CAML_BA_COMPLEX32:
- caml_serialize_block_4(b->data, num_elts * 2); break;
- case CAML_BA_FLOAT64:
- case CAML_BA_INT64:
- caml_serialize_block_8(b->data, num_elts); break;
- case CAML_BA_COMPLEX64:
- caml_serialize_block_8(b->data, num_elts * 2); break;
- case CAML_BA_CAML_INT:
- caml_ba_serialize_longarray(b->data, num_elts, -0x40000000, 0x3FFFFFFF);
- break;
- case CAML_BA_NATIVE_INT:
- caml_ba_serialize_longarray(b->data, num_elts, -0x80000000, 0x7FFFFFFF);
- break;
- }
- /* Compute required size in OCaml heap. Assumes struct caml_ba_array
- is exactly 4 + num_dims words */
- Assert(SIZEOF_BA_ARRAY == 4 * sizeof(value));
- *wsize_32 = (4 + b->num_dims) * 4;
- *wsize_64 = (4 + b->num_dims) * 8;
-}
-
-static void caml_ba_deserialize_longarray(void * dest, intnat num_elts)
-{
- int sixty = caml_deserialize_uint_1();
-#ifdef ARCH_SIXTYFOUR
- if (sixty) {
- caml_deserialize_block_8(dest, num_elts);
- } else {
- intnat * p, n;
- for (n = 0, p = dest; n < num_elts; n++, p++)
- *p = caml_deserialize_sint_4();
- }
-#else
- if (sixty)
- caml_deserialize_error("input_value: cannot read bigarray "
- "with 64-bit OCaml ints");
- caml_deserialize_block_4(dest, num_elts);
-#endif
-}
-
-uintnat caml_ba_deserialize(void * dst)
-{
- struct caml_ba_array * b = dst;
- int i, elt_size;
- uintnat num_elts;
-
- /* Read back header information */
- b->num_dims = caml_deserialize_uint_4();
- b->flags = caml_deserialize_uint_4() | CAML_BA_MANAGED;
- b->proxy = NULL;
- for (i = 0; i < b->num_dims; i++) b->dim[i] = caml_deserialize_uint_4();
- /* Compute total number of elements */
- num_elts = caml_ba_num_elts(b);
- /* Determine element size in bytes */
- if ((b->flags & CAML_BA_KIND_MASK) > CAML_BA_CHAR)
- caml_deserialize_error("input_value: bad bigarray kind");
- elt_size = caml_ba_element_size[b->flags & CAML_BA_KIND_MASK];
- /* Allocate room for data */
- b->data = malloc(elt_size * num_elts);
- if (b->data == NULL)
- caml_deserialize_error("input_value: out of memory for bigarray");
- /* Read data */
- switch (b->flags & CAML_BA_KIND_MASK) {
- case CAML_BA_CHAR:
- case CAML_BA_SINT8:
- case CAML_BA_UINT8:
- caml_deserialize_block_1(b->data, num_elts); break;
- case CAML_BA_SINT16:
- case CAML_BA_UINT16:
- caml_deserialize_block_2(b->data, num_elts); break;
- case CAML_BA_FLOAT32:
- case CAML_BA_INT32:
- caml_deserialize_block_4(b->data, num_elts); break;
- case CAML_BA_COMPLEX32:
- caml_deserialize_block_4(b->data, num_elts * 2); break;
- case CAML_BA_FLOAT64:
- case CAML_BA_INT64:
- caml_deserialize_block_8(b->data, num_elts); break;
- case CAML_BA_COMPLEX64:
- caml_deserialize_block_8(b->data, num_elts * 2); break;
- case CAML_BA_CAML_INT:
- case CAML_BA_NATIVE_INT:
- caml_ba_deserialize_longarray(b->data, num_elts); break;
- }
- /* PR#5516: use C99's flexible array types if possible */
- return SIZEOF_BA_ARRAY + b->num_dims * sizeof(intnat);
-}
-
/* Create / update proxy to indicate that b2 is a sub-array of b1 */
static void caml_ba_update_proxy(struct caml_ba_array * b1,
++ b1->proxy->refcount;
} else {
/* Otherwise, create proxy and attach it to both b1 and b2 */
- proxy = caml_stat_alloc(sizeof(struct caml_ba_proxy));
+ proxy = malloc(sizeof(struct caml_ba_proxy));
+ if (proxy == NULL) caml_raise_out_of_memory();
proxy->refcount = 2; /* original array + sub array */
proxy->data = b1->data;
proxy->size =
switch (b->flags & CAML_BA_KIND_MASK) {
default:
- Assert(0);
+ CAMLassert(0);
case CAML_BA_FLOAT32: {
float init = Double_val(vinit);
float * p;
#undef b
}
-
-/* Initialization */
-
-CAMLprim value caml_ba_init(value unit)
-{
- caml_register_custom_operations(&caml_ba_ops);
- return Val_unit;
-}
+++ /dev/null
-/**************************************************************************/
-/* */
-/* OCaml */
-/* */
-/* Manuel Serrano and Xavier Leroy, INRIA Rocquencourt */
-/* */
-/* Copyright 2000 Institut National de Recherche en Informatique et */
-/* en Automatique. */
-/* */
-/* All rights reserved. This file is distributed under the terms of */
-/* the GNU Lesser General Public License version 2.1, with the */
-/* special exception on linking described in the file LICENSE. */
-/* */
-/**************************************************************************/
-
-#define CAML_INTERNALS
-
-/* Needed (under Linux at least) to get pwrite's prototype in unistd.h.
- Must be defined before the first system .h is included. */
-#define _XOPEN_SOURCE 600
-
-#include <stddef.h>
-#include <string.h>
-#include "bigarray.h"
-#include "caml/custom.h"
-#include "caml/fail.h"
-#include "caml/io.h"
-#include "caml/mlvalues.h"
-#include "caml/sys.h"
-#include "caml/signals.h"
-
-extern int caml_ba_element_size[]; /* from bigarray_stubs.c */
-
-#include <errno.h>
-#ifdef HAS_UNISTD
-#include <unistd.h>
-#endif
-#ifdef HAS_MMAP
-#include <sys/types.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#endif
-
-#if defined(HAS_MMAP)
-
-#ifndef MAP_FAILED
-#define MAP_FAILED ((void *) -1)
-#endif
-
-/* [caml_grow_file] function contributed by Gerd Stolpmann (PR#5543). */
-
-static int caml_grow_file(int fd, file_offset size)
-{
- char c;
- int p;
-
- /* First use pwrite for growing - it is a conservative method, as it
- can never happen that we shrink by accident
- */
-#ifdef HAS_PWRITE
- c = 0;
- p = pwrite(fd, &c, 1, size - 1);
-#else
-
- /* Emulate pwrite with lseek. This should only be necessary on ancient
- systems nowadays
- */
- file_offset currpos;
- currpos = lseek(fd, 0, SEEK_CUR);
- if (currpos != -1) {
- p = lseek(fd, size - 1, SEEK_SET);
- if (p != -1) {
- c = 0;
- p = write(fd, &c, 1);
- if (p != -1)
- p = lseek(fd, currpos, SEEK_SET);
- }
- }
- else p=-1;
-#endif
-#ifdef HAS_TRUNCATE
- if (p == -1 && errno == ESPIPE) {
- /* Plan B. Check if at least ftruncate is possible. There are
- some non-seekable descriptor types that do not support pwrite
- but ftruncate, like shared memory. We never get into this case
- for real files, so there is no danger of truncating persistent
- data by accident
- */
- p = ftruncate(fd, size);
- }
-#endif
- return p;
-}
-
-
-CAMLprim value caml_ba_map_file(value vfd, value vkind, value vlayout,
- value vshared, value vdim, value vstart)
-{
- int fd, flags, major_dim, shared;
- intnat num_dims, i;
- intnat dim[CAML_BA_MAX_NUM_DIMS];
- file_offset startpos, file_size, data_size;
- struct stat st;
- uintnat array_size, page, delta;
- void * addr;
-
- fd = Int_val(vfd);
- flags = Caml_ba_kind_val(vkind) | Caml_ba_layout_val(vlayout);
- startpos = File_offset_val(vstart);
- num_dims = Wosize_val(vdim);
- major_dim = flags & CAML_BA_FORTRAN_LAYOUT ? num_dims - 1 : 0;
- /* Extract dimensions from OCaml array */
- num_dims = Wosize_val(vdim);
- if (num_dims < 1 || num_dims > CAML_BA_MAX_NUM_DIMS)
- caml_invalid_argument("Bigarray.mmap: bad number of dimensions");
- for (i = 0; i < num_dims; i++) {
- dim[i] = Long_val(Field(vdim, i));
- if (dim[i] == -1 && i == major_dim) continue;
- if (dim[i] < 0)
- caml_invalid_argument("Bigarray.create: negative dimension");
- }
- /* Determine file size. We avoid lseek here because it is fragile,
- and because some mappable file types do not support it
- */
- caml_enter_blocking_section();
- if (fstat(fd, &st) == -1) {
- caml_leave_blocking_section();
- caml_sys_error(NO_ARG);
- }
- file_size = st.st_size;
- /* Determine array size in bytes (or size of array without the major
- dimension if that dimension wasn't specified) */
- array_size = caml_ba_element_size[flags & CAML_BA_KIND_MASK];
- for (i = 0; i < num_dims; i++)
- if (dim[i] != -1) array_size *= dim[i];
- /* Check if the major dimension is unknown */
- if (dim[major_dim] == -1) {
- /* Determine major dimension from file size */
- if (file_size < startpos) {
- caml_leave_blocking_section();
- caml_failwith("Bigarray.mmap: file position exceeds file size");
- }
- data_size = file_size - startpos;
- dim[major_dim] = (uintnat) (data_size / array_size);
- array_size = dim[major_dim] * array_size;
- if (array_size != data_size) {
- caml_leave_blocking_section();
- caml_failwith("Bigarray.mmap: file size doesn't match array dimensions");
- }
- } else {
- /* Check that file is large enough, and grow it otherwise */
- if (file_size < startpos + array_size) {
- if (caml_grow_file(fd, startpos + array_size) == -1) { /* PR#5543 */
- caml_leave_blocking_section();
- caml_sys_error(NO_ARG);
- }
- }
- }
- /* Determine offset so that the mapping starts at the given file pos */
- page = sysconf(_SC_PAGESIZE);
- delta = (uintnat) startpos % page;
- /* Do the mmap */
- shared = Bool_val(vshared) ? MAP_SHARED : MAP_PRIVATE;
- if (array_size > 0)
- addr = mmap(NULL, array_size + delta, PROT_READ | PROT_WRITE,
- shared, fd, startpos - delta);
- else
- addr = NULL; /* PR#5463 - mmap fails on empty region */
- caml_leave_blocking_section();
- if (addr == (void *) MAP_FAILED) caml_sys_error(NO_ARG);
- addr = (void *) ((uintnat) addr + delta);
- /* Build and return the OCaml bigarray */
- return caml_ba_alloc(flags | CAML_BA_MAPPED_FILE, num_dims, addr, dim);
-}
-
-#else
-
-CAMLprim value caml_ba_map_file(value vfd, value vkind, value vlayout,
- value vshared, value vdim, value vpos)
-{
- caml_invalid_argument("Bigarray.map_file: not supported");
- return Val_unit;
-}
-
-#endif
-
-CAMLprim value caml_ba_map_file_bytecode(value * argv, int argn)
-{
- return caml_ba_map_file(argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5]);
-}
-
-void caml_ba_unmap_file(void * addr, uintnat len)
-{
-#if defined(HAS_MMAP)
- uintnat page = sysconf(_SC_PAGESIZE);
- uintnat delta = (uintnat) addr % page;
- if (len == 0) return; /* PR#5463 */
- addr = (void *)((uintnat)addr - delta);
- len = len + delta;
-#if defined(_POSIX_SYNCHRONIZED_IO)
- msync(addr, len, MS_ASYNC); /* PR#3571 */
-#endif
- munmap(addr, len);
-#endif
-}
+++ /dev/null
-/**************************************************************************/
-/* */
-/* OCaml */
-/* */
-/* Manuel Serrano and Xavier Leroy, INRIA Rocquencourt */
-/* */
-/* Copyright 2000 Institut National de Recherche en Informatique et */
-/* en Automatique. */
-/* */
-/* All rights reserved. This file is distributed under the terms of */
-/* the GNU Lesser General Public License version 2.1, with the */
-/* special exception on linking described in the file LICENSE. */
-/* */
-/**************************************************************************/
-
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
-#include "bigarray.h"
-#include "caml/alloc.h"
-#include "caml/custom.h"
-#include "caml/fail.h"
-#include "caml/mlvalues.h"
-#include "caml/sys.h"
-#include "unixsupport.h"
-
-extern int caml_ba_element_size[]; /* from bigarray_stubs.c */
-
-static void caml_ba_sys_error(void);
-
-#ifndef INVALID_SET_FILE_POINTER
-#define INVALID_SET_FILE_POINTER (-1)
-#endif
-
-static __int64 caml_ba_set_file_pointer(HANDLE h, __int64 dist, DWORD mode)
-{
- LARGE_INTEGER i;
- DWORD err;
-
- i.QuadPart = dist;
- i.LowPart = SetFilePointer(h, i.LowPart, &i.HighPart, mode);
- if (i.LowPart == INVALID_SET_FILE_POINTER) return -1;
- return i.QuadPart;
-}
-
-CAMLprim value caml_ba_map_file(value vfd, value vkind, value vlayout,
- value vshared, value vdim, value vstart)
-{
- HANDLE fd, fmap;
- int flags, major_dim, mode, perm;
- intnat num_dims, i;
- intnat dim[CAML_BA_MAX_NUM_DIMS];
- __int64 currpos, startpos, file_size, data_size;
- uintnat array_size, page, delta;
- char c;
- void * addr;
- LARGE_INTEGER li;
- SYSTEM_INFO sysinfo;
-
- fd = Handle_val(vfd);
- flags = Caml_ba_kind_val(vkind) | Caml_ba_layout_val(vlayout);
- startpos = Int64_val(vstart);
- num_dims = Wosize_val(vdim);
- major_dim = flags & CAML_BA_FORTRAN_LAYOUT ? num_dims - 1 : 0;
- /* Extract dimensions from OCaml array */
- num_dims = Wosize_val(vdim);
- if (num_dims < 1 || num_dims > CAML_BA_MAX_NUM_DIMS)
- caml_invalid_argument("Bigarray.mmap: bad number of dimensions");
- for (i = 0; i < num_dims; i++) {
- dim[i] = Long_val(Field(vdim, i));
- if (dim[i] == -1 && i == major_dim) continue;
- if (dim[i] < 0)
- caml_invalid_argument("Bigarray.create: negative dimension");
- }
- /* Determine file size */
- currpos = caml_ba_set_file_pointer(fd, 0, FILE_CURRENT);
- if (currpos == -1) caml_ba_sys_error();
- file_size = caml_ba_set_file_pointer(fd, 0, FILE_END);
- if (file_size == -1) caml_ba_sys_error();
- /* Determine array size in bytes (or size of array without the major
- dimension if that dimension wasn't specified) */
- array_size = caml_ba_element_size[flags & CAML_BA_KIND_MASK];
- for (i = 0; i < num_dims; i++)
- if (dim[i] != -1) array_size *= dim[i];
- /* Check if the first/last dimension is unknown */
- if (dim[major_dim] == -1) {
- /* Determine first/last dimension from file size */
- if (file_size < startpos)
- caml_failwith("Bigarray.mmap: file position exceeds file size");
- data_size = file_size - startpos;
- dim[major_dim] = (uintnat) (data_size / array_size);
- array_size = dim[major_dim] * array_size;
- if (array_size != data_size)
- caml_failwith("Bigarray.mmap: file size doesn't match array dimensions");
- }
- /* Restore original file position */
- caml_ba_set_file_pointer(fd, currpos, FILE_BEGIN);
- /* Create the file mapping */
- if (Bool_val(vshared)) {
- perm = PAGE_READWRITE;
- mode = FILE_MAP_WRITE;
- } else {
- perm = PAGE_READONLY; /* doesn't work under Win98 */
- mode = FILE_MAP_COPY;
- }
- li.QuadPart = startpos + array_size;
- fmap = CreateFileMapping(fd, NULL, perm, li.HighPart, li.LowPart, NULL);
- if (fmap == NULL) caml_ba_sys_error();
- /* Determine offset so that the mapping starts at the given file pos */
- GetSystemInfo(&sysinfo);
- delta = (uintnat) (startpos % sysinfo.dwAllocationGranularity);
- /* Map the mapping in memory */
- li.QuadPart = startpos - delta;
- addr =
- MapViewOfFile(fmap, mode, li.HighPart, li.LowPart, array_size + delta);
- if (addr == NULL) caml_ba_sys_error();
- addr = (void *) ((uintnat) addr + delta);
- /* Close the file mapping */
- CloseHandle(fmap);
- /* Build and return the OCaml bigarray */
- return caml_ba_alloc(flags | CAML_BA_MAPPED_FILE, num_dims, addr, dim);
-}
-
-CAMLprim value caml_ba_map_file_bytecode(value * argv, int argn)
-{
- return caml_ba_map_file(argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5]);
-}
-
-void caml_ba_unmap_file(void * addr, uintnat len)
-{
- SYSTEM_INFO sysinfo;
- uintnat delta;
-
- GetSystemInfo(&sysinfo);
- delta = (uintnat) addr % sysinfo.dwAllocationGranularity;
- UnmapViewOfFile((void *)((uintnat)addr - delta));
-}
-
-static void caml_ba_sys_error(void)
-{
- char buffer[512];
- DWORD errnum;
-
- errnum = GetLastError();
- if (!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- errnum,
- 0,
- buffer,
- sizeof(buffer),
- NULL))
- sprintf(buffer, "Unknown error %ld\n", errnum);
- caml_raise_sys_error(caml_copy_string(buffer));
-}
(** [true] if the program is native,
[false] if the program is bytecode. *)
-(** {6 Dynamic loading of compiled files} *)
+(** {1 Dynamic loading of compiled files} *)
val loadfile : string -> unit
(** In bytecode: load the given bytecode object file ([.cmo] file) or
(** In bytecode, the identity function. In native code, replace the last
extension with [.cmxs]. *)
-(** {6 Access control} *)
+(** {1 Access control} *)
val allow_only: string list -> unit
(** [allow_only units] restricts the compilation units that
not allowed. In native code, this function does nothing; object files
with external functions are always allowed to be dynamically linked. *)
-(** {6 Deprecated, low-level API for access control} *)
+(** {1 Deprecated, low-level API for access control} *)
(** @deprecated The functions [add_interfaces], [add_available_units]
and [clear_available_units] should not be used in new programs,
(** Empty the list of compilation units accessible to dynamically-linked
programs. *)
-(** {6 Deprecated, initialization} *)
+(** {1 Deprecated, initialization} *)
val init : unit -> unit
(** @deprecated Initialize the [Dynlink] library. This function is called
automatically when needed. *)
-(** {6 Error reporting} *)
+(** {1 Error reporting} *)
type linking_error =
Undefined_global of string
(**/**)
-(** {6 Internal functions} *)
+(** {1 Internal functions} *)
val digest_interface : string -> string list -> Digest.t
exception Error of error
(* Copied from config.ml to avoid dependencies *)
-let cmxs_magic_number = "Caml2007D002"
+let cmxs_magic_number = "Caml1999D022"
let dll_filename fname =
if Filename.is_implicit fname then Filename.concat (Sys.getcwd ()) fname
-color.o: color.c libgraph.h \
- \
- \
- \
- ../../byterun/caml/mlvalues.h ../../byterun/caml/compatibility.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
-
-draw.o: draw.c libgraph.h \
- \
- \
- \
- ../../byterun/caml/mlvalues.h ../../byterun/caml/compatibility.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- ../../byterun/caml/alloc.h
-dump_img.o: dump_img.c libgraph.h \
- \
- \
- \
- ../../byterun/caml/mlvalues.h ../../byterun/caml/compatibility.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h image.h \
- ../../byterun/caml/alloc.h ../../byterun/caml/memory.h
-events.o: events.c libgraph.h \
- \
- \
- \
- ../../byterun/caml/mlvalues.h ../../byterun/caml/compatibility.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- ../../byterun/caml/alloc.h ../../byterun/caml/signals.h
-fill.o: fill.c libgraph.h \
- \
- \
- \
- ../../byterun/caml/mlvalues.h ../../byterun/caml/compatibility.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- ../../byterun/caml/memory.h
-image.o: image.c libgraph.h \
- \
- \
- \
- ../../byterun/caml/mlvalues.h ../../byterun/caml/compatibility.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h image.h \
- ../../byterun/caml/alloc.h ../../byterun/caml/custom.h
-make_img.o: make_img.c libgraph.h \
- \
- \
- \
- ../../byterun/caml/mlvalues.h ../../byterun/caml/compatibility.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h image.h \
- ../../byterun/caml/memory.h
-open.o: open.c libgraph.h \
- \
- \
- \
- ../../byterun/caml/mlvalues.h ../../byterun/caml/compatibility.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- ../../byterun/caml/alloc.h ../../byterun/caml/callback.h \
- ../../byterun/caml/fail.h ../../byterun/caml/memory.h
-point_col.o: point_col.c libgraph.h \
- \
- \
- \
- ../../byterun/caml/mlvalues.h ../../byterun/caml/compatibility.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h
-sound.o: sound.c libgraph.h \
- \
- \
- \
- ../../byterun/caml/mlvalues.h ../../byterun/caml/compatibility.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h
-subwindow.o: subwindow.c libgraph.h \
- \
- \
- \
- ../../byterun/caml/mlvalues.h ../../byterun/caml/compatibility.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h
-text.o: text.c libgraph.h \
- \
- \
- \
- ../../byterun/caml/mlvalues.h ../../byterun/caml/compatibility.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- ../../byterun/caml/alloc.h
graphics.cmo : graphics.cmi
graphics.cmx : graphics.cmi
graphics.cmi :
include ../Makefile
depend:
- $(CC) -MM $(CFLAGS) *.c | sed -e 's, /[^ ]*\.h,,g' > .depend
+ $(CC) -MM $(CPPFLAGS) *.c | sed -e 's, /[^ ]*\.h,,g' > .depend
$(CAMLRUN) ../../tools/ocamldep -slash *.mli *.ml >> .depend
include .depend
(** Raised by the functions below when they encounter an error. *)
-(** {6 Initializations} *)
+(** {1 Initializations} *)
val open_graph : string -> unit
(** Show the graphics window or switch the screen to graphic mode.
16-bit integers, hence wrong clipping may occur with coordinates
below [-32768] or above [32676]. *)
-(** {6 Colors} *)
+(** {1 Colors} *)
type color = int
(** A color is specified by its R, G, B components. Each component
val magenta : color
-(** {6 Point and line drawing} *)
+(** {1 Point and line drawing} *)
external plot : int -> int -> unit = "caml_gr_plot"
(** Plot the given point with the current drawing color. *)
used when [set_line_width 1] is specified.
Raise [Invalid_argument] if the argument is negative. *)
-(** {6 Text drawing} *)
+(** {1 Text drawing} *)
external draw_char : char -> unit = "caml_gr_draw_char"
(** See {!Graphics.draw_string}.*)
the current font and size. *)
-(** {6 Filling} *)
+(** {1 Filling} *)
val fill_rect : int -> int -> int -> int -> unit
(** [fill_rect x y w h] fills the rectangle with lower left corner
parameters are the same as for {!Graphics.draw_circle}. *)
-(** {6 Images} *)
+(** {1 Images} *)
type image
(** The abstract type for images, in internal representation.
[img] are left unchanged. *)
-(** {6 Mouse and keyboard events} *)
+(** {1 Mouse and keyboard events} *)
type status =
{ mouse_x : int; (** X coordinate of the mouse *)
@since 4.01
*)
-(** {6 Mouse and keyboard polling} *)
+(** {1 Mouse and keyboard polling} *)
val mouse_pos : unit -> int * int
(** Return the position of the mouse cursor, relative to the
would not block. *)
-(** {6 Sound} *)
+(** {1 Sound} *)
external sound : int -> int -> unit = "caml_gr_sound"
(** [sound freq dur] plays a sound at frequency [freq] (in hertz)
for a duration [dur] (in milliseconds). *)
-(** {6 Double buffering} *)
+(** {1 Double buffering} *)
val auto_synchronize : bool -> unit
(** By default, drawing takes place both on the window displayed
#endif
CAMLnoreturn_start
-extern void caml_gr_fail(char *fmt, char *arg)
+extern void caml_gr_fail(const char *fmt, const char *arg)
CAMLnoreturn_end;
extern void caml_gr_check_open(void);
value caml_gr_open_graph(value arg)
{
char display_name[256], geometry_spec[64];
- char * p, * q;
+ const char * p;
+ char * q;
XSizeHints hints;
int ret;
XEvent event;
value caml_gr_set_window_title(value n)
{
if (window_name != NULL) caml_stat_free(window_name);
- window_name = caml_strdup(String_val(n));
+ window_name = caml_stat_strdup(String_val(n));
if (caml_gr_initialized) {
XStoreName(caml_gr_display, caml_gr_window.win, window_name);
XSetIconName(caml_gr_display, caml_gr_window.win, window_name);
static value * graphic_failure_exn = NULL;
-void caml_gr_fail(char *fmt, char *arg)
+void caml_gr_fail(const char *fmt, const char *arg)
{
char buffer[1024];
XFontStruct * caml_gr_font = NULL;
-static void caml_gr_get_font(char *fontname)
+static void caml_gr_get_font(const char *fontname)
{
XFontStruct * font = XLoadQueryFont(caml_gr_display, fontname);
if (font == NULL) caml_gr_fail("cannot find font %s", fontname);
return Val_unit;
}
-static void caml_gr_draw_text(char *txt, int len)
+static void caml_gr_draw_text(const char *txt, int len)
{
if (caml_gr_font == NULL) caml_gr_get_font(DEFAULT_FONT);
if (caml_gr_remember_modeflag)
+++ /dev/null
-bng.o: bng.c bng.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/compatibility.h \
- bng_amd64.c bng_digit.c
-bng_amd64.o: bng_amd64.c
-bng_arm64.o: bng_arm64.c
-bng_digit.o: bng_digit.c
-bng_ia32.o: bng_ia32.c
-bng_ppc.o: bng_ppc.c
-bng_sparc.o: bng_sparc.c
-nat_stubs.o: nat_stubs.c ../../byterun/caml/alloc.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/misc.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/custom.h ../../byterun/caml/intext.h \
- ../../byterun/caml/io.h ../../byterun/caml/fail.h \
- ../../byterun/caml/hash.h ../../byterun/caml/memory.h \
- ../../byterun/caml/gc.h ../../byterun/caml/major_gc.h \
- ../../byterun/caml/freelist.h ../../byterun/caml/minor_gc.h \
- ../../byterun/caml/address_class.h bng.h nat.h
-arith_flags.cmo : arith_flags.cmi
-arith_flags.cmx : arith_flags.cmi
-arith_flags.cmi :
-arith_status.cmo : arith_flags.cmi arith_status.cmi
-arith_status.cmx : arith_flags.cmx arith_status.cmi
-arith_status.cmi :
-big_int.cmo : nat.cmi int_misc.cmi big_int.cmi
-big_int.cmx : nat.cmx int_misc.cmx big_int.cmi
-big_int.cmi : nat.cmi
-int_misc.cmo : int_misc.cmi
-int_misc.cmx : int_misc.cmi
-int_misc.cmi :
-nat.cmo : int_misc.cmi nat.cmi
-nat.cmx : int_misc.cmx nat.cmi
-nat.cmi :
-num.cmo : ratio.cmi nat.cmi int_misc.cmi big_int.cmi arith_flags.cmi num.cmi
-num.cmx : ratio.cmx nat.cmx int_misc.cmx big_int.cmx arith_flags.cmx num.cmi
-num.cmi : ratio.cmi nat.cmi big_int.cmi
-ratio.cmo : nat.cmi int_misc.cmi big_int.cmi arith_flags.cmi ratio.cmi
-ratio.cmx : nat.cmx int_misc.cmx big_int.cmx arith_flags.cmx ratio.cmi
-ratio.cmi : nat.cmi big_int.cmi
+++ /dev/null
-bng.dobj: bng.c bng.h ../../byterun/config.h ../../config/m.h \
- ../../config/s.h ../../byterun/compatibility.h bng_ppc.c bng_digit.c
-bng_alpha.dobj: bng_alpha.c
-bng_amd64.dobj: bng_amd64.c
-bng_digit.dobj: bng_digit.c
-bng_ia32.dobj: bng_ia32.c
-bng_mips.dobj: bng_mips.c
-bng_ppc.dobj: bng_ppc.c
-bng_sparc.dobj: bng_sparc.c
-nat_stubs.dobj: nat_stubs.c ../../byterun/alloc.h \
- ../../byterun/compatibility.h ../../byterun/misc.h \
- ../../byterun/config.h ../../config/m.h ../../config/s.h \
- ../../byterun/mlvalues.h ../../byterun/custom.h ../../byterun/intext.h \
- ../../byterun/io.h ../../byterun/fix_code.h ../../byterun/fail.h \
- ../../byterun/memory.h ../../byterun/gc.h ../../byterun/major_gc.h \
- ../../byterun/freelist.h ../../byterun/minor_gc.h bng.h nat.h
-big_int.cmi: nat.cmi
-num.cmi: ratio.cmi nat.cmi big_int.cmi
-ratio.cmi: nat.cmi big_int.cmi
-arith_flags.cmo: arith_flags.cmi
-arith_flags.cmx: arith_flags.cmi
-arith_status.cmo: arith_flags.cmi arith_status.cmi
-arith_status.cmx: arith_flags.cmx arith_status.cmi
-big_int.cmo: nat.cmi int_misc.cmi big_int.cmi
-big_int.cmx: nat.cmx int_misc.cmx big_int.cmi
-int_misc.cmo: int_misc.cmi
-int_misc.cmx: int_misc.cmi
-nat.cmo: int_misc.cmi nat.cmi
-nat.cmx: int_misc.cmx nat.cmi
-num.cmo: ratio.cmi nat.cmi int_misc.cmi big_int.cmi arith_flags.cmi num.cmi
-num.cmx: ratio.cmx nat.cmx int_misc.cmx big_int.cmx arith_flags.cmx num.cmi
-ratio.cmo: nat.cmi int_misc.cmi big_int.cmi arith_flags.cmi ratio.cmi
-ratio.cmx: nat.cmx int_misc.cmx big_int.cmx arith_flags.cmx ratio.cmi
-bng.sobj: bng.c bng.h ../../byterun/config.h ../../config/m.h \
- ../../config/s.h ../../byterun/compatibility.h bng_ppc.c bng_digit.c
-bng_alpha.sobj: bng_alpha.c
-bng_amd64.sobj: bng_amd64.c
-bng_digit.sobj: bng_digit.c
-bng_ia32.sobj: bng_ia32.c
-bng_mips.sobj: bng_mips.c
-bng_ppc.sobj: bng_ppc.c
-bng_sparc.sobj: bng_sparc.c
-nat_stubs.sobj: nat_stubs.c ../../byterun/alloc.h \
- ../../byterun/compatibility.h ../../byterun/misc.h \
- ../../byterun/config.h ../../config/m.h ../../config/s.h \
- ../../byterun/mlvalues.h ../../byterun/custom.h ../../byterun/intext.h \
- ../../byterun/io.h ../../byterun/fix_code.h ../../byterun/fail.h \
- ../../byterun/memory.h ../../byterun/gc.h ../../byterun/major_gc.h \
- ../../byterun/freelist.h ../../byterun/minor_gc.h bng.h nat.h
-big_int.cmi: nat.cmi
-num.cmi: ratio.cmi nat.cmi big_int.cmi
-ratio.cmi: nat.cmi big_int.cmi
-arith_flags.cmo: arith_flags.cmi
-arith_flags.cmx: arith_flags.cmi
-arith_status.cmo: arith_flags.cmi arith_status.cmi
-arith_status.cmx: arith_flags.cmx arith_status.cmi
-big_int.cmo: nat.cmi int_misc.cmi big_int.cmi
-big_int.cmx: nat.cmx int_misc.cmx big_int.cmi
-int_misc.cmo: int_misc.cmi
-int_misc.cmx: int_misc.cmi
-nat.cmo: int_misc.cmi nat.cmi
-nat.cmx: int_misc.cmx nat.cmi
-num.cmo: ratio.cmi nat.cmi int_misc.cmi big_int.cmi arith_flags.cmi num.cmi
-num.cmx: ratio.cmx nat.cmx int_misc.cmx big_int.cmx arith_flags.cmx num.cmi
-ratio.cmo: nat.cmi int_misc.cmi big_int.cmi arith_flags.cmi ratio.cmi
-ratio.cmx: nat.cmx int_misc.cmx big_int.cmx arith_flags.cmx ratio.cmi
+++ /dev/null
-#**************************************************************************
-#* *
-#* OCaml *
-#* *
-#* Xavier Leroy, projet Cristal, INRIA Rocquencourt *
-#* *
-#* Copyright 1999 Institut National de Recherche en Informatique et *
-#* en Automatique. *
-#* *
-#* All rights reserved. This file is distributed under the terms of *
-#* the GNU Lesser General Public License version 2.1, with the *
-#* special exception on linking described in the file LICENSE. *
-#* *
-#**************************************************************************
-
-# Makefile for the "num" (exact rational arithmetic) library
-
-LIBNAME=nums
-EXTRACFLAGS=-DBNG_ARCH_$(BNG_ARCH) -DBNG_ASM_LEVEL=$(BNG_ASM_LEVEL)
-CAMLOBJS=int_misc.cmo nat.cmo big_int.cmo arith_flags.cmo \
- ratio.cmo num.cmo arith_status.cmo
-CMIFILES=big_int.cmi nat.cmi num.cmi ratio.cmi arith_status.cmi
-COBJS=bng.$(O) nat_stubs.$(O)
-
-include ../Makefile
-
-clean::
- rm -f *~
-
-bng.$(O): bng.h bng_digit.c \
- bng_amd64.c bng_ia32.c bng_ppc.c bng_sparc.c
-
-# At the moment, the following rule only works with gcc
-# It is not a big deal since the .depend file it produces is stored
-# in the repository
-depend:
- $(CC) -MM $(CFLAGS) *.c > .depend
- $(CAMLRUN) $(ROOTDIR)/tools/ocamldep -slash *.mli *.ml >> .depend
-
-ifeq "$(TOOLCHAIN)" "msvc"
-
-.depend.nt: .depend
- sed -e 's/\.o/.$(O)/g' $< > $@
-
-include .depend.nt
-else
-include .depend
-endif
+++ /dev/null
-#**************************************************************************
-#* *
-#* OCaml *
-#* *
-#* Xavier Leroy, projet Cristal, INRIA Rocquencourt *
-#* *
-#* Copyright 1999 Institut National de Recherche en Informatique et *
-#* en Automatique. *
-#* *
-#* All rights reserved. This file is distributed under the terms of *
-#* the GNU Lesser General Public License version 2.1, with the *
-#* special exception on linking described in the file LICENSE. *
-#* *
-#**************************************************************************
-
-include Makefile
+++ /dev/null
-The "libnum" library implements exact-precision arithmetic on
-big integers and on rationals.
-
-This library is derived from Valerie Menissie-Morain's implementation
-of rational arithmetic for Caml V3.1 (INRIA). Xavier Leroy (INRIA)
-did the Caml Light port. Victor Manuel Gulias Fernandez did the
-initial Caml Special Light port. Pierre Weis did most of the
-maintenance and bug fixing.
-
-Initially, the low-level big integer operations were provided by the
-BigNum package developed by Bernard Serpette, Jean Vuillemin and
-Jean-Claude Herve (INRIA and Digital PRL). License issues forced us to
-replace the BigNum package. The current implementation of low-level
-big integer operations is due to Xavier Leroy.
-
-This library is documented in "The CAML Numbers Reference Manual" by
-Valerie Menissier-Morain, technical report 141, INRIA, july 1992,
-available at ftp://ftp.inria.fr/INRIA/publication/RT/RT-0141.ps.gz
-
-
-USAGE:
-
-To use the bignum library from your programs, just do
-
- ocamlc <options> nums.cma <.cmo and .ml files>
-or
- ocamlopt <options> nums.cmxa <.cmx and .ml files>
-
-for the linking phase.
-
-If you'd like to have the bignum functions available at toplevel, do
-
- ocamlmktop -o ocamltopnum <options> nums.cma <.cmo and .ml files>
- ./ocamltopnum
-
-As an example, try:
-
- open Num;;
- let rec fact n =
- if n = 0 then Int 1 else mult_num (num_of_int n) (fact(n-1));;
- string_of_num(fact 1000);;
-
-
-PROCESSOR-SPECIFIC OPTIMIZATIONS:
-
-When compiled with GCC, the low-level primitives use "inline extended asm"
-to exploit useful features of the target processor (additions and
-subtractions with carry; double-width multiplication, division).
-Here are the processors for which such optimizations are available:
- IA32 (x86) (carry, dwmult, dwdiv, 64-bit ops with SSE2 if available)
- AMD64 (Opteron) (carry, dwmult, dwdiv)
- PowerPC (carry, dwmult)
- Alpha (dwmult)
- SPARC (carry, dwmult, dwdiv)
- MIPS (dwmult)
+++ /dev/null
-(**************************************************************************)
-(* *)
-(* OCaml *)
-(* *)
-(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *)
-(* *)
-(* Copyright 1996 Institut National de Recherche en Informatique et *)
-(* en Automatique. *)
-(* *)
-(* All rights reserved. This file is distributed under the terms of *)
-(* the GNU Lesser General Public License version 2.1, with the *)
-(* special exception on linking described in the file LICENSE. *)
-(* *)
-(**************************************************************************)
-
-let error_when_null_denominator_flag = ref true;;
-
-let normalize_ratio_flag = ref false;;
-
-let normalize_ratio_when_printing_flag = ref true;;
-
-let floating_precision = ref 12;;
-
-let approx_printing_flag = ref false;;
+++ /dev/null
-(**************************************************************************)
-(* *)
-(* OCaml *)
-(* *)
-(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *)
-(* *)
-(* Copyright 1996 Institut National de Recherche en Informatique et *)
-(* en Automatique. *)
-(* *)
-(* All rights reserved. This file is distributed under the terms of *)
-(* the GNU Lesser General Public License version 2.1, with the *)
-(* special exception on linking described in the file LICENSE. *)
-(* *)
-(**************************************************************************)
-
-val error_when_null_denominator_flag : bool ref
-val normalize_ratio_flag : bool ref
-val normalize_ratio_when_printing_flag : bool ref
-val floating_precision : int ref
-val approx_printing_flag : bool ref
+++ /dev/null
-(**************************************************************************)
-(* *)
-(* OCaml *)
-(* *)
-(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *)
-(* *)
-(* Copyright 1996 Institut National de Recherche en Informatique et *)
-(* en Automatique. *)
-(* *)
-(* All rights reserved. This file is distributed under the terms of *)
-(* the GNU Lesser General Public License version 2.1, with the *)
-(* special exception on linking described in the file LICENSE. *)
-(* *)
-(**************************************************************************)
-
-open Arith_flags;;
-
-let get_error_when_null_denominator () =
- !error_when_null_denominator_flag
-and set_error_when_null_denominator choice =
- error_when_null_denominator_flag := choice;;
-
-let get_normalize_ratio () = !normalize_ratio_flag
-and set_normalize_ratio choice = normalize_ratio_flag := choice;;
-
-let get_normalize_ratio_when_printing () =
- !normalize_ratio_when_printing_flag
-and set_normalize_ratio_when_printing choice =
- normalize_ratio_when_printing_flag := choice;;
-
-let get_floating_precision () = !floating_precision
-and set_floating_precision i = floating_precision := i;;
-
-let get_approx_printing () = !approx_printing_flag
-and set_approx_printing b = approx_printing_flag := b;;
-
-let arith_print_string s = print_string s; print_string " --> ";;
-
-let arith_print_bool = function
- true -> print_string "ON"
-| _ -> print_string "OFF"
-;;
-
-let arith_status () =
- print_newline ();
-
- arith_print_string
- "Normalization during computation";
- arith_print_bool (get_normalize_ratio ());
- print_newline ();
- print_string " (returned by get_normalize_ratio ())";
- print_newline ();
- print_string " (modifiable with set_normalize_ratio <your choice>)";
- print_newline ();
- print_newline ();
-
- arith_print_string
- "Normalization when printing";
- arith_print_bool (get_normalize_ratio_when_printing ());
- print_newline ();
- print_string
- " (returned by get_normalize_ratio_when_printing ())";
- print_newline ();
- print_string
- " (modifiable with set_normalize_ratio_when_printing <your choice>)";
- print_newline ();
- print_newline ();
-
- arith_print_string
- "Floating point approximation when printing rational numbers";
- arith_print_bool (get_approx_printing ());
- print_newline ();
- print_string
- " (returned by get_approx_printing ())";
- print_newline ();
- print_string
- " (modifiable with set_approx_printing <your choice>)";
- print_newline ();
- (if (get_approx_printing ())
- then (print_string " Default precision = ";
- print_int (get_floating_precision ());
- print_newline ();
- print_string " (returned by get_floating_precision ())";
- print_newline ();
- print_string
- " (modifiable with set_floating_precision <your choice>)";
- print_newline ();
- print_newline ())
- else print_newline());
-
- arith_print_string
- "Error when a rational denominator is null";
- arith_print_bool (get_error_when_null_denominator ());
- print_newline ();
- print_string " (returned by get_error_when_null_denominator ())";
- print_newline ();
- print_string
- " (modifiable with set_error_when_null_denominator <your choice>)";
- print_newline ()
-;;
+++ /dev/null
-(**************************************************************************)
-(* *)
-(* OCaml *)
-(* *)
-(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *)
-(* *)
-(* Copyright 1996 Institut National de Recherche en Informatique et *)
-(* en Automatique. *)
-(* *)
-(* All rights reserved. This file is distributed under the terms of *)
-(* the GNU Lesser General Public License version 2.1, with the *)
-(* special exception on linking described in the file LICENSE. *)
-(* *)
-(**************************************************************************)
-
-(** Flags that control rational arithmetic. *)
-
-val arith_status: unit -> unit
- (** Print the current status of the arithmetic flags. *)
-
-val get_error_when_null_denominator : unit -> bool
-(** See {!Arith_status.set_error_when_null_denominator}.*)
-
-val set_error_when_null_denominator : bool -> unit
- (** Get or set the flag [null_denominator]. When on, attempting to
- create a rational with a null denominator raises an exception.
- When off, rationals with null denominators are accepted.
- Initially: on. *)
-
-val get_normalize_ratio : unit -> bool
-(** See {!Arith_status.set_normalize_ratio}.*)
-
-val set_normalize_ratio : bool -> unit
- (** Get or set the flag [normalize_ratio]. When on, rational
- numbers are normalized after each operation. When off,
- rational numbers are not normalized until printed.
- Initially: off. *)
-
-val get_normalize_ratio_when_printing : unit -> bool
-(** See {!Arith_status.set_normalize_ratio_when_printing}.*)
-
-val set_normalize_ratio_when_printing : bool -> unit
- (** Get or set the flag [normalize_ratio_when_printing].
- When on, rational numbers are normalized before being printed.
- When off, rational numbers are printed as is, without normalization.
- Initially: on. *)
-
-val get_approx_printing : unit -> bool
-(** See {!Arith_status.set_approx_printing}.*)
-
-val set_approx_printing : bool -> unit
- (** Get or set the flag [approx_printing].
- When on, rational numbers are printed as a decimal approximation.
- When off, rational numbers are printed as a fraction.
- Initially: off. *)
-
-val get_floating_precision : unit -> int
-(** See {!Arith_status.set_floating_precision}.*)
-
-val set_floating_precision : int -> unit
- (** Get or set the parameter [floating_precision].
- This parameter is the number of digits displayed when
- [approx_printing] is on.
- Initially: 12. *)
+++ /dev/null
-(**************************************************************************)
-(* *)
-(* OCaml *)
-(* *)
-(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *)
-(* *)
-(* Copyright 1996 Institut National de Recherche en Informatique et *)
-(* en Automatique. *)
-(* *)
-(* All rights reserved. This file is distributed under the terms of *)
-(* the GNU Lesser General Public License version 2.1, with the *)
-(* special exception on linking described in the file LICENSE. *)
-(* *)
-(**************************************************************************)
-
-open Int_misc
-open Nat
-
-type big_int =
- { sign : int;
- abs_value : nat }
-
-let create_big_int sign nat =
- if sign = 1 || sign = -1 ||
- (sign = 0 &&
- is_zero_nat nat 0 (num_digits_nat nat 0 (length_nat nat)))
- then { sign = sign;
- abs_value = nat }
- else invalid_arg "create_big_int"
-
-(* Sign of a big_int *)
-let sign_big_int bi = bi.sign
-
-let zero_big_int =
- { sign = 0;
- abs_value = make_nat 1 }
-
-let unit_big_int =
- { sign = 1;
- abs_value = nat_of_int 1 }
-
-(* Number of digits in a big_int *)
-let num_digits_big_int bi =
- num_digits_nat (bi.abs_value) 0 (length_nat bi.abs_value)
-
-(* Number of bits in a big_int *)
-let num_bits_big_int bi =
- let nd = num_digits_nat (bi.abs_value) 0 (length_nat bi.abs_value) in
- (* nd = 1 if bi = 0 *)
- let lz = num_leading_zero_bits_in_digit bi.abs_value (nd - 1) in
- (* lz = length_of_digit if bi = 0 *)
- nd * length_of_digit - lz
- (* = 0 if bi = 0 *)
-
-(* Opposite of a big_int *)
-let minus_big_int bi =
- { sign = - bi.sign;
- abs_value = copy_nat (bi.abs_value) 0 (num_digits_big_int bi)}
-
-(* Absolute value of a big_int *)
-let abs_big_int bi =
- { sign = if bi.sign = 0 then 0 else 1;
- abs_value = copy_nat (bi.abs_value) 0 (num_digits_big_int bi)}
-
-(* Comparison operators on big_int *)
-
-(*
- compare_big_int (bi, bi2) = sign of (bi-bi2)
- i.e. 1 if bi > bi2
- 0 if bi = bi2
- -1 if bi < bi2
-*)
-let compare_big_int bi1 bi2 =
- if bi1.sign = 0 && bi2.sign = 0 then 0
- else if bi1.sign < bi2.sign then -1
- else if bi1.sign > bi2.sign then 1
- else if bi1.sign = 1 then
- compare_nat (bi1.abs_value) 0 (num_digits_big_int bi1)
- (bi2.abs_value) 0 (num_digits_big_int bi2)
- else
- compare_nat (bi2.abs_value) 0 (num_digits_big_int bi2)
- (bi1.abs_value) 0 (num_digits_big_int bi1)
-
-let eq_big_int bi1 bi2 = compare_big_int bi1 bi2 = 0
-and le_big_int bi1 bi2 = compare_big_int bi1 bi2 <= 0
-and ge_big_int bi1 bi2 = compare_big_int bi1 bi2 >= 0
-and lt_big_int bi1 bi2 = compare_big_int bi1 bi2 < 0
-and gt_big_int bi1 bi2 = compare_big_int bi1 bi2 > 0
-
-let max_big_int bi1 bi2 = if lt_big_int bi1 bi2 then bi2 else bi1
-and min_big_int bi1 bi2 = if gt_big_int bi1 bi2 then bi2 else bi1
-
-(* Operations on big_int *)
-
-let pred_big_int bi =
- match bi.sign with
- 0 -> { sign = -1; abs_value = nat_of_int 1}
- | 1 -> let size_bi = num_digits_big_int bi in
- let copy_bi = copy_nat (bi.abs_value) 0 size_bi in
- ignore (decr_nat copy_bi 0 size_bi 0);
- { sign = if is_zero_nat copy_bi 0 size_bi then 0 else 1;
- abs_value = copy_bi }
- | _ -> let size_bi = num_digits_big_int bi in
- let size_res = succ (size_bi) in
- let copy_bi = create_nat (size_res) in
- blit_nat copy_bi 0 (bi.abs_value) 0 size_bi;
- set_digit_nat copy_bi size_bi 0;
- ignore (incr_nat copy_bi 0 size_res 1);
- { sign = -1;
- abs_value = copy_bi }
-
-let succ_big_int bi =
- match bi.sign with
- 0 -> {sign = 1; abs_value = nat_of_int 1}
- | -1 -> let size_bi = num_digits_big_int bi in
- let copy_bi = copy_nat (bi.abs_value) 0 size_bi in
- ignore (decr_nat copy_bi 0 size_bi 0);
- { sign = if is_zero_nat copy_bi 0 size_bi then 0 else -1;
- abs_value = copy_bi }
- | _ -> let size_bi = num_digits_big_int bi in
- let size_res = succ (size_bi) in
- let copy_bi = create_nat (size_res) in
- blit_nat copy_bi 0 (bi.abs_value) 0 size_bi;
- set_digit_nat copy_bi size_bi 0;
- ignore (incr_nat copy_bi 0 size_res 1);
- { sign = 1;
- abs_value = copy_bi }
-
-let add_big_int bi1 bi2 =
- let size_bi1 = num_digits_big_int bi1
- and size_bi2 = num_digits_big_int bi2 in
- if bi1.sign = bi2.sign
- then (* Add absolute values if signs are the same *)
- { sign = bi1.sign;
- abs_value =
- match compare_nat (bi1.abs_value) 0 size_bi1
- (bi2.abs_value) 0 size_bi2 with
- -1 -> let res = create_nat (succ size_bi2) in
- (blit_nat res 0 (bi2.abs_value) 0 size_bi2;
- set_digit_nat res size_bi2 0;
- ignore
- (add_nat res 0 (succ size_bi2)
- (bi1.abs_value) 0 size_bi1 0);
- res)
- |_ -> let res = create_nat (succ size_bi1) in
- (blit_nat res 0 (bi1.abs_value) 0 size_bi1;
- set_digit_nat res size_bi1 0;
- ignore (add_nat res 0 (succ size_bi1)
- (bi2.abs_value) 0 size_bi2 0);
- res)}
-
- else (* Subtract absolute values if signs are different *)
- match compare_nat (bi1.abs_value) 0 size_bi1
- (bi2.abs_value) 0 size_bi2 with
- 0 -> zero_big_int
- | 1 -> { sign = bi1.sign;
- abs_value =
- let res = copy_nat (bi1.abs_value) 0 size_bi1 in
- (ignore (sub_nat res 0 size_bi1
- (bi2.abs_value) 0 size_bi2 1);
- res) }
- | _ -> { sign = bi2.sign;
- abs_value =
- let res = copy_nat (bi2.abs_value) 0 size_bi2 in
- (ignore (sub_nat res 0 size_bi2
- (bi1.abs_value) 0 size_bi1 1);
- res) }
-
-(* Coercion with int type *)
-let big_int_of_int i =
- { sign = sign_int i;
- abs_value =
- let res = (create_nat 1)
- in (if i = monster_int
- then (set_digit_nat res 0 biggest_int;
- ignore (incr_nat res 0 1 1))
- else set_digit_nat res 0 (abs i));
- res }
-
-let add_int_big_int i bi = add_big_int (big_int_of_int i) bi
-
-let sub_big_int bi1 bi2 = add_big_int bi1 (minus_big_int bi2)
-
-(* Returns i * bi *)
-let mult_int_big_int i bi =
- let size_bi = num_digits_big_int bi in
- let size_res = succ size_bi in
- if i = monster_int
- then let res = create_nat size_res in
- blit_nat res 0 (bi.abs_value) 0 size_bi;
- set_digit_nat res size_bi 0;
- ignore (mult_digit_nat res 0 size_res (bi.abs_value) 0 size_bi
- (nat_of_int biggest_int) 0);
- { sign = - (sign_big_int bi);
- abs_value = res }
- else let res = make_nat (size_res) in
- ignore (mult_digit_nat res 0 size_res (bi.abs_value) 0 size_bi
- (nat_of_int (abs i)) 0);
- { sign = (sign_int i) * (sign_big_int bi);
- abs_value = res }
-
-let mult_big_int bi1 bi2 =
- let size_bi1 = num_digits_big_int bi1
- and size_bi2 = num_digits_big_int bi2 in
- let size_res = size_bi1 + size_bi2 in
- let res = make_nat (size_res) in
- { sign = bi1.sign * bi2.sign;
- abs_value =
- if size_bi2 > size_bi1
- then (ignore (mult_nat res 0 size_res (bi2.abs_value) 0 size_bi2
- (bi1.abs_value) 0 size_bi1);res)
- else (ignore (mult_nat res 0 size_res (bi1.abs_value) 0 size_bi1
- (bi2.abs_value) 0 size_bi2);res) }
-
-(* (quotient, remainder ) of the euclidian division of 2 big_int *)
-let quomod_big_int bi1 bi2 =
- if bi2.sign = 0 then raise Division_by_zero
- else
- let size_bi1 = num_digits_big_int bi1
- and size_bi2 = num_digits_big_int bi2 in
- match compare_nat (bi1.abs_value) 0 size_bi1
- (bi2.abs_value) 0 size_bi2 with
- -1 -> (* 1/2 -> 0, remains 1, -1/2 -> -1, remains 1 *)
- (* 1/-2 -> 0, remains 1, -1/-2 -> 1, remains 1 *)
- if bi1.sign >= 0 then
- (big_int_of_int 0, bi1)
- else if bi2.sign >= 0 then
- (big_int_of_int(-1), add_big_int bi2 bi1)
- else
- (big_int_of_int 1, sub_big_int bi1 bi2)
- | 0 -> (big_int_of_int (bi1.sign * bi2.sign), zero_big_int)
- | _ -> let bi1_negatif = bi1.sign = -1 in
- let size_q =
- if bi1_negatif
- then succ (max (succ (size_bi1 - size_bi2)) 1)
- else max (succ (size_bi1 - size_bi2)) 1
- and size_r = succ (max size_bi1 size_bi2)
- (* r is long enough to contain both quotient and remainder *)
- (* of the euclidian division *)
- in
- (* set up quotient, remainder *)
- let q = create_nat size_q
- and r = create_nat size_r in
- blit_nat r 0 (bi1.abs_value) 0 size_bi1;
- set_to_zero_nat r size_bi1 (size_r - size_bi1);
-
- (* do the division of |bi1| by |bi2|
- - at the beginning, r contains |bi1|
- - at the end, r contains
- * in the size_bi2 least significant digits, the remainder
- * in the size_r-size_bi2 most significant digits, the quotient
- note the conditions for application of div_nat are verified here
- *)
- div_nat r 0 size_r (bi2.abs_value) 0 size_bi2;
-
- (* separate quotient and remainder *)
- blit_nat q 0 r size_bi2 (size_r - size_bi2);
- let not_null_mod = not (is_zero_nat r 0 size_bi2) in
-
- (* correct the signs, adjusting the quotient and remainder *)
- if bi1_negatif && not_null_mod
- then
- (* bi1<0, r>0, noting r for (r, size_bi2) the remainder, *)
- (* we have |bi1|=q * |bi2| + r with 0 < r < |bi2|, *)
- (* thus -bi1 = q * |bi2| + r *)
- (* and bi1 = (-q) * |bi2| + (-r) with -|bi2| < (-r) < 0 *)
- (* thus bi1 = -(q+1) * |bi2| + (|bi2|-r) *)
- (* with 0 < (|bi2|-r) < |bi2| *)
- (* so the quotient has for sign the opposite of the bi2'one *)
- (* and for value q+1 *)
- (* and the remainder is strictly positive *)
- (* has for value |bi2|-r *)
- (let new_r = copy_nat (bi2.abs_value) 0 size_bi2 in
- (* new_r contains (r, size_bi2) the remainder *)
- { sign = - bi2.sign;
- abs_value = (set_digit_nat q (pred size_q) 0;
- ignore (incr_nat q 0 size_q 1); q) },
- { sign = 1;
- abs_value =
- (ignore (sub_nat new_r 0 size_bi2 r 0 size_bi2 1);
- new_r) })
- else
- (if bi1_negatif then set_digit_nat q (pred size_q) 0;
- { sign = if is_zero_nat q 0 size_q
- then 0
- else bi1.sign * bi2.sign;
- abs_value = q },
- { sign = if not_null_mod then 1 else 0;
- abs_value = copy_nat r 0 size_bi2 })
-
-let div_big_int bi1 bi2 = fst (quomod_big_int bi1 bi2)
-and mod_big_int bi1 bi2 = snd (quomod_big_int bi1 bi2)
-
-let gcd_big_int bi1 bi2 =
- let size_bi1 = num_digits_big_int bi1
- and size_bi2 = num_digits_big_int bi2 in
- if is_zero_nat (bi1.abs_value) 0 size_bi1 then abs_big_int bi2
- else if is_zero_nat (bi2.abs_value) 0 size_bi2 then
- { sign = 1;
- abs_value = bi1.abs_value }
- else
- { sign = 1;
- abs_value =
- match compare_nat (bi1.abs_value) 0 size_bi1
- (bi2.abs_value) 0 size_bi2 with
- 0 -> bi1.abs_value
- | 1 ->
- let res = copy_nat (bi1.abs_value) 0 size_bi1 in
- let len =
- gcd_nat res 0 size_bi1 (bi2.abs_value) 0 size_bi2 in
- copy_nat res 0 len
- | _ ->
- let res = copy_nat (bi2.abs_value) 0 size_bi2 in
- let len =
- gcd_nat res 0 size_bi2 (bi1.abs_value) 0 size_bi1 in
- copy_nat res 0 len
- }
-
-(* Coercion operators *)
-
-let monster_big_int = big_int_of_int monster_int;;
-
-let monster_nat = monster_big_int.abs_value;;
-
-let is_int_big_int bi =
- num_digits_big_int bi == 1 &&
- match compare_nat bi.abs_value 0 1 monster_nat 0 1 with
- | 0 -> bi.sign == -1
- | -1 -> true
- | _ -> false;;
-
-let int_of_big_int bi =
- try let n = int_of_nat bi.abs_value in
- if bi.sign = -1 then - n else n
- with Failure _ ->
- if eq_big_int bi monster_big_int then monster_int
- else failwith "int_of_big_int";;
-
-let int_of_big_int_opt bi =
- try Some (int_of_big_int bi) with Failure _ -> None
-
-let big_int_of_nativeint i =
- if i = 0n then
- zero_big_int
- else if i > 0n then begin
- let res = create_nat 1 in
- set_digit_nat_native res 0 i;
- { sign = 1; abs_value = res }
- end else begin
- let res = create_nat 1 in
- set_digit_nat_native res 0 (Nativeint.neg i);
- { sign = -1; abs_value = res }
- end
-
-let nativeint_of_big_int bi =
- if num_digits_big_int bi > 1 then failwith "nativeint_of_big_int";
- let i = nth_digit_nat_native bi.abs_value 0 in
- if bi.sign >= 0 then
- if i >= 0n then i else failwith "nativeint_of_big_int"
- else
- if i >= 0n || i = Nativeint.min_int
- then Nativeint.neg i
- else failwith "nativeint_of_big_int"
-
-let nativeint_of_big_int_opt bi =
- try Some (nativeint_of_big_int bi) with Failure _ -> None
-
-let big_int_of_int32 i = big_int_of_nativeint (Nativeint.of_int32 i)
-
-let int32_of_big_int bi =
- let i = nativeint_of_big_int bi in
- if i <= 0x7FFF_FFFFn && i >= -0x8000_0000n
- then Nativeint.to_int32 i
- else failwith "int32_of_big_int"
-
-let int32_of_big_int_opt bi =
- try Some (int32_of_big_int bi) with Failure _ -> None
-
-let big_int_of_int64 i =
- if Sys.word_size = 64 then
- big_int_of_nativeint (Int64.to_nativeint i)
- else begin
- let (sg, absi) =
- if i = 0L then (0, 0L)
- else if i > 0L then (1, i)
- else (-1, Int64.neg i) in
- let res = create_nat 2 in
- set_digit_nat_native res 0 (Int64.to_nativeint absi);
- set_digit_nat_native res 1 (Int64.to_nativeint (Int64.shift_right absi 32));
- { sign = sg; abs_value = res }
- end
-
-let int64_of_big_int bi =
- if Sys.word_size = 64 then
- Int64.of_nativeint (nativeint_of_big_int bi)
- else begin
- let i =
- match num_digits_big_int bi with
- | 1 -> Int64.logand
- (Int64.of_nativeint (nth_digit_nat_native bi.abs_value 0))
- 0xFFFFFFFFL
- | 2 -> Int64.logor
- (Int64.logand
- (Int64.of_nativeint (nth_digit_nat_native bi.abs_value 0))
- 0xFFFFFFFFL)
- (Int64.shift_left
- (Int64.of_nativeint (nth_digit_nat_native bi.abs_value 1))
- 32)
- | _ -> failwith "int64_of_big_int" in
- if bi.sign >= 0 then
- if i >= 0L then i else failwith "int64_of_big_int"
- else
- if i >= 0L || i = Int64.min_int
- then Int64.neg i
- else failwith "int64_of_big_int"
- end
-
-let int64_of_big_int_opt bi =
- try Some (int64_of_big_int bi) with Failure _ -> None
-
-(* Coercion with nat type *)
-let nat_of_big_int bi =
- if bi.sign = -1
- then failwith "nat_of_big_int"
- else copy_nat (bi.abs_value) 0 (num_digits_big_int bi)
-
-let sys_big_int_of_nat nat off len =
- let length = num_digits_nat nat off len in
- { sign = if is_zero_nat nat off length then 0 else 1;
- abs_value = copy_nat nat off length }
-
-let big_int_of_nat nat =
- sys_big_int_of_nat nat 0 (length_nat nat)
-
-(* Coercion with string type *)
-
-let string_of_big_int bi =
- if bi.sign = -1
- then "-" ^ string_of_nat bi.abs_value
- else string_of_nat bi.abs_value
-
-
-let sys_big_int_of_string_aux s ofs len sgn base =
- if len < 1 then failwith "sys_big_int_of_string";
- let n = sys_nat_of_string base s ofs len in
- if is_zero_nat n 0 (length_nat n) then zero_big_int
- else {sign = sgn; abs_value = n}
-;;
-
-let sys_big_int_of_string_base s ofs len sgn =
- if len < 1 then failwith "sys_big_int_of_string";
- if len < 2 then sys_big_int_of_string_aux s ofs len sgn 10
- else
- match (s.[ofs], s.[ofs+1]) with
- | ('0', 'x') | ('0', 'X') ->
- sys_big_int_of_string_aux s (ofs+2) (len-2) sgn 16
- | ('0', 'o') | ('0', 'O') ->
- sys_big_int_of_string_aux s (ofs+2) (len-2) sgn 8
- | ('0', 'b') | ('0', 'B') ->
- sys_big_int_of_string_aux s (ofs+2) (len-2) sgn 2
- | _ -> sys_big_int_of_string_aux s ofs len sgn 10
-;;
-
-let sys_big_int_of_string s ofs len =
- if len < 1 then failwith "sys_big_int_of_string";
- match s.[ofs] with
- | '-' -> sys_big_int_of_string_base s (ofs+1) (len-1) (-1)
- | '+' -> sys_big_int_of_string_base s (ofs+1) (len-1) 1
- | _ -> sys_big_int_of_string_base s ofs len 1
-;;
-
-let big_int_of_string s =
- sys_big_int_of_string s 0 (String.length s)
-
-let big_int_of_string_opt s =
- try Some (big_int_of_string s) with Failure _ -> None
-
-let power_base_nat base nat off len =
- if base = 0 then nat_of_int 0 else
- if is_zero_nat nat off len || base = 1 then nat_of_int 1 else
- let power_base = make_nat (succ length_of_digit) in
- let (pmax, _pint) = make_power_base base power_base in
- let (n, rem) =
- let (x, y) = quomod_big_int (sys_big_int_of_nat nat off len)
- (big_int_of_int (succ pmax)) in
- (int_of_big_int x, int_of_big_int y) in
- if n = 0 then copy_nat power_base (pred rem) 1 else
- begin
- let res = make_nat n
- and res2 = make_nat (succ n)
- and l = num_bits_int n - 2 in
- blit_nat res 0 power_base pmax 1;
- for i = l downto 0 do
- let len = num_digits_nat res 0 n in
- let len2 = min n (2 * len) in
- let succ_len2 = succ len2 in
- ignore (square_nat res2 0 len2 res 0 len);
- begin
- if n land (1 lsl i) > 0
- then (set_to_zero_nat res 0 len;
- ignore (mult_digit_nat res 0 succ_len2
- res2 0 len2 power_base pmax))
- else blit_nat res 0 res2 0 len2
- end;
- set_to_zero_nat res2 0 len2
- done;
- if rem > 0
- then (ignore (mult_digit_nat res2 0 (succ n)
- res 0 n power_base (pred rem));
- res2)
- else res
- end
-
-let power_int_positive_int i n =
- match sign_int n with
- 0 -> unit_big_int
- | -1 -> invalid_arg "power_int_positive_int"
- | _ -> let nat = power_base_int (abs i) n in
- { sign = if i >= 0
- then sign_int i
- else if n land 1 = 0
- then 1
- else -1;
- abs_value = nat}
-
-let power_big_int_positive_int bi n =
- match sign_int n with
- 0 -> unit_big_int
- | -1 -> invalid_arg "power_big_int_positive_int"
- | _ -> let bi_len = num_digits_big_int bi in
- let res_len = bi_len * n in
- let res = make_nat res_len
- and res2 = make_nat res_len
- and l = num_bits_int n - 2 in
- blit_nat res 0 bi.abs_value 0 bi_len;
- for i = l downto 0 do
- let len = num_digits_nat res 0 res_len in
- let len2 = min res_len (2 * len) in
- set_to_zero_nat res2 0 len2;
- ignore (square_nat res2 0 len2 res 0 len);
- if n land (1 lsl i) > 0 then begin
- let lenp = min res_len (len2 + bi_len) in
- set_to_zero_nat res 0 lenp;
- ignore(mult_nat res 0 lenp res2 0 len2 (bi.abs_value) 0 bi_len)
- end else begin
- blit_nat res 0 res2 0 len2
- end
- done;
- {sign = if bi.sign >= 0 then bi.sign
- else if n land 1 = 0 then 1 else -1;
- abs_value = res}
-
-let power_int_positive_big_int i bi =
- match sign_big_int bi with
- 0 -> unit_big_int
- | -1 -> invalid_arg "power_int_positive_big_int"
- | _ -> let nat = power_base_nat
- (abs i) (bi.abs_value) 0 (num_digits_big_int bi) in
- { sign = if i >= 0
- then sign_int i
- else if is_digit_odd (bi.abs_value) 0
- then -1
- else 1;
- abs_value = nat }
-
-let power_big_int_positive_big_int bi1 bi2 =
- match sign_big_int bi2 with
- 0 -> unit_big_int
- | -1 -> invalid_arg "power_big_int_positive_big_int"
- | _ -> try
- power_big_int_positive_int bi1 (int_of_big_int bi2)
- with Failure _ ->
- try
- power_int_positive_big_int (int_of_big_int bi1) bi2
- with Failure _ ->
- raise Out_of_memory
- (* If neither bi1 nor bi2 is a small integer, bi1^bi2 is not
- representable. Indeed, on a 32-bit platform,
- |bi1| >= 2 and |bi2| >= 2^30, hence bi1^bi2 has at least
- 2^30 bits = 2^27 bytes, greater than the max size of
- allocated blocks. On a 64-bit platform,
- |bi1| >= 2 and |bi2| >= 2^62, hence bi1^bi2 has at least
- 2^62 bits = 2^59 bytes, greater than the max size of
- allocated blocks. *)
-
-(* base_power_big_int compute bi*base^n *)
-let base_power_big_int base n bi =
- match sign_int n with
- 0 -> bi
- | -1 -> let nat = power_base_int base (-n) in
- let len_nat = num_digits_nat nat 0 (length_nat nat)
- and len_bi = num_digits_big_int bi in
- if len_bi < len_nat then
- invalid_arg "base_power_big_int"
- else if len_bi = len_nat &&
- compare_digits_nat (bi.abs_value) len_bi nat len_nat = -1
- then invalid_arg "base_power_big_int"
- else
- let copy = create_nat (succ len_bi) in
- blit_nat copy 0 (bi.abs_value) 0 len_bi;
- set_digit_nat copy len_bi 0;
- div_nat copy 0 (succ len_bi)
- nat 0 len_nat;
- if not (is_zero_nat copy 0 len_nat)
- then invalid_arg "base_power_big_int"
- else { sign = bi.sign;
- abs_value = copy_nat copy len_nat 1 }
- | _ -> let nat = power_base_int base n in
- let len_nat = num_digits_nat nat 0 (length_nat nat)
- and len_bi = num_digits_big_int bi in
- let new_len = len_bi + len_nat in
- let res = make_nat new_len in
- ignore
- (if len_bi > len_nat
- then mult_nat res 0 new_len
- (bi.abs_value) 0 len_bi
- nat 0 len_nat
- else mult_nat res 0 new_len
- nat 0 len_nat
- (bi.abs_value) 0 len_bi)
- ; if is_zero_nat res 0 new_len
- then zero_big_int
- else create_big_int (bi.sign) res
-
-(* Other functions needed *)
-
-(* Integer part of the square root of a big_int *)
-let sqrt_big_int bi =
- match bi.sign with
- | 0 -> zero_big_int
- | -1 -> invalid_arg "sqrt_big_int"
- | _ -> {sign = 1;
- abs_value = sqrt_nat (bi.abs_value) 0 (num_digits_big_int bi)}
-
-let square_big_int bi =
- if bi.sign == 0 then zero_big_int else
- let len_bi = num_digits_big_int bi in
- let len_res = 2 * len_bi in
- let res = make_nat len_res in
- ignore (square_nat res 0 len_res (bi.abs_value) 0 len_bi);
- {sign = 1; abs_value = res}
-
-(* round off of the futur last digit (of the integer represented by the string
- argument of the function) that is now the previous one.
- if s contains an integer of the form (10^n)-1
- then s <- only 0 digits and the result_int is true
- else s <- the round number and the result_int is false *)
-let round_futur_last_digit s off_set length =
- let l = pred (length + off_set) in
- if Char.code(Bytes.get s l) >= Char.code '5'
- then
- let rec round_rec l =
- if l < off_set then true else begin
- let current_char = Bytes.get s l in
- if current_char = '9' then
- (Bytes.set s l '0'; round_rec (pred l))
- else
- (Bytes.set s l (Char.chr (succ (Char.code current_char)));
- false)
- end
- in round_rec (pred l)
- else false
-
-
-(* Approximation with floating decimal point a` la approx_ratio_exp *)
-let approx_big_int prec bi =
- let len_bi = num_digits_big_int bi in
- let n =
- max 0
- (int_of_big_int (
- add_int_big_int
- (-prec)
- (div_big_int (mult_big_int (big_int_of_int (pred len_bi))
- (big_int_of_string "963295986"))
- (big_int_of_string "100000000")))) in
- let s =
- Bytes.unsafe_of_string
- (string_of_big_int (div_big_int bi (power_int_positive_int 10 n)))
- in
- let (sign, off) =
- if Bytes.get s 0 = '-'
- then ("-", 1)
- else ("", 0) in
- if (round_futur_last_digit s off (succ prec))
- then (sign^"1."^(String.make prec '0')^"e"^
- (string_of_int (n + 1 - off + Bytes.length s)))
- else (sign^(Bytes.sub_string s off 1)^"."^
- (Bytes.sub_string s (succ off) (pred prec))
- ^"e"^(string_of_int (n - succ off + Bytes.length s)))
-
-(* Logical operations *)
-
-(* Shift left by N bits *)
-
-let shift_left_big_int bi n =
- if n < 0 then invalid_arg "shift_left_big_int"
- else if n = 0 then bi
- else if bi.sign = 0 then bi
- else begin
- let size_bi = num_digits_big_int bi in
- let size_res = size_bi + ((n + length_of_digit - 1) / length_of_digit) in
- let res = create_nat size_res in
- let ndigits = n / length_of_digit in
- set_to_zero_nat res 0 ndigits;
- blit_nat res ndigits bi.abs_value 0 size_bi;
- let nbits = n mod length_of_digit in
- if nbits > 0 then
- shift_left_nat res ndigits size_bi res (ndigits + size_bi) nbits;
- { sign = bi.sign; abs_value = res }
- end
-
-(* Shift right by N bits (rounds toward zero) *)
-
-let shift_right_towards_zero_big_int bi n =
- if n < 0 then invalid_arg "shift_right_towards_zero_big_int"
- else if n = 0 then bi
- else if bi.sign = 0 then bi
- else begin
- let size_bi = num_digits_big_int bi in
- let ndigits = n / length_of_digit in
- let nbits = n mod length_of_digit in
- if ndigits >= size_bi then zero_big_int else begin
- let size_res = size_bi - ndigits in
- let res = create_nat size_res in
- blit_nat res 0 bi.abs_value ndigits size_res;
- if nbits > 0 then begin
- let tmp = create_nat 1 in
- shift_right_nat res 0 size_res tmp 0 nbits
- end;
- if is_zero_nat res 0 size_res
- then zero_big_int
- else { sign = bi.sign; abs_value = res }
- end
- end
-
-(* Compute 2^n - 1 *)
-
-let two_power_m1_big_int n =
- if n < 0 then invalid_arg "two_power_m1_big_int"
- else if n = 0 then zero_big_int
- else begin
- let idx = n / length_of_digit in
- let size_res = idx + 1 in
- let res = make_nat size_res in
- set_digit_nat_native res idx
- (Nativeint.shift_left 1n (n mod length_of_digit));
- ignore (decr_nat res 0 size_res 0);
- { sign = 1; abs_value = res }
- end
-
-(* Shift right by N bits (rounds toward minus infinity) *)
-
-let shift_right_big_int bi n =
- if n < 0 then invalid_arg "shift_right_big_int"
- else if bi.sign >= 0 then shift_right_towards_zero_big_int bi n
- else
- shift_right_towards_zero_big_int (sub_big_int bi (two_power_m1_big_int n)) n
-
-(* Extract N bits starting at ofs.
- Treats bi in two's complement.
- Result is always positive. *)
-
-let extract_big_int bi ofs n =
- if ofs < 0 || n < 0 then invalid_arg "extract_big_int"
- else if bi.sign = 0 then bi
- else begin
- let size_bi = num_digits_big_int bi in
- let size_res = (n + length_of_digit - 1) / length_of_digit in
- let ndigits = ofs / length_of_digit in
- let nbits = ofs mod length_of_digit in
- let res = make_nat size_res in
- if ndigits < size_bi then
- blit_nat res 0 bi.abs_value ndigits (min size_res (size_bi - ndigits));
- if bi.sign < 0 then begin
- (* Two's complement *)
- complement_nat res 0 size_res;
- (* PR#6010: need to increment res iff digits 0...ndigits-1 of bi are 0.
- In this case, digits 0...ndigits-1 of not(bi) are all 0xFF...FF,
- and adding 1 to them produces a carry out at ndigits. *)
- let rec carry_incr i =
- i >= ndigits || i >= size_bi ||
- (is_digit_zero bi.abs_value i && carry_incr (i + 1)) in
- if carry_incr 0 then ignore (incr_nat res 0 size_res 1)
- end;
- if nbits > 0 then begin
- let tmp = create_nat 1 in
- shift_right_nat res 0 size_res tmp 0 nbits
- end;
- let n' = n mod length_of_digit in
- if n' > 0 then begin
- let tmp = create_nat 1 in
- set_digit_nat_native tmp 0
- (Nativeint.shift_right_logical (-1n) (length_of_digit - n'));
- land_digit_nat res (size_res - 1) tmp 0
- end;
- if is_zero_nat res 0 size_res
- then zero_big_int
- else { sign = 1; abs_value = res }
- end
-
-(* Bitwise logical operations. Arguments must be >= 0. *)
-
-let and_big_int a b =
- if a.sign < 0 || b.sign < 0 then invalid_arg "and_big_int"
- else if a.sign = 0 || b.sign = 0 then zero_big_int
- else begin
- let size_a = num_digits_big_int a
- and size_b = num_digits_big_int b in
- let size_res = min size_a size_b in
- let res = create_nat size_res in
- blit_nat res 0 a.abs_value 0 size_res;
- for i = 0 to size_res - 1 do
- land_digit_nat res i b.abs_value i
- done;
- if is_zero_nat res 0 size_res
- then zero_big_int
- else { sign = 1; abs_value = res }
- end
-
-let or_big_int a b =
- if a.sign < 0 || b.sign < 0 then invalid_arg "or_big_int"
- else if a.sign = 0 then b
- else if b.sign = 0 then a
- else begin
- let size_a = num_digits_big_int a
- and size_b = num_digits_big_int b in
- let size_res = max size_a size_b in
- let res = create_nat size_res in
- let or_aux a' b' size_b' =
- blit_nat res 0 a'.abs_value 0 size_res;
- for i = 0 to size_b' - 1 do
- lor_digit_nat res i b'.abs_value i
- done in
- if size_a >= size_b
- then or_aux a b size_b
- else or_aux b a size_a;
- if is_zero_nat res 0 size_res
- then zero_big_int
- else { sign = 1; abs_value = res }
- end
-
-let xor_big_int a b =
- if a.sign < 0 || b.sign < 0 then invalid_arg "xor_big_int"
- else if a.sign = 0 then b
- else if b.sign = 0 then a
- else begin
- let size_a = num_digits_big_int a
- and size_b = num_digits_big_int b in
- let size_res = max size_a size_b in
- let res = create_nat size_res in
- let xor_aux a' b' size_b' =
- blit_nat res 0 a'.abs_value 0 size_res;
- for i = 0 to size_b' - 1 do
- lxor_digit_nat res i b'.abs_value i
- done in
- if size_a >= size_b
- then xor_aux a b size_b
- else xor_aux b a size_a;
- if is_zero_nat res 0 size_res
- then zero_big_int
- else { sign = 1; abs_value = res }
- end
-
-(* Coercion with float type *)
-
-(* Consider a real number [r] such that
- - the integral part of [r] is the bigint [x]
- - 2^54 <= |x| < 2^63
- - the fractional part of [r] is 0 if [exact = true],
- nonzero if [exact = false].
- Then, the following function returns [r] correctly rounded to
- the nearest double-precision floating-point number.
- This is an instance of the "round to odd" technique formalized in
- "When double rounding is odd" by S. Boldo and G. Melquiond.
- The claim above is lemma Fappli_IEEE_extra.round_odd_fix
- from the CompCert Coq development. *)
-
-let round_big_int_to_float x exact =
- assert (let n = num_bits_big_int x in 55 <= n && n <= 63);
- let m = int64_of_big_int x in
- (* Unless the fractional part is exactly 0, round m to an odd integer *)
- let m = if exact then m else Int64.logor m 1L in
- (* Then convert m to float, with the normal rounding mode. *)
- Int64.to_float m
-
-let float_of_big_int x =
- let n = num_bits_big_int x in
- if n <= 63 then
- Int64.to_float (int64_of_big_int x)
- else begin
- let n = n - 55 in
- (* Extract top 55 bits of x *)
- let top = shift_right_big_int x n in
- (* Check if the other bits are all zero *)
- let exact = eq_big_int x (shift_left_big_int top n) in
- (* Round to float and apply exponent *)
- ldexp (round_big_int_to_float top exact) n
- end
+++ /dev/null
-(**************************************************************************)
-(* *)
-(* OCaml *)
-(* *)
-(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *)
-(* *)
-(* Copyright 1996 Institut National de Recherche en Informatique et *)
-(* en Automatique. *)
-(* *)
-(* All rights reserved. This file is distributed under the terms of *)
-(* the GNU Lesser General Public License version 2.1, with the *)
-(* special exception on linking described in the file LICENSE. *)
-(* *)
-(**************************************************************************)
-
-(** Operations on arbitrary-precision integers.
-
- Big integers (type [big_int]) are signed integers of arbitrary size.
-*)
-
-open Nat
-
-type big_int
- (** The type of big integers. *)
-
-val zero_big_int : big_int
-(** The big integer [0]. *)
-
-val unit_big_int : big_int
- (** The big integer [1]. *)
-
-(** {6 Arithmetic operations} *)
-
-val minus_big_int : big_int -> big_int
-(** Unary negation. *)
-
-val abs_big_int : big_int -> big_int
-(** Absolute value. *)
-
-val add_big_int : big_int -> big_int -> big_int
-(** Addition. *)
-
-val succ_big_int : big_int -> big_int
-(** Successor (add 1). *)
-
-val add_int_big_int : int -> big_int -> big_int
-(** Addition of a small integer to a big integer. *)
-
-val sub_big_int : big_int -> big_int -> big_int
-(** Subtraction. *)
-
-val pred_big_int : big_int -> big_int
-(** Predecessor (subtract 1). *)
-
-val mult_big_int : big_int -> big_int -> big_int
-(** Multiplication of two big integers. *)
-
-val mult_int_big_int : int -> big_int -> big_int
-(** Multiplication of a big integer by a small integer *)
-
-val square_big_int: big_int -> big_int
-(** Return the square of the given big integer *)
-
-val sqrt_big_int: big_int -> big_int
- (** [sqrt_big_int a] returns the integer square root of [a],
- that is, the largest big integer [r] such that [r * r <= a].
- Raise [Invalid_argument] if [a] is negative. *)
-
-val quomod_big_int : big_int -> big_int -> big_int * big_int
- (** Euclidean division of two big integers.
- The first part of the result is the quotient,
- the second part is the remainder.
- Writing [(q,r) = quomod_big_int a b], we have
- [a = q * b + r] and [0 <= r < |b|].
- Raise [Division_by_zero] if the divisor is zero. *)
-
-val div_big_int : big_int -> big_int -> big_int
- (** Euclidean quotient of two big integers.
- This is the first result [q] of [quomod_big_int] (see above). *)
-
-val mod_big_int : big_int -> big_int -> big_int
- (** Euclidean modulus of two big integers.
- This is the second result [r] of [quomod_big_int] (see above). *)
-
-val gcd_big_int : big_int -> big_int -> big_int
-(** Greatest common divisor of two big integers. *)
-
-val power_int_positive_int: int -> int -> big_int
-val power_big_int_positive_int: big_int -> int -> big_int
-val power_int_positive_big_int: int -> big_int -> big_int
-val power_big_int_positive_big_int: big_int -> big_int -> big_int
- (** Exponentiation functions. Return the big integer
- representing the first argument [a] raised to the power [b]
- (the second argument). Depending
- on the function, [a] and [b] can be either small integers
- or big integers. Raise [Invalid_argument] if [b] is negative. *)
-
-(** {6 Comparisons and tests} *)
-
-val sign_big_int : big_int -> int
- (** Return [0] if the given big integer is zero,
- [1] if it is positive, and [-1] if it is negative. *)
-
-val compare_big_int : big_int -> big_int -> int
- (** [compare_big_int a b] returns [0] if [a] and [b] are equal,
- [1] if [a] is greater than [b], and [-1] if [a] is smaller
- than [b]. *)
-
-val eq_big_int : big_int -> big_int -> bool
-val le_big_int : big_int -> big_int -> bool
-val ge_big_int : big_int -> big_int -> bool
-val lt_big_int : big_int -> big_int -> bool
-val gt_big_int : big_int -> big_int -> bool
-(** Usual boolean comparisons between two big integers. *)
-
-val max_big_int : big_int -> big_int -> big_int
-(** Return the greater of its two arguments. *)
-
-val min_big_int : big_int -> big_int -> big_int
-(** Return the smaller of its two arguments. *)
-
-val num_digits_big_int : big_int -> int
- (** Return the number of machine words used to store the
- given big integer. *)
-
-val num_bits_big_int : big_int -> int
- (** Return the number of significant bits in the absolute
- value of the given big integer. [num_bits_big_int a]
- returns 0 if [a] is 0; otherwise it returns a positive
- integer [n] such that [2^(n-1) <= |a| < 2^n].
-
- @since 4.03.0 *)
-
-(** {6 Conversions to and from strings} *)
-
-val string_of_big_int : big_int -> string
- (** Return the string representation of the given big integer,
- in decimal (base 10). *)
-
-val big_int_of_string : string -> big_int
- (** Convert a string to a big integer, in decimal.
- The string consists of an optional [-] or [+] sign,
- followed by one or several decimal digits. *)
-(* TODO: document error condition. *)
-
-val big_int_of_string_opt: string -> big_int option
-(** Convert a string to a big integer, in decimal.
- The string consists of an optional [-] or [+] sign,
- followed by one or several decimal digits. Other the function
- returns [None].
- @since 4.05
-*)
-
-
-(** {6 Conversions to and from other numerical types} *)
-
-val big_int_of_int : int -> big_int
-(** Convert a small integer to a big integer. *)
-
-val is_int_big_int : big_int -> bool
- (** Test whether the given big integer is small enough to
- be representable as a small integer (type [int])
- without loss of precision. On a 32-bit platform,
- [is_int_big_int a] returns [true] if and only if
- [a] is between 2{^30} and 2{^30}-1. On a 64-bit platform,
- [is_int_big_int a] returns [true] if and only if
- [a] is between -2{^62} and 2{^62}-1. *)
-
-val int_of_big_int : big_int -> int
- (** Convert a big integer to a small integer (type [int]).
- Raises [Failure "int_of_big_int"] if the big integer
- is not representable as a small integer. *)
-
-val int_of_big_int_opt: big_int -> int option
-(** Convert a big integer to a small integer (type [int]). Return
- [None] if the big integer is not representable as a small
- integer.
- @since 4.05
-*)
-
-val big_int_of_int32 : int32 -> big_int
-(** Convert a 32-bit integer to a big integer. *)
-
-val big_int_of_nativeint : nativeint -> big_int
-(** Convert a native integer to a big integer. *)
-
-val big_int_of_int64 : int64 -> big_int
-(** Convert a 64-bit integer to a big integer. *)
-
-val int32_of_big_int : big_int -> int32
- (** Convert a big integer to a 32-bit integer.
- Raises [Failure] if the big integer is outside the
- range \[-2{^31}, 2{^31}-1\]. *)
-
-val int32_of_big_int_opt: big_int -> int32 option
-(** Convert a big integer to a 32-bit integer. Return [None] if the
- big integer is outside the range \[-2{^31}, 2{^31}-1\].
- @since 4.05
-*)
-
-val nativeint_of_big_int : big_int -> nativeint
- (** Convert a big integer to a native integer.
- Raises [Failure] if the big integer is outside the
- range [[Nativeint.min_int, Nativeint.max_int]]. *)
-
-val nativeint_of_big_int_opt: big_int -> nativeint option
-(** Convert a big integer to a native integer. Return [None] if the
- big integer is outside the range [[Nativeint.min_int,
- Nativeint.max_int]];
- @since 4.05
-*)
-
-val int64_of_big_int : big_int -> int64
- (** Convert a big integer to a 64-bit integer.
- Raises [Failure] if the big integer is outside the
- range \[-2{^63}, 2{^63}-1\]. *)
-
-val int64_of_big_int_opt: big_int -> int64 option
-(** Convert a big integer to a 64-bit integer. Return [None] if the
- big integer is outside the range \[-2{^63}, 2{^63}-1\].
- @since 4.05
-*)
-
-val float_of_big_int : big_int -> float
- (** Returns a floating-point number approximating the
- given big integer. *)
-
-(** {6 Bit-oriented operations} *)
-
-val and_big_int : big_int -> big_int -> big_int
- (** Bitwise logical 'and'.
- The arguments must be positive or zero. *)
-
-val or_big_int : big_int -> big_int -> big_int
- (** Bitwise logical 'or'.
- The arguments must be positive or zero. *)
-
-val xor_big_int : big_int -> big_int -> big_int
- (** Bitwise logical 'exclusive or'.
- The arguments must be positive or zero. *)
-
-val shift_left_big_int : big_int -> int -> big_int
- (** [shift_left_big_int b n] returns [b] shifted left by [n] bits.
- Equivalent to multiplication by 2^n. *)
-
-val shift_right_big_int : big_int -> int -> big_int
- (** [shift_right_big_int b n] returns [b] shifted right by [n] bits.
- Equivalent to division by 2^n with the result being
- rounded towards minus infinity. *)
-
-val shift_right_towards_zero_big_int : big_int -> int -> big_int
- (** [shift_right_towards_zero_big_int b n] returns [b] shifted
- right by [n] bits. The shift is performed on the absolute
- value of [b], and the result has the same sign as [b].
- Equivalent to division by 2^n with the result being
- rounded towards zero. *)
-
-val extract_big_int : big_int -> int -> int -> big_int
- (** [extract_big_int bi ofs n] returns a nonnegative number
- corresponding to bits [ofs] to [ofs + n - 1] of the
- binary representation of [bi]. If [bi] is negative,
- a two's complement representation is used. *)
-
-(**/**)
-
-(** {6 For internal use} *)
-
-val nat_of_big_int : big_int -> nat
-val big_int_of_nat : nat -> big_int
-val base_power_big_int: int -> int -> big_int -> big_int
-val sys_big_int_of_string: string -> int -> int -> big_int
-val round_futur_last_digit : bytes -> int -> int -> bool
-val approx_big_int: int -> big_int -> string
-
-val round_big_int_to_float: big_int -> bool -> float
-(** @since 4.03.0 *)
+++ /dev/null
-/**************************************************************************/
-/* */
-/* OCaml */
-/* */
-/* Xavier Leroy, projet Cristal, 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 GNU Lesser General Public License version 2.1, with the */
-/* special exception on linking described in the file LICENSE. */
-/* */
-/**************************************************************************/
-
-#include "bng.h"
-#include "caml/config.h"
-
-#if defined(__GNUC__) && BNG_ASM_LEVEL > 0
-#if defined(BNG_ARCH_ia32)
-#include "bng_ia32.c"
-#elif defined(BNG_ARCH_amd64)
-#include "bng_amd64.c"
-#elif defined(BNG_ARCH_ppc)
-#include "bng_ppc.c"
-#elif defined (BNG_ARCH_sparc)
-#include "bng_sparc.c"
-#elif defined (BNG_ARCH_arm64)
-#include "bng_arm64.c"
-#endif
-#endif
-
-#include "bng_digit.c"
-
-/**** Operations that cannot be overridden ****/
-
-/* Return number of leading zero bits in d */
-int bng_leading_zero_bits(bngdigit d)
-{
- int n = BNG_BITS_PER_DIGIT;
-#ifdef ARCH_SIXTYFOUR
- if ((d & 0xFFFFFFFF00000000L) != 0) { n -= 32; d = d >> 32; }
-#endif
- if ((d & 0xFFFF0000) != 0) { n -= 16; d = d >> 16; }
- if ((d & 0xFF00) != 0) { n -= 8; d = d >> 8; }
- if ((d & 0xF0) != 0) { n -= 4; d = d >> 4; }
- if ((d & 0xC) != 0) { n -= 2; d = d >> 2; }
- if ((d & 2) != 0) { n -= 1; d = d >> 1; }
- return n - d;
-}
-
-/* Complement the digits of {a,len} */
-void bng_complement(bng a/*[alen]*/, bngsize alen)
-{
- for (/**/; alen > 0; alen--, a++) *a = ~*a;
-}
-
-/* Return number of significant digits in {a,alen}. */
-bngsize bng_num_digits(bng a/*[alen]*/, bngsize alen)
-{
- while (1) {
- if (alen == 0) return 1;
- if (a[alen - 1] != 0) return alen;
- alen--;
- }
-}
-
-/* Return 0 if {a,alen} = {b,blen}
- -1 if {a,alen} < {b,blen}
- 1 if {a,alen} > {b,blen}. */
-int bng_compare(bng a/*[alen]*/, bngsize alen,
- bng b/*[blen]*/, bngsize blen)
-{
- bngdigit da, db;
-
- while (alen > 0 && a[alen-1] == 0) alen--;
- while (blen > 0 && b[blen-1] == 0) blen--;
- if (alen > blen) return 1;
- if (alen < blen) return -1;
- while (alen > 0) {
- alen--;
- da = a[alen];
- db = b[alen];
- if (da > db) return 1;
- if (da < db) return -1;
- }
- return 0;
-}
-
-/**** Generic definitions of the overridable operations ****/
-
-/* {a,alen} := {a, alen} + carry. Return carry out. */
-static bngcarry bng_generic_add_carry
- (bng a/*[alen]*/, bngsize alen, bngcarry carry)
-{
- if (carry == 0 || alen == 0) return carry;
- do {
- if (++(*a) != 0) return 0;
- a++;
- } while (--alen);
- return 1;
-}
-
-/* {a,alen} := {a,alen} + {b,blen} + carry. Return carry out.
- Require alen >= blen. */
-static bngcarry bng_generic_add
- (bng a/*[alen]*/, bngsize alen,
- bng b/*[blen]*/, bngsize blen,
- bngcarry carry)
-{
- alen -= blen;
- for (/**/; blen > 0; blen--, a++, b++) {
- BngAdd2Carry(*a, carry, *a, *b, carry);
- }
- if (carry == 0 || alen == 0) return carry;
- do {
- if (++(*a) != 0) return 0;
- a++;
- } while (--alen);
- return 1;
-}
-
-/* {a,alen} := {a, alen} - carry. Return carry out. */
-static bngcarry bng_generic_sub_carry
- (bng a/*[alen]*/, bngsize alen, bngcarry carry)
-{
- if (carry == 0 || alen == 0) return carry;
- do {
- if ((*a)-- != 0) return 0;
- a++;
- } while (--alen);
- return 1;
-}
-
-/* {a,alen} := {a,alen} - {b,blen} - carry. Return carry out.
- Require alen >= blen. */
-static bngcarry bng_generic_sub
- (bng a/*[alen]*/, bngsize alen,
- bng b/*[blen]*/, bngsize blen,
- bngcarry carry)
-{
- alen -= blen;
- for (/**/; blen > 0; blen--, a++, b++) {
- BngSub2Carry(*a, carry, *a, *b, carry);
- }
- if (carry == 0 || alen == 0) return carry;
- do {
- if ((*a)-- != 0) return 0;
- a++;
- } while (--alen);
- return 1;
-}
-
-/* {a,alen} := {a,alen} << shift.
- Return the bits shifted out of the most significant digit of a.
- Require 0 <= shift < BITS_PER_BNGDIGIT. */
-static bngdigit bng_generic_shift_left
- (bng a/*[alen]*/, bngsize alen,
- int shift)
-{
- int shift2 = BNG_BITS_PER_DIGIT - shift;
- bngdigit carry = 0;
- if (shift > 0) {
- for (/**/; alen > 0; alen--, a++) {
- bngdigit d = *a;
- *a = (d << shift) | carry;
- carry = d >> shift2;
- }
- }
- return carry;
-}
-
-/* {a,alen} := {a,alen} >> shift.
- Return the bits shifted out of the least significant digit of a.
- Require 0 <= shift < BITS_PER_BNGDIGIT. */
-static bngdigit bng_generic_shift_right
- (bng a/*[alen]*/, bngsize alen,
- int shift)
-{
- int shift2 = BNG_BITS_PER_DIGIT - shift;
- bngdigit carry = 0;
- if (shift > 0) {
- for (a = a + alen - 1; alen > 0; alen--, a--) {
- bngdigit d = *a;
- *a = (d >> shift) | carry;
- carry = d << shift2;
- }
- }
- return carry;
-}
-
-/* {a,alen} := {a,alen} + d * {b,blen}. Return carry out.
- Require alen >= blen. */
-static bngdigit bng_generic_mult_add_digit
- (bng a/*[alen]*/, bngsize alen,
- bng b/*[blen]*/, bngsize blen,
- bngdigit d)
-{
- bngdigit out, ph, pl;
- bngcarry carry;
-
- alen -= blen;
- for (out = 0; blen > 0; blen--, a++, b++) {
- bngdigit bd = *b;
- /* ph:pl = double-digit product of b's current digit and d */
- BngMult(ph, pl, bd, d);
- /* current digit of a += pl + out. Accumulate carries in ph. */
- BngAdd3(*a, ph, *a, pl, out);
- /* prepare out for next iteration */
- out = ph;
- }
- if (alen == 0) return out;
- /* current digit of a += out */
- BngAdd2(*a, carry, *a, out);
- a++;
- alen--;
- /* Propagate carry */
- if (carry == 0 || alen == 0) return carry;
- do {
- if (++(*a) != 0) return 0;
- a++;
- } while (--alen);
- return 1;
-}
-
-/* {a,alen} := {a,alen} - d * {b,blen}. Return carry out.
- Require alen >= blen. */
-static bngdigit bng_generic_mult_sub_digit
- (bng a/*[alen]*/, bngsize alen,
- bng b/*[blen]*/, bngsize blen,
- bngdigit d)
-{
- bngdigit out, ph, pl;
- bngcarry carry;
-
- alen -= blen;
- for (out = 0; blen > 0; blen--, a++, b++) {
- bngdigit bd = *b;
- /* ph:pl = double-digit product of b's current digit and d */
- BngMult(ph, pl, bd, d);
- /* current digit of a -= pl + out. Accumulate carrys in ph. */
- BngSub3(*a, ph, *a, pl, out);
- /* prepare out for next iteration */
- out = ph;
- }
- if (alen == 0) return out;
- /* current digit of a -= out */
- BngSub2(*a, carry, *a, out);
- a++;
- alen--;
- /* Propagate carry */
- if (carry == 0 || alen == 0) return carry;
- do {
- if ((*a)-- != 0) return 0;
- a++;
- } while (--alen);
- return 1;
-}
-
-/* {a,alen} := {a,alen} + {b,blen} * {c,clen}. Return carry out.
- Require alen >= blen + clen. */
-static bngcarry bng_generic_mult_add
- (bng a/*[alen]*/, bngsize alen,
- bng b/*[blen]*/, bngsize blen,
- bng c/*[clen]*/, bngsize clen)
-{
- bngcarry carry;
- for (carry = 0; clen > 0; clen--, c++, alen--, a++)
- carry += bng_mult_add_digit(a, alen, b, blen, *c);
- return carry;
-}
-
-/* {a,alen} := 2 * {a,alen} + {b,blen}^2. Return carry out.
- Require alen >= 2 * blen. */
-static bngcarry bng_generic_square_add
- (bng a/*[alen]*/, bngsize alen,
- bng b/*[blen]*/, bngsize blen)
-{
- bngcarry carry1, carry2;
- bngsize i, aofs;
- bngdigit ph, pl, d;
-
- /* Double products */
- for (carry1 = 0, i = 1; i < blen; i++) {
- aofs = 2 * i - 1;
- carry1 += bng_mult_add_digit(a + aofs, alen - aofs,
- b + i, blen - i, b[i - 1]);
- }
- /* Multiply by two */
- carry1 = (carry1 << 1) | bng_shift_left(a, alen, 1);
- /* Add square of digits */
- carry2 = 0;
- for (i = 0; i < blen; i++) {
- d = b[i];
- BngMult(ph, pl, d, d);
- BngAdd2Carry(*a, carry2, *a, pl, carry2);
- a++;
- BngAdd2Carry(*a, carry2, *a, ph, carry2);
- a++;
- }
- alen -= 2 * blen;
- if (alen > 0 && carry2 != 0) {
- do {
- if (++(*a) != 0) { carry2 = 0; break; }
- a++;
- } while (--alen);
- }
- return carry1 + carry2;
-}
-
-/* {a,len-1} := {b,len} / d. Return {b,len} modulo d.
- Require MSD of b < d.
- If BngDivNeedsNormalization is defined, require d normalized. */
-static bngdigit bng_generic_div_rem_norm_digit
- (bng a/*[len-1]*/, bng b/*[len]*/, bngsize len, bngdigit d)
-{
- bngdigit topdigit, quo, rem;
- intnat i;
-
- topdigit = b[len - 1];
- for (i = len - 2; i >= 0; i--) {
- /* Divide topdigit:current digit of numerator by d */
- BngDiv(quo, rem, topdigit, b[i], d);
- /* Quotient is current digit of result */
- a[i] = quo;
- /* Iterate with topdigit = remainder */
- topdigit = rem;
- }
- return topdigit;
-}
-
-#ifdef BngDivNeedsNormalization
-/* {a,len-1} := {b,len} / d. Return {b,len} modulo d.
- Require MSD of b < d. */
-static bngdigit bng_generic_div_rem_digit
- (bng a/*[len-1]*/, bng b/*[len]*/, bngsize len, bngdigit d)
-{
- bngdigit rem;
- int shift;
-
- /* Normalize d and b */
- shift = bng_leading_zero_bits(d);
- d <<= shift;
- bng_shift_left(b, len, shift);
- /* Do the division */
- rem = bng_div_rem_norm_digit(a, b, len, d);
- /* Undo normalization on b and remainder */
- bng_shift_right(b, len, shift);
- return rem >> shift;
-}
-#endif
-
-/* {n+dlen, nlen-dlen} := {n,nlen} / {d, dlen}.
- {n, dlen} := {n,nlen} modulo {d, dlen}.
- Require nlen > dlen and MSD of n < MSD of d.
- (This implies MSD of d > 0). */
-static void bng_generic_div_rem
- (bng n/*[nlen]*/, bngsize nlen,
- bng d/*[dlen]*/, bngsize dlen)
-{
- bngdigit topden, quo, rem;
- int shift;
- bngsize i, j;
-
- /* Normalize d */
- shift = bng_leading_zero_bits(d[dlen - 1]);
- /* Note that no bits of n are lost by the following shift,
- since n[nlen-1] < d[dlen-1] */
- bng_shift_left(n, nlen, shift);
- bng_shift_left(d, dlen, shift);
- /* Special case if d is just one digit */
- if (dlen == 1) {
- *n = bng_div_rem_norm_digit(n + 1, n, nlen, *d);
- } else {
- topden = d[dlen - 1];
- /* Long division */
- for (j = nlen - 1; j >= dlen; j--) {
- i = j - dlen;
- /* At this point:
- - the current numerator is n[j] : ...................... : n[0]
- - to be subtracted quo times: d[dlen-1] : ... : d[0] : 0... : 0
- (there are i zeroes at the end) */
- /* Under-estimate the next digit of the quotient (quo) */
- if (topden + 1 == 0)
- quo = n[j];
- else
- BngDiv(quo, rem, n[j], n[j - 1], topden + 1);
- /* Subtract d * quo (shifted i places) from numerator */
- n[j] -= bng_mult_sub_digit(n + i, dlen, d, dlen, quo);
- /* Adjust if necessary */
- while (n[j] != 0 || bng_compare(n + i, dlen, d, dlen) >= 0) {
- /* Numerator is still bigger than shifted divisor.
- Increment quotient and subtract shifted divisor. */
- quo++;
- n[j] -= bng_sub(n + i, dlen, d, dlen, 0);
- }
- /* Store quotient digit */
- n[j] = quo;
- }
- }
- /* Undo normalization on remainder and divisor */
- bng_shift_right(n, dlen, shift);
- bng_shift_right(d, dlen, shift);
-}
-
-/**** Construction of the table of operations ****/
-
-struct bng_operations bng_ops = {
- bng_generic_add_carry,
- bng_generic_add,
- bng_generic_sub_carry,
- bng_generic_sub,
- bng_generic_shift_left,
- bng_generic_shift_right,
- bng_generic_mult_add_digit,
- bng_generic_mult_sub_digit,
- bng_generic_mult_add,
- bng_generic_square_add,
- bng_generic_div_rem_norm_digit,
-#ifdef BngDivNeedsNormalization
- bng_generic_div_rem_digit,
-#else
- bng_generic_div_rem_norm_digit,
-#endif
- bng_generic_div_rem
-};
-
-void bng_init(void)
-{
-#ifdef BNG_SETUP_OPS
- BNG_SETUP_OPS;
-#endif
-}
+++ /dev/null
-/**************************************************************************/
-/* */
-/* OCaml */
-/* */
-/* Xavier Leroy, projet Cristal, 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 GNU Lesser General Public License version 2.1, with the */
-/* special exception on linking described in the file LICENSE. */
-/* */
-/**************************************************************************/
-
-#include <string.h>
-#include "caml/config.h"
-
-typedef uintnat bngdigit;
-typedef bngdigit * bng;
-typedef unsigned int bngcarry;
-typedef uintnat bngsize;
-
-#define BNG_BITS_PER_DIGIT (sizeof(bngdigit) * 8)
-#define BNG_BITS_PER_HALF_DIGIT (sizeof(bngdigit) * 4)
-
-struct bng_operations {
-
- /* {a,alen} := {a, alen} + carry. Return carry out. */
- bngcarry (*add_carry)
- (bng a/*[alen]*/, bngsize alen, bngcarry carry);
-#define bng_add_carry bng_ops.add_carry
-
- /* {a,alen} := {a,alen} + {b,blen} + carry. Return carry out.
- Require alen >= blen. */
- bngcarry (*add)
- (bng a/*[alen]*/, bngsize alen,
- bng b/*[blen]*/, bngsize blen,
- bngcarry carry);
-#define bng_add bng_ops.add
-
- /* {a,alen} := {a, alen} - carry. Return carry out. */
- bngcarry (*sub_carry)
- (bng a/*[alen]*/, bngsize alen, bngcarry carry);
-#define bng_sub_carry bng_ops.sub_carry
-
- /* {a,alen} := {a,alen} - {b,blen} - carry. Return carry out.
- Require alen >= blen. */
- bngcarry (*sub)
- (bng a/*[alen]*/, bngsize alen,
- bng b/*[blen]*/, bngsize blen,
- bngcarry carry);
-#define bng_sub bng_ops.sub
-
- /* {a,alen} := {a,alen} << shift.
- Return the bits shifted out of the most significant digit of a.
- Require 0 <= shift < BITS_PER_BNGDIGIT. */
- bngdigit (*shift_left)
- (bng a/*[alen]*/, bngsize alen,
- int shift);
-#define bng_shift_left bng_ops.shift_left
-
- /* {a,alen} := {a,alen} >> shift.
- Return the bits shifted out of the least significant digit of a.
- Require 0 <= shift < BITS_PER_BNGDIGIT. */
- bngdigit (*shift_right)
- (bng a/*[alen]*/, bngsize alen,
- int shift);
-#define bng_shift_right bng_ops.shift_right
-
- /* {a,alen} := {a,alen} + d * {b,blen}. Return carry out.
- Require alen >= blen.
- If alen > blen, the carry out returned is 0 or 1.
- If alen == blen, the carry out returned is a full digit. */
- bngdigit (*mult_add_digit)
- (bng a/*[alen]*/, bngsize alen,
- bng b/*[blen]*/, bngsize blen,
- bngdigit d);
-#define bng_mult_add_digit bng_ops.mult_add_digit
-
- /* {a,alen} := {a,alen} - d * {b,blen}. Return carry out.
- Require alen >= blen.
- If alen > blen, the carry out returned is 0 or 1.
- If alen == blen, the carry out returned is a full digit. */
- bngdigit (*mult_sub_digit)
- (bng a/*[alen]*/, bngsize alen,
- bng b/*[blen]*/, bngsize blen,
- bngdigit d);
-#define bng_mult_sub_digit bng_ops.mult_sub_digit
-
- /* {a,alen} := {a,alen} + {b,blen} * {c,clen}. Return carry out.
- Require alen >= blen + clen. */
- bngcarry (*mult_add)
- (bng a/*[alen]*/, bngsize alen,
- bng b/*[blen]*/, bngsize blen,
- bng c/*[clen]*/, bngsize clen);
-#define bng_mult_add bng_ops.mult_add
-
- /* {a,alen} := 2 * {a,alen} + {b,blen}^2. Return carry out.
- Require alen >= 2 * blen. */
- bngcarry (*square_add)
- (bng a/*[alen]*/, bngsize alen,
- bng b/*[blen]*/, bngsize blen);
-#define bng_square_add bng_ops.square_add
-
- /* {a,len-1} := {b,len} / d. Return {b,len} modulo d.
- Require d is normalized and MSD of b < d.
- See div_rem_digit for a function that does not require d
- to be normalized */
- bngdigit (*div_rem_norm_digit)
- (bng a/*[len-1]*/, bng b/*[len]*/, bngsize len, bngdigit d);
-#define bng_div_rem_norm_digit bng_ops.div_rem_norm_digit
-
- /* {a,len-1} := {b,len} / d. Return {b,len} modulo d.
- Require MSD of b < d. */
- bngdigit (*div_rem_digit)
- (bng a/*[len-1]*/, bng b/*[len]*/, bngsize len, bngdigit d);
-#define bng_div_rem_digit bng_ops.div_rem_digit
-
- /* {n+dlen, nlen-dlen} := {n,nlen} / {d, dlen}.
- {n, dlen} := {n,nlen} modulo {d, dlen}.
- Require nlen > dlen and MSD of n < MSD of d (which implies d != 0). */
- void (*div_rem)
- (bng n/*[nlen]*/, bngsize nlen,
- bng d/*[nlen]*/, bngsize dlen);
-#define bng_div_rem bng_ops.div_rem
-};
-
-extern struct bng_operations bng_ops;
-
-/* Initialize the BNG library */
-extern void bng_init(void);
-
-/* {a,alen} := 0 */
-#define bng_zero(a,alen) memset((a), 0, (alen) * sizeof(bngdigit))
-
-/* {a,len} := {b,len} */
-#define bng_assign(a,b,len) memmove((a), (b), (len) * sizeof(bngdigit))
-
-/* Complement the digits of {a,len} */
-extern void bng_complement(bng a/*[alen]*/, bngsize alen);
-
-/* Return number of significant digits in {a,alen}. */
-extern bngsize bng_num_digits(bng a/*[alen]*/, bngsize alen);
-
-/* Return 1 if {a,alen} is 0, 0 otherwise. */
-#define bng_is_zero(a,alen) (bng_num_digits(a,alen) == 0)
-
-/* Return 0 if {a,alen} = {b,blen}
- <0 if {a,alen} < {b,blen}
- >0 if {a,alen} > {b,blen}. */
-extern int bng_compare(bng a/*[alen]*/, bngsize alen,
- bng b/*[blen]*/, bngsize blen);
-
-/* Return the number of leading zero bits in digit d. */
-extern int bng_leading_zero_bits(bngdigit d);
+++ /dev/null
-/**************************************************************************/
-/* */
-/* OCaml */
-/* */
-/* Xavier Leroy, projet Cristal, 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 GNU Lesser General Public License version 2.1, with the */
-/* special exception on linking described in the file LICENSE. */
-/* */
-/**************************************************************************/
-
-/* Code specific to the AMD x86_64 architecture. */
-
-#define BngAdd2(res,carryout,arg1,arg2) \
- asm("xorl %1, %1 \n\t" \
- "addq %3, %0 \n\t" \
- "setc %b1" \
- : "=r" (res), "=&q" (carryout) \
- : "0" (arg1), "rm" (arg2))
-
-#define BngSub2(res,carryout,arg1,arg2) \
- asm("xorl %1, %1 \n\t" \
- "subq %3, %0 \n\t" \
- "setc %b1" \
- : "=r" (res), "=&q" (carryout) \
- : "0" (arg1), "rm" (arg2))
-
-#define BngMult(resh,resl,arg1,arg2) \
- asm("mulq %3" \
- : "=a" (resl), "=d" (resh) \
- : "a" (arg1), "r" (arg2))
-
-#define BngDiv(quo,rem,nh,nl,d) \
- asm("divq %4" \
- : "=a" (quo), "=d" (rem) \
- : "a" (nl), "d" (nh), "r" (d))
-
-/* Reimplementation in asm of some of the bng operations. */
-
-static bngcarry bng_amd64_add
- (bng a/*[alen]*/, bngsize alen,
- bng b/*[blen]*/, bngsize blen,
- bngcarry carry)
-{
- bngdigit tmp;
- alen -= blen;
- if (blen > 0) {
- asm("negb %b3 \n\t"
- "1: \n\t"
- "movq (%0), %4 \n\t"
- "adcq (%1), %4 \n\t"
- "movq %4, (%0) \n\t"
- "leaq 8(%0), %0 \n\t"
- "leaq 8(%1), %1 \n\t"
- "decq %2 \n\t"
- "jnz 1b \n\t"
- "setc %b3"
- : "=r" (a), "=r" (b), "=r" (blen), "=q" (carry), "=r" (tmp)
- : "0" (a), "1" (b), "2" (blen), "3" (carry));
- }
- if (carry == 0 || alen == 0) return carry;
- do {
- if (++(*a) != 0) return 0;
- a++;
- } while (--alen);
- return 1;
-}
-
-static bngcarry bng_amd64_sub
- (bng a/*[alen]*/, bngsize alen,
- bng b/*[blen]*/, bngsize blen,
- bngcarry carry)
-{
- bngdigit tmp;
- alen -= blen;
- if (blen > 0) {
- asm("negb %b3 \n\t"
- "1: \n\t"
- "movq (%0), %4 \n\t"
- "sbbq (%1), %4 \n\t"
- "movq %4, (%0) \n\t"
- "leaq 8(%0), %0 \n\t"
- "leaq 8(%1), %1 \n\t"
- "decq %2 \n\t"
- "jnz 1b \n\t"
- "setc %b3"
- : "=r" (a), "=r" (b), "=r" (blen), "=q" (carry), "=r" (tmp)
- : "0" (a), "1" (b), "2" (blen), "3" (carry));
- }
- if (carry == 0 || alen == 0) return carry;
- do {
- if ((*a)-- != 0) return 0;
- a++;
- } while (--alen);
- return 1;
-}
-
-static bngdigit bng_amd64_mult_add_digit
- (bng a/*[alen]*/, bngsize alen,
- bng b/*[blen]*/, bngsize blen,
- bngdigit d)
-{
- bngdigit out;
- bngcarry carry;
-
- alen -= blen;
- out = 0;
- if (blen > 0) {
- asm("1: \n\t"
- "movq (%1), %%rax \n\t"
- "mulq %7\n\t" /* rdx:rax = d * next digit of b */
- "addq (%0), %%rax \n\t" /* add next digit of a to rax */
- "adcq $0, %%rdx \n\t" /* accumulate carry in rdx */
- "addq %3, %%rax \n\t" /* add out to rax */
- "adcq $0, %%rdx \n\t" /* accumulate carry in rdx */
- "movq %%rax, (%0) \n\t" /* rax is next digit of result */
- "movq %%rdx, %3 \n\t" /* rdx is next out */
- "leaq 8(%0), %0 \n\t"
- "leaq 8(%1), %1 \n\t"
- "decq %2 \n\t"
- "jnz 1b"
- : "=&r" (a), "=&r" (b), "=&r" (blen), "=&r" (out)
- : "0" (a), "1" (b), "2" (blen), "rm" (d), "3" (out)
- : "rax", "rdx");
- }
- if (alen == 0) return out;
- /* current digit of a += out */
- BngAdd2(*a, carry, *a, out);
- a++;
- alen--;
- /* Propagate carry */
- if (carry == 0 || alen == 0) return carry;
- do {
- if (++(*a) != 0) return 0;
- a++;
- } while (--alen);
- return 1;
-}
-
-static bngdigit bng_amd64_mult_sub_digit
- (bng a/*[alen]*/, bngsize alen,
- bng b/*[blen]*/, bngsize blen,
- bngdigit d)
-{
- bngdigit out, tmp;
- bngcarry carry;
-
- alen -= blen;
- out = 0;
- if (blen > 0) {
- asm("1: \n\t"
- "movq (%1), %%rax \n\t"
- "movq (%0), %4 \n\t"
- "mulq %8\n\t" /* rdx:rax = d * next digit of b */
- "subq %%rax, %4 \n\t" /* subtract rax from next digit of a */
- "adcq $0, %%rdx \n\t" /* accumulate carry in rdx */
- "subq %3, %4 \n\t" /* subtract out */
- "adcq $0, %%rdx \n\t" /* accumulate carry in rdx */
- "movq %4, (%0) \n\t" /* store next digit of result */
- "movq %%rdx, %3 \n\t" /* rdx is next out */
- "leaq 8(%0), %0 \n\t"
- "leaq 8(%1), %1 \n\t"
- "decq %2 \n\t"
- "jnz 1b"
- : "=&r" (a), "=&r" (b), "=&rm" (blen), "=&r" (out), "=&r" (tmp)
- : "0" (a), "1" (b), "2" (blen), "rm" (d), "3" (out)
- : "rax", "rdx");
- }
- if (alen == 0) return out;
- /* current digit of a -= out */
- BngSub2(*a, carry, *a, out);
- a++;
- alen--;
- /* Propagate carry */
- if (carry == 0 || alen == 0) return carry;
- do {
- if ((*a)-- != 0) return 0;
- a++;
- } while (--alen);
- return 1;
-}
-
-static void bng_amd64_setup_ops(void)
-{
- bng_ops.add = bng_amd64_add;
- bng_ops.sub = bng_amd64_sub;
- bng_ops.mult_add_digit = bng_amd64_mult_add_digit;
- bng_ops.mult_sub_digit = bng_amd64_mult_sub_digit;
-}
-
-#define BNG_SETUP_OPS bng_amd64_setup_ops()
+++ /dev/null
-/**************************************************************************/
-/* */
-/* OCaml */
-/* */
-/* Xavier Leroy, projet Gallium, INRIA Rocquencourt */
-/* */
-/* Copyright 2013 Institut National de Recherche en Informatique et */
-/* en Automatique. */
-/* */
-/* All rights reserved. This file is distributed under the terms of */
-/* the GNU Lesser General Public License version 2.1, with the */
-/* special exception on linking described in the file LICENSE. */
-/* */
-/**************************************************************************/
-
-/* Code specific for the ARM 64 (AArch64) architecture */
-
-#define BngMult(resh,resl,arg1,arg2) \
- asm("mul %0, %2, %3 \n\t" \
- "umulh %1, %2, %3" \
- : "=&r" (resl), "=&r" (resh) \
- : "r" (arg1), "r" (arg2))
+++ /dev/null
-/**************************************************************************/
-/* */
-/* OCaml */
-/* */
-/* Xavier Leroy, projet Cristal, 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 GNU Lesser General Public License version 2.1, with the */
-/* special exception on linking described in the file LICENSE. */
-/* */
-/**************************************************************************/
-
-/**** Generic operations on digits ****/
-
-/* These macros can be defined in the machine-specific include file.
- Below are the default definitions (in plain C).
- Except for BngMult, all macros are guaranteed to evaluate their
- arguments exactly once. */
-
-#ifndef BngAdd2
-/* res = arg1 + arg2. carryout = carry out. */
-#define BngAdd2(res,carryout,arg1,arg2) { \
- bngdigit tmp1, tmp2; \
- tmp1 = arg1; \
- tmp2 = tmp1 + (arg2); \
- carryout = (tmp2 < tmp1); \
- res = tmp2; \
-}
-#endif
-
-#ifndef BngAdd2Carry
-/* res = arg1 + arg2 + carryin. carryout = carry out. */
-#define BngAdd2Carry(res,carryout,arg1,arg2,carryin) { \
- bngdigit tmp1, tmp2, tmp3; \
- tmp1 = arg1; \
- tmp2 = tmp1 + (arg2); \
- tmp3 = tmp2 + (carryin); \
- carryout = (tmp2 < tmp1) + (tmp3 < tmp2); \
- res = tmp3; \
-}
-#endif
-
-#ifndef BngAdd3
-/* res = arg1 + arg2 + arg3. Each carry increments carryaccu. */
-#define BngAdd3(res,carryaccu,arg1,arg2,arg3) { \
- bngdigit tmp1, tmp2, tmp3; \
- tmp1 = arg1; \
- tmp2 = tmp1 + (arg2); \
- carryaccu += (tmp2 < tmp1); \
- tmp3 = tmp2 + (arg3); \
- carryaccu += (tmp3 < tmp2); \
- res = tmp3; \
-}
-#endif
-
-#ifndef BngSub2
-/* res = arg1 - arg2. carryout = carry out. */
-#define BngSub2(res,carryout,arg1,arg2) { \
- bngdigit tmp1, tmp2; \
- tmp1 = arg1; \
- tmp2 = arg2; \
- res = tmp1 - tmp2; \
- carryout = (tmp1 < tmp2); \
-}
-#endif
-
-#ifndef BngSub2Carry
-/* res = arg1 - arg2 - carryin. carryout = carry out. */
-#define BngSub2Carry(res,carryout,arg1,arg2,carryin) { \
- bngdigit tmp1, tmp2, tmp3; \
- tmp1 = arg1; \
- tmp2 = arg2; \
- tmp3 = tmp1 - tmp2; \
- res = tmp3 - (carryin); \
- carryout = (tmp1 < tmp2) + (tmp3 < carryin); \
-}
-#endif
-
-#ifndef BngSub3
-/* res = arg1 - arg2 - arg3. Each carry increments carryaccu. */
-#define BngSub3(res,carryaccu,arg1,arg2,arg3) { \
- bngdigit tmp1, tmp2, tmp3, tmp4; \
- tmp1 = arg1; \
- tmp2 = arg2; \
- tmp3 = arg3; \
- tmp4 = tmp1 - tmp2; \
- res = tmp4 - tmp3; \
- carryaccu += (tmp1 < tmp2) + (tmp4 < tmp3); \
-}
-#endif
-
-#define BngLowHalf(d) ((d) & (((bngdigit)1 << BNG_BITS_PER_HALF_DIGIT) - 1))
-#define BngHighHalf(d) ((d) >> BNG_BITS_PER_HALF_DIGIT)
-
-#ifndef BngMult
-/* resl = low digit of product arg1 * arg2
- resh = high digit of product arg1 * arg2. */
-#if SIZEOF_PTR == 4 && defined(ARCH_UINT64_TYPE)
-#define BngMult(resh,resl,arg1,arg2) { \
- ARCH_UINT64_TYPE p = (ARCH_UINT64_TYPE)(arg1) * (ARCH_UINT64_TYPE)(arg2); \
- resh = p >> 32; \
- resl = p; \
-}
-#else
-#define BngMult(resh,resl,arg1,arg2) { \
- bngdigit p11 = BngLowHalf(arg1) * BngLowHalf(arg2); \
- bngdigit p12 = BngLowHalf(arg1) * BngHighHalf(arg2); \
- bngdigit p21 = BngHighHalf(arg1) * BngLowHalf(arg2); \
- bngdigit p22 = BngHighHalf(arg1) * BngHighHalf(arg2); \
- resh = p22 + (p12 >> BNG_BITS_PER_HALF_DIGIT) \
- + (p21 >> BNG_BITS_PER_HALF_DIGIT); \
- BngAdd3(resl, resh, \
- p11, p12 << BNG_BITS_PER_HALF_DIGIT, p21 << BNG_BITS_PER_HALF_DIGIT); \
-}
-#endif
-#endif
-
-#ifndef BngDiv
-/* Divide the double-width number nh:nl by d.
- Require d != 0 and nh < d.
- Store quotient in quo, remainder in rem.
- Can be slow if d is not normalized. */
-#define BngDiv(quo,rem,nh,nl,d) bng_div_aux(&(quo),&(rem),nh,nl,d)
-#define BngDivNeedsNormalization
-
-static void bng_div_aux(bngdigit * quo, bngdigit * rem,
- bngdigit nh, bngdigit nl, bngdigit d)
-{
- bngdigit dl, dh, ql, qh, pl, ph, nsaved;
-
- dl = BngLowHalf(d);
- dh = BngHighHalf(d);
- /* Under-estimate the top half of the quotient (qh) */
- qh = nh / (dh + 1);
- /* Shift nh:nl right by BNG_BITS_PER_HALF_DIGIT bits,
- so that we focus on the top 1.5 digits of the numerator.
- Then, subtract (qh * d) from nh:nl. */
- nsaved = BngLowHalf(nl);
- ph = qh * dh;
- pl = qh * dl;
- nh -= ph; /* Subtract before shifting so that carry propagates for free */
- nl = (nl >> BNG_BITS_PER_HALF_DIGIT) | (nh << BNG_BITS_PER_HALF_DIGIT);
- nh = (nh >> BNG_BITS_PER_HALF_DIGIT);
- nh -= (nl < pl); /* Borrow */
- nl -= pl;
- /* Adjust estimate qh until nh:nl < 0:d */
- while (nh != 0 || nl >= d) {
- nh -= (nl < d); /* Borrow */
- nl -= d;
- qh++;
- }
- /* Under-estimate the bottom half of the quotient (ql) */
- ql = nl / (dh + 1);
- /* Shift nh:nl left by BNG_BITS_PER_HALF_DIGIT bits, restoring the
- low bits we saved earlier, so that we focus on the bottom 1.5 digit
- of the numerator. Then, subtract (ql * d) from nh:nl. */
- ph = ql * dh;
- pl = ql * dl;
- nl -= ph; /* Subtract before shifting so that carry propagates for free */
- nh = (nl >> BNG_BITS_PER_HALF_DIGIT);
- nl = (nl << BNG_BITS_PER_HALF_DIGIT) | nsaved;
- nh -= (nl < pl); /* Borrow */
- nl -= pl;
- /* Adjust estimate ql until nh:nl < 0:d */
- while (nh != 0 || nl >= d) {
- nh -= (nl < d); /* Borrow */
- nl -= d;
- ql++;
- }
- /* We're done */
- *quo = (qh << BNG_BITS_PER_HALF_DIGIT) | ql;
- *rem = nl;
-}
-
-#endif
+++ /dev/null
-/**************************************************************************/
-/* */
-/* OCaml */
-/* */
-/* Xavier Leroy, projet Cristal, 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 GNU Lesser General Public License version 2.1, with the */
-/* special exception on linking described in the file LICENSE. */
-/* */
-/**************************************************************************/
-
-/* Code specific to the Intel IA32 (x86) architecture. */
-
-#define BngAdd2(res,carryout,arg1,arg2) \
- asm("xorl %1, %1 \n\t" \
- "addl %3, %0 \n\t" \
- "setc %b1" \
- : "=r" (res), "=&q" (carryout) \
- : "0" (arg1), "rm" (arg2))
-
-#define BngSub2(res,carryout,arg1,arg2) \
- asm("xorl %1, %1 \n\t" \
- "subl %3, %0 \n\t" \
- "setc %b1" \
- : "=r" (res), "=&q" (carryout) \
- : "0" (arg1), "rm" (arg2))
-
-#define BngMult(resh,resl,arg1,arg2) \
- asm("mull %3" \
- : "=a" (resl), "=d" (resh) \
- : "a" (arg1), "r" (arg2))
-
-#define BngDiv(quo,rem,nh,nl,d) \
- asm("divl %4" \
- : "=a" (quo), "=d" (rem) \
- : "a" (nl), "d" (nh), "r" (d))
-
-/* Reimplementation in asm of some of the bng operations. */
-
-static bngcarry bng_ia32_add
- (bng a/*[alen]*/, bngsize alen,
- bng b/*[blen]*/, bngsize blen,
- bngcarry carry)
-{
- bngdigit tmp;
- alen -= blen;
- if (blen > 0) {
- asm("negb %b3 \n\t"
- "1: \n\t"
- "movl (%0), %4 \n\t"
- "adcl (%1), %4 \n\t"
- "movl %4, (%0) \n\t"
- "leal 4(%0), %0 \n\t"
- "leal 4(%1), %1 \n\t"
- "decl %2 \n\t"
- "jnz 1b \n\t"
- "setc %b3"
- : "+&r" (a), "+&r" (b), "+&r" (blen), "+&q" (carry), "=&r" (tmp));
- }
- if (carry == 0 || alen == 0) return carry;
- do {
- if (++(*a) != 0) return 0;
- a++;
- } while (--alen);
- return 1;
-}
-
-static bngcarry bng_ia32_sub
- (bng a/*[alen]*/, bngsize alen,
- bng b/*[blen]*/, bngsize blen,
- bngcarry carry)
-{
- bngdigit tmp;
- alen -= blen;
- if (blen > 0) {
- asm("negb %b3 \n\t"
- "1: \n\t"
- "movl (%0), %4 \n\t"
- "sbbl (%1), %4 \n\t"
- "movl %4, (%0) \n\t"
- "leal 4(%0), %0 \n\t"
- "leal 4(%1), %1 \n\t"
- "decl %2 \n\t"
- "jnz 1b \n\t"
- "setc %b3"
- : "+&r" (a), "+&r" (b), "+&r" (blen), "+&q" (carry), "=&r" (tmp));
- }
- if (carry == 0 || alen == 0) return carry;
- do {
- if ((*a)-- != 0) return 0;
- a++;
- } while (--alen);
- return 1;
-}
-
-static bngdigit bng_ia32_mult_add_digit
- (bng a/*[alen]*/, bngsize alen,
- bng b/*[blen]*/, bngsize blen,
- bngdigit d)
-{
- bngdigit out;
- bngcarry carry;
-
- alen -= blen;
- out = 0;
- if (blen > 0) {
- asm("1: \n\t"
- "movl (%1), %%eax \n\t"
- "mull %4\n\t" /* edx:eax = d * next digit of b */
- "addl (%0), %%eax \n\t" /* add next digit of a to eax */
- "adcl $0, %%edx \n\t" /* accumulate carry in edx */
- "addl %3, %%eax \n\t" /* add out to eax */
- "adcl $0, %%edx \n\t" /* accumulate carry in edx */
- "movl %%eax, (%0) \n\t" /* eax is next digit of result */
- "movl %%edx, %3 \n\t" /* edx is next out */
- "leal 4(%0), %0 \n\t"
- "leal 4(%1), %1 \n\t"
- "decl %2 \n\t"
- "jnz 1b"
- : "+&r" (a), "+&r" (b), "+&r" (blen), "=m" (out)
- : "m" (d)
- : "eax", "edx");
- }
- if (alen == 0) return out;
- /* current digit of a += out */
- BngAdd2(*a, carry, *a, out);
- a++;
- alen--;
- /* Propagate carry */
- if (carry == 0 || alen == 0) return carry;
- do {
- if (++(*a) != 0) return 0;
- a++;
- } while (--alen);
- return 1;
-}
-
-static bngdigit bng_ia32_mult_sub_digit
- (bng a/*[alen]*/, bngsize alen,
- bng b/*[blen]*/, bngsize blen,
- bngdigit d)
-{
- bngdigit out, tmp;
- bngcarry carry;
-
- alen -= blen;
- out = 0;
- if (blen > 0) {
- asm("1: \n\t"
- "movl (%1), %%eax \n\t"
- "movl (%0), %4 \n\t"
- "mull %5\n\t" /* edx:eax = d * next digit of b */
- "subl %%eax, %4 \n\t" /* subtract eax from next digit of a */
- "adcl $0, %%edx \n\t" /* accumulate carry in edx */
- "subl %3, %4 \n\t" /* subtract out */
- "adcl $0, %%edx \n\t" /* accumulate carry in edx */
- "movl %4, (%0) \n\t" /* store next digit of result */
- "movl %%edx, %3 \n\t" /* edx is next out */
- "leal 4(%0), %0 \n\t"
- "leal 4(%1), %1 \n\t"
- "decl %2 \n\t"
- "jnz 1b"
- : "+&r" (a), "+&r" (b), "=m" (blen), "=m" (out), "=&r" (tmp)
- : "m" (d)
- : "eax", "edx");
- }
- if (alen == 0) return out;
- /* current digit of a -= out */
- BngSub2(*a, carry, *a, out);
- a++;
- alen--;
- /* Propagate carry */
- if (carry == 0 || alen == 0) return carry;
- do {
- if ((*a)-- != 0) return 0;
- a++;
- } while (--alen);
- return 1;
-}
-
-/* This is another asm implementation of some of the bng operations,
- using SSE2 operations to provide 64-bit arithmetic.
- This is faster than the plain IA32 code above on the Pentium 4.
- (Arithmetic operations with carry are slow on the Pentium 4). */
-
-#if BNG_ASM_LEVEL >= 2
-
-static bngcarry bng_ia32sse2_add
- (bng a/*[alen]*/, bngsize alen,
- bng b/*[blen]*/, bngsize blen,
- bngcarry carry)
-{
- alen -= blen;
- if (blen > 0) {
- asm("movd %3, %%mm0 \n\t" /* MM0 is carry */
- "1: \n\t"
- "movd (%0), %%mm1 \n\t" /* MM1 is next digit of a */
- "movd (%1), %%mm2 \n\t" /* MM2 is next digit of b */
- "paddq %%mm1, %%mm0 \n\t" /* Add carry (64 bits) */
- "paddq %%mm2, %%mm0 \n\t" /* Add digits (64 bits) */
- "movd %%mm0, (%0) \n\t" /* Store low 32 bits of result */
- "psrlq $32, %%mm0 \n\t" /* Next carry is top 32 bits of results */
- "addl $4, %0\n\t"
- "addl $4, %1\n\t"
- "subl $1, %2\n\t"
- "jne 1b \n\t"
- "movd %%mm0, %3 \n\t"
- "emms"
- : "+&r" (a), "+&r" (b), "+&r" (blen), "+&rm" (carry));
- }
- if (carry == 0 || alen == 0) return carry;
- do {
- if (++(*a) != 0) return 0;
- a++;
- } while (--alen);
- return 1;
-}
-
-static bngcarry bng_ia32sse2_sub
- (bng a/*[alen]*/, bngsize alen,
- bng b/*[blen]*/, bngsize blen,
- bngcarry carry)
-{
- alen -= blen;
- if (blen > 0) {
- asm("movd %3, %%mm0 \n\t" /* MM0 is carry */
- "1: \n\t"
- "movd (%0), %%mm1 \n\t" /* MM1 is next digit of a */
- "movd (%1), %%mm2 \n\t" /* MM2 is next digit of b */
- "psubq %%mm0, %%mm1 \n\t" /* Subtract carry (64 bits) */
- "psubq %%mm2, %%mm1 \n\t" /* Subtract digits (64 bits) */
- "movd %%mm1, (%0) \n\t" /* Store low 32 bits of result */
- "psrlq $63, %%mm1 \n\t" /* Next carry is sign bit of result */
- "movq %%mm1, %%mm0 \n\t"
- "addl $4, %0\n\t"
- "addl $4, %1\n\t"
- "subl $1, %2\n\t"
- "jne 1b \n\t"
- "movd %%mm0, %3 \n\t"
- "emms"
- : "+&r" (a), "+&r" (b), "+&r" (blen), "+&rm" (carry));
- }
- if (carry == 0 || alen == 0) return carry;
- do {
- if ((*a)-- != 0) return 0;
- a++;
- } while (--alen);
- return 1;
-}
-
-static bngdigit bng_ia32sse2_mult_add_digit
- (bng a/*[alen]*/, bngsize alen,
- bng b/*[blen]*/, bngsize blen,
- bngdigit d)
-{
- bngdigit out;
- bngcarry carry;
-
- alen -= blen;
- out = 0;
- if (blen > 0) {
- asm("pxor %%mm0, %%mm0 \n\t" /* MM0 is carry */
- "movd %4, %%mm7 \n\t" /* MM7 is digit d */
- "1: \n\t"
- "movd (%0), %%mm1 \n\t" /* MM1 is next digit of a */
- "movd (%1), %%mm2 \n\t" /* MM2 is next digit of b */
- "pmuludq %%mm7, %%mm2 \n\t" /* MM2 = d * digit of b */
- "paddq %%mm1, %%mm0 \n\t" /* Add product and carry ... */
- "paddq %%mm2, %%mm0 \n\t" /* ... and digit of a */
- "movd %%mm0, (%0) \n\t" /* Store low 32 bits of result */
- "psrlq $32, %%mm0 \n\t" /* Next carry is high 32 bits result */
- "addl $4, %0\n\t"
- "addl $4, %1\n\t"
- "subl $1, %2\n\t"
- "jne 1b \n\t"
- "movd %%mm0, %3 \n\t"
- "emms"
- : "+&r" (a), "+&r" (b), "+&r" (blen), "=&rm" (out)
- : "m" (d));
- }
- if (alen == 0) return out;
- /* current digit of a += out */
- BngAdd2(*a, carry, *a, out);
- a++;
- alen--;
- /* Propagate carry */
- if (carry == 0 || alen == 0) return carry;
- do {
- if (++(*a) != 0) return 0;
- a++;
- } while (--alen);
- return 1;
-}
-
-static bngdigit bng_ia32sse2_mult_sub_digit
- (bng a/*[alen]*/, bngsize alen,
- bng b/*[blen]*/, bngsize blen,
- bngdigit d)
-{
- static unsigned long long bias1 = 0xFFFFFFFF00000000ULL - 0xFFFFFFFFULL;
- static unsigned long bias2 = 0xFFFFFFFFUL;
- bngdigit out;
- bngcarry carry;
-
- alen -= blen;
- out = 0;
- if (blen > 0) {
- /* Carry C is represented by ENC(C) = 0xFFFFFFFF - C (one's complement) */
- asm("movd %6, %%mm0 \n\t" /* MM0 is carry (initially 0xFFFFFFFF) */
- "movq %5, %%mm6 \n\t" /* MM6 is magic constant bias1 */
- "movd %4, %%mm7 \n\t" /* MM7 is digit d */
- "1: \n\t"
- "movd (%0), %%mm1 \n\t" /* MM1 is next digit of a */
- "movd (%1), %%mm2 \n\t" /* MM2 is next digit of b */
- "paddq %%mm6, %%mm1 \n\t" /* bias digit of a */
- "pmuludq %%mm7, %%mm2 \n\t" /* MM2 = d * digit of b */
- /* Compute
- digit of a + ENC(carry) + 0xFFFFFFFF00000000 - 0xFFFFFFFF - product
- = digit of a - carry + 0xFFFFFFFF00000000 - product
- = digit of a - carry - productlow + (ENC(nextcarry) << 32) */
- "psubq %%mm2, %%mm1 \n\t"
- "paddq %%mm1, %%mm0 \n\t"
- "movd %%mm0, (%0) \n\t" /* Store low 32 bits of result */
- "psrlq $32, %%mm0 \n\t" /* Next carry is 32 high bits of result */
- "addl $4, %0\n\t"
- "addl $4, %1\n\t"
- "subl $1, %2\n\t"
- "jne 1b \n\t"
- "movd %%mm0, %3 \n\t"
- "emms"
- : "+&r" (a), "+&r" (b), "+&r" (blen), "=&rm" (out)
- : "m" (d), "m" (bias1), "m" (bias2));
- out = ~out; /* Undo encoding on out digit */
- }
- if (alen == 0) return out;
- /* current digit of a -= out */
- BngSub2(*a, carry, *a, out);
- a++;
- alen--;
- /* Propagate carry */
- if (carry == 0 || alen == 0) return carry;
- do {
- if ((*a)-- != 0) return 0;
- a++;
- } while (--alen);
- return 1;
-}
-
-/* Detect whether SSE2 instructions are supported */
-
-static int bng_ia32_sse2_supported(void)
-{
- unsigned int flags, newflags, max_id, capabilities;
-
-#define EFLAG_CPUID 0x00200000
-#define CPUID_IDENTIFY 0
-#define CPUID_CAPABILITIES 1
-#define SSE2_CAPABILITY 26
-
- /* Check if processor has CPUID instruction */
- asm("pushfl \n\t"
- "popl %0"
- : "=r" (flags) : );
- newflags = flags ^ EFLAG_CPUID; /* CPUID detection flag */
- asm("pushfl \n\t"
- "pushl %1 \n\t"
- "popfl \n\t"
- "pushfl \n\t"
- "popl %0 \n\t"
- "popfl"
- : "=r" (flags) : "r" (newflags));
- /* If CPUID detection flag cannot be changed, CPUID instruction is not
- available */
- if ((flags & EFLAG_CPUID) != (newflags & EFLAG_CPUID)) return 0;
- /* See if SSE2 extensions are supported */
- asm("pushl %%ebx \n\t" /* need to preserve %ebx for PIC */
- "cpuid \n\t"
- "popl %%ebx"
- : "=a" (max_id) : "a" (CPUID_IDENTIFY): "ecx", "edx");
- if (max_id < 1) return 0;
- asm("pushl %%ebx \n\t"
- "cpuid \n\t"
- "popl %%ebx"
- : "=d" (capabilities) : "a" (CPUID_CAPABILITIES) : "ecx");
- return capabilities & (1 << SSE2_CAPABILITY);
-}
-
-#endif
-
-static void bng_ia32_setup_ops(void)
-{
-#if BNG_ASM_LEVEL >= 2
- if (bng_ia32_sse2_supported()) {
- bng_ops.add = bng_ia32sse2_add;
- bng_ops.sub = bng_ia32sse2_sub;
- bng_ops.mult_add_digit = bng_ia32sse2_mult_add_digit;
- bng_ops.mult_sub_digit = bng_ia32sse2_mult_sub_digit;
- return;
- }
-#endif
- bng_ops.add = bng_ia32_add;
- bng_ops.sub = bng_ia32_sub;
- bng_ops.mult_add_digit = bng_ia32_mult_add_digit;
- bng_ops.mult_sub_digit = bng_ia32_mult_sub_digit;
-}
-
-#define BNG_SETUP_OPS bng_ia32_setup_ops()
+++ /dev/null
-/**************************************************************************/
-/* */
-/* OCaml */
-/* */
-/* Xavier Leroy, projet Cristal, 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 GNU Lesser General Public License version 2.1, with the */
-/* special exception on linking described in the file LICENSE. */
-/* */
-/**************************************************************************/
-
-/* Code specific to the PowerPC architecture. */
-
-#define BngAdd2(res,carryout,arg1,arg2) \
- asm("addc %0, %2, %3 \n\t" \
- "li %1, 0 \n\t" \
- "addze %1, %1" \
- : "=r" (res), "=r" (carryout) \
- : "r" (arg1), "r" (arg2))
-
-#define BngAdd2Carry(res,carryout,arg1,arg2,carryin) \
- asm("addic %1, %4, -1 \n\t" \
- "adde %0, %2, %3 \n\t" \
- "li %1, 0 \n\t" \
- "addze %1, %1" \
- : "=r" (res), "=&r" (carryout) \
- : "r" (arg1), "r" (arg2), "1" (carryin))
-
-#define BngAdd3(res,carryaccu,arg1,arg2,arg3) \
- asm("addc %0, %2, %3 \n\t" \
- "addze %1, %1 \n\t" \
- "addc %0, %0, %4 \n\t" \
- "addze %1, %1" \
- : "=&r" (res), "=&r" (carryaccu) \
- : "r" (arg1), "r" (arg2), "r" (arg3), "1" (carryaccu))
-
-/* The "subtract" instructions interpret carry differently than what we
- need: the processor carry bit CA is 1 if no carry occured,
- 0 if a carry occured. In other terms, CA = !carry.
- Thus, subfe rd,ra,rb computes rd = ra - rb - !CA
- subfe rd,rd,rd sets rd = - !CA
- subfe rd,rd,rd; neg rd, rd sets rd = !CA and recovers "our" carry. */
-
-#define BngSub2(res,carryout,arg1,arg2) \
- asm("subfc %0, %3, %2 \n\t" \
- "subfe %1, %1, %1\n\t" \
- "neg %1, %1" \
- : "=r" (res), "=r" (carryout) \
- : "r" (arg1), "r" (arg2))
-
-#define BngSub2Carry(res,carryout,arg1,arg2,carryin) \
- asm("subfic %1, %4, 0 \n\t" \
- "subfe %0, %3, %2 \n\t" \
- "subfe %1, %1, %1 \n\t" \
- "neg %1, %1" \
- : "=r" (res), "=&r" (carryout) \
- : "r" (arg1), "r" (arg2), "1" (carryin))
-
-/* Here is what happens with carryaccu:
- neg %1, %1 carryaccu = -carryaccu
- addze %1, %1 carryaccu += !carry1
- addze %1, %1 carryaccu += !carry2
- subifc %1, %1, 2 carryaccu = 2 - carryaccu
- Thus, carryaccu_final = carryaccu_initial + 2 - (1 - carry1) - (1 - carry2)
- = carryaccu_initial + carry1 + carry2
-*/
-
-#define BngSub3(res,carryaccu,arg1,arg2,arg3) \
- asm("neg %1, %1 \n\t" \
- "subfc %0, %3, %2 \n\t" \
- "addze %1, %1 \n\t" \
- "subfc %0, %4, %0 \n\t" \
- "addze %1, %1 \n\t" \
- "subfic %1, %1, 2 \n\t" \
- : "=&r" (res), "=&r" (carryaccu) \
- : "r" (arg1), "r" (arg2), "r" (arg3), "1" (carryaccu))
-
-#if defined(__ppc64__) || defined(__PPC64__)
-#define BngMult(resh,resl,arg1,arg2) \
- asm("mulld %0, %2, %3 \n\t" \
- "mulhdu %1, %2, %3" \
- : "=&r" (resl), "=r" (resh) \
- : "r" (arg1), "r" (arg2))
-#else
-#define BngMult(resh,resl,arg1,arg2) \
- asm("mullw %0, %2, %3 \n\t" \
- "mulhwu %1, %2, %3" \
- : "=&r" (resl), "=r" (resh) \
- : "r" (arg1), "r" (arg2))
-#endif
+++ /dev/null
-/**************************************************************************/
-/* */
-/* OCaml */
-/* */
-/* Xavier Leroy, projet Cristal, 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 GNU Lesser General Public License version 2.1, with the */
-/* special exception on linking described in the file LICENSE. */
-/* */
-/**************************************************************************/
-
-/* Code specific to the SPARC (V8 and above) architecture. */
-
-#define BngAdd2(res,carryout,arg1,arg2) \
- asm("addcc %2, %3, %0 \n\t" \
- "addx %%g0, 0, %1" \
- : "=r" (res), "=r" (carryout) \
- : "r" (arg1), "r" (arg2) \
- : "cc")
-
-#define BngAdd2Carry(res,carryout,arg1,arg2,carryin) \
- asm("subcc %%g0, %4, %%g0 \n\t" \
- "addxcc %2, %3, %0 \n\t" \
- "addx %%g0, 0, %1" \
- : "=r" (res), "=r" (carryout) \
- : "r" (arg1), "r" (arg2), "r" (carryin) \
- : "cc")
-
-#define BngAdd3(res,carryaccu,arg1,arg2,arg3) \
- asm("addcc %2, %3, %0 \n\t" \
- "addx %1, 0, %1 \n\t" \
- "addcc %0, %4, %0 \n\t" \
- "addx %1, 0, %1" \
- : "=r" (res), "=r" (carryaccu) \
- : "r" (arg1), "r" (arg2), "r" (arg3), "1" (carryaccu) \
- : "cc")
-
-#define BngSub2(res,carryout,arg1,arg2) \
- asm("subcc %2, %3, %0 \n\t" \
- "addx %%g0, 0, %1" \
- : "=r" (res), "=r" (carryout) \
- : "r" (arg1), "r" (arg2) \
- : "cc")
-
-#define BngSub2Carry(res,carryout,arg1,arg2,carryin) \
- asm("subcc %%g0, %4, %%g0 \n\t" \
- "subxcc %2, %3, %0 \n\t" \
- "addx %%g0, 0, %1" \
- : "=r" (res), "=r" (carryout) \
- : "r" (arg1), "r" (arg2), "r" (carryin) \
- : "cc")
-
-#define BngSub3(res,carryaccu,arg1,arg2,arg3) \
- asm("subcc %2, %3, %0 \n\t" \
- "addx %1, 0, %1 \n\t" \
- "subcc %0, %4, %0 \n\t" \
- "addx %1, 0, %1" \
- : "=r" (res), "=r" (carryaccu) \
- : "r" (arg1), "r" (arg2), "r" (arg3), "1" (carryaccu) \
- : "cc")
-
-#define BngMult(resh,resl,arg1,arg2) \
- asm("umul %2, %3, %0 \n\t" \
- "rd %%y, %1" \
- : "=r" (resl), "=r" (resh) \
- : "r" (arg1), "r" (arg2))
-
-#define BngDiv(quo,rem,nh,nl,d) \
- asm("wr %1, %%y \n\t" \
- "udiv %2, %3, %0" \
- : "=r" (quo) \
- : "r" (nh), "r" (nl), "r" (d)); \
- rem = nl - d * quo
+++ /dev/null
-(**************************************************************************)
-(* *)
-(* OCaml *)
-(* *)
-(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *)
-(* *)
-(* Copyright 1996 Institut National de Recherche en Informatique et *)
-(* en Automatique. *)
-(* *)
-(* All rights reserved. This file is distributed under the terms of *)
-(* the GNU Lesser General Public License version 2.1, with the *)
-(* special exception on linking described in the file LICENSE. *)
-(* *)
-(**************************************************************************)
-
-(* Some extra operations on integers *)
-
-let rec gcd_int i1 i2 =
- if i2 = 0 then abs i1 else gcd_int i2 (i1 mod i2)
-;;
-
-let rec num_bits_int_aux n =
- if n = 0 then 0 else succ(num_bits_int_aux (n lsr 1));;
-
-let num_bits_int n = num_bits_int_aux (abs n);;
-
-let sign_int i = if i = 0 then 0 else if i > 0 then 1 else -1;;
-
-let length_of_int = Sys.word_size - 2;;
-
-let monster_int = 1 lsl length_of_int;;
-let biggest_int = monster_int - 1;;
-let least_int = - biggest_int;;
-
-let compare_int n1 n2 =
- if n1 == n2 then 0 else if n1 > n2 then 1 else -1;;
+++ /dev/null
-(**************************************************************************)
-(* *)
-(* OCaml *)
-(* *)
-(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *)
-(* *)
-(* Copyright 1996 Institut National de Recherche en Informatique et *)
-(* en Automatique. *)
-(* *)
-(* All rights reserved. This file is distributed under the terms of *)
-(* the GNU Lesser General Public License version 2.1, with the *)
-(* special exception on linking described in the file LICENSE. *)
-(* *)
-(**************************************************************************)
-
-(* Some extra operations on integers *)
-
-val gcd_int: int -> int -> int
-val num_bits_int: int -> int
-val compare_int: int -> int -> int
-val sign_int: int -> int
-val length_of_int: int
-val biggest_int: int
-val least_int: int
-val monster_int: int
+++ /dev/null
-/**************************************************************************/
-/* */
-/* OCaml */
-/* */
-/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */
-/* */
-/* Copyright 1999 Institut National de Recherche en Informatique et */
-/* en Automatique. */
-/* */
-/* All rights reserved. This file is distributed under the terms of */
-/* the GNU Lesser General Public License version 2.1, with the */
-/* special exception on linking described in the file LICENSE. */
-/* */
-/**************************************************************************/
-
-/* Nats are represented as unstructured blocks with tag Custom_tag. */
-
-#define Digit_val(nat,pos) (((bng) Data_custom_val(nat))[pos])
+++ /dev/null
-(**************************************************************************)
-(* *)
-(* OCaml *)
-(* *)
-(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *)
-(* *)
-(* Copyright 1996 Institut National de Recherche en Informatique et *)
-(* en Automatique. *)
-(* *)
-(* All rights reserved. This file is distributed under the terms of *)
-(* the GNU Lesser General Public License version 2.1, with the *)
-(* special exception on linking described in the file LICENSE. *)
-(* *)
-(**************************************************************************)
-
-open Int_misc
-
-type nat;;
-
-external create_nat: int -> nat = "create_nat"
-external set_to_zero_nat: nat -> int -> int -> unit = "set_to_zero_nat"
-external blit_nat: nat -> int -> nat -> int -> int -> unit = "blit_nat"
-external set_digit_nat: nat -> int -> int -> unit = "set_digit_nat"
-external nth_digit_nat: nat -> int -> int = "nth_digit_nat"
-external set_digit_nat_native: nat -> int -> nativeint -> unit
- = "set_digit_nat_native"
-external nth_digit_nat_native: nat -> int -> nativeint = "nth_digit_nat_native"
-external num_digits_nat: nat -> int -> int -> int = "num_digits_nat"
-external num_leading_zero_bits_in_digit: nat -> int -> int
- = "num_leading_zero_bits_in_digit"
-external is_digit_int: nat -> int -> bool = "is_digit_int"
-external is_digit_zero: nat -> int -> bool = "is_digit_zero"
-external is_digit_normalized: nat -> int -> bool = "is_digit_normalized"
-external is_digit_odd: nat -> int -> bool = "is_digit_odd"
-external incr_nat: nat -> int -> int -> int -> int = "incr_nat"
-external add_nat: nat -> int -> int -> nat -> int -> int -> int -> int
- = "add_nat" "add_nat_native"
-external complement_nat: nat -> int -> int -> unit = "complement_nat"
-external decr_nat: nat -> int -> int -> int -> int = "decr_nat"
-external sub_nat: nat -> int -> int -> nat -> int -> int -> int -> int
- = "sub_nat" "sub_nat_native"
-external mult_digit_nat:
- nat -> int -> int -> nat -> int -> int -> nat -> int -> int
- = "mult_digit_nat" "mult_digit_nat_native"
-external mult_nat:
- nat -> int -> int -> nat -> int -> int -> nat -> int -> int -> int
- = "mult_nat" "mult_nat_native"
-external square_nat: nat -> int -> int -> nat -> int -> int -> int
- = "square_nat" "square_nat_native"
-external shift_left_nat: nat -> int -> int -> nat -> int -> int -> unit
- = "shift_left_nat" "shift_left_nat_native"
-external div_digit_nat:
- nat -> int -> nat -> int -> nat -> int -> int -> nat -> int -> unit
- = "div_digit_nat" "div_digit_nat_native"
-external div_nat: nat -> int -> int -> nat -> int -> int -> unit
- = "div_nat" "div_nat_native"
-external shift_right_nat: nat -> int -> int -> nat -> int -> int -> unit
- = "shift_right_nat" "shift_right_nat_native"
-external compare_digits_nat: nat -> int -> nat -> int -> int
- = "compare_digits_nat"
-external compare_nat: nat -> int -> int -> nat -> int -> int -> int
- = "compare_nat" "compare_nat_native"
-external land_digit_nat: nat -> int -> nat -> int -> unit = "land_digit_nat"
-external lor_digit_nat: nat -> int -> nat -> int -> unit = "lor_digit_nat"
-external lxor_digit_nat: nat -> int -> nat -> int -> unit = "lxor_digit_nat"
-
-external initialize_nat: unit -> unit = "initialize_nat"
-let _ = initialize_nat()
-
-let length_nat (n : nat) = Obj.size (Obj.repr n) - 1
-
-let length_of_digit = Sys.word_size;;
-
-let make_nat len =
- if len < 0 then invalid_arg "make_nat" else
- let res = create_nat len in set_to_zero_nat res 0 len; res
-
-(* Nat temporaries *)
-let a_2 = make_nat 2
-and a_1 = make_nat 1
-and b_2 = make_nat 2
-
-let copy_nat nat off_set length =
- let res = create_nat (length) in
- blit_nat res 0 nat off_set length;
- res
-
-let is_zero_nat n off len =
- compare_nat (make_nat 1) 0 1 n off (num_digits_nat n off len) = 0
-
-let is_nat_int nat off len =
- num_digits_nat nat off len = 1 && is_digit_int nat off
-
-let sys_int_of_nat nat off len =
- if is_nat_int nat off len
- then nth_digit_nat nat off
- else failwith "int_of_nat"
-
-let int_of_nat nat =
- sys_int_of_nat nat 0 (length_nat nat)
-
-let nat_of_int i =
- if i < 0 then invalid_arg "nat_of_int" else
- let res = make_nat 1 in
- if i = 0 then res else begin set_digit_nat res 0 i; res end
-
-let eq_nat nat1 off1 len1 nat2 off2 len2 =
- compare_nat nat1 off1 (num_digits_nat nat1 off1 len1)
- nat2 off2 (num_digits_nat nat2 off2 len2) = 0
-and le_nat nat1 off1 len1 nat2 off2 len2 =
- compare_nat nat1 off1 (num_digits_nat nat1 off1 len1)
- nat2 off2 (num_digits_nat nat2 off2 len2) <= 0
-and lt_nat nat1 off1 len1 nat2 off2 len2 =
- compare_nat nat1 off1 (num_digits_nat nat1 off1 len1)
- nat2 off2 (num_digits_nat nat2 off2 len2) < 0
-and ge_nat nat1 off1 len1 nat2 off2 len2 =
- compare_nat nat1 off1 (num_digits_nat nat1 off1 len1)
- nat2 off2 (num_digits_nat nat2 off2 len2) >= 0
-and gt_nat nat1 off1 len1 nat2 off2 len2 =
- compare_nat nat1 off1 (num_digits_nat nat1 off1 len1)
- nat2 off2 (num_digits_nat nat2 off2 len2) > 0
-
-(* XL: now implemented in C for better performance.
- The code below doesn't handle carries correctly.
- Fortunately, the carry is never used. *)
-(***
-let square_nat nat1 off1 len1 nat2 off2 len2 =
- let c = ref 0
- and trash = make_nat 1 in
- (* Double product *)
- for i = 0 to len2 - 2 do
- c := !c + mult_digit_nat
- nat1
- (succ (off1 + 2 * i))
- (2 * (pred (len2 - i)))
- nat2
- (succ (off2 + i))
- (pred (len2 - i))
- nat2
- (off2 + i)
- done;
- shift_left_nat nat1 0 len1 trash 0 1;
- (* Square of digit *)
- for i = 0 to len2 - 1 do
- c := !c + mult_digit_nat
- nat1
- (off1 + 2 * i)
- (len1 - 2 * i)
- nat2
- (off2 + i)
- 1
- nat2
- (off2 + i)
- done;
- !c
-***)
-
-(*
-let gcd_int_nat i nat off len =
- if i = 0 then 1 else
- if is_nat_int nat off len then begin
- set_digit_nat nat off (gcd_int (nth_digit_nat nat off) i); 0
- end else begin
- let len_copy = succ len in
- let copy = create_nat len_copy
- and quotient = create_nat 1
- and remainder = create_nat 1 in
- blit_nat copy 0 nat off len;
- set_digit_nat copy len 0;
- div_digit_nat quotient 0 remainder 0 copy 0 len_copy (nat_of_int i) 0;
- set_digit_nat nat off (gcd_int (nth_digit_nat remainder 0) i);
- 0
- end
-*)
-
-let exchange r1 r2 =
- let old1 = !r1 in r1 := !r2; r2 := old1
-
-let gcd_nat nat1 off1 len1 nat2 off2 len2 =
- if is_zero_nat nat1 off1 len1 then begin
- blit_nat nat1 off1 nat2 off2 len2; len2
- end else begin
- let copy1 = ref (create_nat (succ len1))
- and copy2 = ref (create_nat (succ len2)) in
- blit_nat !copy1 0 nat1 off1 len1;
- blit_nat !copy2 0 nat2 off2 len2;
- set_digit_nat !copy1 len1 0;
- set_digit_nat !copy2 len2 0;
- if lt_nat !copy1 0 len1 !copy2 0 len2
- then exchange copy1 copy2;
- let real_len1 =
- ref (num_digits_nat !copy1 0 (length_nat !copy1))
- and real_len2 =
- ref (num_digits_nat !copy2 0 (length_nat !copy2)) in
- while not (is_zero_nat !copy2 0 !real_len2) do
- set_digit_nat !copy1 !real_len1 0;
- div_nat !copy1 0 (succ !real_len1) !copy2 0 !real_len2;
- exchange copy1 copy2;
- real_len1 := !real_len2;
- real_len2 := num_digits_nat !copy2 0 !real_len2
- done;
- blit_nat nat1 off1 !copy1 0 !real_len1;
- !real_len1
- end
-
-(* Integer square root using newton method (nearest integer by default) *)
-
-(* Theorem: the sequence x_{n+1} = ( x_n + a/x_n )/2 converges toward
- the integer square root (by default) of a for any starting value x_0
- strictly greater than the square root of a except if a + 1 is a
- perfect square. In this situation, the sequence alternates between
- the excess and default integer square root. In any case, the last
- strictly decreasing term is the expected result *)
-
-let sqrt_nat rad off len =
- let len = num_digits_nat rad off len in
- (* Working copy of radicand *)
- let len_parity = len mod 2 in
- let rad_len = len + 1 + len_parity in
- let rad =
- let res = create_nat rad_len in
- blit_nat res 0 rad off len;
- set_digit_nat res len 0;
- set_digit_nat res (rad_len - 1) 0;
- res in
- let cand_len = (len + 1) / 2 in (* ceiling len / 2 *)
- let cand_rest = rad_len - cand_len in
- (* Candidate square root cand = "|FFFF .... |" *)
- let cand = make_nat cand_len in
- (* Improve starting square root:
- We compute nbb, the number of significant bits of the first digit of the
- candidate
- (half of the number of significant bits in the first two digits
- of the radicand extended to an even length).
- shift_cand is word_size - nbb *)
- let shift_cand =
- ((num_leading_zero_bits_in_digit rad (len-1)) +
- Sys.word_size * len_parity) / 2 in
- (* All radicand bits are zeroed, we give back 0. *)
- if shift_cand = Sys.word_size then cand else
- begin
- complement_nat cand 0 cand_len;
- shift_right_nat cand 0 1 a_1 0 shift_cand;
- let next_cand = create_nat rad_len in
- (* Repeat until *)
- let rec loop () =
- (* next_cand := rad *)
- blit_nat next_cand 0 rad 0 rad_len;
- (* next_cand <- next_cand / cand *)
- div_nat next_cand 0 rad_len cand 0 cand_len;
- (* next_cand (strong weight) <- next_cand (strong weight) + cand,
- i.e. next_cand <- cand + rad / cand *)
- ignore (add_nat next_cand cand_len cand_rest cand 0 cand_len 0);
- (* next_cand <- next_cand / 2 *)
- shift_right_nat next_cand cand_len cand_rest a_1 0 1;
- if lt_nat next_cand cand_len cand_rest cand 0 cand_len then
- begin (* cand <- next_cand *)
- blit_nat cand 0 next_cand cand_len cand_len; loop ()
- end
- else cand in
- loop ()
- end;;
-
-let power_base_max = make_nat 2;;
-
-match length_of_digit with
- | 64 ->
- set_digit_nat power_base_max 0 (Int64.to_int 1000000000000000000L);
- ignore
- (mult_digit_nat power_base_max 0 2
- power_base_max 0 1 (nat_of_int 9) 0)
- | 32 -> set_digit_nat power_base_max 0 1000000000
- | _ -> assert false
-;;
-
-let pmax =
- match length_of_digit with
- | 64 -> 19
- | 32 -> 9
- | _ -> assert false
-;;
-
-let max_superscript_10_power_in_int =
- match length_of_digit with
- | 64 -> 18
- | 32 -> 9
- | _ -> assert false
-;;
-let max_power_10_power_in_int =
- match length_of_digit with
- | 64 -> nat_of_int (Int64.to_int 1000000000000000000L)
- | 32 -> nat_of_int 1000000000
- | _ -> assert false
-;;
-
-let raw_string_of_digit nat off =
- if is_nat_int nat off 1
- then begin string_of_int (nth_digit_nat nat off) end
- else begin
- blit_nat b_2 0 nat off 1;
- div_digit_nat a_2 0 a_1 0 b_2 0 2 max_power_10_power_in_int 0;
- let leading_digits = nth_digit_nat a_2 0
- and s1 = string_of_int (nth_digit_nat a_1 0) in
- let len = String.length s1 in
- if leading_digits < 10 then begin
- let result = Bytes.make (max_superscript_10_power_in_int+1) '0' in
- Bytes.set result 0 (Char.chr (48 + leading_digits));
- String.blit s1 0 result (Bytes.length result - len) len;
- Bytes.to_string result
- end else begin
- let result = Bytes.make (max_superscript_10_power_in_int+2) '0' in
- String.blit (string_of_int leading_digits) 0 result 0 2;
- String.blit s1 0 result (Bytes.length result - len) len;
- Bytes.to_string result
- end
- end
-
-(* XL: suppression de string_of_digit et de sys_string_of_digit.
- La copie est de toute facon faite dans string_of_nat, qui est le
- seul point d entree public dans ce code.
-
- | Deletion of string_of_digit and sys_string_of_digit.
- The copy is already done in string_of_nat which is the only
- public entry point in this code
-
-*)
-
-(******
-let sys_string_of_digit nat off =
- let s = raw_string_of_digit nat off in
- let result = String.create (String.length s) in
- String.blit s 0 result 0 (String.length s);
- s
-
-let string_of_digit nat =
- sys_string_of_digit nat 0
-
-*******)
-
-(*
- make_power_base affecte power_base des puissances successives de base a
- partir de la puissance 1-ieme.
- A la fin de la boucle i-1 est la plus grande puissance de la base qui tient
- sur un seul digit et j est la plus grande puissance de la base qui tient
- sur un int.
-
- This function returns [(pmax, pint)] where:
- [pmax] is the index of the digit of [power_base] that contains the
- the maximum power of [base] that fits in a digit. This is also one
- less than the exponent of that power.
- [pint] is the exponent of the maximum power of [base] that fits in an [int].
-*)
-let make_power_base base power_base =
- let i = ref 0
- and j = ref 0 in
- set_digit_nat power_base 0 base;
- while incr i; is_digit_zero power_base !i do
- ignore
- (mult_digit_nat power_base !i 2
- power_base (pred !i) 1
- power_base 0)
- done;
- while !j < !i - 1 && is_digit_int power_base !j do incr j done;
- (!i - 2, !j)
-
-(*
-(*
- int_to_string places the representation of the integer int in base 'base'
- in the string s by starting from the end position pos and going towards
- the start, for 'times' places and updates the value of pos.
-*)
-let digits = "0123456789ABCDEF"
-
-let int_to_string int s pos_ref base times =
- let i = ref int
- and j = ref times in
- while ((!i != 0) || (!j != 0)) && (!pos_ref != -1) do
- Bytes.set s !pos_ref (String.get digits (!i mod base));
- decr pos_ref;
- decr j;
- i := !i / base
- done
-*)
-
-let power_base_int base i =
- if i = 0 || base = 1 then
- nat_of_int 1
- else if base = 0 then
- nat_of_int 0
- else if i < 0 then
- invalid_arg "power_base_int"
- else begin
- let power_base = make_nat (succ length_of_digit) in
- let (pmax, _pint) = make_power_base base power_base in
- let n = i / (succ pmax)
- and rem = i mod (succ pmax) in
- if n > 0 then begin
- let newn =
- if i = biggest_int then n else (succ n) in
- let res = make_nat newn
- and res2 = make_nat newn
- and l = num_bits_int n - 2 in
- blit_nat res 0 power_base pmax 1;
- for i = l downto 0 do
- let len = num_digits_nat res 0 newn in
- let len2 = min n (2 * len) in
- let succ_len2 = succ len2 in
- ignore (square_nat res2 0 len2 res 0 len);
- if n land (1 lsl i) > 0 then begin
- set_to_zero_nat res 0 len;
- ignore
- (mult_digit_nat res 0 succ_len2
- res2 0 len2 power_base pmax)
- end else
- blit_nat res 0 res2 0 len2;
- set_to_zero_nat res2 0 len2
- done;
- if rem > 0 then begin
- ignore
- (mult_digit_nat res2 0 newn
- res 0 n power_base (pred rem));
- res2
- end else res
- end else
- copy_nat power_base (pred rem) 1
- end
-
-(* the ith element (i >= 2) of num_digits_max_vector is :
- | |
- | biggest_string_length * log (i) |
- | ------------------------------- | + 1
- | length_of_digit * log (2) |
- -- --
-*)
-
-(* XL: ai specialise le code d origine a length_of_digit = 32.
- | the original code have been specialized to a length_of_digit = 32. *)
-(* Now deleted (useless?) *)
-
-(******
-let num_digits_max_vector =
- [|0; 0; 1024; 1623; 2048; 2378; 2647; 2875; 3072; 3246; 3402;
- 3543; 3671; 3789; 3899; 4001; 4096|]
-
-let num_digits_max_vector =
- match length_of_digit with
- 16 -> [|0; 0; 2048; 3246; 4096; 4755; 5294; 5749; 6144; 6492; 6803;
- 7085; 7342; 7578; 7797; 8001; 8192|]
-(* If really exotic machines !!!!
- | 17 -> [|0; 0; 1928; 3055; 3855; 4476; 4983; 5411; 5783; 6110; 6403;
- 6668; 6910; 7133; 7339; 7530; 7710|]
- | 18 -> [|0; 0; 1821; 2886; 3641; 4227; 4706; 5111; 5461; 5771; 6047;
- 6298; 6526; 6736; 6931; 7112; 7282|]
- | 19 -> [|0; 0; 1725; 2734; 3449; 4005; 4458; 4842; 5174; 5467; 5729;
- 5966; 6183; 6382; 6566; 6738; 6898|]
- | 20 -> [|0; 0; 1639; 2597; 3277; 3804; 4235; 4600; 4915; 5194; 5443;
- 5668; 5874; 6063; 6238; 6401; 6553|]
- | 21 -> [|0; 0; 1561; 2473; 3121; 3623; 4034; 4381; 4681; 4946; 5183;
- 5398; 5594; 5774; 5941; 6096; 6241|]
- | 22 -> [|0; 0; 1490; 2361; 2979; 3459; 3850; 4182; 4468; 4722; 4948;
- 5153; 5340; 5512; 5671; 5819; 5958|]
- | 23 -> [|0; 0; 1425; 2258; 2850; 3308; 3683; 4000; 4274; 4516; 4733;
- 4929; 5108; 5272; 5424; 5566; 5699|]
- | 24 -> [|0; 0; 1366; 2164; 2731; 3170; 3530; 3833; 4096; 4328; 4536;
- 4723; 4895; 5052; 5198; 5334; 5461|]
- | 25 -> [|0; 0; 1311; 2078; 2622; 3044; 3388; 3680; 3932; 4155; 4354;
- 4534; 4699; 4850; 4990; 5121; 5243|]
- | 26 -> [|0; 0; 1261; 1998; 2521; 2927; 3258; 3538; 3781; 3995; 4187;
- 4360; 4518; 4664; 4798; 4924; 5041|]
- | 27 -> [|0; 0; 1214; 1924; 2428; 2818; 3137; 3407; 3641; 3847; 4032;
- 4199; 4351; 4491; 4621; 4742; 4855|]
- | 28 -> [|0; 0; 1171; 1855; 2341; 2718; 3025; 3286; 3511; 3710; 3888;
- 4049; 4196; 4331; 4456; 4572; 4681|]
- | 29 -> [|0; 0; 1130; 1791; 2260; 2624; 2921; 3172; 3390; 3582; 3754;
- 3909; 4051; 4181; 4302; 4415; 4520|]
- | 30 -> [|0; 0; 1093; 1732; 2185; 2536; 2824; 3067; 3277; 3463; 3629;
- 3779; 3916; 4042; 4159; 4267; 4369|]
- | 31 -> [|0; 0; 1057; 1676; 2114; 2455; 2733; 2968; 3171; 3351; 3512;
- 3657; 3790; 3912; 4025; 4130; 4228|]
-*)
- | 32 -> [|0; 0; 1024; 1623; 2048; 2378; 2647; 2875; 3072; 3246; 3402;
- 3543; 3671; 3789; 3899; 4001; 4096|]
- | n -> failwith "num_digits_max_vector"
-******)
-
-let unadjusted_string_of_nat nat off len_nat =
- let len = num_digits_nat nat off len_nat in
- if len = 1 then
- raw_string_of_digit nat off
- else
- let len_copy = ref (succ len) in
- let copy1 = create_nat !len_copy
- and copy2 = make_nat !len_copy
- and rest_digit = make_nat 2 in
- if len > biggest_int / (succ pmax)
- then failwith "number too long"
- else let len_s = (succ pmax) * len in
- let s = Bytes.make len_s '0'
- and pos_ref = ref len_s in
- len_copy := pred !len_copy;
- blit_nat copy1 0 nat off len;
- set_digit_nat copy1 len 0;
- while not (is_zero_nat copy1 0 !len_copy) do
- div_digit_nat copy2 0
- rest_digit 0
- copy1 0 (succ !len_copy)
- power_base_max 0;
- let str = raw_string_of_digit rest_digit 0 in
- String.blit str 0
- s (!pos_ref - String.length str)
- (String.length str);
- pos_ref := !pos_ref - pmax;
- len_copy := num_digits_nat copy2 0 !len_copy;
- blit_nat copy1 0 copy2 0 !len_copy;
- set_digit_nat copy1 !len_copy 0
- done;
- Bytes.unsafe_to_string s
-
-let string_of_nat nat =
- let s = unadjusted_string_of_nat nat 0 (length_nat nat)
- and index = ref 0 in
- begin try
- for i = 0 to String.length s - 2 do
- if String.get s i <> '0' then (index:= i; raise Exit)
- done
- with Exit -> ()
- end;
- String.sub s !index (String.length s - !index)
-
-let base_digit_of_char c base =
- let n = Char.code c in
- if n >= 48 && n <= 47 + min base 10 then n - 48
- else if n >= 65 && n <= 65 + base - 11 then n - 55
- else if n >= 97 && n <= 97 + base - 11 then n - 87
- else failwith "invalid digit"
-
-(*
- The substring (s, off, len) represents a nat in base 'base' which is
-determined here
-*)
-let sys_nat_of_string base s off len =
- let power_base = make_nat (succ length_of_digit) in
- let (pmax, pint) = make_power_base base power_base in
- let new_len = ref (1 + len / (pmax + 1))
- and current_len = ref 1 in
- let possible_len = ref (min 2 !new_len) in
-
- let nat1 = make_nat !new_len
- and nat2 = make_nat !new_len
-
- and digits_read = ref 0
- and bound = off + len - 1
- and int = ref 0 in
-
- for i = off to bound do
- (*
- we read (at most) pint digits, we transform them in a int
- and integrate it to the number
- *)
- let c = String.get s i in
- begin match c with
- ' ' | '\t' | '\n' | '\r' | '\\' -> ()
- | '_' when i > off -> ()
- | _ -> int := !int * base + base_digit_of_char c base;
- incr digits_read
- end;
- if (!digits_read = pint || i = bound) && not (!digits_read = 0) then
- begin
- set_digit_nat nat1 0 !int;
- let erase_len = if !new_len = !current_len then !current_len - 1
- else !current_len in
- for j = 1 to erase_len do
- set_digit_nat nat1 j 0
- done;
- ignore
- (mult_digit_nat nat1 0 !possible_len
- nat2 0 !current_len power_base (pred !digits_read));
- blit_nat nat2 0 nat1 0 !possible_len;
- current_len := num_digits_nat nat1 0 !possible_len;
- possible_len := min !new_len (succ !current_len);
- int := 0;
- digits_read := 0
- end
- done;
- (*
- We reframe nat
- *)
- let nat = create_nat !current_len in
- blit_nat nat 0 nat1 0 !current_len;
- nat
-
-let nat_of_string s = sys_nat_of_string 10 s 0 (String.length s)
-
-let float_of_nat nat = float_of_string(string_of_nat nat)
+++ /dev/null
-(**************************************************************************)
-(* *)
-(* OCaml *)
-(* *)
-(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *)
-(* *)
-(* Copyright 1996 Institut National de Recherche en Informatique et *)
-(* en Automatique. *)
-(* *)
-(* All rights reserved. This file is distributed under the terms of *)
-(* the GNU Lesser General Public License version 2.1, with the *)
-(* special exception on linking described in the file LICENSE. *)
-(* *)
-(**************************************************************************)
-
-(* Module [Nat]: operations on natural numbers *)
-
-type nat
-
-(* Natural numbers (type [nat]) are positive integers of arbitrary size.
- All operations on [nat] are performed in-place. *)
-
-external create_nat: int -> nat = "create_nat"
-val make_nat: int -> nat
-external set_to_zero_nat: nat -> int -> int -> unit = "set_to_zero_nat"
-external blit_nat: nat -> int -> nat -> int -> int -> unit = "blit_nat"
-val copy_nat: nat -> int -> int -> nat
-external set_digit_nat: nat -> int -> int -> unit = "set_digit_nat"
-external nth_digit_nat: nat -> int -> int = "nth_digit_nat"
-external set_digit_nat_native: nat -> int -> nativeint -> unit
- = "set_digit_nat_native"
-external nth_digit_nat_native: nat -> int -> nativeint = "nth_digit_nat_native"
-val length_nat : nat -> int
-external num_digits_nat: nat -> int -> int -> int = "num_digits_nat"
-external num_leading_zero_bits_in_digit: nat -> int -> int
- = "num_leading_zero_bits_in_digit"
-external is_digit_int: nat -> int -> bool = "is_digit_int"
-external is_digit_zero: nat -> int -> bool = "is_digit_zero"
-external is_digit_normalized: nat -> int -> bool = "is_digit_normalized"
-external is_digit_odd: nat -> int -> bool = "is_digit_odd"
-val is_zero_nat: nat -> int -> int -> bool
-val is_nat_int: nat -> int -> int -> bool
-val int_of_nat: nat -> int
-val nat_of_int: int -> nat
-external incr_nat: nat -> int -> int -> int -> int = "incr_nat"
-external add_nat: nat -> int -> int -> nat -> int -> int -> int -> int
- = "add_nat" "add_nat_native"
-external complement_nat: nat -> int -> int -> unit = "complement_nat"
-external decr_nat: nat -> int -> int -> int -> int = "decr_nat"
-external sub_nat: nat -> int -> int -> nat -> int -> int -> int -> int
- = "sub_nat" "sub_nat_native"
-external mult_digit_nat:
- nat -> int -> int -> nat -> int -> int -> nat -> int -> int
- = "mult_digit_nat" "mult_digit_nat_native"
-external mult_nat:
- nat -> int -> int -> nat -> int -> int -> nat -> int -> int -> int
- = "mult_nat" "mult_nat_native"
-external square_nat: nat -> int -> int -> nat -> int -> int -> int
- = "square_nat" "square_nat_native"
-external shift_left_nat: nat -> int -> int -> nat -> int -> int -> unit
- = "shift_left_nat" "shift_left_nat_native"
-external div_digit_nat:
- nat -> int -> nat -> int -> nat -> int -> int -> nat -> int -> unit
- = "div_digit_nat" "div_digit_nat_native"
-external div_nat: nat -> int -> int -> nat -> int -> int -> unit
- = "div_nat" "div_nat_native"
-external shift_right_nat: nat -> int -> int -> nat -> int -> int -> unit
- = "shift_right_nat" "shift_right_nat_native"
-external compare_digits_nat: nat -> int -> nat -> int -> int
- = "compare_digits_nat"
-external compare_nat: nat -> int -> int -> nat -> int -> int -> int
- = "compare_nat" "compare_nat_native"
-val eq_nat : nat -> int -> int -> nat -> int -> int -> bool
-val le_nat : nat -> int -> int -> nat -> int -> int -> bool
-val lt_nat : nat -> int -> int -> nat -> int -> int -> bool
-val ge_nat : nat -> int -> int -> nat -> int -> int -> bool
-val gt_nat : nat -> int -> int -> nat -> int -> int -> bool
-external land_digit_nat: nat -> int -> nat -> int -> unit = "land_digit_nat"
-external lor_digit_nat: nat -> int -> nat -> int -> unit = "lor_digit_nat"
-external lxor_digit_nat: nat -> int -> nat -> int -> unit = "lxor_digit_nat"
-val gcd_nat : nat -> int -> int -> nat -> int -> int -> int
-val sqrt_nat : nat -> int -> int -> nat
-val string_of_nat : nat -> string
-val nat_of_string : string -> nat
-val sys_nat_of_string : int -> string -> int -> int -> nat
-val float_of_nat : nat -> float
-val make_power_base : int -> nat -> int * int
-val power_base_int : int -> int -> nat
-val length_of_digit: int
+++ /dev/null
-/**************************************************************************/
-/* */
-/* OCaml */
-/* */
-/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */
-/* */
-/* Copyright 1996 Institut National de Recherche en Informatique et */
-/* en Automatique. */
-/* */
-/* All rights reserved. This file is distributed under the terms of */
-/* the GNU Lesser General Public License version 2.1, with the */
-/* special exception on linking described in the file LICENSE. */
-/* */
-/**************************************************************************/
-
-#define CAML_INTERNALS
-
-#include "caml/alloc.h"
-#include "caml/config.h"
-#include "caml/custom.h"
-#include "caml/intext.h"
-#include "caml/fail.h"
-#include "caml/hash.h"
-#include "caml/memory.h"
-#include "caml/mlvalues.h"
-
-#include "bng.h"
-#include "nat.h"
-
-/* Stub code for the Nat module. */
-
-static intnat hash_nat(value);
-static void serialize_nat(value, uintnat *, uintnat *);
-static uintnat deserialize_nat(void * dst);
-
-static struct custom_operations nat_operations = {
- "_nat",
- custom_finalize_default,
- custom_compare_default,
- hash_nat,
- serialize_nat,
- deserialize_nat,
- custom_compare_ext_default
-};
-
-CAMLprim value initialize_nat(value unit)
-{
- bng_init();
- caml_register_custom_operations(&nat_operations);
- return Val_unit;
-}
-
-CAMLprim value create_nat(value size)
-{
- mlsize_t sz = Long_val(size);
-
- return caml_alloc_custom(&nat_operations, sz * sizeof(value), 0, 1);
-}
-
-CAMLprim value length_nat(value nat)
-{
- return Val_long(Wosize_val(nat) - 1);
-}
-
-CAMLprim value set_to_zero_nat(value nat, value ofs, value len)
-{
- bng_zero(&Digit_val(nat, Long_val(ofs)), Long_val(len));
- return Val_unit;
-}
-
-CAMLprim value blit_nat(value nat1, value ofs1,
- value nat2, value ofs2,
- value len)
-{
- bng_assign(&Digit_val(nat1, Long_val(ofs1)),
- &Digit_val(nat2, Long_val(ofs2)),
- Long_val(len));
- return Val_unit;
-}
-
-CAMLprim value set_digit_nat(value nat, value ofs, value digit)
-{
- Digit_val(nat, Long_val(ofs)) = Long_val(digit);
- return Val_unit;
-}
-
-CAMLprim value nth_digit_nat(value nat, value ofs)
-{
- return Val_long(Digit_val(nat, Long_val(ofs)));
-}
-
-CAMLprim value set_digit_nat_native(value nat, value ofs, value digit)
-{
- Digit_val(nat, Long_val(ofs)) = Nativeint_val(digit);
- return Val_unit;
-}
-
-CAMLprim value nth_digit_nat_native(value nat, value ofs)
-{
- return caml_copy_nativeint(Digit_val(nat, Long_val(ofs)));
-}
-
-CAMLprim value num_digits_nat(value nat, value ofs, value len)
-{
- return Val_long(bng_num_digits(&Digit_val(nat, Long_val(ofs)),
- Long_val(len)));
-}
-
-CAMLprim value num_leading_zero_bits_in_digit(value nat, value ofs)
-{
- return
- Val_long(bng_leading_zero_bits(Digit_val(nat, Long_val(ofs))));
-}
-
-CAMLprim value is_digit_int(value nat, value ofs)
-{
- return Val_bool(Digit_val(nat, Long_val(ofs)) <= Max_long);
-}
-
-CAMLprim value is_digit_zero(value nat, value ofs)
-{
- return Val_bool(Digit_val(nat, Long_val(ofs)) == 0);
-}
-
-CAMLprim value is_digit_normalized(value nat, value ofs)
-{
- return
- Val_bool(Digit_val(nat, Long_val(ofs))
- & ((bngdigit)1 << (BNG_BITS_PER_DIGIT-1)));
-}
-
-CAMLprim value is_digit_odd(value nat, value ofs)
-{
- return Val_bool(Digit_val(nat, Long_val(ofs)) & 1);
-}
-
-CAMLprim value incr_nat(value nat, value ofs, value len, value carry_in)
-{
- return Val_long(bng_add_carry(&Digit_val(nat, Long_val(ofs)),
- Long_val(len), Long_val(carry_in)));
-}
-
-value add_nat_native(value nat1, value ofs1, value len1,
- value nat2, value ofs2, value len2, value carry_in)
-{
- return Val_long(bng_add(&Digit_val(nat1, Long_val(ofs1)), Long_val(len1),
- &Digit_val(nat2, Long_val(ofs2)), Long_val(len2),
- Long_val(carry_in)));
-}
-
-CAMLprim value add_nat(value *argv, int argn)
-{
- return add_nat_native(argv[0], argv[1], argv[2], argv[3],
- argv[4], argv[5], argv[6]);
-}
-
-CAMLprim value complement_nat(value nat, value ofs, value len)
-{
- bng_complement(&Digit_val(nat, Long_val(ofs)), Long_val(len));
- return Val_unit;
-}
-
-CAMLprim value decr_nat(value nat, value ofs, value len, value carry_in)
-{
- return Val_long(1 ^ bng_sub_carry(&Digit_val(nat, Long_val(ofs)),
- Long_val(len), 1 ^ Long_val(carry_in)));
-}
-
-value sub_nat_native(value nat1, value ofs1, value len1,
- value nat2, value ofs2, value len2, value carry_in)
-{
- return Val_long(1 ^ bng_sub(&Digit_val(nat1, Long_val(ofs1)), Long_val(len1),
- &Digit_val(nat2, Long_val(ofs2)), Long_val(len2),
- 1 ^ Long_val(carry_in)));
-}
-
-CAMLprim value sub_nat(value *argv, int argn)
-{
- return sub_nat_native(argv[0], argv[1], argv[2], argv[3],
- argv[4], argv[5], argv[6]);
-}
-
-value mult_digit_nat_native(value nat1, value ofs1, value len1,
- value nat2, value ofs2, value len2,
- value nat3, value ofs3)
-{
- return
- Val_long(bng_mult_add_digit(
- &Digit_val(nat1, Long_val(ofs1)), Long_val(len1),
- &Digit_val(nat2, Long_val(ofs2)), Long_val(len2),
- Digit_val(nat3, Long_val(ofs3))));
-}
-
-CAMLprim value mult_digit_nat(value *argv, int argn)
-{
- return mult_digit_nat_native(argv[0], argv[1], argv[2], argv[3],
- argv[4], argv[5], argv[6], argv[7]);
-}
-
-value mult_nat_native(value nat1, value ofs1, value len1,
- value nat2, value ofs2, value len2,
- value nat3, value ofs3, value len3)
-{
- return
- Val_long(bng_mult_add(&Digit_val(nat1, Long_val(ofs1)), Long_val(len1),
- &Digit_val(nat2, Long_val(ofs2)), Long_val(len2),
- &Digit_val(nat3, Long_val(ofs3)), Long_val(len3)));
-}
-
-CAMLprim value mult_nat(value *argv, int argn)
-{
- return mult_nat_native(argv[0], argv[1], argv[2], argv[3],
- argv[4], argv[5], argv[6], argv[7], argv[8]);
-}
-
-value square_nat_native(value nat1, value ofs1, value len1,
- value nat2, value ofs2, value len2)
-{
- return
- Val_long(bng_square_add(&Digit_val(nat1, Long_val(ofs1)), Long_val(len1),
- &Digit_val(nat2, Long_val(ofs2)), Long_val(len2)));
-}
-
-CAMLprim value square_nat(value *argv, int argn)
-{
- return square_nat_native(argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5]);
-}
-
-value shift_left_nat_native(value nat1, value ofs1, value len1,
- value nat2, value ofs2, value nbits)
-{
- Digit_val(nat2, Long_val(ofs2)) =
- bng_shift_left(&Digit_val(nat1, Long_val(ofs1)), Long_val(len1),
- Long_val(nbits));
- return Val_unit;
-}
-
-CAMLprim value shift_left_nat(value *argv, int argn)
-{
- return shift_left_nat_native(argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5]);
-}
-
-value div_digit_nat_native(value natq, value ofsq,
- value natr, value ofsr,
- value nat1, value ofs1, value len1,
- value nat2, value ofs2)
-{
- Digit_val(natr, Long_val(ofsr)) =
- bng_div_rem_digit(&Digit_val(natq, Long_val(ofsq)),
- &Digit_val(nat1, Long_val(ofs1)), Long_val(len1),
- Digit_val(nat2, Long_val(ofs2)));
- return Val_unit;
-}
-
-CAMLprim value div_digit_nat(value *argv, int argn)
-{
- return div_digit_nat_native(argv[0], argv[1], argv[2], argv[3],
- argv[4], argv[5], argv[6], argv[7], argv[8]);
-}
-
-value div_nat_native(value nat1, value ofs1, value len1,
- value nat2, value ofs2, value len2)
-{
- bng_div_rem(&Digit_val(nat1, Long_val(ofs1)), Long_val(len1),
- &Digit_val(nat2, Long_val(ofs2)), Long_val(len2));
- return Val_unit;
-}
-
-CAMLprim value div_nat(value *argv, int argn)
-{
- return div_nat_native(argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5]);
-}
-
-value shift_right_nat_native(value nat1, value ofs1, value len1,
- value nat2, value ofs2, value nbits)
-{
- Digit_val(nat2, Long_val(ofs2)) =
- bng_shift_right(&Digit_val(nat1, Long_val(ofs1)), Long_val(len1),
- Long_val(nbits));
- return Val_unit;
-}
-
-CAMLprim value shift_right_nat(value *argv, int argn)
-{
- return shift_right_nat_native(argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5]);
-}
-
-CAMLprim value compare_digits_nat(value nat1, value ofs1,
- value nat2, value ofs2)
-{
- bngdigit d1 = Digit_val(nat1, Long_val(ofs1));
- bngdigit d2 = Digit_val(nat2, Long_val(ofs2));
- if (d1 > d2) return Val_int(1);
- if (d1 < d2) return Val_int(-1);
- return Val_int(0);
-}
-
-value compare_nat_native(value nat1, value ofs1, value len1,
- value nat2, value ofs2, value len2)
-{
- return
- Val_int(bng_compare(&Digit_val(nat1, Long_val(ofs1)), Long_val(len1),
- &Digit_val(nat2, Long_val(ofs2)), Long_val(len2)));
-}
-
-CAMLprim value compare_nat(value *argv, int argn)
-{
- return compare_nat_native(argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5]);
-}
-
-CAMLprim value land_digit_nat(value nat1, value ofs1, value nat2, value ofs2)
-{
- Digit_val(nat1, Long_val(ofs1)) &= Digit_val(nat2, Long_val(ofs2));
- return Val_unit;
-}
-
-CAMLprim value lor_digit_nat(value nat1, value ofs1, value nat2, value ofs2)
-{
- Digit_val(nat1, Long_val(ofs1)) |= Digit_val(nat2, Long_val(ofs2));
- return Val_unit;
-}
-
-CAMLprim value lxor_digit_nat(value nat1, value ofs1, value nat2, value ofs2)
-{
- Digit_val(nat1, Long_val(ofs1)) ^= Digit_val(nat2, Long_val(ofs2));
- return Val_unit;
-}
-
-/* The wire format for a nat is:
- - 32-bit word: number of 32-bit words in nat
- - N 32-bit words (big-endian format)
- For little-endian platforms, the memory layout between 32-bit and 64-bit
- machines is identical, so we can write the nat using caml_serialize_block_4.
- For big-endian 64-bit platforms, we need to swap the two 32-bit halves
- of 64-bit words to obtain the correct behavior. */
-
-static void serialize_nat(value nat,
- uintnat * wsize_32,
- uintnat * wsize_64)
-{
- mlsize_t len = Wosize_val(nat) - 1;
-
-#ifdef ARCH_SIXTYFOUR
- len = len * 2; /* two 32-bit words per 64-bit digit */
- if (len >= ((mlsize_t)1 << 32))
- caml_failwith("output_value: nat too big");
-#endif
- caml_serialize_int_4((int32_t) len);
-#if defined(ARCH_SIXTYFOUR) && defined(ARCH_BIG_ENDIAN)
- { int32_t * p;
- mlsize_t i;
- for (i = len, p = Data_custom_val(nat); i > 0; i -= 2, p += 2) {
- caml_serialize_int_4(p[1]); /* low 32 bits of 64-bit digit */
- caml_serialize_int_4(p[0]); /* high 32 bits of 64-bit digit */
- }
- }
-#else
- caml_serialize_block_4(Data_custom_val(nat), len);
-#endif
- *wsize_32 = len * 4;
- *wsize_64 = len * 4;
-}
-
-static uintnat deserialize_nat(void * dst)
-{
- mlsize_t len;
-
- len = caml_deserialize_uint_4();
-#if defined(ARCH_SIXTYFOUR) && defined(ARCH_BIG_ENDIAN)
- { uint32_t * p;
- mlsize_t i;
- for (i = len, p = dst; i > 1; i -= 2, p += 2) {
- p[1] = caml_deserialize_uint_4(); /* low 32 bits of 64-bit digit */
- p[0] = caml_deserialize_uint_4(); /* high 32 bits of 64-bit digit */
- }
- if (i > 0){
- p[1] = caml_deserialize_uint_4(); /* low 32 bits of 64-bit digit */
- p[0] = 0; /* high 32 bits of 64-bit digit */
- ++ len;
- }
- }
-#else
- caml_deserialize_block_4(dst, len);
-#if defined(ARCH_SIXTYFOUR)
- if (len & 1){
- ((uint32_t *) dst)[len] = 0;
- ++ len;
- }
-#endif
-#endif
- return len * 4;
-}
-
-static intnat hash_nat(value v)
-{
- bngsize len, i;
- uint32_t h;
-
- len = bng_num_digits(&Digit_val(v,0), Wosize_val(v) - 1);
- h = 0;
- for (i = 0; i < len; i++) {
- bngdigit d = Digit_val(v, i);
-#ifdef ARCH_SIXTYFOUR
- /* Mix the two 32-bit halves as if we were on a 32-bit platform,
- namely low 32 bits first, then high 32 bits.
- Also, ignore final 32 bits if they are zero. */
- h = caml_hash_mix_uint32(h, (uint32_t) d);
- d = d >> 32;
- if (d == 0 && i + 1 == len) break;
- h = caml_hash_mix_uint32(h, (uint32_t) d);
-#else
- h = caml_hash_mix_uint32(h, d);
-#endif
- }
- return h;
-}
+++ /dev/null
-(**************************************************************************)
-(* *)
-(* OCaml *)
-(* *)
-(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *)
-(* *)
-(* Copyright 1996 Institut National de Recherche en Informatique et *)
-(* en Automatique. *)
-(* *)
-(* All rights reserved. This file is distributed under the terms of *)
-(* the GNU Lesser General Public License version 2.1, with the *)
-(* special exception on linking described in the file LICENSE. *)
-(* *)
-(**************************************************************************)
-
-open Int_misc
-open Nat
-open Big_int
-open Arith_flags
-open Ratio
-
-type num = Int of int | Big_int of big_int | Ratio of ratio
- (* The type of numbers. *)
-
-let biggest_INT = big_int_of_int biggest_int
-and least_INT = big_int_of_int least_int
-
-(* Coercion big_int -> num *)
-let num_of_big_int bi =
- if le_big_int bi biggest_INT && ge_big_int bi least_INT
- then Int (int_of_big_int bi)
- else Big_int bi
-
-let normalize_num = function
- Int i -> Int i
-| Big_int bi -> num_of_big_int bi
-| Ratio r -> if is_integer_ratio r
- then num_of_big_int (numerator_ratio r)
- else Ratio r
-
-let cautious_normalize_num_when_printing n =
- if (!normalize_ratio_when_printing_flag) then (normalize_num n) else n
-
-let num_of_ratio r =
- ignore (normalize_ratio r);
- if not (is_integer_ratio r) then Ratio r
- else if is_int_big_int (numerator_ratio r) then
- Int (int_of_big_int (numerator_ratio r))
- else Big_int (numerator_ratio r)
-
-(* Operations on num *)
-
-let add_num a b = match (a,b) with
- ((Int int1), (Int int2)) ->
- let r = int1 + int2 in
- if (int1 lxor int2) lor (int1 lxor (r lxor (-1))) < 0
- then Int r (* No overflow *)
- else Big_int(add_big_int (big_int_of_int int1) (big_int_of_int int2))
- | ((Int i), (Big_int bi)) ->
- num_of_big_int (add_int_big_int i bi)
- | ((Big_int bi), (Int i)) ->
- num_of_big_int (add_int_big_int i bi)
-
- | ((Int i), (Ratio r)) ->
- Ratio (add_int_ratio i r)
- | ((Ratio r), (Int i)) ->
- Ratio (add_int_ratio i r)
-
- | ((Big_int bi1), (Big_int bi2)) -> num_of_big_int (add_big_int bi1 bi2)
-
- | ((Big_int bi), (Ratio r)) ->
- Ratio (add_big_int_ratio bi r)
- | ((Ratio r), (Big_int bi)) ->
- Ratio (add_big_int_ratio bi r)
-
- | ((Ratio r1), (Ratio r2)) -> num_of_ratio (add_ratio r1 r2)
-
-let ( +/ ) = add_num
-
-let minus_num = function
- Int i -> if i = monster_int
- then Big_int (minus_big_int (big_int_of_int i))
- else Int (-i)
-| Big_int bi -> Big_int (minus_big_int bi)
-| Ratio r -> Ratio (minus_ratio r)
-
-let sub_num n1 n2 = add_num n1 (minus_num n2)
-
-let ( -/ ) = sub_num
-
-let mult_num a b = match (a,b) with
- ((Int int1), (Int int2)) ->
- if num_bits_int int1 + num_bits_int int2 < length_of_int
- then Int (int1 * int2)
- else num_of_big_int (mult_big_int (big_int_of_int int1)
- (big_int_of_int int2))
-
- | ((Int i), (Big_int bi)) ->
- num_of_big_int (mult_int_big_int i bi)
- | ((Big_int bi), (Int i)) ->
- num_of_big_int (mult_int_big_int i bi)
-
- | ((Int i), (Ratio r)) ->
- num_of_ratio (mult_int_ratio i r)
- | ((Ratio r), (Int i)) ->
- num_of_ratio (mult_int_ratio i r)
-
- | ((Big_int bi1), (Big_int bi2)) ->
- num_of_big_int (mult_big_int bi1 bi2)
-
- | ((Big_int bi), (Ratio r)) ->
- num_of_ratio (mult_big_int_ratio bi r)
- | ((Ratio r), (Big_int bi)) ->
- num_of_ratio (mult_big_int_ratio bi r)
-
- | ((Ratio r1), (Ratio r2)) ->
- num_of_ratio (mult_ratio r1 r2)
-
-let ( */ ) = mult_num
-
-let square_num = function
- Int i -> if 2 * num_bits_int i < length_of_int
- then Int (i * i)
- else num_of_big_int (square_big_int (big_int_of_int i))
- | Big_int bi -> Big_int (square_big_int bi)
- | Ratio r -> Ratio (square_ratio r)
-
-let div_num n1 n2 =
- match n1 with
- | Int i1 ->
- begin match n2 with
- | Int i2 ->
- num_of_ratio (create_ratio (big_int_of_int i1) (big_int_of_int i2))
- | Big_int bi2 -> num_of_ratio (create_ratio (big_int_of_int i1) bi2)
- | Ratio r2 -> num_of_ratio (div_int_ratio i1 r2) end
-
- | Big_int bi1 ->
- begin match n2 with
- | Int i2 -> num_of_ratio (create_ratio bi1 (big_int_of_int i2))
- | Big_int bi2 -> num_of_ratio (create_ratio bi1 bi2)
- | Ratio r2 -> num_of_ratio (div_big_int_ratio bi1 r2) end
-
- | Ratio r1 ->
- begin match n2 with
- | Int i2 -> num_of_ratio (div_ratio_int r1 i2)
- | Big_int bi2 -> num_of_ratio (div_ratio_big_int r1 bi2)
- | Ratio r2 -> num_of_ratio (div_ratio r1 r2) end
-;;
-
-let ( // ) = div_num
-
-let floor_num = function
- Int _ as n -> n
-| Big_int _ as n -> n
-| Ratio r -> num_of_big_int (floor_ratio r)
-
-(* Coercion with ratio type *)
-let ratio_of_num = function
- Int i -> ratio_of_int i
-| Big_int bi -> ratio_of_big_int bi
-| Ratio r -> r
-;;
-
-(* Euclidean division and remainder. The specification is:
-
- a = b * quo_num a b + mod_num a b
- quo_num a b is an integer (Z)
- 0 <= mod_num a b < |b|
-
-A correct but slow implementation is:
-
- quo_num a b =
- if b >= 0 then floor_num (div_num a b)
- else minus_num (floor_num (div_num a (minus_num b)))
-
- mod_num a b =
- sub_num a (mult_num b (quo_num a b))
-
- However, this definition is vastly inefficient (cf PR #3473):
- we define here a better way of computing the same thing.
-
- PR#6753: the previous implementation was based on
- quo_num a b = floor_num (div_num a b)
- which is incorrect for negative b.
-*)
-
-let quo_num n1 n2 =
- match n1, n2 with
- | Int i1, Int i2 ->
- let q = i1 / i2 and r = i1 mod i2 in
- Int (if r >= 0 then q else if i2 > 0 then q - 1 else q + 1)
- | Int i1, Big_int bi2 ->
- num_of_big_int (div_big_int (big_int_of_int i1) bi2)
- | Int i1, Ratio r2 ->
- num_of_big_int (report_sign_ratio r2
- (floor_ratio (div_int_ratio i1 (abs_ratio r2))))
- | Big_int bi1, Int i2 ->
- num_of_big_int (div_big_int bi1 (big_int_of_int i2))
- | Big_int bi1, Big_int bi2 ->
- num_of_big_int (div_big_int bi1 bi2)
- | Big_int bi1, Ratio r2 ->
- num_of_big_int (report_sign_ratio r2
- (floor_ratio (div_big_int_ratio bi1 (abs_ratio r2))))
- | Ratio r1, _ ->
- let r2 = ratio_of_num n2 in
- num_of_big_int (report_sign_ratio r2
- (floor_ratio (div_ratio r1 (abs_ratio r2))))
-
-let mod_num n1 n2 =
- match n1, n2 with
- | Int i1, Int i2 ->
- let r = i1 mod i2 in
- Int (if r >= 0 then r else if i2 > 0 then r + i2 else r - i2)
- | Int i1, Big_int bi2 ->
- num_of_big_int (mod_big_int (big_int_of_int i1) bi2)
- | Big_int bi1, Int i2 ->
- num_of_big_int (mod_big_int bi1 (big_int_of_int i2))
- | Big_int bi1, Big_int bi2 ->
- num_of_big_int (mod_big_int bi1 bi2)
- | _, _ ->
- sub_num n1 (mult_num n2 (quo_num n1 n2))
-
-let power_num_int a b = match (a,b) with
- ((Int i), n) ->
- (match sign_int n with
- 0 -> Int 1
- | 1 -> num_of_big_int (power_int_positive_int i n)
- | _ -> Ratio (create_normalized_ratio
- unit_big_int (power_int_positive_int i (-n))))
-| ((Big_int bi), n) ->
- (match sign_int n with
- 0 -> Int 1
- | 1 -> num_of_big_int (power_big_int_positive_int bi n)
- | _ -> Ratio (create_normalized_ratio
- unit_big_int (power_big_int_positive_int bi (-n))))
-| ((Ratio r), n) ->
- (match sign_int n with
- 0 -> Int 1
- | 1 -> Ratio (power_ratio_positive_int r n)
- | _ -> Ratio (power_ratio_positive_int
- (inverse_ratio r) (-n)))
-
-let power_num_big_int a b = match (a,b) with
- ((Int i), n) ->
- (match sign_big_int n with
- 0 -> Int 1
- | 1 -> num_of_big_int (power_int_positive_big_int i n)
- | _ -> Ratio (create_normalized_ratio
- unit_big_int
- (power_int_positive_big_int i (minus_big_int n))))
-| ((Big_int bi), n) ->
- (match sign_big_int n with
- 0 -> Int 1
- | 1 -> num_of_big_int (power_big_int_positive_big_int bi n)
- | _ -> Ratio (create_normalized_ratio
- unit_big_int
- (power_big_int_positive_big_int bi (minus_big_int n))))
-| ((Ratio r), n) ->
- (match sign_big_int n with
- 0 -> Int 1
- | 1 -> Ratio (power_ratio_positive_big_int r n)
- | _ -> Ratio (power_ratio_positive_big_int
- (inverse_ratio r) (minus_big_int n)))
-
-let power_num a b = match (a,b) with
- (n, (Int i)) -> power_num_int n i
-| (n, (Big_int bi)) -> power_num_big_int n bi
-| _ -> invalid_arg "power_num"
-
-let ( **/ ) = power_num
-
-let is_integer_num = function
- Int _ -> true
-| Big_int _ -> true
-| Ratio r -> is_integer_ratio r
-
-(* integer_num, floor_num, round_num, ceiling_num rendent des nums *)
-let integer_num = function
- Int _ as n -> n
-| Big_int _ as n -> n
-| Ratio r -> num_of_big_int (integer_ratio r)
-
-and round_num = function
- Int _ as n -> n
-| Big_int _ as n -> n
-| Ratio r -> num_of_big_int (round_ratio r)
-
-and ceiling_num = function
- Int _ as n -> n
-| Big_int _ as n -> n
-| Ratio r -> num_of_big_int (ceiling_ratio r)
-
-(* Comparisons on nums *)
-
-let sign_num = function
- Int i -> sign_int i
-| Big_int bi -> sign_big_int bi
-| Ratio r -> sign_ratio r
-
-let eq_num a b = match (a,b) with
- ((Int int1), (Int int2)) -> int1 = int2
-
-| ((Int i), (Big_int bi)) -> eq_big_int (big_int_of_int i) bi
-| ((Big_int bi), (Int i)) -> eq_big_int (big_int_of_int i) bi
-
-| ((Int i), (Ratio r)) -> eq_big_int_ratio (big_int_of_int i) r
-| ((Ratio r), (Int i)) -> eq_big_int_ratio (big_int_of_int i) r
-
-| ((Big_int bi1), (Big_int bi2)) -> eq_big_int bi1 bi2
-
-| ((Big_int bi), (Ratio r)) -> eq_big_int_ratio bi r
-| ((Ratio r), (Big_int bi)) -> eq_big_int_ratio bi r
-
-| ((Ratio r1), (Ratio r2)) -> eq_ratio r1 r2
-
-let ( =/ ) = eq_num
-
-let ( <>/ ) a b = not(eq_num a b)
-
-let compare_num a b = match (a,b) with
- ((Int int1), (Int int2)) -> compare_int int1 int2
-
-| ((Int i), (Big_int bi)) -> compare_big_int (big_int_of_int i) bi
-| ((Big_int bi), (Int i)) -> compare_big_int bi (big_int_of_int i)
-
-| ((Int i), (Ratio r)) -> compare_big_int_ratio (big_int_of_int i) r
-| ((Ratio r), (Int i)) -> -(compare_big_int_ratio (big_int_of_int i) r)
-
-| ((Big_int bi1), (Big_int bi2)) -> compare_big_int bi1 bi2
-
-| ((Big_int bi), (Ratio r)) -> compare_big_int_ratio bi r
-| ((Ratio r), (Big_int bi)) -> -(compare_big_int_ratio bi r)
-
-| ((Ratio r1), (Ratio r2)) -> compare_ratio r1 r2
-
-let lt_num num1 num2 = compare_num num1 num2 < 0
-and le_num num1 num2 = compare_num num1 num2 <= 0
-and gt_num num1 num2 = compare_num num1 num2 > 0
-and ge_num num1 num2 = compare_num num1 num2 >= 0
-
-let ( </ ) = lt_num
-and ( <=/ ) = le_num
-and ( >/ ) = gt_num
-and ( >=/ ) = ge_num
-
-let max_num num1 num2 = if lt_num num1 num2 then num2 else num1
-and min_num num1 num2 = if gt_num num1 num2 then num2 else num1
-
-(* Coercions with basic types *)
-
-(* Coercion with int type *)
-let int_of_num = function
- Int i -> i
-| Big_int bi -> int_of_big_int bi
-| Ratio r -> int_of_ratio r
-
-let int_of_num_opt = function
- Int i -> Some i
-| Big_int bi -> int_of_big_int_opt bi
-| Ratio r -> (try Some (int_of_ratio r) with Failure _ -> None)
-
-and num_of_int i =
- if i = monster_int
- then Big_int (big_int_of_int i)
- else Int i
-
-(* Coercion with nat type *)
-let nat_of_num = function
- Int i -> nat_of_int i
-| Big_int bi -> nat_of_big_int bi
-| Ratio r -> nat_of_ratio r
-
-and num_of_nat nat =
- if (is_nat_int nat 0 (length_nat nat))
- then Int (nth_digit_nat nat 0)
- else Big_int (big_int_of_nat nat)
-
-let nat_of_num_opt x =
- try Some (nat_of_num x) with Failure _ -> None
-
-(* Coercion with big_int type *)
-let big_int_of_num = function
- Int i -> big_int_of_int i
-| Big_int bi -> bi
-| Ratio r -> big_int_of_ratio r
-
-let big_int_of_num_opt x =
- try Some (big_int_of_num x) with Failure _ -> None
-
-let string_of_big_int_for_num bi =
- if !approx_printing_flag
- then approx_big_int !floating_precision bi
- else string_of_big_int bi
-
-(* Coercion with string type *)
-
-let string_of_normalized_num = function
- Int i -> string_of_int i
-| Big_int bi -> string_of_big_int_for_num bi
-| Ratio r -> string_of_ratio r
-let string_of_num n =
- string_of_normalized_num (cautious_normalize_num_when_printing n)
-
-let num_of_string s =
- try
- let flag = !normalize_ratio_flag in
- normalize_ratio_flag := true;
- let r = ratio_of_string s in
- normalize_ratio_flag := flag;
- if eq_big_int (denominator_ratio r) unit_big_int
- then num_of_big_int (numerator_ratio r)
- else Ratio r
- with Failure _ ->
- failwith "num_of_string"
-
-let num_of_string_opt s =
- try Some (num_of_string s) with Failure _ -> None
-
-(* Coercion with float type *)
-let float_of_num = function
- Int i -> float i
-| Big_int bi -> float_of_big_int bi
-| Ratio r -> float_of_ratio r
-
-let succ_num = function
- Int i -> if i = biggest_int
- then Big_int (succ_big_int (big_int_of_int i))
- else Int (succ i)
-| Big_int bi -> num_of_big_int (succ_big_int bi)
-| Ratio r -> Ratio (add_int_ratio 1 r)
-
-and pred_num = function
- Int i -> if i = monster_int
- then Big_int (pred_big_int (big_int_of_int i))
- else Int (pred i)
-| Big_int bi -> num_of_big_int (pred_big_int bi)
-| Ratio r -> Ratio (add_int_ratio (-1) r)
-
-let abs_num = function
- Int i -> if i = monster_int
- then Big_int (minus_big_int (big_int_of_int i))
- else Int (abs i)
- | Big_int bi -> Big_int (abs_big_int bi)
- | Ratio r -> Ratio (abs_ratio r)
-
-let approx_num_fix n num = approx_ratio_fix n (ratio_of_num num)
-and approx_num_exp n num = approx_ratio_exp n (ratio_of_num num)
-
-let incr_num r = r := succ_num !r
-and decr_num r = r := pred_num !r
+++ /dev/null
-(**************************************************************************)
-(* *)
-(* OCaml *)
-(* *)
-(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *)
-(* *)
-(* Copyright 1996 Institut National de Recherche en Informatique et *)
-(* en Automatique. *)
-(* *)
-(* All rights reserved. This file is distributed under the terms of *)
-(* the GNU Lesser General Public License version 2.1, with the *)
-(* special exception on linking described in the file LICENSE. *)
-(* *)
-(**************************************************************************)
-
-(** Operation on arbitrary-precision numbers.
-
- Numbers (type [num]) are arbitrary-precision rational numbers,
- plus the special elements [1/0] (infinity) and [0/0] (undefined).
-*)
-
-open Nat
-open Big_int
-open Ratio
-
-(** The type of numbers. *)
-type num =
- Int of int
- | Big_int of big_int
- | Ratio of ratio
-
-
-(** {6 Arithmetic operations} *)
-
-
-val ( +/ ) : num -> num -> num
-(** Same as {!Num.add_num}.*)
-
-val add_num : num -> num -> num
-(** Addition *)
-
-val minus_num : num -> num
-(** Unary negation. *)
-
-val ( -/ ) : num -> num -> num
-(** Same as {!Num.sub_num}.*)
-
-val sub_num : num -> num -> num
-(** Subtraction *)
-
-val ( */ ) : num -> num -> num
-(** Same as {!Num.mult_num}.*)
-
-val mult_num : num -> num -> num
-(** Multiplication *)
-
-val square_num : num -> num
-(** Squaring *)
-
-val ( // ) : num -> num -> num
-(** Same as {!Num.div_num}.*)
-
-val div_num : num -> num -> num
-(** Division *)
-
-val quo_num : num -> num -> num
-(** Euclidean division: quotient. *)
-
-val mod_num : num -> num -> num
-(** Euclidean division: remainder. *)
-
-val ( **/ ) : num -> num -> num
-(** Same as {!Num.power_num}. *)
-
-val power_num : num -> num -> num
-(** Exponentiation *)
-
-val abs_num : num -> num
-(** Absolute value. *)
-
-val succ_num : num -> num
-(** [succ n] is [n+1] *)
-
-val pred_num : num -> num
-(** [pred n] is [n-1] *)
-
-val incr_num : num ref -> unit
-(** [incr r] is [r:=!r+1], where [r] is a reference to a number. *)
-
-val decr_num : num ref -> unit
-(** [decr r] is [r:=!r-1], where [r] is a reference to a number. *)
-
-val is_integer_num : num -> bool
-(** Test if a number is an integer *)
-
-(** The four following functions approximate a number by an integer : *)
-
-val integer_num : num -> num
-(** [integer_num n] returns the integer closest to [n]. In case of ties,
- rounds towards zero. *)
-
-val floor_num : num -> num
-(** [floor_num n] returns the largest integer smaller or equal to [n]. *)
-
-val round_num : num -> num
-(** [round_num n] returns the integer closest to [n]. In case of ties,
- rounds off zero. *)
-
-val ceiling_num : num -> num
-(** [ceiling_num n] returns the smallest integer bigger or equal to [n]. *)
-
-
-val sign_num : num -> int
-(** Return [-1], [0] or [1] according to the sign of the argument. *)
-
-(** {7 Comparisons between numbers} *)
-
-val ( =/ ) : num -> num -> bool
-val ( </ ) : num -> num -> bool
-val ( >/ ) : num -> num -> bool
-val ( <=/ ) : num -> num -> bool
-val ( >=/ ) : num -> num -> bool
-val ( <>/ ) : num -> num -> bool
-val eq_num : num -> num -> bool
-val lt_num : num -> num -> bool
-val le_num : num -> num -> bool
-val gt_num : num -> num -> bool
-val ge_num : num -> num -> bool
-
-val compare_num : num -> num -> int
-(** Return [-1], [0] or [1] if the first argument is less than,
- equal to, or greater than the second argument. *)
-
-val max_num : num -> num -> num
-(** Return the greater of the two arguments. *)
-
-val min_num : num -> num -> num
-(** Return the smaller of the two arguments. *)
-
-
-(** {6 Coercions with strings} *)
-
-val string_of_num : num -> string
-(** Convert a number to a string, using fractional notation. *)
-
-val approx_num_fix : int -> num -> string
-(** See {!Num.approx_num_exp}.*)
-
-val approx_num_exp : int -> num -> string
-(** Approximate a number by a decimal. The first argument is the
- required precision. The second argument is the number to
- approximate. {!Num.approx_num_fix} uses decimal notation; the first
- argument is the number of digits after the decimal point.
- [approx_num_exp] uses scientific (exponential) notation; the
- first argument is the number of digits in the mantissa. *)
-
-val num_of_string : string -> num
-(** Convert a string to a number.
- Raise [Failure "num_of_string"] if the given string is not
- a valid representation of an integer *)
-
-val num_of_string_opt: string -> num option
-(** Convert a string to a number.
- Return [None] if the given string is not
- a valid representation of an integer.
-
- @since 4.05
-*)
-
-(** {6 Coercions between numerical types} *)
-
-(* TODO: document the functions below (truncating behavior and error conditions). *)
-
-val int_of_num : num -> int
-val int_of_num_opt: num -> int option
-(** @since 4.05.0 *)
-
-val num_of_int : int -> num
-val nat_of_num : num -> nat
-val nat_of_num_opt: num -> nat option
-(** @since 4.05.0 *)
-
-val num_of_nat : nat -> num
-val num_of_big_int : big_int -> num
-val big_int_of_num : num -> big_int
-val big_int_of_num_opt: num -> big_int option
-(** @since 4.05.0 *)
-
-val ratio_of_num : num -> ratio
-val num_of_ratio : ratio -> num
-val float_of_num : num -> float
+++ /dev/null
-(**************************************************************************)
-(* *)
-(* OCaml *)
-(* *)
-(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *)
-(* *)
-(* Copyright 1996 Institut National de Recherche en Informatique et *)
-(* en Automatique. *)
-(* *)
-(* All rights reserved. This file is distributed under the terms of *)
-(* the GNU Lesser General Public License version 2.1, with the *)
-(* special exception on linking described in the file LICENSE. *)
-(* *)
-(**************************************************************************)
-
-open Int_misc
-open Nat
-open Big_int
-open Arith_flags
-
-(* Definition of the type ratio :
- Conventions :
- - the denominator is always a positive number
- - the sign of n/0 is the sign of n
-These convention is automatically respected when a ratio is created with
-the create_ratio primitive
-*)
-
-type ratio = { mutable numerator : big_int;
- mutable denominator : big_int;
- mutable normalized : bool}
-
-let failwith_zero name =
- let s = "infinite or undefined rational number" in
- failwith (if String.length name = 0 then s else name ^ " " ^ s)
-
-let numerator_ratio r = r.numerator
-and denominator_ratio r = r.denominator
-
-let null_denominator r = sign_big_int r.denominator = 0
-
-let verify_null_denominator r =
- if sign_big_int r.denominator = 0
- then (if !error_when_null_denominator_flag
- then (failwith_zero "")
- else true)
- else false
-
-let sign_ratio r = sign_big_int r.numerator
-
-(* Physical normalization of rational numbers *)
-(* 1/0, 0/0 and -1/0 are the normalized forms for n/0 numbers *)
-let normalize_ratio r =
- if r.normalized then r
- else if verify_null_denominator r then begin
- r.numerator <- big_int_of_int (sign_big_int r.numerator);
- r.normalized <- true;
- r
- end else begin
- let p = gcd_big_int r.numerator r.denominator in
- if eq_big_int p unit_big_int
- then begin
- r.normalized <- true; r
- end else begin
- r.numerator <- div_big_int (r.numerator) p;
- r.denominator <- div_big_int (r.denominator) p;
- r.normalized <- true; r
- end
- end
-
-let cautious_normalize_ratio r =
- if (!normalize_ratio_flag) then (normalize_ratio r) else r
-
-let cautious_normalize_ratio_when_printing r =
- if (!normalize_ratio_when_printing_flag) then (normalize_ratio r) else r
-
-let create_ratio bi1 bi2 =
- match sign_big_int bi2 with
- -1 -> cautious_normalize_ratio
- { numerator = minus_big_int bi1;
- denominator = minus_big_int bi2;
- normalized = false }
- | 0 -> if !error_when_null_denominator_flag
- then (failwith_zero "create_ratio")
- else cautious_normalize_ratio
- { numerator = bi1; denominator = bi2; normalized = false }
- | _ -> cautious_normalize_ratio
- { numerator = bi1; denominator = bi2; normalized = false }
-
-let create_normalized_ratio bi1 bi2 =
- match sign_big_int bi2 with
- -1 -> { numerator = minus_big_int bi1;
- denominator = minus_big_int bi2;
- normalized = true }
-| 0 -> if !error_when_null_denominator_flag
- then failwith_zero "create_normalized_ratio"
- else { numerator = bi1; denominator = bi2; normalized = true }
-| _ -> { numerator = bi1; denominator = bi2; normalized = true }
-
-let is_normalized_ratio r = r.normalized
-
-let report_sign_ratio r bi =
- if sign_ratio r = -1
- then minus_big_int bi
- else bi
-
-let abs_ratio r =
- { numerator = abs_big_int r.numerator;
- denominator = r.denominator;
- normalized = r.normalized }
-
-let is_integer_ratio r =
- eq_big_int ((normalize_ratio r).denominator) unit_big_int
-
-(* Operations on rational numbers *)
-
-let add_ratio r1 r2 =
- if !normalize_ratio_flag then begin
- let p = gcd_big_int ((normalize_ratio r1).denominator)
- ((normalize_ratio r2).denominator) in
- if eq_big_int p unit_big_int then
- {numerator = add_big_int (mult_big_int (r1.numerator) r2.denominator)
- (mult_big_int (r2.numerator) r1.denominator);
- denominator = mult_big_int (r1.denominator) r2.denominator;
- normalized = true}
- else begin
- let d1 = div_big_int (r1.denominator) p
- and d2 = div_big_int (r2.denominator) p in
- let n = add_big_int (mult_big_int (r1.numerator) d2)
- (mult_big_int d1 r2.numerator) in
- let p' = gcd_big_int n p in
- { numerator = div_big_int n p';
- denominator = mult_big_int d1 (div_big_int (r2.denominator) p');
- normalized = true }
- end
- end else
- { numerator = add_big_int (mult_big_int (r1.numerator) r2.denominator)
- (mult_big_int (r1.denominator) r2.numerator);
- denominator = mult_big_int (r1.denominator) r2.denominator;
- normalized = false }
-
-let minus_ratio r =
- { numerator = minus_big_int (r.numerator);
- denominator = r.denominator;
- normalized = r.normalized }
-
-let add_int_ratio i r =
- ignore (cautious_normalize_ratio r);
- { numerator = add_big_int (mult_int_big_int i r.denominator) r.numerator;
- denominator = r.denominator;
- normalized = r.normalized }
-
-let add_big_int_ratio bi r =
- ignore (cautious_normalize_ratio r);
- { numerator = add_big_int (mult_big_int bi r.denominator) r.numerator ;
- denominator = r.denominator;
- normalized = r.normalized }
-
-let sub_ratio r1 r2 = add_ratio r1 (minus_ratio r2)
-
-let mult_ratio r1 r2 =
- if !normalize_ratio_flag then begin
- let p1 = gcd_big_int ((normalize_ratio r1).numerator)
- ((normalize_ratio r2).denominator)
- and p2 = gcd_big_int (r2.numerator) r1.denominator in
- let (n1, d2) =
- if eq_big_int p1 unit_big_int
- then (r1.numerator, r2.denominator)
- else (div_big_int (r1.numerator) p1, div_big_int (r2.denominator) p1)
- and (n2, d1) =
- if eq_big_int p2 unit_big_int
- then (r2.numerator, r1.denominator)
- else (div_big_int r2.numerator p2, div_big_int r1.denominator p2) in
- { numerator = mult_big_int n1 n2;
- denominator = mult_big_int d1 d2;
- normalized = true }
- end else
- { numerator = mult_big_int (r1.numerator) r2.numerator;
- denominator = mult_big_int (r1.denominator) r2.denominator;
- normalized = false }
-
-let mult_int_ratio i r =
- if !normalize_ratio_flag then
- begin
- let p = gcd_big_int ((normalize_ratio r).denominator) (big_int_of_int i) in
- if eq_big_int p unit_big_int
- then { numerator = mult_big_int (big_int_of_int i) r.numerator;
- denominator = r.denominator;
- normalized = true }
- else { numerator = mult_big_int (div_big_int (big_int_of_int i) p)
- r.numerator;
- denominator = div_big_int (r.denominator) p;
- normalized = true }
- end
- else
- { numerator = mult_int_big_int i r.numerator;
- denominator = r.denominator;
- normalized = false }
-
-let mult_big_int_ratio bi r =
- if !normalize_ratio_flag then
- begin
- let p = gcd_big_int ((normalize_ratio r).denominator) bi in
- if eq_big_int p unit_big_int
- then { numerator = mult_big_int bi r.numerator;
- denominator = r.denominator;
- normalized = true }
- else { numerator = mult_big_int (div_big_int bi p) r.numerator;
- denominator = div_big_int (r.denominator) p;
- normalized = true }
- end
- else
- { numerator = mult_big_int bi r.numerator;
- denominator = r.denominator;
- normalized = false }
-
-let square_ratio r =
- ignore (cautious_normalize_ratio r);
- { numerator = square_big_int r.numerator;
- denominator = square_big_int r.denominator;
- normalized = r.normalized }
-
-let inverse_ratio r =
- if !error_when_null_denominator_flag && (sign_big_int r.numerator) = 0
- then failwith_zero "inverse_ratio"
- else {numerator = report_sign_ratio r r.denominator;
- denominator = abs_big_int r.numerator;
- normalized = r.normalized}
-
-let div_ratio r1 r2 =
- mult_ratio r1 (inverse_ratio r2)
-
-(* Integer part of a rational number *)
-(* Odd function *)
-let integer_ratio r =
- if null_denominator r then failwith_zero "integer_ratio"
- else if sign_ratio r = 0 then zero_big_int
- else report_sign_ratio r (div_big_int (abs_big_int r.numerator)
- (abs_big_int r.denominator))
-
-(* Floor of a rational number *)
-(* Always less or equal to r *)
-let floor_ratio r =
- ignore (verify_null_denominator r);
- div_big_int (r.numerator) r.denominator
-
-(* Round of a rational number *)
-(* Odd function, 1/2 -> 1 *)
-let round_ratio r =
- ignore (verify_null_denominator r);
- let abs_num = abs_big_int r.numerator in
- let bi = div_big_int abs_num r.denominator in
- report_sign_ratio r
- (if sign_big_int
- (sub_big_int
- (mult_int_big_int
- 2
- (sub_big_int abs_num (mult_big_int (r.denominator) bi)))
- r.denominator) = -1
- then bi
- else succ_big_int bi)
-
-let ceiling_ratio r =
- if (is_integer_ratio r)
- then r.numerator
- else succ_big_int (floor_ratio r)
-
-
-(* Comparison operators on rational numbers *)
-let eq_ratio r1 r2 =
- ignore (normalize_ratio r1);
- ignore (normalize_ratio r2);
- eq_big_int (r1.numerator) r2.numerator &&
- eq_big_int (r1.denominator) r2.denominator
-
-let compare_ratio r1 r2 =
- if verify_null_denominator r1 then
- let sign_num_r1 = sign_big_int r1.numerator in
- if (verify_null_denominator r2)
- then
- let sign_num_r2 = sign_big_int r2.numerator in
- if sign_num_r1 = 1 && sign_num_r2 = -1 then 1
- else if sign_num_r1 = -1 && sign_num_r2 = 1 then -1
- else 0
- else sign_num_r1
- else if verify_null_denominator r2 then
- -(sign_big_int r2.numerator)
- else match compare_int (sign_big_int r1.numerator)
- (sign_big_int r2.numerator) with
- 1 -> 1
- | -1 -> -1
- | _ -> if eq_big_int (r1.denominator) r2.denominator
- then compare_big_int (r1.numerator) r2.numerator
- else compare_big_int
- (mult_big_int (r1.numerator) r2.denominator)
- (mult_big_int (r1.denominator) r2.numerator)
-
-
-let lt_ratio r1 r2 = compare_ratio r1 r2 < 0
-and le_ratio r1 r2 = compare_ratio r1 r2 <= 0
-and gt_ratio r1 r2 = compare_ratio r1 r2 > 0
-and ge_ratio r1 r2 = compare_ratio r1 r2 >= 0
-
-let max_ratio r1 r2 = if lt_ratio r1 r2 then r2 else r1
-and min_ratio r1 r2 = if gt_ratio r1 r2 then r2 else r1
-
-let eq_big_int_ratio bi r =
- (is_integer_ratio r) && eq_big_int bi r.numerator
-
-let compare_big_int_ratio bi r =
- ignore (normalize_ratio r);
- if (verify_null_denominator r)
- then -(sign_big_int r.numerator)
- else compare_big_int (mult_big_int bi r.denominator) r.numerator
-
-let lt_big_int_ratio bi r = compare_big_int_ratio bi r < 0
-and le_big_int_ratio bi r = compare_big_int_ratio bi r <= 0
-and gt_big_int_ratio bi r = compare_big_int_ratio bi r > 0
-and ge_big_int_ratio bi r = compare_big_int_ratio bi r >= 0
-
-(* Coercions *)
-
-(* Coercions with type int *)
-let int_of_ratio r =
- if ((is_integer_ratio r) && (is_int_big_int r.numerator))
- then (int_of_big_int r.numerator)
- else failwith "integer argument required"
-
-and ratio_of_int i =
- { numerator = big_int_of_int i;
- denominator = unit_big_int;
- normalized = true }
-
-(* Coercions with type nat *)
-let ratio_of_nat nat =
- { numerator = big_int_of_nat nat;
- denominator = unit_big_int;
- normalized = true }
-
-and nat_of_ratio r =
- ignore (normalize_ratio r);
- if not (is_integer_ratio r) then
- failwith "nat_of_ratio"
- else if sign_big_int r.numerator > -1 then
- nat_of_big_int (r.numerator)
- else failwith "nat_of_ratio"
-
-(* Coercions with type big_int *)
-let ratio_of_big_int bi =
- { numerator = bi; denominator = unit_big_int; normalized = true }
-
-and big_int_of_ratio r =
- ignore (normalize_ratio r);
- if is_integer_ratio r
- then r.numerator
- else failwith "big_int_of_ratio"
-
-let div_int_ratio i r =
- ignore (verify_null_denominator r);
- mult_int_ratio i (inverse_ratio r)
-
-let div_ratio_int r i =
- div_ratio r (ratio_of_int i)
-
-let div_big_int_ratio bi r =
- ignore (verify_null_denominator r);
- mult_big_int_ratio bi (inverse_ratio r)
-
-let div_ratio_big_int r bi =
- div_ratio r (ratio_of_big_int bi)
-
-(* Functions on type string *)
-(* giving floating point approximations of rational numbers *)
-
-(* Compares strings that contains only digits, have the same length,
- from index i to index i + l *)
-let rec compare_num_string s1 s2 i len =
- if i >= len then 0 else
- let c1 = int_of_char s1.[i]
- and c2 = int_of_char s2.[i] in
- match compare_int c1 c2 with
- | 0 -> compare_num_string s1 s2 (succ i) len
- | c -> c;;
-
-(* Position of the leading digit of the decimal expansion *)
-(* of a strictly positive rational number *)
-(* if the decimal expansion of a non null rational r is equal to *)
-(* sigma for k=-P to N of r_k*10^k then msd_ratio r = N *)
-(* Nota : for a big_int we have msd_ratio = nums_digits_big_int -1 *)
-
-(* Tests if s has only zeros characters from index i to index lim *)
-let rec only_zeros s i lim =
- i >= lim || s.[i] == '0' && only_zeros s (succ i) lim;;
-
-(* Nota : for a big_int we have msd_ratio = nums_digits_big_int -1 *)
-let msd_ratio r =
- ignore (cautious_normalize_ratio r);
- if null_denominator r then failwith_zero "msd_ratio"
- else if sign_big_int r.numerator == 0 then 0
- else begin
- let str_num = string_of_big_int r.numerator
- and str_den = string_of_big_int r.denominator in
- let size_num = String.length str_num
- and size_den = String.length str_den in
- let size_min = min size_num size_den in
- let m = size_num - size_den in
- let cmp = compare_num_string str_num str_den 0 size_min in
- match cmp with
- | 1 -> m
- | -1 -> pred m
- | _ ->
- if m >= 0 then m else
- if only_zeros str_den size_min size_den then m
- else pred m
- end
-;;
-
-(* Decimal approximations of rational numbers *)
-
-(* Approximation with fix decimal point *)
-(* This is an odd function and the last digit is round off *)
-(* Format integer_part . decimal_part_with_n_digits *)
-let approx_ratio_fix n r =
- (* Don't need to normalize *)
- if (null_denominator r) then failwith_zero "approx_ratio_fix"
- else
- let sign_r = sign_ratio r in
- if sign_r = 0
- then "+0" (* r = 0 *)
- else
- (* r.numerator and r.denominator are not null numbers
- s1 contains one more digit than desired for the round off operation *)
- if n >= 0 then begin
- let s1 =
- string_of_nat
- (nat_of_big_int
- (div_big_int
- (base_power_big_int
- 10 (succ n) (abs_big_int r.numerator))
- r.denominator)) in
- (* Round up and add 1 in front if needed *)
- let s2 =
- if round_futur_last_digit (Bytes.unsafe_of_string s1) 0
- (String.length s1)
- then "1" ^ s1
- else s1 in
- let l2 = String.length s2 - 1 in
- (* if s2 without last digit is xxxxyyy with n 'yyy' digits:
- <sign> xxxx . yyy
- if s2 without last digit is yy with <= n digits:
- <sign> 0 . 0yy *)
- if l2 > n then begin
- let s = Bytes.make (l2 + 2) '0' in
- Bytes.set s 0 (if sign_r = -1 then '-' else '+');
- String.blit s2 0 s 1 (l2 - n);
- Bytes.set s (l2 - n + 1) '.';
- String.blit s2 (l2 - n) s (l2 - n + 2) n;
- Bytes.unsafe_to_string s
- end else begin
- let s = Bytes.make (n + 3) '0' in
- Bytes.set s 0 (if sign_r = -1 then '-' else '+');
- Bytes.set s 2 '.';
- String.blit s2 0 s (n + 3 - l2) l2;
- Bytes.unsafe_to_string s
- end
- end else begin
- (* Dubious; what is this code supposed to do? *)
- let s = string_of_big_int
- (div_big_int
- (abs_big_int r.numerator)
- (base_power_big_int
- 10 (-n) r.denominator)) in
- let len = succ (String.length s) in
- let s' = Bytes.make len '0' in
- Bytes.set s' 0 (if sign_r = -1 then '-' else '+');
- String.blit s 0 s' 1 (pred len);
- Bytes.unsafe_to_string s'
- end
-
-(* Number of digits of the decimal representation of an int *)
-let num_decimal_digits_int n =
- String.length (string_of_int n)
-
-(* Approximation with floating decimal point *)
-(* This is an odd function and the last digit is round off *)
-(* Format (+/-)(0. n_first_digits e msd)/(1. n_zeros e (msd+1) *)
-let approx_ratio_exp n r =
- (* Don't need to normalize *)
- if (null_denominator r) then failwith_zero "approx_ratio_exp"
- else if n <= 0 then invalid_arg "approx_ratio_exp"
- else
- let sign_r = sign_ratio r
- and i = ref (n + 3) in
- if sign_r = 0 then
- String.concat "" ["+0."; String.make n '0'; "e0"]
- else
- let msd = msd_ratio (abs_ratio r) in
- let k = n - msd in
- let s =
- (let nat = nat_of_big_int
- (if k < 0
- then
- div_big_int (abs_big_int r.numerator)
- (base_power_big_int 10 (- k)
- r.denominator)
- else
- div_big_int (base_power_big_int
- 10 k (abs_big_int r.numerator))
- r.denominator) in
- string_of_nat nat) in
- if round_futur_last_digit (Bytes.unsafe_of_string s) 0
- (String.length s)
- then
- let m = num_decimal_digits_int (succ msd) in
- let str = Bytes.make (n + m + 4) '0' in
- (String.blit (if sign_r = -1 then "-1." else "+1.") 0 str 0 3);
- Bytes.set str !i ('e');
- incr i;
- (if m = 0
- then Bytes.set str !i '0'
- else String.blit (string_of_int (succ msd)) 0 str !i m);
- Bytes.unsafe_to_string str
- else
- let m = num_decimal_digits_int (succ msd)
- and p = n + 3 in
- let str = Bytes.make (succ (m + p)) '0' in
- (String.blit (if sign_r = -1 then "-0." else "+0.") 0 str 0 3);
- (String.blit s 0 str 3 n);
- Bytes.set str p 'e';
- (if m = 0
- then Bytes.set str (succ p) '0'
- else (String.blit (string_of_int (succ msd)) 0 str (succ p) m));
- Bytes.unsafe_to_string str
-
-(* String approximation of a rational with a fixed number of significant *)
-(* digits printed *)
-let float_of_rational_string r =
- let s = approx_ratio_exp !floating_precision r in
- if String.get s 0 = '+'
- then (String.sub s 1 (pred (String.length s)))
- else s
-
-(* Coercions with type string *)
-let string_of_ratio r =
- ignore (cautious_normalize_ratio_when_printing r);
- if !approx_printing_flag
- then float_of_rational_string r
- else string_of_big_int r.numerator ^ "/" ^ string_of_big_int r.denominator
-
-(* XL: j'ai puissamment simplifie "ratio_of_string" en virant la notation
- scientifique.
- | I have strongly simplified "ratio_of_string" by deleting scientific notation
-*)
-
-let ratio_of_string s =
- try
- let n = String.index s '/' in
- create_ratio (sys_big_int_of_string s 0 n)
- (sys_big_int_of_string s (n+1) (String.length s - n - 1))
- with Not_found ->
- { numerator = big_int_of_string s;
- denominator = unit_big_int;
- normalized = true }
-
-(* Coercion with type float *)
-
-let float_of_ratio r =
- let p = r.numerator and q = r.denominator in
- (* Special cases 0/0, 0/q and p/0 *)
- if sign_big_int q = 0 then begin
- match sign_big_int p with
- | 0 -> nan
- | 1 -> infinity
- | -1 -> neg_infinity
- | _ -> assert false
- end
- else if sign_big_int p = 0 then 0.0
- else begin
- let np = num_bits_big_int p and nq = num_bits_big_int q in
- if np <= 53 && nq <= 53 then
- (* p and q convert to floats exactly; use FP division to get the
- correctly-rounded result. *)
- Int64.to_float (int64_of_big_int p)
- /. Int64.to_float (int64_of_big_int q)
- else begin
- let ap = abs_big_int p in
- (* |p| is in [2^(np-1), 2^np)
- q is in [2^(nq-1), 2^nq)
- hence |p|/q is in (2^(np-nq-1), 2^(np-nq+1)).
- We define n such that |p|/q*2^n is in [2^54, 2^56).
- >= 2^54 so that the round to odd technique applies.
- < 2^56 so that the integral part is representable as an int64. *)
- let n = 55 - (np - nq) in
- (* Scaling |p|/q by 2^n *)
- let (p', q') =
- if n >= 0
- then (shift_left_big_int ap n, q)
- else (ap, shift_left_big_int q (-n)) in
- (* Euclidean division of p' by q' *)
- let (quo, rem) = quomod_big_int p' q' in
- (* quo is the integral part of |p|/q*2^n
- rem/q' is the fractional part. *)
- (* Round quo to float *)
- let f = round_big_int_to_float quo (sign_big_int rem = 0) in
- (* Apply exponent *)
- let f = ldexp f (-n) in
- (* Apply sign *)
- if sign_big_int p < 0 then -. f else f
- end
- end
-
-
-let power_ratio_positive_int r n =
- create_ratio (power_big_int_positive_int (r.numerator) n)
- (power_big_int_positive_int (r.denominator) n)
-
-let power_ratio_positive_big_int r bi =
- create_ratio (power_big_int_positive_big_int (r.numerator) bi)
- (power_big_int_positive_big_int (r.denominator) bi)
+++ /dev/null
-(**************************************************************************)
-(* *)
-(* OCaml *)
-(* *)
-(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *)
-(* *)
-(* Copyright 1996 Institut National de Recherche en Informatique et *)
-(* en Automatique. *)
-(* *)
-(* All rights reserved. This file is distributed under the terms of *)
-(* the GNU Lesser General Public License version 2.1, with the *)
-(* special exception on linking described in the file LICENSE. *)
-(* *)
-(**************************************************************************)
-
-(** Operation on rational numbers.
-
- This module is used to support the implementation of {!Num} and
- should not be called directly. *)
-
-open Nat
-open Big_int
-
-(* Rationals (type [ratio]) are arbitrary-precision rational numbers,
- plus the special elements [1/0] (infinity) and [0/0] (undefined).
- In constrast with numbers (type [num]), the special cases of
- small integers and big integers are not optimized specially. *)
-
-type ratio
-
-(**/**)
-
-val null_denominator : ratio -> bool
-val numerator_ratio : ratio -> big_int
-val denominator_ratio : ratio -> big_int
-val sign_ratio : ratio -> int
-val normalize_ratio : ratio -> ratio
-val cautious_normalize_ratio : ratio -> ratio
-val cautious_normalize_ratio_when_printing : ratio -> ratio
-val create_ratio : big_int -> big_int -> ratio (* assumes nothing *)
-val create_normalized_ratio : big_int -> big_int -> ratio
- (* assumes normalized argument *)
-val is_normalized_ratio : ratio -> bool
-val report_sign_ratio : ratio -> big_int -> big_int
-val abs_ratio : ratio -> ratio
-val is_integer_ratio : ratio -> bool
-val add_ratio : ratio -> ratio -> ratio
-val minus_ratio : ratio -> ratio
-val add_int_ratio : int -> ratio -> ratio
-val add_big_int_ratio : big_int -> ratio -> ratio
-val sub_ratio : ratio -> ratio -> ratio
-val mult_ratio : ratio -> ratio -> ratio
-val mult_int_ratio : int -> ratio -> ratio
-val mult_big_int_ratio : big_int -> ratio -> ratio
-val square_ratio : ratio -> ratio
-val inverse_ratio : ratio -> ratio
-val div_ratio : ratio -> ratio -> ratio
-val integer_ratio : ratio -> big_int
-val floor_ratio : ratio -> big_int
-val round_ratio : ratio -> big_int
-val ceiling_ratio : ratio -> big_int
-val eq_ratio : ratio -> ratio -> bool
-val compare_ratio : ratio -> ratio -> int
-val lt_ratio : ratio -> ratio -> bool
-val le_ratio : ratio -> ratio -> bool
-val gt_ratio : ratio -> ratio -> bool
-val ge_ratio : ratio -> ratio -> bool
-val max_ratio : ratio -> ratio -> ratio
-val min_ratio : ratio -> ratio -> ratio
-val eq_big_int_ratio : big_int -> ratio -> bool
-val compare_big_int_ratio : big_int -> ratio -> int
-val lt_big_int_ratio : big_int -> ratio -> bool
-val le_big_int_ratio : big_int -> ratio -> bool
-val gt_big_int_ratio : big_int -> ratio -> bool
-val ge_big_int_ratio : big_int -> ratio -> bool
-val int_of_ratio : ratio -> int
-val ratio_of_int : int -> ratio
-val ratio_of_nat : nat -> ratio
-val nat_of_ratio : ratio -> nat
-val ratio_of_big_int : big_int -> ratio
-val big_int_of_ratio : ratio -> big_int
-val div_int_ratio : int -> ratio -> ratio
-val div_ratio_int : ratio -> int -> ratio
-val div_big_int_ratio : big_int -> ratio -> ratio
-val div_ratio_big_int : ratio -> big_int -> ratio
-val approx_ratio_fix : int -> ratio -> string
-val approx_ratio_exp : int -> ratio -> string
-val float_of_rational_string : ratio -> string
-val string_of_ratio : ratio -> string
-val ratio_of_string : string -> ratio
-val float_of_ratio : ratio -> float
-val power_ratio_positive_int : ratio -> int -> ratio
-val power_ratio_positive_big_int : ratio -> big_int -> ratio
-aProf.cmi :
-camlinternalAProf.cmi :
-aProf.cmo : aProf.cmi
-aProf.cmx : aProf.cmi
-camlinternalAProf.cmo : camlinternalAProf.cmi
-camlinternalAProf.cmx : camlinternalAProf.cmi
-aProf.cmi :
-camlinternalAProf.cmi :
-aProf.cmo : camlinternalAProf.cmi aProf.cmi
-aProf.cmx : camlinternalAProf.cmx aProf.cmi
-camlinternalAProf.cmo : camlinternalAProf.cmi
-camlinternalAProf.cmx : camlinternalAProf.cmi
-aProf.cmi :
-rawAProf.cmi :
-aProf.cmo : aProf.cmi
-aProf.cmx : aProf.cmi
-rawAProf.cmo : rawAProf.cmi
-rawAProf.cmx : rawAProf.cmi
-aProf.cmo : rawAProf.cmi aProf.cmi
-aProf.cmx : rawAProf.cmx aProf.cmi
-aProf.cmi :
-rawAProf.cmo : rawAProf.cmi
-rawAProf.cmx : rawAProf.cmi
-rawAProf.cmi :
-raw_spacetime_lib.cmo : raw_spacetime_lib.cmi
-raw_spacetime_lib.cmx : raw_spacetime_lib.cmi
-raw_spacetime_lib.cmi :
-spacetime_lib.cmo : raw_spacetime_lib.cmi spacetime_lib.cmi
-spacetime_lib.cmx : raw_spacetime_lib.cmx spacetime_lib.cmi
-spacetime_lib.cmi :
-raw_spacetime_lib.cmo : raw_spacetime_lib.cmi
-raw_spacetime_lib.cmx : raw_spacetime_lib.cmi
-raw_spacetime_lib.cmi :
-raw_spacetime_lib.cmo : raw_spacetime_lib.cmi
-raw_spacetime_lib.cmx : raw_spacetime_lib.cmi
-raw_spacetime_lib.cmi :
-raw_spacetime_lib.cmo : raw_spacetime_lib.cmi
-raw_spacetime_lib.cmx : raw_spacetime_lib.cmi
-raw_spacetime_lib.cmi :
-raw_spacetime_lib.cmo : raw_spacetime_lib.cmi
-raw_spacetime_lib.cmx : raw_spacetime_lib.cmi
-raw_spacetime_lib.cmi :
-raw_spacetime_lib.cmo : raw_spacetime_lib.cmi
-raw_spacetime_lib.cmx : raw_spacetime_lib.cmi
-raw_spacetime_lib.cmi :
-raw_spacetime_lib.cmo : raw_spacetime_lib.cmi
-raw_spacetime_lib.cmx : raw_spacetime_lib.cmi
-raw_spacetime_lib.cmi :
-raw_spacetime_lib.cmo : raw_spacetime_lib.cmi
-raw_spacetime_lib.cmx : raw_spacetime_lib.cmi
-raw_spacetime_lib.cmi :
raw_spacetime_lib.cmo : raw_spacetime_lib.cmi
raw_spacetime_lib.cmx : raw_spacetime_lib.cmi
raw_spacetime_lib.cmi :
CAMLC=$(CAMLRUN) $(ROOTDIR)/ocamlc -nostdlib -I $(ROOTDIR)/stdlib
CAMLOPT=$(CAMLRUN) $(ROOTDIR)/ocamlopt -nostdlib \
-I $(ROOTDIR)/stdlib
-CFLAGS=-I$(ROOTDIR)/byterun $(SHAREDCCCOMPOPTS) $(EXTRACFLAGS)
# The remainder of this file could probably be simplified by including
# ../Makefile.
LIBNAME=raw_spacetime_lib
CAMLOBJS=raw_spacetime_lib.cmo
-CC=$(BYTECC)
COMPFLAGS=-w +33..39 -warn-error A -bin-annot -g -safe-string $(EXTRACAMLFLAGS)
CMIFILES=$(CAMLOBJS:.cmo=.cmi)
$(CAMLOPT) -c $(COMPFLAGS) $<
depend:
- $(CAMLRUN) $(ROOTDIR)/tools/ocamldep *.mli *.ml >> .depend
+ $(CAMLRUN) $(ROOTDIR)/tools/ocamldep *.mli *.ml > .depend
include .depend
(* *)
(* Mark Shinwell and Leo White, Jane Street Europe *)
(* *)
-(* Copyright 2015--2016 Jane Street Group LLC *)
+(* Copyright 2015--2017 Jane Street Group LLC *)
(* *)
(* All rights reserved. This file is distributed under the terms of *)
(* the GNU Lesser General Public License version 2.1, with the *)
let _ = Indirect_call 0L
let _ = Allocation_point 0L
- let part_of_shape_size = function
- | Direct_call _
- | Indirect_call _ -> 1
- | Allocation_point _ -> 3
-
type raw = (Int64.t * (part_of_shape list)) list
- type t = part_of_shape list Int64_map.t
+ type t = {
+ shapes : part_of_shape list Int64_map.t;
+ call_counts : bool;
+ }
- let demarshal chn : t =
+ let part_of_shape_size t = function
+ | Direct_call _ -> if t.call_counts then 2 else 1
+ | Indirect_call _ -> 1
+ | Allocation_point _ -> 3
+
+ let demarshal chn ~call_counts : t =
let raw : raw = Marshal.from_channel chn in
- List.fold_left (fun map (key, data) -> Int64_map.add key data map)
- Int64_map.empty
- raw
+ let shapes =
+ List.fold_left (fun map (key, data) -> Int64_map.add key data map)
+ Int64_map.empty
+ raw
+ in
+ { shapes;
+ call_counts;
+ }
- let find_exn = Int64_map.find
+ let find_exn func_id t = Int64_map.find func_id t.shapes
+ let call_counts t = t.call_counts
end
module Annotation = struct
type uninstrumented_node
type t = node option
+ type trace = t
(* This function unmarshals into malloc blocks, which mean that we
obtain a straightforward means of writing [compare] on [node]s. *)
let callee_node (type target) (t : target t) : target =
callee_node t.node t.offset
+
+ external call_count : ocaml_node -> int -> int
+ = "caml_spacetime_only_works_for_native_code"
+ "caml_spacetime_ocaml_direct_call_point_call_count"
+
+ let call_count t =
+ if Shape_table.call_counts t.shape_table then
+ Some (call_count t.node t.offset)
+ else
+ None
end
module Indirect_call_point = struct
module Callee = struct
(* CR-soon mshinwell: we should think about the names again. This is
a "c_node" but it isn't foreign. *)
- type t = foreign_node
+ type t = {
+ node : foreign_node;
+ call_counts : bool;
+ }
- let is_null = foreign_node_is_null
+ let is_null t = foreign_node_is_null t.node
(* CR-soon mshinwell: maybe rename ...c_node_call_site -> c_node_pc,
since it isn't a call site in this case. *)
- external callee : t -> Function_entry_point.t
+ external callee : foreign_node -> Function_entry_point.t
= "caml_spacetime_only_works_for_native_code"
"caml_spacetime_c_node_call_site"
+ let callee t = callee t.node
+
(* This can return a node satisfying "is_null" in the case of an
uninitialised tail call point. See the comment in the C code. *)
- external callee_node : t -> node
+ external callee_node : foreign_node -> node
= "caml_spacetime_only_works_for_native_code"
"caml_spacetime_c_node_callee_node" "noalloc"
- external next : t -> foreign_node
+ let callee_node t = callee_node t.node
+
+ external call_count : foreign_node -> int
+ = "caml_spacetime_only_works_for_native_code"
+ "caml_spacetime_c_node_call_count"
+
+ let call_count t =
+ if t.call_counts then Some (call_count t.node)
+ else None
+
+ external next : foreign_node -> foreign_node
= "caml_spacetime_only_works_for_native_code"
"caml_spacetime_c_node_next" "noalloc"
let next t =
- let next = next t in
- if foreign_node_is_null next then None
+ let next = { t with node = next t.node; } in
+ if foreign_node_is_null next.node then None
else Some next
end
- external callees : ocaml_node -> int -> Callee.t
+ external callees : ocaml_node -> int -> foreign_node
= "caml_spacetime_only_works_for_native_code"
"caml_spacetime_ocaml_indirect_call_point_callees"
"noalloc"
let callees t =
- let callees = callees t.node t.offset in
+ let callees =
+ { Callee.
+ node = callees t.node t.offset;
+ call_counts = Shape_table.call_counts t.shape_table;
+ }
+ in
if Callee.is_null callees then None
else Some callees
end
match t.remaining_layout with
| [] -> None
| part_of_shape::remaining_layout ->
- let size = Shape_table.part_of_shape_size t.part_of_shape in
+ let size =
+ Shape_table.part_of_shape_size t.shape_table t.part_of_shape
+ in
let offset = t.offset + size in
assert (offset < Obj.size (Obj.repr t.node));
let t =
"caml_spacetime_compare_node" "noalloc"
let fields t ~shape_table =
- match Shape_table.find_exn (function_identifier t) shape_table with
+ let id = function_identifier t in
+ match Shape_table.find_exn id shape_table with
| exception Not_found -> None
| [] -> None
| part_of_shape::remaining_layout ->
finaliser_traces_by_thread : Trace.t array;
snapshots : heap_snapshot array;
events : Event.t list;
+ call_counts : bool;
}
let pathname_suffix_trace = "trace"
let chn = open_in path in
let magic_number : int = Marshal.from_channel chn in
let magic_number_base = magic_number land 0xffff_ffff in
- let version_number = magic_number lsr 32 in
+ let version_number = (magic_number lsr 32) land 0xffff in
+ let features = (magic_number lsr 48) land 0xffff in
if magic_number_base <> 0xace00ace then begin
failwith "Raw_spacetime_lib: not a Spacetime profiling file"
end else begin
match version_number with
| 0 ->
+ let call_counts =
+ match features with
+ | 0 -> false
+ | 1 -> true
+ | _ ->
+ failwith "Raw_spacetime_lib: unknown Spacetime profiling file \
+ feature set"
+ in
let snapshots, events = read_snapshots_and_events chn [] [] in
let num_snapshots = Array.length snapshots in
let time_of_writer_close : float = Marshal.from_channel chn in
let frame_table = Frame_table.demarshal chn in
- let shape_table = Shape_table.demarshal chn in
+ let shape_table = Shape_table.demarshal chn ~call_counts in
let num_threads : int = Marshal.from_channel chn in
let traces_by_thread = Array.init num_threads (fun _ -> None) in
let finaliser_traces_by_thread =
finaliser_traces_by_thread;
snapshots;
events;
+ call_counts;
}
| _ ->
failwith "Raw_spacetime_lib: unknown Spacetime profiling file \
let shape_table t = t.shape_table
let time_of_writer_close t = t.time_of_writer_close
let events t = t.events
+ let has_call_counts t = t.call_counts
end
end
(* *)
(* Mark Shinwell and Leo White, Jane Street Europe *)
(* *)
-(* Copyright 2015--2016 Jane Street Group LLC *)
+(* Copyright 2015--2017 Jane Street Group LLC *)
(* *)
(* All rights reserved. This file is distributed under the terms of *)
(* the GNU Lesser General Public License version 2.1, with the *)
information required to decode profiling annotations written into
values' headers. *)
type t
+ type trace = t
type node
type ocaml_node
(** The node corresponding to the callee. *)
val callee_node : 'target t -> 'target
+
+ (** The number of times the callee was called. Only available if the
+ compiler that recorded the Spacetime profile was configured with
+ "-with-spacetime-call-counts". [None] will be returned otherwise. *)
+ val call_count : _ t -> int option
end
module Indirect_call_point : sig
(** The node corresponding to the callee. *)
val callee_node : t -> node
+ (** The number of times the callee was called. This returns [None] in
+ the same circumstances as [Direct_call_point.call_count], above. *)
+ val call_count : t -> int option
+
(** Move to the next callee to which this call point has branched.
[None] is returned when the end of the list is reached. *)
val next : t -> t option
module Call_point : sig
(** A value of type [t] corresponds to a call point from non-OCaml
code (to either non-OCaml code, or OCaml code via the usual
- assembly veneer). *)
+ assembly veneer). Call counts are not available for such nodes. *)
type t
(** N.B. The address of the callee (of type [Function_entry_point.t]) is
val num_snapshots : t -> int
val snapshot : t -> index:int -> heap_snapshot
val events : t -> Event.t list
+
+ (** Returns [true] iff call count information was recorded in the
+ series. *)
+ val has_call_counts : t -> bool
end
end
-strstubs.o: strstubs.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+strstubs.$(O): strstubs.c ../../byterun/caml/mlvalues.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/alloc.h ../../byterun/caml/memory.h \
../../byterun/caml/fail.h
str.cmo : str.cmi
CAMLOBJS=str.cmo
include ../Makefile
-
str.cmo: str.cmi
str.cmx: str.cmi
+.PHONY: depend
depend:
- $(CC) -MM $(CFLAGS) *.c > .depend
- $(CAMLRUN) $(ROOTDIR)/tools/ocamldep -slash *.mli *.ml >> .depend
-
ifeq "$(TOOLCHAIN)" "msvc"
-
-.depend.nt: .depend
- sed -e 's/\.o/.$(O)/g' $< > $@
-
-include .depend.nt
+ $(error Dependencies cannot be regenerated using the MSVC ports)
else
-include .depend
+ $(CC) -MM $(CPPFLAGS) *.c | sed -e 's/\.o/.$$(O)/g' > .depend
+ $(CAMLRUN) $(ROOTDIR)/tools/ocamldep -slash *.mli *.ml >> .depend
endif
+
+include .depend
(** Regular expressions and high-level string processing *)
-(** {6 Regular expressions} *)
+(** {1 Regular expressions} *)
type regexp
but the regexp matches in a case-insensitive way. *)
-(** {6 String matching and searching} *)
+(** {1 String matching and searching} *)
val string_match : regexp -> string -> int -> bool
the regular expression. *)
-(** {6 Replacement} *)
+(** {1 Replacement} *)
val global_replace : regexp -> string -> string -> string
searching function. *)
-(** {6 Splitting} *)
+(** {1 Splitting} *)
val split : regexp -> string -> string list
the latter are tagged [Text]. *)
-(** {6 Extracting substrings} *)
+(** {1 Extracting substrings} *)
val string_before : string -> int -> string
case ACCEPT:
goto accept;
case SIMPLEOPT: {
- char * set = String_val(Field(cpool, Arg(instr)));
+ const char * set = String_val(Field(cpool, Arg(instr)));
if (txt < endtxt && In_bitset(set, *txt, c)) txt++;
break;
}
case SIMPLESTAR: {
- char * set = String_val(Field(cpool, Arg(instr)));
+ const char * set = String_val(Field(cpool, Arg(instr)));
while (txt < endtxt && In_bitset(set, *txt, c))
txt++;
break;
}
case SIMPLEPLUS: {
- char * set = String_val(Field(cpool, Arg(instr)));
+ const char * set = String_val(Field(cpool, Arg(instr)));
if (txt == endtxt) goto prefix_match;
if (! In_bitset(set, *txt, c)) goto backtrack;
txt++;
CAMLparam3(repl, groups, orig);
CAMLlocal1(res);
mlsize_t start, end, len, n;
- char * p, * q;
+ const char * p;
+ char * q;
int c;
len = 0;
}
res = caml_alloc_string(len);
p = String_val(repl);
- q = String_val(res);
+ q = (char *)String_val(res);
n = caml_string_length(repl);
while (n > 0) {
c = *p++; n--;
-st_stubs.o: st_stubs.c ../../byterun/caml/alloc.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/misc.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/backtrace.h ../../byterun/caml/exec.h \
- ../../byterun/caml/callback.h ../../byterun/caml/custom.h \
- ../../byterun/caml/fail.h ../../byterun/caml/io.h \
- ../../byterun/caml/memory.h ../../byterun/caml/gc.h \
- ../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \
- ../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h \
- ../../byterun/caml/printexc.h ../../byterun/caml/roots.h \
- ../../byterun/caml/signals.h ../../byterun/caml/stacks.h \
- ../../byterun/caml/sys.h threads.h st_posix.h
+st_stubs_b.$(O): st_stubs.c ../../byterun/caml/alloc.h \
+ ../../byterun/caml/misc.h ../../byterun/caml/config.h \
+ ../../byterun/caml/m.h ../../byterun/caml/s.h \
+ ../../byterun/caml/mlvalues.h ../../byterun/caml/backtrace.h \
+ ../../byterun/caml/exec.h ../../byterun/caml/callback.h \
+ ../../byterun/caml/custom.h ../../byterun/caml/fail.h \
+ ../../byterun/caml/io.h ../../byterun/caml/memory.h \
+ ../../byterun/caml/gc.h ../../byterun/caml/major_gc.h \
+ ../../byterun/caml/freelist.h ../../byterun/caml/minor_gc.h \
+ ../../byterun/caml/address_class.h ../../byterun/caml/printexc.h \
+ ../../byterun/caml/roots.h ../../byterun/caml/signals.h \
+ ../../byterun/caml/stacks.h ../../byterun/caml/sys.h threads.h \
+ st_posix.h
+st_stubs_n.$(O): st_stubs.c ../../byterun/caml/alloc.h \
+ ../../byterun/caml/misc.h ../../byterun/caml/config.h \
+ ../../byterun/caml/m.h ../../byterun/caml/s.h \
+ ../../byterun/caml/mlvalues.h ../../byterun/caml/backtrace.h \
+ ../../byterun/caml/exec.h ../../byterun/caml/callback.h \
+ ../../byterun/caml/custom.h ../../byterun/caml/fail.h \
+ ../../byterun/caml/io.h ../../byterun/caml/memory.h \
+ ../../byterun/caml/gc.h ../../byterun/caml/major_gc.h \
+ ../../byterun/caml/freelist.h ../../byterun/caml/minor_gc.h \
+ ../../byterun/caml/address_class.h ../../byterun/caml/printexc.h \
+ ../../byterun/caml/roots.h ../../byterun/caml/signals.h \
+ ../../byterun/caml/stack.h ../../byterun/caml/sys.h threads.h \
+ st_posix.h
condition.cmo : mutex.cmi condition.cmi
condition.cmx : mutex.cmx condition.cmi
condition.cmi : mutex.cmi
HEADER = st_win32.h
endif
+# Note: the header on which object files produced from st_stubs.c
+# should actually depend is known for sure only at compile-time.
+# That's why this dependency is handled in the Makefile directly
+# and removed from the output of the C compiler during make depend
+
BYTECODE_C_OBJS=st_stubs_b.$(O)
NATIVECODE_C_OBJS=st_stubs_n.$(O)
# The following lines produce two object files st_stubs_b.$(O) and
# st_stubs_n.$(O) from the same source file st_stubs.c (it is compiled
-# twice, each time with different of options).
-# Since the source and object file have a different basename, the name of
-# the object file to produce must be given to the C compiler.
-# For gcc this is done with the -ofoo.$(O) option.
-# For msvc it's the /Fofoo.$(O) option.
-
-ifeq "$(TOOLCHAIN)" "msvc"
- CCOUTPUT=/Fo
-else
- CCOUTPUT=-o
-endif
+# twice, each time with different options).
st_stubs_b.$(O): st_stubs.c $(HEADER)
- $(BYTECC) -I$(ROOTDIR)/byterun $(BYTECCCOMPOPTS) $(SHAREDCCCOMPOPTS) \
- $(CCOUTPUT)$@ -c $<
+ $(CC) -c $(CFLAGS) $(CPPFLAGS) -I$(ROOTDIR)/byterun \
+ $(SHAREDCCCOMPOPTS) $(OUTPUTOBJ)$@ $<
st_stubs_n.$(O): st_stubs.c $(HEADER)
- $(NATIVECC) -I$(ROOTDIR)/asmrun -I$(ROOTDIR)/byterun \
- $(NATIVECCCOMPOPTS) $(SHAREDCCCOMPOPTS) -DNATIVE_CODE \
+ $(CC) $(CFLAGS) $(CPPFLAGS) -I$(ROOTDIR)/asmrun -I$(ROOTDIR)/byterun \
+ $(SHAREDCCCOMPOPTS) -DNATIVE_CODE \
-DTARGET_$(ARCH) -DMODEL_$(MODEL) -DSYS_$(SYSTEM) \
- $(CCOUTPUT)$@ -c $<
+ $(OUTPUTOBJ)$@ -c $<
partialclean:
rm -f *.cm*
.ml.cmx:
$(CAMLOPT) -c $(COMPFLAGS) $(OPTCOMPFLAGS) $<
-ifeq "$(UNIX_OR_WIN32)" "unix"
-depend: $(GENFILES)
- -$(CC) -MM -I../../byterun *.c > .depend
- $(CAMLRUN) ../../tools/ocamldep -slash *.mli *.ml >> .depend
-else # Windows
+.PHONY: depend
+ifeq "$(TOOLCHAIN)" "msvc"
depend:
+ $(error Dependencies cannot be regenerated using the MSVC ports)
+else
+depend:
+ $(CC) -MM $(CPPFLAGS) -I$(ROOTDIR)/byterun st_stubs.c \
+ | sed -e 's/st_stubs\.o/st_stubs_b.$$(O)/' \
+ -e 's/ st_\(posix\|win32\)\.h//g' > .depend
+ $(CC) -MM $(CPPFLAGS) -I$(ROOTDIR)/asmrun -I$(ROOTDIR)/byterun \
+ -DNATIVE_CODE -DTARGET_$(ARCH) -DMODEL_$(MODEL) -DSYS_$(SYSTEM) \
+ st_stubs.c | sed -e 's/st_stubs\.o/st_stubs_n.$$(O)/' \
+ -e 's/ st_\(posix\|win32\)\.h//g' >> .depend
+ $(CAMLRUN) ../../tools/ocamldep -slash *.mli *.ml >> .depend
endif
include .depend
}
/* The master lock. This is a mutex that is held most of the time,
- so we implement it in a slightly consoluted way to avoid
+ so we implement it in a slightly convoluted way to avoid
all risks of busy-waiting. Also, we count the number of waiting
threads. */
static int st_mutex_create(st_mutex * res)
{
int rc;
- st_mutex m = malloc(sizeof(pthread_mutex_t));
+ st_mutex m = caml_stat_alloc_noexc(sizeof(pthread_mutex_t));
if (m == NULL) return ENOMEM;
rc = pthread_mutex_init(m, NULL);
- if (rc != 0) { free(m); return rc; }
+ if (rc != 0) { caml_stat_free(m); return rc; }
*res = m;
return 0;
}
{
int rc;
rc = pthread_mutex_destroy(m);
- free(m);
+ caml_stat_free(m);
return rc;
}
static int st_condvar_create(st_condvar * res)
{
int rc;
- st_condvar c = malloc(sizeof(pthread_cond_t));
+ st_condvar c = caml_stat_alloc_noexc(sizeof(pthread_cond_t));
if (c == NULL) return ENOMEM;
rc = pthread_cond_init(c, NULL);
- if (rc != 0) { free(c); return rc; }
+ if (rc != 0) { caml_stat_free(c); return rc; }
*res = c;
return 0;
}
{
int rc;
rc = pthread_cond_destroy(c);
- free(c);
+ caml_stat_free(c);
return rc;
}
static int st_event_create(st_event * res)
{
int rc;
- st_event e = malloc(sizeof(struct st_event_struct));
+ st_event e = caml_stat_alloc_noexc(sizeof(struct st_event_struct));
if (e == NULL) return ENOMEM;
rc = pthread_mutex_init(&e->lock, NULL);
- if (rc != 0) { free(e); return rc; }
+ if (rc != 0) { caml_stat_free(e); return rc; }
rc = pthread_cond_init(&e->triggered, NULL);
- if (rc != 0) { pthread_mutex_destroy(&e->lock); free(e); return rc; }
+ if (rc != 0) { pthread_mutex_destroy(&e->lock); caml_stat_free(e); return rc; }
e->status = 0;
*res = e;
return 0;
int rc1, rc2;
rc1 = pthread_mutex_destroy(&e->lock);
rc2 = pthread_cond_destroy(&e->triggered);
- free(e);
+ caml_stat_free(e);
return rc1 != 0 ? rc1 : rc2;
}
#define Start_closure(v) (((struct caml_thread_descr *)(v))->start_closure)
#define Terminated(v) (((struct caml_thread_descr *)(v))->terminated)
-/* The infos on threads (allocated via malloc()) */
+/* The infos on threads (allocated via caml_stat_alloc()) */
struct caml_thread_struct {
value descr; /* The heap-allocated descriptor (root) */
static caml_thread_t caml_thread_new_info(void)
{
caml_thread_t th;
- th = (caml_thread_t) malloc(sizeof(struct caml_thread_struct));
+ th = (caml_thread_t) caml_stat_alloc_noexc(sizeof(struct caml_thread_struct));
if (th == NULL) return NULL;
th->descr = Val_unit; /* filled later */
#ifdef NATIVE_CODE
#ifndef NATIVE_CODE
caml_stat_free(th->stack_low);
#endif
- if (th->backtrace_buffer != NULL) free(th->backtrace_buffer);
+ if (th->backtrace_buffer != NULL) caml_stat_free(th->backtrace_buffer);
#ifndef WITH_SPACETIME
caml_stat_free(th);
/* CR-soon mshinwell: consider what to do about the Spacetime trace. Could
return Val_unit;
}
-/* Cleanup the thread machinery on program exit or DLL unload. */
+/* Cleanup the thread machinery when the runtime is shut down. Joining the tick
+ thread take 25ms on average / 50ms in the worst case, so we don't do it on
+ program exit. */
CAMLprim value caml_thread_cleanup(value unit) /* ML */
{
char * msg = caml_format_exception(exn);
fprintf(stderr, "Thread %d killed on uncaught exception %s\n",
Int_val(Ident(curr_thread->descr)), msg);
- free(msg);
+ caml_stat_free(msg);
if (caml_backtrace_active) caml_print_exception_backtrace();
fflush(stderr);
return Val_unit;
#include <stdio.h>
#include <signal.h>
+#include <caml/osdeps.h>
+
#define INLINE __inline
#if 1
#define SIGPREEMPTION SIGTERM
-/* Thread-local storage assocaiting a Win32 event to every thread. */
+/* Thread-local storage associating a Win32 event to every thread. */
static DWORD st_thread_sem_key;
/* OS-specific initialization */
static DWORD st_mutex_create(st_mutex * res)
{
- st_mutex m = malloc(sizeof(CRITICAL_SECTION));
+ st_mutex m = caml_stat_alloc_noexc(sizeof(CRITICAL_SECTION));
if (m == NULL) return ERROR_NOT_ENOUGH_MEMORY;
InitializeCriticalSection(m);
*res = m;
static DWORD st_mutex_destroy(st_mutex m)
{
DeleteCriticalSection(m);
- free(m);
+ caml_stat_free(m);
return 0;
}
static DWORD st_condvar_create(st_condvar * res)
{
- st_condvar c = malloc(sizeof(struct st_condvar_struct));
+ st_condvar c = caml_stat_alloc_noexc(sizeof(struct st_condvar_struct));
if (c == NULL) return ERROR_NOT_ENOUGH_MEMORY;
InitializeCriticalSection(&c->lock);
c->waiters = NULL;
{
TRACE1("st_condvar_destroy", c);
DeleteCriticalSection(&c->lock);
- free(c);
+ caml_stat_free(c);
return 0;
}
static void st_check_error(DWORD retcode, char * msg)
{
- char err[1024];
- int errlen, msglen;
+ wchar_t err[1024];
+ int errlen, msglen, ret;
value str;
if (retcode == 0) return;
if (retcode == ERROR_NOT_ENOUGH_MEMORY) caml_raise_out_of_memory();
- if (! FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
+ ret = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
retcode,
0,
err,
- sizeof(err),
- NULL)) {
- sprintf(err, "error code %lx", retcode);
+ sizeof(err)/sizeof(wchar_t),
+ NULL);
+ if (! ret) {
+ ret = swprintf(err, sizeof(err)/sizeof(wchar_t), L"error code %lx", retcode);
}
msglen = strlen(msg);
- errlen = strlen(err);
+ errlen = win_wide_char_to_multi_byte(err, ret, NULL, 0);
str = caml_alloc_string(msglen + 2 + errlen);
memmove (&Byte(str, 0), msg, msglen);
memmove (&Byte(str, msglen), ": ", 2);
- memmove (&Byte(str, msglen + 2), err, errlen);
+ win_wide_char_to_multi_byte(err, ret, &Byte(str, msglen + 2), errlen);
caml_raise_sys_error(str);
}
| "Win32" -> Sys.sigterm
| _ -> Sys.sigvtalrm
-let _ =
+let () =
Sys.set_signal preempt_signal (Sys.Signal_handle preempt);
- thread_initialize();
- at_exit
- (fun () ->
- thread_cleanup();
- (* In case of DLL-embedded OCaml the preempt_signal handler
- will point to nowhere after DLL unloading and an accidental
- preempt_signal will crash the main program. So restore the
- default handler. *)
- Sys.set_signal preempt_signal Sys.Signal_default
- )
+ thread_initialize ();
+ Callback.register "Thread.at_shutdown" (fun () ->
+ thread_cleanup();
+ (* In case of DLL-embedded OCaml the preempt_signal handler
+ will point to nowhere after DLL unloading and an accidental
+ preempt_signal will crash the main program. So restore the
+ default handler. *)
+ Sys.set_signal preempt_signal Sys.Signal_default
+ )
(* Wait functions *)
type t
(** The type of thread handles. *)
-(** {6 Thread creation and termination} *)
+(** {1 Thread creation and termination} *)
val create : ('a -> 'b) -> 'a -> t
(** [Thread.create funct arg] creates a new thread of control,
val kill : t -> unit
(** Terminate prematurely the thread whose handle is given. *)
-(** {6 Suspending threads} *)
+(** {1 Suspending threads} *)
val delay: float -> unit
(** [delay d] suspends the execution of the calling thread for
telling the scheduler that now is a good time to
switch to other threads. *)
-(** {6 Management of signals} *)
+(** {1 Management of signals} *)
(** Signal handling follows the POSIX thread model: signals generated
by a thread are delivered to that thread; signals generated externally
(block the calling thread, if required, but do not block all threads
in the process). *)
-(** {6 Process handling} *)
+(** {1 Process handling} *)
val execv : string -> string array -> unit
val execve : string -> string array -> string array -> unit
val waitpid : Unix.wait_flag list -> int -> int * Unix.process_status
val system : string -> Unix.process_status
-(** {6 Basic input/output} *)
+(** {1 Basic input/output} *)
val read : Unix.file_descr -> bytes -> int -> int -> int
val write : Unix.file_descr -> bytes -> int -> int -> int
val write_substring : Unix.file_descr -> string -> int -> int -> int
-(** {6 Input/output with timeout} *)
+(** {1 Input/output with timeout} *)
val timed_read :
Unix.file_descr ->
Unix.file_descr -> string -> int -> int -> float -> int
(** See {!ThreadUnix.timed_write}. *)
-(** {6 Polling} *)
+(** {1 Polling} *)
val select :
Unix.file_descr list -> Unix.file_descr list ->
Unix.file_descr list -> float ->
Unix.file_descr list * Unix.file_descr list * Unix.file_descr list
-(** {6 Pipes and redirections} *)
+(** {1 Pipes and redirections} *)
val pipe : ?cloexec:bool -> unit -> Unix.file_descr * Unix.file_descr
val open_process_in: string -> in_channel
val open_process_out: string -> out_channel
val open_process: string -> in_channel * out_channel
-(** {6 Time} *)
+(** {1 Time} *)
val sleep : int -> unit
-(** {6 Sockets} *)
+(** {1 Sockets} *)
val socket :
?cloexec:bool -> Unix.socket_domain -> Unix.socket_type -> int ->
scheduler.o: scheduler.c ../../byterun/caml/alloc.h \
../../byterun/caml/misc.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/backtrace.h ../../byterun/caml/exec.h \
- ../../byterun/caml/callback.h ../../byterun/caml/fail.h \
- ../../byterun/caml/io.h ../../byterun/caml/memory.h \
- ../../byterun/caml/gc.h ../../byterun/caml/major_gc.h \
- ../../byterun/caml/freelist.h ../../byterun/caml/minor_gc.h \
- ../../byterun/caml/address_class.h ../../byterun/caml/printexc.h \
- ../../byterun/caml/roots.h ../../byterun/caml/signals.h \
- ../../byterun/caml/stacks.h ../../byterun/caml/sys.h
+ ../../byterun/caml/m.h ../../byterun/caml/s.h \
+ ../../byterun/caml/mlvalues.h ../../byterun/caml/backtrace.h \
+ ../../byterun/caml/exec.h ../../byterun/caml/callback.h \
+ ../../byterun/caml/fail.h ../../byterun/caml/io.h \
+ ../../byterun/caml/memory.h ../../byterun/caml/gc.h \
+ ../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \
+ ../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h \
+ ../../byterun/caml/printexc.h ../../byterun/caml/roots.h \
+ ../../byterun/caml/signals.h ../../byterun/caml/stacks.h \
+ ../../byterun/caml/sys.h
condition.cmo : thread.cmi mutex.cmi condition.cmi
condition.cmx : thread.cmx mutex.cmx condition.cmi
condition.cmi : mutex.cmi
CAMLRUN ?= ../../boot/ocamlrun
CAMLYACC ?= ../../boot/ocamlyacc
-CC=$(BYTECC)
-CFLAGS=-I../../byterun $(BYTECCCOMPOPTS) $(SHAREDCCCOMPOPTS) -g
+CFLAGS += $(SHAREDCCCOMPOPTS)
+CPPFLAGS += -I../../byterun
ROOTDIR=../..
CAMLC=$(CAMLRUN) $(ROOTDIR)/ocamlc -nostdlib \
-I $(ROOTDIR)/stdlib -I $(ROOTDIR)/otherlibs/unix
install:
if test -f dllvmthreads.so; then \
- cp dllvmthreads.so $(INSTALL_STUBLIBDIR)/.; \
+ cp dllvmthreads.so "$(INSTALL_STUBLIBDIR)"; \
fi
- mkdir -p $(INSTALL_LIBDIR)/vmthreads
- cp libvmthreads.a $(INSTALL_LIBDIR)/vmthreads/libvmthreads.a
- cd $(INSTALL_LIBDIR)/vmthreads; $(RANLIB) libvmthreads.a
+ mkdir -p "$(INSTALL_LIBDIR)/vmthreads"
+ cp libvmthreads.a "$(INSTALL_LIBDIR)/vmthreads"
+ cd "$(INSTALL_LIBDIR)/vmthreads"; $(RANLIB) libvmthreads.a
cp $(CMIFILES) $(CMIFILES:.cmi=.mli) $(CMIFILES:.cmi=.cmti) \
- threads.cma stdlib.cma unix.cma $(INSTALL_LIBDIR)/vmthreads
+ threads.cma stdlib.cma unix.cma "$(INSTALL_LIBDIR)/vmthreads"
installopt:
.ml.cmo:
$(CAMLC) -c $(COMPFLAGS) $<
+.PHONY: depend
depend:
- $(CC) -MM $(CFLAGS) *.c > .depend
+ifeq "$(TOOLCHAIN)" "msvc"
+ $(error Dependencies cannot be regenerated using the MSVC ports)
+else
+ $(CC) -MM $(CPPFLAGS) *.c > .depend
$(CAMLRUN) ../../tools/ocamldep -slash *.mli *.ml >> .depend
+endif
include .depend
external float_of_int : int -> float = "%floatofint"
external truncate : float -> int = "%intoffloat"
external int_of_float : float -> int = "%intoffloat"
-external float_of_bits : int64 -> float = "caml_int64_float_of_bits"
+external float_of_bits : int64 -> float
+ = "caml_int64_float_of_bits" "caml_int64_float_of_bits_unboxed"
+ [@@unboxed] [@@noalloc]
let infinity =
float_of_bits 0x7F_F0_00_00_00_00_00_00L
let neg_infinity =
| _ -> s
in
loop 0
-;;
-let string_of_float f = valid_float_lexem (format_float "%.12g" f);;
+let string_of_float f = valid_float_lexem (format_float "%.12g" f)
external float_of_string : string -> float = "caml_float_of_string"
external pos_out : out_channel -> int = "caml_ml_pos_out"
external out_channel_length : out_channel -> int = "caml_ml_channel_size"
external close_out_channel : out_channel -> unit = "caml_ml_close_channel"
-
-let close_out oc = (try flush oc with _ -> ()); close_out_channel oc
+let close_out oc = flush oc; close_out_channel oc
let close_out_noerr oc =
(try flush oc with _ -> ());
(try close_out_channel oc with _ -> ())
external pos_in : in_channel -> int = "caml_ml_pos_in"
external in_channel_length : in_channel -> int = "caml_ml_channel_size"
external close_in : in_channel -> unit = "caml_ml_close_channel"
-let close_in_noerr ic = (try close_in ic with _ -> ());;
+let close_in_noerr ic = (try close_in ic with _ -> ())
external set_binary_mode_in : in_channel -> bool -> unit
= "caml_ml_set_binary_mode"
type ('a, 'b, 'c) format = ('a, 'b, 'c, 'c) format4
-let string_of_format (Format (fmt, str)) = str
+let string_of_format (Format (_fmt, str)) = str
external format_of_string :
('a, 'b, 'c, 'd, 'e, 'f) format6 ->
('a, 'b, 'c, 'd, 'e, 'f) format6 = "%identity"
-let (^^) (Format (fmt1, str1)) (Format (fmt2, str2)) =
+let ( ^^ ) (Format (fmt1, str1)) (Format (fmt2, str2)) =
Format (CamlinternalFormatBasics.concat_fmt fmt1 fmt2,
str1 ^ "%," ^ str2)
defined(HAS_SETITIMER) && \
defined(HAS_GETTIMEOFDAY) && \
(defined(HAS_WAITPID) || defined(HAS_WAIT4)))
-#include "Cannot compile libthreads, system calls missing"
+#warning "Cannot compile libthreads, system calls missing"
#endif
#include <errno.h>
value thread_yield(value unit) /* ML */
{
- Assert(curr_thread != NULL);
+ CAMLassert(curr_thread != NULL);
Assign(curr_thread->retval, Val_unit);
return schedule_thread();
}
{
value accu;
- Assert(curr_thread != NULL);
+ CAMLassert(curr_thread != NULL);
/* Pop accu from event frame, making it look like a C_CALL frame
followed by a RETURN frame */
accu = *caml_extern_sp++;
value thread_sleep(value unit) /* ML */
{
- Assert(curr_thread != NULL);
+ CAMLassert(curr_thread != NULL);
check_callback();
curr_thread->status = SUSPENDED;
return schedule_thread();
value thread_delay(value time) /* ML */
{
double date = timeofday() + Double_val(time);
- Assert(curr_thread != NULL);
+ CAMLassert(curr_thread != NULL);
check_callback();
curr_thread->status = BLOCKED_DELAY;
Assign(curr_thread->delay, caml_copy_double(date));
value thread_join(value th) /* ML */
{
check_callback();
- Assert(curr_thread != NULL);
+ CAMLassert(curr_thread != NULL);
if (((caml_thread_t)th)->status == KILLED) return Val_unit;
curr_thread->status = BLOCKED_JOIN;
Assign(curr_thread->joining, th);
value thread_wait_pid(value pid) /* ML */
{
- Assert(curr_thread != NULL);
+ CAMLassert(curr_thread != NULL);
check_callback();
curr_thread->status = BLOCKED_WAIT;
curr_thread->waitpid = pid;
value thread_self(value unit) /* ML */
{
- Assert(curr_thread != NULL);
+ CAMLassert(curr_thread != NULL);
return (value) curr_thread;
}
th->sp = NULL;
th->trapsp = NULL;
if (th->backtrace_buffer != NULL) {
- free(th->backtrace_buffer);
+ caml_stat_free(th->backtrace_buffer);
th->backtrace_buffer = NULL;
}
return retval;
char * msg = caml_format_exception(exn);
fprintf(stderr, "Thread %d killed on uncaught exception %s\n",
Int_val(curr_thread->ident), msg);
- free(msg);
+ caml_stat_free(msg);
if (caml_backtrace_active) caml_print_exception_backtrace();
fflush(stderr);
return Val_unit;
(** The type of thread handles. *)
-(** {6 Thread creation and termination} *)
+(** {1 Thread creation and termination} *)
val create : ('a -> 'b) -> 'a -> t
(** [Thread.create funct arg] creates a new thread of control,
(** Terminate prematurely the thread whose handle is given.
This functionality is available only with bytecode-level threads. *)
-(** {6 Suspending threads} *)
+(** {1 Suspending threads} *)
val delay : float -> unit
(** [delay d] suspends the execution of the calling thread for
(**/**)
-(** {6 Synchronization primitives}
+(** {1 Synchronization primitives}
The following primitives provide the basis for implementing
synchronization functions between threads. Their direct use is
(block the calling thread, if required, but do not block all threads
in the process). *)
-(** {6 Process handling} *)
+(** {1 Process handling} *)
val execv : string -> string array -> unit
val execve : string -> string array -> string array -> unit
val waitpid : Unix.wait_flag list -> int -> int * Unix.process_status
val system : string -> Unix.process_status
-(** {6 Basic input/output} *)
+(** {1 Basic input/output} *)
val read : Unix.file_descr -> bytes -> int -> int -> int
val write : Unix.file_descr -> bytes -> int -> int -> int
val write_substring : Unix.file_descr -> string -> int -> int -> int
val single_write_substring : Unix.file_descr -> string -> int -> int -> int
-(** {6 Input/output with timeout} *)
+(** {1 Input/output with timeout} *)
val timed_read : Unix.file_descr -> bytes -> int -> int -> float -> int
(** See {!ThreadUnix.timed_write}. *)
Unix.file_descr -> string -> int -> int -> float -> int
(** See {!ThreadUnix.timed_write}. *)
-(** {6 Polling} *)
+(** {1 Polling} *)
val select :
Unix.file_descr list -> Unix.file_descr list -> Unix.file_descr list ->
float ->
Unix.file_descr list * Unix.file_descr list * Unix.file_descr list
-(** {6 Pipes and redirections} *)
+(** {1 Pipes and redirections} *)
val pipe : ?cloexec:bool -> unit -> Unix.file_descr * Unix.file_descr
val open_process_in : string -> in_channel
val open_process_full :
string -> string array -> in_channel * out_channel * in_channel
-(** {6 Time} *)
+(** {1 Time} *)
val sleep : int -> unit
-(** {6 Sockets} *)
+(** {1 Sockets} *)
val socket :
?cloexec:bool -> Unix.socket_domain -> Unix.socket_type -> int ->
exit 2
external environment : unit -> string array = "unix_environment"
+external unsafe_environment : unit -> string array = "unix_environment_unsafe"
external getenv: string -> string = "caml_sys_getenv"
+external unsafe_getenv: string -> string = "caml_sys_unsafe_getenv"
external putenv: string -> string -> unit = "unix_putenv"
type interval_timer =
external fstat : file_descr -> stats = "unix_fstat_64"
end
+external map_internal:
+ file_descr -> ('a, 'b) CamlinternalBigarray.kind
+ -> 'c CamlinternalBigarray.layout
+ -> bool -> int array -> int64
+ -> ('a, 'b, 'c) CamlinternalBigarray.genarray
+ = "caml_unix_map_file_bytecode" "caml_unix_map_file"
+
+let map_file fd ?(pos=0L) kind layout shared dims =
+ map_internal fd kind layout shared dims pos
+
type access_permission =
R_OK
| W_OK
accept.o: accept.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/alloc.h ../../byterun/caml/fail.h \
../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h \
socketaddr.h
access.o: access.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/alloc.h ../../byterun/caml/memory.h \
- ../../byterun/caml/signals.h unixsupport.h
+ ../../byterun/caml/signals.h ../../byterun/caml/osdeps.h unixsupport.h
addrofstr.o: addrofstr.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/memory.h ../../byterun/caml/fail.h unixsupport.h \
socketaddr.h
alarm.o: alarm.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- unixsupport.h
-bind.o: bind.c ../../byterun/caml/fail.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/misc.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/mlvalues.h \
- unixsupport.h socketaddr.h
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h unixsupport.h
+bind.o: bind.c ../../byterun/caml/fail.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/mlvalues.h unixsupport.h \
+ socketaddr.h
chdir.o: chdir.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- ../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/memory.h ../../byterun/caml/gc.h \
+ ../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \
+ ../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h \
+ ../../byterun/caml/signals.h ../../byterun/caml/osdeps.h unixsupport.h
chmod.o: chmod.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- ../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/memory.h ../../byterun/caml/gc.h \
+ ../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \
+ ../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h \
+ ../../byterun/caml/signals.h ../../byterun/caml/osdeps.h unixsupport.h
chown.o: chown.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h
chroot.o: chroot.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h
close.o: close.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/signals.h unixsupport.h
closedir.o: closedir.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h
-connect.o: connect.c ../../byterun/caml/fail.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/misc.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/mlvalues.h \
+connect.o: connect.c ../../byterun/caml/fail.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/mlvalues.h \
../../byterun/caml/signals.h unixsupport.h socketaddr.h
cst2constr.o: cst2constr.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/fail.h cst2constr.h
cstringv.o: cstringv.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- ../../byterun/caml/memory.h unixsupport.h
-dup.o: dup.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- unixsupport.h
-dup2.o: dup2.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- unixsupport.h
-envir.o: envir.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- ../../byterun/caml/alloc.h
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/memory.h ../../byterun/caml/gc.h \
+ ../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \
+ ../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h \
+ ../../byterun/caml/osdeps.h unixsupport.h
+dup.o: dup.c ../../byterun/caml/mlvalues.h ../../byterun/caml/config.h \
+ ../../byterun/caml/m.h ../../byterun/caml/s.h \
+ ../../byterun/caml/misc.h unixsupport.h
+dup2.o: dup2.c ../../byterun/caml/mlvalues.h ../../byterun/caml/config.h \
+ ../../byterun/caml/m.h ../../byterun/caml/s.h \
+ ../../byterun/caml/misc.h unixsupport.h
+envir.o: envir.c ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/mlvalues.h \
+ ../../byterun/caml/misc.h ../../byterun/caml/alloc.h
errmsg.o: errmsg.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/alloc.h
execv.o: execv.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- ../../byterun/caml/memory.h unixsupport.h
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/memory.h ../../byterun/caml/gc.h \
+ ../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \
+ ../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h \
+ ../../byterun/caml/osdeps.h unixsupport.h
execve.o: execve.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- ../../byterun/caml/memory.h unixsupport.h
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/memory.h ../../byterun/caml/gc.h \
+ ../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \
+ ../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h \
+ ../../byterun/caml/osdeps.h unixsupport.h
execvp.o: execvp.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/memory.h ../../byterun/caml/osdeps.h unixsupport.h
-exit.o: exit.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- unixsupport.h
-fchmod.o: fchmod.c ../../byterun/caml/fail.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/misc.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/mlvalues.h \
+exit.o: exit.c ../../byterun/caml/mlvalues.h ../../byterun/caml/config.h \
+ ../../byterun/caml/m.h ../../byterun/caml/s.h \
+ ../../byterun/caml/misc.h unixsupport.h
+fchmod.o: fchmod.c ../../byterun/caml/fail.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/mlvalues.h \
../../byterun/caml/signals.h unixsupport.h
-fchown.o: fchown.c ../../byterun/caml/fail.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/misc.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/mlvalues.h \
+fchown.o: fchown.c ../../byterun/caml/fail.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/mlvalues.h \
../../byterun/caml/signals.h unixsupport.h
-fcntl.o: fcntl.c ../../byterun/caml/fail.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/misc.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/mlvalues.h \
- unixsupport.h
-fork.o: fork.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- ../../byterun/caml/debugger.h unixsupport.h
+fcntl.o: fcntl.c ../../byterun/caml/fail.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/mlvalues.h unixsupport.h
+fork.o: fork.c ../../byterun/caml/mlvalues.h ../../byterun/caml/config.h \
+ ../../byterun/caml/m.h ../../byterun/caml/s.h \
+ ../../byterun/caml/misc.h ../../byterun/caml/debugger.h unixsupport.h
ftruncate.o: ftruncate.c ../../byterun/caml/fail.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/misc.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/io.h ../../byterun/caml/signals.h unixsupport.h
+ ../../byterun/caml/misc.h ../../byterun/caml/config.h \
+ ../../byterun/caml/m.h ../../byterun/caml/s.h \
+ ../../byterun/caml/mlvalues.h ../../byterun/caml/io.h \
+ ../../byterun/caml/signals.h unixsupport.h
getaddrinfo.o: getaddrinfo.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/alloc.h ../../byterun/caml/fail.h \
../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h \
cst2constr.h socketaddr.h
getcwd.o: getcwd.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- ../../byterun/caml/alloc.h ../../byterun/caml/fail.h unixsupport.h
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/alloc.h ../../byterun/caml/fail.h \
+ ../../byterun/caml/osdeps.h ../../byterun/caml/memory.h \
+ ../../byterun/caml/gc.h ../../byterun/caml/major_gc.h \
+ ../../byterun/caml/freelist.h ../../byterun/caml/minor_gc.h \
+ ../../byterun/caml/address_class.h unixsupport.h
getegid.o: getegid.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- unixsupport.h
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h unixsupport.h
geteuid.o: geteuid.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- unixsupport.h
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h unixsupport.h
getgid.o: getgid.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- unixsupport.h
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h unixsupport.h
getgr.o: getgr.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/fail.h ../../byterun/caml/alloc.h \
../../byterun/caml/memory.h unixsupport.h
getgroups.o: getgroups.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/alloc.h ../../byterun/caml/fail.h unixsupport.h
gethost.o: gethost.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/alloc.h ../../byterun/caml/fail.h \
../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h \
socketaddr.h
gethostname.o: gethostname.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/alloc.h ../../byterun/caml/fail.h unixsupport.h
getlogin.o: getlogin.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/alloc.h unixsupport.h
getnameinfo.o: getnameinfo.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/alloc.h ../../byterun/caml/fail.h \
../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h \
socketaddr.h
getpeername.o: getpeername.c ../../byterun/caml/fail.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/misc.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/mlvalues.h \
- unixsupport.h socketaddr.h
+ ../../byterun/caml/misc.h ../../byterun/caml/config.h \
+ ../../byterun/caml/m.h ../../byterun/caml/s.h \
+ ../../byterun/caml/mlvalues.h unixsupport.h socketaddr.h
getpid.o: getpid.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- unixsupport.h
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h unixsupport.h
getppid.o: getppid.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- unixsupport.h
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h unixsupport.h
getproto.o: getproto.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/alloc.h ../../byterun/caml/fail.h \
../../byterun/caml/memory.h unixsupport.h
getpw.o: getpw.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/alloc.h ../../byterun/caml/memory.h \
../../byterun/caml/fail.h unixsupport.h
getserv.o: getserv.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/alloc.h ../../byterun/caml/fail.h \
../../byterun/caml/memory.h unixsupport.h
getsockname.o: getsockname.c ../../byterun/caml/fail.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/misc.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/mlvalues.h \
- unixsupport.h socketaddr.h
+ ../../byterun/caml/misc.h ../../byterun/caml/config.h \
+ ../../byterun/caml/m.h ../../byterun/caml/s.h \
+ ../../byterun/caml/mlvalues.h unixsupport.h socketaddr.h
gettimeofday.o: gettimeofday.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/alloc.h ../../byterun/caml/fail.h unixsupport.h
getuid.o: getuid.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- unixsupport.h
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h unixsupport.h
gmtime.o: gmtime.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/alloc.h ../../byterun/caml/fail.h \
../../byterun/caml/memory.h unixsupport.h
initgroups.o: initgroups.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/alloc.h ../../byterun/caml/fail.h unixsupport.h
isatty.o: isatty.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- unixsupport.h
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h unixsupport.h
itimer.o: itimer.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/alloc.h ../../byterun/caml/fail.h \
../../byterun/caml/memory.h unixsupport.h
-kill.o: kill.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- ../../byterun/caml/fail.h unixsupport.h ../../byterun/caml/signals.h
-link.o: link.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- ../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h
-listen.o: listen.c ../../byterun/caml/fail.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/misc.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/mlvalues.h \
- unixsupport.h
-lockf.o: lockf.c ../../byterun/caml/fail.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/misc.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/mlvalues.h \
+kill.o: kill.c ../../byterun/caml/mlvalues.h ../../byterun/caml/config.h \
+ ../../byterun/caml/m.h ../../byterun/caml/s.h \
+ ../../byterun/caml/misc.h ../../byterun/caml/fail.h unixsupport.h \
+ ../../byterun/caml/signals.h
+link.o: link.c ../../byterun/caml/mlvalues.h ../../byterun/caml/config.h \
+ ../../byterun/caml/m.h ../../byterun/caml/s.h \
+ ../../byterun/caml/misc.h ../../byterun/caml/memory.h \
+ ../../byterun/caml/signals.h unixsupport.h
+listen.o: listen.c ../../byterun/caml/fail.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/mlvalues.h unixsupport.h
+lockf.o: lockf.c ../../byterun/caml/fail.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/mlvalues.h \
../../byterun/caml/signals.h unixsupport.h
lseek.o: lseek.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/alloc.h ../../byterun/caml/io.h \
../../byterun/caml/signals.h unixsupport.h
mkdir.o: mkdir.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h
-mkfifo.o: mkfifo.c ../../byterun/caml/fail.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/misc.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/mlvalues.h \
+mkfifo.o: mkfifo.c ../../byterun/caml/fail.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/mlvalues.h \
+ ../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h
+mmap.o: mmap.c ../../byterun/caml/bigarray.h ../../byterun/caml/config.h \
+ ../../byterun/caml/m.h ../../byterun/caml/s.h \
+ ../../byterun/caml/mlvalues.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/fail.h ../../byterun/caml/io.h \
+ ../../byterun/caml/signals.h ../../byterun/caml/sys.h unixsupport.h
+mmap_ba.o: mmap_ba.c ../../byterun/caml/alloc.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/mlvalues.h \
+ ../../byterun/caml/bigarray.h ../../byterun/caml/custom.h \
+ ../../byterun/caml/memory.h ../../byterun/caml/gc.h \
+ ../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \
+ ../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h
+nice.o: nice.c ../../byterun/caml/mlvalues.h ../../byterun/caml/config.h \
+ ../../byterun/caml/m.h ../../byterun/caml/s.h \
+ ../../byterun/caml/misc.h unixsupport.h
+open.o: open.c ../../byterun/caml/mlvalues.h ../../byterun/caml/config.h \
+ ../../byterun/caml/m.h ../../byterun/caml/s.h \
+ ../../byterun/caml/misc.h ../../byterun/caml/alloc.h \
../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h
-nice.o: nice.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- unixsupport.h
-open.o: open.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- ../../byterun/caml/alloc.h ../../byterun/caml/memory.h \
- ../../byterun/caml/signals.h unixsupport.h
opendir.o: opendir.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/memory.h ../../byterun/caml/alloc.h \
../../byterun/caml/signals.h unixsupport.h
-pipe.o: pipe.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- ../../byterun/caml/alloc.h unixsupport.h
-putenv.o: putenv.c ../../byterun/caml/fail.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/misc.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/memory.h unixsupport.h
-read.o: read.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- ../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h
+pipe.o: pipe.c ../../byterun/caml/mlvalues.h ../../byterun/caml/config.h \
+ ../../byterun/caml/m.h ../../byterun/caml/s.h \
+ ../../byterun/caml/misc.h ../../byterun/caml/alloc.h unixsupport.h
+putenv.o: putenv.c ../../byterun/caml/fail.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/mlvalues.h \
+ ../../byterun/caml/memory.h ../../byterun/caml/gc.h \
+ ../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \
+ ../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h \
+ ../../byterun/caml/osdeps.h unixsupport.h
+read.o: read.c ../../byterun/caml/mlvalues.h ../../byterun/caml/config.h \
+ ../../byterun/caml/m.h ../../byterun/caml/s.h \
+ ../../byterun/caml/misc.h ../../byterun/caml/memory.h \
+ ../../byterun/caml/signals.h unixsupport.h
readdir.o: readdir.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/fail.h ../../byterun/caml/alloc.h \
../../byterun/caml/signals.h unixsupport.h
readlink.o: readlink.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/memory.h ../../byterun/caml/alloc.h \
../../byterun/caml/fail.h ../../byterun/caml/signals.h unixsupport.h
rename.o: rename.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h
rewinddir.o: rewinddir.c ../../byterun/caml/fail.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/misc.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/mlvalues.h \
- unixsupport.h
+ ../../byterun/caml/misc.h ../../byterun/caml/config.h \
+ ../../byterun/caml/m.h ../../byterun/caml/s.h \
+ ../../byterun/caml/mlvalues.h unixsupport.h
rmdir.o: rmdir.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- ../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/memory.h ../../byterun/caml/gc.h \
+ ../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \
+ ../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h \
+ ../../byterun/caml/signals.h ../../byterun/caml/osdeps.h unixsupport.h
select.o: select.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/alloc.h ../../byterun/caml/fail.h \
../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h
sendrecv.o: sendrecv.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/alloc.h ../../byterun/caml/fail.h \
../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h \
socketaddr.h
setgid.o: setgid.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- unixsupport.h
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h unixsupport.h
setgroups.o: setgroups.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/alloc.h ../../byterun/caml/fail.h \
../../byterun/caml/memory.h unixsupport.h
-setsid.o: setsid.c ../../byterun/caml/fail.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/misc.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/mlvalues.h \
- unixsupport.h
+setsid.o: setsid.c ../../byterun/caml/fail.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/mlvalues.h unixsupport.h
setuid.o: setuid.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- unixsupport.h
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h unixsupport.h
shutdown.o: shutdown.c ../../byterun/caml/fail.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/misc.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/mlvalues.h \
- unixsupport.h
-signals.o: signals.c ../../byterun/caml/alloc.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/misc.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/mlvalues.h \
+ ../../byterun/caml/misc.h ../../byterun/caml/config.h \
+ ../../byterun/caml/m.h ../../byterun/caml/s.h \
+ ../../byterun/caml/mlvalues.h unixsupport.h
+signals.o: signals.c ../../byterun/caml/alloc.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/mlvalues.h \
../../byterun/caml/fail.h ../../byterun/caml/memory.h \
../../byterun/caml/gc.h ../../byterun/caml/major_gc.h \
../../byterun/caml/freelist.h ../../byterun/caml/minor_gc.h \
../../byterun/caml/address_class.h ../../byterun/caml/signals.h \
unixsupport.h
sleep.o: sleep.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/signals.h unixsupport.h
-socket.o: socket.c ../../byterun/caml/fail.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/misc.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/mlvalues.h \
- unixsupport.h
+socket.o: socket.c ../../byterun/caml/fail.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/mlvalues.h unixsupport.h
socketaddr.o: socketaddr.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/alloc.h ../../byterun/caml/memory.h unixsupport.h \
socketaddr.h
socketpair.o: socketpair.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/alloc.h ../../byterun/caml/fail.h unixsupport.h
sockopt.o: sockopt.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/memory.h ../../byterun/caml/alloc.h \
../../byterun/caml/fail.h unixsupport.h socketaddr.h
-stat.o: stat.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- ../../byterun/caml/memory.h ../../byterun/caml/gc.h \
- ../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \
- ../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h \
- ../../byterun/caml/alloc.h ../../byterun/caml/signals.h \
- ../../byterun/caml/io.h unixsupport.h cst2constr.h nanosecond_stat.h
+stat.o: stat.c ../../byterun/caml/mlvalues.h ../../byterun/caml/config.h \
+ ../../byterun/caml/m.h ../../byterun/caml/s.h \
+ ../../byterun/caml/misc.h ../../byterun/caml/memory.h \
+ ../../byterun/caml/gc.h ../../byterun/caml/major_gc.h \
+ ../../byterun/caml/freelist.h ../../byterun/caml/minor_gc.h \
+ ../../byterun/caml/address_class.h ../../byterun/caml/alloc.h \
+ ../../byterun/caml/signals.h ../../byterun/caml/io.h unixsupport.h \
+ cst2constr.h nanosecond_stat.h
strofaddr.o: strofaddr.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/alloc.h ../../byterun/caml/fail.h unixsupport.h \
socketaddr.h
-symlink.o: symlink.c ../../byterun/caml/fail.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/misc.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/mlvalues.h \
+symlink.o: symlink.c ../../byterun/caml/fail.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/mlvalues.h \
../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h
termios.o: termios.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/alloc.h ../../byterun/caml/fail.h unixsupport.h
-time.o: time.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- ../../byterun/caml/alloc.h unixsupport.h
+time.o: time.c ../../byterun/caml/mlvalues.h ../../byterun/caml/config.h \
+ ../../byterun/caml/m.h ../../byterun/caml/s.h \
+ ../../byterun/caml/misc.h ../../byterun/caml/alloc.h unixsupport.h
times.o: times.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/alloc.h ../../byterun/caml/memory.h unixsupport.h
truncate.o: truncate.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/memory.h ../../byterun/caml/gc.h \
../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \
../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h \
../../byterun/caml/fail.h ../../byterun/caml/signals.h \
../../byterun/caml/io.h unixsupport.h
umask.o: umask.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- unixsupport.h
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h unixsupport.h
unixsupport.o: unixsupport.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/alloc.h ../../byterun/caml/callback.h \
../../byterun/caml/memory.h ../../byterun/caml/fail.h unixsupport.h \
cst2constr.h
unlink.o: unlink.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- ../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h
-utimes.o: utimes.c ../../byterun/caml/fail.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/misc.h \
- ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h
-wait.o: wait.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
- ../../byterun/caml/alloc.h ../../byterun/caml/fail.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/memory.h ../../byterun/caml/gc.h \
../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \
../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h \
- ../../byterun/caml/signals.h unixsupport.h
+ ../../byterun/caml/signals.h ../../byterun/caml/osdeps.h unixsupport.h
+utimes.o: utimes.c ../../byterun/caml/fail.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/mlvalues.h \
+ ../../byterun/caml/memory.h ../../byterun/caml/gc.h \
+ ../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \
+ ../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h \
+ ../../byterun/caml/signals.h ../../byterun/caml/osdeps.h unixsupport.h
+wait.o: wait.c ../../byterun/caml/mlvalues.h ../../byterun/caml/config.h \
+ ../../byterun/caml/m.h ../../byterun/caml/s.h \
+ ../../byterun/caml/misc.h ../../byterun/caml/alloc.h \
+ ../../byterun/caml/fail.h ../../byterun/caml/memory.h \
+ ../../byterun/caml/gc.h ../../byterun/caml/major_gc.h \
+ ../../byterun/caml/freelist.h ../../byterun/caml/minor_gc.h \
+ ../../byterun/caml/address_class.h ../../byterun/caml/signals.h \
+ unixsupport.h
write.o: write.c ../../byterun/caml/mlvalues.h \
- ../../byterun/caml/compatibility.h ../../byterun/caml/config.h \
- ../../byterun/caml/../../config/m.h \
- ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h
unix.cmo : unix.cmi
unix.cmx : unix.cmi
getnameinfo.o getpeername.o getpid.o getppid.o getproto.o getpw.o \
gettimeofday.o getserv.o getsockname.o getuid.o gmtime.o \
initgroups.o isatty.o itimer.o kill.o link.o listen.o lockf.o lseek.o \
- mkdir.o mkfifo.o nice.o open.o opendir.o pipe.o putenv.o read.o \
+ mkdir.o mkfifo.o mmap.o mmap_ba.o \
+ nice.o open.o opendir.o pipe.o putenv.o read.o \
readdir.o readlink.o rename.o rewinddir.o rmdir.o select.o sendrecv.o \
setgid.o setgroups.o setsid.o setuid.o shutdown.o signals.o \
sleep.o socket.o socketaddr.o \
include ../Makefile
+.PHONY: depend
depend:
- $(CC) -MM $(CFLAGS) *.c > .depend
+ifeq "$(TOOLCHAIN)" "msvc"
+ $(error Dependencies cannot be regenerated using the MSVC ports)
+else
+ $(CC) -MM $(CPPFLAGS) *.c > .depend
$(CAMLRUN) ../../tools/ocamldep -slash *.mli *.ml >> .depend
+endif
include .depend
#include <caml/alloc.h>
#include <caml/memory.h>
#include <caml/signals.h>
+#define CAML_INTERNALS
+#include <caml/osdeps.h>
#include "unixsupport.h"
#ifdef HAS_UNISTD
CAMLprim value unix_access(value path, value perms)
{
CAMLparam2(path, perms);
- char * p;
+ char_os * p;
int ret, cv_flags;
caml_unix_check_path(path, "access");
cv_flags = caml_convert_flag_list(perms, access_permission_table);
- p = caml_strdup(String_val(path));
+ p = caml_stat_strdup_to_os(String_val(path));
caml_enter_blocking_section();
- ret = access(p, cv_flags);
+ ret = access_os(p, cv_flags);
caml_leave_blocking_section();
caml_stat_free(p);
if (ret == -1)
/* */
/**************************************************************************/
+#define CAML_INTERNALS
+
#include <caml/mlvalues.h>
#include <caml/memory.h>
#include <caml/signals.h>
+#include <caml/osdeps.h>
#include "unixsupport.h"
CAMLprim value unix_chdir(value path)
{
CAMLparam1(path);
- char * p;
+ char_os * p;
int ret;
caml_unix_check_path(path, "chdir");
- p = caml_strdup(String_val(path));
+ p = caml_stat_strdup_to_os(String_val(path));
caml_enter_blocking_section();
- ret = chdir(p);
+ ret = chdir_os(p);
caml_leave_blocking_section();
caml_stat_free(p);
if (ret == -1) uerror("chdir", path);
/* */
/**************************************************************************/
+#define CAML_INTERNALS
+
#include <sys/types.h>
#include <sys/stat.h>
#include <caml/mlvalues.h>
#include <caml/memory.h>
#include <caml/signals.h>
+#include <caml/osdeps.h>
#include "unixsupport.h"
CAMLprim value unix_chmod(value path, value perm)
{
CAMLparam2(path, perm);
- char * p;
+ char_os * p;
int ret;
caml_unix_check_path(path, "chmod");
- p = caml_strdup(String_val(path));
+ p = caml_stat_strdup_to_os(String_val(path));
caml_enter_blocking_section();
- ret = chmod(p, Int_val(perm));
+ ret = chmod_os(p, Int_val(perm));
caml_leave_blocking_section();
caml_stat_free(p);
if (ret == -1) uerror("chmod", path);
char * p;
int ret;
caml_unix_check_path(path, "chown");
- p = caml_strdup(String_val(path));
+ p = caml_stat_strdup(String_val(path));
caml_enter_blocking_section();
ret = chown(p, Int_val(uid), Int_val(gid));
caml_leave_blocking_section();
char * p;
int ret;
caml_unix_check_path(path, "chroot");
- p = caml_strdup(String_val(path));
+ p = caml_stat_strdup(String_val(path));
caml_enter_blocking_section();
ret = chroot(p);
caml_leave_blocking_section();
/* */
/**************************************************************************/
+#define CAML_INTERNALS
+
#include <errno.h>
#include <caml/mlvalues.h>
#include <caml/memory.h>
+#include <caml/osdeps.h>
#include "unixsupport.h"
-char ** cstringvect(value arg, char * cmdname)
+char_os ** cstringvect(value arg, char * cmdname)
{
- char ** res;
+ char_os ** res;
mlsize_t size, i;
size = Wosize_val(arg);
for (i = 0; i < size; i++)
if (! caml_string_is_c_safe(Field(arg, i)))
unix_error(EINVAL, cmdname, Field(arg, i));
- res = (char **) caml_stat_alloc((size + 1) * sizeof(char *));
- for (i = 0; i < size; i++) res[i] = String_val(Field(arg, i));
+ res = (char_os **) caml_stat_alloc((size + 1) * sizeof(char_os *));
+ for (i = 0; i < size; i++) res[i] = caml_stat_strdup_to_os(String_val(Field(arg, i)));
res[size] = NULL;
return res;
}
+
+void cstringvect_free(char_os ** v)
+{
+ int i = 0;
+ while (v[i]) caml_stat_free(v[i++]);
+ caml_stat_free((char *)v);
+}
/* */
/**************************************************************************/
+#include <caml/config.h>
+
+#ifdef HAS_UNISTD
+#include <unistd.h>
+#endif
+#include <sys/types.h>
+#ifdef HAS_GETAUXVAL
+#include <sys/auxv.h>
+#endif
+
#include <caml/mlvalues.h>
#include <caml/alloc.h>
-#ifndef _WIN32
extern char ** environ;
-#endif
-CAMLprim value unix_environment(value unit)
+CAMLprim value unix_environment_unsafe(value unit)
{
if (environ != NULL) {
return caml_copy_string_array((const char**)environ);
return Atom(0);
}
}
+
+static char **secure_environ(void)
+{
+#ifdef HAS_GETAUXVAL
+ if (!getauxval(AT_SECURE))
+ return environ;
+ else
+ return NULL;
+#elif defined(HAS_ISSETUGID)
+ if (!issetugid ())
+ return environ;
+ else
+ return NULL;
+#else
+ if (geteuid () == getuid () && getegid () == getgid ())
+ return environ;
+ else
+ return NULL;
+#endif
+}
+
+CAMLprim value unix_environment(value unit)
+{
+ char **e = secure_environ();
+ if (e != NULL) {
+ return caml_copy_string_array((const char**)e);
+ } else {
+ return Atom(0);
+ }
+}
/* */
/**************************************************************************/
+#define CAML_INTERNALS
+
#include <caml/mlvalues.h>
#include <caml/memory.h>
+#include <caml/osdeps.h>
#include "unixsupport.h"
CAMLprim value unix_execv(value path, value args)
{
- char ** argv;
+ char_os * wpath;
+ char_os ** argv;
caml_unix_check_path(path, "execv");
argv = cstringvect(args, "execv");
- (void) execv(String_val(path), argv);
- caml_stat_free((char *) argv);
+ wpath = caml_stat_strdup_to_os(String_val(path));
+ (void) execv_os(wpath, EXECV_CAST argv);
+ caml_stat_free(wpath);
+ cstringvect_free(argv);
uerror("execv", path);
return Val_unit; /* never reached, but suppress warnings */
/* from smart compilers */
/* */
/**************************************************************************/
+#define CAML_INTERNALS
+
#include <caml/mlvalues.h>
#include <caml/memory.h>
+#include <caml/osdeps.h>
#include "unixsupport.h"
CAMLprim value unix_execve(value path, value args, value env)
{
- char ** argv;
- char ** envp;
+ char_os ** argv;
+ char_os ** envp;
+ char_os * wpath;
caml_unix_check_path(path, "execve");
argv = cstringvect(args, "execve");
envp = cstringvect(env, "execve");
- (void) execve(String_val(path), argv, envp);
- caml_stat_free((char *) argv);
- caml_stat_free((char *) envp);
+ wpath = caml_stat_strdup_to_os(String_val(path));
+ (void) execve_os(wpath, EXECV_CAST argv, EXECV_CAST envp);
+ caml_stat_free(wpath);
+ cstringvect_free(argv);
+ cstringvect_free(envp);
uerror("execve", path);
return Val_unit; /* never reached, but suppress warnings */
/* from smart compilers */
/* */
/**************************************************************************/
+#define _GNU_SOURCE /* helps to find execvpe() */
#include <caml/mlvalues.h>
#include <caml/memory.h>
#define CAML_INTERNALS
#include <caml/osdeps.h>
#include "unixsupport.h"
-
-#ifndef _WIN32
-extern char ** environ;
-#endif
+#include "errno.h"
CAMLprim value unix_execvp(value path, value args)
{
- char ** argv;
+ char_os ** argv;
+ char_os * wpath;
caml_unix_check_path(path, "execvp");
argv = cstringvect(args, "execvp");
- (void) execvp(String_val(path), argv);
- caml_stat_free((char *) argv);
+ wpath = caml_stat_strdup_to_os(String_val(path));
+ (void) execvp_os((const char_os *)wpath, EXECV_CAST argv);
+ caml_stat_free(wpath);
+ cstringvect_free(argv);
uerror("execvp", path);
return Val_unit; /* never reached, but suppress warnings */
/* from smart compilers */
}
+#ifdef HAS_EXECVPE
+
CAMLprim value unix_execvpe(value path, value args, value env)
{
- char * exefile;
- char ** argv;
- char ** envp;
+ char_os ** argv;
+ char_os ** envp;
+ char_os * wpath;
caml_unix_check_path(path, "execvpe");
- exefile = caml_search_exe_in_path(String_val(path));
argv = cstringvect(args, "execvpe");
envp = cstringvect(env, "execvpe");
- (void) execve(exefile, argv, envp);
- caml_stat_free(exefile);
- caml_stat_free((char *) argv);
- caml_stat_free((char *) envp);
+ wpath = caml_stat_strdup_to_os(String_val(path));
+ (void) execvpe_os((const char_os *)wpath, EXECV_CAST argv, EXECV_CAST envp);
+ caml_stat_free(wpath);
+ cstringvect_free(argv);
+ cstringvect_free(envp);
uerror("execvpe", path);
return Val_unit; /* never reached, but suppress warnings */
/* from smart compilers */
}
+
+#else
+
+CAMLprim value unix_execvpe(value path, value args, value env)
+{
+ unix_error(ENOSYS, "execvpe", path);
+ return Val_unit;
+}
+
+#endif
+
if (caml_string_length(vnode) == 0) {
node = NULL;
} else {
- node = caml_strdup(String_val(vnode));
+ node = caml_stat_strdup(String_val(vnode));
}
/* Extract "service" parameter */
if (caml_string_length(vserv) == 0) {
serv = NULL;
} else {
- serv = caml_strdup(String_val(vserv));
+ serv = caml_stat_strdup(String_val(vserv));
}
/* Parse options, set hints */
memset(&hints, 0, sizeof(hints));
/* */
/**************************************************************************/
+#define CAML_INTERNALS
+
#include <caml/mlvalues.h>
#include <caml/alloc.h>
#include <caml/fail.h>
+#include <caml/osdeps.h>
#include "unixsupport.h"
#if !defined (_WIN32) && !macintosh
CAMLprim value unix_getcwd(value unit)
{
- char buff[PATH_MAX];
- if (getcwd(buff, sizeof(buff)) == 0) uerror("getcwd", Nothing);
- return caml_copy_string(buff);
-}
-
-#else
-#ifdef HAS_GETWD
-
-CAMLprim value unix_getcwd(value unit)
-{
- char buff[PATH_MAX];
- if (getwd(buff) == 0) uerror("getcwd", copy_string(buff));
- return copy_string(buff);
+ char_os buff[PATH_MAX];
+ char_os * ret;
+ ret = getcwd_os(buff, sizeof(buff)/sizeof(*buff));
+ if (ret == 0) uerror("getcwd", Nothing);
+ return caml_copy_string_of_os(buff);
}
#else
{ caml_invalid_argument("getcwd not implemented"); }
#endif
-#endif
if (! caml_string_is_c_safe(name)) caml_raise_not_found();
-#if HAS_GETHOSTBYNAME_R || GETHOSTBYNAME_IS_REENTRANT
- hostname = caml_strdup(String_val(name));
-#else
- hostname = String_val(name);
-#endif
+ hostname = caml_stat_strdup(String_val(name));
#if HAS_GETHOSTBYNAME_R == 5
{
#endif
#endif
-#if HAS_GETHOSTBYNAME_R || GETHOSTBYNAME_IS_REENTRANT
caml_stat_free(hostname);
-#endif
if (hp == (struct hostent *) NULL) caml_raise_not_found();
return alloc_host_entry(hp);
int ret;
caml_unix_check_path(path1, "link");
caml_unix_check_path(path2, "link");
- p1 = caml_strdup(String_val(path1));
- p2 = caml_strdup(String_val(path2));
+ p1 = caml_stat_strdup(String_val(path1));
+ p2 = caml_stat_strdup(String_val(path2));
caml_enter_blocking_section();
ret = link(p1, p2);
caml_leave_blocking_section();
char * p;
int ret;
caml_unix_check_path(path, "mkdir");
- p = caml_strdup(String_val(path));
+ p = caml_stat_strdup(String_val(path));
caml_enter_blocking_section();
ret = mkdir(p, Int_val(perm));
caml_leave_blocking_section();
char * p;
int ret;
caml_unix_check_path(path, "mkfifo");
- p = caml_strdup(String_val(path));
+ p = caml_stat_strdup(String_val(path));
caml_enter_blocking_section();
ret = mkfifo(p, Int_val(mode));
caml_leave_blocking_section();
char * p;
int ret;
caml_unix_check_path(path, "mkfifo");
- p = caml_strdup(String_val(path));
+ p = caml_stat_strdup(String_val(path));
caml_enter_blocking_section();
ret = mknod(p, (Int_val(mode) & 07777) | S_IFIFO, 0);
caml_leave_blocking_section();
--- /dev/null
+/**************************************************************************/
+/* */
+/* OCaml */
+/* */
+/* Manuel Serrano and Xavier Leroy, INRIA Rocquencourt */
+/* */
+/* Copyright 2000 Institut National de Recherche en Informatique et */
+/* en Automatique. */
+/* */
+/* All rights reserved. This file is distributed under the terms of */
+/* the GNU Lesser General Public License version 2.1, with the */
+/* special exception on linking described in the file LICENSE. */
+/* */
+/**************************************************************************/
+
+#define CAML_INTERNALS
+
+/* Needed (under Linux at least) to get pwrite's prototype in unistd.h.
+ Must be defined before the first system .h is included. */
+#define _XOPEN_SOURCE 600
+
+#include <stddef.h>
+#include "caml/bigarray.h"
+#include "caml/fail.h"
+#include "caml/io.h"
+#include "caml/mlvalues.h"
+#include "caml/signals.h"
+#include "caml/sys.h"
+#include "unixsupport.h"
+
+#include <errno.h>
+#ifdef HAS_UNISTD
+#include <unistd.h>
+#endif
+#ifdef HAS_MMAP
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#endif
+
+/* Temporary compatibility stuff so that this file can also be compiled
+ from otherlibs/bigarray/ and included in the bigarray library. */
+
+#ifdef IN_OCAML_BIGARRAY
+#define MAP_FILE_FUNCTION caml_ba_map_file
+#define MAP_FILE_FUNCTION_BYTECODE caml_ba_map_file_bytecode
+#define UNMAP_FILE_FUNCTION caml_ba_unmap_file
+#define ALLOC_FUNCTION caml_ba_mapped_alloc
+#define CAML_MAP_FILE "Bigarray.map_file"
+#define MAP_FILE_ERROR() caml_sys_error(NO_ARG)
+#else
+#define MAP_FILE_FUNCTION caml_unix_map_file
+#define MAP_FILE_FUNCTION_BYTECODE caml_unix_map_file_bytecode
+#define UNMAP_FILE_FUNCTION caml_unix_unmap_file
+#define ALLOC_FUNCTION caml_unix_mapped_alloc
+#define MAP_FILE_FUNCTION caml_unix_map_file
+#define CAML_MAP_FILE "Unix.map_file"
+#define MAP_FILE_ERROR() uerror("map_file", Nothing)
+#endif
+
+/* Defined in [mmap_ba.c] */
+CAMLextern value
+ALLOC_FUNCTION(int flags, int num_dims, void * data, intnat * dim);
+
+#if defined(HAS_MMAP)
+
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *) -1)
+#endif
+
+/* [caml_grow_file] function contributed by Gerd Stolpmann (PR#5543). */
+
+static int caml_grow_file(int fd, file_offset size)
+{
+ char c;
+ int p;
+
+ /* First use pwrite for growing - it is a conservative method, as it
+ can never happen that we shrink by accident
+ */
+#ifdef HAS_PWRITE
+ c = 0;
+ p = pwrite(fd, &c, 1, size - 1);
+#else
+
+ /* Emulate pwrite with lseek. This should only be necessary on ancient
+ systems nowadays
+ */
+ file_offset currpos;
+ currpos = lseek(fd, 0, SEEK_CUR);
+ if (currpos != -1) {
+ p = lseek(fd, size - 1, SEEK_SET);
+ if (p != -1) {
+ c = 0;
+ p = write(fd, &c, 1);
+ if (p != -1)
+ p = lseek(fd, currpos, SEEK_SET);
+ }
+ }
+ else p=-1;
+#endif
+#ifdef HAS_TRUNCATE
+ if (p == -1 && errno == ESPIPE) {
+ /* Plan B. Check if at least ftruncate is possible. There are
+ some non-seekable descriptor types that do not support pwrite
+ but ftruncate, like shared memory. We never get into this case
+ for real files, so there is no danger of truncating persistent
+ data by accident
+ */
+ p = ftruncate(fd, size);
+ }
+#endif
+ return p;
+}
+
+
+CAMLprim value MAP_FILE_FUNCTION(value vfd, value vkind, value vlayout,
+ value vshared, value vdim, value vstart)
+{
+ int fd, flags, major_dim, shared;
+ intnat num_dims, i;
+ intnat dim[CAML_BA_MAX_NUM_DIMS];
+ file_offset startpos, file_size, data_size;
+ struct stat st;
+ uintnat array_size, page, delta;
+ void * addr;
+
+ fd = Int_val(vfd);
+ flags = Caml_ba_kind_val(vkind) | Caml_ba_layout_val(vlayout);
+ startpos = File_offset_val(vstart);
+ num_dims = Wosize_val(vdim);
+ major_dim = flags & CAML_BA_FORTRAN_LAYOUT ? num_dims - 1 : 0;
+ /* Extract dimensions from OCaml array */
+ num_dims = Wosize_val(vdim);
+ if (num_dims < 1 || num_dims > CAML_BA_MAX_NUM_DIMS)
+ caml_invalid_argument(CAML_MAP_FILE ": bad number of dimensions");
+ for (i = 0; i < num_dims; i++) {
+ dim[i] = Long_val(Field(vdim, i));
+ if (dim[i] == -1 && i == major_dim) continue;
+ if (dim[i] < 0)
+ caml_invalid_argument(CAML_MAP_FILE ": negative dimension");
+ }
+ /* Determine file size. We avoid lseek here because it is fragile,
+ and because some mappable file types do not support it
+ */
+ caml_enter_blocking_section();
+ if (fstat(fd, &st) == -1) {
+ caml_leave_blocking_section();
+ MAP_FILE_ERROR();
+ }
+ file_size = st.st_size;
+ /* Determine array size in bytes (or size of array without the major
+ dimension if that dimension wasn't specified) */
+ array_size = caml_ba_element_size[flags & CAML_BA_KIND_MASK];
+ for (i = 0; i < num_dims; i++)
+ if (dim[i] != -1) array_size *= dim[i];
+ /* Check if the major dimension is unknown */
+ if (dim[major_dim] == -1) {
+ /* Determine major dimension from file size */
+ if (file_size < startpos) {
+ caml_leave_blocking_section();
+ caml_failwith(CAML_MAP_FILE ": file position exceeds file size");
+ }
+ data_size = file_size - startpos;
+ dim[major_dim] = (uintnat) (data_size / array_size);
+ array_size = dim[major_dim] * array_size;
+ if (array_size != data_size) {
+ caml_leave_blocking_section();
+ caml_failwith(CAML_MAP_FILE ": file size doesn't match array dimensions");
+ }
+ } else {
+ /* Check that file is large enough, and grow it otherwise */
+ if (file_size < startpos + array_size) {
+ if (caml_grow_file(fd, startpos + array_size) == -1) { /* PR#5543 */
+ caml_leave_blocking_section();
+ MAP_FILE_ERROR();
+ }
+ }
+ }
+ /* Determine offset so that the mapping starts at the given file pos */
+ page = sysconf(_SC_PAGESIZE);
+ delta = (uintnat) startpos % page;
+ /* Do the mmap */
+ shared = Bool_val(vshared) ? MAP_SHARED : MAP_PRIVATE;
+ if (array_size > 0)
+ addr = mmap(NULL, array_size + delta, PROT_READ | PROT_WRITE,
+ shared, fd, startpos - delta);
+ else
+ addr = NULL; /* PR#5463 - mmap fails on empty region */
+ caml_leave_blocking_section();
+ if (addr == (void *) MAP_FAILED) MAP_FILE_ERROR();
+ addr = (void *) ((uintnat) addr + delta);
+ /* Build and return the OCaml bigarray */
+ return ALLOC_FUNCTION(flags, num_dims, addr, dim);
+}
+
+#else
+
+CAMLprim value MAP_FILE_FUNCTION(value vfd, value vkind, value vlayout,
+ value vshared, value vdim, value vpos)
+{
+ caml_invalid_argument("Unix.map_file: not supported");
+ return Val_unit;
+}
+
+#endif
+
+CAMLprim value MAP_FILE_FUNCTION_BYTECODE(value * argv, int argn)
+{
+ return MAP_FILE_FUNCTION(argv[0], argv[1], argv[2],
+ argv[3], argv[4], argv[5]);
+}
+
+void UNMAP_FILE_FUNCTION(void * addr, uintnat len)
+{
+#if defined(HAS_MMAP)
+ uintnat page = sysconf(_SC_PAGESIZE);
+ uintnat delta = (uintnat) addr % page;
+ if (len == 0) return; /* PR#5463 */
+ addr = (void *)((uintnat)addr - delta);
+ len = len + delta;
+#if defined(_POSIX_SYNCHRONIZED_IO)
+ msync(addr, len, MS_ASYNC); /* PR#3571 */
+#endif
+ munmap(addr, len);
+#endif
+}
--- /dev/null
+/**************************************************************************/
+/* */
+/* OCaml */
+/* */
+/* Manuel Serrano and Xavier Leroy, INRIA Rocquencourt */
+/* */
+/* Copyright 2000 Institut National de Recherche en Informatique et */
+/* en Automatique. */
+/* */
+/* All rights reserved. This file is distributed under the terms of */
+/* the GNU Lesser General Public License version 2.1, with the */
+/* special exception on linking described in the file LICENSE. */
+/* */
+/**************************************************************************/
+
+#define CAML_INTERNALS
+
+#include "caml/alloc.h"
+#include "caml/bigarray.h"
+#include "caml/custom.h"
+#include "caml/memory.h"
+#include "caml/misc.h"
+
+/* Allocation of bigarrays for memory-mapped files.
+ This is the OS-independent part of [mmap.c]. */
+
+/* Temporary compatibility stuff so that this file can also be compiled
+ from otherlibs/bigarray/ and included in the bigarray library. */
+
+#ifdef IN_OCAML_BIGARRAY
+#define UNMAP_FILE_FUNCTION caml_ba_unmap_file
+#define ALLOC_FUNCTION caml_ba_mapped_alloc
+#else
+#define UNMAP_FILE_FUNCTION caml_unix_unmap_file
+#define ALLOC_FUNCTION caml_unix_mapped_alloc
+#endif
+
+CAMLextern void UNMAP_FILE_FUNCTION(void * addr, uintnat len);
+
+static void caml_ba_mapped_finalize(value v)
+{
+ struct caml_ba_array * b = Caml_ba_array_val(v);
+ CAMLassert(b->flags & CAML_BA_MANAGED_MASK == CAML_BA_MAPPED_FILE);
+ if (b->proxy == NULL) {
+ UNMAP_FILE_FUNCTION(b->data, caml_ba_byte_size(b));
+ } else {
+ if (-- b->proxy->refcount == 0) {
+ UNMAP_FILE_FUNCTION(b->proxy->data, b->proxy->size);
+ free(b->proxy);
+ }
+ }
+}
+
+/* Operation table for bigarrays representing memory-mapped files.
+ Only the finalization method differs from regular bigarrays. */
+
+static struct custom_operations caml_ba_mapped_ops = {
+ "_bigarray",
+ caml_ba_mapped_finalize,
+ caml_ba_compare,
+ caml_ba_hash,
+ caml_ba_serialize,
+ caml_ba_deserialize,
+ custom_compare_ext_default
+};
+
+/* [caml_ba_mapped_alloc] allocates a new bigarray object in the heap
+ corresponding to a memory-mapped file. */
+
+CAMLexport value
+ALLOC_FUNCTION(int flags, int num_dims, void * data, intnat * dim)
+{
+ uintnat asize;
+ int i;
+ value res;
+ struct caml_ba_array * b;
+ intnat dimcopy[CAML_BA_MAX_NUM_DIMS];
+
+ CAMLassert(num_dims >= 0 && num_dims <= CAML_BA_MAX_NUM_DIMS);
+ CAMLassert((flags & CAML_BA_KIND_MASK) <= CAML_BA_CHAR);
+ for (i = 0; i < num_dims; i++) dimcopy[i] = dim[i];
+ asize = SIZEOF_BA_ARRAY + num_dims * sizeof(intnat);
+ res = caml_alloc_custom(&caml_ba_mapped_ops, asize, 0, 1);
+ b = Caml_ba_array_val(res);
+ b->data = data;
+ b->num_dims = num_dims;
+ b->flags = flags | CAML_BA_MAPPED_FILE;
+ b->proxy = NULL;
+ for (i = 0; i < num_dims; i++) b->dim[i] = dimcopy[i];
+ return res;
+}
#if defined(O_CLOEXEC)
if (cloexec) cv_flags |= O_CLOEXEC;
#endif
- p = caml_strdup(String_val(path));
+ p = caml_stat_strdup(String_val(path));
/* open on a named FIFO can block (PR#1533) */
caml_enter_blocking_section();
fd = open(p, cv_flags, Int_val(perm));
char * p;
caml_unix_check_path(path, "opendir");
- p = caml_strdup(String_val(path));
+ p = caml_stat_strdup(String_val(path));
caml_enter_blocking_section();
d = opendir(p);
caml_leave_blocking_section();
/* */
/**************************************************************************/
+#define CAML_INTERNALS
+
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <caml/fail.h>
#include <caml/memory.h>
#include <caml/mlvalues.h>
+#include <caml/osdeps.h>
#include "unixsupport.h"
CAMLprim value unix_putenv(value name, value val)
{
- mlsize_t namelen = caml_string_length(name);
- mlsize_t vallen = caml_string_length(val);
char * s;
+ char_os * p;
+ int ret;
if (! (caml_string_is_c_safe(name) && caml_string_is_c_safe(val)))
unix_error(EINVAL, "putenv", name);
- s = (char *) caml_stat_alloc(namelen + 1 + vallen + 1);
- memmove (s, String_val(name), namelen);
- s[namelen] = '=';
- memmove (s + namelen + 1, String_val(val), vallen);
- s[namelen + 1 + vallen] = 0;
- if (putenv(s) == -1) {
- caml_stat_free(s);
+ s = caml_stat_strconcat(3, name, "=", val);
+ p = caml_stat_strdup_to_os(s);
+ caml_stat_free(s);
+ ret = putenv_os(p);
+ if (ret == -1) {
+ caml_stat_free(p);
uerror("putenv", name);
}
return Val_unit;
int len;
char * p;
caml_unix_check_path(path, "readlink");
- p = caml_strdup(String_val(path));
+ p = caml_stat_strdup(String_val(path));
caml_enter_blocking_section();
len = readlink(p, buffer, sizeof(buffer) - 1);
caml_leave_blocking_section();
int ret;
caml_unix_check_path(path1, "rename");
caml_unix_check_path(path2, "rename");
- p1 = caml_strdup(String_val(path1));
- p2 = caml_strdup(String_val(path2));
+ p1 = caml_stat_strdup(String_val(path1));
+ p2 = caml_stat_strdup(String_val(path2));
caml_enter_blocking_section();
ret = rename(p1, p2);
caml_leave_blocking_section();
/* */
/**************************************************************************/
+#define CAML_INTERNALS
+
#include <caml/mlvalues.h>
#include <caml/memory.h>
#include <caml/signals.h>
+#include <caml/osdeps.h>
#include "unixsupport.h"
CAMLprim value unix_rmdir(value path)
{
CAMLparam1(path);
- char * p;
+ char_os * p;
int ret;
caml_unix_check_path(path, "rmdir");
- p = caml_strdup(String_val(path));
+ p = caml_stat_strdup_to_os(String_val(path));
caml_enter_blocking_section();
- ret = rmdir(p);
+ ret = rmdir_os(p);
caml_leave_blocking_section();
caml_stat_free(p);
if (ret == -1) uerror("rmdir", path);
/* Use a string rather than an abstract block so that it can be
marshaled safely. Remember that a is in network byte order,
hence is marshaled in an endian-independent manner. */
- res = caml_alloc_string(4);
- memcpy(String_val(res), a, 4);
+ res = caml_alloc_initialized_string(4, (char *)a);
return res;
}
CAMLexport value alloc_inet6_addr(struct in6_addr * a)
{
value res;
- res = caml_alloc_string(16);
- memcpy(String_val(res), a, 16);
+ res = caml_alloc_initialized_string(16, (char *)a);
return res;
}
mlsize_t path_length =
strnlen(adr->s_unix.sun_path,
adr_len - offsetof(struct sockaddr_un, sun_path));
- n = caml_alloc_string(path_length);
- memmove(String_val(n), adr->s_unix.sun_path, path_length);
+ n = caml_alloc_initialized_string(path_length, (char *)adr->s_unix.sun_path);
Begin_root (n);
res = caml_alloc_small(1, 0);
Field(res,0) = n;
struct stat buf;
char * p;
caml_unix_check_path(path, "stat");
- p = caml_strdup(String_val(path));
+ p = caml_stat_strdup(String_val(path));
caml_enter_blocking_section();
ret = stat(p, &buf);
caml_leave_blocking_section();
struct stat buf;
char * p;
caml_unix_check_path(path, "lstat");
- p = caml_strdup(String_val(path));
+ p = caml_stat_strdup(String_val(path));
caml_enter_blocking_section();
#ifdef HAS_SYMLINK
ret = lstat(p, &buf);
struct stat buf;
char * p;
caml_unix_check_path(path, "stat");
- p = caml_strdup(String_val(path));
+ p = caml_stat_strdup(String_val(path));
caml_enter_blocking_section();
ret = stat(p, &buf);
caml_leave_blocking_section();
struct stat buf;
char * p;
caml_unix_check_path(path, "lstat");
- p = caml_strdup(String_val(path));
+ p = caml_stat_strdup(String_val(path));
caml_enter_blocking_section();
#ifdef HAS_SYMLINK
ret = lstat(p, &buf);
int ret;
caml_unix_check_path(path1, "symlink");
caml_unix_check_path(path2, "symlink");
- p1 = caml_strdup(String_val(path1));
- p2 = caml_strdup(String_val(path2));
+ p1 = caml_stat_strdup(String_val(path1));
+ p2 = caml_stat_strdup(String_val(path2));
caml_enter_blocking_section();
ret = symlink(p1, p2);
caml_leave_blocking_section();
char * p;
int ret;
caml_unix_check_path(path, "truncate");
- p = caml_strdup(String_val(path));
+ p = caml_stat_strdup(String_val(path));
caml_enter_blocking_section();
ret = truncate(p, Long_val(len));
caml_leave_blocking_section();
int ret;
file_offset len = File_offset_val(vlen);
caml_unix_check_path(path, "truncate");
- p = caml_strdup(String_val(path));
+ p = caml_stat_strdup(String_val(path));
caml_enter_blocking_section();
ret = truncate(p, len);
caml_leave_blocking_section();
exit 2
external environment : unit -> string array = "unix_environment"
+external unsafe_environment : unit -> string array = "unix_environment_unsafe"
external getenv: string -> string = "caml_sys_getenv"
-(* external unsafe_getenv: string -> string = "caml_sys_unsafe_getenv" *)
+external unsafe_getenv: string -> string = "caml_sys_unsafe_getenv"
external putenv: string -> string -> unit = "unix_putenv"
type process_status =
external execv : string -> string array -> 'a = "unix_execv"
external execve : string -> string array -> string array -> 'a = "unix_execve"
external execvp : string -> string array -> 'a = "unix_execvp"
-external execvpe : string -> string array -> string array -> 'a = "unix_execvpe"
+external execvpe_c :
+ string -> string array -> string array -> 'a = "unix_execvpe"
+
+let execvpe_ml name args env =
+ (* Try to execute the given file *)
+ let exec file =
+ try
+ execve file args env
+ with Unix_error(ENOEXEC, _, _) ->
+ (* Assume this is a script and try to execute through the shell *)
+ let argc = Array.length args in
+ (* Drop the original args.(0) if it is there *)
+ let new_args = Array.append
+ [| "/bin/sh"; file |]
+ (if argc = 0 then args else Array.sub args 1 (argc - 1)) in
+ execve new_args.(0) new_args env in
+ (* Try each path element in turn *)
+ let rec scan_dir eacces = function
+ | [] ->
+ (* No matching file was found (if [eacces = false]) or
+ a matching file was found but we got a "permission denied"
+ error while trying to execute it (if [eacces = true]).
+ Raise the error appropriate to each case. *)
+ raise (Unix_error((if eacces then EACCES else ENOENT),
+ "execvpe", name))
+ | dir :: rem ->
+ let dir = (* an empty path element means the current directory *)
+ if dir = "" then Filename.current_dir_name else dir in
+ try
+ exec (Filename.concat dir name)
+ with Unix_error(err, _, _) as exn ->
+ match err with
+ (* The following errors are treated as nonfatal, meaning that
+ we will ignore them and continue searching in the path.
+ Among those errors, EACCES is recorded specially so as
+ to produce the correct exception in the end.
+ To determine which errors are nonfatal, we looked at the
+ execvpe() sources in Glibc and in OpenBSD. *)
+ | EACCES ->
+ scan_dir true rem
+ | EISDIR|ELOOP|ENAMETOOLONG|ENODEV|ENOENT|ENOTDIR|ETIMEDOUT ->
+ scan_dir eacces rem
+ (* Other errors, e.g. E2BIG, are fatal and abort the search. *)
+ | _ ->
+ raise exn in
+ if String.contains name '/' then
+ (* If the command name contains "/" characters, don't search in path *)
+ exec name
+ else
+ (* Split path into elements and search in these elements *)
+ (try unsafe_getenv "PATH" with Not_found -> "/bin:/usr/bin")
+ |> String.split_on_char ':'
+ |> scan_dir false
+ (* [unsafe_getenv] and not [getenv] to be consistent with [execvp],
+ which looks up the PATH environment variable whether SUID or not. *)
+
+let execvpe name args env =
+ try
+ execvpe_c name args env
+ with Unix_error(ENOSYS, _, _) ->
+ execvpe_ml name args env
+
external fork : unit -> int = "unix_fork"
external wait : unit -> int * process_status = "unix_wait"
external waitpid : wait_flag list -> int -> int * process_status
external fstat : file_descr -> stats = "unix_fstat_64"
end
+external map_internal:
+ file_descr -> ('a, 'b) CamlinternalBigarray.kind
+ -> 'c CamlinternalBigarray.layout
+ -> bool -> int array -> int64
+ -> ('a, 'b, 'c) CamlinternalBigarray.genarray
+ = "caml_unix_map_file_bytecode" "caml_unix_map_file"
+
+let map_file fd ?(pos=0L) kind layout shared dims =
+ map_internal fd kind layout shared dims pos
+
type access_permission =
R_OK
| W_OK
exception whenever the underlying system call signals an error. *)
-(** {6 Error report} *)
+(** {1 Error report} *)
type error =
describing the error and exits with code 2. *)
-(** {6 Access to the process environment} *)
+(** {1 Access to the process environment} *)
val environment : unit -> string array
(** Return the process environment, as an array of strings
- with the format ``variable=value''. *)
+ with the format ``variable=value''. The returned array
+ is empty if the process has special privileges. *)
+
+val unsafe_environment : unit -> string array
+(** Return the process environment, as an array of strings with the
+ format ``variable=value''. Unlike {!environment}, this function
+ returns a populated array even if the process has special
+ privileges. See the documentation for {!unsafe_getenv} for more
+ details.
+
+ @since 4.06.0 *)
val getenv : string -> string
(** Return the value associated to a variable in the process
(This function is identical to {!Sys.getenv}. *)
-(*
val unsafe_getenv : string -> string
(** Return the value associated to a variable in the process
environment.
for executables, the locations for temporary files or logs, and the
like.
- @raise Not_found if the variable is unbound. *)
-*)
+ @raise Not_found if the variable is unbound.
+ @since 4.06.0 *)
val putenv : string -> string -> unit
(** [Unix.putenv name value] sets the value associated to a
and [value] its new associated value. *)
-(** {6 Process handling} *)
+(** {1 Process handling} *)
type process_status =
On Windows: not implemented. *)
-(** {6 Basic file input/output} *)
+(** {1 Basic file input/output} *)
type file_descr
a byte sequence.
@since 4.02.0 *)
-(** {6 Interfacing with the standard input/output library} *)
+(** {1 Interfacing with the standard input/output library} *)
(** Return the descriptor corresponding to an output channel. *)
-(** {6 Seeking and truncating} *)
+(** {1 Seeking and truncating} *)
type seek_command =
On Windows: not implemented. *)
-(** {6 File status} *)
+(** {1 File status} *)
type file_kind =
(** Return [true] if the given file descriptor refers to a terminal or
console window, [false] otherwise. *)
-(** {6 File operations on large files} *)
+(** {1 File operations on large files} *)
module LargeFile :
sig
regular integers (type [int]), thus allowing operating on files
whose sizes are greater than [max_int]. *)
-(** {6 Operations on file names} *)
+(** {6 Mapping files into memory} *)
+
+val map_file :
+ file_descr -> ?pos:int64 -> ('a, 'b) CamlinternalBigarray.kind ->
+ 'c CamlinternalBigarray.layout -> bool -> int array ->
+ ('a, 'b, 'c) CamlinternalBigarray.genarray
+(** Memory mapping of a file as a big array.
+ [map_file fd kind layout shared dims]
+ returns a big array of kind [kind], layout [layout],
+ and dimensions as specified in [dims]. The data contained in
+ this big array are the contents of the file referred to by
+ the file descriptor [fd] (as opened previously with
+ [Unix.openfile], for example). The optional [pos] parameter
+ is the byte offset in the file of the data being mapped;
+ it defaults to 0 (map from the beginning of the file).
+
+ If [shared] is [true], all modifications performed on the array
+ are reflected in the file. This requires that [fd] be opened
+ with write permissions. If [shared] is [false], modifications
+ performed on the array are done in memory only, using
+ copy-on-write of the modified pages; the underlying file is not
+ affected.
+
+ [Genarray.map_file] is much more efficient than reading
+ the whole file in a big array, modifying that big array,
+ and writing it afterwards.
+
+ To adjust automatically the dimensions of the big array to
+ the actual size of the file, the major dimension (that is,
+ the first dimension for an array with C layout, and the last
+ dimension for an array with Fortran layout) can be given as
+ [-1]. [Genarray.map_file] then determines the major dimension
+ from the size of the file. The file must contain an integral
+ number of sub-arrays as determined by the non-major dimensions,
+ otherwise [Failure] is raised.
+
+ If all dimensions of the big array are given, the file size is
+ matched against the size of the big array. If the file is larger
+ than the big array, only the initial portion of the file is
+ mapped to the big array. If the file is smaller than the big
+ array, the file is automatically grown to the size of the big array.
+ This requires write permissions on [fd].
+
+ Array accesses are bounds-checked, but the bounds are determined by
+ the initial call to [map_file]. Therefore, you should make sure no
+ other process modifies the mapped file while you're accessing it,
+ or a SIGBUS signal may be raised. This happens, for instance, if the
+ file is shrunk.
+
+ [Invalid_argument] or [Failure] may be raised in cases where argument
+ validation fails.
+ @since 4.06.0 *)
+
+(** {1 Operations on file names} *)
val unlink : string -> unit
*)
val rename : string -> string -> unit
-(** [rename old new] changes the name of a file from [old] to [new]. *)
+(** [rename old new] changes the name of a file from [old] to [new],
+ moving it between directories if needed. If [new] already
+ exists, its contents will be replaced with those of [old].
+ Depending on the operating system, the metadata (permissions,
+ owner, etc) of [new] can either be preserved or be replaced by
+ those of [old]. *)
val link : string -> string -> unit
(** [link source dest] creates a hard link named [dest] to the file
named [source]. *)
-(** {6 File permissions and ownership} *)
+(** {1 File permissions and ownership} *)
type access_permission =
tests for read permission instead. *)
-(** {6 Operations on file descriptors} *)
+(** {1 Operations on file descriptors} *)
val dup : ?cloexec:bool -> file_descr -> file_descr
See {!Unix.set_close_on_exec}.*)
-(** {6 Directories} *)
+(** {1 Directories} *)
val mkdir : string -> file_perm -> unit
-(** {6 Pipes and redirections} *)
+(** {1 Pipes and redirections} *)
val pipe : ?cloexec:bool -> unit -> file_descr * file_descr
On Windows: not implemented. *)
-(** {6 High-level process and redirection management} *)
+(** {1 High-level process and redirection management} *)
val create_process :
and return its termination status. *)
-(** {6 Symbolic links} *)
+(** {1 Symbolic links} *)
val symlink : ?to_dir:bool -> string -> string -> unit
(** Read the contents of a symbolic link. *)
-(** {6 Polling} *)
+(** {1 Polling} *)
val select :
component). *)
-(** {6 Locking} *)
+(** {1 Locking} *)
type lock_command =
F_ULOCK (** Unlock a region *)
*)
-(** {6 Signals}
+(** {1 Signals}
Note: installation of signal handlers is performed via
the functions {!Sys.signal} and {!Sys.set_signal}.
*)
On Windows: not implemented (no inter-process signals on Windows). *)
-(** {6 Time functions} *)
+(** {1 Time functions} *)
type process_times =
On Windows: not implemented. *)
-(** {6 User id, group id} *)
+(** {1 User id, group id} *)
val getuid : unit -> int
On Windows, always raise [Not_found]. *)
-(** {6 Internet addresses} *)
+(** {1 Internet addresses} *)
type inet_addr
(** A special IPv6 address representing the host machine ([::1]). *)
-(** {6 Sockets} *)
+(** {1 Sockets} *)
type socket_domain =
@since 4.02.0 *)
-(** {6 Socket options} *)
+(** {1 Socket options} *)
type socket_bool_option =
and clear it. *)
-(** {6 High-level network connection functions} *)
+(** {1 High-level network connection functions} *)
val open_connection : sockaddr -> in_channel * out_channel
On Windows, it is not implemented. Use threads. *)
-(** {6 Host and protocol databases} *)
+(** {1 Host and protocol databases} *)
type host_entry =
@raise Not_found if an error occurs. *)
-(** {6 Terminal interface} *)
+(** {1 Terminal interface} *)
(** The following functions implement the POSIX standard terminal
add [module Unix = UnixLabels] in your implementation.
*)
-(** {6 Error report} *)
+(** {1 Error report} *)
type error = Unix.error =
describing the error and exits with code 2. *)
-(** {6 Access to the process environment} *)
+(** {1 Access to the process environment} *)
val environment : unit -> string array
environment. Raise [Not_found] if the variable is unbound.
(This function is identical to [Sys.getenv].) *)
-(*
val unsafe_getenv : string -> string
(** Return the value associated to a variable in the process
environment.
for executables, the locations for temporary files or logs, and the
like.
- @raise Not_found if the variable is unbound. *)
-*)
+ @raise Not_found if the variable is unbound.
+ @since 4.06.0 *)
val putenv : string -> string -> unit
(** [Unix.putenv name value] sets the value associated to a
and [value] its new associated value. *)
-(** {6 Process handling} *)
+(** {1 Process handling} *)
type process_status = Unix.process_status =
lower priorities.) Return the new nice value. *)
-(** {6 Basic file input/output} *)
+(** {1 Basic file input/output} *)
type file_descr = Unix.file_descr
a byte sequence.
@since 4.02.0 *)
-(** {6 Interfacing with the standard input/output library} *)
+(** {1 Interfacing with the standard input/output library} *)
(** Return the descriptor corresponding to an output channel. *)
-(** {6 Seeking and truncating} *)
+(** {1 Seeking and truncating} *)
type seek_command = Unix.seek_command =
to the given size. *)
-(** {6 File status} *)
+(** {1 File status} *)
type file_kind = Unix.file_kind =
(** Return [true] if the given file descriptor refers to a terminal or
console window, [false] otherwise. *)
-(** {6 File operations on large files} *)
+(** {1 File operations on large files} *)
module LargeFile :
sig
whose sizes are greater than [max_int]. *)
-(** {6 Operations on file names} *)
+(** {1 Mapping files into memory} *)
+
+val map_file :
+ file_descr -> ?pos:int64 -> kind:('a, 'b) CamlinternalBigarray.kind ->
+ layout:'c CamlinternalBigarray.layout -> shared:bool -> dims:int array ->
+ ('a, 'b, 'c) CamlinternalBigarray.genarray
+(** Memory mapping of a file as a big array.
+ [map_file fd kind layout shared dims]
+ returns a big array of kind [kind], layout [layout],
+ and dimensions as specified in [dims]. The data contained in
+ this big array are the contents of the file referred to by
+ the file descriptor [fd] (as opened previously with
+ [Unix.openfile], for example). The optional [pos] parameter
+ is the byte offset in the file of the data being mapped;
+ it defaults to 0 (map from the beginning of the file).
+
+ If [shared] is [true], all modifications performed on the array
+ are reflected in the file. This requires that [fd] be opened
+ with write permissions. If [shared] is [false], modifications
+ performed on the array are done in memory only, using
+ copy-on-write of the modified pages; the underlying file is not
+ affected.
+
+ [Genarray.map_file] is much more efficient than reading
+ the whole file in a big array, modifying that big array,
+ and writing it afterwards.
+
+ To adjust automatically the dimensions of the big array to
+ the actual size of the file, the major dimension (that is,
+ the first dimension for an array with C layout, and the last
+ dimension for an array with Fortran layout) can be given as
+ [-1]. [Genarray.map_file] then determines the major dimension
+ from the size of the file. The file must contain an integral
+ number of sub-arrays as determined by the non-major dimensions,
+ otherwise [Failure] is raised.
+
+ If all dimensions of the big array are given, the file size is
+ matched against the size of the big array. If the file is larger
+ than the big array, only the initial portion of the file is
+ mapped to the big array. If the file is smaller than the big
+ array, the file is automatically grown to the size of the big array.
+ This requires write permissions on [fd].
+
+ Array accesses are bounds-checked, but the bounds are determined by
+ the initial call to [map_file]. Therefore, you should make sure no
+ other process modifies the mapped file while you're accessing it,
+ or a SIGBUS signal may be raised. This happens, for instance, if the
+ file is shrunk.
+
+ [Invalid_argument] or [Failure] may be raised in cases where argument
+ validation fails.
+ @since 4.06.0 *)
+
+(** {1 Operations on file names} *)
val unlink : string -> unit
named [source]. *)
-(** {6 File permissions and ownership} *)
+(** {1 File permissions and ownership} *)
type access_permission = Unix.access_permission =
file. Raise [Unix_error] otherwise. *)
-(** {6 Operations on file descriptors} *)
+(** {1 Operations on file descriptors} *)
val dup : ?cloexec:bool -> file_descr -> file_descr
See {!UnixLabels.set_close_on_exec}.*)
-(** {6 Directories} *)
+(** {1 Directories} *)
val mkdir : string -> perm:file_perm -> unit
-(** {6 Pipes and redirections} *)
+(** {1 Pipes and redirections} *)
val pipe : ?cloexec:bool -> unit -> file_descr * file_descr
(** Create a named pipe with the given permissions. *)
-(** {6 High-level process and redirection management} *)
+(** {1 High-level process and redirection management} *)
val create_process :
and return its termination status. *)
-(** {6 Symbolic links} *)
+(** {1 Symbolic links} *)
val symlink : ?to_dir:bool -> src:string -> dst:string -> unit
(** Read the contents of a link. *)
-(** {6 Polling} *)
+(** {1 Polling} *)
val select :
and over which an exceptional condition is pending (third
component). *)
-(** {6 Locking} *)
+(** {1 Locking} *)
type lock_command = Unix.lock_command =
It returns immediately if successful, or fails otherwise. *)
-(** {6 Signals}
+(** {1 Signals}
Note: installation of signal handlers is performed via
the functions {!Sys.signal} and {!Sys.set_signal}.
*)
(** Wait until a non-ignored, non-blocked signal is delivered. *)
-(** {6 Time functions} *)
+(** {1 Time functions} *)
type process_times = Unix.process_times =
after its next expiration. *)
-(** {6 User id, group id} *)
+(** {1 User id, group id} *)
val getuid : unit -> int
[Not_found]. *)
-(** {6 Internet addresses} *)
+(** {1 Internet addresses} *)
type inet_addr = Unix.inet_addr
(** A special IPv6 address representing the host machine ([::1]). *)
-(** {6 Sockets} *)
+(** {1 Sockets} *)
type socket_domain = Unix.socket_domain =
-(** {6 Socket options} *)
+(** {1 Socket options} *)
type socket_bool_option =
(** Return the error condition associated with the given socket,
and clear it. *)
-(** {6 High-level network connection functions} *)
+(** {1 High-level network connection functions} *)
val open_connection : sockaddr -> in_channel * out_channel
never returns normally. *)
-(** {6 Host and protocol databases} *)
+(** {1 Host and protocol databases} *)
type host_entry = Unix.host_entry =
Raise [Not_found] if an error occurs. *)
-(** {6 Terminal interface} *)
+(** {1 Terminal interface} *)
(** The following functions implement the POSIX standard terminal
}
}
-void unix_error(int errcode, char *cmdname, value cmdarg)
+void unix_error(int errcode, const char *cmdname, value cmdarg)
{
value res;
value name = Val_unit, err = Val_unit, arg = Val_unit;
caml_raise(res);
}
-void uerror(char *cmdname, value cmdarg)
+void uerror(const char *cmdname, value cmdarg)
{
unix_error(errno, cmdname, cmdarg);
}
-void caml_unix_check_path(value path, char * cmdname)
+void caml_unix_check_path(value path, const char * cmdname)
{
if (! caml_string_is_c_safe(path)) unix_error(ENOENT, cmdname, path);
}
extern int code_of_unix_error (value error);
CAMLnoreturn_start
-extern void unix_error (int errcode, char * cmdname, value arg)
+extern void unix_error (int errcode, const char * cmdname, value arg)
CAMLnoreturn_end;
CAMLnoreturn_start
-extern void uerror (char * cmdname, value arg)
+extern void uerror (const char * cmdname, value arg)
CAMLnoreturn_end;
-extern void caml_unix_check_path(value path, char * cmdname);
+extern void caml_unix_check_path(value path, const char * cmdname);
#define UNIX_BUFFER_SIZE 65536
#define DIR_Val(v) *((DIR **) &Field(v, 0))
extern char ** cstringvect(value arg, char * cmdname);
+extern void cstringvect_free(char **);
extern int unix_cloexec_default;
extern int unix_cloexec_p(value cloexec);
}
#endif
+#define EXECV_CAST
+
#endif /* CAML_UNIXSUPPORT_H */
/* */
/**************************************************************************/
+#define CAML_INTERNALS
+
#include <caml/mlvalues.h>
#include <caml/memory.h>
#include <caml/signals.h>
+#include <caml/osdeps.h>
#include "unixsupport.h"
CAMLprim value unix_unlink(value path)
{
CAMLparam1(path);
- char * p;
+ char_os * p;
int ret;
caml_unix_check_path(path, "unlink");
- p = caml_strdup(String_val(path));
+ p = caml_stat_strdup_to_os(String_val(path));
caml_enter_blocking_section();
- ret = unlink(p);
+ ret = unlink_os(p);
caml_leave_blocking_section();
caml_stat_free(p);
if (ret == -1) uerror("unlink", path);
/* */
/**************************************************************************/
+#define CAML_INTERNALS
+
#include <caml/fail.h>
#include <caml/mlvalues.h>
#include <caml/memory.h>
#include <caml/signals.h>
+#include <caml/osdeps.h>
#include "unixsupport.h"
#if defined(HAS_UTIMES)
tv[1].tv_usec = (mt - tv[1].tv_sec) * 1000000;
t = tv;
}
- p = caml_strdup(String_val(path));
+ p = caml_stat_strdup(String_val(path));
caml_enter_blocking_section();
ret = utimes(p, t);
caml_leave_blocking_section();
CAMLprim value unix_utimes(value path, value atime, value mtime)
{
CAMLparam3(path, atime, mtime);
+#ifdef _WIN32
+ struct _utimbuf times, * t;
+#else
struct utimbuf times, * t;
- char * p;
+#endif
+ char_os * p;
int ret;
double at, mt;
caml_unix_check_path(path, "utimes");
at = Double_val(atime);
mt = Double_val(mtime);
if (at == 0.0 && mt == 0.0) {
- t = (struct utimbuf *) NULL;
+ t = NULL;
} else {
times.actime = at;
times.modtime = mt;
t = ×
}
- p = caml_strdup(String_val(path));
+ p = caml_stat_strdup_to_os(String_val(path));
caml_enter_blocking_section();
- ret = utime(p, t);
+ ret = utime_os(p, t);
caml_leave_blocking_section();
caml_stat_free(p);
if (ret == -1) uerror("utimes", path);
graphics.mli: ../graph/graphics.mli
cp ../graph/graphics.mli graphics.mli
+.PHONY:
depend:
graphics.cmo: graphics.cmi
SetTextAlign(grwindow.gcBitmap, TA_UPDATECP|TA_BOTTOM);
SetTextAlign(grwindow.gc, TA_UPDATECP|TA_BOTTOM);
if (grremember_mode) {
- TextOut(grwindow.gcBitmap,0,0,(char *)text,x);
+ TextOutA(grwindow.gcBitmap,0,0,String_val(text),x);
}
if(grdisplay_mode) {
- TextOut(grwindow.gc,0,0,(char *)text,x);
+ TextOutA(grwindow.gc,0,0,String_val(text),x);
}
GetCurrentPosition(grwindow.gc,&pt);
grwindow.grx = pt.x;
CAMLprim value caml_gr_set_window_title(value text)
{
- SetWindowText(grwindow.hwnd,(char *)text);
+ SetWindowTextA(grwindow.hwnd,(char *)text);
return Val_unit;
}
mlsize_t len = caml_string_length(str);
if (len > 32767) len = 32767;
- GetTextExtentPoint(grwindow.gc,String_val(str), len,&extent);
+ GetTextExtentPointA(grwindow.gc,String_val(str), len,&extent);
res = caml_alloc_tuple(2);
Field(res, 0) = Val_long(extent.cx);
if (n_points < 3)
gr_fail("fill_poly: not enough points",0);
- poly = (POINT *)malloc(n_points*sizeof(POINT));
+ poly = (POINT *)caml_stat_alloc(n_points*sizeof(POINT));
p = poly;
for( i = 0; i < n_points; i++ ){
SelectObject(grwindow.gcBitmap,grwindow.CurrentBrush);
Polygon(grwindow.gc,poly,n_points);
}
- free(poly);
+ caml_stat_free(poly);
return Val_unit;
}
HFONT CreationFont(char *name)
{
- LOGFONT CurrentFont;
- memset(&CurrentFont, 0, sizeof(LOGFONT));
+ LOGFONTA CurrentFont;
+ memset(&CurrentFont, 0, sizeof(LOGFONTA));
CurrentFont.lfCharSet = ANSI_CHARSET;
CurrentFont.lfWeight = FW_NORMAL;
CurrentFont.lfHeight = grwindow.CurrentFontSize;
CurrentFont.lfPitchAndFamily = (BYTE) (FIXED_PITCH | FF_MODERN);
strncpy(CurrentFont.lfFaceName, name, sizeof(CurrentFont.lfFaceName));
CurrentFont.lfFaceName[sizeof(CurrentFont.lfFaceName) - 1] = 0;
- return (CreateFontIndirect(&CurrentFont));
+ return (CreateFontIndirectA(&CurrentFont));
}
void SetCoordinates(HWND hwnd)
int DoRegisterClass(void)
{
- WNDCLASS wc;
+ WNDCLASSA wc;
memset(&wc,0,sizeof(WNDCLASS));
wc.style = CS_HREDRAW|CS_VREDRAW|CS_OWNDC ;
wc.lpszMenuName = 0;
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
wc.hIcon = 0;
- return RegisterClass(&wc);
+ return RegisterClassA(&wc);
}
static value gr_reset(void)
return 1;
}
}
- grwindow.hwnd = CreateWindow(szOcamlWindowClass,
- WINDOW_NAME,
- WS_OVERLAPPEDWINDOW,
- x,y,
- w,h,
- NULL,0,hInst,NULL);
+ grwindow.hwnd = CreateWindowA(szOcamlWindowClass,
+ WINDOW_NAME,
+ WS_OVERLAPPEDWINDOW,
+ x,y,
+ w,h,
+ NULL,0,hInst,NULL);
if (grwindow.hwnd == NULL) {
open_graph_errmsg = "Cannot create window";
SetEvent(open_graph_event);
-unix.cmo: unix.cmi
-unix.cmx: unix.cmi
-unixLabels.cmo: unix.cmi unixLabels.cmi
-unixLabels.cmx: unix.cmx unixLabels.cmi
-unixLabels.cmi: unix.cmi
+windbug.$(O): windbug.c windbug.h
+cst2constr.$(O): cst2constr.c ../../byterun/caml/mlvalues.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/fail.h ../unix/cst2constr.h
+mmap_ba.$(O): mmap_ba.c ../../byterun/caml/alloc.h ../../byterun/caml/misc.h \
+ ../../byterun/caml/config.h ../../byterun/caml/m.h \
+ ../../byterun/caml/s.h ../../byterun/caml/mlvalues.h \
+ ../../byterun/caml/bigarray.h ../../byterun/caml/custom.h \
+ ../../byterun/caml/memory.h ../../byterun/caml/gc.h \
+ ../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \
+ ../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h
+unix.cmo : unix.cmi
+unix.cmx : unix.cmi
+unix.cmi :
+unixLabels.cmo : unix.cmi unixLabels.cmi
+unixLabels.cmx : unix.cmx unixLabels.cmi
+unixLabels.cmi : unix.cmi
# Files in this directory
WIN_FILES = accept.c bind.c channels.c close.c \
- close_on.c connect.c createprocess.c dup.c dup2.c errmsg.c \
- getpeername.c getpid.c getsockname.c gettimeofday.c \
+ close_on.c connect.c createprocess.c dup.c dup2.c errmsg.c envir.c \
+ getpeername.c getpid.c getsockname.c gettimeofday.c isatty.c \
link.c listen.c lockf.c lseek.c nonblock.c \
- mkdir.c open.c pipe.c read.c readlink.c rename.c \
+ mkdir.c mmap.c open.c pipe.c read.c readlink.c rename.c \
select.c sendrecv.c \
shutdown.c sleep.c socket.c sockopt.c startup.c stat.c \
symlink.c system.c times.c unixsupport.c windir.c winwait.c write.c \
# Files from the ../unix directory
UNIX_FILES = access.c addrofstr.c chdir.c chmod.c cst2constr.c \
- cstringv.c envir.c execv.c execve.c execvp.c \
+ cstringv.c execv.c execve.c execvp.c \
exit.c getaddrinfo.c getcwd.c gethost.c gethostname.c \
getnameinfo.c getproto.c \
- getserv.c gmtime.c putenv.c rmdir.c \
+ getserv.c gmtime.c mmap_ba.c putenv.c rmdir.c \
socketaddr.c strofaddr.c time.c unlink.c utimes.c
UNIX_CAML_FILES = unix.mli unixLabels.mli unixLabels.ml
$(UNIX_FILES) $(UNIX_CAML_FILES): %: ../unix/%
cp ../unix/$* $*
+.PHONY: depend
+ifeq "$(TOOLCHAIN)" "msvc"
depend:
-
-$(COBJS): unixsupport.h
+ $(error Dependencies cannot be regenerated using the MSVC ports)
+else
+depend: $(ALL_FILES) $(UNIX_CAML_FILES) unix.ml
+ $(CC) -MM $(CPPFLAGS) -I../unix $(ALL_FILES) \
+ | sed -e 's/\.o/.$$(O)/g' > .depend
+ $(CAMLRUN) $(ROOTDIR)/tools/ocamldep -slash $(UNIX_CAML_FILES) \
+ unix.ml >> .depend
+endif
include .depend
fflush(stdin);
#endif
chan = caml_open_descriptor_in(win_CRT_fd_of_filedescr(handle));
+ chan->flags |= CHANNEL_FLAG_MANAGED_BY_GC;
+ /* as in caml_ml_open_descriptor_in() */
if (Descr_kind_val(handle) == KIND_SOCKET)
chan->flags |= CHANNEL_FLAG_FROM_SOCKET;
vchan = caml_alloc_channel(chan);
struct channel * chan;
chan = caml_open_descriptor_out(win_CRT_fd_of_filedescr(handle));
+ chan->flags |= CHANNEL_FLAG_MANAGED_BY_GC;
+ /* as in caml_ml_open_descriptor_out() */
if (Descr_kind_val(handle) == KIND_SOCKET)
chan->flags |= CHANNEL_FLAG_FROM_SOCKET;
vchan = caml_alloc_channel(chan);
static int win_has_console(void);
-value win_create_process_native(value cmd, value cmdline, value env,
- value fd1, value fd2, value fd3)
+static DWORD do_create_process_native(wchar_t * exefile, wchar_t * cmdline, wchar_t * env,
+ HANDLE fd1, HANDLE fd2, HANDLE fd3, HANDLE * hProcess)
{
PROCESS_INFORMATION pi;
STARTUPINFO si;
- char * exefile, * envp;
DWORD flags, err;
HANDLE hp;
- caml_unix_check_path(cmd, "create_process");
- if (! caml_string_is_c_safe(cmdline))
- unix_error(EINVAL, "create_process", cmdline);
- /* [env] is checked for null bytes at construction time, see unix.ml */
-
err = ERROR_SUCCESS;
- exefile = caml_search_exe_in_path(String_val(cmd));
- if (env != Val_int(0)) {
- envp = String_val(Field(env, 0));
- } else {
- envp = NULL;
- }
/* Prepare stdin/stdout/stderr redirection */
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESTDHANDLES;
/* Duplicate the handles fd1, fd2, fd3 to make sure they are inheritable */
hp = GetCurrentProcess();
- if (! DuplicateHandle(hp, Handle_val(fd1), hp, &(si.hStdInput),
+ if (! DuplicateHandle(hp, fd1, hp, &(si.hStdInput),
0, TRUE, DUPLICATE_SAME_ACCESS)) {
err = GetLastError(); goto ret1;
}
- if (! DuplicateHandle(hp, Handle_val(fd2), hp, &(si.hStdOutput),
+ if (! DuplicateHandle(hp, fd2, hp, &(si.hStdOutput),
0, TRUE, DUPLICATE_SAME_ACCESS)) {
err = GetLastError(); goto ret2;
}
- if (! DuplicateHandle(hp, Handle_val(fd3), hp, &(si.hStdError),
+ if (! DuplicateHandle(hp, fd3, hp, &(si.hStdError),
0, TRUE, DUPLICATE_SAME_ACCESS)) {
err = GetLastError(); goto ret3;
}
si.dwFlags = (STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES);
si.wShowWindow = SW_HIDE;
}
+ flags |= CREATE_UNICODE_ENVIRONMENT;
/* Create the process */
- if (! CreateProcess(exefile, String_val(cmdline), NULL, NULL,
- TRUE, flags, envp, NULL, &si, &pi)) {
+ if (! CreateProcess(exefile, cmdline, NULL, NULL,
+ TRUE, flags, env, NULL, &si, &pi)) {
err = GetLastError(); goto ret4;
}
CloseHandle(pi.hThread);
ret2:
CloseHandle(si.hStdInput);
ret1:
+ *hProcess = (err == ERROR_SUCCESS) ? pi.hProcess : NULL;
+ return err;
+}
+
+value win_create_process_native(value cmd, value cmdline, value env,
+ value fd1, value fd2, value fd3)
+{
+ wchar_t * exefile, * wcmdline, * wenv, * wcmd;
+ HANDLE hProcess;
+ DWORD err;
+ int size;
+
+ caml_unix_check_path(cmd, "create_process");
+ if (! caml_string_is_c_safe(cmdline))
+ unix_error(EINVAL, "create_process", cmdline);
+ /* [env] is checked for null bytes at construction time, see unix.ml */
+
+ wcmd = caml_stat_strdup_to_utf16(String_val(cmd));
+ exefile = caml_search_exe_in_path(wcmd);
+ caml_stat_free(wcmd);
+ wcmdline = caml_stat_strdup_to_utf16(String_val(cmdline));
+
+ if (env != Val_int(0)) {
+ env = Field(env, 0);
+ size = win_multi_byte_to_wide_char(String_val(env), caml_string_length(env), NULL, 0);
+ wenv = caml_stat_alloc((size + 1)*sizeof(wchar_t));
+ win_multi_byte_to_wide_char(String_val(env), caml_string_length(env), wenv, size);
+ wenv[size] = 0;
+ } else {
+ wenv = NULL;
+ }
+
+ err = do_create_process_native(exefile, wcmdline, wenv,
+ Handle_val(fd1), Handle_val(fd2), Handle_val(fd3), &hProcess);
+
+ if (wenv != NULL) caml_stat_free(wenv);
+ caml_stat_free(wcmdline);
caml_stat_free(exefile);
if (err != ERROR_SUCCESS) {
win32_maperr(err);
}
/* Return the process handle as pseudo-PID
(this is consistent with the wait() emulation in the MSVC C library */
- return Val_long(pi.hProcess);
+ return Val_long(hProcess);
}
CAMLprim value win_create_process(value * argv, int argn)
HANDLE h, log;
int i;
- h = CreateFile("CONOUT$", GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
+ h = CreateFile(L"CONOUT$", GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (h == INVALID_HANDLE_VALUE) {
return 0;
--- /dev/null
+/**************************************************************************/
+/* */
+/* OCaml */
+/* */
+/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */
+/* */
+/* Copyright 1996 Institut National de Recherche en Informatique et */
+/* en Automatique. */
+/* */
+/* All rights reserved. This file is distributed under the terms of */
+/* the GNU Lesser General Public License version 2.1, with the */
+/* special exception on linking described in the file LICENSE. */
+/* */
+/**************************************************************************/
+
+#define CAML_INTERNALS
+
+#include <caml/mlvalues.h>
+#include <caml/alloc.h>
+#include <caml/memory.h>
+#include <caml/osdeps.h>
+
+#include <Windows.h>
+#include <stdlib.h>
+
+CAMLprim value unix_environment(value unit)
+{
+ /* Win32 doesn't have a notion of setuid bit, so accessing environ is safe. */
+ if (_wenviron != NULL) {
+ return caml_alloc_array((void *)caml_copy_string_of_utf16, (const char**)_wenviron);
+ } else {
+ return Atom(0);
+ }
+}
/* */
/**************************************************************************/
+#define CAML_INTERNALS
+
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <caml/mlvalues.h>
#include <caml/alloc.h>
+#include <caml/osdeps.h>
#include "unixsupport.h"
extern int error_table[];
CAMLprim value unix_error_message(value err)
{
int errnum;
- char buffer[512];
+ wchar_t buffer[512];
errnum = Is_block(err) ? Int_val(Field(err, 0)) : error_table[Int_val(err)];
if (errnum > 0)
-errnum,
0,
buffer,
- sizeof(buffer),
+ sizeof(buffer)/sizeof(wchar_t),
NULL))
- return caml_copy_string(buffer);
- sprintf(buffer, "unknown error #%d", errnum);
- return caml_copy_string(buffer);
+ return caml_copy_string_of_utf16(buffer);
+ swprintf(buffer, sizeof(buffer)/sizeof(wchar_t), L"unknown error #%d", errnum);
+ return caml_copy_string_of_utf16(buffer);
}
--- /dev/null
+/**************************************************************************/
+/* */
+/* OCaml */
+/* */
+/* David Allsopp, OCaml Labs, Cambridge. */
+/* */
+/* Copyright 2017 MetaStack Solutions Ltd. */
+/* */
+/* All rights reserved. This file is distributed under the terms of */
+/* the GNU Lesser General Public License version 2.1, with the */
+/* special exception on linking described in the file LICENSE. */
+/* */
+/**************************************************************************/
+
+#include <caml/mlvalues.h>
+#include "unixsupport.h"
+
+CAMLprim value unix_isatty(value fd)
+{
+ DWORD lpMode;
+ HANDLE hFile = Handle_val(fd);
+ return (Val_bool((GetFileType(hFile) == FILE_TYPE_CHAR)
+ && GetConsoleMode(hFile, &lpMode)));
+}
/* */
/**************************************************************************/
+#define CAML_INTERNALS
+
#include <caml/mlvalues.h>
#include <caml/fail.h>
+#include <caml/memory.h>
+#include <caml/osdeps.h>
#include "unixsupport.h"
#include <windows.h>
typedef
BOOL (WINAPI *tCreateHardLink)(
- LPCTSTR lpFileName,
- LPCTSTR lpExistingFileName,
+ LPCWSTR lpFileName,
+ LPCWSTR lpExistingFileName,
LPSECURITY_ATTRIBUTES lpSecurityAttributes
);
{
HMODULE hModKernel32;
tCreateHardLink pCreateHardLink;
- hModKernel32 = GetModuleHandle("KERNEL32.DLL");
+ BOOL result;
+ wchar_t * wpath1, * wpath2;
+ hModKernel32 = GetModuleHandle(L"KERNEL32.DLL");
pCreateHardLink =
- (tCreateHardLink) GetProcAddress(hModKernel32, "CreateHardLinkA");
+ (tCreateHardLink) GetProcAddress(hModKernel32, "CreateHardLinkW");
if (pCreateHardLink == NULL)
caml_invalid_argument("Unix.link not implemented");
caml_unix_check_path(path1, "link");
caml_unix_check_path(path2, "link");
- if (! pCreateHardLink(String_val(path2), String_val(path1), NULL)) {
+
+ wpath1 = caml_stat_strdup_to_utf16(String_val(path1));
+ wpath2 = caml_stat_strdup_to_utf16(String_val(path2));
+
+ result = pCreateHardLink(wpath2, wpath1, NULL);
+
+ caml_stat_free(wpath1);
+ caml_stat_free(wpath2);
+
+ if (! result) {
win32_maperr(GetLastError());
uerror("link", path2);
}
/* */
/**************************************************************************/
+#define CAML_INTERNALS
+
#include <caml/mlvalues.h>
+#include <caml/osdeps.h>
+#include <caml/memory.h>
#include "unixsupport.h"
CAMLprim value unix_mkdir(path, perm)
value path, perm;
{
+ int err;
+ wchar_t * wpath;
caml_unix_check_path(path, "mkdir");
- if (_mkdir(String_val(path)) == -1) uerror("mkdir", path);
+ wpath = caml_stat_strdup_to_utf16(String_val(path));
+ err = _wmkdir(wpath);
+ caml_stat_free(wpath);
+ if (err == -1) uerror("mkdir", path);
return Val_unit;
}
--- /dev/null
+/**************************************************************************/
+/* */
+/* OCaml */
+/* */
+/* Manuel Serrano and Xavier Leroy, INRIA Rocquencourt */
+/* */
+/* Copyright 2000 Institut National de Recherche en Informatique et */
+/* en Automatique. */
+/* */
+/* All rights reserved. This file is distributed under the terms of */
+/* the GNU Lesser General Public License version 2.1, with the */
+/* special exception on linking described in the file LICENSE. */
+/* */
+/**************************************************************************/
+
+#define CAML_INTERNALS
+
+#include <stddef.h>
+#include "caml/alloc.h"
+#include "caml/bigarray.h"
+#include "caml/fail.h"
+#include "caml/io.h"
+#include "caml/mlvalues.h"
+#include "caml/signals.h"
+#include "caml/sys.h"
+#include "caml/osdeps.h"
+#include "unixsupport.h"
+
+/* Temporary compatibility stuff so that this file can also be compiled
+ from otherlibs/bigarray/ and included in the bigarray library. */
+
+#ifdef IN_OCAML_BIGARRAY
+#define MAP_FILE_FUNCTION caml_ba_map_file
+#define MAP_FILE_FUNCTION_BYTECODE caml_ba_map_file_bytecode
+#define UNMAP_FILE_FUNCTION caml_ba_unmap_file
+#define ALLOC_FUNCTION caml_ba_mapped_alloc
+#define CAML_MAP_FILE "Bigarray.map_file"
+static void caml_ba_sys_error(void);
+#define MAP_FILE_ERROR() caml_ba_sys_error()
+#else
+#define MAP_FILE_FUNCTION caml_unix_map_file
+#define MAP_FILE_FUNCTION_BYTECODE caml_unix_map_file_bytecode
+#define UNMAP_FILE_FUNCTION caml_unix_unmap_file
+#define ALLOC_FUNCTION caml_unix_mapped_alloc
+#define MAP_FILE_FUNCTION caml_unix_map_file
+#define CAML_MAP_FILE "Unix.map_file"
+#define MAP_FILE_ERROR() \
+ do { win32_maperr(GetLastError()); uerror("map_file", Nothing); } while(0)
+#endif
+
+/* Defined in [mmap_ba.c] */
+CAMLextern value
+ALLOC_FUNCTION(int flags, int num_dims, void * data, intnat * dim);
+
+#ifndef INVALID_SET_FILE_POINTER
+#define INVALID_SET_FILE_POINTER (-1)
+#endif
+
+static __int64 caml_set_file_pointer(HANDLE h, __int64 dist, DWORD mode)
+{
+ LARGE_INTEGER i;
+ DWORD err;
+
+ i.QuadPart = dist;
+ i.LowPart = SetFilePointer(h, i.LowPart, &i.HighPart, mode);
+ if (i.LowPart == INVALID_SET_FILE_POINTER) return -1;
+ return i.QuadPart;
+}
+
+CAMLprim value MAP_FILE_FUNCTION(value vfd, value vkind, value vlayout,
+ value vshared, value vdim, value vstart)
+{
+ HANDLE fd, fmap;
+ int flags, major_dim, mode, perm;
+ intnat num_dims, i;
+ intnat dim[CAML_BA_MAX_NUM_DIMS];
+ __int64 currpos, startpos, file_size, data_size;
+ uintnat array_size, page, delta;
+ char c;
+ void * addr;
+ LARGE_INTEGER li;
+ SYSTEM_INFO sysinfo;
+
+ fd = Handle_val(vfd);
+ flags = Caml_ba_kind_val(vkind) | Caml_ba_layout_val(vlayout);
+ startpos = Int64_val(vstart);
+ num_dims = Wosize_val(vdim);
+ major_dim = flags & CAML_BA_FORTRAN_LAYOUT ? num_dims - 1 : 0;
+ /* Extract dimensions from OCaml array */
+ num_dims = Wosize_val(vdim);
+ if (num_dims < 1 || num_dims > CAML_BA_MAX_NUM_DIMS)
+ caml_invalid_argument(CAML_MAP_FILE ": bad number of dimensions");
+ for (i = 0; i < num_dims; i++) {
+ dim[i] = Long_val(Field(vdim, i));
+ if (dim[i] == -1 && i == major_dim) continue;
+ if (dim[i] < 0)
+ caml_invalid_argument(CAML_MAP_FILE ": negative dimension");
+ }
+ /* Determine file size */
+ currpos = caml_set_file_pointer(fd, 0, FILE_CURRENT);
+ if (currpos == -1) MAP_FILE_ERROR();
+ file_size = caml_set_file_pointer(fd, 0, FILE_END);
+ if (file_size == -1) MAP_FILE_ERROR();
+ /* Determine array size in bytes (or size of array without the major
+ dimension if that dimension wasn't specified) */
+ array_size = caml_ba_element_size[flags & CAML_BA_KIND_MASK];
+ for (i = 0; i < num_dims; i++)
+ if (dim[i] != -1) array_size *= dim[i];
+ /* Check if the first/last dimension is unknown */
+ if (dim[major_dim] == -1) {
+ /* Determine first/last dimension from file size */
+ if (file_size < startpos)
+ caml_failwith(CAML_MAP_FILE ": file position exceeds file size");
+ data_size = file_size - startpos;
+ dim[major_dim] = (uintnat) (data_size / array_size);
+ array_size = dim[major_dim] * array_size;
+ if (array_size != data_size)
+ caml_failwith(CAML_MAP_FILE ": file size doesn't match array dimensions");
+ }
+ /* Restore original file position */
+ caml_set_file_pointer(fd, currpos, FILE_BEGIN);
+ /* Create the file mapping */
+ if (Bool_val(vshared)) {
+ perm = PAGE_READWRITE;
+ mode = FILE_MAP_WRITE;
+ } else {
+ perm = PAGE_READONLY; /* doesn't work under Win98 */
+ mode = FILE_MAP_COPY;
+ }
+ li.QuadPart = startpos + array_size;
+ fmap = CreateFileMapping(fd, NULL, perm, li.HighPart, li.LowPart, NULL);
+ if (fmap == NULL) MAP_FILE_ERROR();
+ /* Determine offset so that the mapping starts at the given file pos */
+ GetSystemInfo(&sysinfo);
+ delta = (uintnat) (startpos % sysinfo.dwAllocationGranularity);
+ /* Map the mapping in memory */
+ li.QuadPart = startpos - delta;
+ addr =
+ MapViewOfFile(fmap, mode, li.HighPart, li.LowPart, array_size + delta);
+ if (addr == NULL) MAP_FILE_ERROR();
+ addr = (void *) ((uintnat) addr + delta);
+ /* Close the file mapping */
+ CloseHandle(fmap);
+ /* Build and return the OCaml bigarray */
+ return ALLOC_FUNCTION(flags, num_dims, addr, dim);
+}
+
+CAMLprim value MAP_FILE_FUNCTION_BYTECODE(value * argv, int argn)
+{
+ return MAP_FILE_FUNCTION(argv[0], argv[1], argv[2],
+ argv[3], argv[4], argv[5]);
+}
+
+void UNMAP_FILE_FUNCTION(void * addr, uintnat len)
+{
+ SYSTEM_INFO sysinfo;
+ uintnat delta;
+
+ GetSystemInfo(&sysinfo);
+ delta = (uintnat) addr % sysinfo.dwAllocationGranularity;
+ UnmapViewOfFile((void *)((uintnat)addr - delta));
+}
+
+#ifdef IN_OCAML_BIGARRAY
+
+/* This function reports a Win32 error as a Sys_error exception.
+ It is included for backward compatibility with the old
+ Bigarray.*.map_file implementation. */
+
+static void caml_ba_sys_error(void)
+{
+ wchar_t buffer[512];
+ DWORD errnum;
+
+ errnum = GetLastError();
+ if (!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ errnum,
+ 0,
+ buffer,
+ sizeof(buffer)/sizeof(wchar_t),
+ NULL))
+ swprintf(buffer, sizeof(buffer)/sizeof(wchar_t), L"Unknown error %ld\n", errnum);
+ caml_raise_sys_error(caml_copy_string_of_utf16(buffer));
+}
+
+#endif
/* */
/**************************************************************************/
+#define CAML_INTERNALS
+
#include <caml/mlvalues.h>
#include <caml/alloc.h>
+#include <caml/osdeps.h>
+#include <caml/memory.h>
#include "unixsupport.h"
#include <fcntl.h>
int fileaccess, createflags, fileattrib, filecreate, sharemode, cloexec;
SECURITY_ATTRIBUTES attr;
HANDLE h;
+ wchar_t * wpath;
caml_unix_check_path(path, "open");
fileaccess = caml_convert_flag_list(flags, open_access_flags);
: cloexec & KEEPEXEC ? TRUE
: !unix_cloexec_default;
- h = CreateFile(String_val(path), fileaccess,
+ wpath = caml_stat_strdup_to_utf16(String_val(path));
+ h = CreateFile(wpath, fileaccess,
sharemode, &attr,
filecreate, fileattrib, NULL);
+ caml_stat_free(wpath);
if (h == INVALID_HANDLE_VALUE) {
win32_maperr(GetLastError());
uerror("open", path);
/* */
/**************************************************************************/
+#define CAML_INTERNALS
+
#include <caml/mlvalues.h>
#include <caml/memory.h>
#include <caml/alloc.h>
#include <caml/fail.h>
#include <caml/signals.h>
+#include <caml/osdeps.h>
#include "unixsupport.h"
#include <errno.h>
#include <winioctl.h>
CAMLparam1(opath);
CAMLlocal1(result);
HANDLE h;
- char* path;
+ wchar_t* path;
DWORD attributes;
caml_unix_check_path(opath, "readlink");
- path = caml_strdup(String_val(opath));
+ path = caml_stat_strdup_to_utf16(String_val(opath));
caml_enter_blocking_section();
attributes = GetFileAttributes(path);
if (point->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
int cbLen = point->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(WCHAR);
int len;
- len = WideCharToMultiByte(
- CP_THREAD_ACP,
- 0,
- point->SymbolicLinkReparseBuffer.PathBuffer + point->SymbolicLinkReparseBuffer.SubstituteNameOffset / 2,
- cbLen,
- NULL,
- 0,
- NULL,
- NULL);
+ len = win_wide_char_to_multi_byte(point->SymbolicLinkReparseBuffer.PathBuffer + point->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR), cbLen, NULL, 0);
result = caml_alloc_string(len);
- WideCharToMultiByte(
- CP_THREAD_ACP,
- 0,
- point->SymbolicLinkReparseBuffer.PathBuffer + point->SymbolicLinkReparseBuffer.SubstituteNameOffset / 2,
+ win_wide_char_to_multi_byte(point->SymbolicLinkReparseBuffer.PathBuffer + point->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR),
cbLen,
String_val(result),
- len,
- NULL,
- NULL);
+ len);
CloseHandle(h);
}
else {
/* */
/**************************************************************************/
+#define CAML_INTERNALS
+
#include <stdio.h>
#include <caml/mlvalues.h>
+#include <caml/osdeps.h>
+#include <caml/memory.h>
#include "unixsupport.h"
CAMLprim value unix_rename(value path1, value path2)
{
- static int supports_MoveFileEx = -1; /* don't know yet */
+ wchar_t * wpath1, * wpath2;
BOOL ok;
caml_unix_check_path(path1, "rename");
caml_unix_check_path(path2, "rename");
- if (supports_MoveFileEx < 0) {
- OSVERSIONINFO VersionInfo;
- VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- supports_MoveFileEx =
- (GetVersionEx(&VersionInfo) != 0)
- && (VersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
- }
- if (supports_MoveFileEx > 0)
- ok = MoveFileEx(String_val(path1), String_val(path2),
- MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH |
- MOVEFILE_COPY_ALLOWED);
- else
- ok = MoveFile(String_val(path1), String_val(path2));
+ wpath1 = caml_stat_strdup_to_utf16(String_val(path1));
+ wpath2 = caml_stat_strdup_to_utf16(String_val(path2));
+ ok = MoveFileEx(wpath1, wpath2,
+ MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH |
+ MOVEFILE_COPY_ALLOWED);
+ caml_stat_free(wpath1);
+ caml_stat_free(wpath2);
if (! ok) {
win32_maperr(GetLastError());
uerror("rename", path1);
/* */
/**************************************************************************/
+#define CAML_INTERNALS
+
#include <errno.h>
#include <caml/mlvalues.h>
#include <caml/memory.h>
#include <caml/alloc.h>
#include <caml/signals.h>
+#include <caml/osdeps.h>
#include "unixsupport.h"
#include "cst2constr.h"
#define _INTEGRAL_MAX_BITS 64
}
/* path allocated outside the OCaml heap */
-static int safe_do_stat(int do_lstat, int use_64, char* path, mlsize_t l, HANDLE fstat, __int64* st_ino, struct _stat64* res)
+static int safe_do_stat(int do_lstat, int use_64, wchar_t* path, HANDLE fstat, __int64* st_ino, struct _stat64* res)
{
BY_HANDLE_FILE_INFORMATION info;
int i;
- char* ptr;
+ wchar_t* ptr;
char c;
HANDLE h;
unsigned short mode;
* emulated using GetFinalPathNameByHandle, but the pre-Vista emulation is a
* bit too much effort for a simulated value, so it's simply ignored!
*/
- if (path && (ptr = strrchr(path, '.')) && (!_stricmp(ptr, ".exe") ||
- !_stricmp(ptr, ".cmd") ||
- !_stricmp(ptr, ".bat") ||
- !_stricmp(ptr, ".com"))) {
+ if (path && (ptr = wcsrchr(path, '.')) && (!_wcsicmp(ptr, L".exe") ||
+ !_wcsicmp(ptr, L".cmd") ||
+ !_wcsicmp(ptr, L".bat") ||
+ !_wcsicmp(ptr, L".com"))) {
mode |= _S_IEXEC;
}
mode |= (mode & 0700) >> 3;
return 1;
}
-static int do_stat(int do_lstat, int use_64, char* opath, mlsize_t l, HANDLE fstat, __int64* st_ino, struct _stat64* res)
+static int do_stat(int do_lstat, int use_64, char* opath, HANDLE fstat, __int64* st_ino, struct _stat64* res)
{
- char* path;
+ wchar_t* wpath;
int ret;
- path = caml_strdup(opath);
- ret = safe_do_stat(do_lstat, use_64, path, l, fstat, st_ino, res);
- caml_stat_free(path);
+ wpath = caml_stat_strdup_to_utf16(opath);
+ ret = safe_do_stat(do_lstat, use_64, wpath, fstat, st_ino, res);
+ caml_stat_free(wpath);
return ret;
}
__int64 st_ino;
caml_unix_check_path(path, "stat");
- if (!do_stat(0, 0, String_val(path), caml_string_length(path), NULL, &st_ino, &buf)) {
+ if (!do_stat(0, 0, String_val(path), NULL, &st_ino, &buf)) {
uerror("stat", path);
}
return stat_aux(0, st_ino, &buf);
__int64 st_ino;
caml_unix_check_path(path, "stat");
- if (!do_stat(0, 1, String_val(path), caml_string_length(path), NULL, &st_ino, &buf)) {
+ if (!do_stat(0, 1, String_val(path), NULL, &st_ino, &buf)) {
uerror("stat", path);
}
return stat_aux(1, st_ino, &buf);
__int64 st_ino;
caml_unix_check_path(path, "lstat");
- if (!do_stat(1, 0, String_val(path), caml_string_length(path), NULL, &st_ino, &buf)) {
+ if (!do_stat(1, 0, String_val(path), NULL, &st_ino, &buf)) {
uerror("lstat", path);
}
return stat_aux(0, st_ino, &buf);
__int64 st_ino;
caml_unix_check_path(path, "lstat");
- if (!do_stat(1, 1, String_val(path), caml_string_length(path), NULL, &st_ino, &buf)) {
+ if (!do_stat(1, 1, String_val(path), NULL, &st_ino, &buf)) {
uerror("lstat", path);
}
return stat_aux(1, st_ino, &buf);
ft = GetFileType(h) & ~FILE_TYPE_REMOTE;
switch(ft) {
case FILE_TYPE_DISK:
- if (!safe_do_stat(0, use_64, NULL, 0, Handle_val(handle), &st_ino, &buf)) {
+ if (!safe_do_stat(0, use_64, NULL, Handle_val(handle), &st_ino, &buf)) {
uerror("fstat", Nothing);
}
break;
/* */
/**************************************************************************/
+#define CAML_INTERNALS
+
/*
* Windows Vista functions enabled
*/
#include <caml/alloc.h>
#include <caml/fail.h>
#include <caml/signals.h>
+#include <caml/osdeps.h>
#include "unixsupport.h"
-typedef BOOLEAN (WINAPI *LPFN_CREATESYMBOLICLINK) (LPTSTR, LPTSTR, DWORD);
+typedef BOOLEAN (WINAPI *LPFN_CREATESYMBOLICLINK) (LPWSTR, LPWSTR, DWORD);
static LPFN_CREATESYMBOLICLINK pCreateSymbolicLink = NULL;
static int no_symlink = 0;
CAMLparam3(to_dir, osource, odest);
DWORD flags = (Bool_val(to_dir) ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0);
BOOLEAN result;
- LPTSTR source;
- LPTSTR dest;
+ LPWSTR source;
+ LPWSTR dest;
caml_unix_check_path(osource, "symlink");
caml_unix_check_path(odest, "symlink");
}
if (!pCreateSymbolicLink) {
- pCreateSymbolicLink = (LPFN_CREATESYMBOLICLINK)GetProcAddress(GetModuleHandle("kernel32"), "CreateSymbolicLinkA");
+ pCreateSymbolicLink = (LPFN_CREATESYMBOLICLINK)GetProcAddress(GetModuleHandle(L"kernel32"), "CreateSymbolicLinkW");
no_symlink = !pCreateSymbolicLink;
goto again;
}
/* Copy source and dest outside the OCaml heap */
- source = caml_strdup(String_val(osource));
- dest = caml_strdup(String_val(odest));
+ source = caml_stat_strdup_to_utf16(String_val(osource));
+ dest = caml_stat_strdup_to_utf16(String_val(odest));
caml_enter_blocking_section();
result = pCreateSymbolicLink(dest, source, flags);
/* */
/**************************************************************************/
+#define CAML_INTERNALS
+
#include <caml/mlvalues.h>
#include <caml/memory.h>
#include <caml/alloc.h>
#include <caml/signals.h>
+#include <caml/osdeps.h>
#include "unixsupport.h"
#include <process.h>
#include <stdio.h>
{
int ret;
value st;
- char *buf;
- intnat len;
+ wchar_t *buf;
caml_unix_check_path(cmd, "system");
- len = caml_string_length (cmd);
- buf = caml_stat_alloc (len + 1);
- memmove (buf, String_val (cmd), len + 1);
+ buf = caml_stat_strdup_to_utf16 (String_val (cmd));
caml_enter_blocking_section();
_flushall();
- ret = system(buf);
+ ret = _wsystem(buf);
caml_leave_blocking_section();
caml_stat_free(buf);
if (ret == -1) uerror("system", Nothing);
exit 2
external environment : unit -> string array = "unix_environment"
+(* On Win32 environment access is always considered safe. *)
+let unsafe_environment = environment
external getenv: string -> string = "caml_sys_getenv"
-(* external unsafe_getenv: string -> string = "caml_sys_unsafe_getenv" *)
+external unsafe_getenv: string -> string = "caml_sys_unsafe_getenv"
external putenv: string -> string -> unit = "unix_putenv"
type process_status =
external stat : string -> stats = "unix_stat"
external lstat : string -> stats = "unix_lstat"
external fstat : file_descr -> stats = "unix_fstat"
-let isatty fd =
- match (fstat fd).st_kind with S_CHR -> true | _ -> false
+external isatty : file_descr -> bool = "unix_isatty"
(* Operations on file names *)
external fstat : file_descr -> stats = "unix_fstat_64"
end
+(* Mapping files into memory *)
+
+external map_internal:
+ file_descr -> ('a, 'b) CamlinternalBigarray.kind
+ -> 'c CamlinternalBigarray.layout
+ -> bool -> int array -> int64
+ -> ('a, 'b, 'c) CamlinternalBigarray.genarray
+ = "caml_unix_map_file_bytecode" "caml_unix_map_file"
+
+let map_file fd ?(pos=0L) kind layout shared dims =
+ map_internal fd kind layout shared dims pos
+
(* File permissions and ownership *)
type access_permission =
external readlink : string -> string = "unix_readlink"
external symlink_stub : bool -> string -> string -> unit = "unix_symlink"
+(* See https://caml.inria.fr/mantis/view.php?id=7564.
+ The Windows API used to create symbolic links does not normalize the target
+ of a symbolic link, so we do it here. Note that we cannot use the native
+ Windows call GetFullPathName to do this because we need relative paths to
+ stay relative. *)
+let normalize_slashes path =
+ if String.length path >= 4 && path.[0] = '\\' && path.[1] = '\\' && path.[2] = '?' && path.[3] = '\\' then
+ path
+ else
+ String.init (String.length path) (fun i -> match path.[i] with '/' -> '\\' | c -> c)
+
let symlink ?to_dir source dest =
let to_dir =
match to_dir with
with _ ->
false
in
- symlink_stub to_dir source dest
+ let source = normalize_slashes source in
+ symlink_stub to_dir source dest
external has_symlink : unit -> bool = "unix_has_symlink"
| MSG_DONTROUTE
| MSG_PEEK
-external socket :
+external socket :
?cloexec: bool -> socket_domain -> socket_type -> int -> file_descr
= "unix_socket"
let socketpair ?cloexec:_ _dom _ty _proto = invalid_arg "Unix.socketpair not implemented"
with e ->
close out_read; close out_write;
close in_read; close in_write;
- close err_read; close err_write;
+ close err_read; close err_write;
raise e
end;
close out_read;
return err;
}
-void unix_error(int errcode, char *cmdname, value cmdarg)
+void unix_error(int errcode, const char *cmdname, value cmdarg)
{
value res;
value name = Val_unit, err = Val_unit, arg = Val_unit;
caml_raise(res);
}
-void uerror(char * cmdname, value cmdarg)
+void uerror(const char * cmdname, value cmdarg)
{
unix_error(errno, cmdname, cmdarg);
}
-void caml_unix_check_path(value path, char * cmdname)
+void caml_unix_check_path(value path, const char * cmdname)
{
if (! caml_string_is_c_safe(path)) unix_error(ENOENT, cmdname, path);
}
extern value unix_error_of_code (int errcode);
CAMLnoreturn_start
-extern void unix_error (int errcode, char * cmdname, value arg)
+extern void unix_error (int errcode, const char * cmdname, value arg)
CAMLnoreturn_end;
CAMLnoreturn_start
-extern void uerror (char * cmdname, value arg)
+extern void uerror (const char * cmdname, value arg)
CAMLnoreturn_end;
-extern void caml_unix_check_path(value path, char * cmdname);
+extern void caml_unix_check_path(value path, const char * cmdname);
extern value unix_freeze_buffer (value);
-extern char ** cstringvect(value arg, char * cmdname);
+extern wchar_t ** cstringvect(value arg, char * cmdname);
+extern void cstringvect_free(wchar_t **);
extern int unix_cloexec_default;
extern int unix_cloexec_p(value cloexec);
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
#endif
+#define EXECV_CAST (const char_os * const *)
+
#endif /* CAML_UNIXSUPPORT_H */
/* */
/**************************************************************************/
+#define CAML_INTERNALS
+
#include <caml/mlvalues.h>
#include <caml/memory.h>
#include <errno.h>
#include <caml/alloc.h>
#include <caml/fail.h>
+#include <caml/osdeps.h>
#include "unixsupport.h"
CAMLprim value win_findfirst(value name)
{
HANDLE h;
value v;
- WIN32_FIND_DATA fileinfo;
+ WIN32_FIND_DATAW fileinfo;
value valname = Val_unit;
value valh = Val_unit;
+ wchar_t * wname;
caml_unix_check_path(name, "opendir");
Begin_roots2 (valname,valh);
- h = FindFirstFile(String_val(name),&fileinfo);
+ wname = caml_stat_strdup_to_utf16(String_val(name));
+ h = FindFirstFile(wname,&fileinfo);
+ caml_stat_free(wname);
if (h == INVALID_HANDLE_VALUE) {
DWORD err = GetLastError();
if (err == ERROR_NO_MORE_FILES)
uerror("opendir", Nothing);
}
}
- valname = caml_copy_string(fileinfo.cFileName);
+ valname = caml_copy_string_of_utf16(fileinfo.cFileName);
valh = win_alloc_handle(h);
v = caml_alloc_small(2, 0);
Field(v,0) = valname;
CAMLprim value win_findnext(value valh)
{
- WIN32_FIND_DATA fileinfo;
+ WIN32_FIND_DATAW fileinfo;
BOOL retcode;
retcode = FindNextFile(Handle_val(valh), &fileinfo);
uerror("readdir", Nothing);
}
}
- return caml_copy_string(fileinfo.cFileName);
+ return caml_copy_string_of_utf16(fileinfo.cFileName);
}
CAMLprim value win_findclose(value valh)
#define LIST_NEXT(T, e) ((T)(list_next((LPLIST)(e))))
-/* Get number of element */
+/* Get the number of elements */
int list_length (LPLIST);
-/* Concat two list. */
+/* Concatenate two lists */
LPLIST list_concat (LPLIST, LPLIST);
#endif /* _WINLIST_H */
retcode = WaitForSingleObject(pid_req, INFINITE);
if (retcode == WAIT_FAILED) err = GetLastError();
caml_leave_blocking_section();
- if (err) {
- win32_maperr(err);
- uerror("waitpid", Nothing);
- }
+ } else {
+ /* GPR#1155: we don't rely solely on GetExitCodeProcess to
+ determine whether the process has terminated or not. This is
+ because GetExitCodeProcess might return that the process has
+ terminated before the resources associated with the process are
+ released. This can be a problem since by default one cannot
+ delete a file or directory that is still in use. */
+ retcode = WaitForSingleObject(pid_req, 0);
+ if (retcode == WAIT_TIMEOUT)
+ return alloc_process_status((HANDLE) 0, 0);
+ if (retcode == WAIT_FAILED) err = GetLastError();
+ }
+ if (err) {
+ win32_maperr(err);
+ uerror("waitpid", Nothing);
}
if (! GetExitCodeProcess(pid_req, &status)) {
win32_maperr(GetLastError());
/* Pool of worker threads.
*
- * These functions help to manage a pool of worker thread and submit task to
+ * These functions help to manage a pool of worker threads and submit task to
* the pool. It helps to reduce the number of thread creation.
*
* Each worker are started in alertable wait state and jobs are submitted as
* This function will be called using the data following:
* - hStop must be watched for change, since it represents an external command
* to stop the call. This event is shared through the WORKER structure, which
- * can be access throuhg worker_job_event_done.
+ * can be accessed through worker_job_event_done.
* - data is user provided data for the function.
*/
typedef void (*WORKERFUNC) (HANDLE, void *);
| Ptyp_constr(longident, lst) ->
Ptyp_constr(longident, List.map loop lst)
| Ptyp_object (lst, o) ->
- Ptyp_object
- (List.map (fun (s, attrs, t) -> (s, attrs, loop t)) lst, o)
+ Ptyp_object (List.map loop_object_field lst, o)
| Ptyp_class (longident, lst) ->
Ptyp_class (longident, List.map loop lst)
| Ptyp_alias(core_type, string) ->
Rtag(label,attrs,flag,List.map loop lst)
| Rinherit t ->
Rinherit (loop t)
+ and loop_object_field =
+ function
+ | Otag(label, attrs, t) ->
+ Otag(label, attrs, loop t)
+ | Oinherit t ->
+ Oinherit (loop t)
in
loop t
let let_ ?loc ?attrs a b c = mk ?loc ?attrs (Pcl_let (a, b, c))
let constraint_ ?loc ?attrs a b = mk ?loc ?attrs (Pcl_constraint (a, b))
let extension ?loc ?attrs a = mk ?loc ?attrs (Pcl_extension a)
+ let open_ ?loc ?attrs a b c = mk ?loc ?attrs (Pcl_open (a, b, c))
end
module Cty = struct
let signature ?loc ?attrs a = mk ?loc ?attrs (Pcty_signature a)
let arrow ?loc ?attrs a b c = mk ?loc ?attrs (Pcty_arrow (a, b, c))
let extension ?loc ?attrs a = mk ?loc ?attrs (Pcty_extension a)
+ let open_ ?loc ?attrs a b c = mk ?loc ?attrs (Pcty_open (a, b, c))
end
module Ctf = struct
type loc = Location.t
type attrs = attribute list
-(** {2 Default locations} *)
+(** {1 Default locations} *)
val default_loc: loc ref
(** Default value for all optional location arguments. *)
(** Set the [default_loc] within the scope of the execution
of the provided function. *)
-(** {2 Constants} *)
+(** {1 Constants} *)
module Const : sig
val char : char -> constant
val float : ?suffix:char -> string -> constant
end
-(** {2 Core language} *)
+(** {1 Core language} *)
(** Type expressions *)
module Typ :
-> core_type
val tuple: ?loc:loc -> ?attrs:attrs -> core_type list -> core_type
val constr: ?loc:loc -> ?attrs:attrs -> lid -> core_type list -> core_type
- val object_: ?loc:loc -> ?attrs:attrs ->
- (str * attributes * core_type) list -> closed_flag ->
- core_type
+ val object_: ?loc:loc -> ?attrs:attrs -> object_field list
+ -> closed_flag -> core_type
val class_: ?loc:loc -> ?attrs:attrs -> lid -> core_type list -> core_type
val alias: ?loc:loc -> ?attrs:attrs -> core_type -> string -> core_type
val variant: ?loc:loc -> ?attrs:attrs -> row_field list -> closed_flag
str -> lid -> extension_constructor
end
-(** {2 Module language} *)
+(** {1 Module language} *)
(** Module type expressions *)
module Mty:
end
-(** {2 Class language} *)
+(** {1 Class language} *)
(** Class type expressions *)
module Cty:
val arrow: ?loc:loc -> ?attrs:attrs -> arg_label -> core_type ->
class_type -> class_type
val extension: ?loc:loc -> ?attrs:attrs -> extension -> class_type
+ val open_: ?loc:loc -> ?attrs:attrs -> override_flag -> lid -> class_type
+ -> class_type
end
(** Class type fields *)
val constraint_: ?loc:loc -> ?attrs:attrs -> class_expr -> class_type ->
class_expr
val extension: ?loc:loc -> ?attrs:attrs -> extension -> class_expr
+ val open_: ?loc:loc -> ?attrs:attrs -> override_flag -> lid -> class_expr
+ -> class_expr
end
(** Class fields *)
sub.attributes sub attrs; List.iter (sub.typ sub) tl
| Rinherit t -> sub.typ sub t
+ let object_field sub = function
+ | Otag (_, attrs, t) ->
+ sub.attributes sub attrs; sub.typ sub t
+ | Oinherit t -> sub.typ sub t
+
let iter sub {ptyp_desc = desc; ptyp_loc = loc; ptyp_attributes = attrs} =
sub.location sub loc;
sub.attributes sub attrs;
| Ptyp_tuple tyl -> List.iter (sub.typ sub) tyl
| Ptyp_constr (lid, tl) ->
iter_loc sub lid; List.iter (sub.typ sub) tl
- | Ptyp_object (l, _o) ->
- let f (_, a, t) = sub.attributes sub a; sub.typ sub t in
- List.iter f l
+ | Ptyp_object (ol, _o) ->
+ List.iter (object_field sub) ol
| Ptyp_class (lid, tl) ->
iter_loc sub lid; List.iter (sub.typ sub) tl
| Ptyp_alias (t, _) -> sub.typ sub t
| Pcty_arrow (_lab, t, ct) ->
sub.typ sub t; sub.class_type sub ct
| Pcty_extension x -> sub.extension sub x
+ | Pcty_open (_ovf, lid, e) ->
+ iter_loc sub lid; sub.class_type sub e
let iter_field sub {pctf_desc = desc; pctf_loc = loc; pctf_attributes = attrs}
=
iter_loc sub lid; sub.type_declaration sub d
| Pwith_module (lid, lid2) ->
iter_loc sub lid; iter_loc sub lid2
- | Pwith_typesubst d -> sub.type_declaration sub d
+ | Pwith_typesubst (lid, d) ->
+ iter_loc sub lid; sub.type_declaration sub d
| Pwith_modsubst (s, lid) ->
iter_loc sub s; iter_loc sub lid
| Pcl_constraint (ce, ct) ->
sub.class_expr sub ce; sub.class_type sub ct
| Pcl_extension x -> sub.extension sub x
+ | Pcl_open (_ovf, lid, e) ->
+ iter_loc sub lid; sub.class_expr sub e
let iter_kind sub = function
| Cfk_concrete (_o, e) -> sub.expr sub e
open Parsetree
-(** {2 A generic Parsetree iterator} *)
+(** {1 A generic Parsetree iterator} *)
type iterator = {
attribute: iterator -> attribute -> unit;
let row_field sub = function
| Rtag (l, attrs, b, tl) ->
- Rtag (l, sub.attributes sub attrs, b, List.map (sub.typ sub) tl)
+ Rtag (map_loc sub l, sub.attributes sub attrs,
+ b, List.map (sub.typ sub) tl)
| Rinherit t -> Rinherit (sub.typ sub t)
+ let object_field sub = function
+ | Otag (l, attrs, t) ->
+ Otag (map_loc sub l, sub.attributes sub attrs, sub.typ sub t)
+ | Oinherit t -> Oinherit (sub.typ sub t)
+
let map sub {ptyp_desc = desc; ptyp_loc = loc; ptyp_attributes = attrs} =
let open Typ in
let loc = sub.location sub loc in
| Ptyp_constr (lid, tl) ->
constr ~loc ~attrs (map_loc sub lid) (List.map (sub.typ sub) tl)
| Ptyp_object (l, o) ->
- let f (s, a, t) =
- (map_loc sub s, sub.attributes sub a, sub.typ sub t) in
- object_ ~loc ~attrs (List.map f l) o
+ object_ ~loc ~attrs (List.map (object_field sub) l) o
| Ptyp_class (lid, tl) ->
class_ ~loc ~attrs (map_loc sub lid) (List.map (sub.typ sub) tl)
| Ptyp_alias (t, s) -> alias ~loc ~attrs (sub.typ sub t) s
| Pcty_arrow (lab, t, ct) ->
arrow ~loc ~attrs lab (sub.typ sub t) (sub.class_type sub ct)
| Pcty_extension x -> extension ~loc ~attrs (sub.extension sub x)
+ | Pcty_open (ovf, lid, ct) ->
+ open_ ~loc ~attrs ovf (map_loc sub lid) (sub.class_type sub ct)
let map_field sub {pctf_desc = desc; pctf_loc = loc; pctf_attributes = attrs}
=
Pwith_type (map_loc sub lid, sub.type_declaration sub d)
| Pwith_module (lid, lid2) ->
Pwith_module (map_loc sub lid, map_loc sub lid2)
- | Pwith_typesubst d -> Pwith_typesubst (sub.type_declaration sub d)
+ | Pwith_typesubst (lid, d) ->
+ Pwith_typesubst (map_loc sub lid, sub.type_declaration sub d)
| Pwith_modsubst (s, lid) ->
Pwith_modsubst (map_loc sub s, map_loc sub lid)
| Pcl_constraint (ce, ct) ->
constraint_ ~loc ~attrs (sub.class_expr sub ce) (sub.class_type sub ct)
| Pcl_extension x -> extension ~loc ~attrs (sub.extension sub x)
+ | Pcl_open (ovf, lid, ce) ->
+ open_ ~loc ~attrs ovf (map_loc sub lid) (sub.class_expr sub ce)
let map_kind sub = function
| Cfk_concrete (o, e) -> Cfk_concrete (o, sub.expr sub e)
lid "open_modules", make_list make_string !Clflags.open_modules;
lid "for_package", make_option make_string !Clflags.for_package;
lid "debug", make_bool !Clflags.debug;
+ lid "use_threads", make_bool !Clflags.use_threads;
+ lid "use_vmthreads", make_bool !Clflags.use_vmthreads;
get_cookies ()
]
in
Clflags.for_package := get_option get_string payload
| "debug" ->
Clflags.debug := get_bool payload
+ | "use_threads" ->
+ Clflags.use_threads := get_bool payload
+ | "use_vmthreads" ->
+ Clflags.use_vmthreads := get_bool payload
| "cookies" ->
let l = get_list (get_pair get_string (fun x -> x)) payload in
cookies :=
let ppx_context = PpxContext.make
-let ext_of_exn exn =
+let extension_of_exn exn =
match error_of_exn exn with
- | Some error -> extension_of_error error
+ | Some (`Ok error) -> extension_of_error error
+ | Some `Already_displayed -> { loc = Location.none; txt = "ocaml.error" }, PStr []
| None -> raise exn
let mapper = mapper () in
mapper.structure mapper ast
with exn ->
- [{pstr_desc = Pstr_extension (ext_of_exn exn, []);
+ [{pstr_desc = Pstr_extension (extension_of_exn exn, []);
pstr_loc = Location.none}]
in
let fields = PpxContext.update_cookies fields in
let mapper = mapper () in
mapper.signature mapper ast
with exn ->
- [{psig_desc = Psig_extension (ext_of_exn exn, []);
+ [{psig_desc = Psig_extension (extension_of_exn exn, []);
psig_loc = Location.none}]
in
let fields = PpxContext.update_cookies fields in
let mapper () =
try mapper (Array.to_list (Array.sub a 1 (n - 3)))
with exn ->
- (* PR #6463 *)
+ (* PR#6463 *)
let f _ _ = raise exn in
{default_mapper with structure = f; signature = f}
in
open Parsetree
-(** {2 A generic Parsetree mapper} *)
+(** {1 A generic Parsetree mapper} *)
type mapper = {
attribute: mapper -> attribute -> attribute;
val default_mapper: mapper
(** A default mapper, which implements a "deep identity" mapping. *)
-(** {2 Apply mappers to compilation units} *)
+(** {1 Apply mappers to compilation units} *)
val tool_name: unit -> string
(** Can be used within a ppx preprocessor to know which tool is
function implements proper error reporting for uncaught
exceptions. *)
-(** {2 Registration API} *)
+(** {1 Registration API} *)
val register_function: (string -> (string list -> mapper) -> unit) ref
the ppx driver. *)
-(** {2 Convenience functions to write mappers} *)
+(** {1 Convenience functions to write mappers} *)
val map_opt: ('a -> 'b) -> 'a option -> 'b option
inserted in a generated Parsetree. The compiler will be
responsible for reporting the warning. *)
-(** {2 Helper functions to call external mappers} *)
+(** {1 Helper functions to call external mappers} *)
val add_ppx_context_str:
tool_name:string -> Parsetree.structure -> Parsetree.structure
restore:bool -> Parsetree.signature -> Parsetree.signature
(** Same as [drop_ppx_context_str], but for signatures. *)
-(** {2 Cookies} *)
+(** {1 Cookies} *)
(** Cookies are used to pass information from a ppx processor to
a further invocation of itself, when called from the OCaml
string_of_cst c
| _ -> None
+let string_of_opt_payload p =
+ match string_of_payload p with
+ | Some s -> s
+ | None -> ""
+
let rec error_of_extension ext =
match ext with
| ({txt = ("ocaml.error"|"error") as txt; loc}, p) ->
| [] -> []
in
begin match p with
+ | PStr [] -> raise Location.Already_displayed_error
| PStr({pstr_desc=Pstr_eval
({pexp_desc=Pexp_constant(Pconst_string(msg,_))}, _)}::
{pstr_desc=Pstr_eval
| ({txt; loc}, _) ->
Location.errorf ~loc "Uninterpreted extension '%s'." txt
+let cat s1 s2 =
+ if s2 = "" then s1 else s1 ^ "\n" ^ s2
+
let rec deprecated_of_attrs = function
| [] -> None
| ({txt = "ocaml.deprecated"|"deprecated"; _}, p) :: _ ->
- begin match string_of_payload p with
- | Some txt -> Some txt
- | None -> Some ""
- end
+ Some (string_of_opt_payload p)
| _ :: tl -> deprecated_of_attrs tl
let check_deprecated loc attrs s =
match deprecated_of_attrs attrs with
| None -> ()
- | Some "" -> Location.prerr_warning loc (Warnings.Deprecated s)
- | Some txt ->
- Location.prerr_warning loc (Warnings.Deprecated (s ^ "\n" ^ txt))
+ | Some txt -> Location.deprecated loc (cat s txt)
-let rec check_deprecated_mutable loc attrs s =
- match attrs with
- | [] -> ()
+let check_deprecated_inclusion ~def ~use loc attrs1 attrs2 s =
+ match deprecated_of_attrs attrs1, deprecated_of_attrs attrs2 with
+ | None, _ | Some _, Some _ -> ()
+ | Some txt, None -> Location.deprecated ~def ~use loc (cat s txt)
+
+let rec deprecated_mutable_of_attrs = function
+ | [] -> None
| ({txt = "ocaml.deprecated_mutable"|"deprecated_mutable"; _}, p) :: _ ->
- let txt =
- match string_of_payload p with
- | Some txt -> "\n" ^ txt
- | None -> ""
- in
- Location.prerr_warning loc
- (Warnings.Deprecated (Printf.sprintf "mutating field %s%s"
- s txt))
- | _ :: tl -> check_deprecated_mutable loc tl s
+ Some (string_of_opt_payload p)
+ | _ :: tl -> deprecated_mutable_of_attrs tl
+
+let check_deprecated_mutable loc attrs s =
+ match deprecated_mutable_of_attrs attrs with
+ | None -> ()
+ | Some txt ->
+ Location.deprecated loc (Printf.sprintf "mutating field %s" (cat s txt))
+
+let check_deprecated_mutable_inclusion ~def ~use loc attrs1 attrs2 s =
+ match deprecated_mutable_of_attrs attrs1,
+ deprecated_mutable_of_attrs attrs2
+ with
+ | None, _ | Some _, Some _ -> ()
+ | Some txt, None ->
+ Location.deprecated ~def ~use loc
+ (Printf.sprintf "mutating field %s" (cat s txt))
let rec deprecated_of_sig = function
| {psig_desc = Psig_attribute a} :: tl ->
| _ -> None
-let emit_external_warnings =
- (* Note: this is run as a preliminary pass when type-checking an
- interface or implementation. This allows to cover all kinds of
- attributes, but the drawback is that it doesn't take local
- configuration of warnings (with '@@warning'/'@@warnerror'
- attributes) into account. We should rather check for
- 'ppwarning' attributes during the actual type-checking, making
- sure to cover all contexts (easier and more ugly alternative:
- duplicate here the logic which control warnings locally). *)
- let open Ast_iterator in
- {
- default_iterator with
- attribute = (fun _ a ->
- match a with
- | {txt="ocaml.ppwarning"|"ppwarning"},
- PStr[{pstr_desc=Pstr_eval({pexp_desc=Pexp_constant
- (Pconst_string (s, _))},_);
- pstr_loc}] ->
- Location.prerr_warning pstr_loc (Warnings.Preprocessor s)
- | _ -> ()
- )
- }
-
-
-let warning_scope = ref []
-
-let warning_enter_scope () =
- warning_scope := (Warnings.backup ()) :: !warning_scope
-let warning_leave_scope () =
- match !warning_scope with
- | [] -> assert false
- | hd :: tl ->
- Warnings.restore hd;
- warning_scope := tl
-
-let warning_attribute attrs =
+let warning_attribute ?(ppwarning = true) =
let process loc txt errflag payload =
match string_of_payload payload with
| Some s ->
(Warnings.Attribute_payload
(txt, "A single string literal is expected"))
in
- List.iter
- (function
- | ({txt = ("ocaml.warning"|"warning") as txt; loc}, payload) ->
- process loc txt false payload
- | ({txt = ("ocaml.warnerror"|"warnerror") as txt; loc}, payload) ->
- process loc txt true payload
- | _ ->
- ()
- )
- attrs
-
-let with_warning_attribute attrs f =
+ function
+ | ({txt = ("ocaml.warning"|"warning") as txt; loc}, payload) ->
+ process loc txt false payload
+ | ({txt = ("ocaml.warnerror"|"warnerror") as txt; loc}, payload) ->
+ process loc txt true payload
+ | {txt="ocaml.ppwarning"|"ppwarning"},
+ PStr[{pstr_desc=Pstr_eval({pexp_desc=Pexp_constant
+ (Pconst_string (s, _))},_);
+ pstr_loc}] when ppwarning ->
+ Location.prerr_warning pstr_loc (Warnings.Preprocessor s)
+ | _ ->
+ ()
+
+let warning_scope ?ppwarning attrs f =
+ let prev = Warnings.backup () in
try
- warning_enter_scope ();
- warning_attribute attrs;
+ List.iter (warning_attribute ?ppwarning) (List.rev attrs);
let ret = f () in
- warning_leave_scope ();
+ Warnings.restore prev;
ret
with exn ->
- warning_leave_scope ();
+ Warnings.restore prev;
raise exn
val check_deprecated: Location.t -> Parsetree.attributes -> string -> unit
+val check_deprecated_inclusion:
+ def:Location.t -> use:Location.t -> Location.t -> Parsetree.attributes ->
+ Parsetree.attributes -> string -> unit
val deprecated_of_attrs: Parsetree.attributes -> string option
val deprecated_of_sig: Parsetree.signature -> string option
val deprecated_of_str: Parsetree.structure -> string option
val check_deprecated_mutable:
Location.t -> Parsetree.attributes -> string -> unit
+val check_deprecated_mutable_inclusion:
+ def:Location.t -> use:Location.t -> Location.t -> Parsetree.attributes ->
+ Parsetree.attributes -> string -> unit
val error_of_extension: Parsetree.extension -> Location.error
-val warning_enter_scope: unit -> unit
-val warning_leave_scope: unit -> unit
-val warning_attribute: Parsetree.attributes -> unit
-val with_warning_attribute: Parsetree.attributes -> (unit -> 'a) -> 'a
+val warning_attribute: ?ppwarning:bool -> Parsetree.attribute -> unit
+ (** Apply warning settings from the specified attribute.
+ "ocaml.warning"/"ocaml.warnerror" (and variants without the prefix)
+ are processed and other attributes are ignored.
-val emit_external_warnings: Ast_iterator.iterator
+ Also implement ocaml.ppwarning (unless ~ppwarning:false is
+ passed).
+ *)
+
+val warning_scope:
+ ?ppwarning:bool ->
+ Parsetree.attributes -> (unit -> 'a) -> 'a
+ (** Execute a function in a new scope for warning settings. This
+ means that the effect of any call to [warning_attribute] during
+ the execution of this function will be discarded after
+ execution.
+
+ The function also takes a list of attributes which are processed
+ with [warning_attribute] in the fresh scope before the function
+ is executed.
+ *)
val warn_on_literal_pattern: Parsetree.attributes -> bool
val explicit_arity: Parsetree.attributes -> bool
open Longident
open Parsetree
+let pp_deps = ref []
+
module StringSet = Set.Make(struct type t = string let compare = compare end)
module StringMap = Map.Make(String)
| Ptyp_arrow(_, t1, t2) -> add_type bv t1; add_type bv t2
| Ptyp_tuple tl -> List.iter (add_type bv) tl
| Ptyp_constr(c, tl) -> add bv c; List.iter (add_type bv) tl
- | Ptyp_object (fl, _) -> List.iter (fun (_, _, t) -> add_type bv t) fl
+ | Ptyp_object (fl, _) ->
+ List.iter
+ (function Otag (_, _, t) -> add_type bv t
+ | Oinherit t -> add_type bv t) fl
| Ptyp_class(c, tl) -> add bv c; List.iter (add_type bv) tl
| Ptyp_alias(t, _) -> add_type bv t
| Ptyp_variant(fl, _, _) ->
| Pcty_arrow(_, ty1, cty2) ->
add_type bv ty1; add_class_type bv cty2
| Pcty_extension e -> handle_extension e
+ | Pcty_open (_ovf, m, e) ->
+ let bv = open_module bv m.txt in add_class_type bv e
and add_class_type_field bv pctf =
match pctf.pctf_desc with
(function
| Pwith_type (_, td) -> add_type_declaration bv td
| Pwith_module (_, lid) -> addmodule bv lid
- | Pwith_typesubst td -> add_type_declaration bv td
+ | Pwith_typesubst (_, td) -> add_type_declaration bv td
| Pwith_modsubst (_, lid) -> addmodule bv lid
)
cstrl
| Pcl_constraint(ce, ct) ->
add_class_expr bv ce; add_class_type bv ct
| Pcl_extension e -> handle_extension e
+ | Pcl_open (_ovf, m, e) ->
+ let bv = open_module bv m.txt in add_class_expr bv e
and add_class_field bv pcf =
match pcf.pcf_desc with
val free_structure_names : StringSet.t ref
+(* dependencies found by preprocessing tools (plugins) *)
+val pp_deps : string list ref
+
val open_module : bound_map -> Longident.t -> bound_map
val add_use_file : bound_map -> Parsetree.toplevel_phrase list -> unit
| None | Some {ds_body=""; _} -> attrs
| Some ds -> attrs @ [info_attr ds]
-(* Docstrings not attached to a specifc item *)
+(* Docstrings not attached to a specific item *)
type text = docstring list
(** Emit warnings for unattached and ambiguous docstrings *)
val warn_bad_docstrings : unit -> unit
-(** {3 Docstrings} *)
+(** {2 Docstrings} *)
(** Documentation comments *)
type docstring
(** Get the location of a docstring *)
val docstring_loc : docstring -> Location.t
-(** {3 Set functions}
+(** {2 Set functions}
These functions are used by the lexer to associate docstrings to
the locations of tokens. *)
(** Docstrings immediately preceding the token which follows this one *)
val set_post_extra_docstrings : Lexing.position -> docstring list -> unit
-(** {3 Items}
+(** {2 Items}
The {!docs} type represents documentation attached to an item. *)
two positions (for ambiguity warnings) *)
val mark_rhs_docs : int -> int -> unit
-(** {3 Fields and constructors}
+(** {2 Fields and constructors}
The {!info} type represents documentation attached to a field or
constructor. *)
(** Fetch the field info following the symbol at a given position. *)
val rhs_info : int -> info
-(** {3 Unattached comments}
+(** {2 Unattached comments}
The {!text} type represents documentation which is not attached to
anything. *)
val rhs_text : int -> text
val rhs_text_lazy : int -> text Lazy.t
-(** {3 Extra text}
+(** {2 Extra text}
There may be additional text attached to the delimiters of a block
(e.g. [struct] and [end]). This is fetched by the following
(* To buffer string literals *)
-let initial_string_buffer = Bytes.create 256
-let string_buff = ref initial_string_buffer
-let string_index = ref 0
-
-let reset_string_buffer () =
- string_buff := initial_string_buffer;
- string_index := 0
-
-let store_string_char c =
- if !string_index >= Bytes.length !string_buff then begin
- let new_buff = Bytes.create (Bytes.length (!string_buff) * 2) in
- Bytes.blit !string_buff 0 new_buff 0 (Bytes.length !string_buff);
- string_buff := new_buff
- end;
- Bytes.unsafe_set !string_buff !string_index c;
- incr string_index
-
-let store_string s =
- for i = 0 to String.length s - 1 do
- store_string_char s.[i];
- done
-
-let store_lexeme lexbuf =
- store_string (Lexing.lexeme lexbuf)
-
-let get_stored_string () =
- let s = Bytes.sub_string !string_buff 0 !string_index in
- string_buff := initial_string_buffer;
- s
+let string_buffer = Buffer.create 256
+let reset_string_buffer () = Buffer.reset string_buffer
+let get_stored_string () = Buffer.contents string_buffer
+
+let store_string_char c = Buffer.add_char string_buffer c
+let store_string_utf_8_uchar u = Buffer.add_utf_8_uchar string_buffer u
+let store_string s = Buffer.add_string string_buffer s
+let store_lexeme lexbuf = store_string (Lexing.lexeme lexbuf)
(* To store the position of the beginning of a string and comment *)
let string_start_loc = ref Location.none;;
let store_escaped_char lexbuf c =
if in_comment () then store_lexeme lexbuf else store_string_char c
+let store_escaped_uchar lexbuf u =
+ if in_comment () then store_lexeme lexbuf else store_string_utf_8_uchar u
+
let with_comment_buffer comment lexbuf =
let start_loc = Location.curr lexbuf in
comment_start_loc := [start_loc];
(* To translate escape sequences *)
+let hex_digit_value d = (* assert (d in '0'..'9' 'a'..'f' 'A'..'F') *)
+ let d = Char.code d in
+ if d >= 97 then d - 87 else
+ if d >= 65 then d - 55 else
+ d - 48
+
+let hex_num_value lexbuf ~first ~last =
+ let rec loop acc i = match i > last with
+ | true -> acc
+ | false ->
+ let value = hex_digit_value (Lexing.lexeme_char lexbuf i) in
+ loop (16 * acc + value) (i + 1)
+ in
+ loop 0 first
+
let char_for_backslash = function
| 'n' -> '\010'
| 'r' -> '\013'
Char.chr c
let char_for_hexadecimal_code lexbuf i =
- let d1 = Char.code (Lexing.lexeme_char lexbuf i) in
- let val1 = if d1 >= 97 then d1 - 87
- else if d1 >= 65 then d1 - 55
- else d1 - 48
- in
- let d2 = Char.code (Lexing.lexeme_char lexbuf (i+1)) in
- let val2 = if d2 >= 97 then d2 - 87
- else if d2 >= 65 then d2 - 55
- else d2 - 48
+ let byte = hex_num_value lexbuf ~first:i ~last:(i+1) in
+ Char.chr byte
+
+let uchar_for_uchar_escape lexbuf =
+ let err e =
+ raise
+ (Error (Illegal_escape (Lexing.lexeme lexbuf ^ e), Location.curr lexbuf))
in
- Char.chr (val1 * 16 + val2)
+ let len = Lexing.lexeme_end lexbuf - Lexing.lexeme_start lexbuf in
+ let first = 3 (* skip opening \u{ *) in
+ let last = len - 2 (* skip closing } *) in
+ let digit_count = last - first + 1 in
+ match digit_count > 6 with
+ | true -> err ", too many digits, expected 1 to 6 hexadecimal digits"
+ | false ->
+ let cp = hex_num_value lexbuf ~first ~last in
+ if Uchar.is_valid cp then Uchar.unsafe_of_int cp else
+ err (", " ^ Printf.sprintf "%X" cp ^ " is not a Unicode scalar value")
(* recover the name from a LABEL or OPTLABEL token *)
(* Warn about Latin-1 characters used in idents *)
let warn_latin1 lexbuf =
- Location.prerr_warning (Location.curr lexbuf)
- (Warnings.Deprecated "ISO-Latin1 characters in identifiers")
-;;
+ Location.deprecated (Location.curr lexbuf)"ISO-Latin1 characters in identifiers"
let handle_docstrings = ref true
let comment_list = ref []
['A'-'Z' 'a'-'z' '_' '\192'-'\214' '\216'-'\246' '\248'-'\255' '\'' '0'-'9']
let symbolchar =
['!' '$' '%' '&' '*' '+' '-' '.' '/' ':' '<' '=' '>' '?' '@' '^' '|' '~']
+let dotsymbolchar =
+ ['!' '$' '%' '&' '*' '+' '-' '/' ':' '=' '>' '?' '@' '^' '|' '~']
let decimal_literal =
['0'-'9'] ['0'-'9' '_']*
+let hex_digit =
+ ['0'-'9' 'A'-'F' 'a'-'f']
let hex_literal =
'0' ['x' 'X'] ['0'-'9' 'A'-'F' 'a'-'f']['0'-'9' 'A'-'F' 'a'-'f' '_']*
let oct_literal =
| "->" { MINUSGREATER }
| "." { DOT }
| ".." { DOTDOT }
+ | "." (dotsymbolchar symbolchar* as s) { DOTOP s }
| ":" { COLON }
| "::" { COLONCOLON }
| ":=" { COLONEQUAL }
"(*"
{ comment_start_loc := (Location.curr lexbuf) :: !comment_start_loc;
store_lexeme lexbuf;
- comment lexbuf;
+ comment lexbuf
}
| "*)"
{ match !comment_start_loc with
| [_] -> comment_start_loc := []; Location.curr lexbuf
| _ :: l -> comment_start_loc := l;
store_lexeme lexbuf;
- comment lexbuf;
+ comment lexbuf
}
| "\""
{
| '\\' 'x' ['0'-'9' 'a'-'f' 'A'-'F'] ['0'-'9' 'a'-'f' 'A'-'F']
{ store_escaped_char lexbuf (char_for_hexadecimal_code lexbuf 2);
string lexbuf }
+ | '\\' 'u' '{' hex_digit+ '}'
+ { store_escaped_uchar lexbuf (uchar_for_uchar_escape lexbuf);
+ string lexbuf }
| '\\' _
{ if not (in_comment ()) then begin
(* Should be an error, but we are very lax.
| Initial (* There have been no docstrings yet *)
| After of docstring list
(* There have been docstrings, none of which were
- preceeded by a blank line *)
+ preceded by a blank line *)
| Before of docstring list * docstring list * docstring list
(* There have been docstrings, some of which were
- preceeded by a blank line *)
+ preceded by a blank line *)
and docstring = Docstrings.docstring
(* This reference should be in Clflags, but it would create an additional
dependency and make bootstrapping Camlp4 more difficult. *)
-type t = { loc_start: position; loc_end: position; loc_ghost: bool };;
+type t = Warnings.loc = { loc_start: position; loc_end: position; loc_ghost: bool };;
let in_file name =
let loc = {
end
done;
(* Print character location (useful for Emacs) *)
- Format.fprintf ppf "Characters %i-%i:@."
+ Format.fprintf ppf "@[<v>Characters %i-%i:@,"
loc.loc_start.pos_cnum loc.loc_end.pos_cnum;
(* Print the input, underlining the location *)
Format.pp_print_string ppf " ";
| '\n' ->
if !line = !line_start && !line = !line_end then begin
(* loc is on one line: underline location *)
- Format.fprintf ppf "@. ";
+ Format.fprintf ppf "@, ";
for _i = !pos_at_bol to loc.loc_start.pos_cnum - 1 do
Format.pp_print_char ppf ' '
done;
done
end;
if !line >= !line_start && !line <= !line_end then begin
- Format.fprintf ppf "@.";
+ Format.fprintf ppf "@,";
if pos < loc.loc_end.pos_cnum then Format.pp_print_string ppf " "
end;
incr line;
else if !line > !line_start && !line < !line_end then
(* intermediate line of multiline loc: print whole line *)
Format.pp_print_char ppf c
- done
+ done;
+ Format.fprintf ppf "@]"
(* Highlight the location using one of the supported modes. *)
end
;;
-let print ppf loc =
+let default_printer ppf loc =
setup_colors ();
if loc.loc_start.pos_fname = "//toplevel//"
&& highlight_locations ppf [loc] then ()
- else fprintf ppf "@{<loc>%a@}%s@." print_loc loc msg_colon
+ else fprintf ppf "@{<loc>%a@}%s@," print_loc loc msg_colon
;;
+let printer = ref default_printer
+let print ppf loc = !printer ppf loc
+
let error_prefix = "Error"
let warning_prefix = "Warning"
-let print_error_prefix ppf () =
+let print_error_prefix ppf =
setup_colors ();
- fprintf ppf "@{<error>%s@}:" error_prefix;
- ()
+ fprintf ppf "@{<error>%s@}" error_prefix;
;;
let print_compact ppf loc =
;;
let print_error ppf loc =
- print ppf loc;
- print_error_prefix ppf ()
+ fprintf ppf "%a%t:" print loc print_error_prefix;
;;
let print_error_cur_file ppf () = print_error ppf (in_file !input_name);;
let default_warning_printer loc ppf w =
- if Warnings.is_active w then begin
+ match Warnings.report w with
+ | `Inactive -> ()
+ | `Active { Warnings. number; message; is_error; sub_locs } ->
setup_colors ();
+ fprintf ppf "@[<v>";
print ppf loc;
- fprintf ppf "@{<warning>%s@} %a@." warning_prefix Warnings.print w
- end
+ if is_error
+ then
+ fprintf ppf "%t (%s %d): %s@," print_error_prefix
+ (String.uncapitalize_ascii warning_prefix) number message
+ else fprintf ppf "@{<warning>%s@} %d: %s@," warning_prefix number message;
+ List.iter
+ (fun (loc, msg) ->
+ if loc <> none then fprintf ppf " %a %s@," print loc msg
+ )
+ sub_locs;
+ fprintf ppf "@]"
;;
let warning_printer = ref default_warning_printer ;;
let register_error_of_exn f = error_of_exn := f :: !error_of_exn
+exception Already_displayed_error = Warnings.Errors
+
let error_of_exn exn =
- let rec loop = function
- | [] -> None
- | f :: rest ->
- match f exn with
- | Some _ as r -> r
- | None -> loop rest
- in
- loop !error_of_exn
+ match exn with
+ | Already_displayed_error -> Some `Already_displayed
+ | _ ->
+ let rec loop = function
+ | [] -> None
+ | f :: rest ->
+ match f exn with
+ | Some error -> Some (`Ok error)
+ | None -> loop rest
+ in
+ loop !error_of_exn
let rec default_error_reporter ppf ({loc; msg; sub; if_highlight} as err) =
let highlighted =
if highlighted then
Format.pp_print_string ppf if_highlight
else begin
- fprintf ppf "%a%a %s" print loc print_error_prefix () msg;
- List.iter (Format.fprintf ppf "@\n@[<2>%a@]" default_error_reporter) sub
+ fprintf ppf "@[<v>%a %s" print_error loc msg;
+ List.iter (Format.fprintf ppf "@,@[<2>%a@]" default_error_reporter) sub;
+ fprintf ppf "@]"
end
let error_reporter = ref default_error_reporter
| Sys_error msg ->
Some (errorf ~loc:(in_file !input_name)
"I/O error: %s" msg)
- | Warnings.Errors n ->
- Some
- (errorf ~loc:(in_file !input_name)
- "Some fatal warnings were triggered (%d occurrences)" n)
| Misc.HookExnWrapper {error = e; hook_name;
hook_info={Misc.sourcefile}} ->
let sub = match error_of_exn e with
- | None -> error (Printexc.to_string e)
- | Some err -> err
+ | None | Some `Already_displayed -> error (Printexc.to_string e)
+ | Some (`Ok err) -> err
in
Some
(errorf ~loc:(in_file sourcefile)
external reraise : exn -> 'a = "%reraise"
let rec report_exception_rec n ppf exn =
- try match error_of_exn exn with
- | Some err ->
- fprintf ppf "@[%a@]@." report_error err
- | None -> reraise exn
- with exn when n > 0 ->
- report_exception_rec (n-1) ppf exn
+ try
+ match error_of_exn exn with
+ | None -> reraise exn
+ | Some `Already_displayed -> ()
+ | Some (`Ok err) -> fprintf ppf "@[%a@]@." report_error err
+ with exn when n > 0 -> report_exception_rec (n-1) ppf exn
let report_exception ppf exn = report_exception_rec 5 ppf exn
pp_ksprintf
~before:print_phanton_error_prefix
(fun msg -> raise (Error ({loc; msg; sub; if_highlight})))
+
+let deprecated ?(def = none) ?(use = none) loc msg =
+ prerr_warning loc (Warnings.Deprecated (msg, def, use))
open Format
-type t = {
+type t = Warnings.loc = {
loc_start: Lexing.position;
loc_end: Lexing.position;
loc_ghost: bool;
val echo_eof: unit -> unit
val reset: unit -> unit
+val default_printer : formatter -> t -> unit
+val printer : (formatter -> t -> unit) ref
+
val warning_printer : (t -> formatter -> Warnings.t -> unit) ref
(** Hook for intercepting warnings. *)
val absname: bool ref
-(* Support for located errors *)
+(** Support for located errors *)
type error =
{
if_highlight: string; (* alternative message if locations are highlighted *)
}
+exception Already_displayed_error
exception Error of error
-val print_error_prefix: formatter -> unit -> unit
- (* print the prefix "Error:" possibly with style *)
-
val error: ?loc:t -> ?sub:error list -> ?if_highlight:string -> string -> error
val errorf: ?loc:t -> ?sub:error list -> ?if_highlight:string
val error_of_printer_file: (formatter -> 'a -> unit) -> 'a -> error
-val error_of_exn: exn -> error option
+val error_of_exn: exn -> [ `Ok of error | `Already_displayed ] option
val register_error_of_exn: (exn -> error option) -> unit
- (* Each compiler module which defines a custom type of exception
- which can surface as a user-visible error should register
- a "printer" for this exception using [register_error_of_exn].
- The result of the printer is an [error] value containing
- a location, a message, and optionally sub-messages (each of them
- being located as well). *)
+(** Each compiler module which defines a custom type of exception
+ which can surface as a user-visible error should register
+ a "printer" for this exception using [register_error_of_exn].
+ The result of the printer is an [error] value containing
+ a location, a message, and optionally sub-messages (each of them
+ being located as well). *)
val report_error: formatter -> error -> unit
(** Original error reporter for use in hooks. *)
val report_exception: formatter -> exn -> unit
- (* Reraise the exception if it is unknown. *)
+(** Reraise the exception if it is unknown. *)
+
+val deprecated: ?def:t -> ?use:t -> t -> string -> unit
with Not_found ->
[String.sub s pos (String.length s - pos)]
+let unflatten l =
+ match l with
+ | [] -> None
+ | hd :: tl -> Some (List.fold_left (fun p s -> Ldot(p, s)) (Lident hd) tl)
+
let parse s =
- match split_at_dots s 0 with
- [] -> Lident "" (* should not happen, but don't put assert false
- so as not to crash the toplevel (see Genprintval) *)
- | hd :: tl -> List.fold_left (fun p s -> Ldot(p, s)) (Lident hd) tl
+ match unflatten (split_at_dots s 0) with
+ | None -> Lident "" (* should not happen, but don't put assert false
+ so as not to crash the toplevel (see Genprintval) *)
+ | Some v -> v
| Lapply of t * t
val flatten: t -> string list
+val unflatten: string list -> t option
val last: t -> string
val parse: string -> t
let wrap_class_attrs body attrs =
{body with pcl_attributes = attrs @ body.pcl_attributes}
+let wrap_class_type_attrs body attrs =
+ {body with pcty_attributes = attrs @ body.pcty_attributes}
let wrap_mod_attrs body attrs =
{body with pmod_attributes = attrs @ body.pmod_attributes}
let wrap_mty_attrs body attrs =
%token <string> INFIXOP2
%token <string> INFIXOP3
%token <string> INFIXOP4
+%token <string> DOTOP
%token INHERIT
%token INITIALIZER
%token <string * char option> INT
%nonassoc HASH /* simple_expr/toplevel_directive */
%left HASHOP
%nonassoc below_DOT
-%nonassoc DOT
+%nonassoc DOT DOTOP
/* Finally, the first tokens of simple_expr are above everything else. */
%nonassoc BACKQUOTE BANG BEGIN CHAR FALSE FLOAT INT
LBRACE LBRACELESS LBRACKET LBRACKETBAR LIDENT LPAREN
{ mkclass(Pcl_apply($1, List.rev $2)) }
| let_bindings IN class_expr
{ class_of_let_bindings $1 $3 }
+ | LET OPEN override_flag attributes mod_longident IN class_expr
+ { wrap_class_attrs (mkclass(Pcl_open($3, mkrhs $5 5, $7))) $4 }
| class_expr attribute
{ Cl.attr $1 $2 }
| extension
{ Cty.attr $1 $2 }
| extension
{ mkcty(Pcty_extension $1) }
+ | LET OPEN override_flag attributes mod_longident IN class_signature
+ { wrap_class_type_attrs (mkcty(Pcty_open($3, mkrhs $5 5, $7))) $4 }
;
class_sig_body:
class_self_type class_sig_fields
seq_expr:
| expr %prec below_SEMI { $1 }
- | expr SEMI { reloc_exp $1 }
+ | expr SEMI { $1 }
| expr SEMI seq_expr { mkexp(Pexp_sequence($1, $3)) }
| expr SEMI PERCENT attr_id seq_expr
{ let seq = mkexp(Pexp_sequence ($1, $5)) in
{ mkexp_attrs(Pexp_for($3, $5, $7, $6, $9)) $2 }
| expr COLONCOLON expr
{ mkexp_cons (rhs_loc 2) (ghexp(Pexp_tuple[$1;$3])) (symbol_rloc()) }
- | LPAREN COLONCOLON RPAREN LPAREN expr COMMA expr RPAREN
- { mkexp_cons (rhs_loc 2) (ghexp(Pexp_tuple[$5;$7])) (symbol_rloc()) }
| expr INFIXOP0 expr
{ mkinfix $1 $2 $3 }
| expr INFIXOP1 expr
[Nolabel,$1; Nolabel,$4; Nolabel,$7])) }
| simple_expr DOT LBRACE expr RBRACE LESSMINUS expr
{ bigarray_set $1 $4 $7 }
+ | simple_expr DOTOP LBRACKET expr RBRACKET LESSMINUS expr
+ { let id = mkexp @@ Pexp_ident( ghloc @@ Lident ("." ^ $2 ^ "[]<-")) in
+ mkexp @@ Pexp_apply(id , [Nolabel, $1; Nolabel, $4; Nolabel, $7]) }
+ | simple_expr DOTOP LPAREN expr RPAREN LESSMINUS expr
+ { let id = mkexp @@ Pexp_ident( ghloc @@ Lident ("." ^ $2 ^ "()<-")) in
+ mkexp @@ Pexp_apply(id , [Nolabel, $1; Nolabel, $4; Nolabel, $7]) }
+ | simple_expr DOTOP LBRACE expr RBRACE LESSMINUS expr
+ { let id = mkexp @@ Pexp_ident( ghloc @@ Lident ("." ^ $2 ^ "{}<-")) in
+ mkexp @@ Pexp_apply(id , [Nolabel, $1; Nolabel, $4; Nolabel, $7]) }
+ | simple_expr DOT mod_longident DOTOP LBRACKET expr RBRACKET LESSMINUS expr
+ { let id = mkexp @@ Pexp_ident( ghloc @@ Ldot($3,"." ^ $4 ^ "[]<-")) in
+ mkexp @@ Pexp_apply(id , [Nolabel, $1; Nolabel, $6; Nolabel, $9]) }
+ | simple_expr DOT mod_longident DOTOP LPAREN expr RPAREN LESSMINUS expr
+ { let id = mkexp @@ Pexp_ident( ghloc @@ Ldot($3, "." ^ $4 ^ "()<-")) in
+ mkexp @@ Pexp_apply(id , [Nolabel, $1; Nolabel, $6; Nolabel, $9]) }
+ | simple_expr DOT mod_longident DOTOP LBRACE expr RBRACE LESSMINUS expr
+ { let id = mkexp @@ Pexp_ident( ghloc @@ Ldot($3, "." ^ $4 ^ "{}<-")) in
+ mkexp @@ Pexp_apply(id , [Nolabel, $1; Nolabel, $6; Nolabel, $9]) }
| label LESSMINUS expr
{ mkexp(Pexp_setinstvar(mkrhs $1 1, $3)) }
| ASSERT ext_attributes simple_expr %prec below_HASH
[Nolabel,$1; Nolabel,$4])) }
| simple_expr DOT LBRACKET seq_expr error
{ unclosed "[" 3 "]" 5 }
+ | simple_expr DOTOP LBRACKET expr RBRACKET
+ { let id = mkexp @@ Pexp_ident( ghloc @@ Lident ("." ^ $2 ^ "[]")) in
+ mkexp @@ Pexp_apply(id, [Nolabel, $1; Nolabel, $4]) }
+ | simple_expr DOTOP LBRACKET expr error
+ { unclosed "[" 3 "]" 5 }
+ | simple_expr DOTOP LPAREN expr RPAREN
+ { let id = mkexp @@ Pexp_ident( ghloc @@ Lident ("." ^ $2 ^ "()")) in
+ mkexp @@ Pexp_apply(id, [Nolabel, $1; Nolabel, $4]) }
+ | simple_expr DOTOP LPAREN expr error
+ { unclosed "(" 3 ")" 5 }
+ | simple_expr DOTOP LBRACE expr RBRACE
+ { let id = mkexp @@ Pexp_ident( ghloc @@ Lident ("." ^ $2 ^ "{}")) in
+ mkexp @@ Pexp_apply(id, [Nolabel, $1; Nolabel, $4]) }
+ | simple_expr DOTOP LBRACE expr error
+ { unclosed "{" 3 "}" 5 }
+ | simple_expr DOT mod_longident DOTOP LBRACKET expr RBRACKET
+ { let id = mkexp @@ Pexp_ident( ghloc @@ Ldot($3, "." ^ $4 ^ "[]")) in
+ mkexp @@ Pexp_apply(id, [Nolabel, $1; Nolabel, $6]) }
+ | simple_expr DOT mod_longident DOTOP LBRACKET expr error
+ { unclosed "[" 5 "]" 7 }
+ | simple_expr DOT mod_longident DOTOP LPAREN expr RPAREN
+ { let id = mkexp @@ Pexp_ident( ghloc @@ Ldot($3, "." ^ $4 ^ "()")) in
+ mkexp @@ Pexp_apply(id, [Nolabel, $1; Nolabel, $6]) }
+ | simple_expr DOT mod_longident DOTOP LPAREN expr error
+ { unclosed "(" 5 ")" 7 }
+ | simple_expr DOT mod_longident DOTOP LBRACE expr RBRACE
+ { let id = mkexp @@ Pexp_ident( ghloc @@ Ldot($3, "." ^ $4 ^ "{}")) in
+ mkexp @@ Pexp_apply(id, [Nolabel, $1; Nolabel, $6]) }
+ | simple_expr DOT mod_longident DOTOP LBRACE expr error
+ { unclosed "{" 5 "}" 7 }
| simple_expr DOT LBRACE expr RBRACE
{ bigarray_get $1 $4 }
| simple_expr DOT LBRACE expr_comma_list error
| LIDENT lident_list { mkrhs $1 1 :: $2 }
;
let_binding_body:
- val_ident fun_binding
+ val_ident strict_binding
{ (mkpatvar $1 1, $2) }
+ | val_ident type_constraint EQUAL seq_expr
+ { let v = mkpatvar $1 1 in (* PR#7344 *)
+ let t =
+ match $2 with
+ Some t, None -> t
+ | _, Some t -> t
+ | _ -> assert false
+ in
+ (ghpat(Ppat_constraint(v, ghtyp(Ptyp_poly([],t)))),
+ mkexp_constraint $4 $2) }
| val_ident COLON typevar_list DOT core_type EQUAL seq_expr
{ (ghpat(Ppat_constraint(mkpatvar $1 1,
ghtyp(Ptyp_poly(List.rev $3,$5)))),
{ mkpat(Ppat_construct(mkrhs $1 1, Some $2)) }
| name_tag pattern %prec prec_constr_appl
{ mkpat(Ppat_variant($1, Some $2)) }
- | LPAREN COLONCOLON RPAREN LPAREN pattern COMMA pattern RPAREN
- { mkpat_cons (rhs_loc 2) (ghpat(Ppat_tuple[$5;$7])) (symbol_rloc()) }
- | LPAREN COLONCOLON RPAREN LPAREN pattern COMMA pattern error
- { unclosed "(" 4 ")" 8 }
| LAZY ext_attributes simple_pattern
{ mkpat_attrs (Ppat_lazy $3) $2}
;
{ (Ptype_variant(List.rev $3), Private, None) }
| EQUAL DOTDOT
{ (Ptype_open, Public, None) }
+ | EQUAL PRIVATE DOTDOT
+ { (Ptype_open, Private, None) }
| EQUAL private_flag LBRACE label_declarations RBRACE
{ (Ptype_record $4, $2, None) }
| EQUAL core_type EQUAL private_flag constructor_declarations
{ (Ptype_variant(List.rev $5), $4, Some $2) }
- | EQUAL core_type EQUAL DOTDOT
- { (Ptype_open, Public, Some $2) }
+ | EQUAL core_type EQUAL private_flag DOTDOT
+ { (Ptype_open, $4, Some $2) }
| EQUAL core_type EQUAL private_flag LBRACE label_declarations RBRACE
{ (Ptype_record $6, $4, Some $2) }
;
;
-type_parameters:
- /*empty*/ { [] }
- | type_parameter { [$1] }
- | LPAREN type_parameter_list RPAREN { List.rev $2 }
-;
type_parameter:
type_variance type_variable { $2, $1 }
;
| with_constraints AND with_constraint { $3 :: $1 }
;
with_constraint:
- TYPE type_parameters label_longident with_type_binder core_type_no_attr
- constraints
+ TYPE optional_type_parameters label_longident with_type_binder
+ core_type_no_attr constraints
{ Pwith_type
(mkrhs $3 3,
(Type.mk (mkrhs (Longident.last $3) 3)
~loc:(symbol_rloc()))) }
/* used label_longident instead of type_longident to disallow
functor applications in type path */
- | TYPE type_parameters label COLONEQUAL core_type_no_attr
+ | TYPE optional_type_parameters label_longident COLONEQUAL core_type_no_attr
{ Pwith_typesubst
- (Type.mk (mkrhs $3 3)
+ (mkrhs $3 3,
+ (Type.mk (mkrhs (Longident.last $3) 3)
~params:$2
~manifest:$5
- ~loc:(symbol_rloc())) }
+ ~loc:(symbol_rloc()))) }
| MODULE mod_longident EQUAL mod_ext_longident
{ Pwith_module (mkrhs $2 2, mkrhs $4 4) }
- | MODULE UIDENT COLONEQUAL mod_ext_longident
+ | MODULE mod_longident COLONEQUAL mod_ext_longident
{ Pwith_modsubst (mkrhs $2 2, mkrhs $4 4) }
;
with_type_binder:
;
tag_field:
name_tag OF opt_ampersand amper_type_list attributes
- { Rtag ($1, add_info_attrs (symbol_info ()) $5, $3, List.rev $4) }
+ { Rtag (mkrhs $1 1, add_info_attrs (symbol_info ()) $5,
+ $3, List.rev $4) }
| name_tag attributes
- { Rtag ($1, add_info_attrs (symbol_info ()) $2, true, []) }
+ { Rtag (mkrhs $1 1, add_info_attrs (symbol_info ()) $2, true, []) }
;
opt_ampersand:
AMPERSAND { true }
| core_type_list STAR simple_core_type { $3 :: $1 }
;
meth_list:
- field_semi meth_list { let (f, c) = $2 in ($1 :: f, c) }
+ field_semi meth_list { let (f, c) = $2 in ($1 :: f, c) }
+ | inherit_field_semi meth_list { let (f, c) = $2 in ($1 :: f, c) }
| field_semi { [$1], Closed }
| field { [$1], Closed }
+ | inherit_field_semi { [$1], Closed }
+ | simple_core_type { [Oinherit $1], Closed }
| DOTDOT { [], Open }
;
field:
label COLON poly_type_no_attr attributes
- { (mkrhs $1 1, add_info_attrs (symbol_info ()) $4, $3) }
+ { Otag (mkrhs $1 1, add_info_attrs (symbol_info ()) $4, $3) }
;
field_semi:
| Some _ as info_before_semi -> info_before_semi
| None -> symbol_info ()
in
- (mkrhs $1 1, add_info_attrs info ($4 @ $6), $3) }
+ ( Otag (mkrhs $1 1, add_info_attrs info ($4 @ $6), $3)) }
;
+inherit_field_semi:
+ simple_core_type SEMI { Oinherit $1 }
+
label:
LIDENT { $1 }
;
| INFIXOP2 { $1 }
| INFIXOP3 { $1 }
| INFIXOP4 { $1 }
- | HASHOP { $1 }
+ | DOTOP LPAREN RPAREN { "."^ $1 ^"()" }
+ | DOTOP LPAREN RPAREN LESSMINUS { "."^ $1 ^ "()<-" }
+ | DOTOP LBRACKET RBRACKET { "."^ $1 ^"[]" }
+ | DOTOP LBRACKET RBRACKET LESSMINUS { "."^ $1 ^ "[]<-" }
+ | DOTOP LBRACE RBRACE { "."^ $1 ^"{}" }
+ | DOTOP LBRACE RBRACE LESSMINUS { "."^ $1 ^ "{}<-" }
+ | HASHOP { $1 }
| BANG { "!" }
| PLUS { "+" }
| PLUSDOT { "+." }
UIDENT { $1 }
| LBRACKET RBRACKET { "[]" }
| LPAREN RPAREN { "()" }
- /* | COLONCOLON { "::" } */
| LPAREN COLONCOLON RPAREN { "::" }
| FALSE { "false" }
| TRUE { "true" }
;
constr_longident:
mod_longident %prec below_DOT { $1 }
+ | mod_longident DOT LPAREN COLONCOLON RPAREN { Ldot($1,"::") }
| LBRACKET RBRACKET { Lident "[]" }
| LPAREN RPAREN { Lident "()" }
+ | LPAREN COLONCOLON RPAREN { Lident "::" }
| FALSE { Lident "false" }
| TRUE { Lident "true" }
;
Suffixes are rejected by the typechecker.
*)
-(** {2 Extension points} *)
+(** {1 Extension points} *)
type attribute = string loc * payload
(* [@id ARG]
| PTyp of core_type (* : T *)
| PPat of pattern * expression option (* ? P or ? P when E *)
-(** {2 Core language} *)
+(** {1 Core language} *)
(* Type expressions *)
| Ptyp_arrow of arg_label * core_type * core_type
(* T1 -> T2 Simple
~l:T1 -> T2 Labelled
- ?l:T1 -> T2 Otional
+ ?l:T1 -> T2 Optional
*)
| Ptyp_tuple of core_type list
(* T1 * ... * Tn
T tconstr
(T1, ..., Tn) tconstr
*)
- | Ptyp_object of (string loc * attributes * core_type) list * closed_flag
+ | Ptyp_object of object_field list * closed_flag
(* < l1:T1; ...; ln:Tn > (flag = Closed)
< l1:T1; ...; ln:Tn; .. > (flag = Open)
*)
*)
and row_field =
- | Rtag of label * attributes * bool * core_type list
+ | Rtag of label loc * attributes * bool * core_type list
(* [`A] ( true, [] )
[`A of T] ( false, [T] )
[`A of T1 & .. & Tn] ( false, [T1;...Tn] )
| Rinherit of core_type
(* [ T ] *)
+and object_field =
+ | Otag of label loc * attributes * core_type
+ | Oinherit of core_type
+
(* Patterns *)
and pattern =
(* (E :> T) (None, T)
(E : T0 :> T) (Some T0, T)
*)
- | Pexp_send of expression * string loc
+ | Pexp_send of expression * label loc
(* E # m *)
| Pexp_new of Longident.t loc
(* new M.c *)
- | Pexp_setinstvar of string loc * expression
+ | Pexp_setinstvar of label loc * expression
(* x <- 2 *)
- | Pexp_override of (string loc * expression) list
+ | Pexp_override of (label loc * expression) list
(* {< x1 = E1; ...; Xn = En >} *)
| Pexp_letmodule of string loc * module_expr * expression
(* let module M = ME in E *)
pld_mutable: mutable_flag;
pld_type: core_type;
pld_loc: Location.t;
- pld_attributes: attributes; (* l [@id1] [@id2] : T *)
+ pld_attributes: attributes; (* l : T [@id1] [@id2] *)
}
(* { ...; l: T; ... } (mutable=Immutable)
pcd_args: constructor_arguments;
pcd_res: core_type option;
pcd_loc: Location.t;
- pcd_attributes: attributes; (* C [@id1] [@id2] of ... *)
+ pcd_attributes: attributes; (* C of ... [@id1] [@id2] *)
}
and constructor_arguments =
pext_name: string loc;
pext_kind : extension_constructor_kind;
pext_loc : Location.t;
- pext_attributes: attributes; (* C [@id1] [@id2] of ... *)
+ pext_attributes: attributes; (* C of ... [@id1] [@id2] *)
}
and extension_constructor_kind =
| C = D
*)
-(** {2 Class language} *)
+(** {1 Class language} *)
(* Type expressions for the class language *)
*)
| Pcty_extension of extension
(* [%id] *)
+ | Pcty_open of override_flag * Longident.t loc * class_type
+ (* let open M in CT *)
and class_signature =
{
and class_type_field_desc =
| Pctf_inherit of class_type
(* inherit CT *)
- | Pctf_val of (string loc * mutable_flag * virtual_flag * core_type)
+ | Pctf_val of (label loc * mutable_flag * virtual_flag * core_type)
(* val x: T *)
- | Pctf_method of (string loc * private_flag * virtual_flag * core_type)
+ | Pctf_method of (label loc * private_flag * virtual_flag * core_type)
(* method x: T
Note: T can be a Ptyp_poly.
| Pcl_constraint of class_expr * class_type
(* (CE : CT) *)
| Pcl_extension of extension
- (* [%id] *)
+ (* [%id] *)
+ | Pcl_open of override_flag * Longident.t loc * class_expr
+ (* let open M in CE *)
+
and class_structure =
{
inherit! CE
inherit! CE as x
*)
- | Pcf_val of (string loc * mutable_flag * class_field_kind)
+ | Pcf_val of (label loc * mutable_flag * class_field_kind)
(* val x = E
val virtual x: T
*)
- | Pcf_method of (string loc * private_flag * class_field_kind)
+ | Pcf_method of (label loc * private_flag * class_field_kind)
(* method x = E (E can be a Pexp_poly)
method virtual x: T (T can be a Ptyp_poly)
*)
and class_declaration = class_expr class_infos
-(** {2 Module language} *)
+(** {1 Module language} *)
(* Type expressions for the module language *)
the name of the type_declaration. *)
| Pwith_module of Longident.t loc * Longident.t loc
(* with module X.Y = Z *)
- | Pwith_typesubst of type_declaration
- (* with type t := ... *)
- | Pwith_modsubst of string loc * Longident.t loc
- (* with module X := Z *)
+ | Pwith_typesubst of Longident.t loc * type_declaration
+ (* with type X.t := ..., same format as [Pwith_type] *)
+ | Pwith_modsubst of Longident.t loc * Longident.t loc
+ (* with module X.Y := Z *)
(* Value expressions for the module language *)
}
(* X = ME *)
-(** {2 Toplevel} *)
+(** {1 Toplevel} *)
(* Toplevel phrases *)
let prefix_symbols = [ '!'; '?'; '~' ] ;;
let infix_symbols = [ '='; '<'; '>'; '@'; '^'; '|'; '&'; '+'; '-'; '*'; '/';
- '$'; '%' ]
+ '$'; '%'; '#' ]
+
(* type fixity = Infix| Prefix *)
let special_infix_strings =
- ["asr"; "land"; "lor"; "lsl"; "lsr"; "lxor"; "mod"; "or"; ":="; "!=" ]
+ ["asr"; "land"; "lor"; "lsl"; "lsr"; "lxor"; "mod"; "or"; ":="; "!="; "::" ]
(* determines if the string is an infix string.
checks backwards, first allowing a renaming postfix ("_102") which
| s when List.mem s special_infix_strings -> `Infix s
| s when List.mem s.[0] infix_symbols -> `Infix s
| s when List.mem s.[0] prefix_symbols -> `Prefix s
+ | s when s.[0] = '.' -> `Mixfix s
| _ -> `Normal
let view_fixity_of_exp = function
- | {pexp_desc = Pexp_ident {txt=Lident l;_};_} -> fixity_of_string l
+ | {pexp_desc = Pexp_ident {txt=Lident l;_}; pexp_attributes = []} ->
+ fixity_of_string l
| _ -> `Normal
let is_infix = function | `Infix _ -> true | _ -> false
+let is_mixfix = function `Mixfix _ -> true | _ -> false
(* which identifiers are in fact operators needing parentheses *)
let needs_parens txt =
- is_infix (fixity_of_string txt)
+ let fix = fixity_of_string txt in
+ is_infix fix
+ || is_mixfix fix
|| List.mem txt.[0] prefix_symbols
(* some infixes need spaces around parens to avoid clashes with comment
| Pexp_construct ( {txt= Lident "[]";_},_) -> `nil
| Pexp_construct ( {txt= Lident"::";_},Some _) ->
let rec loop exp acc = match exp with
- | {pexp_desc=Pexp_construct ({txt=Lident "[]";_},_);_} ->
+ | {pexp_desc=Pexp_construct ({txt=Lident "[]";_},_);
+ pexp_attributes = []} ->
(List.rev acc,true)
| {pexp_desc=
Pexp_construct ({txt=Lident "::";_},
- Some ({pexp_desc= Pexp_tuple([e1;e2]);_}));_} ->
+ Some ({pexp_desc= Pexp_tuple([e1;e2]);
+ pexp_attributes = []}));
+ pexp_attributes = []}
+ ->
loop e2 (e1::acc)
| e -> (List.rev (e::acc),false) in
let (ls,b) = loop x [] in
(type_with_label ctxt) (l,ct1) (core_type ctxt) ct2
| Ptyp_alias (ct, s) ->
pp f "@[<2>%a@;as@;'%s@]" (core_type1 ctxt) ct s
+ | Ptyp_poly ([], ct) ->
+ core_type ctxt f ct
| Ptyp_poly (sl, ct) ->
pp f "@[<2>%a%a@]"
(fun f l ->
(fun f l -> match l with
|[] -> ()
|[x]-> pp f "%a@;" (core_type1 ctxt) x
- | _ -> list ~first:"(" ~last:")@;" (core_type ctxt) ~sep:"," f l)
+ | _ -> list ~first:"(" ~last:")@;" (core_type ctxt) ~sep:",@;" f l)
l longident_loc li
| Ptyp_variant (l, closed, low) ->
let type_variant_helper f x =
match x with
| Rtag (l, attrs, _, ctl) ->
- pp f "@[<2>%a%a@;%a@]" string_quot l
+ pp f "@[<2>%a%a@;%a@]" string_quot l.txt
(fun f l -> match l with
|[] -> ()
| _ -> pp f "@;of@;%a"
pp f ">@ %a"
(list string_quot) xs) low
| Ptyp_object (l, o) ->
- let core_field_type f (s, attrs, ct) =
- pp f "@[<hov2>%s: %a@ %a@ @]" s.txt
- (core_type ctxt) ct (attributes ctxt) attrs (* Cf #7200 *)
+ let core_field_type f = function
+ | Otag (l, attrs, ct) ->
+ pp f "@[<hov2>%s: %a@ %a@ @]" l.txt
+ (core_type ctxt) ct (attributes ctxt) attrs (* Cf #7200 *)
+ | Oinherit ct ->
+ pp f "@[<hov2>%a@ @]" (core_type ctxt) ct
in
let field_var f = function
| Asttypes.Closed -> ()
(* be cautious when use [pattern], [pattern1] is preferred *)
and pattern ctxt f x =
let rec list_of_pattern acc = function (* only consider ((A|B)|C)*)
- | {ppat_desc= Ppat_or (p1,p2);_} ->
+ | {ppat_desc= Ppat_or (p1,p2); ppat_attributes = []} ->
list_of_pattern (p2::acc) p1
| x -> x::acc
in
| {ppat_desc =
Ppat_construct
({ txt = Lident("::") ;_},
- Some ({ppat_desc = Ppat_tuple([pat1; pat2]);_})); _}
+ Some ({ppat_desc = Ppat_tuple([pat1; pat2]);_}));
+ ppat_attributes = []}
+
->
pp f "%a::%a" (simple_pattern ctxt) pat1 pattern_list_helper pat2 (*RA*)
| p -> pattern1 ctxt f p
else
(match po with
| Some x -> pp f "%a@;%a" longident_loc li (simple_pattern ctxt) x
- | None -> pp f "%a@;"longident_loc li )
+ | None -> pp f "%a" longident_loc li)
| _ -> simple_pattern ctxt f x
and simple_pattern ctxt (f:Format.formatter) (x:pattern) : unit =
pp f "#%a" longident_loc li
| Ppat_record (l, closed) ->
let longident_x_pattern f (li, p) =
- match (li,p.ppat_desc) with
- | ({txt=Lident s;_ },Ppat_var {txt;_} ) when s = txt ->
+ match (li,p) with
+ | ({txt=Lident s;_ },
+ {ppat_desc=Ppat_var {txt;_};
+ ppat_attributes=[]; _})
+ when s = txt ->
pp f "@[<2>%a@]" longident_loc li
| _ ->
pp f "@[<2>%a@;=@;%a@]" longident_loc li (pattern1 ctxt) p
pp f "@[<2>{@;%a;_}@]" (list longident_x_pattern ~sep:";@;") l
end
| Ppat_tuple l ->
- pp f "@[<1>(%a)@]" (list ~sep:"," (pattern1 ctxt)) l (* level1*)
+ pp f "@[<1>(%a)@]" (list ~sep:",@;" (pattern1 ctxt)) l (* level1*)
| Ppat_constant (c) -> pp f "%a" constant c
| Ppat_interval (c1, c2) -> pp f "%a..%a" constant c1 constant c2
| Ppat_variant (l,None) -> pp f "`%s" l
(* single case pattern parens needed here *)
pp f "%a@ " (simple_pattern ctxt) p
| Optional rest ->
- begin match p.ppat_desc with
- | Ppat_var {txt;_} when txt = rest ->
+ begin match p with
+ | {ppat_desc = Ppat_var {txt;_}; ppat_attributes = []}
+ when txt = rest ->
(match opt with
| Some o -> pp f "?(%s=@;%a)@;" rest (expression ctxt) o
| None -> pp f "?%s@ " rest)
rest (pattern1 ctxt) p (expression ctxt) o
| None -> pp f "?%s:%a@;" rest (simple_pattern ctxt) p)
end
- | Labelled l -> match p.ppat_desc with
- | Ppat_var {txt;_} when txt = l ->
+ | Labelled l -> match p with
+ | {ppat_desc = Ppat_var {txt;_}; ppat_attributes = []}
+ when txt = l ->
pp f "~%s@;" l
| _ -> pp f "~%s:%a@;" l (simple_pattern ctxt) p
| Pexp_apply ({ pexp_desc = Pexp_ident {txt = id; _};
pexp_attributes=[]; _}, args)
when List.for_all (fun (lab, _) -> lab = Nolabel) args -> begin
+ let print_indexop a path_prefix assign left right print_index indices
+ rem_args =
+ let print_path ppf = function
+ | None -> ()
+ | Some m -> pp ppf ".%a" longident m in
+ match assign, rem_args with
+ | false, [] ->
+ pp f "@[%a%a%s%a%s@]"
+ (simple_expr ctxt) a print_path path_prefix
+ left (list ~sep:"," print_index) indices right; true
+ | true, [v] ->
+ pp f "@[%a%a%s%a%s@ <-@;<1 2>%a@]"
+ (simple_expr ctxt) a print_path path_prefix
+ left (list ~sep:"," print_index) indices right
+ (simple_expr ctxt) v; true
+ | _ -> false in
match id, List.map snd args with
| Lident "!", [e] ->
pp f "@[<hov>!%a@]" (simple_expr ctxt) e; true
| Ldot (path, ("get"|"set" as func)), a :: other_args -> begin
- let print left right print_index indexes rem_args =
- match func, rem_args with
- | "get", [] ->
- pp f "@[%a.%s%a%s@]"
- (simple_expr ctxt) a
- left (list ~sep:"," print_index) indexes right; true
- | "set", [v] ->
- pp f "@[%a.%s%a%s@ <-@;<1 2>%a@]"
- (simple_expr ctxt) a
- left (list ~sep:"," print_index) indexes right
- (simple_expr ctxt) v; true
- | _ -> false
- in
+ let assign = func = "set" in
+ let print = print_indexop a None assign in
match path, other_args with
| Lident "Array", i :: rest ->
- print "(" ")" (expression ctxt) [i] rest
+ print ".(" ")" (expression ctxt) [i] rest
| Lident "String", i :: rest ->
- print "[" "]" (expression ctxt) [i] rest
+ print ".[" "]" (expression ctxt) [i] rest
| Ldot (Lident "Bigarray", "Array1"), i1 :: rest ->
- print "{" "}" (simple_expr ctxt) [i1] rest
+ print ".{" "}" (simple_expr ctxt) [i1] rest
| Ldot (Lident "Bigarray", "Array2"), i1 :: i2 :: rest ->
- print "{" "}" (simple_expr ctxt) [i1; i2] rest
+ print ".{" "}" (simple_expr ctxt) [i1; i2] rest
| Ldot (Lident "Bigarray", "Array3"), i1 :: i2 :: i3 :: rest ->
- print "{" "}" (simple_expr ctxt) [i1; i2; i3] rest
+ print ".{" "}" (simple_expr ctxt) [i1; i2; i3] rest
| Ldot (Lident "Bigarray", "Genarray"),
{pexp_desc = Pexp_array indexes; pexp_attributes = []} :: rest ->
- print "{" "}" (simple_expr ctxt) indexes rest
+ print ".{" "}" (simple_expr ctxt) indexes rest
| _ -> false
end
+ | (Lident s | Ldot(_,s)) , a :: i :: rest
+ when s.[0] = '.' ->
+ let n = String.length s in
+ (* extract operator:
+ assignment operators end with [right_bracket ^ "<-"],
+ access operators end with [right_bracket] directly
+ *)
+ let assign = s.[n - 1] = '-' in
+ let kind =
+ (* extract the right end bracket *)
+ if assign then s.[n - 3] else s.[n - 1] in
+ let left, right = match kind with
+ | ')' -> '(', ")"
+ | ']' -> '[', "]"
+ | '}' -> '{', "}"
+ | _ -> assert false in
+ let path_prefix = match id with
+ | Ldot(m,_) -> Some m
+ | _ -> None in
+ let left = String.sub s 0 (1+String.index s left) in
+ print_indexop a path_prefix assign left right
+ (expression ctxt) [i] rest
| _ -> false
end
| _ -> false
when ctxt.semi ->
paren true (expression reset_ctxt) f x
| Pexp_fun (l, e0, p, e) ->
- pp f "@[<2>fun@;%a@;->@;%a@]"
+ pp f "@[<2>fun@;%a->@;%a@]"
(label_exp ctxt) (l, e0, p)
(expression ctxt) e
| Pexp_function l ->
(expression reset_ctxt) e (case_list ctxt) l
| Pexp_let (rf, l, e) ->
(* pp f "@[<2>let %a%a in@;<1 -2>%a@]"
- (*no identation here, a new line*) *)
+ (*no indentation here, a new line*) *)
(* rec_flag rf *)
pp f "@[<2>%a in@;<1 -2>%a@]"
(bindings reset_ctxt) (rf,l)
| None -> () (* pp f "()" *)) eo
| Pexp_sequence _ ->
let rec sequence_helper acc = function
- | {pexp_desc=Pexp_sequence(e1,e2);_} ->
+ | {pexp_desc=Pexp_sequence(e1,e2); pexp_attributes = []} ->
sequence_helper (e1::acc) e2
| v -> List.rev (v::acc) in
let lst = sequence_helper [] x in
| Pexp_variant (l, None) -> pp f "`%s" l
| Pexp_record (l, eo) ->
let longident_x_expression f ( li, e) =
- match e.pexp_desc with
- | Pexp_ident {txt;_} when li.txt = txt ->
+ match e with
+ | {pexp_desc=Pexp_ident {txt;_};
+ pexp_attributes=[]; _} when li.txt = txt ->
pp f "@[<hov2>%a@]" longident_loc li
| _ ->
pp f "@[<hov2>%a@;=@;%a@]" longident_loc li (simple_expr ctxt) e
item_attributes ctxt f x.pctf_attributes
in
pp f "@[<hv0>@[<hv2>object@[<1>%a@]@ %a@]@ end@]"
- (fun f ct -> match ct.ptyp_desc with
- | Ptyp_any -> ()
- | _ -> pp f " (%a)" (core_type ctxt) ct) ct
+ (fun f -> function
+ {ptyp_desc=Ptyp_any; ptyp_attributes=[]; _} -> ()
+ | ct -> pp f " (%a)" (core_type ctxt) ct) ct
(list class_type_field ~sep:"@;") l
(* call [class_signature] called by [class_signature] *)
| Pcty_extension e ->
extension ctxt f e;
attributes ctxt f x.pcty_attributes
+ | Pcty_open (ovf, lid, e) ->
+ pp f "@[<2>let open%s %a in@;%a@]" (override ovf) longident_loc lid
+ (class_type ctxt) e
(* [class type a = object end] *)
and class_type_declaration_list ctxt f l =
pp f "@[<2>method%s %a%a@]%a"
(override ovf)
private_flag pf
- (fun f e -> match e.pexp_desc with
- | Pexp_poly (e, Some ct) ->
+ (fun f -> function
+ | {pexp_desc=Pexp_poly (e, Some ct); pexp_attributes=[]; _} ->
pp f "%s :@;%a=@;%a"
s.txt (core_type ctxt) ct (expression ctxt) e
- | Pexp_poly (e,None) -> bind e
+ | {pexp_desc=Pexp_poly (e, None); pexp_attributes=[]; _} ->
+ bind e
| _ -> bind e) e
(item_attributes ctxt) x.pcf_attributes
| Pcf_constraint (ct1, ct2) ->
(class_expr ctxt) ce
(class_type ctxt) ct
| Pcl_extension e -> extension ctxt f e
+ | Pcl_open (ovf, lid, e) ->
+ pp f "@[<2>let open%s %a in@;%a@]" (override ovf) longident_loc lid
+ (class_expr ctxt) e
and module_type ctxt f x =
if x.pmty_attributes <> [] then begin
ls longident_loc li (type_declaration ctxt) td
| Pwith_module (li, li2) ->
pp f "module %a =@ %a" longident_loc li longident_loc li2;
- | Pwith_typesubst ({ptype_params=ls;_} as td) ->
+ | Pwith_typesubst (li, ({ptype_params=ls;_} as td)) ->
let ls = List.map fst ls in
- pp f "type@ %a %s :=@ %a"
+ pp f "type@ %a %a :=@ %a"
(list (core_type ctxt) ~sep:"," ~first:"(" ~last:")")
- ls td.ptype_name.txt
+ ls longident_loc li
(type_declaration ctxt) td
- | Pwith_modsubst (s, li2) ->
- pp f "module %s :=@ %a" s.txt longident_loc li2 in
+ | Pwith_modsubst (li, li2) ->
+ pp f "module %a :=@ %a" longident_loc li longident_loc li2 in
(match l with
| [] -> pp f "@[<hov2>%a@]" (module_type ctxt) mt
| _ -> pp f "@[<hov2>(%a@ with@ %a)@]"
(class_description "class") x
(list ~sep:"@," (class_description "and")) xs
end
- | Psig_module ({pmd_type={pmty_desc=Pmty_alias alias};_} as pmd) ->
+ | Psig_module ({pmd_type={pmty_desc=Pmty_alias alias;
+ pmty_attributes=[]; _};_} as pmd) ->
pp f "@[<hov>module@ %s@ =@ %a@]%a" pmd.pmd_name.txt
longident_loc alias
(item_attributes ctxt) pmd.pmd_attributes
let tyvars_str tyvars = List.map (fun v -> v.txt) tyvars in
let is_desugared_gadt p e =
let gadt_pattern =
- match p.ppat_desc with
- | Ppat_constraint({ppat_desc=Ppat_var _} as pat,
- {ptyp_desc=Ptyp_poly (args_tyvars, rt)}) ->
- Some (pat, args_tyvars, rt)
+ match p with
+ | {ppat_desc=Ppat_constraint({ppat_desc=Ppat_var _} as pat,
+ {ptyp_desc=Ptyp_poly (args_tyvars, rt)});
+ ppat_attributes=[]}->
+ Some (pat, args_tyvars, rt)
| _ -> None in
let rec gadt_exp tyvars e =
- match e.pexp_desc with
- | Pexp_newtype (tyvar, e) -> gadt_exp (tyvar :: tyvars) e
- | Pexp_constraint (e, ct) -> Some (List.rev tyvars, e, ct)
+ match e with
+ | {pexp_desc=Pexp_newtype (tyvar, e); pexp_attributes=[]} ->
+ gadt_exp (tyvar :: tyvars) e
+ | {pexp_desc=Pexp_constraint (e, ct); pexp_attributes=[]} ->
+ Some (List.rev tyvars, e, ct)
| _ -> None in
let gadt_exp = gadt_exp [] e in
match gadt_pattern, gadt_exp with
if x.pexp_attributes <> []
then pp f "%a@;=@;%a" (pattern ctxt) p (expression ctxt) x else
match is_desugared_gadt p x with
+ | Some (p, [], ct, e) ->
+ pp f "%a@;: %a@;=@;%a"
+ (simple_pattern ctxt) p (core_type ctxt) ct (expression ctxt) e
| Some (p, tyvars, ct, e) -> begin
- pp f "%a@;: type@;%a.%a@;=@;%a"
+ pp f "%a@;: type@;%a.@;%a@;=@;%a"
(simple_pattern ctxt) p (list pp_print_string ~sep:"@;")
(tyvars_str tyvars) (core_type ctxt) ct (expression ctxt) e
end
| None -> begin
- match (x.pexp_desc,p.ppat_desc) with
- | ( _ , Ppat_constraint( p ,ty)) -> (* special case for the first*)
- begin match ty.ptyp_desc with
- | Ptyp_poly _ ->
+ match p with
+ | {ppat_desc=Ppat_constraint(p ,ty);
+ ppat_attributes=[]} -> (* special case for the first*)
+ begin match ty with
+ | {ptyp_desc=Ptyp_poly _; ptyp_attributes=[]} ->
pp f "%a@;:@;%a@;=@;%a" (simple_pattern ctxt) p
(core_type ctxt) ty (expression ctxt) x
| _ ->
pp f "(%a@;:@;%a)@;=@;%a" (simple_pattern ctxt) p
(core_type ctxt) ty (expression ctxt) x
end
- | (_, Ppat_var _) ->
+ | {ppat_desc=Ppat_var _; ppat_attributes=[]} ->
pp f "%a@ %a" (simple_pattern ctxt) p pp_print_pexp_function x
| _ ->
pp f "%a@;=@;%a" (pattern ctxt) p (expression ctxt) x
(* [in] is not printed *)
and bindings ctxt f (rf,l) =
let binding kwd rf f x =
- pp f "@[<2>%s %a%a@]@ %a" kwd rec_flag rf
+ pp f "@[<2>%s %a%a@]%a" kwd rec_flag rf
(binding ctxt) x (item_attributes ctxt) x.pvb_attributes
in
match l with
| Pstr_typext te -> type_extension ctxt f te
| Pstr_exception ed -> exception_declaration ctxt f ed
| Pstr_module x ->
- let rec module_helper me =
- match me.pmod_desc with
- | Pmod_functor(s,mt,me') when me.pmod_attributes = [] ->
+ let rec module_helper = function
+ | {pmod_desc=Pmod_functor(s,mt,me'); pmod_attributes = []} ->
if mt = None then pp f "()"
else Misc.may (pp f "(%s:%a)" s.txt (module_type ctxt)) mt;
module_helper me'
- | _ -> me
+ | me -> me
in
pp f "@[<hov2>module %s%a@]%a"
x.pmb_name.txt
(fun f me ->
let me = module_helper me in
- match me.pmod_desc with
- | Pmod_constraint
- (me',
- ({pmty_desc=(Pmty_ident (_)
- | Pmty_signature (_));_} as mt))
- when me.pmod_attributes = [] ->
+ match me with
+ | {pmod_desc=
+ Pmod_constraint
+ (me',
+ ({pmty_desc=(Pmty_ident (_)
+ | Pmty_signature (_));_} as mt));
+ pmod_attributes = []} ->
pp f " :@;%a@;=@;%a@;"
(module_type ctxt) mt (module_expr ctxt) me'
| _ -> pp f " =@ %a" (module_expr ctxt) me
(item_attributes ctxt) attrs
| Pstr_class l ->
let extract_class_args cl =
- let rec loop acc cl =
- match cl.pcl_desc with
- | Pcl_fun (l, eo, p, cl') when cl.pcl_attributes = [] ->
+ let rec loop acc = function
+ | {pcl_desc=Pcl_fun (l, eo, p, cl'); pcl_attributes = []} ->
loop ((l,eo,p) :: acc) cl'
- | _ -> List.rev acc, cl
+ | cl -> List.rev acc, cl
in
let args, cl = loop [] cl in
let constr, cl =
- match cl.pcl_desc with
- | Pcl_constraint (cl', ct) when cl.pcl_attributes = [] ->
+ match cl with
+ | {pcl_desc=Pcl_constraint (cl', ct); pcl_attributes = []} ->
Some ct, cl'
| _ -> None, cl
in
and type_params ctxt f = function
| [] -> ()
- | l -> pp f "%a " (list (type_param ctxt) ~first:"(" ~last:")" ~sep:",") l
+ | l -> pp f "%a " (list (type_param ctxt) ~first:"(" ~last:")" ~sep:",@;") l
and type_def_list ctxt f (rf, l) =
let type_decl kwd rf f x =
(fun f -> function
| Pcstr_tuple [] -> core_type1 ctxt f r
| Pcstr_tuple l -> pp f "%a@;->@;%a"
- (list (core_type1 ctxt) ~sep:"*@;") l
+ (list (core_type1 ctxt) ~sep:"@;*@;") l
(core_type1 ctxt) r
| Pcstr_record l ->
pp f "%a@;->@;%a" (record_declaration ctxt) l (core_type1 ctxt) r
list aux f l ~sep:""
and label_x_expression_param ctxt f (l,e) =
- let simple_name = match e.pexp_desc with
- | Pexp_ident {txt=Lident l;_} -> Some l
+ let simple_name = match e with
+ | {pexp_desc=Pexp_ident {txt=Lident l;_};
+ pexp_attributes=[]} -> Some l
| _ -> None
in match l with
| Nolabel -> expression2 ctxt f e (* level 2*)
| Ptyp_object (l, c) ->
line i ppf "Ptyp_object %a\n" fmt_closed_flag c;
let i = i + 1 in
- List.iter
- (fun (s, attrs, t) ->
- line i ppf "method %s\n" s.txt;
- attributes i ppf attrs;
- core_type (i + 1) ppf t
- )
- l
+ List.iter (
+ function
+ | Otag (l, attrs, t) ->
+ line i ppf "method %s\n" l.txt;
+ attributes i ppf attrs;
+ core_type (i + 1) ppf t
+ | Oinherit ct ->
+ line i ppf "Oinherit\n";
+ core_type (i + 1) ppf ct
+ ) l
| Ptyp_class (li, l) ->
line i ppf "Ptyp_class %a\n" fmt_longident_loc li;
list i core_type ppf l
| Pcty_extension (s, arg) ->
line i ppf "Pcty_extension \"%s\"\n" s.txt;
payload i ppf arg
+ | Pcty_open (ovf, m, e) ->
+ line i ppf "Pcty_open %a \"%a\"\n" fmt_override_flag ovf
+ fmt_longident_loc m;
+ class_type i ppf e
and class_signature i ppf cs =
line i ppf "class_signature\n";
| Pcl_extension (s, arg) ->
line i ppf "Pcl_extension \"%s\"\n" s.txt;
payload i ppf arg
+ | Pcl_open (ovf, m, e) ->
+ line i ppf "Pcl_open %a \"%a\"\n" fmt_override_flag ovf
+ fmt_longident_loc m;
+ class_expr i ppf e
and class_structure i ppf { pcstr_self = p; pcstr_fields = l } =
line i ppf "class_structure\n";
| Pwith_type (lid, td) ->
line i ppf "Pwith_type %a\n" fmt_longident_loc lid;
type_declaration (i+1) ppf td;
- | Pwith_typesubst (td) ->
- line i ppf "Pwith_typesubst\n";
+ | Pwith_typesubst (lid, td) ->
+ line i ppf "Pwith_typesubst %a\n" fmt_longident_loc lid;
type_declaration (i+1) ppf td;
| Pwith_module (lid1, lid2) ->
line i ppf "Pwith_module %a = %a\n"
fmt_longident_loc lid1
fmt_longident_loc lid2;
- | Pwith_modsubst (s, li) ->
+ | Pwith_modsubst (lid1, lid2) ->
line i ppf "Pwith_modsubst %a = %a\n"
- fmt_string_loc s
- fmt_longident_loc li;
+ fmt_longident_loc lid1
+ fmt_longident_loc lid2;
and module_expr i ppf x =
line i ppf "module_expr %a\n" fmt_location x.pmod_loc;
and label_x_bool_x_core_type_list i ppf x =
match x with
Rtag (l, attrs, b, ctl) ->
- line i ppf "Rtag \"%s\" %s\n" l (string_of_bool b);
+ line i ppf "Rtag \"%s\" %s\n" l.txt (string_of_bool b);
attributes (i+1) ppf attrs;
list (i+1) core_type ppf ctl
| Rinherit (ct) ->
arrayLabels.cmo : array.cmi arrayLabels.cmi
arrayLabels.cmx : array.cmx arrayLabels.cmi
arrayLabels.cmi :
-buffer.cmo : sys.cmi string.cmi bytes.cmi buffer.cmi
-buffer.cmx : sys.cmx string.cmx bytes.cmx buffer.cmi
-buffer.cmi :
+buffer.cmo : uchar.cmi sys.cmi string.cmi char.cmi bytes.cmi buffer.cmi
+buffer.cmx : uchar.cmx sys.cmx string.cmx char.cmx bytes.cmx buffer.cmi
+buffer.cmi : uchar.cmi
bytes.cmo : pervasives.cmi char.cmi bytes.cmi
bytes.cmx : pervasives.cmx char.cmx bytes.cmi
bytes.cmi :
callback.cmo : obj.cmi callback.cmi
callback.cmx : obj.cmx callback.cmi
callback.cmi :
+camlinternalBigarray.cmo : complex.cmi
+camlinternalBigarray.cmx : complex.cmx
camlinternalFormat.cmo : sys.cmi string.cmi char.cmi \
camlinternalFormatBasics.cmi bytes.cmi buffer.cmi camlinternalFormat.cmi
camlinternalFormat.cmx : sys.cmx string.cmx char.cmx \
filename.cmx : sys.cmx string.cmx random.cmx printf.cmx lazy.cmx buffer.cmx \
filename.cmi
filename.cmi :
-format.cmo : string.cmi pervasives.cmi camlinternalFormatBasics.cmi \
+format.cmo : string.cmi pervasives.cmi list.cmi camlinternalFormatBasics.cmi \
camlinternalFormat.cmi buffer.cmi format.cmi
-format.cmx : string.cmx pervasives.cmx camlinternalFormatBasics.cmx \
+format.cmx : string.cmx pervasives.cmx list.cmx camlinternalFormatBasics.cmx \
camlinternalFormat.cmx buffer.cmx format.cmi
format.cmi : pervasives.cmi buffer.cmi
gc.cmo : sys.cmi string.cmi printf.cmi gc.cmi
array.p.cmx : array.cmi
arrayLabels.cmo : array.cmi arrayLabels.cmi
arrayLabels.p.cmx : array.cmx arrayLabels.cmi
-buffer.cmo : sys.cmi string.cmi bytes.cmi buffer.cmi
-buffer.p.cmx : sys.cmx string.cmx bytes.cmx buffer.cmi
+buffer.cmo : uchar.cmi sys.cmi string.cmi char.cmi bytes.cmi buffer.cmi
+buffer.p.cmx : uchar.cmx sys.cmx string.cmx char.cmx bytes.cmx buffer.cmi
bytes.cmo : pervasives.cmi char.cmi bytes.cmi
bytes.p.cmx : pervasives.cmx char.cmx bytes.cmi
bytesLabels.cmo : bytes.cmi bytesLabels.cmi
bytesLabels.p.cmx : bytes.cmx bytesLabels.cmi
callback.cmo : obj.cmi callback.cmi
callback.p.cmx : obj.cmx callback.cmi
+camlinternalBigarray.cmo : complex.cmi
+camlinternalBigarray.p.cmx : complex.cmx
camlinternalFormat.cmo : sys.cmi string.cmi char.cmi \
camlinternalFormatBasics.cmi bytes.cmi buffer.cmi camlinternalFormat.cmi
camlinternalFormat.p.cmx : sys.cmx string.cmx char.cmx \
filename.cmi
filename.p.cmx : sys.cmx string.cmx random.cmx printf.cmx lazy.cmx buffer.cmx \
filename.cmi
-format.cmo : string.cmi pervasives.cmi camlinternalFormatBasics.cmi \
+format.cmo : string.cmi pervasives.cmi list.cmi camlinternalFormatBasics.cmi \
camlinternalFormat.cmi buffer.cmi format.cmi
-format.p.cmx : string.cmx pervasives.cmx camlinternalFormatBasics.cmx \
+format.p.cmx : string.cmx pervasives.cmx list.cmx camlinternalFormatBasics.cmx \
camlinternalFormat.cmx buffer.cmx format.cmi
gc.cmo : sys.cmi string.cmi printf.cmi gc.cmi
gc.p.cmx : sys.cmx string.cmx printf.cmx gc.cmi
filename.cmo complex.cmo \
arrayLabels.cmo listLabels.cmo bytesLabels.cmo \
stringLabels.cmo moreLabels.cmo stdLabels.cmo \
- spacetime.cmo
+ spacetime.cmo camlinternalBigarray.cmo
.PHONY: all
all: stdlib.cma std_exit.cmo camlheader target_camlheader camlheader_ur
ifeq "$(UNIX_OR_WIN32)" "unix"
$(CAMLHEADERS):
for suff in '' d i; do \
- $(BYTECC) $(BYTECCCOMPOPTS) $(BYTECCLINKOPTS) \
+ $(CC) $(CFLAGS) $(CPPFLAGS) -I../byterun $(LDFLAGS) \
-DRUNTIME_NAME='"$(BINDIR)/ocamlrun'$$suff'"' \
- header.c -o tmpheader$(EXE) && \
+ header.c $(OUTPUTEXE)tmpheader$(EXE) && \
strip tmpheader$(EXE) && \
mv tmpheader$(EXE) camlheader$$suff && \
- $(BYTECC) $(BYTECCCOMPOPTS) $(BYTECCLINKOPTS) \
+ $(CC) $(CFLAGS) $(CPPFLAGS) -I../byterun $(LDFLAGS) \
-DRUNTIME_NAME='"$(TARGET_BINDIR)/ocamlrun'$$suff'"' \
- header.c -o tmpheader$(EXE) && \
+ header.c $(OUTPUTEXE)tmpheader$(EXE) && \
strip tmpheader$(EXE) && \
mv tmpheader$(EXE) target_camlheader$$suff; \
done && \
# TODO: see whether there is a way to further merge the rules below
# with those above
-camlheader target_camlheader camlheader_ur:
- $(BYTECC) $(BYTECCCOMPOPTS) -c -I../byterun \
- -DRUNTIME_NAME='"ocamlrun"' headernt.c
+camlheader target_camlheader camlheader_ur: headernt.c
+ $(CC) -c $(CFLAGS) $(CPPFLAGS) -I../byterun \
+ -DRUNTIME_NAME='"ocamlrun"' $(OUTPUTOBJ)headernt.$(O) $<
$(MKEXE) -o tmpheader.exe headernt.$(O) $(EXTRALIBS)
rm -f camlheader.exe
mv tmpheader.exe camlheader
cp camlheader target_camlheader
cp camlheader camlheader_ur
-camlheaderd target_camlheaderd:
- $(BYTECC) $(BYTECCCOMPOPTS) -c -I../byterun \
- -DRUNTIME_NAME='"ocamlrund"' headernt.c
+camlheaderd target_camlheaderd: headernt.c
+ $(CC) -c $(CFLAGS) $(CPPFLAGS) -I../byterun \
+ -DRUNTIME_NAME='"ocamlrund"' $(OUTPUTOBJ)headernt.$(O) $<
$(MKEXE) -o tmpheader.exe headernt.$(O) $(EXTRALIBS)
mv tmpheader.exe camlheaderd
cp camlheaderd target_camlheaderd
-camlheaderi:
- $(BYTECC) $(BYTECCCOMPOPTS) -c -I../byterun \
- -DRUNTIME_NAME='"ocamlruni"' headernt.c
+camlheaderi: headernt.c
+ $(CC) -c $(CFLAGS) $(CPPFLAGS) -I../byterun \
+ -DRUNTIME_NAME='"ocamlruni"' $(OUTPUTOBJ)headernt.$(O)
$(MKEXE) -o tmpheader.exe headernt.$(O) $(EXTRALIBS)
mv tmpheader.exe camlheaderi
else if s.[n] = ' ' then loop (n+1)
else n
in
- try loop (String.index s ' ')
- with Not_found -> len
+ match String.index s '\t' with
+ | n -> loop (n+1)
+ | exception Not_found ->
+ begin match String.index s ' ' with
+ | n -> loop (n+1)
+ | exception Not_found -> len
+ end
let max_arg_len cur (kwd, spec, doc) =
| _ -> max cur (String.length kwd + second_word doc)
+let replace_leading_tab s =
+ let seen = ref false in
+ String.map (function '\t' when not !seen -> seen := true; ' ' | c -> c) s
+
let add_padding len ksd =
match ksd with
| (_, _, "") ->
| (kwd, (Symbol _ as spec), msg) ->
let cutcol = second_word msg in
let spaces = String.make ((max 0 (len - cutcol)) + 3) ' ' in
- (kwd, spec, "\n" ^ spaces ^ msg)
+ (kwd, spec, "\n" ^ spaces ^ replace_leading_tab msg)
| (kwd, spec, msg) ->
let cutcol = second_word msg in
let kwd_len = String.length kwd in
let diff = len - kwd_len - cutcol in
if diff <= 0 then
- (kwd, spec, msg)
+ (kwd, spec, replace_leading_tab msg)
else
let spaces = String.make diff ' ' in
- let prefix = String.sub msg 0 cutcol in
+ let prefix = String.sub (replace_leading_tab msg) 0 cutcol in
let suffix = String.sub msg cutcol (String.length msg - cutcol) in
(kwd, spec, prefix ^ spaces ^ suffix)
if provided with the same parameters. *)
val align: ?limit: int -> (key * spec * doc) list -> (key * spec * doc) list
-(** Align the documentation strings by inserting spaces at the first
- space, according to the length of the keyword. Use a
- space as the first character in a doc string if you want to
- align the whole string. The doc strings corresponding to
- [Symbol] arguments are aligned on the next line.
- @param limit options with keyword and message longer than
- [limit] will not be used to compute the alignement.
-*)
+(** Align the documentation strings by inserting spaces at the first alignment
+ separator (tab or, if tab is not found, space), according to the length of
+ the keyword. Use a alignment separator as the first character in a doc
+ string if you want to align the whole string. The doc strings corresponding
+ to [Symbol] arguments are aligned on the next line.
+ @param limit options with keyword and message longer than [limit] will not
+ be used to compute the alignment. *)
val current : int ref
(** Position (in {!Sys.argv}) of the argument being processed. You can
external create_float: int -> float array = "caml_make_float_vect"
let make_float = create_float
+module Floatarray = struct
+ external create : int -> floatarray = "caml_floatarray_create"
+ external length : floatarray -> int = "%floatarray_length"
+ external get : floatarray -> int -> float = "%floatarray_safe_get"
+ external set : floatarray -> int -> float -> unit = "%floatarray_safe_set"
+ external unsafe_get : floatarray -> int -> float = "%floatarray_unsafe_get"
+ external unsafe_set : floatarray -> int -> float -> unit
+ = "%floatarray_unsafe_set"
+end
+
let init l f =
if l = 0 then [||] else
if l < 0 then invalid_arg "Array.init"
of [l]. *)
-(** {6 Iterators} *)
+(** {1 Iterators} *)
val iter : ('a -> unit) -> 'a array -> unit
where [n] is the length of the array [a]. *)
-(** {6 Iterators on two arrays} *)
+(** {1 Iterators on two arrays} *)
val iter2 : ('a -> 'b -> unit) -> 'a array -> 'b array -> unit
@since 4.03.0 *)
-(** {6 Array scanning} *)
+(** {1 Array scanning} *)
val for_all : ('a -> bool) -> 'a array -> bool
@since 4.03.0 *)
-(** {6 Sorting} *)
+(** {1 Sorting} *)
val sort : ('a -> 'a -> int) -> 'a array -> unit
(**/**)
-(** {6 Undocumented functions} *)
+(** {1 Undocumented functions} *)
(* The following is for system use only. Do not call directly. *)
external unsafe_get : 'a array -> int -> 'a = "%array_unsafe_get"
external unsafe_set : 'a array -> int -> 'a -> unit = "%array_unsafe_set"
+
+module Floatarray : sig
+ external create : int -> floatarray = "caml_floatarray_create"
+ external length : floatarray -> int = "%floatarray_length"
+ external get : floatarray -> int -> float = "%floatarray_safe_get"
+ external set : floatarray -> int -> float -> unit = "%floatarray_safe_set"
+ external unsafe_get : floatarray -> int -> float = "%floatarray_unsafe_get"
+ external unsafe_set : floatarray -> int -> float -> unit
+ = "%floatarray_unsafe_set"
+end
{!Array.create_float}. *)
-(** {6 Sorting} *)
+(** {1 Sorting} *)
val sort : cmp:('a -> 'a -> int) -> 'a array -> unit
(**/**)
-(** {6 Undocumented functions} *)
+(** {1 Undocumented functions} *)
(* The following is for system use only. Do not call directly. *)
external unsafe_get : 'a array -> int -> 'a = "%array_unsafe_get"
external unsafe_set : 'a array -> int -> 'a -> unit = "%array_unsafe_set"
+
+module Floatarray : sig
+ external create : int -> floatarray = "caml_floatarray_create"
+ external length : floatarray -> int = "%floatarray_length"
+ external get : floatarray -> int -> float = "%floatarray_safe_get"
+ external set : floatarray -> int -> float -> unit = "%floatarray_safe_set"
+ external unsafe_get : floatarray -> int -> float = "%floatarray_unsafe_get"
+ external unsafe_set : floatarray -> int -> float -> unit
+ = "%floatarray_unsafe_set"
+end
Bytes.unsafe_set b.buffer pos c;
b.position <- pos + 1
+ let add_utf_8_uchar b u = match Uchar.to_int u with
+ | u when u < 0 -> assert false
+ | u when u <= 0x007F ->
+ add_char b (Char.unsafe_chr u)
+ | u when u <= 0x07FF ->
+ let pos = b.position in
+ if pos + 2 > b.length then resize b 2;
+ Bytes.unsafe_set b.buffer (pos )
+ (Char.unsafe_chr (0xC0 lor (u lsr 6)));
+ Bytes.unsafe_set b.buffer (pos + 1)
+ (Char.unsafe_chr (0x80 lor (u land 0x3F)));
+ b.position <- pos + 2
+ | u when u <= 0xFFFF ->
+ let pos = b.position in
+ if pos + 3 > b.length then resize b 3;
+ Bytes.unsafe_set b.buffer (pos )
+ (Char.unsafe_chr (0xE0 lor (u lsr 12)));
+ Bytes.unsafe_set b.buffer (pos + 1)
+ (Char.unsafe_chr (0x80 lor ((u lsr 6) land 0x3F)));
+ Bytes.unsafe_set b.buffer (pos + 2)
+ (Char.unsafe_chr (0x80 lor (u land 0x3F)));
+ b.position <- pos + 3
+ | u when u <= 0x10FFFF ->
+ let pos = b.position in
+ if pos + 4 > b.length then resize b 4;
+ Bytes.unsafe_set b.buffer (pos )
+ (Char.unsafe_chr (0xF0 lor (u lsr 18)));
+ Bytes.unsafe_set b.buffer (pos + 1)
+ (Char.unsafe_chr (0x80 lor ((u lsr 12) land 0x3F)));
+ Bytes.unsafe_set b.buffer (pos + 2)
+ (Char.unsafe_chr (0x80 lor ((u lsr 6) land 0x3F)));
+ Bytes.unsafe_set b.buffer (pos + 3)
+ (Char.unsafe_chr (0x80 lor (u land 0x3F)));
+ b.position <- pos + 4
+ | _ -> assert false
+
+ let add_utf_16be_uchar b u = match Uchar.to_int u with
+ | u when u < 0 -> assert false
+ | u when u <= 0xFFFF ->
+ let pos = b.position in
+ if pos + 2 > b.length then resize b 2;
+ Bytes.unsafe_set b.buffer (pos ) (Char.unsafe_chr (u lsr 8));
+ Bytes.unsafe_set b.buffer (pos + 1) (Char.unsafe_chr (u land 0xFF));
+ b.position <- pos + 2
+ | u when u <= 0x10FFFF ->
+ let u' = u - 0x10000 in
+ let hi = 0xD800 lor (u' lsr 10) in
+ let lo = 0xDC00 lor (u' land 0x3FF) in
+ let pos = b.position in
+ if pos + 4 > b.length then resize b 4;
+ Bytes.unsafe_set b.buffer (pos ) (Char.unsafe_chr (hi lsr 8));
+ Bytes.unsafe_set b.buffer (pos + 1) (Char.unsafe_chr (hi land 0xFF));
+ Bytes.unsafe_set b.buffer (pos + 2) (Char.unsafe_chr (lo lsr 8));
+ Bytes.unsafe_set b.buffer (pos + 3) (Char.unsafe_chr (lo land 0xFF));
+ b.position <- pos + 4
+ | _ -> assert false
+
+ let add_utf_16le_uchar b u = match Uchar.to_int u with
+ | u when u < 0 -> assert false
+ | u when u <= 0xFFFF ->
+ let pos = b.position in
+ if pos + 2 > b.length then resize b 2;
+ Bytes.unsafe_set b.buffer (pos ) (Char.unsafe_chr (u land 0xFF));
+ Bytes.unsafe_set b.buffer (pos + 1) (Char.unsafe_chr (u lsr 8));
+ b.position <- pos + 2
+ | u when u <= 0x10FFFF ->
+ let u' = u - 0x10000 in
+ let hi = 0xD800 lor (u' lsr 10) in
+ let lo = 0xDC00 lor (u' land 0x3FF) in
+ let pos = b.position in
+ if pos + 4 > b.length then resize b 4;
+ Bytes.unsafe_set b.buffer (pos ) (Char.unsafe_chr (hi land 0xFF));
+ Bytes.unsafe_set b.buffer (pos + 1) (Char.unsafe_chr (hi lsr 8));
+ Bytes.unsafe_set b.buffer (pos + 2) (Char.unsafe_chr (lo land 0xFF));
+ Bytes.unsafe_set b.buffer (pos + 3) (Char.unsafe_chr (lo lsr 8));
+ b.position <- pos + 4
+ | _ -> assert false
+
let add_substring b s offset len =
if offset < 0 || len < 0 || offset > String.length s - len
then invalid_arg "Buffer.add_substring/add_subbytes";
val add_char : t -> char -> unit
(** [add_char b c] appends the character [c] at the end of buffer [b]. *)
+val add_utf_8_uchar : t -> Uchar.t -> unit
+(** [add_utf_8_uchar b u] appends the {{:https://tools.ietf.org/html/rfc3629}
+ UTF-8} encoding of [u] at the end of buffer [b].
+
+ @since 4.06.0 *)
+
+val add_utf_16le_uchar : t -> Uchar.t -> unit
+(** [add_utf_16le_uchar b u] appends the
+ {{:https://tools.ietf.org/html/rfc2781}UTF-16LE} encoding of [u]
+ at the end of buffer [b].
+
+ @since 4.06.0 *)
+
+val add_utf_16be_uchar : t -> Uchar.t -> unit
+(** [add_utf_16be_uchar b u] appends the
+ {{:https://tools.ietf.org/html/rfc2781}UTF-16BE} encoding of [u]
+ at the end of buffer [b].
+
+ @since 4.06.0 *)
+
val add_string : t -> string -> unit
(** [add_string b s] appends the string [s] at the end of buffer [b]. *)
(** The equality function for byte sequences.
@since 4.03.0 *)
-(** {4 Unsafe conversions (for advanced users)}
+(** {3 Unsafe conversions (for advanced users)}
This section describes unsafe, low-level conversion functions
between [bytes] and [string]. They do not copy the internal data;
Raise [Invalid_argument] if [start] and [len] do not designate a
valid range of [s]. *)
-val sub_string : bytes -> int -> int -> string
+val sub_string : bytes -> pos:int -> len:int -> string
(** Same as [sub] but return a string instead of a byte sequence. *)
val extend : bytes -> left:int -> right:int -> bytes
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Manuel Serrano and Xavier Leroy, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2000 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Bigarray types. These must be kept in sync with the tables in
+ ../typing/typeopt.ml *)
+
+type float32_elt = Float32_elt
+type float64_elt = Float64_elt
+type int8_signed_elt = Int8_signed_elt
+type int8_unsigned_elt = Int8_unsigned_elt
+type int16_signed_elt = Int16_signed_elt
+type int16_unsigned_elt = Int16_unsigned_elt
+type int32_elt = Int32_elt
+type int64_elt = Int64_elt
+type int_elt = Int_elt
+type nativeint_elt = Nativeint_elt
+type complex32_elt = Complex32_elt
+type complex64_elt = Complex64_elt
+
+type ('a, 'b) kind =
+ Float32 : (float, float32_elt) kind
+ | Float64 : (float, float64_elt) kind
+ | Int8_signed : (int, int8_signed_elt) kind
+ | Int8_unsigned : (int, int8_unsigned_elt) kind
+ | Int16_signed : (int, int16_signed_elt) kind
+ | Int16_unsigned : (int, int16_unsigned_elt) kind
+ | Int32 : (int32, int32_elt) kind
+ | Int64 : (int64, int64_elt) kind
+ | Int : (int, int_elt) kind
+ | Nativeint : (nativeint, nativeint_elt) kind
+ | Complex32 : (Complex.t, complex32_elt) kind
+ | Complex64 : (Complex.t, complex64_elt) kind
+ | Char : (char, int8_unsigned_elt) kind
+
+type c_layout = C_layout_typ
+type fortran_layout = Fortran_layout_typ
+
+type 'a layout =
+ C_layout: c_layout layout
+ | Fortran_layout: fortran_layout layout
+
+type ('a, 'b, 'c) genarray
| Ignored_float (pad_opt, prec_opt) ->
Param_format_EBB
(Float (Float_f, pad_of_pad_opt pad_opt, prec_of_prec_opt prec_opt, fmt))
- | Ignored_bool ->
- Param_format_EBB (Bool fmt)
+ | Ignored_bool pad_opt ->
+ Param_format_EBB (Bool (pad_of_pad_opt pad_opt, fmt))
| Ignored_format_arg (pad_opt, fmtty) ->
Param_format_EBB (Format_arg (pad_opt, fmtty, fmt))
| Ignored_format_subst (pad_opt, fmtty) ->
(***)
-(* Print the optionnal '+', ' ' or '#' associated to an int conversion. *)
+(* Print the optional '+', ' ' or '#' associated to an int conversion. *)
let bprint_iconv_flag buf iconv = match iconv with
| Int_pd | Int_pi -> buffer_add_char buf '+'
| Int_sd | Int_si -> buffer_add_char buf ' '
(***)
-(* Print the optionnal '+' associated to a float conversion. *)
+(* Print the optional '+' associated to a float conversion. *)
let bprint_fconv_flag buf fconv = match fconv with
| Float_pf | Float_pe | Float_pE
| Float_pg | Float_pG | Float_ph | Float_pH ->
| Caml_char rest ->
buffer_add_char buf '%'; bprint_ignored_flag buf ign_flag;
buffer_add_char buf 'C'; fmtiter rest false;
- | Bool rest ->
+ | Bool (pad, rest) ->
buffer_add_char buf '%'; bprint_ignored_flag buf ign_flag;
- buffer_add_char buf 'B'; fmtiter rest false;
+ bprint_padding buf pad; buffer_add_char buf 'B';
+ fmtiter rest false;
| Alpha rest ->
buffer_add_char buf '%'; bprint_ignored_flag buf ign_flag;
buffer_add_char buf 'a'; fmtiter rest false;
| Char rest -> Char_ty (fmtty_of_fmt rest)
| Caml_char rest -> Char_ty (fmtty_of_fmt rest)
- | Bool rest -> Bool_ty (fmtty_of_fmt rest)
+ | Bool (pad, rest) -> fmtty_of_padding_fmtty pad (Bool_ty (fmtty_of_fmt rest))
| Alpha rest -> Alpha_ty (fmtty_of_fmt rest)
| Theta rest -> Theta_ty (fmtty_of_fmt rest)
| Custom (arity, _, rest) -> fmtty_of_custom arity (fmtty_of_fmt rest)
| Ignored_nativeint (_, _) -> fmtty_of_fmt fmt
| Ignored_int64 (_, _) -> fmtty_of_fmt fmt
| Ignored_float (_, _) -> fmtty_of_fmt fmt
- | Ignored_bool -> fmtty_of_fmt fmt
+ | Ignored_bool _ -> fmtty_of_fmt fmt
| Ignored_format_arg _ -> fmtty_of_fmt fmt
| Ignored_format_subst (_, fmtty) -> concat_fmtty fmtty (fmtty_of_fmt fmt)
| Ignored_reader -> Ignored_reader_ty (fmtty_of_fmt fmt)
(* Type a format according to an fmtty. *)
(* If typing succeed, generate a copy of the format with the same
type parameters as the fmtty. *)
-(* Raise a Failure with an error message in case of type mismatch. *)
+(* Raise [Failure] with an error message in case of type mismatch. *)
let rec type_format :
type a1 b1 c1 d1 e1 f1
a2 b2 c2 d2 e2 f2 .
Fmt_fmtty_EBB (Float (fconv, pad, prec, fmt'), fmtty')
| Padprec_fmtty_EBB (_, _, _) -> raise Type_mismatch
)
- | Bool fmt_rest, Bool_ty fmtty_rest ->
- let Fmt_fmtty_EBB (fmt', fmtty') = type_format_gen fmt_rest fmtty_rest in
- Fmt_fmtty_EBB (Bool fmt', fmtty')
+ | Bool (pad, fmt_rest), _ -> (
+ match type_padding pad fmtty with
+ | Padding_fmtty_EBB (pad, Bool_ty fmtty_rest) ->
+ let Fmt_fmtty_EBB (fmt', fmtty') = type_format_gen fmt_rest fmtty_rest in
+ Fmt_fmtty_EBB (Bool (pad, fmt'), fmtty')
+ | Padding_fmtty_EBB (_, _) -> raise Type_mismatch
+ )
| Flush fmt_rest, fmtty_rest ->
let Fmt_fmtty_EBB (fmt', fmtty') = type_format_gen fmt_rest fmtty_rest in
Fmt_fmtty_EBB (Flush fmt', fmtty')
| Ignored_nativeint _ as ign' -> type_ignored_param_one ign' fmt fmtty
| Ignored_int64 _ as ign' -> type_ignored_param_one ign' fmt fmtty
| Ignored_float _ as ign' -> type_ignored_param_one ign' fmt fmtty
- | Ignored_bool as ign' -> type_ignored_param_one ign' fmt fmtty
+ | Ignored_bool _ as ign' -> type_ignored_param_one ign' fmt fmtty
| Ignored_scan_char_set _ as ign' -> type_ignored_param_one ign' fmt fmtty
| Ignored_scan_get_counter _ as ign' -> type_ignored_param_one ign' fmt fmtty
| Ignored_scan_next_char as ign' -> type_ignored_param_one ign' fmt fmtty
(******************************************************************************)
(* Printing tools *)
-(* Add padding spaces arround a string. *)
+(* Add padding spaces around a string. *)
let fix_padding padty width str =
let len = String.length str in
let width, padty =
let new_acc = Acc_data_string (acc, format_caml_char c) in
make_printf k o new_acc rest
| String (pad, rest) ->
- make_string_padding k o acc rest pad (fun str -> str)
+ make_padding k o acc rest pad (fun str -> str)
| Caml_string (pad, rest) ->
- make_string_padding k o acc rest pad string_to_caml_string
+ make_padding k o acc rest pad string_to_caml_string
| Int (iconv, pad, prec, rest) ->
make_int_padding_precision k o acc rest pad prec convert_int iconv
| Int32 (iconv, pad, prec, rest) ->
make_int_padding_precision k o acc rest pad prec convert_int64 iconv
| Float (fconv, pad, prec, rest) ->
make_float_padding_precision k o acc rest pad prec fconv
- | Bool rest ->
- fun b -> make_printf k o (Acc_data_string (acc, string_of_bool b)) rest
+ | Bool (pad, rest) ->
+ make_padding k o acc rest pad string_of_bool
| Alpha rest ->
fun f x -> make_printf k o (Acc_delay (acc, fun o -> f o x)) rest
| Theta rest ->
| Ignored_nativeint (_, _) -> make_invalid_arg k o acc fmt
| Ignored_int64 (_, _) -> make_invalid_arg k o acc fmt
| Ignored_float (_, _) -> make_invalid_arg k o acc fmt
- | Ignored_bool -> make_invalid_arg k o acc fmt
+ | Ignored_bool _ -> make_invalid_arg k o acc fmt
| Ignored_format_arg _ -> make_invalid_arg k o acc fmt
| Ignored_format_subst (_, fmtty) -> make_from_fmtty k o acc fmtty fmt
| Ignored_reader -> assert false
make_printf k o (Acc_invalid_arg (acc, "Printf: bad conversion %_")) fmt
(* Fix padding, take it as an extra integer argument if needed. *)
-and make_string_padding : type x z a b c d e f .
+and make_padding : type x z a b c d e f .
(b -> (b, c) acc -> f) -> b -> (b, c) acc ->
(a, b, c, d, e, f) fmt ->
(x, z -> a) padding -> (z -> string) -> x =
fn_of_padding_precision k o rest pad prec
| Float (_, pad, prec, rest) ->
fn_of_padding_precision k o rest pad prec
- | Bool rest ->
+ | Bool (No_padding, rest) ->
const (make_iprintf k o rest)
+ | Bool (Lit_padding _, rest) ->
+ const (make_iprintf k o rest)
+ | Bool (Arg_padding _, rest) ->
+ const (const (make_iprintf k o rest))
| Alpha rest ->
const (const (make_iprintf k o rest))
| Theta rest ->
| End_of_acc -> ()
(******************************************************************************)
- (* Error managment *)
+ (* Error management *)
-(* Raise a Failure with a pretty-printed error message. *)
+(* Raise [Failure] with a pretty-printed error message. *)
let failwith_message (Format (fmt, _)) =
let buf = Buffer.create 256 in
let k () acc = strput_acc buf acc; failwith (Buffer.contents buf) in
| Lit_precision p -> Precision_fmt_EBB (Lit_precision p, fmt)
| Arg_precision -> Precision_fmt_EBB (Arg_precision, fmt)
-(* Create a padprec_fmt_ebb forma a padding, a precision and a format. *)
+(* Create a padprec_fmt_ebb from a padding, a precision and a format. *)
(* Copy the padding and the precision to disjoin type parameters of arguments
and result. *)
let make_padprec_fmt_ebb : type x y z t .
(* Format parsing *)
(* Parse a string representing a format and create a fmt_ebb. *)
-(* Raise an Failure exception in case of invalid format. *)
+(* Raise [Failure] in case of invalid format. *)
let fmt_ebb_of_string ?legacy_behavior str =
(* Parameters naming convention: *)
(* - lit_start: start of the literal sequence. *)
A typical example would be "%+ d": specifying both '+' (if the
number is positive, pad with a '+' to get the same width as
- negative numbres) and ' ' (if the number is positive, pad with
+ negative numbers) and ' ' (if the number is positive, pad with
a space) does not make sense, but the legacy (< 4.02)
implementation was happy to just ignore the space.
*)
in
- (* Raise a Failure with a friendly error message. *)
+ (* Raise [Failure] with a friendly error message. *)
let invalid_format_message str_ind msg =
failwith_message
"invalid format %S: at character number %d, %s"
- str str_ind msg;
+ str str_ind msg
in
- (* Used when the end of the format (or the current sub-format) was encoutered
+ (* Used when the end of the format (or the current sub-format) was encountered
unexpectedly. *)
let unexpected_end_of_format end_ind =
invalid_format_message end_ind
invalid_format_message str_ind
"non-zero widths are unsupported for %c conversions"
in
- (* Raise Failure with a friendly error message about an option dependencie
+ (* Raise [Failure] with a friendly error message about an option dependency
problem. *)
let invalid_format_without str_ind c s =
failwith_message
str str_ind c s
in
- (* Raise Failure with a friendly error message about an unexpected
+ (* Raise [Failure] with a friendly error message about an unexpected
character. *)
let expected_character str_ind expected read =
failwith_message
| '0' .. '9' -> parse_literal minus str_ind
| ('+' | '-') as symb when legacy_behavior ->
(* Legacy mode would accept and ignore '+' or '-' before the
- integer describing the desired precision; not that this
+ integer describing the desired precision; note that this
cannot happen for padding width, as '+' and '-' already have
a semantics there.
first pad with zeros... To add insult to the injury, the
legacy implementation ignores the 0-padding indication and
does the 5 padding with spaces instead. We reuse this
- interpretation for compatiblity, but statically reject this
+ interpretation for compatibility, but statically reject this
format when the legacy mode is disabled, to protect strict
users from this corner case. *)
match get_pad (), get_prec () with
make_padprec_fmt_ebb (get_pad ()) (get_prec ()) fmt_rest in
Fmt_EBB (Float (fconv, pad', prec', fmt_rest'))
| 'b' | 'B' ->
+ let pad = check_no_0 symb (get_padprec ()) in
let Fmt_EBB fmt_rest = parse str_ind end_ind in
- if get_ign () then Fmt_EBB (Ignored_param (Ignored_bool, fmt_rest))
- else Fmt_EBB (Bool fmt_rest)
+ if get_ign () then
+ let ignored = Ignored_bool (get_padprec_opt '_') in
+ Fmt_EBB (Ignored_param (ignored, fmt_rest))
+ else
+ let Padding_fmt_EBB (pad', fmt_rest') =
+ make_padding_fmt_ebb pad fmt_rest in
+ Fmt_EBB (Bool (pad', fmt_rest'))
| 'a' ->
let Fmt_EBB fmt_rest = parse str_ind end_ind in
Fmt_EBB (Alpha fmt_rest)
)
| _ -> ()
- (* Try to read the optionnal <name> after "@{" or "@[". *)
+ (* Try to read the optional <name> after "@{" or "@[". *)
and parse_tag : type e f . bool -> int -> int -> (_, _, e, f) fmt_ebb =
fun is_open_tag str_ind end_ind ->
try
if is_open_tag then Open_tag sub_format else Open_box sub_format in
Fmt_EBB (Formatting_gen (formatting, fmt_rest))
- (* Try to read the optionnal <width offset> after "@;". *)
+ (* Try to read the optional <width offset> after "@;". *)
and parse_good_break : type e f . int -> int -> (_, _, e, f) fmt_ebb =
fun str_ind end_ind ->
let next_ind, formatting_lit =
let fail_single_percent str_ind =
failwith_message
"invalid format %S: '%%' alone is not accepted in character sets, \
- use %%%% instead at position %d." str str_ind;
+ use %%%% instead at position %d." str str_ind
in
(* Parse the first character of a char set. *)
let rec parse_char_set_start str_ind end_ind =
if str_ind = end_ind then unexpected_end_of_format end_ind;
let c = str.[str_ind] in
- parse_char_set_after_char (str_ind + 1) end_ind c;
+ parse_char_set_after_char (str_ind + 1) end_ind c
(* Parse the content of a char set until the first ']'. *)
and parse_char_set_content str_ind end_ind =
str_ind + 1
| '-' ->
add_char '-';
- parse_char_set_content (str_ind + 1) end_ind;
+ parse_char_set_content (str_ind + 1) end_ind
| c ->
- parse_char_set_after_char (str_ind + 1) end_ind c;
+ parse_char_set_after_char (str_ind + 1) end_ind c
(* Test for range in char set. *)
and parse_char_set_after_char str_ind end_ind c =
search_subformat_end (sub_end + 2) end_ind c
| '}' ->
(* Error: %(...%}. *)
- expected_character (str_ind + 1) "character ')'" '}';
+ expected_character (str_ind + 1) "character ')'" '}'
| ')' ->
(* Error: %{...%). *)
- expected_character (str_ind + 1) "character '}'" ')';
+ expected_character (str_ind + 1) "character '}'" ')'
| _ ->
search_subformat_end (str_ind + 2) end_ind c
end
else incompatible_flag pct_ind str_ind symb "'+'"
| false, false, _ -> assert false
- (* Raise a Failure with a friendly error message about incompatible options.*)
+ (* Raise [Failure] with a friendly error message about incompatible options.*)
and incompatible_flag : type a . int -> int -> char -> string -> a =
fun pct_ind str_ind symb option ->
let subfmt = String.sub str pct_ind (str_ind - pct_ind) in
failwith_message
"invalid format %S: at character number %d, \
%s is incompatible with '%c' in sub-format %S"
- str pct_ind option symb subfmt;
+ str pct_ind option symb subfmt
in parse 0 (String.length str)
(* Guarded string to format conversions *)
(* Convert a string to a format according to an fmtty. *)
-(* Raise a Failure with an error message in case of type mismatch. *)
+(* Raise [Failure] with an error message in case of type mismatch. *)
let format_of_string_fmtty str fmtty =
let Fmt_EBB fmt = fmt_ebb_of_string str in
try Format (type_format fmt fmtty, str)
str (string_of_fmtty fmtty)
(* Convert a string to a format compatible with an other format. *)
-(* Raise a Failure with an error message in case of type mismatch. *)
+(* Raise [Failure] with an error message in case of type mismatch. *)
let format_of_string_format str (Format (fmt', str')) =
let Fmt_EBB fmt = fmt_ebb_of_string str in
try Format (type_format fmt (fmtty_of_fmt fmt'), str)
NOTE [1]: the typing of Format_subst_ty requires not one format type, but
two, one to establish the link between the format argument and the
first six parameters, and the other for the link between the format
-argumant and the last six parameters.
+argument and the last six parameters.
| Format_subst_ty : (* %(...%) *)
('g, 'h, 'i, 'j, 'k, 'l,
-> ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
'a3, 'b3, 'c3, 'd3, 'e3, 'f3) fmtty_rel
-does assume that the two input have exactly the same term structure
+does assume that the two inputs have exactly the same term structure
(and is only every used for argument witnesses of the
Format_subst_ty constructor).
*)
when it leads to a new indentation of the current line *)
| Pp_fits (* Internal usage: when a block fits on a single line *)
-(* Formatting element used by the Format pretty-printter. *)
+(* Formatting element used by the Format pretty-printer. *)
type formatting_lit =
| Close_box (* @] *)
| Close_tag (* @} *)
| Escaped_percent (* @%% *)
| Scan_indic of char (* @X *)
-(* Formatting element used by the Format pretty-printter. *)
+(* Formatting element used by the Format pretty-printer. *)
type ('a, 'b, 'c, 'd, 'e, 'f) formatting_gen =
| Open_tag : ('a, 'b, 'c, 'd, 'e, 'f) format6 -> (* @{ *)
('a, 'b, 'c, 'd, 'e, 'f) formatting_gen
('a, 'b, 'c, 'd, 'e, 'f) fmt ->
('x, 'b, 'c, 'd, 'e, 'f) fmt
| Bool : (* %[bB] *)
- ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- (bool -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
+ ('x, bool -> 'a) padding * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x, 'b, 'c, 'd, 'e, 'f) fmt
| Flush : (* %! *)
('a, 'b, 'c, 'd, 'e, 'f) fmt ->
('a, 'b, 'c, 'd, 'e, 'f) fmt
We include a type Custom of "custom converters", where an
arbitrary function can be used to convert one or more
arguments. There is no syntax for custom converters, it is only
- inteded for custom processors that wish to rely on the
+ intended for custom processors that wish to rely on the
stdlib-defined format GADTs.
For instance a pre-processor could choose to interpret strings
| Ignored_float : (* %_f *)
pad_option * prec_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
| Ignored_bool : (* %_B *)
- ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
| Ignored_format_arg : (* %_{...%} *)
pad_option * ('g, 'h, 'i, 'j, 'k, 'l) fmtty ->
('a, 'b, 'c, 'd, 'd, 'a) ignored
Char (concat_fmt rest fmt2)
| Caml_char rest ->
Caml_char (concat_fmt rest fmt2)
- | Bool rest ->
- Bool (concat_fmt rest fmt2)
+ | Bool (pad, rest) ->
+ Bool (pad, concat_fmt rest fmt2)
| Alpha rest ->
Alpha (concat_fmt rest fmt2)
| Theta rest ->
('a, 'b, 'c, 'd, 'e, 'f) fmt ->
('x, 'b, 'c, 'd, 'e, 'f) fmt
| Bool : (* %[bB] *)
- ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- (bool -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
+ ('x, bool -> 'a) padding * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x, 'b, 'c, 'd, 'e, 'f) fmt
| Flush : (* %! *)
('a, 'b, 'c, 'd, 'e, 'f) fmt ->
('a, 'b, 'c, 'd, 'e, 'f) fmt
| Ignored_float :
pad_option * prec_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
| Ignored_bool :
- ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
| Ignored_format_arg :
pad_option * ('g, 'h, 'i, 'j, 'k, 'l) fmtty ->
('a, 'b, 'c, 'd, 'd, 'a) ignored
match shape with
| Function ->
if Obj.tag n = Obj.closure_tag && Obj.size n <= Obj.size o
- then begin overwrite o n; Obj.truncate o (Obj.size n) (* PR #4008 *) end
+ then begin overwrite o n; Obj.truncate o (Obj.size n) (* PR#4008 *) end
else overwrite o (Obj.repr (fun x -> (Obj.obj n : _ -> _) x))
| Lazy ->
if Obj.tag n = Obj.lazy_tag then
All functions in this module are for system use only, not for the
casual user. *)
-(** {6 Classes} *)
+(** {1 Classes} *)
type tag
type label
string * int * int ->
(t * (table -> Obj.t -> t) * (Obj.t -> t) * Obj.t)
-(** {6 Objects} *)
+(** {1 Objects} *)
val copy : (< .. > as 'a) -> 'a
val create_object : table -> obj
external get_public_method : obj -> tag -> closure
= "caml_get_public_method" [@@noalloc]
-(** {6 Table cache} *)
+(** {1 Table cache} *)
type tables
val lookup_tables : tables -> closure array -> tables
-(** {6 Builtins to reduce code size} *)
+(** {1 Builtins to reduce code size} *)
(*
val get_const : t -> closure
| SendMeth
| Closure of closure
-(** {6 Parameters} *)
+(** {1 Parameters} *)
(* currently disabled *)
type params =
val params : params
-(** {6 Statistics} *)
+(** {1 Statistics} *)
type stats =
{ classes : int;
(** Ephemerons and weak hash table *)
-(** Ephemerons and weak hash table
-
- Ephemerons and weak hash table are useful when one wants to cache
+(** Ephemerons and weak hash table are useful when one wants to cache
or memorize the computation of a function, as long as the
arguments and the function are used, without creating memory leaks
by continuously keeping old computation results that are not
useful anymore because one argument or the function is freed. An
- implementation using {Hashtbl.t} is not suitable because all
+ implementation using {!Hashtbl.t} is not suitable because all
associations would keep in memory the arguments and the result.
Ephemerons can also be used for "adding" a field to an arbitrary
(* The pretty-printing boxes definition:
a pretty-printing box is either
- - hbox: horizontal (no split in the line)
- - vbox: vertical (the line is splitted at every break hint)
- - hvbox: horizontal/vertical
+ - hbox: horizontal box (no line splitting)
+ - vbox: vertical box (every break hint splits the line)
+ - hvbox: horizontal/vertical box
(the box behaves as an horizontal box if it fits on
the current line, otherwise the box behaves as a vertical box)
- - hovbox: horizontal or vertical
- (the box is compacting material, printing as much material on every
- lines)
- - box: horizontal or vertical with box enhanced structure
+ - hovbox: horizontal or vertical compacting box
+ (the box is compacting material, printing as much material as possible
+ on every lines)
+ - box: horizontal or vertical compacting box with enhanced box structure
(the box behaves as an horizontal or vertical box but break hints split
the line if splitting would move to the left)
*)
| Pp_if_newline (* to do something only if this very
line has been broken *)
| Pp_open_tag of tag (* opening a tag name *)
- | Pp_close_tag (* closing the most recently opened tag *)
+ | Pp_close_tag (* closing the most recently open tag *)
and tag = string
mutable pp_left_total : int;
(* Total width of tokens ever put in queue. *)
mutable pp_right_total : int;
- (* Current number of opened boxes. *)
+ (* Current number of open boxes. *)
mutable pp_curr_depth : int;
- (* Maximum number of boxes which can be simultaneously opened. *)
+ (* Maximum number of boxes which can be simultaneously open. *)
mutable pp_max_boxes : int;
(* Ellipsis string. *)
mutable pp_ellipsis : string;
mutable pp_out_flush : unit -> unit;
(* Output of new lines. *)
mutable pp_out_newline : unit -> unit;
- (* Output of indentation spaces. *)
+ (* Output of break hints spaces. *)
mutable pp_out_spaces : int -> unit;
+ (* Output of indentation of new lines. *)
+ mutable pp_out_indent : int -> unit;
(* Are tags printed ? *)
mutable pp_print_tags : bool;
(* Are tags marked ? *)
out_flush : unit -> unit;
out_newline : unit -> unit;
out_spaces : int -> unit;
+ out_indent : int -> unit;
}
let pp_output_string state s = state.pp_out_string s 0 (String.length s)
and pp_output_newline state = state.pp_out_newline ()
and pp_output_spaces state n = state.pp_out_spaces n
+and pp_output_indent state n = state.pp_out_indent n
(* To format a break, indenting a new line. *)
let break_new_line state offset width =
let real_indent = min state.pp_max_indent indent in
state.pp_current_indent <- real_indent;
state.pp_space_left <- state.pp_margin - state.pp_current_indent;
- pp_output_spaces state state.pp_current_indent
+ pp_output_indent state state.pp_current_indent
(* To force a line break inside a box: no offset is added. *)
| [] -> [n]
| x :: l as ls -> if n < x then n :: ls else x :: add_tab n l in
tabs := add_tab (state.pp_margin - state.pp_space_left) !tabs
- | [] -> () (* No opened tabulation box. *)
+ | [] -> () (* No open tabulation box. *)
end
| Pp_tbreak (n, off) ->
if offset >= 0
then break_same_line state (offset + n)
else break_new_line state (tab + off) state.pp_margin
- | [] -> () (* No opened tabulation box. *)
+ | [] -> () (* No open tabulation box. *)
end
| Pp_newline ->
begin match state.pp_format_stack with
| Format_elem (_, width) :: _ -> break_line state width
- | [] -> pp_output_newline state (* No opened box. *)
+ | [] -> pp_output_newline state (* No open box. *)
end
| Pp_if_newline ->
| Pp_vbox -> break_new_line state off width
| Pp_hbox -> break_same_line state n
end
- | [] -> () (* No opened box. *)
+ | [] -> () (* No open box. *)
end
| Pp_open_tag tag_name ->
then enqueue_string state state.pp_ellipsis
-(* The box which is always opened. *)
+(* The box which is always open. *)
let pp_open_sys_box state = pp_open_box_gen state 0 Pp_hovbox
(* Close a box, setting sizes of its sub boxes. *)
state.pp_space_left <- state.pp_margin;
pp_open_sys_box state
+let clear_tag_stack state =
+ List.iter
+ (fun _ -> pp_close_tag state ())
+ state.pp_tag_stack
+
(* Flushing pretty-printer queue. *)
let pp_flush_queue state b =
+ clear_tag_stack state;
while state.pp_curr_depth > 1 do
pp_close_box state ()
done;
if b then pp_output_newline state;
pp_rinit state
-
(*
Procedures to format values and use boxes.
and pp_open_box state indent = pp_open_box_gen state indent Pp_box
-(* Printing all queued text.
- [print_newline] prints a new line after flushing the queue.
- [print_flush] on flush the queue without adding a newline. *)
+(* Printing queued text.
+
+ [pp_print_flush] prints all pending items in the pretty-printer queue and
+ then flushes the low level output device of the formatter to actually
+ display printing material.
+
+ [pp_print_newline] behaves as [pp_print_flush] after printing an additional
+ new line. *)
let pp_print_newline state () =
pp_flush_queue state true; state.pp_out_flush ()
and pp_print_flush state () =
out_flush = g;
out_newline = h;
out_spaces = i;
+ out_indent = j;
} =
state.pp_out_string <- f;
state.pp_out_flush <- g;
state.pp_out_newline <- h;
- state.pp_out_spaces <- i
-
+ state.pp_out_spaces <- i;
+ state.pp_out_indent <- j
let pp_get_formatter_out_functions state () = {
out_string = state.pp_out_string;
out_flush = state.pp_out_flush;
out_newline = state.pp_out_newline;
out_spaces = state.pp_out_spaces;
+ out_indent = state.pp_out_indent;
}
(state.pp_out_string, state.pp_out_flush)
-let pp_flush_formatter state =
- pp_flush_queue state false
-
(* The default function to output new lines. *)
let display_newline state () = state.pp_out_string "\n" 0 1
end
+(* The default function to output indentation of new lines. *)
+let display_indent = display_blanks
+
(* Setting a formatter basic output functions as printing to a given
[Pervasive.out_channel] value. *)
-let pp_set_formatter_out_channel state os =
- state.pp_out_string <- output_substring os;
- state.pp_out_flush <- (fun () -> flush os);
+let pp_set_formatter_out_channel state oc =
+ state.pp_out_string <- output_substring oc;
+ state.pp_out_flush <- (fun () -> flush oc);
state.pp_out_newline <- display_newline state;
- state.pp_out_spaces <- display_blanks state
-
+ state.pp_out_spaces <- display_blanks state;
+ state.pp_out_indent <- display_indent state
(*
let default_pp_print_open_tag = ignore
let default_pp_print_close_tag = ignore
-(* Bulding a formatter given its basic output functions.
+(* Building a formatter given its basic output functions.
Other fields get reasonable default values. *)
-let pp_make_formatter f g h i =
+let pp_make_formatter f g h i j =
(* The initial state of the formatter contains a dummy box. *)
let pp_queue = make_queue () in
let sys_tok =
pp_out_flush = g;
pp_out_newline = h;
pp_out_spaces = i;
+ pp_out_indent = j;
pp_print_tags = false;
pp_mark_tags = false;
pp_mark_open_tag = default_pp_mark_open_tag;
}
-(* Make a formatter with default functions to output spaces and new lines. *)
+(* Build a formatter out of its out functions. *)
+let formatter_of_out_functions out_funs =
+ pp_make_formatter
+ out_funs.out_string
+ out_funs.out_flush
+ out_funs.out_newline
+ out_funs.out_spaces
+ out_funs.out_indent
+
+
+(* Make a formatter with default functions to output spaces,
+ indentation, and new lines. *)
let make_formatter output flush =
- let ppf = pp_make_formatter output flush ignore ignore in
+ let ppf = pp_make_formatter output flush ignore ignore ignore in
ppf.pp_out_newline <- display_newline ppf;
ppf.pp_out_spaces <- display_blanks ppf;
+ ppf.pp_out_indent <- display_indent ppf;
ppf
(* [flush_buffer_formatter buf ppf] flushes formatter [ppf],
- then return the contents of buffer [buff] thst is reset.
+ then returns the contents of buffer [buf] that is reset.
Formatter [ppf] is supposed to print to buffer [buf], otherwise this
function is not really useful. *)
let flush_buffer_formatter buf ppf =
(* Flush [str_formatter] and get the contents of [stdbuf]. *)
let flush_str_formatter () = flush_buffer_formatter stdbuf str_formatter
+(*
+ Symbolic pretty-printing
+*)
+
+(*
+ Symbolic pretty-printing is pretty-printing with no low level output.
+
+ When using a symbolic formatter, all regular pretty-printing activities
+ occur but output material is symbolic and stored in a buffer of output
+ items. At the end of pretty-printing, flushing the output buffer allows
+ post-processing of symbolic output before low level output operations.
+*)
+
+type symbolic_output_item =
+ | Output_flush
+ | Output_newline
+ | Output_string of string
+ | Output_spaces of int
+ | Output_indent of int
+
+type symbolic_output_buffer = {
+ mutable symbolic_output_contents : symbolic_output_item list;
+}
+
+let make_symbolic_output_buffer () =
+ { symbolic_output_contents = [] }
+
+let clear_symbolic_output_buffer sob =
+ sob.symbolic_output_contents <- []
+
+let get_symbolic_output_buffer sob =
+ List.rev sob.symbolic_output_contents
+
+let flush_symbolic_output_buffer sob =
+ let items = get_symbolic_output_buffer sob in
+ clear_symbolic_output_buffer sob;
+ items
+
+let add_symbolic_output_item sob item =
+ sob.symbolic_output_contents <- item :: sob.symbolic_output_contents
+
+let formatter_of_symbolic_output_buffer sob =
+ let symbolic_flush sob () =
+ add_symbolic_output_item sob Output_flush
+ and symbolic_newline sob () =
+ add_symbolic_output_item sob Output_newline
+ and symbolic_string sob s i n =
+ add_symbolic_output_item sob (Output_string (String.sub s i n))
+ and symbolic_spaces sob n =
+ add_symbolic_output_item sob (Output_spaces n)
+ and symbolic_indent sob n =
+ add_symbolic_output_item sob (Output_indent n) in
+
+ let f = symbolic_string sob
+ and g = symbolic_flush sob
+ and h = symbolic_newline sob
+ and i = symbolic_spaces sob
+ and j = symbolic_indent sob in
+ pp_make_formatter f g h i j
+
(*
Basic functions on the 'standard' formatter
state.pp_out_newline <- h;
state.pp_out_spaces <- i
-
(* Deprecated : subsumed by pp_get_formatter_out_functions *)
let pp_get_all_formatter_output_functions state () =
(state.pp_out_string, state.pp_out_flush,
(* Deprecated : error prone function, do not use it.
- Define a formatter of your own writing to the buffer,
- as in
+ This function is neither compositional nor incremental, since it flushes
+ the pretty-printer queue at each call.
+ To get the same functionality, define a formatter of your own writing to
+ the buffer argument, as in
let ppf = formatter_of_buffer b
- then use {!fprintf ppf} as useual. *)
+ then use {!fprintf ppf} as usual. *)
let bprintf b (Format (fmt, _) : ('a, formatter, unit) format) =
let k ppf acc = output_acc ppf acc; pp_flush_queue ppf false in
make_printf k (formatter_of_buffer b) End_of_acc fmt
(* *)
(**************************************************************************)
-(** Pretty printing.
+(** Pretty-printing.
This module implements a pretty-printing facility to format values
- within 'pretty-printing boxes'. The pretty-printer splits lines
- at specified break hints, and indents lines according to the box
- structure.
+ within {{!boxes}'pretty-printing boxes'} and {{!tags}'semantic tags'}
+ combined with a set of {{!fpp}printf-like functions}.
+ The pretty-printer splits lines at specified {{!breaks}break hints},
+ and indents lines according to the box structure.
+ Similarly, {{!tags}semantic tags} can be used to decouple text
+ presentation from its contents.
+
+ This pretty-printing facility is implemented as an overlay on top of
+ abstract {{!section:formatter}formatters} which provide basic output
+ functions.
+ Some formatters are predefined, notably:
+ - {!std_formatter} outputs to {{!Pervasives.stdout}stdout}
+ - {!err_formatter} outputs to {{!Pervasives.stderr}stderr}
+
+ Most functions in the {!Format} module come in two variants:
+ a short version that operates on {!std_formatter} and the
+ generic version prefixed by [pp_] that takes a formatter
+ as its first argument.
+
+ More formatters can be created with {!formatter_of_out_channel},
+ {!formatter_of_buffer}, {!formatter_of_symbolic_output_buffer}
+ or using {{!section:formatter}custom formatters}.
+*)
+
+(** {1 Introduction}
For a gentle introduction to the basics of pretty-printing using
[Format], read
{{:http://caml.inria.fr/resources/doc/guides/format.en.html}
You may consider this module as providing an extension to the
[printf] facility to provide automatic line splitting. The addition of
- pretty-printing annotations to your regular [printf] formats gives you
- fancy indentation and line breaks.
+ pretty-printing annotations to your regular [printf] format strings gives
+ you fancy indentation and line breaks.
Pretty-printing annotations are described below in the documentation of
the function {!Format.fprintf}.
- You may also use the explicit box management and printing functions
- provided by this module. This style is more basic but more verbose
- than the [fprintf] concise formats.
+ You may also use the explicit pretty-printing box management and printing
+ functions provided by this module. This style is more basic but more
+ verbose than the concise [fprintf] format strings.
For instance, the sequence
[open_box 0; print_string "x ="; print_space ();
[printf "@[x =@ %i@]@." 1].
Rule of thumb for casual users of this library:
- - use simple boxes (as obtained by [open_box 0]);
- - use simple break hints (as obtained by [print_cut ()] that outputs a
+ - use simple pretty-printing boxes (as obtained by [open_box 0]);
+ - use simple break hints as obtained by [print_cut ()] that outputs a
simple break hint, or by [print_space ()] that outputs a space
- indicating a break hint);
- - once a box is opened, display its material with basic printing
- functions (e. g. [print_int] and [print_string]);
- - when the material for a box has been printed, call [close_box ()] to
- close the box;
- - at the end of your routine, flush the pretty-printer to display all the
- remaining material, e.g. evaluate [print_newline ()].
-
- The behaviour of pretty-printing commands is unspecified
- if there is no opened pretty-printing box. Each box opened via
+ indicating a break hint;
+ - once a pretty-printing box is open, display its material with basic
+ printing functions (e. g. [print_int] and [print_string]);
+ - when the material for a pretty-printing box has been printed, call
+ [close_box ()] to close the box;
+ - at the end of pretty-printing, flush the pretty-printer to display all
+ the remaining material, e.g. evaluate [print_newline ()].
+
+ The behavior of pretty-printing commands is unspecified
+ if there is no open pretty-printing box. Each box opened by
one of the [open_] functions below must be closed using [close_box]
for proper formatting. Otherwise, some of the material printed in the
boxes may not be output, or may be formatted incorrectly.
- In case of interactive use, the system closes all opened boxes and
- flushes all pending text (as with the [print_newline] function)
- after each phrase. Each phrase is therefore executed in the initial
- state of the pretty-printer.
+ In case of interactive use, each phrase is executed in the initial state
+ of the standard pretty-printer: after each phrase execution, the
+ interactive system closes all open pretty-printing boxes, flushes all
+ pending text, and resets the standard pretty-printer.
+
+ Warning: mixing calls to pretty-printing functions of this module with
+ calls to {!Pervasives} low level output functions is error prone.
+
+ The pretty-printing functions output material that is delayed in the
+ pretty-printer queue and stacks in order to compute proper line
+ splitting. In contrast, basic I/O output functions write directly in
+ their output device. As a consequence, the output of a basic I/O function
+ may appear before the output of a pretty-printing function that has been
+ called before. For instance,
+ [
+ Pervasives.print_string "<";
+ Format.print_string "PRETTY";
+ Pervasives.print_string ">";
+ Format.print_string "TEXT";
+ ]
+ leads to output [<>PRETTYTEXT].
- Warning: the material output by the following functions is delayed
- in the pretty-printer queue in order to compute the proper line
- splitting. Hence, you should not mix calls to the printing functions
- of the basic I/O system with calls to the functions of this module:
- this could result in some strange output seemingly unrelated with
- the evaluation order of printing commands.
*)
-(** {6 Boxes} *)
+type formatter
+(** Abstract data corresponding to a pretty-printer (also called a
+ formatter) and all its machinery. See also {!section:formatter}. *)
+
+(** {1:boxes Pretty-printing boxes} *)
+
+(** The pretty-printing engine uses the concepts of pretty-printing box and
+ break hint to drive indentation and line splitting behavior of the
+ pretty-printer.
+
+ Each different pretty-printing box kind introduces a specific line splitting
+ policy:
+
+ - within an {e horizontal} box, break hints never split the line (but the
+ line may be split in a box nested deeper),
+ - within a {e vertical} box, break hints always split the line,
+ - within an {e horizontal/vertical} box, if the box fits on the current line
+ then break hints never split the line, otherwise break hint always split
+ the line,
+ - within a {e compacting} box, a break hint never splits the line,
+ unless there is no more room on the current line.
+
+ Note that line splitting policy is box specific: the policy of a box does
+ not rule the policy of inner boxes. For instance, if a vertical box is
+ nested in an horizontal box, all break hints within the vertical box will
+ split the line.
+*)
+val pp_open_box : formatter -> int -> unit
val open_box : int -> unit
-(** [open_box d] opens a new pretty-printing box
- with offset [d].
+(** [pp_open_box ppf d] opens a new compacting pretty-printing box with
+ offset [d] in the formatter [ppf].
- This box prints material as much as possible on every line.
+ Within this box, the pretty-printer prints as much as possible material on
+ every line.
A break hint splits the line if there is no more room on the line to
print the remainder of the box.
- A break hint also splits the line if the splitting ``moves to the left''
- (i.e. it gives an indentation smaller than the one of the current line).
+
+ Within this box, the pretty-printer emphasizes the box structure: a break
+ hint also splits the line if the splitting ``moves to the left''
+ (i.e. the new line gets an indentation smaller than the one of the current
+ line).
This box is the general purpose pretty-printing box.
If the pretty-printer splits the line in the box, offset [d] is added to
- the current indentation. *)
+ the current indentation.
+*)
+
+val pp_close_box : formatter -> unit -> unit
val close_box : unit -> unit
-(** Closes the most recently opened pretty-printing box. *)
+(** Closes the most recently open pretty-printing box. *)
+
+val pp_open_hbox : formatter -> unit -> unit
+val open_hbox : unit -> unit
+(** [pp_open_hbox ppf ()] opens a new 'horizontal' pretty-printing box.
+
+ This box prints material on a single line.
+
+ Break hints in a horizontal box never split the line.
+ (Line splitting may still occur inside boxes nested deeper).
+*)
+
+val pp_open_vbox : formatter -> int -> unit
+val open_vbox : int -> unit
+(** [pp_open_vbox ppf d] opens a new 'vertical' pretty-printing box
+ with offset [d].
+
+ This box prints material on as many lines as break hints in the box.
+
+ Every break hint in a vertical box splits the line.
+
+ If the pretty-printer splits the line in the box, [d] is added to the
+ current indentation.
+*)
+
+val pp_open_hvbox : formatter -> int -> unit
+val open_hvbox : int -> unit
+(** [pp_open_hvbox ppf d] opens a new 'horizontal/vertical' pretty-printing box
+ with offset [d].
+
+ This box behaves as an horizontal box if it fits on a single line,
+ otherwise it behaves as a vertical box.
-(** {6 Formatting functions} *)
+ If the pretty-printer splits the line in the box, [d] is added to the
+ current indentation.
+*)
+val pp_open_hovbox : formatter -> int -> unit
+val open_hovbox : int -> unit
+(** [pp_open_hovbox ppf d] opens a new 'horizontal-or-vertical'
+ pretty-printing box with offset [d].
+
+ This box prints material as much as possible on every line.
+
+ A break hint splits the line if there is no more room on the line to
+ print the remainder of the box.
+
+ If the pretty-printer splits the line in the box, [d] is added to the
+ current indentation.
+*)
+
+(** {1 Formatting functions} *)
+
+val pp_print_string : formatter -> string -> unit
val print_string : string -> unit
-(** [print_string str] prints [str] in the current box. *)
+(** [pp_print_string ppf s] prints [s] in the current pretty-printing box. *)
+val pp_print_as : formatter -> int -> string -> unit
val print_as : int -> string -> unit
-(** [print_as len str] prints [str] in the
- current box. The pretty-printer formats [str] as if
- it were of length [len]. *)
+(** [pp_print_as ppf len s] prints [s] in the current pretty-printing box.
+ The pretty-printer formats [s] as if it were of length [len].
+*)
+val pp_print_int : formatter -> int -> unit
val print_int : int -> unit
-(** Prints an integer in the current box. *)
+(** Print an integer in the current pretty-printing box. *)
+val pp_print_float : formatter -> float -> unit
val print_float : float -> unit
-(** Prints a floating point number in the current box. *)
+(** Print a floating point number in the current pretty-printing box. *)
+val pp_print_char : formatter -> char -> unit
val print_char : char -> unit
-(** Prints a character in the current box. *)
+(** Print a character in the current pretty-printing box. *)
+val pp_print_bool : formatter -> bool -> unit
val print_bool : bool -> unit
-(** Prints a boolean in the current box. *)
+(** Print a boolean in the current pretty-printing box. *)
-(** {6 Break hints} *)
+(** {1:breaks Break hints} *)
(** A 'break hint' tells the pretty-printer to output some space or split the
- line whichever way is more appropriate to the current box splitting rules.
+ line whichever way is more appropriate to the current pretty-printing box
+ splitting rules.
Break hints are used to separate printing items and are mandatory to let
the pretty-printer correctly split lines and indent items.
- the 'cut': split the line if appropriate.
Note: the notions of space and line splitting are abstract for the
- pretty-printing engine, since those notions can be completely defined
+ pretty-printing engine, since those notions can be completely redefined
by the programmer.
However, in the pretty-printer default setting, ``output a space'' simply
means printing a space character (ASCII code 32) and ``split the line''
- is printing a newline character (ASCII code 10).
-
+ means printing a newline character (ASCII code 10).
*)
+val pp_print_space : formatter -> unit -> unit
val print_space : unit -> unit
-(** [print_space ()] the 'space' break hint:
- the pretty-printer may split the line at this
- point, otherwise it prints one space.
- It is equivalent to [print_break 1 0]. *)
+(** [pp_print_space ppf ()] emits a 'space' break hint:
+ the pretty-printer may split the line at this point,
+ otherwise it prints one space.
+ [pp_print_space ppf ()] is equivalent to [pp_print_break ppf 1 0].
+*)
+
+val pp_print_cut : formatter -> unit -> unit
val print_cut : unit -> unit
-(** [print_cut ()] the 'cut' break hint:
- the pretty-printer may split the line at this
- point, otherwise it prints nothing.
- It is equivalent to [print_break 0 0]. *)
+(** [pp_print_cut ppf ()] emits a 'cut' break hint:
+ the pretty-printer may split the line at this point,
+ otherwise it prints nothing.
+ [pp_print_cut ppf ()] is equivalent to [pp_print_break ppf 0 0].
+*)
+
+val pp_print_break : formatter -> int -> int -> unit
val print_break : int -> int -> unit
-(** [print_break nspaces offset] the 'full' break hint:
- the pretty-printer may split the line at this
- point, otherwise it prints [nspaces] spaces.
+(** [pp_print_break ppf nspaces offset] emits a 'full' break hint:
+ the pretty-printer may split the line at this point,
+ otherwise it prints [nspaces] spaces.
If the pretty-printer splits the line, [offset] is added to
the current indentation.
*)
-val print_flush : unit -> unit
-(** Flushes the pretty printer: all opened boxes are closed,
- and all pending text is displayed. *)
+val pp_force_newline : formatter -> unit -> unit
+val force_newline : unit -> unit
+(** Force a new line in the current pretty-printing box.
-val print_newline : unit -> unit
-(** Equivalent to [print_flush] followed by a new line. *)
+ The pretty-printer must split the line at this point,
-val force_newline : unit -> unit
-(** Forces a new line in the current box.
- Not the normal way of pretty-printing, since the new line does not reset
- the current line count.
- You should prefer using break hints within a vertcal box. *)
+ Not the normal way of pretty-printing, since imperative line splitting may
+ interfere with current line counters and box size calculation.
+ Using break hints within an enclosing vertical box is a better
+ alternative.
+*)
+val pp_print_if_newline : formatter -> unit -> unit
val print_if_newline : unit -> unit
-(** Executes the next formatting command if the preceding line
+(** Execute the next formatting command if the preceding line
has just been split. Otherwise, ignore the next formatting
- command. *)
+ command.
+*)
-(** {6 Margin} *)
+(** {1 Pretty-printing termination} *)
+val pp_print_flush : formatter -> unit -> unit
+val print_flush : unit -> unit
+(** End of pretty-printing: resets the pretty-printer to initial state.
+
+ All open pretty-printing boxes are closed, all pending text is printed.
+ In addition, the pretty-printer low level output device is flushed to
+ ensure that all pending text is really displayed.
+
+ Note: never use [print_flush] in the normal course of a pretty-printing
+ routine, since the pretty-printer uses a complex buffering machinery to
+ properly indent the output; manually flushing those buffers at random
+ would conflict with the pretty-printer strategy and result to poor
+ rendering.
+
+ Only consider using [print_flush] when displaying all pending material is
+ mandatory (for instance in case of interactive use when you want the user
+ to read some text) and when resetting the pretty-printer state will not
+ disturb further pretty-printing.
+
+ Warning: If the output device of the pretty-printer is an output channel,
+ repeated calls to [print_flush] means repeated calls to {!Pervasives.flush}
+ to flush the out channel; these explicit flush calls could foil the
+ buffering strategy of output channels and could dramatically impact
+ efficiency.
+*)
+
+val pp_print_newline : formatter -> unit -> unit
+val print_newline : unit -> unit
+(** End of pretty-printing: resets the pretty-printer to initial state.
+
+ All open pretty-printing boxes are closed, all pending text is printed.
+
+ Equivalent to {!print_flush} followed by a new line.
+ See corresponding words of caution for {!print_flush}.
+
+ Note: this is not the normal way to output a new line;
+ the preferred method is using break hints within a vertical pretty-printing
+ box.
+*)
+
+(** {1 Margin} *)
+
+val pp_set_margin : formatter -> int -> unit
val set_margin : int -> unit
-(** [set_margin d] sets the right margin to [d] (in characters):
+(** [pp_set_margin ppf d] sets the right margin to [d] (in characters):
the pretty-printer splits lines that overflow the right margin according to
the break hints given.
Nothing happens if [d] is smaller than 2.
If [d] is too large, the right margin is set to the maximum
- admissible value (which is greater than [10^9]). *)
+ admissible value (which is greater than [10 ^ 9]).
+ If [d] is less than the current maximum indentation limit, the
+ maximum indentation limit is decreased while trying to preserve
+ a minimal ratio [max_indent/margin>=50%] and if possible
+ the current difference [margin - max_indent].
+*)
+val pp_get_margin : formatter -> unit -> int
val get_margin : unit -> int
(** Returns the position of the right margin. *)
-(** {6 Maximum indentation limit} *)
+(** {1 Maximum indentation limit} *)
+val pp_set_max_indent : formatter -> int -> unit
val set_max_indent : int -> unit
-(** [set_max_indent d] sets the maximum indentation limit of lines to [d] (in
- characters):
- once this limit is reached, new boxes are rejected to the left,
- if they do not fit on the current line.
+(** [pp_set_max_indent ppf d] sets the maximum indentation limit of lines
+ to [d] (in characters):
+ once this limit is reached, new pretty-printing boxes are rejected to the
+ left, if they do not fit on the current line.
+
Nothing happens if [d] is smaller than 2.
If [d] is too large, the limit is set to the maximum
- admissible value (which is greater than [10 ^ 9]). *)
+ admissible value (which is greater than [10 ^ 9]).
+
+ If [d] is greater or equal than the current margin, it is ignored,
+ and the current maximum indentation limit is kept.
+*)
+val pp_get_max_indent : formatter -> unit -> int
val get_max_indent : unit -> int
(** Return the maximum indentation limit (in characters). *)
-(** {6 Formatting depth: maximum number of boxes allowed before ellipsis} *)
+(** {1 Maximum formatting depth} *)
+
+(** The maximum formatting depth is the maximum number of pretty-printing
+ boxes simultaneously open.
+ Material inside boxes nested deeper is printed as an ellipsis (more
+ precisely as the text returned by {!get_ellipsis_text} [()]).
+*)
+
+val pp_set_max_boxes : formatter -> int -> unit
val set_max_boxes : int -> unit
-(** [set_max_boxes max] sets the maximum number of boxes simultaneously
- opened.
+(** [pp_set_max_boxes ppf max] sets the maximum number of pretty-printing
+ boxes simultaneously open.
+
Material inside boxes nested deeper is printed as an ellipsis (more
- precisely as the text returned by [get_ellipsis_text ()]).
- Nothing happens if [max] is smaller than 2. *)
+ precisely as the text returned by {!get_ellipsis_text} [()]).
+ Nothing happens if [max] is smaller than 2.
+*)
+
+val pp_get_max_boxes : formatter -> unit -> int
val get_max_boxes : unit -> int
-(** Returns the maximum number of boxes allowed before ellipsis. *)
+(** Returns the maximum number of pretty-printing boxes allowed before
+ ellipsis.
+*)
+val pp_over_max_boxes : formatter -> unit -> bool
val over_max_boxes : unit -> bool
-(** Tests if the maximum number of boxes allowed have already been opened. *)
+(** Tests if the maximum number of pretty-printing boxes allowed have already
+ been opened.
+*)
-(** {6 Advanced formatting} *)
+(** {1 Tabulation boxes} *)
-val open_hbox : unit -> unit
-(** [open_hbox ()] opens a new 'horizontal' pretty-printing box.
+(**
- This box prints material on a single line.
+ A {e tabulation box} prints material on lines divided into cells of fixed
+ length. A tabulation box provides a simple way to display vertical columns
+ of left adjusted text.
- Break hints in a horizontal box never split the line.
- (Line splitting may still occur inside boxes nested deeper). *)
+ This box features command [set_tab] to define cell boundaries, and command
+ [print_tab] to move from cell to cell and split the line when there is no
+ more cells to print on the line.
-val open_vbox : int -> unit
-(** [open_vbox d] opens a new 'vertical' pretty-printing box
- with offset [d].
+ Note: printing within tabulation box is line directed, so arbitrary line
+ splitting inside a tabulation box leads to poor rendering. Yet, controlled
+ use of tabulation boxes allows simple printing of columns within
+ module {!Format}.
+*)
- This box prints material on as many lines as break hints in the box.
+val pp_open_tbox : formatter -> unit -> unit
+val open_tbox : unit -> unit
+(** [open_tbox ()] opens a new tabulation box.
- Every break hint in a vertical box splits the line.
+ This box prints lines separated into cells of fixed width.
- If the pretty-printer splits the line in the box, [d] is added to the
- current indentation. *)
+ Inside a tabulation box, special {e tabulation markers} defines points of
+ interest on the line (for instance to delimit cell boundaries).
+ Function {!Format.set_tab} sets a tabulation marker at insertion point.
-val open_hvbox : int -> unit
-(** [open_hvbox d] opens a new 'horizontal-vertical' pretty-printing box
- with offset [d].
+ A tabulation box features specific {e tabulation breaks} to move to next
+ tabulation marker or split the line. Function {!Format.print_tbreak} prints
+ a tabulation break.
+*)
- This box behaves as an horizontal box if it fits on a single line,
- otherwise it behaves as a vertical box.
+val pp_close_tbox : formatter -> unit -> unit
+val close_tbox : unit -> unit
+(** Closes the most recently opened tabulation box. *)
- If the pretty-printer splits the line in the box, [d] is added to the
- current indentation. *)
+val pp_set_tab : formatter -> unit -> unit
+val set_tab : unit -> unit
+(** Sets a tabulation marker at current insertion point. *)
-val open_hovbox : int -> unit
-(** [open_hovbox d] opens a new 'horizontal-or-vertical' pretty-printing box
- with offset [d].
+val pp_print_tab : formatter -> unit -> unit
+val print_tab : unit -> unit
+(** [print_tab ()] emits a 'next' tabulation break hint: if not already set on
+ a tabulation marker, the insertion point moves to the first tabulation
+ marker on the right, or the pretty-printer splits the line and insertion
+ point moves to the leftmost tabulation marker.
- This box prints material as much as possible on every line.
+ It is equivalent to [print_tbreak 0 0]. *)
- A break hint splits the line if there is no more room on the line to
- print the remainder of the box.
+val pp_print_tbreak : formatter -> int -> int -> unit
+val print_tbreak : int -> int -> unit
+(** [print_tbreak nspaces offset] emits a 'full' tabulation break hint.
- If the pretty-printer splits the line in the box, [d] is added to the
- current indentation. *)
+ If not already set on a tabulation marker, the insertion point moves to the
+ first tabulation marker on the right and the pretty-printer prints
+ [nspaces] spaces.
-(** {6 Ellipsis} *)
+ If there is no next tabulation marker on the right, the pretty-printer
+ splits the line at this point, then insertion point moves to the leftmost
+ tabulation marker of the box.
+ If the pretty-printer splits the line, [offset] is added to
+ the current indentation.
+*)
+
+(** {1 Ellipsis} *)
+
+val pp_set_ellipsis_text : formatter -> string -> unit
val set_ellipsis_text : string -> unit
-(** Set the text of the ellipsis printed when too many boxes
- are opened (a single dot, [.], by default). *)
+(** Set the text of the ellipsis printed when too many pretty-printing boxes
+ are open (a single dot, [.], by default).
+*)
+val pp_get_ellipsis_text : formatter -> unit -> string
val get_ellipsis_text : unit -> string
(** Return the text of the ellipsis. *)
-(** {6:tags Semantic Tags} *)
+(** {1:tags Semantic tags} *)
type tag = string
-(** {i Semantic tags} (or simply {e tags}) are used to decorate printed
- entities for user's defined purposes, e.g. setting font and giving size
- indications for a display device, or marking delimitation of semantic
- entities (e.g. HTML or TeX elements or terminal escape sequences).
-
- By default, those tags do not influence line splitting calculation:
- the tag 'markers' are not considered as part of the printing
- material that drives line splitting (in other words, the length of
- those strings is considered as zero for line splitting).
+(** {i Semantic tags} (or simply {e tags}) are user's defined delimiters
+ to associate user's specific operations to printed entities.
- Thus, tag handling is in some sense transparent to pretty-printing
- and does not interfere with usual indentation. Hence, a single
- pretty printing routine can output both simple 'verbatim'
- material or richer decorated output depending on the treatment of
- tags. By default, tags are not active, hence the output is not
- decorated with tag information. Once [set_tags] is set to [true],
- the pretty printer engine honours tags and decorates the output
- accordingly.
-
- When a tag has been opened (or closed), it is both and successively
- 'printed' and 'marked'. Printing a tag means calling a
- formatter specific function with the name of the tag as argument:
- that 'tag printing' function can then print any regular material
+ Common usage of semantic tags is text decoration to get specific font or
+ text size rendering for a display device, or marking delimitation of
+ entities (e.g. HTML or TeX elements or terminal escape sequences).
+ More sophisticated usage of semantic tags could handle dynamic
+ modification of the pretty-printer behavior to properly print the material
+ within some specific tags.
+
+ In order to properly delimit printed entities, a semantic tag must be
+ opened before and closed after the entity. Semantic tags must be properly
+ nested like parentheses.
+
+ Tag specific operations occur any time a tag is opened or closed, At each
+ occurrence, two kinds of operations are performed {e tag-marking} and
+ {e tag-printing}:
+- The tag-marking operation is the simpler tag specific operation: it simply
+ writes a tag specific string into the output device of the
+ formatter. Tag-marking does not interfere with line-splitting computation.
+- The tag-printing operation is the more involved tag specific operation: it
+ can print arbitrary material to the formatter. Tag-printing is tightly
+ linked to the current pretty-printer operations.
+
+ Roughly speaking, tag-marking is commonly used to get a better rendering of
+ texts in the rendering device, while tag-printing allows fine tuning of
+ printing routines to print the same entity differently according to the
+ semantic tags (i.e. print additional material or even omit parts of the
+ output).
+
+ More precisely: when a semantic tag is opened or closed then both and
+ successive 'tag-printing' and 'tag-marking' operations occur:
+ - Tag-printing a semantic tag means calling the formatter specific function
+ [print_open_tag] (resp. [print_close_tag]) with the name of the tag as
+ argument: that tag-printing function can then print any regular material
to the formatter (so that this material is enqueued as usual in the
- formatter queue for further line splitting computation). Marking a
- tag means to output an arbitrary string (the 'tag marker'),
- directly into the output device of the formatter. Hence, the
- formatter specific 'tag marking' function must return the tag
- marker string associated to its tag argument. Being flushed
- directly into the output device of the formatter, tag marker
- strings are not considered as part of the printing material that
+ formatter queue for further line splitting computation).
+ - Tag-marking a semantic tag means calling the formatter specific function
+ [mark_open_tag] (resp. [mark_close_tag]) with the name of the tag as
+ argument: that tag-marking function can then return the 'tag-opening
+ marker' (resp. `tag-closing marker') for direct output into the output
+ device of the formatter.
+
+ Being written directly into the output device of the formatter, semantic
+ tag marker strings are not considered as part of the printing material that
drives line splitting (in other words, the length of the strings
- corresponding to tag markers is considered as zero for line
- splitting). In addition, advanced users may take advantage of
- the specificity of tag markers to be precisely output when the
- pretty printer has already decided where to split the lines, and
- precisely when the queue is flushed into the output device.
+ corresponding to tag markers is considered as zero for line splitting).
- In the spirit of HTML tags, the default tag marking functions
- output tags enclosed in "<" and ">": hence, the opening marker of
- tag [t] is ["<t>"] and the closing marker ["</t>"].
+ Thus, semantic tag handling is in some sense transparent to pretty-printing
+ and does not interfere with usual indentation. Hence, a single
+ pretty-printing routine can output both simple 'verbatim' material or
+ richer decorated output depending on the treatment of tags. By default,
+ tags are not active, hence the output is not decorated with tag
+ information. Once [set_tags] is set to [true], the pretty-printer engine
+ honors tags and decorates the output accordingly.
+
+ Default tag-marking functions behave the HTML way: tags are enclosed in "<"
+ and ">"; hence, opening marker for tag [t] is ["<t>"] and closing marker is
+ ["</t>"].
- Default tag printing functions just do nothing.
+ Default tag-printing functions just do nothing.
- Tag marking and tag printing functions are user definable and can
- be set by calling [set_formatter_tag_functions]. *)
+ Tag-marking and tag-printing functions are user definable and can
+ be set by calling {!set_formatter_tag_functions}.
+ Semantic tag operations may be set on or off with {!set_tags}.
+ Tag-marking operations may be set on or off with {!set_mark_tags}.
+ Tag-printing operations may be set on or off with {!set_print_tags}.
+*)
+
+val pp_open_tag : formatter -> string -> unit
val open_tag : tag -> unit
-(** [open_tag t] opens the tag named [t]; the [print_open_tag]
- function of the formatter is called with [t] as argument;
- the tag marker [mark_open_tag t] will be flushed into the output
- device of the formatter. *)
+(** [pp_open_tag ppf t] opens the semantic tag named [t].
+ The [print_open_tag] tag-printing function of the formatter is called with
+ [t] as argument; then the opening tag marker for [t], as given by
+ [mark_open_tag t], is written into the output device of the formatter.
+*)
+
+val pp_close_tag : formatter -> unit -> unit
val close_tag : unit -> unit
-(** [close_tag ()] closes the most recently opened tag [t].
- In addition, the [print_close_tag] function of the formatter is called
- with [t] as argument. The marker [mark_close_tag t] will be flushed
- into the output device of the formatter. *)
+(** [pp_close_tag ppf ()] closes the most recently opened semantic tag [t].
+
+ The closing tag marker, as given by [mark_close_tag t], is written into the
+ output device of the formatter; then the [print_close_tag] tag-printing
+ function of the formatter is called with [t] as argument.
+*)
+val pp_set_tags : formatter -> bool -> unit
val set_tags : bool -> unit
-(** [set_tags b] turns on or off the treatment of tags (default is off). *)
+(** [pp_set_tags ppf b] turns on or off the treatment of semantic tags
+ (default is off).
+*)
+val pp_set_print_tags : formatter -> bool -> unit
val set_print_tags : bool -> unit
-(** [set_print_tags b] turns on or off the printing of tags. *)
+(** [pp_set_print_tags ppf b] turns on or off the tag-printing operations. *)
+val pp_set_mark_tags : formatter -> bool -> unit
val set_mark_tags : bool -> unit
-(** [set_mark_tags b] turns on or off the output of tag markers. *)
+(** [pp_set_mark_tags ppf b] turns on or off the tag-marking operations. *)
+val pp_get_print_tags : formatter -> unit -> bool
val get_print_tags : unit -> bool
-(** Return the current status of tags printing. *)
+(** Return the current status of tag-printing operations. *)
+val pp_get_mark_tags : formatter -> unit -> bool
val get_mark_tags : unit -> bool
-(** Return the current status of tags marking. *)
-
-(** {6 Redirecting the standard formatter output} *)
+(** Return the current status of tag-marking operations. *)
+(** {1 Redirecting the standard formatter output} *)
+val pp_set_formatter_out_channel :
+ formatter -> Pervasives.out_channel -> unit
val set_formatter_out_channel : Pervasives.out_channel -> unit
-(** Redirect the pretty-printer output to the given channel.
+(** Redirect the standard pretty-printer output to the given channel.
(All the output functions of the standard formatter are set to the
- default output functions printing to the given channel.) *)
+ default output functions printing to the given channel.)
+ [set_formatter_out_channel] is equivalent to
+ {!pp_set_formatter_out_channel} [std_formatter].
+*)
+
+val pp_set_formatter_output_functions :
+ formatter -> (string -> int -> int -> unit) -> (unit -> unit) -> unit
val set_formatter_output_functions :
(string -> int -> int -> unit) -> (unit -> unit) -> unit
-(** [set_formatter_output_functions out flush] redirects the
- pretty-printer output functions to the functions [out] and
+(** [pp_set_formatter_output_functions ppf out flush] redirects the
+ standard pretty-printer output functions to the functions [out] and
[flush].
The [out] function performs all the pretty-printer string output.
The [flush] function is called whenever the pretty-printer is flushed
(via conversion [%!], or pretty-printing indications [@?] or [@.], or
- using low level functions [print_flush] or [print_newline]). *)
+ using low level functions [print_flush] or [print_newline]).
+*)
+val pp_get_formatter_output_functions :
+ formatter -> unit -> (string -> int -> int -> unit) * (unit -> unit)
val get_formatter_output_functions :
unit -> (string -> int -> int -> unit) * (unit -> unit)
-(** Return the current output functions of the pretty-printer. *)
+(** Return the current output functions of the standard pretty-printer. *)
-(** {6:meaning Changing the meaning of standard formatter pretty printing} *)
+(** {1:meaning Redefining formatter output} *)
(** The [Format] module is versatile enough to let you completely redefine
- the meaning of pretty printing: you may provide your own functions to define
- how to handle indentation, line splitting, and even printing of all the
- characters that have to be printed! *)
+ the meaning of pretty-printing output: you may provide your own functions
+ to define how to handle indentation, line splitting, and even printing of
+ all the characters that have to be printed!
+*)
+
+(** {2 Redefining output functions} *)
type formatter_out_functions = {
out_string : string -> int -> int -> unit;
out_flush : unit -> unit;
out_newline : unit -> unit;
out_spaces : int -> unit;
-} (** @since 4.01.0 *)
+ out_indent : int -> unit;
+}
+(** The set of output functions specific to a formatter:
+- the [out_string] function performs all the pretty-printer string output.
+ It is called with a string [s], a start position [p], and a number of
+ characters [n]; it is supposed to output characters [p] to [p + n - 1] of
+ [s].
+- the [out_flush] function flushes the pretty-printer output device.
+- [out_newline] is called to open a new line when the pretty-printer splits
+ the line.
+- the [out_spaces] function outputs spaces when a break hint leads to spaces
+ instead of a line split. It is called with the number of spaces to output.
+- the [out_indent] function performs new line indentation when the
+ pretty-printer splits the line. It is called with the indentation value of
+ the new line.
+
+ By default:
+- fields [out_string] and [out_flush] are output device specific;
+ (e.g. {!Pervasives.output_string} and {!Pervasives.flush} for a
+ {!Pervasives.out_channel} device, or [Buffer.add_substring] and
+ {!Pervasives.ignore} for a [Buffer.t] output device),
+- field [out_newline] is equivalent to [out_string "\n" 0 1];
+- fields [out_spaces] and [out_indent] are equivalent to
+ [out_string (String.make n ' ') 0 n].
+ @since 4.01.0
+*)
+val pp_set_formatter_out_functions :
+ formatter -> formatter_out_functions -> unit
val set_formatter_out_functions : formatter_out_functions -> unit
-(** [set_formatter_out_functions f]
- Redirect the pretty-printer output to the functions [f.out_string]
- and [f.out_flush] as described in
- [set_formatter_output_functions]. In addition, the pretty-printer function
- that outputs a newline is set to the function [f.out_newline] and
- the function that outputs indentation spaces is set to the function
- [f.out_spaces].
+(** [pp_set_formatter_out_functions ppf out_funs]
+ Set all the pretty-printer output functions of [ppf] to those of
+ argument [out_funs],
This way, you can change the meaning of indentation (which can be
something else than just printing space characters) and the meaning of new
lines opening (which can be connected to any other action needed by the
- application at hand). The two functions [f.out_spaces] and [f.out_newline]
- are normally connected to [f.out_string] and [f.out_flush]: respective
- default values for [f.out_space] and [f.out_newline] are
- [f.out_string (String.make n ' ') 0 n] and [f.out_string "\n" 0 1].
- @since 4.01.0 *)
+ application at hand).
+
+ Reasonable defaults for functions [out_spaces] and [out_newline] are
+ respectively [out_funs.out_string (String.make n ' ') 0 n] and
+ [out_funs.out_string "\n" 0 1].
+ @since 4.01.0
+*)
+val pp_get_formatter_out_functions :
+ formatter -> unit -> formatter_out_functions
val get_formatter_out_functions : unit -> formatter_out_functions
(** Return the current output functions of the pretty-printer,
including line splitting and indentation functions. Useful to record the
current setting and restore it afterwards.
- @since 4.01.0 *)
+ @since 4.01.0
+*)
-(** {6:tagsmeaning Changing the meaning of printing semantic tags} *)
+(** {1:tagsmeaning Redefining semantic tag operations} *)
type formatter_tag_functions = {
mark_open_tag : tag -> string;
print_open_tag : tag -> unit;
print_close_tag : tag -> unit;
}
-(** The tag handling functions specific to a formatter:
- [mark] versions are the 'tag marking' functions that associate a string
- marker to a tag in order for the pretty-printing engine to flush
+(** The semantic tag handling functions specific to a formatter:
+ [mark] versions are the 'tag-marking' functions that associate a string
+ marker to a tag in order for the pretty-printing engine to write
those markers as 0 length tokens in the output device of the formatter.
- [print] versions are the 'tag printing' functions that can perform
- regular printing when a tag is closed or opened. *)
+ [print] versions are the 'tag-printing' functions that can perform
+ regular printing when a tag is closed or opened.
+*)
+val pp_set_formatter_tag_functions :
+ formatter -> formatter_tag_functions -> unit
val set_formatter_tag_functions : formatter_tag_functions -> unit
-(** [set_formatter_tag_functions tag_funs] changes the meaning of
- opening and closing tags to use the functions in [tag_funs].
+(** [pp_set_formatter_tag_functions ppf tag_funs] changes the meaning of
+ opening and closing semantic tag operations to use the functions in
+ [tag_funs] when printing on [ppf].
- When opening a tag name [t], the string [t] is passed to the
- opening tag marking function (the [mark_open_tag] field of the
+ When opening a semantic tag with name [t], the string [t] is passed to the
+ opening tag-marking function (the [mark_open_tag] field of the
record [tag_funs]), that must return the opening tag marker for
- that name. When the next call to [close_tag ()] happens, the tag
- name [t] is sent back to the closing tag marking function (the
+ that name. When the next call to [close_tag ()] happens, the semantic tag
+ name [t] is sent back to the closing tag-marking function (the
[mark_close_tag] field of record [tag_funs]), that must return a
closing tag marker for that name.
- The [print_] field of the record contains the functions that are
- called at tag opening and tag closing time, to output regular
- material in the pretty-printer queue. *)
+ The [print_] field of the record contains the tag-printing functions that
+ are called at tag opening and tag closing time, to output regular material
+ in the pretty-printer queue.
+*)
+val pp_get_formatter_tag_functions :
+ formatter -> unit -> formatter_tag_functions
val get_formatter_tag_functions : unit -> formatter_tag_functions
-(** Return the current tag functions of the pretty-printer. *)
-
-(** {6 Multiple formatted output} *)
-
-type formatter
-(** Abstract data corresponding to a pretty-printer (also called a
- formatter) and all its machinery.
-
- Defining new pretty-printers permits unrelated output of material in
- parallel on several output channels.
- All the parameters of a pretty-printer are local to a formatter:
- margin, maximum indentation limit, maximum number of boxes
- simultaneously opened, ellipsis, and so on, are specific to
- each pretty-printer and may be fixed independently.
- Given a {!Pervasives.out_channel} output channel [oc], a new formatter
- writing to that channel is simply obtained by calling
- [formatter_of_out_channel oc].
- Alternatively, the [make_formatter] function allocates a new
- formatter with explicit output and flushing functions
- (convenient to output material to strings for instance).
+(** Return the current semantic tag operation functions of the standard
+ pretty-printer. *)
+
+(** {1:formatter Defining formatters}
+
+ Defining new formatters permits unrelated output of material in
+ parallel on several output devices.
+ All the parameters of a formatter are local to the formatter:
+ right margin, maximum indentation limit, maximum number of pretty-printing
+ boxes simultaneously open, ellipsis, and so on, are specific to
+ each formatter and may be fixed independently.
+
+ For instance, given a {!Buffer.t} buffer [b], {!formatter_of_buffer} [b]
+ returns a new formatter using buffer [b] as its output device.
+ Similarly, given a {!Pervasives.out_channel} output channel [oc],
+ {!formatter_of_out_channel} [oc] returns a new formatter using
+ channel [oc] as its output device.
+
+ Alternatively, given [out_funs], a complete set of output functions for a
+ formatter, then {!formatter_of_out_functions} [out_funs] computes a new
+ formatter using those functions for output.
*)
val formatter_of_out_channel : out_channel -> formatter
-(** [formatter_of_out_channel oc] returns a new formatter that
- writes to the corresponding channel [oc]. *)
+(** [formatter_of_out_channel oc] returns a new formatter writing
+ to the corresponding output channel [oc].
+*)
val std_formatter : formatter
-(** The standard formatter used by the formatting functions
- above. It is defined as [formatter_of_out_channel stdout]. *)
+(** The standard formatter to write to standard output.
+
+ It is defined as {!formatter_of_out_channel} {!Pervasives.stdout}.
+*)
val err_formatter : formatter
-(** A formatter to use with formatting functions below for
- output to standard error. It is defined as
- [formatter_of_out_channel stderr]. *)
+(** A formatter to write to standard error.
+
+ It is defined as {!formatter_of_out_channel} {!Pervasives.stderr}.
+*)
val formatter_of_buffer : Buffer.t -> formatter
(** [formatter_of_buffer b] returns a new formatter writing to
- buffer [b]. As usual, the formatter has to be flushed at
- the end of pretty printing, using [pp_print_flush] or
- [pp_print_newline], to display all the pending material. *)
+ buffer [b]. At the end of pretty-printing, the formatter must be flushed
+ using {!pp_print_flush} or {!pp_print_newline}, to print all the
+ pending material into the buffer.
+*)
val stdbuf : Buffer.t
(** The string buffer in which [str_formatter] writes. *)
val str_formatter : formatter
-(** A formatter to use with formatting functions below for
- output to the [stdbuf] string buffer.
- [str_formatter] is defined as [formatter_of_buffer stdbuf]. *)
+(** A formatter to output to the {!stdbuf} string buffer.
+
+ [str_formatter] is defined as {!formatter_of_buffer} {!stdbuf}.
+*)
val flush_str_formatter : unit -> string
(** Returns the material printed with [str_formatter], flushes
- the formatter and resets the corresponding buffer. *)
+ the formatter and resets the corresponding buffer.
+*)
val make_formatter :
(string -> int -> int -> unit) -> (unit -> unit) -> formatter
-(** [make_formatter out flush] returns a new formatter that writes according
- to the output function [out], and the flushing function [flush]. For
- instance, a formatter to the {!Pervasives.out_channel} [oc] is returned by
- [make_formatter (Pervasives.output oc) (fun () -> Pervasives.flush oc)]. *)
+(** [make_formatter out flush] returns a new formatter that outputs with
+ function [out], and flushes with function [flush].
+
+ For instance, {[
+ make_formatter
+ (Pervasives.output oc)
+ (fun () -> Pervasives.flush oc) ]}
+ returns a formatter to the {!Pervasives.out_channel} [oc].
+*)
-(** {6 Basic functions to use with formatters} *)
+val formatter_of_out_functions :
+ formatter_out_functions -> formatter
+(** [formatter_of_out_functions out_funs] returns a new formatter that writes
+ with the set of output functions [out_funs].
-val pp_open_hbox : formatter -> unit -> unit
-val pp_open_vbox : formatter -> int -> unit
-val pp_open_hvbox : formatter -> int -> unit
-val pp_open_hovbox : formatter -> int -> unit
-val pp_open_box : formatter -> int -> unit
-val pp_close_box : formatter -> unit -> unit
-val pp_open_tag : formatter -> string -> unit
-val pp_close_tag : formatter -> unit -> unit
-val pp_print_string : formatter -> string -> unit
-val pp_print_as : formatter -> int -> string -> unit
-val pp_print_int : formatter -> int -> unit
-val pp_print_float : formatter -> float -> unit
-val pp_print_char : formatter -> char -> unit
-val pp_print_bool : formatter -> bool -> unit
-val pp_print_break : formatter -> int -> int -> unit
-val pp_print_cut : formatter -> unit -> unit
-val pp_print_space : formatter -> unit -> unit
-val pp_force_newline : formatter -> unit -> unit
-val pp_print_flush : formatter -> unit -> unit
-val pp_print_newline : formatter -> unit -> unit
-val pp_print_if_newline : formatter -> unit -> unit
-val pp_set_tags : formatter -> bool -> unit
-val pp_set_print_tags : formatter -> bool -> unit
-val pp_set_mark_tags : formatter -> bool -> unit
-val pp_get_print_tags : formatter -> unit -> bool
-val pp_get_mark_tags : formatter -> unit -> bool
-val pp_set_margin : formatter -> int -> unit
-val pp_get_margin : formatter -> unit -> int
-val pp_set_max_indent : formatter -> int -> unit
-val pp_get_max_indent : formatter -> unit -> int
-val pp_set_max_boxes : formatter -> int -> unit
-val pp_get_max_boxes : formatter -> unit -> int
-val pp_over_max_boxes : formatter -> unit -> bool
-val pp_set_ellipsis_text : formatter -> string -> unit
-val pp_get_ellipsis_text : formatter -> unit -> string
-val pp_set_formatter_out_channel :
- formatter -> Pervasives.out_channel -> unit
+ See definition of type {!formatter_out_functions} for the meaning of argument
+ [out_funs].
-val pp_set_formatter_output_functions :
- formatter -> (string -> int -> int -> unit) -> (unit -> unit) -> unit
+ @since 4.06.0
+*)
-val pp_get_formatter_output_functions :
- formatter -> unit -> (string -> int -> int -> unit) * (unit -> unit)
+(** {2:symbolic Symbolic pretty-printing} *)
-val pp_set_formatter_tag_functions :
- formatter -> formatter_tag_functions -> unit
+(**
+ Symbolic pretty-printing is pretty-printing using a symbolic formatter,
+ i.e. a formatter that outputs symbolic pretty-printing items.
-val pp_get_formatter_tag_functions :
- formatter -> unit -> formatter_tag_functions
+ When using a symbolic formatter, all regular pretty-printing activities
+ occur but output material is symbolic and stored in a buffer of output items.
+ At the end of pretty-printing, flushing the output buffer allows
+ post-processing of symbolic output before performing low level output
+ operations.
-val pp_set_formatter_out_functions :
- formatter -> formatter_out_functions -> unit
-(** @since 4.01.0 *)
+ In practice, first define a symbolic output buffer [b] using:
+ - [let sob = make_symbolic_output_buffer ()].
+ Then define a symbolic formatter with:
+ - [let ppf = formatter_of_symbolic_output_buffer sob]
-val pp_get_formatter_out_functions :
- formatter -> unit -> formatter_out_functions
-(** These functions are the basic ones: usual functions
- operating on the standard formatter are defined via partial
- evaluation of these primitives. For instance,
- [print_string] is equal to [pp_print_string std_formatter].
- @since 4.01.0 *)
+ Use symbolic formatter [ppf] as usual, and retrieve symbolic items at end
+ of pretty-printing by flushing symbolic output buffer [sob] with:
+ - [flush_symbolic_output_buffer sob].
+*)
+
+type symbolic_output_item =
+ | Output_flush (** symbolic flush command *)
+ | Output_newline (** symbolic newline command *)
+ | Output_string of string
+ (** [Output_string s]: symbolic output for string [s]*)
+ | Output_spaces of int
+ (** [Output_spaces n]: symbolic command to output [n] spaces *)
+ | Output_indent of int
+ (** [Output_indent i]: symbolic indentation of size [i] *)
+(** Items produced by symbolic pretty-printers
+ @since 4.06.0
+*)
+
+type symbolic_output_buffer
+(**
+ The output buffer of a symbolic pretty-printer.
+
+ @since 4.06.0
+*)
+
+val make_symbolic_output_buffer : unit -> symbolic_output_buffer
+(** [make_symbolic_output_buffer ()] returns a fresh buffer for
+ symbolic output.
+
+ @since 4.06.0
+*)
+
+val clear_symbolic_output_buffer : symbolic_output_buffer -> unit
+(** [clear_symbolic_output_buffer sob] resets buffer [sob].
+
+ @since 4.06.0
+*)
+
+val get_symbolic_output_buffer :
+ symbolic_output_buffer -> symbolic_output_item list
+(** [get_symbolic_output_buffer sob] returns the contents of buffer [sob].
+
+ @since 4.06.0
+*)
+
+val flush_symbolic_output_buffer :
+ symbolic_output_buffer -> symbolic_output_item list
+(** [flush_symbolic_output_buffer sob] returns the contents of buffer
+ [sob] and resets buffer [sob].
+ [flush_symbolic_output_buffer sob] is equivalent to
+ [let items = get_symbolic_output_buffer sob in
+ clear_symbolic_output_buffer sob; items]
+
+ @since 4.06.0
+*)
+
+val add_symbolic_output_item :
+ symbolic_output_buffer -> symbolic_output_item -> unit
+(** [add_symbolic_output_item sob itm] adds item [itm] to buffer [sob].
-val pp_flush_formatter : formatter -> unit
-(** [pp_flush_formatter fmt] flushes [fmt]'s internal queue, ensuring that all
- the printing and flushing actions have been performed. In addition, this
- operation will close all boxes and reset the state of the formatter.
+ @since 4.06.0
+*)
+
+val formatter_of_symbolic_output_buffer : symbolic_output_buffer -> formatter
+(** [formatter_of_symbolic_output_buffer sob] returns a symbolic formatter
+ that outputs to [symbolic_output_buffer] [sob].
- This will not flush [fmt]'s output. In most cases, the user may want to use
- {!pp_print_flush} instead.
- @since 4.04.0 *)
+ @since 4.06.0
+*)
-(** {6 Convenience formatting functions.} *)
+(** {1 Convenience formatting functions.} *)
val pp_print_list:
?pp_sep:(formatter -> unit -> unit) ->
(formatter -> 'a -> unit) -> (formatter -> 'a list -> unit)
(** [pp_print_list ?pp_sep pp_v ppf l] prints items of list [l],
using [pp_v] to print each item, and calling [pp_sep]
- between items ([pp_sep] defaults to {!pp_print_cut}).
+ between items ([pp_sep] defaults to {!pp_print_cut}.
Does nothing on empty lists.
@since 4.02.0
*)
val pp_print_text : formatter -> string -> unit
-(** [pp_print_text ppf s] prints [s] with spaces and newlines
- respectively printed with {!pp_print_space} and
- {!pp_force_newline}.
+(** [pp_print_text ppf s] prints [s] with spaces and newlines respectively
+ printed using {!pp_print_space} and {!pp_force_newline}.
@since 4.02.0
*)
-(** {6 [printf] like functions for pretty-printing.} *)
+(** {1:fpp Formatted pretty-printing} *)
+
+(**
+ Module [Format] provides a complete set of [printf] like functions for
+ pretty-printing using format string specifications.
+
+ Specific annotations may be added in the format strings to give
+ pretty-printing commands to the pretty-printing engine.
+
+ Those annotations are introduced in the format strings using the [@]
+ character. For instance, [@ ] means a space break, [@,] means a cut,
+ [@\[] opens a new box, and [@\]] closes the last open box.
+
+*)
val fprintf : formatter -> ('a, formatter, unit) format -> 'a
according to the format string [fmt], and outputs the resulting string on
the formatter [ff].
- The format [fmt] is a character string which contains three types of
+ The format string [fmt] is a character string which contains three types of
objects: plain characters and conversion specifications as specified in
the {!Printf} module, and pretty-printing indications specific to the
[Format] module.
box may be optionally specified with the following syntax:
the [<] character, followed by an optional box type indication,
then an optional integer offset, and the closing [>] character.
- Box type is one of [h], [v], [hv], [b], or [hov].
- '[h]' stands for an 'horizontal' box,
- '[v]' stands for a 'vertical' box,
- '[hv]' stands for an 'horizontal-vertical' box,
- '[b]' stands for an 'horizontal-or-vertical' box demonstrating indentation,
- '[hov]' stands a simple 'horizontal-or-vertical' box.
+ Pretty-printing box type is one of [h], [v], [hv], [b], or [hov].
+ '[h]' stands for an 'horizontal' pretty-printing box,
+ '[v]' stands for a 'vertical' pretty-printing box,
+ '[hv]' stands for an 'horizontal/vertical' pretty-printing box,
+ '[b]' stands for an 'horizontal-or-vertical' pretty-printing box
+ demonstrating indentation,
+ '[hov]' stands a simple 'horizontal-or-vertical' pretty-printing box.
For instance, [@\[<hov 2>] opens an 'horizontal-or-vertical'
- box with indentation 2 as obtained with [open_hovbox 2].
- For more details about boxes, see the various box opening
+ pretty-printing box with indentation 2 as obtained with [open_hovbox 2].
+ For more details about pretty-printing boxes, see the various box opening
functions [open_*box].
- [@\]]: close the most recently opened pretty-printing box.
- [@,]: output a 'cut' break hint, as with [print_cut ()].
then an integer [offset], and a closing [>] character.
If no parameters are provided, the good break defaults to a
'space' break hint.
- - [@.]: flush the pretty printer and split the line, as with
+ - [@.]: flush the pretty-printer and split the line, as with
[print_newline ()].
- [@<n>]: print the following item as if it were of length [n].
Hence, [printf "@<0>%s" arg] prints [arg] as a zero length string.
If [@<n>] is not followed by a conversion specification,
then the following character of the format is printed as if
it were of length [n].
- - [@\{]: open a tag. The name of the tag may be optionally
+ - [@\{]: open a semantic tag. The name of the tag may be optionally
specified with the following syntax:
the [<] character, followed by an optional string
specification, and the closing [>] character. The string
specification is any character string that does not contain the
closing character ['>']. If omitted, the tag name defaults to the
empty string.
- For more details about tags, see the functions [open_tag] and
- [close_tag].
- - [@\}]: close the most recently opened tag.
- - [@?]: flush the pretty printer as with [print_flush ()].
+ For more details about semantic tags, see the functions {!open_tag} and
+ {!close_tag}.
+ - [@\}]: close the most recently opened semantic tag.
+ - [@?]: flush the pretty-printer as with [print_flush ()].
This is equivalent to the conversion [%!].
- [@\n]: force a newline, as with [force_newline ()], not the normal way
of pretty-printing, you should prefer using break hints inside a vertical
- box.
+ pretty-printing box.
- Note: If you need to prevent the interpretation of a [@] character as a
- pretty-printing indication, you must escape it with a [%] character.
+ Note: To prevent the interpretation of a [@] character as a
+ pretty-printing indication, escape it with a [%] character.
Old quotation mode [@@] is deprecated since it is not compatible with
formatted input interpretation of character ['@'].
returns a string containing the result of formatting the arguments.
The type of [asprintf] is general enough to interact nicely with [%a]
conversions.
+
@since 4.01.0
*)
val ifprintf : formatter -> ('a, formatter, unit) format -> 'a
(** Same as [fprintf] above, but does not print anything.
Useful to ignore some material when conditionally printing.
+
@since 3.10.0
*)
-(** Formatted output functions with continuations. *)
+(** Formatted Pretty-Printing with continuations. *)
val kfprintf :
(formatter -> 'a) -> formatter ->
('b, formatter, unit, 'a) format4 -> 'b
(** Same as [kfprintf] above, but does not print anything.
Useful to ignore some material when conditionally printing.
+
@since 3.12.0
*)
val kasprintf : (string -> 'a) -> ('b, formatter, unit, 'a) format4 -> 'b
(** Same as [asprintf] above, but instead of returning the string,
passes it to the first argument.
+
@since 4.03
*)
-(** {6 Deprecated} *)
+(** {1 Deprecated} *)
val bprintf : Buffer.t -> ('a, formatter, unit) format -> 'a
[@@ocaml.deprecated]
(** @deprecated This function is error prone. Do not use it.
+ This function is neither compositional nor incremental, since it flushes
+ the pretty-printer queue at each call.
If you need to print to some buffer [b], you must first define a
formatter writing to [b], using [let to_b = formatter_of_buffer b]; then
- use regular calls to [Format.fprintf] on formatter [to_b]. *)
+ use regular calls to [Format.fprintf] with formatter [to_b].
+*)
val kprintf : (string -> 'a) -> ('b, unit, string, 'a) format4 -> 'b
[@@ocaml.deprecated "Use Format.ksprintf instead."]
(int -> unit)
[@@ocaml.deprecated "Use Format.pp_get_formatter_out_functions instead."]
(** @deprecated Subsumed by [pp_get_formatter_out_functions]. *)
-
-(** Tabulation boxes are deprecated. *)
-
-val pp_open_tbox : formatter -> unit -> unit
-[@@ocaml.deprecated "Tabulation boxes are not supported any more."]
-(** @deprecated since 4.03.0 *)
-
-val pp_close_tbox : formatter -> unit -> unit
-[@@ocaml.deprecated "Tabulation boxes are not supported any more."]
-(** @deprecated since 4.03.0 *)
-
-val pp_print_tbreak : formatter -> int -> int -> unit
-[@@ocaml.deprecated "Tabulation boxes are not supported any more."]
-(** @deprecated since 4.03.0 *)
-
-val pp_set_tab : formatter -> unit -> unit
-[@@ocaml.deprecated "Tabulation boxes are not supported any more."]
-(** @deprecated since 4.03.0 *)
-
-val pp_print_tab : formatter -> unit -> unit
-[@@ocaml.deprecated "Tabulation boxes are not supported any more."]
-(** @deprecated since 4.03.0 *)
-
-val open_tbox : unit -> unit
-[@@ocaml.deprecated "Tabulation boxes are not supported any more."]
-(** @deprecated since 4.03.0 *)
-
-val close_tbox : unit -> unit
-[@@ocaml.deprecated "Tabulation boxes are not supported any more."]
-(** @deprecated since 4.03.0 *)
-
-val print_tbreak : int -> int -> unit
-[@@ocaml.deprecated "Tabulation boxes are not supported any more."]
-(** @deprecated since 4.03.0 *)
-
-val set_tab : unit -> unit
-[@@ocaml.deprecated "Tabulation boxes are not supported any more."]
-(** @deprecated since 4.03.0 *)
-
-val print_tab : unit -> unit
-[@@ocaml.deprecated "Tabulation boxes are not supported any more."]
-(** @deprecated since 4.03.0 *)
mutable space_overhead : int;
(** The major GC speed is computed from this parameter.
This is the memory that will be "wasted" because the GC does not
- immediatly collect unreachable blocks. It is expressed as a
+ immediately collect unreachable blocks. It is expressed as a
percentage of the memory used for live data.
The GC will work more (use more CPU time and collect
blocks more eagerly) if [space_overhead] is smaller.
*)
-(** {6 Generic interface} *)
+(** {1 Generic interface} *)
type ('a, 'b) t
buckets by size.
@since 4.00.0 *)
-(** {6 Functorial interface} *)
+(** {1 Functorial interface} *)
(** The functorial interface allows the use of specific comparison
and hash functions, either for performance/security concerns,
@since 4.00.0 *)
-(** {6 The polymorphic hash functions} *)
+(** {1 The polymorphic hash functions} *)
val hash : 'a -> int
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "../config/s.h"
+#include "caml/s.h"
#ifdef HAS_UNISTD
#include <unistd.h>
#endif
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include "../byterun/caml/mlvalues.h"
-#include "../byterun/caml/exec.h"
+#include "caml/mlvalues.h"
+#include "caml/exec.h"
char * default_runtime_path = RUNTIME_NAME;
#include "caml/exec.h"
#ifndef __MINGW32__
-#pragma comment(linker , "/entry:headerentry")
#pragma comment(linker , "/subsystem:console")
#pragma comment(lib , "kernel32")
#ifdef _UCRT
return FALSE;
}
-#define msg_and_length(msg) msg , (sizeof(msg) - 1)
+#if WINDOWS_UNICODE
+#define CP CP_UTF8
+#else
+#define CP CP_THREAD_ACP
+#endif
+
+static void write_console(HANDLE hOut, WCHAR *wstr)
+{
+ DWORD consoleMode, numwritten, len;
+ static char str[MAX_PATH];
+
+ if (GetConsoleMode(hOut, &consoleMode) != 0) { /* The output stream is a Console */
+ WriteConsole(hOut, wstr, wcslen(wstr), &numwritten, NULL);
+ } else { /* The output stream is redirected */
+ len = WideCharToMultiByte(CP, 0, wstr, wcslen(wstr), str, sizeof(str), NULL, NULL);
+ WriteFile(hOut, str, len, &numwritten, NULL);
+ }
+}
-static __inline void __declspec(noreturn) run_runtime(char * runtime,
- char * const cmdline)
+static __inline void __declspec(noreturn) run_runtime(wchar_t * runtime,
+ wchar_t * const cmdline)
{
- char path[MAX_PATH];
+ wchar_t path[MAX_PATH];
STARTUPINFO stinfo;
PROCESS_INFORMATION procinfo;
DWORD retcode;
- if (SearchPath(NULL, runtime, ".exe", MAX_PATH, path, &runtime) == 0) {
+ if (SearchPath(NULL, runtime, L".exe", sizeof(path)/sizeof(wchar_t), path, &runtime) == 0) {
HANDLE errh;
- DWORD numwritten;
errh = GetStdHandle(STD_ERROR_HANDLE);
- WriteFile(errh, msg_and_length("Cannot exec "), &numwritten, NULL);
- WriteFile(errh, runtime, strlen(runtime), &numwritten, NULL);
- WriteFile(errh, msg_and_length("\r\n"), &numwritten, NULL);
+ write_console(errh, L"Cannot exec ");
+ write_console(errh, runtime);
+ write_console(errh, L"\r\n");
ExitProcess(2);
#if _MSC_VER >= 1200
__assume(0); /* Not reached */
if (!CreateProcess(path, cmdline, NULL, NULL, TRUE, 0, NULL, NULL,
&stinfo, &procinfo)) {
HANDLE errh;
- DWORD numwritten;
errh = GetStdHandle(STD_ERROR_HANDLE);
- WriteFile(errh, msg_and_length("Cannot exec "), &numwritten, NULL);
- WriteFile(errh, runtime, strlen(runtime), &numwritten, NULL);
- WriteFile(errh, msg_and_length("\r\n"), &numwritten, NULL);
+ write_console(errh, L"Cannot exec ");
+ write_console(errh, runtime);
+ write_console(errh, L"\r\n");
ExitProcess(2);
#if _MSC_VER >= 1200
__assume(0); /* Not reached */
#endif
}
-#ifdef __MINGW32__
-int main()
-#else
-void __declspec(noreturn) __cdecl headerentry()
-#endif
+int wmain(void)
{
- char truename[MAX_PATH];
- char * cmdline = GetCommandLine();
+ wchar_t truename[MAX_PATH];
+ wchar_t * cmdline = GetCommandLine();
char * runtime_path;
+ wchar_t wruntime_path[MAX_PATH];
HANDLE h;
- GetModuleFileName(NULL, truename, sizeof(truename));
+ GetModuleFileName(NULL, truename, sizeof(truename)/sizeof(wchar_t));
h = CreateFile(truename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
if (h == INVALID_HANDLE_VALUE ||
(runtime_path = read_runtime_path(h)) == NULL) {
HANDLE errh;
- DWORD numwritten;
errh = GetStdHandle(STD_ERROR_HANDLE);
- WriteFile(errh, truename, strlen(truename), &numwritten, NULL);
- WriteFile(errh, msg_and_length(" not found or is not a bytecode"
- " executable file\r\n"),
- &numwritten, NULL);
+ write_console(errh, truename);
+ write_console(errh, L" not found or is not a bytecode executable file\r\n");
ExitProcess(2);
#if _MSC_VER >= 1200
__assume(0); /* Not reached */
#endif
}
CloseHandle(h);
- run_runtime(runtime_path , cmdline);
+ MultiByteToWideChar(CP, 0, runtime_path, -1, wruntime_path, sizeof(wruntime_path)/sizeof(wchar_t));
+ run_runtime(wruntime_path , cmdline);
#if _MSC_VER >= 1200
__assume(0); /* Not reached */
#endif
(** Bitwise logical exclusive or. *)
val lognot : int32 -> int32
-(** Bitwise logical negation *)
+(** Bitwise logical negation. *)
external shift_left : int32 -> int -> int32 = "%int32_lsl"
(** [Int32.shift_left x y] shifts [x] to the left by [y] bits.
external of_string : string -> int32 = "caml_int32_of_string"
(** Convert the given string to a 32-bit integer.
- The string is read in decimal (by default) or in hexadecimal,
- octal or binary if the string begins with [0x], [0o] or [0b]
- respectively.
- Raise [Failure "int_of_string"] if the given string is not
+ The string is read in decimal (by default, or if the string
+ begins with [0u]) or in hexadecimal, octal or binary if the
+ string begins with [0x], [0o] or [0b] respectively.
+
+ The [0u] prefix reads the input as an unsigned integer in the range
+ [[0, 2*Int32.max_int+1]]. If the input exceeds {!Int32.max_int}
+ it is converted to the signed integer
+ [Int32.min_int + input - Int32.max_int - 1].
+
+ The [_] (underscore) character can appear anywhere in the string
+ and is ignored.
+ Raise [Failure "Int32.of_string"] if the given string is not
a valid representation of an integer, or if the integer represented
exceeds the range of integers representable in type [int32]. *)
(**/**)
-(** {6 Deprecated functions} *)
+(** {1 Deprecated functions} *)
external format : string -> int32 -> string = "caml_int32_format"
(** Do not use this deprecated function. Instead,
(** Bitwise logical exclusive or. *)
val lognot : int64 -> int64
-(** Bitwise logical negation *)
+(** Bitwise logical negation. *)
external shift_left : int64 -> int -> int64 = "%int64_lsl"
(** [Int64.shift_left x y] shifts [x] to the left by [y] bits.
external of_string : string -> int64 = "caml_int64_of_string"
(** Convert the given string to a 64-bit integer.
- The string is read in decimal (by default) or in hexadecimal,
- octal or binary if the string begins with [0x], [0o] or [0b]
- respectively.
- Raise [Failure "int_of_string"] if the given string is not
+ The string is read in decimal (by default, or if the string
+ begins with [0u]) or in hexadecimal, octal or binary if the
+ string begins with [0x], [0o] or [0b] respectively.
+
+ The [0u] prefix reads the input as an unsigned integer in the range
+ [[0, 2*Int64.max_int+1]]. If the input exceeds {!Int64.max_int}
+ it is converted to the signed integer
+ [Int64.min_int + input - Int64.max_int - 1].
+
+ The [_] (underscore) character can appear anywhere in the string
+ and is ignored.
+ Raise [Failure "Int64.of_string"] if the given string is not
a valid representation of an integer, or if the integer represented
exceeds the range of integers representable in type [int64]. *)
(**/**)
-(** {6 Deprecated functions} *)
+(** {1 Deprecated functions} *)
external format : string -> int64 -> string = "caml_int64_format"
(** Do not use this deprecated function. Instead,
The GC will magically change things from (2) to (3) according to its
fancy.
+ If OCaml was configured with the -flat-float-array option (which is
+ currently the default), the following is also true:
We cannot use representation (3) for a [float Lazy.t] because
[caml_make_array] assumes that only a [float] value can have tag
[Double_tag].
(** The run-time library for lexers generated by [ocamllex]. *)
-(** {6 Positions} *)
+(** {1 Positions} *)
type position = {
pos_fname : string;
*)
-(** {6 Lexer buffers} *)
+(** {1 Lexer buffers} *)
type lexbuf =
provided. A return value of 0 means end of input. *)
-(** {6 Functions for lexer semantic actions} *)
+(** {1 Functions for lexer semantic actions} *)
(** The following functions can be called from the semantic actions
@since 3.11.0
*)
-(** {6 Miscellaneous functions} *)
+(** {1 Miscellaneous functions} *)
val flush_input : lexbuf -> unit
(** Discard the contents of the buffer and reset the current
(**/**)
-(** {6 } *)
+(** {1 } *)
(** The following definitions are used by the generated scanners only.
They are not intended to be used directly by user programs. *)
let rev l = rev_append l []
+let rec init_tailrec_aux acc i n f =
+ if i >= n then acc
+ else init_tailrec_aux (f i :: acc) (i+1) n f
+
+let rec init_aux i n f =
+ if i >= n then []
+ else
+ let r = f i in
+ r :: init_aux (i+1) n f
+
+let init len f =
+ if len < 0 then invalid_arg "List.init" else
+ if len > 10_000 then rev (init_tailrec_aux [] 0 len f)
+ else init_aux 0 len f
+
let rec flatten = function
[] -> []
| l::r -> l @ flatten r
;;
let rec compare_length_with l n =
- match l, n with
- | [], 0 -> 0
- | [], _ -> if n > 0 then -1 else 1
- | _, 0 -> 1
- | _ :: l, n -> compare_length_with l (n-1)
+ match l with
+ | [] ->
+ if n = 0 then 0 else
+ if n > 0 then -1 else 1
+ | _ :: l ->
+ if n <= 0 then 1 else
+ compare_length_with l (n-1)
;;
val rev : 'a list -> 'a list
(** List reversal. *)
+val init : int -> (int -> 'a) -> 'a list
+(** [List.init len f] is [f 0; f 1; ...; f (len-1)], evaluated left to right.
+
+ @raise Invalid_argument if len < 0.
+ @since 4.06.0
+*)
+
val append : 'a list -> 'a list -> 'a list
(** Concatenate two lists. Same as the infix operator [@].
Not tail-recursive (length of the first argument). *)
(** An alias for [concat]. *)
-(** {6 Iterators} *)
+(** {1 Iterators} *)
val iter : ('a -> unit) -> 'a list -> unit
[f a1 (f a2 (... (f an b) ...))]. Not tail-recursive. *)
-(** {6 Iterators on two lists} *)
+(** {1 Iterators on two lists} *)
val iter2 : ('a -> 'b -> unit) -> 'a list -> 'b list -> unit
to have different lengths. Not tail-recursive. *)
-(** {6 List scanning} *)
+(** {1 List scanning} *)
val for_all : ('a -> bool) -> 'a list -> bool
equality to compare list elements. *)
-(** {6 List searching} *)
+(** {1 List searching} *)
val find : ('a -> bool) -> 'a list -> 'a
The order of the elements in the input list is preserved. *)
-(** {6 Association lists} *)
+(** {1 Association lists} *)
val assoc : 'a -> ('a * 'b) list -> 'b
of structural equality to compare keys. Not tail-recursive. *)
-(** {6 Lists of pairs} *)
+(** {1 Lists of pairs} *)
val split : ('a * 'b) list -> 'a list * 'b list
have different lengths. Not tail-recursive. *)
-(** {6 Sorting} *)
+(** {1 Sorting} *)
val sort : ('a -> 'a -> int) -> 'a list -> 'a list
(** Merge two lists:
Assuming that [l1] and [l2] are sorted according to the
comparison function [cmp], [merge cmp l1 l2] will return a
- sorted list containting all the elements of [l1] and [l2].
+ sorted list containing all the elements of [l1] and [l2].
If several elements compare equal, the elements of [l1] will be
before the elements of [l2].
Not tail-recursive (sum of the lengths of the arguments).
val rev : 'a list -> 'a list
(** List reversal. *)
+val init : len:int -> f:(int -> 'a) -> 'a list
+(** [List.init len f] is [f 0; f 1; ...; f (len-1)], evaluated left to right.
+
+ @raise Invalid_argument if [len < 0].
+ @since 4.06.0
+*)
+
val append : 'a list -> 'a list -> 'a list
(** Catenate two lists. Same function as the infix operator [@].
Not tail-recursive (length of the first argument). The [@]
operator is not tail-recursive either. *)
val rev_append : 'a list -> 'a list -> 'a list
-(** [List.rev_append l1 l2] reverses [l1] and concatenates it to [l2].
- This is equivalent to {!List.rev}[ l1 @ l2], but [rev_append] is
+(** [List.rev_append l1 l2] reverses [l1] and concatenates it with [l2].
+ This is equivalent to [(]{!List.rev}[ l1) @ l2], but [rev_append] is
tail-recursive and more efficient. *)
val concat : 'a list list -> 'a list
(length of the argument + length of the longest sub-list). *)
-(** {6 Iterators} *)
+(** {1 Iterators} *)
val iter : f:('a -> unit) -> 'a list -> unit
[f a1 (f a2 (... (f an b) ...))]. Not tail-recursive. *)
-(** {6 Iterators on two lists} *)
+(** {1 Iterators on two lists} *)
val iter2 : f:('a -> 'b -> unit) -> 'a list -> 'b list -> unit
to have different lengths. Not tail-recursive. *)
-(** {6 List scanning} *)
+(** {1 List scanning} *)
val for_all : f:('a -> bool) -> 'a list -> bool
equality to compare list elements. *)
-(** {6 List searching} *)
+(** {1 List searching} *)
val find : f:('a -> bool) -> 'a list -> 'a
The order of the elements in the input list is preserved. *)
-(** {6 Association lists} *)
+(** {1 Association lists} *)
val assoc : 'a -> ('a * 'b) list -> 'b
of structural equality to compare keys. Not tail-recursive. *)
-(** {6 Lists of pairs} *)
+(** {1 Lists of pairs} *)
val split : ('a * 'b) list -> 'a list * 'b list
have different lengths. Not tail-recursive. *)
-(** {6 Sorting} *)
+(** {1 Sorting} *)
val sort : cmp:('a -> 'a -> int) -> 'a list -> 'a list
(** Merge two lists:
Assuming that [l1] and [l2] are sorted according to the
comparison function [cmp], [merge cmp l1 l2] will return a
- sorted list containting all the elements of [l1] and [l2].
+ sorted list containing all the elements of [l1] and [l2].
If several elements compare equal, the elements of [l1] will be
before the elements of [l2].
Not tail-recursive (sum of the lengths of the arguments).
val is_empty: 'a t -> bool
val mem: key -> 'a t -> bool
val add: key -> 'a -> 'a t -> 'a t
+ val update: key -> ('a option -> 'a option) -> 'a t -> 'a t
val singleton: key -> 'a -> 'a t
val remove: key -> 'a t -> 'a t
val merge:
type 'a t =
Empty
- | Node of 'a t * key * 'a * 'a t * int
+ | Node of {l:'a t; v:key; d:'a; r:'a t; h:int}
let height = function
Empty -> 0
- | Node(_,_,_,_,h) -> h
+ | Node {h} -> h
let create l x d r =
let hl = height l and hr = height r in
- Node(l, x, d, r, (if hl >= hr then hl + 1 else hr + 1))
+ Node{l; v=x; d; r; h=(if hl >= hr then hl + 1 else hr + 1)}
- let singleton x d = Node(Empty, x, d, Empty, 1)
+ let singleton x d = Node{l=Empty; v=x; d; r=Empty; h=1}
let bal l x d r =
- let hl = match l with Empty -> 0 | Node(_,_,_,_,h) -> h in
- let hr = match r with Empty -> 0 | Node(_,_,_,_,h) -> h in
+ let hl = match l with Empty -> 0 | Node {h} -> h in
+ let hr = match r with Empty -> 0 | Node {h} -> h in
if hl > hr + 2 then begin
match l with
Empty -> invalid_arg "Map.bal"
- | Node(ll, lv, ld, lr, _) ->
+ | Node{l=ll; v=lv; d=ld; r=lr} ->
if height ll >= height lr then
create ll lv ld (create lr x d r)
else begin
match lr with
Empty -> invalid_arg "Map.bal"
- | Node(lrl, lrv, lrd, lrr, _)->
+ | Node{l=lrl; v=lrv; d=lrd; r=lrr}->
create (create ll lv ld lrl) lrv lrd (create lrr x d r)
end
end else if hr > hl + 2 then begin
match r with
Empty -> invalid_arg "Map.bal"
- | Node(rl, rv, rd, rr, _) ->
+ | Node{l=rl; v=rv; d=rd; r=rr} ->
if height rr >= height rl then
create (create l x d rl) rv rd rr
else begin
match rl with
Empty -> invalid_arg "Map.bal"
- | Node(rll, rlv, rld, rlr, _) ->
+ | Node{l=rll; v=rlv; d=rld; r=rlr} ->
create (create l x d rll) rlv rld (create rlr rv rd rr)
end
end else
- Node(l, x, d, r, (if hl >= hr then hl + 1 else hr + 1))
+ Node{l; v=x; d; r; h=(if hl >= hr then hl + 1 else hr + 1)}
let empty = Empty
let rec add x data = function
Empty ->
- Node(Empty, x, data, Empty, 1)
- | Node(l, v, d, r, h) as m ->
+ Node{l=Empty; v=x; d=data; r=Empty; h=1}
+ | Node {l; v; d; r; h} as m ->
let c = Ord.compare x v in
if c = 0 then
- if d == data then m else Node(l, x, data, r, h)
+ if d == data then m else Node{l; v=x; d=data; r; h}
else if c < 0 then
let ll = add x data l in
if l == ll then m else bal ll v d r
let rec find x = function
Empty ->
raise Not_found
- | Node(l, v, d, r, _) ->
+ | Node {l; v; d; r} ->
let c = Ord.compare x v in
if c = 0 then d
else find x (if c < 0 then l else r)
let rec find_first_aux v0 d0 f = function
Empty ->
(v0, d0)
- | Node(l, v, d, r, _) ->
+ | Node {l; v; d; r} ->
if f v then
find_first_aux v d f l
else
let rec find_first f = function
Empty ->
raise Not_found
- | Node(l, v, d, r, _) ->
+ | Node {l; v; d; r} ->
if f v then
find_first_aux v d f l
else
let rec find_first_opt_aux v0 d0 f = function
Empty ->
Some (v0, d0)
- | Node(l, v, d, r, _) ->
+ | Node {l; v; d; r} ->
if f v then
find_first_opt_aux v d f l
else
let rec find_first_opt f = function
Empty ->
None
- | Node(l, v, d, r, _) ->
+ | Node {l; v; d; r} ->
if f v then
find_first_opt_aux v d f l
else
let rec find_last_aux v0 d0 f = function
Empty ->
(v0, d0)
- | Node(l, v, d, r, _) ->
+ | Node {l; v; d; r} ->
if f v then
find_last_aux v d f r
else
let rec find_last f = function
Empty ->
raise Not_found
- | Node(l, v, d, r, _) ->
+ | Node {l; v; d; r} ->
if f v then
find_last_aux v d f r
else
let rec find_last_opt_aux v0 d0 f = function
Empty ->
Some (v0, d0)
- | Node(l, v, d, r, _) ->
+ | Node {l; v; d; r} ->
if f v then
find_last_opt_aux v d f r
else
let rec find_last_opt f = function
Empty ->
None
- | Node(l, v, d, r, _) ->
+ | Node {l; v; d; r} ->
if f v then
find_last_opt_aux v d f r
else
let rec find_opt x = function
Empty ->
None
- | Node(l, v, d, r, _) ->
+ | Node {l; v; d; r} ->
let c = Ord.compare x v in
if c = 0 then Some d
else find_opt x (if c < 0 then l else r)
let rec mem x = function
Empty ->
false
- | Node(l, v, _, r, _) ->
+ | Node {l; v; r} ->
let c = Ord.compare x v in
c = 0 || mem x (if c < 0 then l else r)
let rec min_binding = function
Empty -> raise Not_found
- | Node(Empty, x, d, _, _) -> (x, d)
- | Node(l, _, _, _, _) -> min_binding l
+ | Node {l=Empty; v; d} -> (v, d)
+ | Node {l} -> min_binding l
let rec min_binding_opt = function
Empty -> None
- | Node(Empty, x, d, _, _) -> Some (x, d)
- | Node(l, _, _, _, _) -> min_binding_opt l
+ | Node {l=Empty; v; d} -> Some (v, d)
+ | Node {l}-> min_binding_opt l
let rec max_binding = function
Empty -> raise Not_found
- | Node(_, x, d, Empty, _) -> (x, d)
- | Node(_, _, _, r, _) -> max_binding r
+ | Node {v; d; r=Empty} -> (v, d)
+ | Node {r} -> max_binding r
let rec max_binding_opt = function
Empty -> None
- | Node(_, x, d, Empty, _) -> Some (x, d)
- | Node(_, _, _, r, _) -> max_binding_opt r
+ | Node {v; d; r=Empty} -> Some (v, d)
+ | Node {r} -> max_binding_opt r
let rec remove_min_binding = function
Empty -> invalid_arg "Map.remove_min_elt"
- | Node(Empty, _, _, r, _) -> r
- | Node(l, x, d, r, _) -> bal (remove_min_binding l) x d r
+ | Node {l=Empty; r} -> r
+ | Node {l; v; d; r} -> bal (remove_min_binding l) v d r
let merge t1 t2 =
match (t1, t2) with
let rec remove x = function
Empty ->
Empty
- | (Node(l, v, d, r, _) as t) ->
+ | (Node {l; v; d; r} as m) ->
let c = Ord.compare x v in
if c = 0 then merge l r
else if c < 0 then
- let ll = remove x l in if l == ll then t else bal ll v d r
+ let ll = remove x l in if l == ll then m else bal ll v d r
else
- let rr = remove x r in if r == rr then t else bal l v d rr
+ let rr = remove x r in if r == rr then m else bal l v d rr
+
+ let rec update x f = function
+ Empty ->
+ begin match f None with
+ | None -> Empty
+ | Some data -> Node{l=Empty; v=x; d=data; r=Empty; h=1}
+ end
+ | Node {l; v; d; r; h} as m ->
+ let c = Ord.compare x v in
+ if c = 0 then begin
+ match f (Some d) with
+ | None -> merge l r
+ | Some data ->
+ if d == data then m else Node{l; v=x; d=data; r; h}
+ end else if c < 0 then
+ let ll = update x f l in
+ if l == ll then m else bal ll v d r
+ else
+ let rr = update x f r in
+ if r == rr then m else bal l v d rr
let rec iter f = function
Empty -> ()
- | Node(l, v, d, r, _) ->
+ | Node {l; v; d; r} ->
iter f l; f v d; iter f r
let rec map f = function
Empty ->
Empty
- | Node(l, v, d, r, h) ->
+ | Node {l; v; d; r; h} ->
let l' = map f l in
let d' = f d in
let r' = map f r in
- Node(l', v, d', r', h)
+ Node{l=l'; v; d=d'; r=r'; h}
let rec mapi f = function
Empty ->
Empty
- | Node(l, v, d, r, h) ->
+ | Node {l; v; d; r; h} ->
let l' = mapi f l in
let d' = f v d in
let r' = mapi f r in
- Node(l', v, d', r', h)
+ Node{l=l'; v; d=d'; r=r'; h}
let rec fold f m accu =
match m with
Empty -> accu
- | Node(l, v, d, r, _) ->
+ | Node {l; v; d; r} ->
fold f r (f v d (fold f l accu))
let rec for_all p = function
Empty -> true
- | Node(l, v, d, r, _) -> p v d && for_all p l && for_all p r
+ | Node {l; v; d; r} -> p v d && for_all p l && for_all p r
let rec exists p = function
Empty -> false
- | Node(l, v, d, r, _) -> p v d || exists p l || exists p r
+ | Node {l; v; d; r} -> p v d || exists p l || exists p r
(* Beware: those two functions assume that the added k is *strictly*
smaller (or bigger) than all the present keys in the tree; it
respects this precondition.
*)
- let rec add_min_binding k v = function
- | Empty -> singleton k v
- | Node (l, x, d, r, _) ->
- bal (add_min_binding k v l) x d r
+ let rec add_min_binding k x = function
+ | Empty -> singleton k x
+ | Node {l; v; d; r} ->
+ bal (add_min_binding k x l) v d r
- let rec add_max_binding k v = function
- | Empty -> singleton k v
- | Node (l, x, d, r, _) ->
- bal l x d (add_max_binding k v r)
+ let rec add_max_binding k x = function
+ | Empty -> singleton k x
+ | Node {l; v; d; r} ->
+ bal l v d (add_max_binding k x r)
(* Same as create and bal, but no assumptions are made on the
relative heights of l and r. *)
match (l, r) with
(Empty, _) -> add_min_binding v d r
| (_, Empty) -> add_max_binding v d l
- | (Node(ll, lv, ld, lr, lh), Node(rl, rv, rd, rr, rh)) ->
+ | (Node{l=ll; v=lv; d=ld; r=lr; h=lh}, Node{l=rl; v=rv; d=rd; r=rr; h=rh}) ->
if lh > rh + 2 then bal ll lv ld (join lr v d r) else
if rh > lh + 2 then bal (join l v d rl) rv rd rr else
create l v d r
let rec split x = function
Empty ->
(Empty, None, Empty)
- | Node(l, v, d, r, _) ->
+ | Node {l; v; d; r} ->
let c = Ord.compare x v in
if c = 0 then (l, Some d, r)
else if c < 0 then
let rec merge f s1 s2 =
match (s1, s2) with
(Empty, Empty) -> Empty
- | (Node (l1, v1, d1, r1, h1), _) when h1 >= height s2 ->
+ | (Node {l=l1; v=v1; d=d1; r=r1; h=h1}, _) when h1 >= height s2 ->
let (l2, d2, r2) = split v1 s2 in
concat_or_join (merge f l1 l2) v1 (f v1 (Some d1) d2) (merge f r1 r2)
- | (_, Node (l2, v2, d2, r2, _)) ->
+ | (_, Node {l=l2; v=v2; d=d2; r=r2}) ->
let (l1, d1, r1) = split v2 s1 in
concat_or_join (merge f l1 l2) v2 (f v2 d1 (Some d2)) (merge f r1 r2)
| _ ->
let rec union f s1 s2 =
match (s1, s2) with
| (Empty, s) | (s, Empty) -> s
- | (Node (l1, v1, d1, r1, h1), Node (l2, v2, d2, r2, h2)) ->
+ | (Node {l=l1; v=v1; d=d1; r=r1; h=h1}, Node {l=l2; v=v2; d=d2; r=r2; h=h2}) ->
if h1 >= h2 then
let (l2, d2, r2) = split v1 s2 in
let l = union f l1 l2 and r = union f r1 r2 in
let rec filter p = function
Empty -> Empty
- | Node(l, v, d, r, _) as t ->
+ | Node {l; v; d; r} as m ->
(* call [p] in the expected left-to-right order *)
let l' = filter p l in
let pvd = p v d in
let r' = filter p r in
- if pvd then if l==l' && r==r' then t else join l' v d r'
+ if pvd then if l==l' && r==r' then m else join l' v d r'
else concat l' r'
let rec partition p = function
Empty -> (Empty, Empty)
- | Node(l, v, d, r, _) ->
+ | Node {l; v; d; r} ->
(* call [p] in the expected left-to-right order *)
let (lt, lf) = partition p l in
let pvd = p v d in
let rec cons_enum m e =
match m with
Empty -> e
- | Node(l, v, d, r, _) -> cons_enum l (More(v, d, r, e))
+ | Node {l; v; d; r} -> cons_enum l (More(v, d, r, e))
let compare cmp m1 m2 =
let rec compare_aux e1 e2 =
let rec cardinal = function
Empty -> 0
- | Node(l, _, _, r, _) -> cardinal l + 1 + cardinal r
+ | Node {l; r} -> cardinal l + 1 + cardinal r
let rec bindings_aux accu = function
Empty -> accu
- | Node(l, v, d, r, _) -> bindings_aux ((v, d) :: bindings_aux accu r) l
+ | Node {l; v; d; r} -> bindings_aux ((v, d) :: bindings_aux accu r) l
let bindings s =
bindings_aux [] s
of [x] in [m] disappears.
@before 4.03 Physical equality was not ensured. *)
+ val update: key -> ('a option -> 'a option) -> 'a t -> 'a t
+ (** [update x f m] returns a map containing the same bindings as
+ [m], except for the binding of [x]. Depending on the value of
+ [y] where [y] is [f (find_opt x m)], the binding of [x] is
+ added, removed or updated. If [y] is [None], the binding is
+ removed if it exists; otherwise, if [y] is [Some z] then [x]
+ is associated to [z] in the resulting map. If [x] was already
+ bound in [m] to a value that is physically equal to [z], [m]
+ is returned unchanged (the result of the function is then
+ physically equal to [m]).
+ @since 4.06.0
+ *)
+
val singleton: key -> 'a -> 'a t
(** [singleton x y] returns the one-element map that contains a binding [y]
for [x].
the [Marshal.from_*] functions is given as ['a], but this is
misleading: the returned OCaml value does not possess type ['a]
for all ['a]; it has one, unique type which cannot be determined
- at compile-type. The programmer should explicitly give the expected
+ at compile-time. The programmer should explicitly give the expected
type of the returned value, using the following syntax:
- [(Marshal.from_channel chan : type)].
Anything can happen at run-time if the object in the file does not
belong to the given type.
Values of extensible variant types, for example exceptions (of
- extensible type [exn]), returned by the unmarhsaller should not be
+ extensible type [exn]), returned by the unmarshaller should not be
pattern-matched over through [match ... with] or [try ... with],
because unmarshalling does not preserve the information required for
matching their constructors. Structural equalities with other
val is_empty: 'a t -> bool
val mem : key -> 'a t -> bool
val add : key:key -> data:'a -> 'a t -> 'a t
+ val update: key:key -> f:('a option -> 'a option) -> 'a t -> 'a t
val singleton: key -> 'a -> 'a t
val remove : key -> 'a t -> 'a t
val merge:
(** Bitwise logical exclusive or. *)
val lognot : nativeint -> nativeint
-(** Bitwise logical negation *)
+(** Bitwise logical negation. *)
external shift_left : nativeint -> int -> nativeint = "%nativeint_lsl"
(** [Nativeint.shift_left x y] shifts [x] to the left by [y] bits.
external of_string : string -> nativeint = "caml_nativeint_of_string"
(** Convert the given string to a native integer.
- The string is read in decimal (by default) or in hexadecimal,
- octal or binary if the string begins with [0x], [0o] or [0b]
- respectively.
- Raise [Failure "int_of_string"] if the given string is not
+ The string is read in decimal (by default, or if the string
+ begins with [0u]) or in hexadecimal, octal or binary if the
+ string begins with [0x], [0o] or [0b] respectively.
+
+ The [0u] prefix reads the input as an unsigned integer in the range
+ [[0, 2*Nativeint.max_int+1]]. If the input exceeds {!Nativeint.max_int}
+ it is converted to the signed integer
+ [Int64.min_int + input - Nativeint.max_int - 1].
+
+ Raise [Failure "Nativeint.of_string"] if the given string is not
a valid representation of an integer, or if the integer represented
exceeds the range of integers representable in type [nativeint]. *)
(**/**)
-(** {6 Deprecated functions} *)
+(** {1 Deprecated functions} *)
external format : string -> nativeint -> string = "caml_nativeint_format"
(** [Nativeint.format fmt n] return the string representation of the
external reachable_words : t -> int = "caml_obj_reachable_words"
external field : t -> int -> t = "%obj_field"
external set_field : t -> int -> t -> unit = "%obj_set_field"
-external array_get: 'a array -> int -> 'a = "%array_safe_get"
-external array_set: 'a array -> int -> 'a -> unit = "%array_safe_set"
-let [@inline always] double_field x i = array_get (obj x : float array) i
+external floatarray_get : floatarray -> int -> float = "caml_floatarray_get"
+external floatarray_set :
+ floatarray -> int -> float -> unit = "caml_floatarray_set"
+let [@inline always] double_field x i = floatarray_get (obj x : floatarray) i
let [@inline always] set_double_field x i v =
- array_set (obj x : float array) i v
+ floatarray_set (obj x : floatarray) i v
external new_block : int -> int -> t = "caml_obj_block"
external dup : t -> t = "caml_obj_dup"
external truncate : t -> int -> unit = "caml_obj_truncate"
(**/**)
-(** {6 } *)
+(** {1 } *)
(** The following definitions are used by the generated parsers only.
They are not intended to be used directly by user programs. *)
(* String and byte sequence operations -- more in modules String and Bytes *)
external string_length : string -> int = "%string_length"
-external bytes_length : bytes -> int = "%string_length"
+external bytes_length : bytes -> int = "%bytes_length"
external bytes_create : int -> bytes = "caml_create_bytes"
external string_blit : string -> int -> bytes -> int -> int -> unit
= "caml_blit_string" [@@noalloc]
try Some (int_of_string s)
with Failure _ -> None
-
external string_get : string -> int -> char = "%string_safe_get"
let valid_float_lexem s =
in
loop 0
-
let string_of_float f = valid_float_lexem (format_float "%.12g" f)
external float_of_string : string -> float = "caml_float_of_string"
let flush_all () =
let rec iter = function
[] -> ()
- | a :: l -> (try flush a with _ -> ()); iter l
+ | a::l ->
+ begin try
+ flush a
+ with Sys_error _ ->
+ () (* ignore channels closed during a preceding flush. *)
+ end;
+ iter l
in iter (out_channels_list ())
external unsafe_output : out_channel -> bytes -> int -> int -> unit
*)
-(** {6 Exceptions} *)
+(** {1 Exceptions} *)
external raise : exn -> 'a = "%raise"
(** Raise the given exception value *)
provided for use in your programs. *)
-(** {6 Comparisons} *)
+(** {1 Comparisons} *)
external ( = ) : 'a -> 'a -> bool = "%equal"
(** [e1 = e2] tests for structural equality of [e1] and [e2].
if and only if their current contents are structurally equal,
even if the two mutable objects are not the same physical object.
Equality between functional values raises [Invalid_argument].
- Equality between cyclic data structures may not terminate. *)
+ Equality between cyclic data structures may not terminate.
+ Left-associative operator at precedence level 4/11. *)
external ( <> ) : 'a -> 'a -> bool = "%notequal"
-(** Negation of {!Pervasives.( = )}. *)
+(** Negation of {!Pervasives.( = )}.
+ Left-associative operator at precedence level 4/11. *)
external ( < ) : 'a -> 'a -> bool = "%lessthan"
-(** See {!Pervasives.( >= )}. *)
+(** See {!Pervasives.( >= )}.
+ Left-associative operator at precedence level 4/11. *)
external ( > ) : 'a -> 'a -> bool = "%greaterthan"
-(** See {!Pervasives.( >= )}. *)
+(** See {!Pervasives.( >= )}.
+ Left-associative operator at precedence level 4/11. *)
external ( <= ) : 'a -> 'a -> bool = "%lessequal"
-(** See {!Pervasives.( >= )}. *)
+(** See {!Pervasives.( >= )}.
+ Left-associative operator at precedence level 4/11. *)
external ( >= ) : 'a -> 'a -> bool = "%greaterequal"
(** Structural ordering functions. These functions coincide with
The ordering is compatible with [( = )]. As in the case
of [( = )], mutable structures are compared by contents.
Comparison between functional values raises [Invalid_argument].
- Comparison between cyclic structures may not terminate. *)
+ Comparison between cyclic structures may not terminate.
+ Left-associative operator at precedence level 4/11. *)
external compare : 'a -> 'a -> int = "%compare"
(** [compare x y] returns [0] if [x] is equal to [y],
also affects [e2].
On non-mutable types, the behavior of [( == )] is
implementation-dependent; however, it is guaranteed that
- [e1 == e2] implies [compare e1 e2 = 0]. *)
+ [e1 == e2] implies [compare e1 e2 = 0].
+ Left-associative operator at precedence level 4/11. *)
external ( != ) : 'a -> 'a -> bool = "%noteq"
-(** Negation of {!Pervasives.( == )}. *)
+(** Negation of {!Pervasives.( == )}.
+ Left-associative operator at precedence level 4/11. *)
-(** {6 Boolean operations} *)
+(** {1 Boolean operations} *)
external not : bool -> bool = "%boolnot"
(** The boolean negation. *)
external ( && ) : bool -> bool -> bool = "%sequand"
(** The boolean 'and'. Evaluation is sequential, left-to-right:
in [e1 && e2], [e1] is evaluated first, and if it returns [false],
- [e2] is not evaluated at all. *)
+ [e2] is not evaluated at all.
+ Right-associative operator at precedence level 3/11. *)
external ( & ) : bool -> bool -> bool = "%sequand"
[@@ocaml.deprecated "Use (&&) instead."]
-(** @deprecated {!Pervasives.( && )} should be used instead. *)
+(** @deprecated {!Pervasives.( && )} should be used instead.
+ Right-associative operator at precedence level 3/11. *)
external ( || ) : bool -> bool -> bool = "%sequor"
(** The boolean 'or'. Evaluation is sequential, left-to-right:
in [e1 || e2], [e1] is evaluated first, and if it returns [true],
- [e2] is not evaluated at all. *)
+ [e2] is not evaluated at all.
+ Right-associative operator at precedence level 2/11.
+*)
external ( or ) : bool -> bool -> bool = "%sequor"
[@@ocaml.deprecated "Use (||) instead."]
-(** @deprecated {!Pervasives.( || )} should be used instead.*)
+(** @deprecated {!Pervasives.( || )} should be used instead.
+ Right-associative operator at precedence level 2/11. *)
-(** {6 Debugging} *)
+(** {1 Debugging} *)
external __LOC__ : string = "%loc_LOC"
(** [__LOC__] returns the location at which this expression appears in
@since 4.02.0
*)
-(** {6 Composition operators} *)
+(** {1 Composition operators} *)
external ( |> ) : 'a -> ('a -> 'b) -> 'b = "%revapply"
(** Reverse-application operator: [x |> f |> g] is exactly equivalent
to [g (f (x))].
+ Left-associative operator at precedence level 4/11.
@since 4.01
-*)
+ *)
external ( @@ ) : ('a -> 'b) -> 'a -> 'b = "%apply"
(** Application operator: [g @@ f @@ x] is exactly equivalent to
[g (f (x))].
+ Right-associative operator at precedence level 5/11.
@since 4.01
*)
-(** {6 Integer arithmetic} *)
+(** {1 Integer arithmetic} *)
(** Integers are 31 bits wide (or 63 bits on 64-bit processors).
All operations are taken modulo 2{^31} (or 2{^63}).
They do not fail on overflow. *)
external ( ~- ) : int -> int = "%negint"
-(** Unary negation. You can also write [- e] instead of [~- e]. *)
+(** Unary negation. You can also write [- e] instead of [~- e].
+ Unary operator at precedence level 9/11 for [- e]
+ and 11/11 for [~- e]. *)
external ( ~+ ) : int -> int = "%identity"
(** Unary addition. You can also write [+ e] instead of [~+ e].
+ Unary operator at precedence level 9/11 for [+ e]
+ and 11/11 for [~+ e].
@since 3.12.0
*)
(** [pred x] is [x - 1]. *)
external ( + ) : int -> int -> int = "%addint"
-(** Integer addition. *)
+(** Integer addition.
+ Left-associative operator at precedence level 6/11. *)
external ( - ) : int -> int -> int = "%subint"
-(** Integer subtraction. *)
+(** Integer subtraction.
+ Left-associative operator at precedence level 6/11. *)
external ( * ) : int -> int -> int = "%mulint"
-(** Integer multiplication. *)
+(** Integer multiplication.
+ Left-associative operator at precedence level 7/11. *)
external ( / ) : int -> int -> int = "%divint"
(** Integer division.
Integer division rounds the real quotient of its arguments towards zero.
More precisely, if [x >= 0] and [y > 0], [x / y] is the greatest integer
less than or equal to the real quotient of [x] by [y]. Moreover,
- [(- x) / y = x / (- y) = - (x / y)]. *)
+ [(- x) / y = x / (- y) = - (x / y)].
+ Left-associative operator at precedence level 7/11. *)
external ( mod ) : int -> int -> int = "%modint"
(** Integer remainder. If [y] is not zero, the result
[abs(x mod y) <= abs(y) - 1].
If [y = 0], [x mod y] raises [Division_by_zero].
Note that [x mod y] is negative only if [x < 0].
- Raise [Division_by_zero] if [y] is zero. *)
+ Raise [Division_by_zero] if [y] is zero.
+ Left-associative operator at precedence level 7/11. *)
val abs : int -> int
(** Return the absolute value of the argument. Note that this may be
(** The smallest representable integer. *)
-(** {7 Bitwise operations} *)
+(** {2 Bitwise operations} *)
external ( land ) : int -> int -> int = "%andint"
-(** Bitwise logical and. *)
+(** Bitwise logical and.
+ Left-associative operator at precedence level 7/11. *)
external ( lor ) : int -> int -> int = "%orint"
-(** Bitwise logical or. *)
+(** Bitwise logical or.
+ Left-associative operator at precedence level 7/11. *)
external ( lxor ) : int -> int -> int = "%xorint"
-(** Bitwise logical exclusive or. *)
+(** Bitwise logical exclusive or.
+ Left-associative operator at precedence level 7/11. *)
val lnot : int -> int
(** Bitwise logical negation. *)
(** [n lsl m] shifts [n] to the left by [m] bits.
The result is unspecified if [m < 0] or [m >= bitsize],
where [bitsize] is [32] on a 32-bit platform and
- [64] on a 64-bit platform. *)
+ [64] on a 64-bit platform.
+ Right-associative operator at precedence level 8/11. *)
external ( lsr ) : int -> int -> int = "%lsrint"
(** [n lsr m] shifts [n] to the right by [m] bits.
This is a logical shift: zeroes are inserted regardless of
the sign of [n].
- The result is unspecified if [m < 0] or [m >= bitsize]. *)
+ The result is unspecified if [m < 0] or [m >= bitsize].
+ Right-associative operator at precedence level 8/11. *)
external ( asr ) : int -> int -> int = "%asrint"
(** [n asr m] shifts [n] to the right by [m] bits.
This is an arithmetic shift: the sign bit of [n] is replicated.
- The result is unspecified if [m < 0] or [m >= bitsize]. *)
+ The result is unspecified if [m < 0] or [m >= bitsize].
+ Right-associative operator at precedence level 8/11. *)
-(** {6 Floating-point arithmetic}
+(** {1 Floating-point arithmetic}
OCaml's floating-point numbers follow the
IEEE 754 standard, using double precision (64 bits) numbers.
*)
external ( ~-. ) : float -> float = "%negfloat"
-(** Unary negation. You can also write [-. e] instead of [~-. e]. *)
+(** Unary negation. You can also write [-. e] instead of [~-. e].
+ Unary operator at precedence level 9/11 for [-. e]
+ and 11/11 for [~-. e]. *)
external ( ~+. ) : float -> float = "%identity"
(** Unary addition. You can also write [+. e] instead of [~+. e].
+ Unary operator at precedence level 9/11 for [+. e]
+ and 11/11 for [~+. e].
@since 3.12.0
*)
external ( +. ) : float -> float -> float = "%addfloat"
-(** Floating-point addition *)
+(** Floating-point addition.
+ Left-associative operator at precedence level 6/11. *)
external ( -. ) : float -> float -> float = "%subfloat"
-(** Floating-point subtraction *)
+(** Floating-point subtraction.
+ Left-associative operator at precedence level 6/11. *)
external ( *. ) : float -> float -> float = "%mulfloat"
-(** Floating-point multiplication *)
+(** Floating-point multiplication.
+ Left-associative operator at precedence level 7/11. *)
external ( /. ) : float -> float -> float = "%divfloat"
-(** Floating-point division. *)
+(** Floating-point division.
+ Left-associative operator at precedence level 7/11. *)
external ( ** ) : float -> float -> float = "caml_power_float" "pow"
[@@unboxed] [@@noalloc]
-(** Exponentiation. *)
+(** Exponentiation.
+ Right-associative operator at precedence level 8/11. *)
external sqrt : float -> float = "caml_sqrt_float" "sqrt"
[@@unboxed] [@@noalloc]
normal, subnormal, zero, infinite, or not a number. *)
-(** {6 String operations}
+(** {1 String operations}
More string operations are provided in module {!String}.
*)
val ( ^ ) : string -> string -> string
-(** String concatenation. *)
+(** String concatenation.
+ Right-associative operator at precedence level 5/11. *)
-(** {6 Character operations}
+(** {1 Character operations}
More character operations are provided in module {!Char}.
*)
outside the range 0--255. *)
-(** {6 Unit operations} *)
+(** {1 Unit operations} *)
external ignore : 'a -> unit = "%ignore"
(** Discard the value of its argument and return [()].
avoids the warning. *)
-(** {6 String conversion functions} *)
+(** {1 String conversion functions} *)
val string_of_bool : bool -> string
(** Return the string representation of a boolean. As the returned values
external int_of_string : string -> int = "caml_int_of_string"
(** Convert the given string to an integer.
- The string is read in decimal (by default), in hexadecimal (if it
- begins with [0x] or [0X]), in octal (if it begins with [0o] or [0O]),
- or in binary (if it begins with [0b] or [0B]).
+ The string is read in decimal (by default, or if the string
+ begins with [0u]), in hexadecimal (if it begins with [0x] or
+ [0X]), in octal (if it begins with [0o] or [0O]), or in binary
+ (if it begins with [0b] or [0B]).
+
+ The [0u] prefix reads the input as an unsigned integer in the range
+ [[0, 2*max_int+1]]. If the input exceeds {!max_int}
+ it is converted to the signed integer
+ [min_int + input - max_int - 1].
+
The [_] (underscore) character can appear anywhere in the string
and is ignored.
Raise [Failure "int_of_string"] if the given string is not
val int_of_string_opt: string -> int option
-(** Same as [int_of_string], but returs [None] instead of raising.
+(** Same as [int_of_string], but returns [None] instead of raising.
@since 4.05
*)
@since 4.05
*)
-(** {6 Pair operations} *)
+(** {1 Pair operations} *)
external fst : 'a * 'b -> 'a = "%field0"
(** Return the first component of a pair. *)
(** Return the second component of a pair. *)
-(** {6 List operations}
+(** {1 List operations}
More list operations are provided in module {!List}.
*)
val ( @ ) : 'a list -> 'a list -> 'a list
-(** List concatenation. Not tail-recursive (length of the first argument). *)
+(** List concatenation. Not tail-recursive (length of the first argument).
+ Right-associative operator at precedence level 5/11. *)
-(** {6 Input/output}
+(** {1 Input/output}
Note: all input/output functions can raise [Sys_error] when the system
calls they invoke fail. *)
(** The standard error output for the process. *)
-(** {7 Output functions on standard output} *)
+(** {2 Output functions on standard output} *)
val print_char : char -> unit
(** Print a character on standard output. *)
buffering of standard output. *)
-(** {7 Output functions on standard error} *)
+(** {2 Output functions on standard error} *)
val prerr_char : char -> unit
(** Print a character on standard error. *)
standard error. *)
-(** {7 Input functions on standard input} *)
+(** {2 Input functions on standard input} *)
val read_line : unit -> string
(** Flush standard output, then read characters from standard input
if the line read is not a valid representation of an integer. *)
val read_int_opt: unit -> int option
-(** Same as [read_int_opt], but returs [None] instead of raising.
+(** Same as [read_int_opt], but returns [None] instead of raising.
@since 4.05
*)
@since 4.05.0 *)
-(** {7 General output functions} *)
+(** {2 General output functions} *)
type open_flag =
Open_rdonly (** open for reading. *)
do not distinguish between text mode and binary mode. *)
-(** {7 General input functions} *)
+(** {2 General input functions} *)
val open_in : string -> in_channel
(** Open the named file for reading, and return a new input channel
do not distinguish between text mode and binary mode. *)
-(** {7 Operations on large files} *)
+(** {2 Operations on large files} *)
module LargeFile :
sig
operating on files whose sizes are greater than [max_int]. *)
-(** {6 References} *)
+(** {1 References} *)
type 'a ref = { mutable contents : 'a }
(** The type of references (mutable indirection cells) containing
external ( ! ) : 'a ref -> 'a = "%field0"
(** [!r] returns the current contents of reference [r].
- Equivalent to [fun r -> r.contents]. *)
+ Equivalent to [fun r -> r.contents].
+ Unary operator at precedence level 11/11.*)
external ( := ) : 'a ref -> 'a -> unit = "%setfield0"
(** [r := a] stores the value of [a] in reference [r].
- Equivalent to [fun r v -> r.contents <- v]. *)
+ Equivalent to [fun r v -> r.contents <- v].
+ Right-associative operator at precedence level 1/11. *)
external incr : int ref -> unit = "%incr"
(** Increment the integer contained in the given reference.
(** Decrement the integer contained in the given reference.
Equivalent to [fun r -> r := pred !r]. *)
-(** {6 Result type} *)
+(** {1 Result type} *)
(** @since 4.03.0 *)
type ('a,'b) result = Ok of 'a | Error of 'b
-(** {6 Operations on format strings} *)
+(** {1 Operations on format strings} *)
(** Format strings are character strings with special lexical conventions
that defines the functionality of formatted input/output functions. Format
[f2]: in case of formatted output, it accepts arguments from [f1], then
arguments from [f2]; in case of formatted input, it returns results from
[f1], then results from [f2].
-*)
+ Right-associative operator at precedence level 5/11. *)
-(** {6 Program termination} *)
+(** {1 Program termination} *)
val exit : int -> 'a
(** Terminate the process, returning the given status code
terminates early because of an uncaught exception. *)
val at_exit : (unit -> unit) -> unit
-(** Register the given function to be called at program
- termination time. The functions registered with [at_exit]
- will be called when the program executes {!Pervasives.exit},
- or terminates, either normally or because of an uncaught exception.
- The functions are called in 'last in, first out' order:
- the function most recently added with [at_exit] is called first. *)
+(** Register the given function to be called at program termination
+ time. The functions registered with [at_exit] will be called when
+ the program does any of the following:
+ - executes {!Pervasives.exit}
+ - terminates, either normally or because of an uncaught
+ exception
+ - executes the C function [caml_shutdown].
+ The functions are called in 'last in, first out' order: the
+ function most recently added with [at_exit] is called first. *)
(**/**)
@since 3.11.2
*)
-(** {6 Raw backtraces} *)
+(** {1 Raw backtraces} *)
type raw_backtrace
(** The abstract type [raw_backtrace] stores a backtrace in
@since 4.05.0
*)
-(** {6 Current call stack} *)
+(** {1 Current call stack} *)
val get_callstack: int -> raw_backtrace
(** [Printexc.get_callstack n] returns a description of the top of the
@since 4.01.0
*)
-(** {6 Uncaught exceptions} *)
+(** {1 Uncaught exceptions} *)
val set_uncaught_exception_handler: (exn -> raw_backtrace -> unit) -> unit
(** [Printexc.set_uncaught_exception_handler fn] registers [fn] as the handler
*)
-(** {6 Manipulation of backtrace information}
+(** {1 Manipulation of backtrace information}
These functions are used to traverse the slots of a raw backtrace
and extract information from them in a programmer-friendly format.
end
-(** {6 Raw backtrace slots} *)
+(** {1 Raw backtrace slots} *)
type raw_backtrace_slot
(** This type allows direct access to raw backtrace slots, without any
@since 4.04.0
*)
-(** {6 Exception slots} *)
+(** {1 Exception slots} *)
val exn_slot_id: exn -> int
(** [Printexc.exn_slot_id] returns an integer which uniquely identifies
- [e] or [E]: convert a floating-point argument to decimal notation,
in the style [d.ddd e+-dd] (mantissa and exponent).
- [g] or [G]: convert a floating-point argument to decimal notation,
- in style [f] or [e], [E] (whichever is more compact).
+ in style [f] or [e], [E] (whichever is more compact). Moreover,
+ any trailing zeros are removed from the fractional part of the result
+ and the decimal-point character is removed if there is no fractional
+ part remaining.
- [h] or [H]: convert a floating-point argument to hexadecimal notation,
in the style [0xh.hhhh e+-dd] (hexadecimal mantissa, exponent in
decimal and denotes a power of 2).
(** Pseudo-random number generators (PRNG). *)
-(** {6 Basic functions} *)
+(** {1 Basic functions} *)
val init : int -> unit
(** Initialize the generator, using the argument as a seed.
(** [Random.bool ()] returns [true] or [false] with probability 0.5 each. *)
-(** {6 Advanced functions} *)
+(** {1 Advanced functions} *)
(** The functions from module {!State} manipulate the current state
of the random generator explicitly.
More precisely, given [ic], all successive calls [fscanf ic] must read
from the same scanning buffer.
This obliged this library to allocated scanning buffers that were
- not properly garbbage collectable, hence leading to memory leaks.
+ not properly garbage collectable, hence leading to memory leaks.
If you need to read from a [Pervasives.in_channel] input channel
[ic], simply define a [Scanning.in_channel] formatted input channel as in
[let ib = Scanning.from_channel ic], then use [Scanf.bscanf ib] as usual.
let scan_digit_plus basis digitp width ib =
(* Ensure we have got enough width left,
- and read at list one digit. *)
+ and read at least one digit. *)
if width = 0 then bad_token_length "digits" else
let c = Scanning.checked_peek_char ib in
if digitp c then
(******************************************************************************)
- (* Readers managment *)
+ (* Reader management *)
(* A call to take_format_readers on a format is evaluated into functions
taking readers as arguments and aggregate them into an heterogeneous list *)
| Nativeint (_, _, _, rest) -> take_format_readers k rest
| Int64 (_, _, _, rest) -> take_format_readers k rest
| Float (_, _, _, rest) -> take_format_readers k rest
- | Bool rest -> take_format_readers k rest
+ | Bool (_, rest) -> take_format_readers k rest
| Alpha rest -> take_format_readers k rest
| Theta rest -> take_format_readers k rest
| Flush rest -> take_format_readers k rest
| Ignored_nativeint (_, _) -> take_format_readers k fmt
| Ignored_int64 (_, _) -> take_format_readers k fmt
| Ignored_float (_, _) -> take_format_readers k fmt
- | Ignored_bool -> take_format_readers k fmt
+ | Ignored_bool _ -> take_format_readers k fmt
| Ignored_format_arg _ -> take_format_readers k fmt
| Ignored_format_subst (_, fmtty) -> take_fmtty_format_readers k fmtty fmt
| Ignored_scan_char_set _ -> take_format_readers k fmt
(* Make a generic scanning function. *)
(* Scan a stream according to a format and readers obtained by
- take_format_readers, and aggegate scanned values into an
+ take_format_readers, and aggregate scanned values into an
heterogeneous list. *)
(* Return the heterogeneous list of scanned values. *)
let rec make_scanf : type a c d e f.
| Float ((Float_h | Float_ph | Float_sh | Float_H | Float_pH | Float_sH),
pad, prec, rest) ->
pad_prec_scanf ib rest readers pad prec scan_hex_float token_float
- | Bool rest ->
- let _ = scan_bool ib in
- let b = token_bool ib in
- Cons (b, make_scanf ib rest readers)
+ | Bool (pad, rest) ->
+ let scan _ _ ib = scan_bool ib in
+ pad_prec_scanf ib rest readers pad No_precision scan token_bool
| Alpha _ ->
invalid_arg "scanf: bad conversion \"%a\""
| Theta _ ->
| Cons (reader, readers_rest) ->
let x = reader ib in
Cons (x, make_scanf ib fmt_rest readers_rest)
- | Nil ->
+ | Nil ->
invalid_arg "scanf: missing reader"
end
| Flush rest ->
(** Formatted input functions. *)
-(** {6 Introduction} *)
+(** {1 Introduction} *)
-(** {7 Functional input with format strings} *)
+(** {2 Functional input with format strings} *)
(** The module {!Scanf} provides formatted input functions or {e scanners}.
read in the input according to [fmt].
*)
-(** {7 A simple example} *)
+(** {2 A simple example} *)
(** As suggested above, the expression [bscanf ic "%d" f] reads a decimal
integer [n] from the source of characters [ic] and returns [f n].
keyboard, the result we get is [42].
*)
-(** {7 Formatted input as a functional feature} *)
+(** {2 Formatted input as a functional feature} *)
(** The OCaml scanning facility is reminiscent of the corresponding C feature.
However, it is also largely different, simpler, and yet more powerful:
facility is fully type-checked at compile time.
*)
-(** {6 Formatted input channel} *)
+(** {1 Formatted input channel} *)
module Scanning : sig
end
-(** {6 Type of formatted input functions} *)
+(** {1 Type of formatted input functions} *)
type ('a, 'b, 'c, 'd) scanner =
('a, Scanning.in_channel, 'b, 'c, 'a -> 'd, 'd) format6 -> 'c
For instance, the {!Scanf.scanf} function below has type
[('a, 'b, 'c, 'd) scanner], since it is a formatted input function that
reads from {!Scanning.stdin}: [scanf fmt f] applies [f] to the arguments
- specified by [fmt], reading those arguments from [!Pervasives.stdin] as
+ specified by [fmt], reading those arguments from {!Pervasives.stdin} as
expected.
If the format [fmt] has some [%r] indications, the corresponding
[Scan_failure].
*)
-(** {6 The general formatted input function} *)
+(** {1 The general formatted input function} *)
val bscanf : Scanning.in_channel -> ('a, 'b, 'c, 'd) scanner
string.
*)
-(** {6 Format string description} *)
+(** {1 Format string description} *)
(** The format string is a character string which contains three types of
objects:
(see scanning {!Scanf.indication}).
*)
-(** {7:space The space character in format strings} *)
+(** {2:space The space character in format strings} *)
(** As mentioned above, a plain character in the format string is just
matched with the next character of the input; however, two characters are
[Price = 1 $], or even [Price=1$].
*)
-(** {7:conversion Conversion specifications in format strings} *)
+(** {2:conversion Conversion specifications in format strings} *)
(** Conversion specifications consist in the [%] character, followed by
an optional flag, an optional field width, and followed by one or
[ocamlyacc]-generated parsers.
*)
-(** {7:indication Scanning indications in format strings} *)
+(** {2:indication Scanning indications in format strings} *)
(** Scanning indications appear just after the string conversions [%s]
and [%[ range ]] to delimit the end of the token. A scanning
characters).
*)
-(** {7 Exceptions during scanning} *)
+(** {2 Exceptions during scanning} *)
(** Scanners may raise the following exceptions when the input cannot be read
according to the format string:
simply returns the characters read so far, or [""] if none were ever read.
*)
-(** {6 Specialised formatted input functions} *)
+(** {1 Specialised formatted input functions} *)
val sscanf : string -> ('a, 'b, 'c, 'd) scanner
(** Same as {!Scanf.bscanf}, but reads from the given string. *)
(** Same as {!Scanf.kscanf} but reads from the given string.
@since 4.02.0 *)
-(** {6 Reading format strings from input} *)
+(** {1 Reading format strings from input} *)
val bscanf_format :
Scanning.in_channel -> ('a, 'b, 'c, 'd, 'e, 'f) format6 ->
@since 4.00.0
*)
-(** {6 Deprecated} *)
+(** {1 Deprecated} *)
val fscanf : Pervasives.in_channel -> ('a, 'b, 'c, 'd) scanner
[@@ocaml.deprecated "Use Scanning.from_channel then Scanf.bscanf."]
module Make(Ord: OrderedType) =
struct
type elt = Ord.t
- type t = Empty | Node of t * elt * t * int
+ type t = Empty | Node of {l:t; v:elt; r:t; h:int}
(* Sets are represented by balanced binary trees (the heights of the
children differ by at most 2 *)
let height = function
Empty -> 0
- | Node(_, _, _, h) -> h
+ | Node {h} -> h
(* Creates a new node with left son l, value v and right son r.
We must have all elements of l < v < all elements of r.
Inline expansion of height for better speed. *)
let create l v r =
- let hl = match l with Empty -> 0 | Node(_,_,_,h) -> h in
- let hr = match r with Empty -> 0 | Node(_,_,_,h) -> h in
- Node(l, v, r, (if hl >= hr then hl + 1 else hr + 1))
+ let hl = match l with Empty -> 0 | Node {h} -> h in
+ let hr = match r with Empty -> 0 | Node {h} -> h in
+ Node{l; v; r; h=(if hl >= hr then hl + 1 else hr + 1)}
(* Same as create, but performs one step of rebalancing if necessary.
Assumes l and r balanced and | height l - height r | <= 3.
where no rebalancing is required. *)
let bal l v r =
- let hl = match l with Empty -> 0 | Node(_,_,_,h) -> h in
- let hr = match r with Empty -> 0 | Node(_,_,_,h) -> h in
+ let hl = match l with Empty -> 0 | Node {h} -> h in
+ let hr = match r with Empty -> 0 | Node {h} -> h in
if hl > hr + 2 then begin
match l with
Empty -> invalid_arg "Set.bal"
- | Node(ll, lv, lr, _) ->
+ | Node{l=ll; v=lv; r=lr} ->
if height ll >= height lr then
create ll lv (create lr v r)
else begin
match lr with
Empty -> invalid_arg "Set.bal"
- | Node(lrl, lrv, lrr, _)->
+ | Node{l=lrl; v=lrv; r=lrr}->
create (create ll lv lrl) lrv (create lrr v r)
end
end else if hr > hl + 2 then begin
match r with
Empty -> invalid_arg "Set.bal"
- | Node(rl, rv, rr, _) ->
+ | Node{l=rl; v=rv; r=rr} ->
if height rr >= height rl then
create (create l v rl) rv rr
else begin
match rl with
Empty -> invalid_arg "Set.bal"
- | Node(rll, rlv, rlr, _) ->
+ | Node{l=rll; v=rlv; r=rlr} ->
create (create l v rll) rlv (create rlr rv rr)
end
end else
- Node(l, v, r, (if hl >= hr then hl + 1 else hr + 1))
+ Node{l; v; r; h=(if hl >= hr then hl + 1 else hr + 1)}
(* Insertion of one element *)
let rec add x = function
- Empty -> Node(Empty, x, Empty, 1)
- | Node(l, v, r, _) as t ->
+ Empty -> Node{l=Empty; v=x; r=Empty; h=1}
+ | Node{l; v; r} as t ->
let c = Ord.compare x v in
if c = 0 then t else
if c < 0 then
let rr = add x r in
if r == rr then t else bal l v rr
- let singleton x = Node(Empty, x, Empty, 1)
+ let singleton x = Node{l=Empty; v=x; r=Empty; h=1}
(* Beware: those two functions assume that the added v is *strictly*
smaller (or bigger) than all the present elements in the tree; it
respects this precondition.
*)
- let rec add_min_element v = function
- | Empty -> singleton v
- | Node (l, x, r, _h) ->
- bal (add_min_element v l) x r
+ let rec add_min_element x = function
+ | Empty -> singleton x
+ | Node {l; v; r} ->
+ bal (add_min_element x l) v r
- let rec add_max_element v = function
- | Empty -> singleton v
- | Node (l, x, r, _h) ->
- bal l x (add_max_element v r)
+ let rec add_max_element x = function
+ | Empty -> singleton x
+ | Node {l; v; r} ->
+ bal l v (add_max_element x r)
(* Same as create and bal, but no assumptions are made on the
relative heights of l and r. *)
match (l, r) with
(Empty, _) -> add_min_element v r
| (_, Empty) -> add_max_element v l
- | (Node(ll, lv, lr, lh), Node(rl, rv, rr, rh)) ->
+ | (Node{l=ll; v=lv; r=lr; h=lh}, Node{l=rl; v=rv; r=rr; h=rh}) ->
if lh > rh + 2 then bal ll lv (join lr v r) else
if rh > lh + 2 then bal (join l v rl) rv rr else
create l v r
let rec min_elt = function
Empty -> raise Not_found
- | Node(Empty, v, _, _) -> v
- | Node(l, _, _, _) -> min_elt l
+ | Node{l=Empty; v} -> v
+ | Node{l} -> min_elt l
let rec min_elt_opt = function
Empty -> None
- | Node(Empty, v, _, _) -> Some v
- | Node(l, _, _, _) -> min_elt_opt l
+ | Node{l=Empty; v} -> Some v
+ | Node{l} -> min_elt_opt l
let rec max_elt = function
Empty -> raise Not_found
- | Node(_, v, Empty, _) -> v
- | Node(_, _, r, _) -> max_elt r
+ | Node{v; r=Empty} -> v
+ | Node{r} -> max_elt r
let rec max_elt_opt = function
Empty -> None
- | Node(_, v, Empty, _) -> Some v
- | Node(_, _, r, _) -> max_elt_opt r
+ | Node{v; r=Empty} -> Some v
+ | Node{r} -> max_elt_opt r
(* Remove the smallest element of the given set *)
let rec remove_min_elt = function
Empty -> invalid_arg "Set.remove_min_elt"
- | Node(Empty, _, r, _) -> r
- | Node(l, v, r, _) -> bal (remove_min_elt l) v r
+ | Node{l=Empty; r} -> r
+ | Node{l; v; r} -> bal (remove_min_elt l) v r
(* Merge two trees l and r into one.
All elements of l must precede the elements of r.
let rec split x = function
Empty ->
(Empty, false, Empty)
- | Node(l, v, r, _) ->
+ | Node{l; v; r} ->
let c = Ord.compare x v in
if c = 0 then (l, true, r)
else if c < 0 then
let rec mem x = function
Empty -> false
- | Node(l, v, r, _) ->
+ | Node{l; v; r} ->
let c = Ord.compare x v in
c = 0 || mem x (if c < 0 then l else r)
let rec remove x = function
Empty -> Empty
- | (Node(l, v, r, _) as t) ->
+ | (Node{l; v; r} as t) ->
let c = Ord.compare x v in
if c = 0 then merge l r
else
match (s1, s2) with
(Empty, t2) -> t2
| (t1, Empty) -> t1
- | (Node(l1, v1, r1, h1), Node(l2, v2, r2, h2)) ->
+ | (Node{l=l1; v=v1; r=r1; h=h1}, Node{l=l2; v=v2; r=r2; h=h2}) ->
if h1 >= h2 then
if h2 = 1 then add v2 s1 else begin
let (l2, _, r2) = split v1 s2 in
match (s1, s2) with
(Empty, _) -> Empty
| (_, Empty) -> Empty
- | (Node(l1, v1, r1, _), t2) ->
+ | (Node{l=l1; v=v1; r=r1}, t2) ->
match split v1 t2 with
(l2, false, r2) ->
concat (inter l1 l2) (inter r1 r2)
match (s1, s2) with
(Empty, _) -> Empty
| (t1, Empty) -> t1
- | (Node(l1, v1, r1, _), t2) ->
+ | (Node{l=l1; v=v1; r=r1}, t2) ->
match split v1 t2 with
(l2, false, r2) ->
join (diff l1 l2) v1 (diff r1 r2)
let rec cons_enum s e =
match s with
Empty -> e
- | Node(l, v, r, _) -> cons_enum l (More(v, r, e))
+ | Node{l; v; r} -> cons_enum l (More(v, r, e))
let rec compare_aux e1 e2 =
match (e1, e2) with
true
| _, Empty ->
false
- | Node (l1, v1, r1, _), (Node (l2, v2, r2, _) as t2) ->
+ | Node {l=l1; v=v1; r=r1}, (Node {l=l2; v=v2; r=r2} as t2) ->
let c = Ord.compare v1 v2 in
if c = 0 then
subset l1 l2 && subset r1 r2
else if c < 0 then
- subset (Node (l1, v1, Empty, 0)) l2 && subset r1 t2
+ subset (Node {l=l1; v=v1; r=Empty; h=0}) l2 && subset r1 t2
else
- subset (Node (Empty, v1, r1, 0)) r2 && subset l1 t2
+ subset (Node {l=Empty; v=v1; r=r1; h=0}) r2 && subset l1 t2
let rec iter f = function
Empty -> ()
- | Node(l, v, r, _) -> iter f l; f v; iter f r
+ | Node{l; v; r} -> iter f l; f v; iter f r
let rec fold f s accu =
match s with
Empty -> accu
- | Node(l, v, r, _) -> fold f r (f v (fold f l accu))
+ | Node{l; v; r} -> fold f r (f v (fold f l accu))
let rec for_all p = function
Empty -> true
- | Node(l, v, r, _) -> p v && for_all p l && for_all p r
+ | Node{l; v; r} -> p v && for_all p l && for_all p r
let rec exists p = function
Empty -> false
- | Node(l, v, r, _) -> p v || exists p l || exists p r
+ | Node{l; v; r} -> p v || exists p l || exists p r
let rec filter p = function
Empty -> Empty
- | (Node(l, v, r, _)) as t ->
+ | (Node{l; v; r}) as t ->
(* call [p] in the expected left-to-right order *)
let l' = filter p l in
let pv = p v in
let rec partition p = function
Empty -> (Empty, Empty)
- | Node(l, v, r, _) ->
+ | Node{l; v; r} ->
(* call [p] in the expected left-to-right order *)
let (lt, lf) = partition p l in
let pv = p v in
let rec cardinal = function
Empty -> 0
- | Node(l, _, r, _) -> cardinal l + 1 + cardinal r
+ | Node{l; r} -> cardinal l + 1 + cardinal r
let rec elements_aux accu = function
Empty -> accu
- | Node(l, v, r, _) -> elements_aux (v :: elements_aux accu r) l
+ | Node{l; v; r} -> elements_aux (v :: elements_aux accu r) l
let elements s =
elements_aux [] s
let rec find x = function
Empty -> raise Not_found
- | Node(l, v, r, _) ->
+ | Node{l; v; r} ->
let c = Ord.compare x v in
if c = 0 then v
else find x (if c < 0 then l else r)
let rec find_first_aux v0 f = function
Empty ->
v0
- | Node(l, v, r, _) ->
+ | Node{l; v; r} ->
if f v then
find_first_aux v f l
else
let rec find_first f = function
Empty ->
raise Not_found
- | Node(l, v, r, _) ->
+ | Node{l; v; r} ->
if f v then
find_first_aux v f l
else
let rec find_first_opt_aux v0 f = function
Empty ->
Some v0
- | Node(l, v, r, _) ->
+ | Node{l; v; r} ->
if f v then
find_first_opt_aux v f l
else
let rec find_first_opt f = function
Empty ->
None
- | Node(l, v, r, _) ->
+ | Node{l; v; r} ->
if f v then
find_first_opt_aux v f l
else
let rec find_last_aux v0 f = function
Empty ->
v0
- | Node(l, v, r, _) ->
+ | Node{l; v; r} ->
if f v then
find_last_aux v f r
else
let rec find_last f = function
Empty ->
raise Not_found
- | Node(l, v, r, _) ->
+ | Node{l; v; r} ->
if f v then
find_last_aux v f r
else
let rec find_last_opt_aux v0 f = function
Empty ->
Some v0
- | Node(l, v, r, _) ->
+ | Node{l; v; r} ->
if f v then
find_last_opt_aux v f r
else
let rec find_last_opt f = function
Empty ->
None
- | Node(l, v, r, _) ->
+ | Node{l; v; r} ->
if f v then
find_last_opt_aux v f r
else
let rec find_opt x = function
Empty -> None
- | Node(l, v, r, _) ->
+ | Node{l; v; r} ->
let c = Ord.compare x v in
if c = 0 then Some v
else find_opt x (if c < 0 then l else r)
let rec map f = function
| Empty -> Empty
- | Node (l, v, r, _) as t ->
+ | Node{l; v; r} as t ->
(* enforce left-to-right evaluation order *)
let l' = map f l in
let v' = f v in
let rec sub n l =
match n, l with
| 0, l -> Empty, l
- | 1, x0 :: l -> Node (Empty, x0, Empty, 1), l
- | 2, x0 :: x1 :: l -> Node (Node(Empty, x0, Empty, 1), x1, Empty, 2), l
+ | 1, x0 :: l -> Node {l=Empty; v=x0; r=Empty; h=1}, l
+ | 2, x0 :: x1 :: l ->
+ Node{l=Node{l=Empty; v=x0; r=Empty; h=1}; v=x1; r=Empty; h=2}, l
| 3, x0 :: x1 :: x2 :: l ->
- Node (Node(Empty, x0, Empty, 1), x1, Node(Empty, x2, Empty, 1), 2),l
+ Node{l=Node{l=Empty; v=x0; r=Empty; h=1}; v=x1;
+ r=Node{l=Empty; v=x2; r=Empty; h=1}; h=2}, l
| n, l ->
let nl = n / 2 in
let left, l = sub nl l in
val save_event : ?time:float -> t -> event_name:string -> unit
(** [save_and_close series] writes information into [series] required for
- interpeting the snapshots that [series] contains and then closes the
+ interpreting the snapshots that [series] contains and then closes the
[series] file. This function must be called to produce a valid series
file.
The optional [time] parameter is as for {!Snapshot.take}.
accepted, but one of the following components is rejected. *)
-(** {6 Stream builders} *)
+(** {1 Stream builders} *)
val from : (int -> 'a option) -> 'a t
(** [Stream.from f] returns a stream built from the function [f].
(** Return the stream of the characters read from the input channel. *)
-(** {6 Stream iterator} *)
+(** {1 Stream iterator} *)
val iter : ('a -> unit) -> 'a t -> unit
(** [Stream.iter f s] scans the whole stream s, applying function [f]
in turn to each stream element encountered. *)
-(** {6 Predefined parsers} *)
+(** {1 Predefined parsers} *)
val next : 'a t -> 'a
(** Return the first element of the stream and remove it from the
(** Return [()] if the stream is empty, else raise {!Stream.Failure}. *)
-(** {6 Useful functions} *)
+(** {1 Useful functions} *)
val peek : 'a t -> 'a option
(** Return [Some] of "the first element" of the stream, or [None] if
Raise [Invalid_argument] if [n < 0] or [n > ]{!Sys.max_string_length}.
@since 4.02.0 *)
-val copy : string -> string
+val copy : string -> string [@@ocaml.deprecated]
(** Return a copy of the given string. *)
val sub : string -> pos:int -> len:int -> string
(** Remove the given file name from the file system. *)
external rename : string -> string -> unit = "caml_sys_rename"
-(** Rename a file. The first argument is the old name and the
- second is the new name. If there is already another file
- under the new name, [rename] may replace it, or raise an
- exception, depending on your operating system. *)
+(** Rename a file. [rename oldpath newpath] renames the file
+ called [oldpath], giving it [newpath] as its new name,
+ moving it between directories if needed. If [newpath] already
+ exists, its contents will be replaced with those of [oldpath].
+ Depending on the operating system, the metadata (permissions,
+ owner, etc) of [newpath] can either be preserved or be replaced by
+ those of [oldpath].
+ @since 4.06 concerning the "replace existing file" behavior *)
external getenv : string -> string = "caml_sys_getenv"
(** Return the value associated to a variable in the process
@since 4.03.0 *)
-(** {6 Signal handling} *)
+(** {1 Signal handling} *)
type signal_behavior =
(** Same as {!Sys.signal} but return value is ignored. *)
-(** {7 Signal numbers for the standard POSIX signals.} *)
+(** {2 Signal numbers for the standard POSIX signals.} *)
val sigabrt : int
(** Abnormal termination *)
@since 4.03.0 *)
-(** {6 Optimization} *)
+(** {1 Optimization} *)
external opaque_identity : 'a -> 'a = "%opaque"
(** For the purposes of optimization, [opaque_identity] behaves like an
let lo_bound = 0xD7FF
let hi_bound = 0xE000
+let bom = 0xFEFF
+let rep = 0xFFFD
+
let succ u =
if u = lo_bound then hi_bound else
if u = max then invalid_arg err_no_succ else
val max : t
(** [max] is U+10FFFF. *)
+val bom : t
+(** [bom] is U+FEFF, the
+ {{:http://unicode.org/glossary/#byte_order_mark}byte order mark} (BOM)
+ character.
+
+ @since 4.06.0 *)
+
+val rep : t
+(** [rep] is U+FFFD, the
+ {{:http://unicode.org/glossary/#replacement_character}replacement}
+ character.
+
+ @since 4.06.0 *)
+
val succ : t -> t
(** [succ u] is the scalar value after [u] in the set of Unicode scalar
values.
(** Arrays of weak pointers and hash sets of weak pointers. *)
-(** {6 Low-level functions} *)
+(** {1 Low-level functions} *)
type 'a t
(** The type of arrays of weak pointers (weak arrays). A weak
do not designate a valid subarray of [ar2].*)
-(** {6 Weak hash sets} *)
+(** {1 Weak hash sets} *)
(** A weak hash set is a hashed set of values. Each value may
magically disappear from the set when it is not used by the
`make all-foo`, `make parallel-foo`:: runs only the tests in the directories whose name starts with `foo`: `parallel-typing`, `all-lib`, etc.
-`make one DIR=tests/foo`:: runs only the tests in the directory `tests/foo`. This is often equivalent to `cd tests/foo && make`, but sometimes the latter breaks the test makefile if it contains fragile relative filesystem paths. Such errors should be fixed if you find them, but `make one DIR=...` is the more reliable option as it runs exactly as `make all` which is heavily tested.
\ No newline at end of file
+`make one DIR=tests/foo`:: runs only the tests in the directory `tests/foo`. This is often equivalent to `cd tests/foo && make`, but sometimes the latter breaks the test makefile if it contains fragile relative filesystem paths. Such errors should be fixed if you find them, but `make one DIR=...` is the more reliable option as it runs exactly as `make all` which is heavily tested.
+
+`make promote DIR=tests/foo`:: most test run a program and compare the result of the program, store in a file `foo.result`, with a reference output stored in `foo.reference` -- the test fails if the two output differ. Sometimes a change in result is innocuous, it comes from an intended change in output instead of a regression. `make promote` copies the new result file into the reference file, making the test pass again. Whenever you use this rule please check carefully, using `git diff`, that the change really corresponds to an intended output difference, and not to a regression. You then need to commit the change to reference file, and your commit message should explain why the output changed.
FIND=find
include ../config/Makefile
+ifeq "$(UNIX_OR_WIN32)" "unix"
+ ifeq "$(SYSTEM)" "cygwin"
+ find := /usr/bin/find
+ else # Non-cygwin Unix
+ find := find
+ endif
+else # Windows
+ find := /usr/bin/find
+ FLEXDLL_SUBMODULE_PRESENT := $(wildcard ../flexdll/Makefile)
+ ifeq "$(FLEXDLL_SUBMODULE_PRESENT)" ""
+ FLEXLINK_PREFIX=
+ else
+ ROOT:=$(shell cd .. && pwd| cygpath -m -f -)
+ EMPTY=
+ FLEXLINK_PREFIX:=OCAML_FLEXLINK="$(ROOT)/boot/ocamlrun \
+ $(ROOT)/flexdll/flexlink.exe" $(EMPTY)
+ endif
+endif
+
+failstamp := failure.stamp
+
+ocamltest_directory := ../ocamltest
+
+ocamltest_program := $(or \
+ $(wildcard $(ocamltest_directory)/ocamltest.opt$(EXE)),\
+ $(wildcard $(ocamltest_directory)/ocamltest$(EXE)))
+
+ocamltest := $(FLEXLINK_PREFIX) $(ocamltest_program)
+
.PHONY: default
default:
@echo "Available targets:"
@echo " all launch all tests"
+ @echo " legacy launch legacy tests"
+ @echo " new launch new (ocamltest based) tests"
@echo " all-foo launch all tests beginning with foo"
@echo " parallel launch all tests using GNU parallel"
@echo " parallel-foo launch all tests beginning with foo using \
@echo "(default value = $(MAX_TESTSUITE_DIR_RETRIES))"
.PHONY: all
-all: lib tools
+all:
+ @rm -f _log
+ @$(MAKE) $(NO_PRINT) legacy-without-report
+ @$(MAKE) $(NO_PRINT) new-without-report
+ @$(MAKE) $(NO_PRINT) report
+
+.PHONY: legacy
+legacy:
+ @rm -f _log
+ @$(MAKE) $(NO_PRINT) legacy-without-report
+ @$(MAKE) $(NO_PRINT) report
+
+.PHONY: legacy-without-report
+legacy-without-report: lib tools
@for dir in tests/*; do \
$(MAKE) $(NO_PRINT) exec-one DIR=$$dir; \
- done 2>&1 | tee _log
+ done 2>&1 | tee -a _log
@$(MAKE) $(NO_PRINT) retries
- @$(MAKE) report
+
+.PHONY: new
+new:
+ @rm -f _log
+ @$(MAKE) $(NO_PRINT) new-without-report
+ @$(MAKE) $(NO_PRINT) report
+
+.PHONY: new-without-report
+new-without-report: lib tools
+ @rm -f $(failstamp)
+ @(for file in `$(find) tests -name ocamltests`; do \
+ dir=`dirname $$file`; \
+ echo Running tests from \'$$dir\' ... ; \
+ (IFS=$$(printf "\r\n"); while read testfile; do \
+ TERM=dumb OCAMLRUNPARAM= \
+ $(ocamltest) $$dir/$$testfile || \
+ touch $(failstamp); \
+ done < $$file) || touch $(failstamp); \
+ done || touch $(failstamp)) 2>&1 | tee -a _log
+ @if [ -f $(failstamp) ]; then rm $(failstamp); exit 1; fi
.PHONY: all-%
all-%: lib tools
.PHONY: exec-one
exec-one:
- @if [ ! -f $(DIR)/Makefile ]; then \
+ @if [ ! -f $(DIR)/Makefile -a ! -f $(DIR)/ocamltests ]; then \
for dir in $(DIR)/*; do \
if [ -d $$dir ]; then \
$(MAKE) exec-one DIR=$$dir; \
fi; \
done; \
- else \
+ elif [ -f $(DIR)/Makefile ]; then \
echo "Running tests from '$$DIR' ..."; \
cd $(DIR) && \
$(MAKE) TERM=dumb BASEDIR=$(BASEDIR) || echo '=> unexpected error'; \
@for file in `$(FIND) interactive tests -name Makefile`; do \
(cd `dirname $$file` && $(MAKE) BASEDIR=$(BASEDIR) clean); \
done
+ $(FIND) . -name '*_ocamltest*' | xargs rm -rf
+ rm -f $(failstamp)
.PHONY: report
report:
@if [ ! -f _log ]; then echo "No '_log' file."; exit 1; fi
@awk -f makefiles/summarize.awk <_log
+.PHONY: retry-list
retry-list:
@while read LINE; do \
if [ -n "$$LINE" ] ; then \
done <_retries;
@$(MAKE) $(NO_PRINT) retries
+.PHONY: retries
retries:
@awk -v retries=1 -v max_retries=$(MAX_TESTSUITE_DIR_RETRIES) \
-f makefiles/summarize.awk <_log >_retries
include ../makefiles/Makefile.common
.PHONY: compile-targets
-compile-targets: testing.cmi testing.cmo
+compile-targets: testing.cmi testing.cma
@if $(BYTECODE_ONLY); then : ; else \
- $(MAKE) testing.cmx; \
+ $(MAKE) testing.cmxa; \
fi
+
+testing.cma: testing.cmo
+ $(OCAMLC) -a -linkall $(ADD_COMPFLAGS) -o $@ $<
+
+testing.cmxa: testing.cmx
+ $(OCAMLOPT) -a -linkall $(ADD_COMPFLAGS) -o $@ $<
TOPDIR=$(BASEDIR)/..
include $(TOPDIR)/Makefile.tools
+.PHONY: defaultpromote
defaultpromote:
@for file in *.reference; do \
cp `basename $$file reference`result $$file; \
done
+.PHONY: defaultclean
defaultclean:
@rm -f *.cmo *.cmi *.cmx *.cma *.cmxa *.cmxs *.$(O) *.$(SO) *.$(A) *.exe
@rm -f *.exe.manifest
@$(ASPP) $(ASPPFLAGS) -DSYS_$(SYSTEM) -o $*.o $*.s
.c.o:
- @$(CC) -c -I$(CTOPDIR)/byterun $*.c -o $*.$(O)
+ @$(CC) $(CFLAGS) -c -I$(CTOPDIR)/byterun $*.c -o $*.$(O)
.f.o:
@$(FORTRAN_COMPILER) -c -I$(CTOPDIR)/byterun $*.f -o $*.$(O)
# changes, we strip -dlambda-produced identifiers of their unique
# identifier: "x/1234" becomes simply "x".
+.PHONY: default
default:
@for file in *.ml; do \
$(OCAMLC) -dlambda -c $$file 2>&1 | \
&& echo " => passed" || echo " => failed"; \
done
+.PHONY: promote
promote: defaultpromote
+.PHONY: clean
clean: defaultclean
@rm -f *.result
#* *
#**************************************************************************
+.PHONY: default
default:
@for file in *.ml; do \
$(OCAMLC) -dparsetree -c $$file 2>$$file.result >/dev/null || true; \
&& echo " => passed" || echo " => failed"; \
done
+.PHONY: promote
promote: defaultpromote
+.PHONY: clean
clean: defaultclean
@rm -f *.result
#* *
#**************************************************************************
+.PHONY: default
default:
@for file in *.ml; do \
printf " ... testing '$$file':"; \
echo " => passed" || echo " => failed"; \
done
+.PHONY: promote
promote:
@for file in *.corrected; do \
cp $$file `basename $$file .corrected`; \
done
+.PHONY: clean
clean: defaultclean
@rm -f *.corrected
#* *
#**************************************************************************
-CC=$(NATIVECC) $(NATIVECCCOMPOPTS)
FC=$(FORTAN_COMPILER)
CMO_FILES=$(MODULES:=.cmo)
CMX_FILES=$(MODULES:=.cmx)
CMA_FILES=$(LIBRARIES:=.cma)
CMXA_FILES=$(LIBRARIES:=.cmxa)
-O_FILES=$(F_FILES:=.o) $(C_FILES:=.o)
+O_FILES=$(F_FILES:=.$(O)) $(C_FILES:=.$(O))
CUSTOM_FLAG=`if [ -n "$(C_FILES)" ]; then echo '-custom'; fi`
ADD_CFLAGS+=$(CUSTOM_FLAG)
continue; \
fi; \
fi; \
- $(MAKE) run-file DESC=ocamlc COMP='$(OCAMLC)' \
- RUNTIME='$(MYRUNTIME)' \
- COMPFLAGS='-w a $(ADD_COMPFLAGS) $(ADD_CFLAGS) $(O_FILES) \
- $(CMA_FILES) -I $(OTOPDIR)/testsuite/lib \
- $(CMO_FILES)' \
- FILE=$$file PROGRAM_ARGS=$(PROGRAM_ARGS) \
+ if $(NATIVECODE_ONLY); then : ; else \
+ $(MAKE) run-file DESC=ocamlc COMP='$(OCAMLC)' \
+ RUNTIME='$(MYRUNTIME)' \
+ COMPFLAGS='$(ADD_COMPFLAGS) $(ADD_CFLAGS) $(O_FILES) \
+ $(CMA_FILES) -I $(OTOPDIR)/testsuite/lib \
+ $(CMO_FILES)' \
+ FILE=$$file PROGRAM_ARGS='$(PROGRAM_ARGS)'; \
+ fi \
&& \
if $(BYTECODE_ONLY); then : ; else \
$(MAKE) run-file DESC=ocamlopt COMP='$(OCAMLOPT)' \
RUNTIME= \
- COMPFLAGS='-w a $(ADD_COMPFLAGS) $(ADD_OPTFLAGS) \
+ COMPFLAGS='$(ADD_COMPFLAGS) $(ADD_OPTFLAGS) \
$(O_FILES) $(CMXA_FILES) \
-I $(OTOPDIR)/testsuite/lib $(CMX_FILES)' \
- FILE=$$file PROGRAM_ARGS=$(PROGRAM_ARGS); \
+ FILE=$$file PROGRAM_ARGS='$(PROGRAM_ARGS)'; \
fi \
&& \
if [ -n "$(UNSAFE)" ]; then \
$(MAKE) run-file DESC=ocamlc-unsafe COMP='$(OCAMLC)' \
RUNTIME='$(MYRUNTIME)' \
- COMPFLAGS='-w a -unsafe $(ADD_COMPFLAGS) $(ADD_CFLAGS) \
+ COMPFLAGS='-unsafe $(ADD_COMPFLAGS) $(ADD_CFLAGS) \
$(O_FILES) $(CMA_FILES) \
-I $(OTOPDIR)/testsuite/lib $(CMO_FILES)' \
FILE=$$file \
if $(BYTECODE_ONLY); then : ; else \
$(MAKE) run-file DESC=ocamlopt-unsafe COMP='$(OCAMLOPT)' \
RUNTIME= \
- COMPFLAGS='-w a -unsafe $(ADD_COMPFLAGS) $(ADD_OPTFLAGS)\
+ COMPFLAGS='-unsafe $(ADD_COMPFLAGS) $(ADD_OPTFLAGS)\
$(O_FILES) $(CMXA_FILES) \
-I $(OTOPDIR)/testsuite/lib $(CMX_FILES)' \
FILE=$$file; \
rm -f "$$T"; \
} || true
@rm -f program program$(EXE)
- @$(COMP) $(COMPFLAGS) $(FILE) -o program$(EXE)
+ @if [ -f "$(FILE).silent-compilation" ]; then \
+ temp="$$(mktemp "$${TMPDIR:-/tmp}/ocaml-test-XXXXXXXX")"; \
+ $(COMP) $(COMPFLAGS) $(FILE) -o program$(EXE) >$$temp 2>&1 ; \
+ if [ -s "$$temp" ]; then \
+ rm -f $$temp; \
+ printf " Error: compilation wrote to stdout/stderr!\n"; \
+ exit 1; \
+ fi; \
+ rm -f $$temp; \
+ else \
+ $(COMP) $(COMPFLAGS) $(FILE) -o program$(EXE); \
+ fi
@F="`basename $(FILE) .ml`"; \
if [ -f $$F.runner ]; then \
RUNTIME="$(RUNTIME)" sh $$F.runner; \
#* *
#**************************************************************************
+.PHONY: default
default:
@for file in *.ml; do \
TERM=dumb $(OCAML) $(TOPFLAGS) <$$file 2>&1 \
&& echo " => passed" || echo " => failed"; \
done
+.PHONY: promote
promote: defaultpromote
+.PHONY: clean
clean: defaultclean
@rm -f *.result
--- /dev/null
+BASEDIR=../..
+
+default:
+ @printf " ... testing 'afl_instrumentation':"
+ @if ! which afl-showmap > /dev/null; then \
+ echo " => skipped (afl-showmap unavailable)"; \
+ else \
+ if OCAMLOPT='$(OCAMLOPT)' ./test.sh > /dev/null; then \
+ echo " => passed"; \
+ else \
+ echo " => failed"; \
+ fi \
+ fi
+
+include $(BASEDIR)/makefiles/Makefile.common
+
+clean: defaultclean
--- /dev/null
+external reset_instrumentation : bool -> unit = "caml_reset_afl_instrumentation"
+external sys_exit : int -> 'a = "caml_sys_exit"
+
+let name n =
+ fst (Test.tests.(int_of_string n - 1))
+let run n =
+ snd (Test.tests.(int_of_string n - 1)) ()
+
+let orig_random = Random.get_state ()
+
+let () =
+ (* Random.set_state orig_random; *)
+ reset_instrumentation true;
+ begin
+ match Sys.argv with
+ | [| _; "len" |] -> print_int (Array.length Test.tests); print_newline (); flush stdout
+ | [| _; "name"; n |] -> print_string (name n); flush stdout
+ | [| _; "1"; n |] -> run n
+ | [| _; "2"; n |] -> run n; (* Random.set_state orig_random; *)reset_instrumentation false; run n
+ | _ -> failwith "error"
+ end;
+ sys_exit 0
--- /dev/null
+let opaque = Sys.opaque_identity
+
+let lists n =
+ let l = opaque [n; n; n] in
+ match List.rev l with
+ | [a; b; c] when a = n && b = n && c = n -> ()
+ | _ -> assert false
+
+let fresh_exception x =
+ opaque @@
+ let module M = struct
+ exception E of int
+ let throw () = raise (E x)
+ end in
+ try
+ M.throw ()
+ with
+ M.E n -> assert (n = x)
+
+let obj_with_closure x =
+ opaque (object method foo = x end)
+
+let r = ref 42
+let state () =
+ incr r;
+ if !r > 43 then print_string "woo" else ()
+
+let classes (x : int) =
+ opaque @@
+ let module M = struct
+ class a = object
+ method foo = x
+ end
+ class c = object
+ inherit a
+ end
+ end in
+ let o = new M.c in
+ assert (o#foo = x)
+
+
+class c_global = object
+ method foo = 42
+end
+let obj_ordering () = opaque @@
+ (* Object IDs change, but should be in the same relative order *)
+ let a = new c_global in
+ let b = new c_global in
+ if a < b then print_string "a" else print_string "b"
+
+let random () = opaque @@
+ (* as long as there's no self_init, this should be deterministic *)
+ if Random.int 100 < 50 then print_string "a" else print_string "b";
+ if Random.int 100 < 50 then print_string "a" else print_string "b";
+ if Random.int 100 < 50 then print_string "a" else print_string "b";
+ if Random.int 100 < 50 then print_string "a" else print_string "b";
+ if Random.int 100 < 50 then print_string "a" else print_string "b";
+ if Random.int 100 < 50 then print_string "a" else print_string "b";
+ if Random.int 100 < 50 then print_string "a" else print_string "b";
+ if Random.int 100 < 50 then print_string "a" else print_string "b";
+ if Random.int 100 < 50 then print_string "a" else print_string "b"
+
+let tests =
+ [| ("lists", fun () -> lists 42);
+ ("manylists", fun () -> for i = 1 to 10 do lists 42 done);
+ ("exceptions", fun () -> fresh_exception 100);
+ ("objects", fun () -> ignore (obj_with_closure 42));
+ (* ("state", state); *) (* this one should fail *)
+ ("classes", fun () -> classes 42);
+ ("obj_ordering", obj_ordering);
+ (* ("random", random); *)
+ |]
+
--- /dev/null
+#!/bin/bash
+
+set -e
+
+$OCAMLOPT -c -afl-instrument test.ml
+$OCAMLOPT -afl-inst-ratio 0 test.cmx harness.ml -o test
+
+NTESTS=`./test len`
+failures=''
+echo "running $NTESTS tests..."
+for t in `seq 1 $NTESTS`; do
+ printf "%14s: " `./test name $t`
+ # when run twice, the instrumentation output should double
+ afl-showmap -q -o output-1 -- ./test 1 $t
+ afl-showmap -q -o output-2 -- ./test 2 $t
+ # see afl-showmap.c for what the numbers mean
+ cat output-1 | sed '
+ s/:6/:7/; s/:5/:6/;
+ s/:4/:5/; s/:3/:4/;
+ s/:2/:4/; s/:1/:2/;
+ ' > output-2-predicted
+ if cmp -s output-2-predicted output-2; then
+ echo "passed."
+ else
+ echo "failed:"
+ paste output-2 output-1
+ failures=1
+ fi
+done
+
+if [ -z "$failures" ]; then echo "all tests passed"; else exit 1; fi
+
+rm -f {test,harness}.{cmi,cmx,o} test output-{1,2,2-predicted}
+++ /dev/null
-#**************************************************************************
-#* *
-#* OCaml *
-#* *
-#* Xavier Clerc, SED, 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 GNU Lesser General Public License version 2.1, with the *
-#* special exception on linking described in the file LICENSE. *
-#* *
-#**************************************************************************
-
-BASEDIR=../..
-include $(BASEDIR)/makefiles/Makefile.several
-include $(BASEDIR)/makefiles/Makefile.common
+(* TEST *)
+
let () =
let a = [|0;1;2;3;4;5;6;7;8;9|] in
assert (Array.exists (fun a -> a < 10) a);
assert (not (Array.memq (ref 1) (Array.make 100 (ref 1))));
let f = Array.create_float 10 in
Array.fill f 0 10 1.0;
- assert (not (Array.memq 1.0 f));
+ (* FIXME
+ if Config.flat_float_array then assert (not (Array.memq 1.0 f));
+ *)
;;
let () = print_endline "OK"
BASEDIR=../..
+include $(BASEDIR)/../config/Makefile
+
INCLUDES=\
-I $(OTOPDIR)/parsing \
-I $(OTOPDIR)/utils \
register_typing_switch
ARGS_optargs=-g
ARGS_is_static=-I $(OTOPDIR)/byterun is_in_static_data.c
-MLCASES_FLAMBDA=is_static_flambda unrolling_flambda unrolling_flambda2 \
- static_float_array_flambda static_float_array_flambda_opaque
+MLCASES_FLAMBDA=is_static_flambda unrolling_flambda unrolling_flambda2
+MLCASES_FLAMBDA_FLOAT=static_float_array_flambda \
+ static_float_array_flambda_opaque
ARGS_is_static_flambda=\
-I $(OTOPDIR)/byterun is_in_static_data.c is_static_flambda_dep.ml
ARGS_static_float_array_flambda=\
ARGS_pgcd=-DINT_INT -DFUN=pgcd_30030 main.c
skips:
- @for c in $(CASES) $(MLCASES) $(MLCASES_FLAMBDA); do \
+ @for c in $(CASES) $(MLCASES) $(MLCASES_FLAMBDA) \
+ $(MLCASES_FLAMBDA_FLOAT); do \
echo " ... testing '$$c': => skipped"; \
done
@$(OCAMLOPT) $(ARGS_$(NAME)) -o $(NAME).exe $(NAME).ml && \
./$(NAME).exe && echo " => passed" || echo " => failed"
-one_ml_flambda:
- @if $(FLAMBDA); then \
+one_ml_cond:
+ @if $(COND); then \
$(OCAMLOPT) $(ARGS_$(NAME)) -o $(NAME).exe $(NAME).ml && \
./$(NAME).exe && echo " => passed" || echo " => failed"; \
else \
fi
one:
- @$(call CC,$(NAME).out $(ARGS_$(NAME)) $(NAME).$(O) $(ARCH).$(O)) \
+ @$(call CCOMP,$(NAME).out $(ARGS_$(NAME)) $(NAME).$(O) $(ARCH).$(O)) \
&& echo " => passed" || echo " => failed"
clean: defaultclean
endif
ifeq ($(CCOMPTYPE),msvc)
-CC=set -o pipefail ; $(NATIVECC) $(CFLAGS) /Fe$(1) | tail -n +2
-CFLAGS=$(NATIVECCCOMPOPTS)
+CCOMP=set -o pipefail ; $(CC) $(CFLAGS) /Fe$(1) | tail -n +2
else
-CC=$(NATIVECC) $(CFLAGS) -o $(1)
-CFLAGS=$(NATIVECCCOMPOPTS) -g
+CCOMP=$(CC) $(CFLAGS) -o $(1)
endif
tests: $(CASES:=.$(O))
@for c in $(CASES); do \
done
@for c in $(MLCASES_FLAMBDA); do \
printf " ... testing '$$c':"; \
- $(MAKE) one_ml_flambda NAME=$$c; \
+ $(MAKE) one_ml_cond NAME=$$c COND=$(FLAMBDA); \
+ done
+ @for c in $(MLCASES_FLAMBDA_FLOAT); do \
+ printf " ... testing '$$c':"; \
+ $(MAKE) one_ml_cond NAME=$$c \
+ COND='$(FLAMBDA) && $(FLAT_FLOAT_ARRAY)'; \
done
promote:
let () =
f true;
f false
+
+(* Verify that physical equality/inequality is correctly propagated *)
+
+(* In these tests, tuple can be statically allocated only if it is a
+ known constant since the function is never inlined (hence this
+ code is never at toplevel) *)
+
+let () =
+ let f () =
+ let v = (1, 2) in
+ (* eq is supposed to be considered always true since v is a
+ constant, hence aliased to a symbol.
+ It is not yet optimized away if it is not constant *)
+ let eq = v == v in
+ let n = if eq then 1 else 2 in
+ let tuple = (n,n) in
+ assert(is_in_static_data tuple)
+ in
+ (f [@inlined never]) ()
+
+let () =
+ let f () =
+ let v = (1, 2) in
+ (* same with inequality *)
+ let eq = v != v in
+ let n = if eq then 1 else 2 in
+ let tuple = (n,n) in
+ assert(is_in_static_data tuple)
+ in
+ (f [@inlined never]) ()
+
+let () =
+ let f x =
+ let v1 = Some x in
+ let v2 = None in
+ let eq = v1 == v2 in
+ (* The values are structurally different, so must be physically
+ different *)
+ let n = if eq then 1 else 2 in
+ let tuple = (n,n) in
+ assert(is_in_static_data tuple)
+ in
+ (f [@inlined never]) ()
+
+let () =
+ let f x =
+ let v1 = Some x in
+ let v2 = None in
+ let eq = v1 != v2 in
+ (* same with inequality *)
+ let n = if eq then 1 else 2 in
+ let tuple = (n,n) in
+ assert(is_in_static_data tuple)
+ in
+ (f [@inlined never]) ()
+
+let () =
+ let f x =
+ let v1 = (1, 2) in
+ let v2 = (3, 2) in
+ let eq = v1 == v2 in
+ (* difference is deeper *)
+ let n = if eq then 1 else 2 in
+ let tuple = (n,n) in
+ assert(is_in_static_data tuple)
+ in
+ (f [@inlined never]) ()
+
+module Int = struct
+ type t = int
+ let compare (a:int) b = compare a b
+end
+module IntMap = (Map.Make [@inlined])(Int)
+
+let () =
+ let f () =
+ let a = IntMap.empty in
+ let b = (IntMap.add [@inlined]) 1 (Some 1) a in
+ assert(is_in_static_data b);
+ let c = (IntMap.add [@inlined]) 1 (Some 2) b in
+ assert(is_in_static_data c);
+ let d = (IntMap.add [@inlined]) 1 (Some 2) c in
+ assert(is_in_static_data d);
+ in
+ (f [@inlined never]) ()
let out_name = Filename.chop_extension filename ^ ".s" in
Emitaux.output_channel := open_out out_name
end; (* otherwise, stdout *)
- Clflags.dlcode := false;
- Compilenv.reset ~source_provenance:(Timings.File filename) "test";
+ Compilenv.reset "test";
Emit.begin_assembly();
let ic = open_in filename in
let lb = Lexing.from_channel ic in
"-dreload", Arg.Set dump_reload, "";
"-dscheduling", Arg.Set dump_scheduling, "";
"-dlinear", Arg.Set dump_linear, "";
- "-dtimings", Arg.Set print_timings, "";
+ "-dtimings", Arg.Unit (fun () -> profile_columns := [ `Time ]), "";
] compile_file usage
-let _ = (*Printexc.catch*) Timings.(time All) main ();
- if !Clflags.print_timings then Timings.print Format.std_formatter;
+let () =
+ main ();
+ Profile.print Format.std_formatter !Clflags.profile_columns;
exit 0
Fatal error: exception Pervasives.Exit
Raised at file "pr6920_why_swallow.ml", line 1, characters 41-45
-Called from file "pr6920_why_swallow.ml", line 4, characters 4-14
+Called from file "pr6920_why_swallow.ml", line 4, characters 4-13
Called from file "pr6920_why_swallow.ml", line 11, characters 2-6
Fatal error: exception Pervasives.Exit
Raised at file "pr6920_why_swallow.ml", line 1, characters 35-45
-Called from file "pr6920_why_swallow.ml", line 4, characters 4-14
+Called from file "pr6920_why_swallow.ml", line 4, characters 4-13
Called from file "pr6920_why_swallow.ml", line 11, characters 2-6
print_newline ();;
-let b = (Float_array.small_float_array [@inlined]) 12
+let b = Float_array.small_float_array 12
let c = (Float_array.longer_float_array [@inlined]) 34
let print_array a =
+++ /dev/null
-#**************************************************************************
-#* *
-#* OCaml *
-#* *
-#* Xavier Clerc, SED, 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 GNU Lesser General Public License version 2.1, with the *
-#* special exception on linking described in the file LICENSE. *
-#* *
-#**************************************************************************
-
-BASEDIR=../..
-#MODULES=
-MAIN_MODULE=io
-EXEC_ARGS=io.ml
-
-include $(BASEDIR)/makefiles/Makefile.one
-include $(BASEDIR)/makefiles/Makefile.common
+(* TEST
+ arguments = "io.ml"
+ files = "test-file-short-lines"
+*)
+
(* Test a file copy function *)
let test msg funct f1 f2 =
+++ /dev/null
-#**************************************************************************
-#* *
-#* OCaml *
-#* *
-#* Xavier Clerc, SED, 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 GNU Lesser General Public License version 2.1, with the *
-#* special exception on linking described in the file LICENSE. *
-#* *
-#**************************************************************************
-
-BASEDIR=../..
-#MODULES=
-MAIN_MODULE=wc
-EXEC_ARGS=wc.ml
-
-include $(BASEDIR)/makefiles/Makefile.one
-include $(BASEDIR)/makefiles/Makefile.common
+(* TEST
+ arguments = "wc.ml"
+*)
(* Counts characters, lines and words in one or several files. *)
-1199 characters, 178 words, 55 lines
+1232 characters, 184 words, 58 lines
+++ /dev/null
-#**************************************************************************
-#* *
-#* OCaml *
-#* *
-#* Xavier Clerc, SED, 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 GNU Lesser General Public License version 2.1, with the *
-#* special exception on linking described in the file LICENSE. *
-#* *
-#**************************************************************************
-
-BASEDIR=../..
-
-MODULES=offset pr6726 pr7427
-MAIN_MODULE=main
-
-include $(BASEDIR)/makefiles/Makefile.one
-include $(BASEDIR)/makefiles/Makefile.common
+(* TEST
+ modules = "offset.ml pr6726.ml pr7427.ml"
+*)
+
(* PR#6435 *)
module F (M : sig
| 4|5|7 -> 100
| 7 | 8 -> 6
| 9 -> 7
-| _ -> 8;;
+| _ -> 8 [@@ocaml.warning "-12"];;
test "quatre" g 4 4 ;
test "quatre" g 7 100 ; ()
;;
let f = function (([]|[_]) as x)|(_::([] as x))|(_::_::x) -> x
+ [@@ocaml.warning "-12"]
;;
test "zob" f [] [] ;
| A,_,_ -> 1
| _,A,_ -> 2
| B,B,_ -> 3
-| A,_,(100|103) -> 5
+| A,_,(100|103) -> 5 [@@ocaml.warning "-11"]
;;
test "yaya" yaya (A,A,0) 1 ;
| (J,J,((C|D) as x |E x|F (_,x))) | (J,_,((C|J) as x)) -> autre (x,x,x)
| (J, J, (I|H _|K _)) -> 9
| I,_,_ -> 6
-| E _,_,_ -> 7
+| E _,_,_ -> 7 [@@ocaml.warning "-12"]
;;
(*
File "morematch.ml", line 437, characters 43-44:
| YB,YB,_ -> 3
| ((YB|YC), (YB|YC), (X|Y|Z|V _|T _)) -> 6
| _,_,(X|U _) -> 8
-| _,_,Y -> 5
+| _,_,Y -> 5 [@@ocaml.warning "-11-12"]
;;
(*
File "morematch.ml", line 459, characters 7-8:
let f = function
| A (`A|`C) -> 0
| B (`B,`D) -> 1
- | C -> 2
+ | C -> 2 [@@ocaml.warning "-8"]
let g x = try f x with Match_failure _ -> 3
| _, _, _, _, _, A, _, _, _, _, B, _, _, _, _, _ -> "11"
| B, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ -> "12"
| _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ -> "13"
-
+[@@ocaml.warning "-11"]
(*
File "morematch.ml", line 1094, characters 5-51:
Warning: this match case is unused.
--- /dev/null
+(* GPR#1271 *)
+
+module F (X : sig val x : int end) = struct
+ let rec f1 y = f270 (X.x + y)
+ and f2 y = (f1 [@inlined never]) y
+ and f3 y = (f2 [@inlined never]) y
+ and f4 y = (f3 [@inlined never]) y
+ and f5 y = (f4 [@inlined never]) y
+ and f6 y = (f5 [@inlined never]) y
+ and f7 y = (f6 [@inlined never]) y
+ and f8 y = (f7 [@inlined never]) y
+ and f9 y = (f8 [@inlined never]) y
+ and f10 y = (f9 [@inlined never]) y
+ and f11 y = (f10 [@inlined never]) y
+ and f12 y = (f11 [@inlined never]) y
+ and f13 y = (f12 [@inlined never]) y
+ and f14 y = (f13 [@inlined never]) y
+ and f15 y = (f14 [@inlined never]) y
+ and f16 y = (f15 [@inlined never]) y
+ and f17 y = (f16 [@inlined never]) y
+ and f18 y = (f17 [@inlined never]) y
+ and f19 y = (f18 [@inlined never]) y
+ and f20 y = (f19 [@inlined never]) y
+ and f21 y = (f20 [@inlined never]) y
+ and f22 y = (f21 [@inlined never]) y
+ and f23 y = (f22 [@inlined never]) y
+ and f24 y = (f23 [@inlined never]) y
+ and f25 y = (f24 [@inlined never]) y
+ and f26 y = (f25 [@inlined never]) y
+ and f27 y = (f26 [@inlined never]) y
+ and f28 y = (f27 [@inlined never]) y
+ and f29 y = (f28 [@inlined never]) y
+ and f30 y = (f29 [@inlined never]) y
+ and f31 y = (f30 [@inlined never]) y
+ and f32 y = (f31 [@inlined never]) y
+ and f33 y = (f32 [@inlined never]) y
+ and f34 y = (f33 [@inlined never]) y
+ and f35 y = (f34 [@inlined never]) y
+ and f36 y = (f35 [@inlined never]) y
+ and f37 y = (f36 [@inlined never]) y
+ and f38 y = (f37 [@inlined never]) y
+ and f39 y = (f38 [@inlined never]) y
+ and f40 y = (f39 [@inlined never]) y
+ and f41 y = (f40 [@inlined never]) y
+ and f42 y = (f41 [@inlined never]) y
+ and f43 y = (f42 [@inlined never]) y
+ and f44 y = (f43 [@inlined never]) y
+ and f45 y = (f44 [@inlined never]) y
+ and f46 y = (f45 [@inlined never]) y
+ and f47 y = (f46 [@inlined never]) y
+ and f48 y = (f47 [@inlined never]) y
+ and f49 y = (f48 [@inlined never]) y
+ and f50 y = (f49 [@inlined never]) y
+ and f51 y = (f50 [@inlined never]) y
+ and f52 y = (f51 [@inlined never]) y
+ and f53 y = (f52 [@inlined never]) y
+ and f54 y = (f53 [@inlined never]) y
+ and f55 y = (f54 [@inlined never]) y
+ and f56 y = (f55 [@inlined never]) y
+ and f57 y = (f56 [@inlined never]) y
+ and f58 y = (f57 [@inlined never]) y
+ and f59 y = (f58 [@inlined never]) y
+ and f60 y = (f59 [@inlined never]) y
+ and f61 y = (f60 [@inlined never]) y
+ and f62 y = (f61 [@inlined never]) y
+ and f63 y = (f62 [@inlined never]) y
+ and f64 y = (f63 [@inlined never]) y
+ and f65 y = (f64 [@inlined never]) y
+ and f66 y = (f65 [@inlined never]) y
+ and f67 y = (f66 [@inlined never]) y
+ and f68 y = (f67 [@inlined never]) y
+ and f69 y = (f68 [@inlined never]) y
+ and f70 y = (f69 [@inlined never]) y
+ and f71 y = (f70 [@inlined never]) y
+ and f72 y = (f71 [@inlined never]) y
+ and f73 y = (f72 [@inlined never]) y
+ and f74 y = (f73 [@inlined never]) y
+ and f75 y = (f74 [@inlined never]) y
+ and f76 y = (f75 [@inlined never]) y
+ and f77 y = (f76 [@inlined never]) y
+ and f78 y = (f77 [@inlined never]) y
+ and f79 y = (f78 [@inlined never]) y
+ and f80 y = (f79 [@inlined never]) y
+ and f81 y = (f80 [@inlined never]) y
+ and f82 y = (f81 [@inlined never]) y
+ and f83 y = (f82 [@inlined never]) y
+ and f84 y = (f83 [@inlined never]) y
+ and f85 y = (f84 [@inlined never]) y
+ and f86 y = (f85 [@inlined never]) y
+ and f87 y = (f86 [@inlined never]) y
+ and f88 y = (f87 [@inlined never]) y
+ and f89 y = (f88 [@inlined never]) y
+ and f90 y = (f89 [@inlined never]) y
+ and f91 y = (f90 [@inlined never]) y
+ and f92 y = (f91 [@inlined never]) y
+ and f93 y = (f92 [@inlined never]) y
+ and f94 y = (f93 [@inlined never]) y
+ and f95 y = (f94 [@inlined never]) y
+ and f96 y = (f95 [@inlined never]) y
+ and f97 y = (f96 [@inlined never]) y
+ and f98 y = (f97 [@inlined never]) y
+ and f99 y = (f98 [@inlined never]) y
+ and f100 y = (f99 [@inlined never]) y
+ and f101 y = (f100 [@inlined never]) y
+ and f102 y = (f101 [@inlined never]) y
+ and f103 y = (f102 [@inlined never]) y
+ and f104 y = (f103 [@inlined never]) y
+ and f105 y = (f104 [@inlined never]) y
+ and f106 y = (f105 [@inlined never]) y
+ and f107 y = (f106 [@inlined never]) y
+ and f108 y = (f107 [@inlined never]) y
+ and f109 y = (f108 [@inlined never]) y
+ and f110 y = (f109 [@inlined never]) y
+ and f111 y = (f110 [@inlined never]) y
+ and f112 y = (f111 [@inlined never]) y
+ and f113 y = (f112 [@inlined never]) y
+ and f114 y = (f113 [@inlined never]) y
+ and f115 y = (f114 [@inlined never]) y
+ and f116 y = (f115 [@inlined never]) y
+ and f117 y = (f116 [@inlined never]) y
+ and f118 y = (f117 [@inlined never]) y
+ and f119 y = (f118 [@inlined never]) y
+ and f120 y = (f119 [@inlined never]) y
+ and f121 y = (f120 [@inlined never]) y
+ and f122 y = (f121 [@inlined never]) y
+ and f123 y = (f122 [@inlined never]) y
+ and f124 y = (f123 [@inlined never]) y
+ and f125 y = (f124 [@inlined never]) y
+ and f126 y = (f125 [@inlined never]) y
+ and f127 y = (f126 [@inlined never]) y
+ and f128 y = (f127 [@inlined never]) y
+ and f129 y = (f128 [@inlined never]) y
+ and f130 y = (f129 [@inlined never]) y
+ and f131 y = (f130 [@inlined never]) y
+ and f132 y = (f131 [@inlined never]) y
+ and f133 y = (f132 [@inlined never]) y
+ and f134 y = (f133 [@inlined never]) y
+ and f135 y = (f134 [@inlined never]) y
+ and f136 y = (f135 [@inlined never]) y
+ and f137 y = (f136 [@inlined never]) y
+ and f138 y = (f137 [@inlined never]) y
+ and f139 y = (f138 [@inlined never]) y
+ and f140 y = (f139 [@inlined never]) y
+ and f141 y = (f140 [@inlined never]) y
+ and f142 y = (f141 [@inlined never]) y
+ and f143 y = (f142 [@inlined never]) y
+ and f144 y = (f143 [@inlined never]) y
+ and f145 y = (f144 [@inlined never]) y
+ and f146 y = (f145 [@inlined never]) y
+ and f147 y = (f146 [@inlined never]) y
+ and f148 y = (f147 [@inlined never]) y
+ and f149 y = (f148 [@inlined never]) y
+ and f150 y = (f149 [@inlined never]) y
+ and f151 y = (f150 [@inlined never]) y
+ and f152 y = (f151 [@inlined never]) y
+ and f153 y = (f152 [@inlined never]) y
+ and f154 y = (f153 [@inlined never]) y
+ and f155 y = (f154 [@inlined never]) y
+ and f156 y = (f155 [@inlined never]) y
+ and f157 y = (f156 [@inlined never]) y
+ and f158 y = (f157 [@inlined never]) y
+ and f159 y = (f158 [@inlined never]) y
+ and f160 y = (f159 [@inlined never]) y
+ and f161 y = (f160 [@inlined never]) y
+ and f162 y = (f161 [@inlined never]) y
+ and f163 y = (f162 [@inlined never]) y
+ and f164 y = (f163 [@inlined never]) y
+ and f165 y = (f164 [@inlined never]) y
+ and f166 y = (f165 [@inlined never]) y
+ and f167 y = (f166 [@inlined never]) y
+ and f168 y = (f167 [@inlined never]) y
+ and f169 y = (f168 [@inlined never]) y
+ and f170 y = (f169 [@inlined never]) y
+ and f171 y = (f170 [@inlined never]) y
+ and f172 y = (f171 [@inlined never]) y
+ and f173 y = (f172 [@inlined never]) y
+ and f174 y = (f173 [@inlined never]) y
+ and f175 y = (f174 [@inlined never]) y
+ and f176 y = (f175 [@inlined never]) y
+ and f177 y = (f176 [@inlined never]) y
+ and f178 y = (f177 [@inlined never]) y
+ and f179 y = (f178 [@inlined never]) y
+ and f180 y = (f179 [@inlined never]) y
+ and f181 y = (f180 [@inlined never]) y
+ and f182 y = (f181 [@inlined never]) y
+ and f183 y = (f182 [@inlined never]) y
+ and f184 y = (f183 [@inlined never]) y
+ and f185 y = (f184 [@inlined never]) y
+ and f186 y = (f185 [@inlined never]) y
+ and f187 y = (f186 [@inlined never]) y
+ and f188 y = (f187 [@inlined never]) y
+ and f189 y = (f188 [@inlined never]) y
+ and f190 y = (f189 [@inlined never]) y
+ and f191 y = (f190 [@inlined never]) y
+ and f192 y = (f191 [@inlined never]) y
+ and f193 y = (f192 [@inlined never]) y
+ and f194 y = (f193 [@inlined never]) y
+ and f195 y = (f194 [@inlined never]) y
+ and f196 y = (f195 [@inlined never]) y
+ and f197 y = (f196 [@inlined never]) y
+ and f198 y = (f197 [@inlined never]) y
+ and f199 y = (f198 [@inlined never]) y
+ and f200 y = (f199 [@inlined never]) y
+ and f201 y = (f200 [@inlined never]) y
+ and f202 y = (f201 [@inlined never]) y
+ and f203 y = (f202 [@inlined never]) y
+ and f204 y = (f203 [@inlined never]) y
+ and f205 y = (f204 [@inlined never]) y
+ and f206 y = (f205 [@inlined never]) y
+ and f207 y = (f206 [@inlined never]) y
+ and f208 y = (f207 [@inlined never]) y
+ and f209 y = (f208 [@inlined never]) y
+ and f210 y = (f209 [@inlined never]) y
+ and f211 y = (f210 [@inlined never]) y
+ and f212 y = (f211 [@inlined never]) y
+ and f213 y = (f212 [@inlined never]) y
+ and f214 y = (f213 [@inlined never]) y
+ and f215 y = (f214 [@inlined never]) y
+ and f216 y = (f215 [@inlined never]) y
+ and f217 y = (f216 [@inlined never]) y
+ and f218 y = (f217 [@inlined never]) y
+ and f219 y = (f218 [@inlined never]) y
+ and f220 y = (f219 [@inlined never]) y
+ and f221 y = (f220 [@inlined never]) y
+ and f222 y = (f221 [@inlined never]) y
+ and f223 y = (f222 [@inlined never]) y
+ and f224 y = (f223 [@inlined never]) y
+ and f225 y = (f224 [@inlined never]) y
+ and f226 y = (f225 [@inlined never]) y
+ and f227 y = (f226 [@inlined never]) y
+ and f228 y = (f227 [@inlined never]) y
+ and f229 y = (f228 [@inlined never]) y
+ and f230 y = (f229 [@inlined never]) y
+ and f231 y = (f230 [@inlined never]) y
+ and f232 y = (f231 [@inlined never]) y
+ and f233 y = (f232 [@inlined never]) y
+ and f234 y = (f233 [@inlined never]) y
+ and f235 y = (f234 [@inlined never]) y
+ and f236 y = (f235 [@inlined never]) y
+ and f237 y = (f236 [@inlined never]) y
+ and f238 y = (f237 [@inlined never]) y
+ and f239 y = (f238 [@inlined never]) y
+ and f240 y = (f239 [@inlined never]) y
+ and f241 y = (f240 [@inlined never]) y
+ and f242 y = (f241 [@inlined never]) y
+ and f243 y = (f242 [@inlined never]) y
+ and f244 y = (f243 [@inlined never]) y
+ and f245 y = (f244 [@inlined never]) y
+ and f246 y = (f245 [@inlined never]) y
+ and f247 y = (f246 [@inlined never]) y
+ and f248 y = (f247 [@inlined never]) y
+ and f249 y = (f248 [@inlined never]) y
+ and f250 y = (f249 [@inlined never]) y
+ and f251 y = (f250 [@inlined never]) y
+ and f252 y = (f251 [@inlined never]) y
+ and f253 y = (f252 [@inlined never]) y
+ and f254 y = (f253 [@inlined never]) y
+ and f255 y = (f254 [@inlined never]) y
+ and f256 y = (f255 [@inlined never]) y
+ and f257 y = (f256 [@inlined never]) y
+ and f258 y = (f257 [@inlined never]) y
+ and f259 y = (f258 [@inlined never]) y
+ and f260 y = (f259 [@inlined never]) y
+ and f261 y = (f260 [@inlined never]) y
+ and f262 y = (f261 [@inlined never]) y
+ and f263 y = (f262 [@inlined never]) y
+ and f264 y = (f263 [@inlined never]) y
+ and f265 y = (f264 [@inlined never]) y
+ and f266 y = (f265 [@inlined never]) y
+ and f267 y = (f266 [@inlined never]) y
+ and f268 y = (f267 [@inlined never]) y
+ and f269 y = (f268 [@inlined never]) y
+ and f270 y = (f269 [@inlined never]) y
+end
+
+let words0 = Gc.minor_words ()
+let words1 = Gc.minor_words ()
+module X = F (struct let x = 42 end)
+let words2 = Gc.minor_words ()
+
+let expected = words1 -. words0
+
+let () =
+ match Sys.backend_type with
+ | Sys.Native ->
+ Printf.printf "%.0f" ((words2 -. words1) -. expected)
+ | Sys.Bytecode | Sys.Other _ ->
+ print_string "0"
--- /dev/null
+0
+All tests succeeded.
let bug () =
let mat = [| [|false|] |]
and test = ref false in
- printf "Value of test at the beginning : %b\n" !test; flush stdout;
+ printf "Value of test at the beginning : %B\n" !test; flush stdout;
(try let _ = mat.(0).(-1) in
(test := true;
printf "Am I going through this block of instructions ?\n";
flush stdout)
- with Invalid_argument _ -> printf "Value of test now : %b\n" !test
+ with Invalid_argument _ -> printf "Value of test now : %B\n" !test
);
(try if mat.(0).(-1) then ()
with Invalid_argument _ -> ()
let s = Bytes.of_string "\000"
let () =
(* ensure that the string is not constant *)
- s.[0] <- '\001'
+ Bytes.set s 0 '\001'
let unknown_true =
Bytes.get s 0 = '\001'
+++ /dev/null
-(*
-
-A testbed file for the module Format.
-
-*)
-
-open Testing;;
-
-open Format;;
-
-(* BR#4769 *)
-let test0 () =
- let b = Buffer.create 10 in
- let msg = "Hello world!" in
- Format.bprintf b "%s" msg;
- let s = Buffer.contents b in
- s = msg
-;;
-
-test (test0 ())
-;;
+++ /dev/null
- 0
-All tests succeeded.
+++ /dev/null
-#**************************************************************************
-#* *
-#* OCaml *
-#* *
-#* Xavier Clerc, SED, 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 GNU Lesser General Public License version 2.1, with the *
-#* special exception on linking described in the file LICENSE. *
-#* *
-#**************************************************************************
-
-BASEDIR=../..
-MODULES=multdef
-MAIN_MODULE=usemultdef
-
-include $(BASEDIR)/makefiles/Makefile.one
-include $(BASEDIR)/makefiles/Makefile.common
--- /dev/null
+usemultdef.ml
+(* TEST
+ modules = "multdef.ml"
+*)
+
let _ = print_int(Multdef.f 1); print_newline(); exit 0
+++ /dev/null
-#**************************************************************************
-#* *
-#* OCaml *
-#* *
-#* Xavier Clerc, SED, 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 GNU Lesser General Public License version 2.1, with the *
-#* special exception on linking described in the file LICENSE. *
-#* *
-#**************************************************************************
-
-BASEDIR=../..
-
-MODULES=length
-MAIN_MODULE=tlength
-
-include $(BASEDIR)/makefiles/Makefile.one
-include $(BASEDIR)/makefiles/Makefile.common
--- /dev/null
+tlength.ml
+(* TEST
+ modules = "length.ml"
+*)
+
(*
A testbed file for private type abbreviation definitions.
-#**************************************************************************
-#* *
-#* OCaml *
-#* *
-#* Xavier Clerc, SED, 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 GNU Lesser General Public License version 2.1, with the *
-#* special exception on linking described in the file LICENSE. *
-#* *
-#**************************************************************************
-
-all: pr6322.ml check
-
BASEDIR=../..
include $(BASEDIR)/makefiles/Makefile.several
include $(BASEDIR)/makefiles/Makefile.common
-GENERATED_SOURCES=pr6322.ml *.safe-string
-
-pr6322.ml: $(SAFE_STRING).safe-string
-ifeq ($(SAFE_STRING),false)
- @cat pr6322.ml.in > $@
-else
- @echo "Printf.printf \"PR#6322=Ok\\n%!\"" > $@
-endif
-
-%.safe-string:
- @rm -f pr6322.ml
- @touch $@
+# The trigraph.ml test always fails under OpenBSD 6 / i386
+# because of an unrelated warning emitted by the linker called by ocamlopt
+# (see commit log for details).
+# As a temporary workaround, we skip this test.
+SKIP=test $$file = trigraph.ml \
+ && test `uname -m` = i386 && test `uname -s` = OpenBSD
--- /dev/null
+type t =
+ { mutable x : int;
+ y : int }
+
+let f { x = c } =
+ fun () -> c;;
+
+let r = { x = 10; y = 20 };;
+
+let h = f r;;
+
+print_endline (string_of_int (h ()));;
+
+r.x <- 20;;
+
+print_endline (string_of_int (h ()));;
+
print_endline "Union+concat (with Map.union)";
let f3 _ l r = if l = r then None else Some (l ^ r) in
show (IntMap.union f3 m1 m2);
-
()
+
+let show m = IntMap.iter (fun k v -> Printf.printf "%d -> %d\n" k v) m
+
+let update x f m =
+ let yp = IntMap.find_opt x m in
+ let y = f yp in
+ match yp, y with
+ | _, None -> IntMap.remove x m
+ | None, Some z -> IntMap.add x z m
+ | Some zp, Some z -> if zp == z then m else IntMap.add x z m
+
+let () =
+ print_endline "Update";
+ let rec init m = function
+ | -1 -> m
+ | n -> init (IntMap.add n n m) (n - 1)
+ in
+ let n = 9 in
+ let m = init IntMap.empty n in
+ for i = 0 to n + 1 do
+ for j = 0 to n + 1 do
+ List.iter (function (k, f) ->
+ let m1 = update i f m in
+ let m2 = IntMap.update i f m in
+ if not (IntMap.equal ( = ) m1 m2 && ((m1 == m) = (m2 == m))) then begin
+ Printf.printf "ERROR: %s: %d -> %d\n" k i j;
+ print_endline "expected result:";
+ show m1;
+ print_endline "result:";
+ show m2;
+ end
+ )
+ [
+ "replace", (function None -> None | Some _ -> Some j);
+ "delete if exists, bind otherwise", (function None -> Some j | Some _ -> None);
+ "delete", (function None -> None | Some _ -> None);
+ "insert", (function None -> Some j | Some _ -> Some j);
+ ]
+ done;
+ done;
+;;
+++ /dev/null
-(* No string sharing PR#6322. This test is not applicable when OCaml is compiled with -safe-string. *)
-
-let test x = match x with
- | true -> "a"
- | false -> "a"
-
-let () =
- let s1 = test true in
- let s2 = test false in
- s1.[0] <- 'p';
- if s1 <> s2 then Printf.printf "PR#6322=Ok\n%!"
+++ /dev/null
-PR#6322=Ok
--- /dev/null
+[@@@ocaml.warning "-21-5"]
+
+let foo g () = g 1; ()
+let f1 ?x y = print_endline "f1"
+let f2 ?x y = print_endline "f2"
+
+let () =
+ try foo (raise Exit; f1); print_endline "FAIL"
+ with Exit -> print_endline "OK"
+
+let r : (?x:unit -> int -> unit) ref = ref f1
+let h = foo r.contents
+let () = h (); r := f2; h ()
--- /dev/null
+OK
+f1
+f1
--- /dev/null
+(* PR#6373 *)
+
+let () = print_string "??'"
--- /dev/null
+??'
\ No newline at end of file
BASEDIR=../..
-CC=$(NATIVECC) -I $(CTOPDIR)/byterun
COMPFLAGS=-I $(OTOPDIR)/otherlibs/unix
LD_PATH=$(TOPDIR)/otherlibs/unix
.PHONY: common
common:
- @$(CC) -c callbackprim.c
+ @$(CC) -c $(CFLAGS) $(CPPFLAGS) -I$(CTOPDIR)/byterun callbackprim.c
.PHONY: skip
skip:
value mycallback1(value fun, value arg)
{
value res;
- res = callback(fun, arg);
+ res = caml_callback(fun, arg);
return res;
}
value mycallback2(value fun, value arg1, value arg2)
{
value res;
- res = callback2(fun, arg1, arg2);
+ res = caml_callback2(fun, arg1, arg2);
return res;
}
value mycallback3(value fun, value arg1, value arg2, value arg3)
{
value res;
- res = callback3(fun, arg1, arg2, arg3);
+ res = caml_callback3(fun, arg1, arg2, arg3);
return res;
}
args[1] = arg2;
args[2] = arg3;
args[3] = arg4;
- res = callbackN(fun, 4, args);
+ res = caml_callbackN(fun, 4, args);
return res;
}
value mypushroot(value v, value fun, value arg)
{
Begin_root(v)
- callback(fun, arg);
+ caml_callback(fun, arg);
End_roots();
return v;
}
CAMLparam3 (v, fun, arg);
CAMLlocal2 (x, y);
x = v;
- y = callback (fun, arg);
+ y = caml_callback (fun, arg);
v = x;
CAMLreturn (v);
}
extern int fib(int n);
extern char * format_result(int n);
+#ifdef _WIN32
+int wmain(int argc, wchar_t ** argv)
+#else
int main(int argc, char ** argv)
+#endif
{
printf("Initializing OCaml code...\n");
+
+ /* Initializing the runtime twice, to check that it's possible to
+ make nested calls to caml_startup/caml_shutdown. */
#ifdef NO_BYTECODE_FILE
caml_startup(argv);
+ caml_startup(argv);
#else
caml_main(argv);
+ caml_main(argv);
#endif
+
printf("Back in C code...\n");
printf("Computing fib(20)...\n");
printf("%s\n", format_result(fib(20)));
+
+ caml_shutdown();
+ caml_shutdown();
+
return 0;
}
--- /dev/null
+BASEDIR=../..
+TOPFLAGS+=-dlambda
+include $(BASEDIR)/makefiles/Makefile.dlambda
+include $(BASEDIR)/makefiles/Makefile.common
--- /dev/null
+module type S = sig
+ val foo : int -> int
+end
+
+module O (X : S) = struct
+ let cow x = X.foo x
+ let sheep x = 1 + cow x
+end [@@inline always]
+
+module F (X : S) (Y : S) = struct
+ let cow x = Y.foo (X.foo x)
+ let sheep x = 1 + cow x
+end [@@inline always]
+
+module type S1 = sig
+ val bar : int -> int
+ val foo : int -> int
+end
+
+module type T = sig
+ val sheep : int -> int
+end
+
+module F1 (X : S) (Y : S) : T = struct
+ let cow x = Y.foo (X.foo x)
+ let sheep x = 1 + cow x
+end [@@inline always]
+
+module F2 : S1 -> S1 -> T = functor (X : S) -> functor (Y : S) -> struct
+ let cow x = Y.foo (X.foo x)
+ let sheep x = 1 + cow x
+end [@@inline always]
+
+module M : sig
+ module F (X : S1) (Y : S1) : T
+end = struct
+ module F (X : S) (Y : S) = struct
+ let cow x = Y.foo (X.foo x)
+ let sheep x = 1 + cow x
+ end [@@inline always]
+end
--- /dev/null
+(setglobal Functors!
+ (let
+ (O =
+ (module-defn(O) functors.ml(5):48-143
+ (function X is_a_functor always_inline
+ (let
+ (cow = (function x (apply (field 0 X) x))
+ sheep = (function x (+ 1 (apply cow x))))
+ (makeblock 0 cow sheep))))
+ F =
+ (module-defn(F) functors.ml(10):145-256
+ (function X Y is_a_functor always_inline
+ (let
+ (cow =
+ (function x
+ (apply (field 0 Y) (apply (field 0 X) x)))
+ sheep = (function x (+ 1 (apply cow x))))
+ (makeblock 0 cow sheep))))
+ F1/1022 =
+ (module-defn(F1/1022) functors.ml(24):380-496
+ (function X Y is_a_functor always_inline
+ (let
+ (cow =
+ (function x
+ (apply (field 0 Y) (apply (field 0 X) x)))
+ sheep = (function x (+ 1 (apply cow x))))
+ (makeblock 0 sheep))))
+ F2/1029 =
+ (module-defn(F2/1029) functors.ml(29):498-648
+ (function X Y is_a_functor always_inline
+ (let
+ (X =a (makeblock 0 (field 1 X))
+ Y =a (makeblock 0 (field 1 Y))
+ cow =
+ (function x
+ (apply (field 0 Y) (apply (field 0 X) x)))
+ sheep = (function x (+ 1 (apply cow x))))
+ (makeblock 0 sheep))))
+ M =
+ (module-defn(M) functors.ml(34):650-834
+ (let
+ (F =
+ (module-defn(F) functors.ml(37):713-830
+ (function X Y is_a_functor always_inline
+ (let
+ (cow =
+ (function x
+ (apply (field 0 Y)
+ (apply (field 0 X) x)))
+ sheep =
+ (function x (+ 1 (apply cow x))))
+ (makeblock 0 cow sheep)))))
+ (makeblock 0
+ (function funarg funarg is_a_functor stub
+ (let
+ (let =
+ (apply F (makeblock 0 (field 1 funarg))
+ (makeblock 0 (field 1 funarg))))
+ (makeblock 0 (field 1 let))))))))
+ (makeblock 0 O F F1/1022 F2/1029 M)))
--- /dev/null
+#**************************************************************************
+#* *
+#* OCaml *
+#* *
+#* Xavier Clerc, SED, 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 GNU Lesser General Public License version 2.1, with the *
+#* special exception on linking described in the file LICENSE. *
+#* *
+#**************************************************************************
+
+BASEDIR=../..
+include $(BASEDIR)/makefiles/Makefile.toplevel
+include $(BASEDIR)/makefiles/Makefile.common
--- /dev/null
+let rec x = let y = () in x;;
+
+let rec x = let module M = struct let f = x let g = x () end in fun () -> ();;
+
+let rec x = let module M = struct let f = x () let g = x end in fun () -> ();;
+
+let rec x = (let module M = struct let f = y 0 let g = () end in fun () -> ())
+ and y = succ;;
+
+let rec x = let module M = struct module N = struct let y = x end end in M.N.y;;
+
+let rec x = let module M = struct let f = x () and g = x end in fun () -> ();;
+
+class c _ = object end;;
+let rec x = new c x;;
+
+let rec x = ignore x;;
+
+let rec x = y 0 and y _ = ();;
+
+let rec c = { c with Complex.re = 1.0 };;
+
+let rec b = if b then true else false;;
+
+let r = ref ()
+let rec x = r := x;;
+
+let rec x =
+ for i = 0 to 1 do
+ let z = y in ignore z
+ done
+and y = x; ();;
+
+let rec x =
+ for i = 0 to y do
+ ()
+ done
+and y = 10;;
+
+let rec x =
+ for i = y to 10 do
+ ()
+ done
+and y = 0;;
+
+let rec x =
+ while false do
+ let y = x in ignore y
+ done
+and y = x; ();;
+
+let rec x =
+ while y do
+ ()
+ done
+and y = false;;
+
+let rec x =
+ while y do
+ let y = x in ignore y
+ done
+and y = false;;
+
+let rec x = y#m and y = object method m = () end;;
+
+let rec x = (object method m _ = () end)#m x;;
+
+let rec x = y.contents and y = { contents = 3 };;
+
+let rec x = object val mutable v = 0 method m = v <- y end and y = 1;;
+
+let rec x = assert y and y = true;;
+
+let rec x = object method m = x end;;
+
+let rec x = object method m = ignore x end;;
+
+(* The builtin Pervasives.ref is currently treated as a constructor.
+ Other functions of the same name should not be so treated. *)
+let _ =
+ let module Pervasives =
+ struct
+ let ref _ = assert false
+ end in
+ let rec x = Pervasives.ref y
+ and y = fun () -> ignore x
+ in (x, y)
+;;
+
+(* An example, from Leo White, of let rec bindings that allocate
+ values of unknown size *)
+let foo p x =
+ let rec f =
+ if p then (fun y -> x + g y) else (fun y -> g y)
+ and g =
+ if not p then (fun y -> x - f y) else (fun y -> f y)
+ in
+ (f, g)
+;;
+
+module type T = sig end
+let rec x = (module (val y : T) : T)
+and y = let module M = struct let x = x end in (module M : T)
+;;
+
+let rec x =
+ match let _ = y in raise Not_found with
+ _ -> "x"
+ | exception Not_found -> "z"
+and y = match x with
+ z -> ("y", z);;
+
--- /dev/null
+
+# Characters 12-27:
+ let rec x = let y = () in x;;
+ ^^^^^^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 13-77:
+ let rec x = let module M = struct let f = x let g = x () end in fun () -> ();;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 13-77:
+ let rec x = let module M = struct let f = x () let g = x end in fun () -> ();;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 13-79:
+ let rec x = (let module M = struct let f = y 0 let g = () end in fun () -> ())
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 13-79:
+ let rec x = let module M = struct module N = struct let y = x end end in M.N.y;;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 13-77:
+ let rec x = let module M = struct let f = x () and g = x end in fun () -> ();;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# class c : 'a -> object end
+# Characters 12-19:
+ let rec x = new c x;;
+ ^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 13-21:
+ let rec x = ignore x;;
+ ^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 13-16:
+ let rec x = y 0 and y _ = ();;
+ ^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 13-40:
+ let rec c = { c with Complex.re = 1.0 };;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 13-38:
+ let rec b = if b then true else false;;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 28-34:
+ let rec x = r := x;;
+ ^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 15-65:
+ ..for i = 0 to 1 do
+ let z = y in ignore z
+ done
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 15-46:
+ ..for i = 0 to y do
+ ()
+ done
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 15-47:
+ ..for i = y to 10 do
+ ()
+ done
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 15-62:
+ ..while false do
+ let y = x in ignore y
+ done
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 15-39:
+ ..while y do
+ ()
+ done
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 15-58:
+ ..while y do
+ let y = x in ignore y
+ done
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 13-16:
+ let rec x = y#m and y = object method m = () end;;
+ ^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 13-45:
+ let rec x = (object method m _ = () end)#m x;;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 13-23:
+ let rec x = y.contents and y = { contents = 3 };;
+ ^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 13-59:
+ let rec x = object val mutable v = 0 method m = v <- y end and y = 1;;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 13-21:
+ let rec x = assert y and y = true;;
+ ^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 13-36:
+ let rec x = object method m = x end;;
+ ^^^^^^^^^^^^^^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 13-43:
+ let rec x = object method m = ignore x end;;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# * Characters 230-246:
+ let rec x = Pervasives.ref y
+ ^^^^^^^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# * Characters 127-175:
+ if p then (fun y -> x + g y) else (fun y -> g y)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 37-61:
+ let rec x = (module (val y : T) : T)
+ ^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 15-98:
+ ..match let _ = y in raise Not_found with
+ _ -> "x"
+ | exception Not_found -> "z".
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+#
--- /dev/null
+(* Example from Stephen Dolan.
+ Accessing an extension constructor involves accessing the module
+ in which it's defined.
+ *)
+module type T =
+ sig exception A of int end;;
+
+let rec x =
+ let module M = (val m) in
+ M.A 42
+and (m : (module T)) =
+ (module (struct exception A of int end));;
--- /dev/null
+
+# * * * module type T = sig exception A of int end
+# Characters 15-49:
+ ..let module M = (val m) in
+ M.A 42
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+#
--- /dev/null
+let test =
+ let rec x = [| y; y |] and y = 1. in
+ assert (x = [| 1.; 1. |]);
+ assert (y = 1.);
+ ()
+;;
--- /dev/null
+
+# Characters 25-35:
+ let rec x = [| y; y |] and y = 1. in
+ ^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+#
--- /dev/null
+(* This is not allowed because constructing the generic array 'x' involves
+ inspecting 'y', which is bound in the same recursive group *)
+let f z = let rec x = [| y; z |] and y = z in x;;
--- /dev/null
+
+# * Characters 162-172:
+ let f z = let rec x = [| y; z |] and y = z in x;;
+ ^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+#
--- /dev/null
+let rec a = lazy b and b = 3;;
+
+let rec e = lazy (fun _ -> f) and f = ();;
--- /dev/null
+
+# Characters 12-18:
+ let rec a = lazy b and b = 3;;
+ ^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# val e : ('a -> unit) lazy_t = lazy <fun>
+val f : unit = ()
+#
--- /dev/null
+module type S = sig val y : float end;;
+module type T = sig val x : float val y : float end;;
+type t = T : (module S) -> t;;
+
+let rec x = let module M = (val m) in T (module M)
+and (m : (module T)) = (module (struct let x = 10.0 and y = 20.0 end));;
--- /dev/null
+
+# module type S = sig val y : float end
+# module type T = sig val x : float val y : float end
+# type t = T : (module S) -> t
+# Characters 13-51:
+ let rec x = let module M = (val m) in T (module M)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+#
--- /dev/null
+(* From Stephen Dolan *)
+type (_,_) eq = Refl : ('a, 'a) eq;;
+let cast (type a) (type b) (Refl : (a, b) eq) (x : a) = (x : b);;
+
+let is_int (type a) =
+ let rec (p : (int, a) eq) = match p with Refl -> Refl in
+ p
+
+let bang = print_string (cast (is_int : (int, string) eq) 42);;
--- /dev/null
+
+# type (_, _) eq = Refl : ('a, 'a) eq
+# val cast : ('a, 'b) eq -> 'a -> 'b = <fun>
+# Characters 53-78:
+ let rec (p : (int, a) eq) = match p with Refl -> Refl in
+ ^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+#
--- /dev/null
+let rec r = let rec x () = r and y () = x () in y () in r "oops";;
--- /dev/null
+
+# Characters 58-64:
+ let rec r = let rec x () = r and y () = x () in y () in r "oops";;
+ ^^^^^^
+Warning 20: this argument will not be used by the function.
+Characters 12-52:
+ let rec r = let rec x () = r and y () = x () in y () in r "oops";;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+#
--- /dev/null
+type t = {x: int64} [@@unboxed];;
+let rec x = {x = y} and y = 3L;;
+
+type r = A of r [@@unboxed];;
+let rec y = A y;;
+
--- /dev/null
+
+# type t = { x : int64; } [@@unboxed]
+# Characters 12-19:
+ let rec x = {x = y} and y = 3L;;
+ ^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# type r = A of r [@@unboxed]
+# Characters 12-15:
+ let rec y = A y;;
+ ^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+#
--- /dev/null
+let rec x = (x; ());;
+
+let rec x = let x = () in x;;
+
+let rec x = [y]
+and y = let x = () in x;;
+
+let rec x = [y]
+and y = let rec x = () in x;;
+
+let rec x =
+ let a = x in
+ fun () -> a ()
+and y =
+ [x];;
+
+let rec x = let module M = struct let f = x end in ();;
+
+module type T = sig val y: int end
+
+let rec x = let module M =
+ struct
+ module N =
+ struct
+ let y = x
+ end
+ end
+ in fun () -> ignore (M.N.y ());;
+
+let rec x = "x";;
+
+class c = object end
+let rec x = fun () -> new c;;
+
+let rec x = (y, y)
+and y = fun () -> ignore x;;
+
+let rec x = Some y
+and y = fun () -> ignore x
+;;
+
+let rec x = `A y
+and y = fun () -> ignore x
+;;
+
+let rec x = { contents = y }
+and y = fun () -> ignore x;;
+
+let r = ref (fun () -> ())
+let rec x = fun () -> r := x;;
+
+let rec x = fun () -> y.contents and y = { contents = 3 };;
+
+let rec x = function
+ Some _ -> ignore (y [])
+ | None -> ignore (y [])
+and y = function
+ [] -> ignore (x None)
+ | _ :: _ -> ignore (x None)
+ ;;
+
+let rec x = lazy (Lazy.force x + Lazy.force x)
+ ;;
+
+let rec x = { x with contents = 3 } [@ocaml.warning "-23"];;
+
+let rec x = let y = (x; ()) in y;;
+
+let rec x = [|y|] and y = 0;;
+
+(* Recursively constructing arrays of known non-float type is permitted *)
+let rec deep_cycle : [`Tuple of [`Shared of 'a] array] as 'a
+ = `Tuple [| `Shared deep_cycle |];;
+
+(* Constructing float arrays was disallowed altogether at one point
+ by an overzealous check. Constructing float arrays in recursive
+ bindings is fine when they don't partake in the recursion. *)
+let rec _x = let _ = [| 1.0 |] in 1. in ();;
--- /dev/null
+
+# Characters 12-27:
+ let rec x = let y = () in x;;
+ ^^^^^^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 13-77:
+ let rec x = let module M = struct let f = x let g = x () end in fun () -> ();;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 13-77:
+ let rec x = let module M = struct let f = x () let g = x end in fun () -> ();;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 13-79:
+ let rec x = (let module M = struct let f = y 0 let g = () end in fun () -> ())
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 13-79:
+ let rec x = let module M = struct module N = struct let y = x end end in M.N.y;;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 13-77:
+ let rec x = let module M = struct let f = x () and g = x end in fun () -> ();;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# class c : 'a -> object end
+# Characters 12-19:
+ let rec x = new c x;;
+ ^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 13-21:
+ let rec x = ignore x;;
+ ^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 13-16:
+ let rec x = y 0 and y _ = ();;
+ ^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 13-18:
+ let rec x = [|y|]
+ ^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 13-40:
+ let rec c = { c with Complex.re = 1.0 };;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 13-36:
+ let rec x = { x with contents = 3 };;
+ ^^^^^^^^^^^^^^^^^^^^^^^
+Warning 23: all the fields are explicitly listed in this record:
+the 'with' clause is useless.
+Characters 13-36:
+ let rec x = { x with contents = 3 };;
+ ^^^^^^^^^^^^^^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 13-38:
+ let rec b = if b then true else false;;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 28-34:
+ let rec x = r := x;;
+ ^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 15-65:
+ ..for i = 0 to 1 do
+ let z = y in ignore z
+ done
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 15-46:
+ ..for i = 0 to y do
+ ()
+ done
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 15-47:
+ ..for i = y to 10 do
+ ()
+ done
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 15-62:
+ ..while false do
+ let y = x in ignore y
+ done
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 15-39:
+ ..while y do
+ ()
+ done
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 15-58:
+ ..while y do
+ let y = x in ignore y
+ done
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 13-45:
+ let rec x = (object method m _ = () end)#m x;;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 13-23:
+ let rec x = y.contents and y = { contents = 3 };;
+ ^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 13-59:
+ let rec x = object val mutable v = 0 method m = v <- y end and y = 1;;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 13-21:
+ let rec x = assert y and y = true;;
+ ^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 13-36:
+ let rec x = object method m = x end;;
+ ^^^^^^^^^^^^^^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 13-43:
+ let rec x = object method m = ignore x end;;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# * Characters 230-246:
+ let rec x = Pervasives.ref y
+ ^^^^^^^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# * Characters 127-175:
+ if p then (fun y -> x + g y) else (fun y -> g y)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 13-33:
+ let rec x = let y = (x; ()) in y;;
+ ^^^^^^^^^^^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 15-58:
+ ..for i = 0 to 1 do
+ let z = y in z
+ done
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 37-61:
+ let rec x = (module (val y : T) : T)
+ ^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 15-55:
+ ..while false do
+ let y = x in y
+ done
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 15-98:
+ ..match let _ = y in raise Not_found with
+ _ -> "x"
+ | exception Not_found -> "z".
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+#
+++ /dev/null
-(* a bug in cmmgen.ml provokes a segfault in certain natively compiled
- letrec-bindings involving float arrays *)
-let test =
- let rec x = [| y; y |] and y = 1. in
- assert (x = [| 1.; 1. |]);
- assert (y = 1.);
- ()
--- /dev/null
+let rec x = let _y = [| |] in ();;
+
+let rec x = let y = [| |] in y :: x;;
--- /dev/null
+let rec c = lazy (0 + d) and d = 3;;
+
+let () = Printf.printf "%d\n" (Lazy.force c)
--- /dev/null
+(* Mantis PR7447 *)
+
+let rec r = (let rec x = `A r and y = fun () -> x in y)
+
+let (`A x) = r ()
+
+let _ = x ()
--- /dev/null
+let rec f = let g = f in fun x -> g x;;
--- /dev/null
+(* Test construction of cyclic values where the cycles pass through references *)
+
+type t = { mutable next : t; mutable inst : n ref }
+and n = T of t
+
+let rec d = { next = d; inst = ref (T d) }
+
+let f t1 t2 =
+ let rec self = ref init
+ and init () = t1 (function () -> self := t2; t2 ())
+ in fun () -> !self ()
+;;
--- /dev/null
+BASEDIR=../..
+include $(BASEDIR)/makefiles/Makefile.toplevel
+include $(BASEDIR)/makefiles/Makefile.common
--- /dev/null
+
+(* Correct escapes and their encoding *)
+
+let () =
+ assert ("\xF0\x9F\x90\xAB" = "\u{1F42B}");
+ assert ("\xF0\x9F\x90\xAB" = "\u{01F42B}");
+ assert ("\x00" = "\u{0}");
+ assert ("\x00" = "\u{00}");
+ assert ("\x00" = "\u{000}");
+ assert ("\x00" = "\u{0000}");
+ assert ("\x00" = "\u{00000}");
+ assert ("\x00" = "\u{000000}");
+ assert ("\xC3\xA9" = "\u{E9}");
+ assert ("\xC3\xA9" = "\u{0E9}");
+ assert ("\xC3\xA9" = "\u{00E9}");
+ assert ("\xC3\xA9" = "\u{000E9}");
+ assert ("\xC3\xA9" = "\u{0000E9}");
+ assert ("\xC3\xA9" = "\u{0000E9}");
+ assert ("\xF4\x8F\xBF\xBF" = "\u{10FFFF}");
+ ()
+;;
+
+
+(* Errors *)
+
+let invalid_sv = "\u{0D800}" ;;
+let invalid_sv = "\u{D800}" ;;
+let invalid_sv = "\u{D900}" ;;
+let invalid_sv = "\u{DFFF}" ;;
+let invalid_sv = "\u{110000} ;;
+
+let too_many_digits = "\u{01234567}" ;;
+let no_hex_digits = "\u{}" ;;
+let illegal_hex_digit = "\u{u}" ;;
--- /dev/null
+
+# # Characters 34-43:
+ let invalid_sv = "\u{0D800}" ;;
+ ^^^^^^^^^
+Error: Illegal backslash escape in string or character (\u{0D800}, D800 is not a Unicode scalar value)
+# Characters 18-26:
+ let invalid_sv = "\u{D800}" ;;
+ ^^^^^^^^
+Error: Illegal backslash escape in string or character (\u{D800}, D800 is not a Unicode scalar value)
+# Characters 18-26:
+ let invalid_sv = "\u{D900}" ;;
+ ^^^^^^^^
+Error: Illegal backslash escape in string or character (\u{D900}, D900 is not a Unicode scalar value)
+# Characters 18-26:
+ let invalid_sv = "\u{DFFF}" ;;
+ ^^^^^^^^
+Error: Illegal backslash escape in string or character (\u{DFFF}, DFFF is not a Unicode scalar value)
+# Characters 18-28:
+ let invalid_sv = "\u{110000} ;;
+ ^^^^^^^^^^
+Error: Illegal backslash escape in string or character (\u{110000}, 110000 is not a Unicode scalar value)
+# Characters 24-36:
+ let too_many_digits = "\u{01234567}" ;;
+ ^^^^^^^^^^^^
+Error: Illegal backslash escape in string or character (\u{01234567}, too many digits, expected 1 to 6 hexadecimal digits)
+# Characters 21-23:
+ let no_hex_digits = "\u{}" ;;
+ ^^
+Warning 14: illegal backslash escape in string.
+val no_hex_digits : string = "\\u{}"
+# Characters 25-27:
+ let illegal_hex_digit = "\u{u}" ;;
+ ^^
+Warning 14: illegal backslash escape in string.
+val illegal_hex_digit : string = "\\u{u}"
+#
;;
let f_unit () = record "unit()";;
-let f_bool b = record "bool(%b)" b;;
+let f_bool b = record "bool(%B)" b;;
let r_set = ref false;;
let r_clear = ref true;;
let f_string s = record "string(%s)" s;;
test_expand (expand1@spec) args1 expected1;;
test_expand (expand2@spec) args2 expected2;;
+
+let test_align () =
+ let spec =
+ [
+ "-foo", Arg.String ignore, "FOO Do foo with FOO";
+ "-bar", Arg.Tuple [Arg.String ignore; Arg.String ignore], "FOO BAR\tDo bar with FOO and BAR";
+ "-cha", Arg.Unit ignore, " Another option";
+ "-sym", Arg.Symbol (["a"; "b"], ignore), "\ty\tfoo";
+ "-sym2", Arg.Symbol (["a"; "b"], ignore), "x bar";
+ ]
+ in
+ print_endline (Arg.usage_string (Arg.align spec) "")
+;;
+
+test_align ();;
+
+ -foo FOO Do foo with FOO
+ -bar FOO BAR Do bar with FOO and BAR
+ -cha Another option
+ -sym {a|b}
+ y foo
+ -sym2 {a|b}
+ x bar
+ -help Display this list of options
+ --help Display this list of options
+
(* Tests *)
let tests () =
- testing_function "map_file";
let mapped_file = Filename.temp_file "bigarray" ".data" in
begin
+ testing_function "map_file";
let fd =
Unix.openfile mapped_file
[Unix.O_RDWR; Unix.O_TRUNC; Unix.O_CREAT] 0o666 in
let a =
- array1_of_genarray (Genarray.map_file fd float64 c_layout true [|10000|])
+ array1_of_genarray (Unix.map_file fd float64 c_layout true [|10000|])
in
Unix.close fd;
for i = 0 to 9999 do a.{i} <- float i done;
let fd = Unix.openfile mapped_file [Unix.O_RDONLY] 0 in
let b =
array2_of_genarray
- (Genarray.map_file fd float64 fortran_layout false [|100; -1|])
+ (Unix.map_file fd float64 fortran_layout false [|100; -1|])
in
Unix.close fd;
let ok = ref true in
b.{50,50} <- (-1.0);
let fd = Unix.openfile mapped_file [Unix.O_RDONLY] 0 in
let c =
- array2_of_genarray (Genarray.map_file fd float64 c_layout false [|-1; 100|])
+ array2_of_genarray (Unix.map_file fd float64 c_layout false [|-1; 100|])
in
Unix.close fd;
let ok = ref true in
let fd = Unix.openfile mapped_file [Unix.O_RDONLY] 0 in
let c =
array2_of_genarray
- (Genarray.map_file fd ~pos:800L float64 c_layout false [|-1; 100|])
+ (Unix.map_file fd ~pos:800L float64 c_layout false [|-1; 100|])
in
Unix.close fd;
let ok = ref true in
let fd = Unix.openfile mapped_file [Unix.O_RDONLY] 0 in
let c =
array2_of_genarray
- (Genarray.map_file fd ~pos:79200L float64 c_layout false [|-1; 100|])
+ (Unix.map_file fd ~pos:79200L float64 c_layout false [|-1; 100|])
in
Unix.close fd;
let ok = ref true in
for j = 0 to 99 do
if c.{0,j} <> float (100 * 99 + j) then ok := false
done;
- test 4 !ok true
+ test 4 !ok true;
+
+ testing_function "map_file errors";
+ (* Insufficient permissions *)
+ let fd = Unix.openfile mapped_file [Unix.O_RDONLY] 0 in
+ test 1 true
+ begin try
+ ignore (Unix.map_file fd float64 c_layout true [|-1; 100|]); false
+ with
+ | Unix.Unix_error((Unix.EACCES | Unix.EPERM), _, _) -> true
+ | Unix.Unix_error(err, _, _) ->
+ Printf.eprintf "Unexpected error %s\n%!" (Unix.error_message err);
+ false
+ end;
+ Unix.close fd;
+ (* Invalid handle *)
+ test 2 true
+ begin try
+ ignore (Unix.map_file fd float64 c_layout true [|-1; 100|]); false
+ with
+ | Unix.Unix_error((Unix.EBADF|Unix.EINVAL), _, _) -> true
+ | Unix.Unix_error(err, _, _) ->
+ Printf.eprintf "Unexpected error %s\n%!" (Unix.error_message err);
+ false
+ end
+
end;
(* Force garbage collection of the mapped bigarrays above, otherwise
Win32 doesn't let us erase the file. Notice the begin...end above
()
[@@inline never]
-
(********* End of test *********)
let _ =
map_file
1... 2... 3... 4...
+map_file errors
+ 1... 2...
test_structured_io 14 (make_array3 complex64 fortran_layout 1 10 20 30
makecomplex);
- testing_function "map_file";
- let mapped_file = Filename.temp_file "bigarray" ".data" in
- begin
- let fd =
- Unix.openfile mapped_file
- [Unix.O_RDWR; Unix.O_TRUNC; Unix.O_CREAT] 0o666 in
- let a = Array1.map_file fd float64 c_layout true 10000 in
- Unix.close fd;
- for i = 0 to 9999 do a.{i} <- float i done;
- let fd = Unix.openfile mapped_file [Unix.O_RDONLY] 0 in
- let b = Array2.map_file fd float64 fortran_layout false 100 (-1) in
- Unix.close fd;
- let ok = ref true in
- for i = 0 to 99 do
- for j = 0 to 99 do
- if b.{j+1,i+1} <> float (100 * i + j) then ok := false
- done
- done;
- test 1 !ok true;
- b.{50,50} <- (-1.0);
- let fd = Unix.openfile mapped_file [Unix.O_RDONLY] 0 in
- let c = Array2.map_file fd float64 c_layout false (-1) 100 in
- Unix.close fd;
- let ok = ref true in
- for i = 0 to 99 do
- for j = 0 to 99 do
- if c.{i,j} <> float (100 * i + j) then ok := false
- done
- done;
- test 2 !ok true;
- let fd = Unix.openfile mapped_file [Unix.O_RDONLY] 0 in
- let c = Array2.map_file fd ~pos:800L float64 c_layout false (-1) 100 in
- Unix.close fd;
- let ok = ref true in
- for i = 1 to 99 do
- for j = 0 to 99 do
- if c.{i-1,j} <> float (100 * i + j) then ok := false
- done
- done;
- test 3 !ok true;
- let fd = Unix.openfile mapped_file [Unix.O_RDONLY] 0 in
- let c = Array2.map_file fd ~pos:79200L float64 c_layout false (-1) 100 in
- Unix.close fd;
- let ok = ref true in
- for j = 0 to 99 do
- if c.{0,j} <> float (100 * 99 + j) then ok := false
- done;
- test 4 !ok true
- end;
- (* Force garbage collection of the mapped bigarrays above, otherwise
- Win32 doesn't let us erase the file. Notice the begin...end above
- so that the VM doesn't keep stack references to the mapped bigarrays. *)
- Gc.full_major();
- Sys.remove mapped_file;
-
()
[@@inline never]
output_value/input_value
1... 2... 3... 4... 5... 6... 7... 8... 9... 10... 11... 12... 13... 14...
-map_file
- 1... 2... 3... 4...
--- /dev/null
+(** Test the various change_layout for Genarray and the various Array[n] *)
+
+open Bigarray
+
+let pp_sep ppf () = Format.fprintf ppf ";@ "
+ let print_array pp ppf a =
+ Format.fprintf ppf "@[<hov>[|%a|]@]"
+ Format.(pp_print_list ~pp_sep pp) (Array.to_list a)
+
+let print_index = print_array Format.pp_print_int
+
+let do_test n test =
+ let rec aux l n =
+ if n = 0 then l
+ else
+ aux
+ begin match test (n-1) with
+ | Some error -> error :: l
+ | None -> l
+ end
+ (n-1) in
+ aux [] n
+
+let kind = float64
+
+let c = c_layout
+let fortran = fortran_layout
+
+let rank = 5
+let dims = Array.init rank (fun n -> n+2)
+let size = Array.fold_left ( * ) 1 dims
+
+let report s test =
+ let errors = do_test size test in
+ if errors = [] then
+ Format.printf"@[%s: Ok@]@." s
+ else
+ Format.printf "@[%s:@;Failed at indices @[<hov>%a@]@]@." s
+ (Format.pp_print_list ~pp_sep print_index)
+ errors
+
+let array =
+ let a = Array1.create kind c size in
+ for i = 0 to size - 1 do a.{i} <- float i done;
+ a
+
+(** Test for generic biggarray *)
+let gen = reshape (genarray_of_array1 array) dims
+
+let sizes =
+ let a = Array.make rank 1 in
+ let _ = Array.fold_left (fun (i,s) x -> a.(i)<- s; (i+1, s * x)) (0,1) dims in
+ a
+
+let multi_index n =
+ Array.init rank ( fun i -> (n / sizes.(i)) mod dims.(i) )
+
+let testG n =
+ let pos = multi_index n in
+ let initial = Genarray.get gen pos in
+ Genarray.set gen pos (-1.);
+ let different = Genarray.get gen pos <> initial in
+ let gen' = Genarray.change_layout gen fortran in
+ Genarray.set gen' ( Array.init rank @@ fun n -> 1 + pos.( rank - 1 - n ) ) initial;
+ if not (different && initial = Genarray.get gen pos) then Some pos
+ else None
+
+;;
+report "Generic rank test" testG
+;;
+
+(* Scalar *)
+let scalar =
+ let a = Array0.create kind c in
+ Array0.set a 0.; a
+;;
+let test =
+ let a' = Array0.change_layout scalar fortran in
+ Array0.set a' 1.;
+ Array0.get scalar = 1.
+
+;;
+Format.printf "Scalar test: %s@." (if test then "Ok" else "Failed")
+;;
+
+(* Vector *)
+let vec = array1_of_genarray @@ reshape gen [|size|]
+let test1 i =
+ let initial = vec.{i} in
+ vec.{i} <- -1.;
+ let different = vec.{i} <> initial in
+ let vec' = Array1.change_layout vec fortran in
+ vec'.{ i + 1 } <- initial;
+ if different && initial = vec.{i} then None
+ else Some [|i|]
+
+;;
+report "Rank-1 array test" test1
+;;
+
+(* Matrix *)
+let mat = array2_of_genarray @@ reshape gen [|dims.(0); size / dims.(0) |]
+let bi_index n = n mod dims.(0), n / dims.(0)
+
+let test2 n =
+ let i, j = bi_index n in
+ let initial = mat.{i,j} in
+ mat.{i,j} <- -1.;
+ let different = mat.{i,j} <> initial in
+ let mat' = Array2.change_layout mat fortran in
+ mat'.{ j + 1, i + 1 } <- initial;
+ if different && initial = mat.{i, j} then None
+ else Some [|i; j|]
+
+
+;;
+report "Rank-2 array test" test2
+;;
+
+(* Rank 3 *)
+let t3 = array3_of_genarray @@
+ reshape gen [|dims.(0); dims.(1); size / (dims.(0) * dims.(1)) |]
+
+let tri_index n =
+ n mod dims.(0),
+ (n/ dims.(0)) mod dims.(1),
+ n / (dims.(0) * dims.(1))
+
+let test3 n =
+ let i, j, k = tri_index n in
+ let initial = t3.{i,j,k} in
+ t3.{i,j,k} <- -1.;
+ let different = t3.{i,j,k} <> initial in
+ let t3' = Array3.change_layout t3 fortran in
+ t3'.{ k + 1, j + 1, i + 1 } <- initial;
+ if different && initial = t3.{i, j, k} then None
+ else Some [|i;j;k|]
+
+
+;;
+report "Rank-3 array test" test3
+;;
--- /dev/null
+Generic rank test: Ok
+Scalar test: Ok
+Rank-1 array test: Ok
+Rank-2 array test: Ok
+Rank-3 array test: Ok
let _ =
let y = Array1.of_array float64 fortran_layout [| 1. |] in
- (f y).{1};
+ ignore ((f y).{1});
(f y).{1} <- 3.14
let failed = output "failed"
;;
+let buffer_truncate = "Buffer.truncate"
+
+let unexpected str =
+ Printf.sprintf "The Invalid_argument exception has been raised with an \
+ invalid value as argument \"%s\". Expecting \"%s\"."
+ str buffer_truncate
+
+let validate f str msg =
+ if str=buffer_truncate then f msg
+ else failed (unexpected str)
+
(* Tests *)
let () = print_string "Standard Library: Module Buffer\n"
;;
Buffer.truncate buf (-1);
failed msg
with
- Invalid_argument "Buffer.truncate" ->
- passed msg
+ Invalid_argument str -> validate passed str msg
;;
let truncate_large : unit =
Buffer.truncate buf (n+1);
failed msg
with
- Invalid_argument "Buffer.truncate" ->
- passed msg
+ Invalid_argument str -> validate passed str msg
;;
let truncate_correct : unit =
else
failed msg
with
- Invalid_argument "Buffer.truncate" ->
- failed msg
+ Invalid_argument str -> validate failed str msg
;;
let reset_non_zero : unit =
else
failed msg
;;
+
+let utf_8_spec =
+ (* UTF-8 byte sequences, cf. table 3.7 Unicode 9. *)
+ [(0x0000,0x007F), [|(0x00,0x7F)|];
+ (0x0080,0x07FF), [|(0xC2,0xDF); (0x80,0xBF)|];
+ (0x0800,0x0FFF), [|(0xE0,0xE0); (0xA0,0xBF); (0x80,0xBF)|];
+ (0x1000,0xCFFF), [|(0xE1,0xEC); (0x80,0xBF); (0x80,0xBF)|];
+ (0xD000,0xD7FF), [|(0xED,0xED); (0x80,0x9F); (0x80,0xBF)|];
+ (0xE000,0xFFFF), [|(0xEE,0xEF); (0x80,0xBF); (0x80,0xBF)|];
+ (0x10000,0x3FFFF), [|(0xF0,0xF0); (0x90,0xBF); (0x80,0xBF); (0x80,0xBF)|];
+ (0x40000,0xFFFFF), [|(0xF1,0xF3); (0x80,0xBF); (0x80,0xBF); (0x80,0xBF)|];
+ (0x100000,0x10FFFF), [|(0xF4,0xF4); (0x80,0x8F); (0x80,0xBF); (0x80,0xBF)|]]
+;;
+
+let utf_16be_spec =
+ (* UTF-16BE byte sequences, derived from table 3.5 Unicode 9. *)
+ [(0x0000,0xD7FF), [|(0x00,0xD7); (0x00,0xFF)|];
+ (0xE000,0xFFFF), [|(0xE0,0xFF); (0x00,0xFF)|];
+ (0x10000,0x10FFFF), [|(0xD8,0xDB); (0x00,0xFF); (0xDC,0xDF); (0x00,0xFF)|]]
+;;
+
+let uchar_map_of_spec spec =
+ (* array mapping Uchar.t as ints to byte sequences according to [spec]. *)
+ let map = Array.make ((Uchar.to_int Uchar.max) + 1) "" in
+ let add_range ((umin, umax), bytes) =
+ let len = Array.length bytes in
+ let bmin i = if i < len then fst bytes.(i) else max_int in
+ let bmax i = if i < len then snd bytes.(i) else min_int in
+ let uchar = ref umin in
+ let buf = Bytes.create len in
+ let add len' =
+ if len <> len' then () else
+ begin
+ let bytes = Bytes.to_string buf in
+ map.(!uchar) <- bytes;
+ incr uchar;
+ end
+ in
+ for b0 = bmin 0 to bmax 0 do
+ Bytes.unsafe_set buf 0 (Char.chr b0);
+ for b1 = bmin 1 to bmax 1 do
+ Bytes.unsafe_set buf 1 (Char.chr b1);
+ for b2 = bmin 2 to bmax 2 do
+ Bytes.unsafe_set buf 2 (Char.chr b2);
+ for b3 = bmin 3 to bmax 3 do
+ Bytes.unsafe_set buf 3 (Char.chr b3);
+ add 4;
+ done;
+ add 3;
+ done;
+ add 2;
+ done;
+ add 1;
+ done;
+ assert (!uchar - 1 = umax)
+ in
+ List.iter add_range spec;
+ map
+;;
+
+let test_spec_map msg utf_x_map buffer_add_utf_x_uchar =
+ let b = Buffer.create 4 in
+ let rec loop u =
+ Buffer.clear b; buffer_add_utf_x_uchar b u;
+ match Buffer.contents b = utf_x_map.(Uchar.to_int u) with
+ | false -> failed (sprintf "%s of U+%04X" msg (Uchar.to_int u))
+ | true ->
+ if Uchar.equal u Uchar.max then passed msg else loop (Uchar.succ u)
+ in
+ loop Uchar.min
+;;
+
+let add_utf_8_uchar : unit =
+ let map = uchar_map_of_spec utf_8_spec in
+ test_spec_map
+ "add_utf_8_uchar: test against spec" map Buffer.add_utf_8_uchar
+;;
+
+let add_utf_16be_uchar : unit =
+ let map = uchar_map_of_spec utf_16be_spec in
+ test_spec_map
+ "add_utf_16be_uchar: test against spec" map Buffer.add_utf_16be_uchar
+;;
+
+let add_utf_16le_uchar : unit =
+ (* The uchar_map_of_spec generation function doesn't work on a LE spec since
+ uchars and byte seqs have to increase and map together; simply swap
+ the map obtained with utf_16be_spec. *)
+ let map =
+ let swap bytes =
+ let swap i = match i with
+ | 0 -> 1 | 1 -> 0 | 2 -> 3 | 3 -> 2 | _ -> assert false
+ in
+ String.init (String.length bytes) (fun i -> bytes.[swap i])
+ in
+ Array.map swap (uchar_map_of_spec utf_16be_spec)
+ in
+ test_spec_map
+ "add_utf_16le_uchar: test against spec" map Buffer.add_utf_16le_uchar
+;;
Buffer truncate: in-range passed
Buffer reset: non-zero passed
Buffer reset: zero passed
+Buffer add_utf_8_uchar: test against spec passed
+Buffer add_utf_16be_uchar: test against spec passed
+Buffer add_utf_16le_uchar: test against spec passed
for i = 0 to 15 do
let j = i lsl 2 in
data.(i) <-
- Int32.logor (Int32.shift_left (Int32.of_int (Bytes.get s (j+3) |> Char.code)) 24)
- (Int32.logor (Int32.shift_left (Int32.of_int (Bytes.get s (j+2) |> Char.code)) 16)
- (Int32.logor (Int32.shift_left (Int32.of_int (Bytes.get s (j+1) |> Char.code)) 8)
- (Int32.of_int (Bytes.get s j |> Char.code))))
+ let byte n = Bytes.get s (j+n) |> Char.code |> Int32.of_int in
+ let open Int32 in
+ byte 0
+ |> logor (shift_left (byte 1) 8)
+ |> logor (shift_left (byte 2) 16)
+ |> logor (shift_left (byte 3) 24)
done;
data
COMPFLAGS=-I $(OTOPDIR)/otherlibs/bigarray -I $(OTOPDIR)/otherlibs/dynlink \
-I $(OTOPDIR)/byterun
-LD_PATH=$(TOPDIR)/otherlibs/bigarray:$(TOPDIR)/otherlibs/dynlink
+LD_PATH=$(TOPDIR)/otherlibs/win32unix:$(TOPDIR)/otherlibs/bigarray:$(TOPDIR)/otherlibs/dynlink
default:
@$(SET_LD_PATH) $(MAKE) all
Now starting the OCaml engine.
Main is running.
+Loading ../../../otherlibs/win32unix/unix.cma
Loading ../../../otherlibs/bigarray/bigarray.cma
Loading plugin.cmo
I'm the plugin.
#endif /* WIN32 && !CYGWIN */
_DLLAPI void _CALLPROC start_caml_engine() {
- char * argv[2];
- argv[0] = "--";
+ wchar_t * argv[2];
+ argv[0] = L"--";
argv[1] = NULL;
caml_startup(argv);
}
with Dynlink.Error e ->
print_endline (Dynlink.error_message e)
+(* Callback must be linked to load Unix dynamically *)
+let _ = Callback.register
+module CamlinternalBigarray = CamlinternalBigarray
+
let () =
ignore (Hashtbl.hash 42.0);
print_endline "Main is running.";
Dynlink.init ();
Dynlink.allow_unsafe_modules true;
- let s1,s2 =
- if Dynlink.is_native then
- "../../../otherlibs/bigarray/bigarray.cmxs",
- "plugin.cmxs"
- else
- "../../../otherlibs/bigarray/bigarray.cma",
- "plugin.cmo"
+ let s1,s2,s3 =
+ Dynlink.adapt_filename "../../../otherlibs/win32unix/unix.cma",
+ Dynlink.adapt_filename "../../../otherlibs/bigarray/bigarray.cma",
+ Dynlink.adapt_filename "plugin.cmo"
in
load s1;
load s2;
+ load s3;
print_endline "OK."
Now starting the OCaml engine.
Main is running.
+Loading ../../../otherlibs/win32unix/unix.cmxs
Loading ../../../otherlibs/bigarray/bigarray.cmxs
Loading plugin.cmxs
I'm the plugin.
.PHONY: default
default:
- @if ! $(SUPPORTS_SHARED_LIBRARIES) || $(BYTECODE_ONLY) ; then \
+ @if ! $(NATDYNLINK) || $(BYTECODE_ONLY) ; then \
echo " ... testing 'main' => skipped"; \
else \
$(SET_LD_PATH) $(MAKE) all; \
--- /dev/null
+BASEDIR=../..
+include $(BASEDIR)/makefiles/Makefile.several
+include $(BASEDIR)/makefiles/Makefile.common
--- /dev/null
+(* Standard test case *)
+let () =
+ let l = List.init 10 (fun x -> x) in
+ assert (List.exists (fun a -> a < 10) l);
+ assert (List.exists (fun a -> a > 0) l);
+ assert (List.exists (fun a -> a = 0) l);
+ assert (List.exists (fun a -> a = 1) l);
+ assert (List.exists (fun a -> a = 2) l);
+ assert (List.exists (fun a -> a = 3) l);
+ assert (List.exists (fun a -> a = 4) l);
+ assert (List.exists (fun a -> a = 5) l);
+ assert (List.exists (fun a -> a = 6) l);
+ assert (List.exists (fun a -> a = 7) l);
+ assert (List.exists (fun a -> a = 8) l);
+ assert (List.exists (fun a -> a = 9) l);
+ assert (not (List.exists (fun a -> a < 0) l));
+ assert (not (List.exists (fun a -> a > 9) l));
+ assert (List.exists (fun _ -> true) l);
+
+ assert (List.compare_lengths [] [] = 0);
+ assert (List.compare_lengths [1;2] ['a';'b'] = 0);
+ assert (List.compare_lengths [] [1;2] < 0);
+ assert (List.compare_lengths ['a'] [1;2] < 0);
+ assert (List.compare_lengths [1;2] [] > 0);
+ assert (List.compare_lengths [1;2] ['a'] > 0);
+
+ assert (List.compare_length_with [] 0 = 0);
+ assert (List.compare_length_with [] 1 < 0);
+ assert (List.compare_length_with [] (-1) > 0);
+ assert (List.compare_length_with [] max_int < 0);
+ assert (List.compare_length_with [] min_int > 0);
+ assert (List.compare_length_with [1] 0 > 0);
+ assert (List.compare_length_with ['1'] 1 = 0);
+ assert (List.compare_length_with ['1'] 2 < 0);
+ ()
+;;
+
+(* Empty test case *)
+let () =
+ assert ((List.init 0 (fun x -> x)) = []);
+;;
+
+(* Erroneous test case *)
+
+let () =
+ let result = try
+ let _ = List.init (-1) (fun x -> x) in false
+ with Invalid_argument e -> true (* Exception caught *)
+ in assert result;
+;;
+
+(* Evaluation order *)
+let () =
+ let test n =
+ let result = ref false in
+ let _ = List.init n (fun x -> result := (x = n - 1)) in
+ assert !result
+ in
+ let threshold = 10_000 in (* Threshold must equal the value in stdlib/list.ml *)
+ test threshold; (* Non tail-recursive case *)
+ test (threshold + 1) (* Tail-recursive case *)
+;;
+
+let () = print_endline "OK";;
+++ /dev/null
-#**************************************************************************
-#* *
-#* OCaml *
-#* *
-#* Xavier Clerc, SED, 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 GNU Lesser General Public License version 2.1, with the *
-#* special exception on linking described in the file LICENSE. *
-#* *
-#**************************************************************************
-
-BASEDIR=../..
-LIBRARIES=nums
-ADD_COMPFLAGS=-I $(OTOPDIR)/otherlibs/num
-LD_PATH=$(TOPDIR)/otherlibs/num
-PROGRAM_ARGS=1000
-
-include $(BASEDIR)/makefiles/Makefile.several
-include $(BASEDIR)/makefiles/Makefile.common
+++ /dev/null
-(* Pi digits computed with the sreaming algorithm given on pages 4, 6
- & 7 of "Unbounded Spigot Algorithms for the Digits of Pi", Jeremy
- Gibbons, August 2004. *)
-
-open Printf;;
-open Big_int;;
-
-let ( !$ ) = Big_int.big_int_of_int
-and ( +$ ) = Big_int.add_big_int
-and ( *$ ) = Big_int.mult_big_int
-and ( =$ ) = Big_int.eq_big_int
-;;
-
-let zero = Big_int.zero_big_int
-and one = Big_int.unit_big_int
-and three = !$ 3
-and four = !$ 4
-and ten = !$ 10
-and neg_ten = !$(-10)
-;;
-
-(* Linear Fractional (aka M=F6bius) Transformations *)
-module LFT = struct
-
- let floor_ev (q, r, s, t) x = div_big_int (q *$ x +$ r) (s *$ x +$ t);;
-
- let unit = (one, zero, zero, one);;
-
- let comp (q, r, s, t) (q', r', s', t') =
- (q *$ q' +$ r *$ s', q *$ r' +$ r *$ t',
- s *$ q' +$ t *$ s', s *$ r' +$ t *$ t')
-;;
-
-end
-;;
-
-let next z = LFT.floor_ev z three
-and safe z n = (n =$ LFT.floor_ev z four)
-and prod z n = LFT.comp (ten, neg_ten *$ n, zero, one) z
-and cons z k =
- let den = 2 * k + 1 in
- LFT.comp z (!$ k, !$(2 * den), zero, !$ den)
-;;
-
-let rec digit k z n row col =
- if n > 0 then
- let y = next z in
- if safe z y then
- if col = 10 then (
- let row = row + 10 in
- printf "\t:%i\n%s" row (string_of_big_int y);
- digit k (prod z y) (n - 1) row 1
- )
- else (
- print_string(string_of_big_int y);
- digit k (prod z y) (n - 1) row (col + 1)
- )
- else digit (k + 1) (cons z k) n row col
- else
- printf "%*s\t:%i\n" (10 - col) "" (row + col)
-;;
-
-let digits n = digit 1 LFT.unit n 0 0
-;;
-
-let usage () =
- prerr_endline "Usage: pi_big_int <number of digits to compute for pi>";
- exit 2
-;;
-
-let main () =
- let args = Sys.argv in
- if Array.length args <> 2 then usage () else
- digits (int_of_string Sys.argv.(1))
-;;
-
-main ()
-;;
+++ /dev/null
-3141592653 :10
-5897932384 :20
-6264338327 :30
-9502884197 :40
-1693993751 :50
-0582097494 :60
-4592307816 :70
-4062862089 :80
-9862803482 :90
-5342117067 :100
-9821480865 :110
-1328230664 :120
-7093844609 :130
-5505822317 :140
-2535940812 :150
-8481117450 :160
-2841027019 :170
-3852110555 :180
-9644622948 :190
-9549303819 :200
-6442881097 :210
-5665933446 :220
-1284756482 :230
-3378678316 :240
-5271201909 :250
-1456485669 :260
-2346034861 :270
-0454326648 :280
-2133936072 :290
-6024914127 :300
-3724587006 :310
-6063155881 :320
-7488152092 :330
-0962829254 :340
-0917153643 :350
-6789259036 :360
-0011330530 :370
-5488204665 :380
-2138414695 :390
-1941511609 :400
-4330572703 :410
-6575959195 :420
-3092186117 :430
-3819326117 :440
-9310511854 :450
-8074462379 :460
-9627495673 :470
-5188575272 :480
-4891227938 :490
-1830119491 :500
-2983367336 :510
-2440656643 :520
-0860213949 :530
-4639522473 :540
-7190702179 :550
-8609437027 :560
-7053921717 :570
-6293176752 :580
-3846748184 :590
-6766940513 :600
-2000568127 :610
-1452635608 :620
-2778577134 :630
-2757789609 :640
-1736371787 :650
-2146844090 :660
-1224953430 :670
-1465495853 :680
-7105079227 :690
-9689258923 :700
-5420199561 :710
-1212902196 :720
-0864034418 :730
-1598136297 :740
-7477130996 :750
-0518707211 :760
-3499999983 :770
-7297804995 :780
-1059731732 :790
-8160963185 :800
-9502445945 :810
-5346908302 :820
-6425223082 :830
-5334468503 :840
-5261931188 :850
-1710100031 :860
-3783875288 :870
-6587533208 :880
-3814206171 :890
-7766914730 :900
-3598253490 :910
-4287554687 :920
-3115956286 :930
-3882353787 :940
-5937519577 :950
-8185778053 :960
-2171226806 :970
-6130019278 :980
-7661119590 :990
-9216420198 :1000
+++ /dev/null
-(* Pi digits computed with the sreaming algorithm given on pages 4, 6
- & 7 of "Unbounded Spigot Algorithms for the Digits of Pi", Jeremy
- Gibbons, August 2004. *)
-
-open Printf;;
-open Num;;
-
-let zero = num_of_int 0
-and one = num_of_int 1
-and three = num_of_int 3
-and four = num_of_int 4
-and ten = num_of_int 10
-and neg_ten = num_of_int(-10)
-;;
-
-(* Linear Fractional Transformation *)
-module LFT = struct
-
- let floor_ev (q, r, s, t) x = quo_num (q */ x +/ r) (s */ x +/ t);;
-
- let unit = (one, zero, zero, one);;
-
- let comp (q, r, s, t) (q', r', s', t') =
- (q */ q' +/ r */ s', q */ r' +/ r */ t',
- s */ q' +/ t */ s', s */ r' +/ t */ t')
-;;
-
-end
-;;
-
-let next z = LFT.floor_ev z three
-and safe z n = (n =/ LFT.floor_ev z four)
-and prod z n = LFT.comp (ten, neg_ten */ n, zero, one) z
-and cons z k =
- let den = 2 * k + 1 in
- LFT.comp z (num_of_int k, num_of_int(2 * den), zero, num_of_int den)
-;;
-
-let rec digit k z n row col =
- if n > 0 then
- let y = next z in
- if safe z y then
- if col = 10 then (
- let row = row + 10 in
- printf "\t:%i\n%s" row (string_of_num y);
- digit k (prod z y) (n-1) row 1
- )
- else (
- print_string(string_of_num y);
- digit k (prod z y) (n-1) row (col + 1)
- )
- else digit (k + 1) (cons z k) n row col
- else
- printf "%*s\t:%i\n" (10 - col) "" (row + col)
-;;
-
-let digits n = digit 1 LFT.unit n 0 0
-;;
-
-let usage () =
- prerr_endline "Usage: pi_num <number of digits to compute for pi>";
- exit 2
-;;
-
-let main () =
- let args = Sys.argv in
- if Array.length args <> 2 then usage () else
- digits (int_of_string Sys.argv.(1))
-;;
-
-main ()
-;;
+++ /dev/null
-3141592653 :10
-5897932384 :20
-6264338327 :30
-9502884197 :40
-1693993751 :50
-0582097494 :60
-4592307816 :70
-4062862089 :80
-9862803482 :90
-5342117067 :100
-9821480865 :110
-1328230664 :120
-7093844609 :130
-5505822317 :140
-2535940812 :150
-8481117450 :160
-2841027019 :170
-3852110555 :180
-9644622948 :190
-9549303819 :200
-6442881097 :210
-5665933446 :220
-1284756482 :230
-3378678316 :240
-5271201909 :250
-1456485669 :260
-2346034861 :270
-0454326648 :280
-2133936072 :290
-6024914127 :300
-3724587006 :310
-6063155881 :320
-7488152092 :330
-0962829254 :340
-0917153643 :350
-6789259036 :360
-0011330530 :370
-5488204665 :380
-2138414695 :390
-1941511609 :400
-4330572703 :410
-6575959195 :420
-3092186117 :430
-3819326117 :440
-9310511854 :450
-8074462379 :460
-9627495673 :470
-5188575272 :480
-4891227938 :490
-1830119491 :500
-2983367336 :510
-2440656643 :520
-0860213949 :530
-4639522473 :540
-7190702179 :550
-8609437027 :560
-7053921717 :570
-6293176752 :580
-3846748184 :590
-6766940513 :600
-2000568127 :610
-1452635608 :620
-2778577134 :630
-2757789609 :640
-1736371787 :650
-2146844090 :660
-1224953430 :670
-1465495853 :680
-7105079227 :690
-9689258923 :700
-5420199561 :710
-1212902196 :720
-0864034418 :730
-1598136297 :740
-7477130996 :750
-0518707211 :760
-3499999983 :770
-7297804995 :780
-1059731732 :790
-8160963185 :800
-9502445945 :810
-5346908302 :820
-6425223082 :830
-5334468503 :840
-5261931188 :850
-1710100031 :860
-3783875288 :870
-6587533208 :880
-3814206171 :890
-7766914730 :900
-3598253490 :910
-4287554687 :920
-3115956286 :930
-3882353787 :940
-5937519577 :950
-8185778053 :960
-2171226806 :970
-6130019278 :980
-7661119590 :990
-9216420198 :1000
+++ /dev/null
-#**************************************************************************
-#* *
-#* OCaml *
-#* *
-#* Xavier Clerc, SED, 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 GNU Lesser General Public License version 2.1, with the *
-#* special exception on linking described in the file LICENSE. *
-#* *
-#**************************************************************************
-
-BASEDIR=../..
-MODULES=test test_nats test_big_ints test_ratios test_nums test_io
-MAIN_MODULE=end_test
-LIBRARIES=nums
-ADD_COMPFLAGS=-w a -I $(OTOPDIR)/otherlibs/num
-LD_PATH=$(TOPDIR)/otherlibs/num
-
-include $(BASEDIR)/makefiles/Makefile.one
-include $(BASEDIR)/makefiles/Makefile.common
+++ /dev/null
-Test.end_tests ();;
+++ /dev/null
-
-num_digits_nat
- -1... 0... 1...
-length_nat
- 1...
-equal_nat
- 1... 2... 3... 4...
-incr_nat
- 1... 2... 3... 4...
-decr_nat
- 1... 2... 3... 4...
-is_zero_nat
- 1... 2... 3... 4...
-string_of_nat
- 1... 2...
-string_of_nat && nat_of_string
- 1... 2... 3... 4... 5... 6... 7... 8... 9... 10... 11... 12... 13... 14... 15... 16... 17... 18... 19... 20... 21... 22...
-gcd_nat
- 1... 2... 3... 4... 5... 6... 7... 8... 9... 10... 11... 12... 13... 14... 15... 16... 17... 18... 19... 20...
-sqrt_nat
- 1... 2... 3... 4... 5...
-compare_big_int
- 1... 2... 3... 4... 5... 6... 7... 8... 9... 10... 11... 12... 13...
-pred_big_int
- 1... 2... 3...
-succ_big_int
- 1... 2... 3...
-add_big_int
- 1... 2... 3... 4... 5... 6... 7... 8... 9... 10... 11... 12... 13... 14... 15... 16... 17...
-sub_big_int
- 1... 2... 3... 4... 5... 6... 7... 8... 9... 10... 11... 12... 13... 14... 15... 16... 17...
-mult_int_big_int
- 1... 2... 3... 4...
-mult_big_int
- 1... 2... 3... 4... 5...
-quomod_big_int
- 1... 2... 3... 4... 5... 6... 7... 8... 9... 10... 11... 12... 13... 14... 15... 16... 17... 18... 19... 20... 21... 22... 23... 24... 25...
-gcd_big_int
- 1... 2... 3... 4... 5... 6... 7... 8... 9... 10... 11... 12... 13... 14... 15... 16... 17... 18... 19... 20... 21... 22... 23... 24... 25... 26... 27... 28...
-int_of_big_int
- 1... 2... 3... 4... 5... 6... 7... 8...
-is_int_big_int
- 1... 2... 3... 4... 5... 6... 7... 8... 9... 10...
-sys_string_of_big_int
- 1...
-big_int_of_string
- 1... 2... 4... 5... 6... 7... 9... 10... 18... 19... 20... 21...
-power_base_int
- 1... 2... 3...
-base_power_big_int
- 1... 2... 3...
-power_int_positive_big_int
- 1... 2... 3... 4... 5... 6... 7...
-power_big_int_positive_int
- 1... 2... 3... 4... 5...
-power_big_int_positive_big_int
- 1... 2... 3... 4... 5... 6... 7... 8... 9...
-square_big_int
- 1... 2... 3... 4...
-big_int_of_nativeint
- 1... 2... 3...
-nativeint_of_big_int
- 1... 2... 2...
-big_int_of_int32
- 1... 2... 3...
-int32_of_big_int
- 1... 2... 3... 4... 5... 6... 7... 8...
-big_int_of_int64
- 1... 2... 3... 4... 5... 6... 7... 8...
-int64_of_big_int
- 1... 2... 3... 4... 5... 6... 7... 8...
-and_big_int
- 1... 2... 3... 4... 5... 6...
-or_big_int
- 1... 2... 3... 4... 5... 6...
-xor_big_int
- 1... 2... 3... 4... 5... 6...
-shift_left_big_int
- 1... 2... 2... 3... 4... 5... 6...
-shift_right_big_int
- 1... 2... 3... 4... 5... 6...
-shift_right_towards_zero_big_int
- 1... 2...
-extract_big_int
- 1... 2... 3... 4... 5... 6... 7... 8... 9... 10...
-hashing of big integers
- 1... 2... 3... 4... 5... 6...
-float_of_big_int
- 1... 2... 3... 4... 5... 6... 7... 8...
-create_ratio
- 1... 2... 3... 4... 5... 6... 7... 8...
-create_normalized_ratio
- 1... 2... 3... 4... 5... 6... 7... 8... 9... 10...
-null_denominator
- 1... 2...
-sign_ratio
- 1... 2... 3...
-normalize_ratio
- 1... 2... 3... 4...
-report_sign_ratio
- 1... 2...
-is_integer_ratio
- 1... 2...
-add_ratio
- 1... 2... 3... 4... 5... 6... 7... 8... 9... 10... 11... 12... 1... 2... 3... 4...
-sub_ratio
- 1... 2... 3... 4... 5... 6... 7... 8...
-mult_ratio
- 1... 2... 3... 4... 5... 6... 7... 8...
-div_ratio
- 1... 2... 3... 4... 5... 6... 7... 8...
-integer_ratio
- 1... 2... 3... 4... 5...
-floor_ratio
- 1... 2... 3... 4... 5...
-round_ratio
- 1... 2... 3... 4... 5...
-ceiling_ratio
- 1... 2... 3... 4... 5... 6...
-eq_ratio
- 1... 2... 3... 4... 5...
-compare_ratio
- 1... 2... 3... 4... 5... 6... 7... 8... 9... 10... 11... 12... 13... 14... 15... 16... 17... 18... 19... 20... 21... 22... 23... 24... 25... 26... 27... 28... 29... 30... 31... 32... 33... 34... 35... 36...
-eq_big_int_ratio
- 1... 2... 3... 4... 5...
-compare_big_int_ratio
- 1... 2... 3... 4... 5... 6... 7... 8... 9...
-int_of_ratio
- 1... 2... 3... 4... 5...
-ratio_of_int
- 1... 2...
-nat_of_ratio
- 1... 2... 3... 4...
-ratio_of_big_int
- 1...
-big_int_of_ratio
- 1... 2... 3...
-string_of_ratio
- 1... 2... 3... 4...
-ratio_of_string
- 1... 6... 7... 8...
-round_futur_last_digit
- 1... 2... 3... 4... 5... 6... 7... 8... 9... 10... 11... 12... 13... 14... 15... 16... 17... 18... 19... 20... 21... 22... 23... 24...
-approx_ratio_fix
- 1... 2... 3... 4... 5... 6... 7... 8... 9... 10... 11... 12... 13... 14...
-approx_ratio_exp
- 1... 2... 3... 4... 5... 6... 7... 8... 9...
-float_of_ratio
- 1...
-add_num
- 1... 2... 3... 4... 5... 6... 7... 8... 9...
-sub_num
- 1... 2... 3... 4... 5... 7... 8... 9... 10...
-mult_num
- 1... 2... 3... 4... 5... 6... 7... 8... 9...
-div_num
- 1... 2... 3... 4... 5... 6... 7... 8... 9...
-is_integer_num
- 1... 2... 3... 4...
-num_of_ratio
- 1... 2... 3...
-num_of_string
- 1... 7... 8... 11... 12... 13... 14... 15...
-output_value/input_value on nats
- 1... 2... 3... 4... 5... 6... 7...
-output_value/input_value on big ints
- 1... 2... 3... 4... 5...
-output_value/input_value on nums
- 1... 2... 3... 4... 5... 6... 7... 8...
-************* TESTS COMPLETED SUCCESSFULLY ****************
+++ /dev/null
-open Printf;;
-
-let flush_all () = flush stdout; flush stderr;;
-
-let message s = print_string s; print_newline ();;
-
-let error_occurred = ref false;;
-let immediate_failure = ref true;;
-
-let error () =
- if !immediate_failure then exit 2 else begin
- error_occurred := true;
- flush_all ();
- false
- end;;
-
-let success () = flush_all (); true;;
-
-let function_tested = ref "";;
-
-let testing_function s =
- flush_all ();
- function_tested := s;
- print_newline();
- message s;;
-
-let test test_number eq_fun (answer, correct_answer) =
- flush_all ();
- if not (eq_fun answer correct_answer) then begin
- fprintf stderr ">>> Bad result (%s, test %d)\n" !function_tested test_number;
- error ()
- end else begin
- printf " %d..." test_number;
- success ()
- end;;
-
-let failure_test test_number fun_to_test arg =
- flush_all ();
- try
- fun_to_test arg;
- fprintf stderr ">>> Failure expected (%s, test %d)\n"
- !function_tested test_number;
- error ()
- with _ ->
- printf " %d..." test_number;
- success ();;
-
-let failwith_test test_number fun_to_test arg correct_failure =
- flush_all ();
- try
- fun_to_test arg;
- fprintf stderr ">>> Failure expected (%s, test %d)\n"
- !function_tested test_number;
- error ()
- with x ->
- if x = correct_failure then begin
- printf " %d..." test_number;
- success ()
- end else begin
- fprintf stderr ">>> Bad failure (%s, test %d)\n"
- !function_tested test_number;
- error ()
- end;;
-
-let end_tests () =
- flush_all ();
- print_newline ();
- if !error_occurred then begin
- print_endline "************* TESTS FAILED ****************"; exit 2
- end else begin
- print_endline "************* TESTS COMPLETED SUCCESSFULLY ****************";
- exit 0
- end;;
-
-let eq = (==);;
-let eq_int (i: int) (j: int) = (i = j);;
-let eq_string (i: string) (j: string) = (i = j);;
-let eq_bytes (i: bytes) (j: bytes) = (i = j);;
-let eq_nativeint (i: nativeint) (j: nativeint) = (i = j);;
-let eq_int32 (i: int32) (j: int32) = (i = j);;
-let eq_int64 (i: int64) (j: int64) = (i = j);;
-let eq_float (x: float) (y: float) = Pervasives.compare x y = 0;;
-
-let sixtyfour = (1 lsl 31) <> 0;;
-
-let rec gcd_int i1 i2 =
- if i2 = 0 then abs i1 else gcd_int i2 (i1 mod i2);;
-
-let rec num_bits_int_aux n =
- if n = 0 then 0 else succ(num_bits_int_aux (n lsr 1));;
-
-let num_bits_int n = num_bits_int_aux (abs n);;
-
-let sign_int i = if i = 0 then 0 else if i > 0 then 1 else -1;;
-
-let length_of_int = Sys.word_size - 2;;
-
-let monster_int = 1 lsl length_of_int;;
-let biggest_int = monster_int - 1;;
-let least_int = - biggest_int;;
-
-let compare_int n1 n2 =
- if n1 == n2 then 0 else if n1 > n2 then 1 else -1;;
+++ /dev/null
-open Test;;
-open Nat;;
-open Big_int;;
-open List;;
-
-testing_function "compare_big_int";;
-
-test 1
-eq_int (compare_big_int zero_big_int zero_big_int, 0);;
-test 2
-eq_int (compare_big_int zero_big_int (big_int_of_int 1), (-1));;
-test 3
-eq_int (compare_big_int zero_big_int (big_int_of_int (-1)), 1);;
-test 4
-eq_int (compare_big_int (big_int_of_int 1) zero_big_int, 1);;
-test 5
-eq_int (compare_big_int (big_int_of_int (-1)) zero_big_int, (-1));;
-test 6
-eq_int (compare_big_int (big_int_of_int 1) (big_int_of_int 1), 0);;
-test 7
-eq_int (compare_big_int (big_int_of_int (-1)) (big_int_of_int (-1)), 0);;
-test 8
-eq_int (compare_big_int (big_int_of_int 1) (big_int_of_int (-1)), 1);;
-test 9
-eq_int (compare_big_int (big_int_of_int (-1)) (big_int_of_int 1), (-1));;
-test 10
-eq_int (compare_big_int (big_int_of_int 1) (big_int_of_int 2), (-1));;
-test 11
-eq_int (compare_big_int (big_int_of_int 2) (big_int_of_int 1), 1);;
-test 12
-eq_int (compare_big_int (big_int_of_int (-1)) (big_int_of_int (-2)), 1);;
-test 13
-eq_int (compare_big_int (big_int_of_int (-2)) (big_int_of_int (-1)), (-1));;
-
-
-testing_function "pred_big_int";;
-
-test 1
-eq_big_int (pred_big_int zero_big_int, big_int_of_int (-1));;
-test 2
-eq_big_int (pred_big_int unit_big_int, zero_big_int);;
-test 3
-eq_big_int (pred_big_int (big_int_of_int (-1)), big_int_of_int (-2));;
-
-testing_function "succ_big_int";;
-
-test 1
-eq_big_int (succ_big_int zero_big_int, unit_big_int);;
-test 2
-eq_big_int (succ_big_int unit_big_int, big_int_of_int 2);;
-test 3
-eq_big_int (succ_big_int (big_int_of_int (-1)), zero_big_int);;
-
-testing_function "add_big_int";;
-
-test 1
-eq_big_int (add_big_int zero_big_int zero_big_int, zero_big_int);;
-test 2
-eq_big_int (add_big_int zero_big_int (big_int_of_int 1),
- big_int_of_int 1);;
-test 3
-eq_big_int (add_big_int (big_int_of_int 1) zero_big_int,
- big_int_of_int 1);;
-test 4
-eq_big_int (add_big_int zero_big_int (big_int_of_int (-1)),
- big_int_of_int (-1));;
-test 5
-eq_big_int (add_big_int (big_int_of_int (-1)) zero_big_int,
- big_int_of_int (-1));;
-test 6
-eq_big_int (add_big_int (big_int_of_int 1) (big_int_of_int 1),
- big_int_of_int 2);;
-test 7
-eq_big_int (add_big_int (big_int_of_int 1) (big_int_of_int 2),
- big_int_of_int 3);;
-test 8
-eq_big_int (add_big_int (big_int_of_int 2) (big_int_of_int 1),
- big_int_of_int 3);;
-test 9
-eq_big_int (add_big_int (big_int_of_int (-1)) (big_int_of_int (-1)),
- big_int_of_int (-2));;
-test 10
-eq_big_int (add_big_int (big_int_of_int (-1)) (big_int_of_int (-2)),
- big_int_of_int (-3));;
-test 11
-eq_big_int (add_big_int (big_int_of_int (-2)) (big_int_of_int (-1)),
- big_int_of_int (-3));;
-test 12
-eq_big_int (add_big_int (big_int_of_int 1) (big_int_of_int (-1)),
- zero_big_int);;
-test 13
-eq_big_int (add_big_int (big_int_of_int (-1)) (big_int_of_int 1),
- zero_big_int);;
-test 14
-eq_big_int (add_big_int (big_int_of_int 1) (big_int_of_int (-2)),
- big_int_of_int (-1));;
-test 15
-eq_big_int (add_big_int (big_int_of_int (-2)) (big_int_of_int 1),
- big_int_of_int (-1));;
-test 16
-eq_big_int (add_big_int (big_int_of_int (-1)) (big_int_of_int 2),
- big_int_of_int 1);;
-test 17
-eq_big_int (add_big_int (big_int_of_int 2) (big_int_of_int (-1)),
- big_int_of_int 1);;
-
-
-testing_function "sub_big_int";;
-
-test 1
-eq_big_int (sub_big_int zero_big_int zero_big_int, zero_big_int);;
-test 2
-eq_big_int (sub_big_int zero_big_int (big_int_of_int 1),
- big_int_of_int (-1));;
-test 3
-eq_big_int (sub_big_int (big_int_of_int 1) zero_big_int,
- big_int_of_int 1);;
-test 4
-eq_big_int (sub_big_int zero_big_int (big_int_of_int (-1)),
- big_int_of_int 1);;
-test 5
-eq_big_int (sub_big_int (big_int_of_int (-1)) zero_big_int,
- big_int_of_int (-1));;
-test 6
-eq_big_int (sub_big_int (big_int_of_int 1) (big_int_of_int 1),
- zero_big_int);;
-test 7
-eq_big_int (sub_big_int (big_int_of_int 1) (big_int_of_int 2),
- big_int_of_int (-1));;
-test 8
-eq_big_int (sub_big_int (big_int_of_int 2) (big_int_of_int 1),
- big_int_of_int 1);;
-test 9
-eq_big_int (sub_big_int (big_int_of_int (-1)) (big_int_of_int (-1)),
- zero_big_int);;
-test 10
-eq_big_int (sub_big_int (big_int_of_int (-1)) (big_int_of_int (-2)),
- big_int_of_int 1);;
-test 11
-eq_big_int (sub_big_int (big_int_of_int (-2)) (big_int_of_int (-1)),
- big_int_of_int (-1));;
-test 12
-eq_big_int (sub_big_int (big_int_of_int 1) (big_int_of_int (-1)),
- big_int_of_int 2);;
-test 13
-eq_big_int (sub_big_int (big_int_of_int (-1)) (big_int_of_int 1),
- big_int_of_int (-2));;
-test 14
-eq_big_int (sub_big_int (big_int_of_int 1) (big_int_of_int (-2)),
- big_int_of_int 3);;
-test 15
-eq_big_int (sub_big_int (big_int_of_int (-2)) (big_int_of_int 1),
- big_int_of_int (-3));;
-test 16
-eq_big_int (sub_big_int (big_int_of_int (-1)) (big_int_of_int 2),
- big_int_of_int (-3));;
-test 17
-eq_big_int (sub_big_int (big_int_of_int 2) (big_int_of_int (-1)),
- big_int_of_int 3);;
-
-testing_function "mult_int_big_int";;
-
-test 1
-eq_big_int (mult_int_big_int 0 (big_int_of_int 3), zero_big_int);;
-test 2
-eq_big_int (mult_int_big_int 1 (big_int_of_int 3), big_int_of_int 3);;
-test 3
-eq_big_int (mult_int_big_int 1 zero_big_int, zero_big_int);;
-test 4
-eq_big_int (mult_int_big_int 2 (big_int_of_int 3), big_int_of_int 6);;
-
-testing_function "mult_big_int";;
-
-test 1
-eq_big_int (mult_big_int zero_big_int zero_big_int,
- zero_big_int);;
-test 2
-eq_big_int (mult_big_int (big_int_of_int 2) (big_int_of_int 3),
- big_int_of_int 6);;
-test 3
-eq_big_int (mult_big_int (big_int_of_int 2) (big_int_of_int (-3)),
- big_int_of_int (-6));;
-test 4
-eq_big_int (mult_big_int (big_int_of_string "12724951")
- (big_int_of_string "81749606400"),
- big_int_of_string "1040259735709286400");;
-test 5
-eq_big_int (mult_big_int (big_int_of_string "26542080")
- (big_int_of_string "81749606400"),
- big_int_of_string "2169804593037312000");;
-
-testing_function "quomod_big_int";;
-
-let (quotient, modulo) =
- quomod_big_int (big_int_of_int 1) (big_int_of_int 1) in
- test 1 eq_big_int (quotient, big_int_of_int 1) &&
- test 2 eq_big_int (modulo, zero_big_int);;
-
-let (quotient, modulo) =
- quomod_big_int (big_int_of_int 1) (big_int_of_int (-1)) in
- test 3 eq_big_int (quotient, big_int_of_int (-1)) &&
- test 4 eq_big_int (modulo, zero_big_int);;
-
-let (quotient, modulo) =
- quomod_big_int (big_int_of_int (-1)) (big_int_of_int 1) in
- test 5 eq_big_int (quotient, big_int_of_int (-1)) &&
- test 6 eq_big_int (modulo, zero_big_int);;
-
-let (quotient, modulo) =
- quomod_big_int (big_int_of_int 3) (big_int_of_int 2) in
- test 7 eq_big_int (quotient, big_int_of_int 1) &&
- test 8 eq_big_int (modulo, big_int_of_int 1);;
-
-let (quotient, modulo) =
- quomod_big_int (big_int_of_int 5) (big_int_of_int 3) in
- test 9 eq_big_int (quotient, big_int_of_int 1) &&
- test 10 eq_big_int (modulo, big_int_of_int 2);;
-
-let (quotient, modulo) =
- quomod_big_int (big_int_of_int (-5)) (big_int_of_int 3) in
- test 11 eq_big_int (quotient, big_int_of_int (-2)) &&
- test 12 eq_big_int (modulo, big_int_of_int 1);;
-
-let (quotient, modulo) =
- quomod_big_int (big_int_of_int 1) (big_int_of_int 2) in
- test 13 eq_big_int (quotient, zero_big_int) &&
- test 14 eq_big_int (modulo, big_int_of_int 1);;
-
-let (quotient, modulo) =
- quomod_big_int (big_int_of_int (-1)) (big_int_of_int 3) in
- test 15 eq_big_int (quotient, minus_big_int unit_big_int) &&
- test 16 eq_big_int (modulo, big_int_of_int 2);;
-
-failwith_test 17
-(quomod_big_int (big_int_of_int 1)) zero_big_int
-Division_by_zero
-;;
-
-let (quotient, modulo) =
- quomod_big_int (big_int_of_int 10) (big_int_of_int 20) in
- test 18 eq_big_int (quotient, big_int_of_int 0) &&
- test 19 eq_big_int (modulo, big_int_of_int 10);;
-
-let (quotient, modulo) =
- quomod_big_int (big_int_of_int (-10)) (big_int_of_int 20) in
- test 20 eq_big_int (quotient, big_int_of_int (-1)) &&
- test 21 eq_big_int (modulo, big_int_of_int 10);;
-
-let (quotient, modulo) =
- quomod_big_int (big_int_of_int 10) (big_int_of_int (-20)) in
- test 22 eq_big_int (quotient, big_int_of_int 0) &&
- test 23 eq_big_int (modulo, big_int_of_int 10);;
-
-let (quotient, modulo) =
- quomod_big_int (big_int_of_int (-10)) (big_int_of_int (-20)) in
- test 24 eq_big_int (quotient, big_int_of_int 1) &&
- test 25 eq_big_int (modulo, big_int_of_int 10);;
-
-
-testing_function "gcd_big_int";;
-
-test 1
-eq_big_int (gcd_big_int zero_big_int zero_big_int,
- zero_big_int);;
-test 2
-eq_big_int (gcd_big_int zero_big_int (big_int_of_int 1),
- big_int_of_int 1);;
-test 3
-eq_big_int (gcd_big_int (big_int_of_int 1) zero_big_int,
- big_int_of_int 1);;
-test 4
-eq_big_int (gcd_big_int (big_int_of_int 1) (big_int_of_int 2),
- big_int_of_int 1);;
-test 5
-eq_big_int (gcd_big_int (big_int_of_int 2) (big_int_of_int 1),
- big_int_of_int 1);;
-test 6
-eq_big_int (gcd_big_int (big_int_of_int 1) (big_int_of_int 1),
- big_int_of_int 1);;
-test 7
-eq_big_int (gcd_big_int (big_int_of_int 9) (big_int_of_int 16),
- big_int_of_int 1);;
-test 8
-eq_big_int (gcd_big_int (big_int_of_int 12) (big_int_of_int 16),
- big_int_of_int 4);;
-
-for i = 9 to 28 do
- let n1 = Random.int 1000000000
- and n2 = Random.int 100000 in
- let _ =
- test i eq
- (int_of_big_int (gcd_big_int (big_int_of_int n1) (big_int_of_int n2)),
- gcd_int n1 n2) in
- ()
-done;;
-
-testing_function "int_of_big_int";;
-
-test 1
-eq_int (int_of_big_int (big_int_of_int 1), 1);;
-test 2
-eq_int (int_of_big_int (big_int_of_int(-1)), -1);;
-test 3
-eq_int (int_of_big_int zero_big_int, 0);;
-test 4
-eq_int (int_of_big_int (big_int_of_int max_int), max_int);;
-test 5
-eq_int (int_of_big_int (big_int_of_int min_int), min_int);;
-failwith_test 6
- (fun () -> int_of_big_int (succ_big_int (big_int_of_int max_int)))
- () (Failure "int_of_big_int");;
-failwith_test 7
- (fun () -> int_of_big_int (pred_big_int (big_int_of_int min_int)))
- () (Failure "int_of_big_int");;
-failwith_test 8
- (fun () -> int_of_big_int (mult_big_int (big_int_of_int min_int)
- (big_int_of_int 2)))
- () (Failure "int_of_big_int");;
-
-
-testing_function "is_int_big_int";;
-
-test 1
-eq (is_int_big_int (big_int_of_int 1), true);;
-test 2
-eq (is_int_big_int (big_int_of_int (-1)), true);;
-test 3
-eq (is_int_big_int (succ_big_int (big_int_of_int biggest_int)), false);;
-test 4
-eq (int_of_big_int (big_int_of_int monster_int), monster_int);;
-(* Should be true *)
-test 5
-eq (is_int_big_int (big_int_of_string (string_of_int biggest_int)), true);;
-test 6
-eq (is_int_big_int (big_int_of_string (string_of_int least_int)), true);;
-test 7
-eq (is_int_big_int (big_int_of_string (string_of_int monster_int)), true);;
-
-(* Should be false *)
-(* Successor of biggest_int is not an int *)
-test 8
-eq (is_int_big_int (succ_big_int (big_int_of_int (biggest_int))), false);;
-test 9
-eq (is_int_big_int
- (succ_big_int (succ_big_int (big_int_of_int (biggest_int)))), false);;
-(* Negation of monster_int (as a big_int) is not an int *)
-test 10
-eq (is_int_big_int
- (minus_big_int (big_int_of_string (string_of_int monster_int))), false);;
-
-
-testing_function "sys_string_of_big_int";;
-
-test 1
-eq_string (string_of_big_int (big_int_of_int 1), "1");;
-
-
-testing_function "big_int_of_string";;
-
-test 1
-eq_big_int (big_int_of_string "1", big_int_of_int 1);;
-test 2
-eq_big_int (big_int_of_string "-1", big_int_of_int (-1));;
-test 4
-eq_big_int (big_int_of_string "0", zero_big_int);;
-
-failwith_test 5 big_int_of_string "sdjdkfighdgf"
- (Failure "invalid digit");;
-
-test 6
-eq_big_int (big_int_of_string "123", big_int_of_int 123);;
-test 7
-eq_big_int (big_int_of_string "+3456", big_int_of_int 3456);;
-
-test 9
-eq_big_int (big_int_of_string "-3456", big_int_of_int (-3456));;
-
-
-let implode = List.fold_left (^) "";; (* To hell with efficiency *)
-
-let l = rev [
-"174679877494298468451661416292903906557638850173895426081611831060970135303";
-"044177587617233125776581034213405720474892937404345377707655788096850784519";
-"539374048533324740018513057210881137248587265169064879918339714405948322501";
-"445922724181830422326068913963858377101914542266807281471620827145038901025";
-"322784396182858865537924078131032036927586614781817695777639491934361211399";
-"888524140253852859555118862284235219972858420374290985423899099648066366558";
-"238523612660414395240146528009203942793935957539186742012316630755300111472";
-"852707974927265572257203394961525316215198438466177260614187266288417996647";
-"132974072337956513457924431633191471716899014677585762010115338540738783163";
-"739223806648361958204720897858193606022290696766988489073354139289154127309";
-"916985231051926209439373780384293513938376175026016587144157313996556653811";
-"793187841050456120649717382553450099049321059330947779485538381272648295449";
-"847188233356805715432460040567660999184007627415398722991790542115164516290";
-"619821378529926683447345857832940144982437162642295073360087284113248737998";
-"046564369129742074737760485635495880623324782103052289938185453627547195245";
-"688272436219215066430533447287305048225780425168823659431607654712261368560";
-"702129351210471250717394128044019490336608558608922841794819375031757643448";
-"32"
-] in
-
-let bi1 = big_int_of_string (implode (rev l)) in
-
-let bi2 = big_int_of_string (implode (rev ("3" :: tl l))) in
-
-test 10
-eq_big_int (bi1, (add_big_int (mult_big_int bi2 (big_int_of_string "10"))
- (big_int_of_string "2")))
-(* test 11
- &&
-eq_big_int (bi1, (add_big_int (mult_big_int bi2 (big_int_of_string "10e0"))
- (big_int_of_string "20e-1"))) &&
-test 12
-eq_big_int (minus_big_int bi1,
- (add_big_int (mult_big_int bi2 (big_int_of_string "-10e0"))
- (big_int_of_string "-20e-1"))) &&
-test 13
-eq_big_int (bi1, (add_big_int (mult_big_int bi2 (big_int_of_string "+10e0"))
- (big_int_of_string "+20e-1"))) &&
-test 14
-eq_big_int (minus_big_int bi1,
- (add_big_int (mult_big_int bi2 (big_int_of_string "-10e+0"))
- (big_int_of_string "-20e-1"))) &&
-test 15
-eq_big_int (minus_big_int bi1,
- (add_big_int (mult_big_int bi2 (big_int_of_string "-1e+1"))
- (big_int_of_string "-2e-0"))) &&
-test 16
-eq_big_int (minus_big_int bi1,
- (add_big_int (mult_big_int bi2 (big_int_of_string "-0.1e+2"))
- (big_int_of_string "-2.0e-0"))) &&
-test 17
-eq_big_int (minus_big_int bi1,
- (add_big_int (mult_big_int bi2 (big_int_of_string "-1.000e+1"))
- (big_int_of_string "-0.02e2")))*)
-;;
-
-test 18
-eq_big_int (big_int_of_string "0xAbC", big_int_of_int 0xABC);;
-
-test 19
-eq_big_int (big_int_of_string "-0o452", big_int_of_int (-0o452));;
-
-test 20
-eq_big_int (big_int_of_string "0B110101", big_int_of_int 53);;
-
-test 21
-eq_big_int (big_int_of_string "0b11_01_01", big_int_of_int 53);;
-
-testing_function "power_base_int";;
-
-test 1
-eq_big_int (big_int_of_nat (power_base_int 10 0), unit_big_int)
-;;
-test 2
-eq_big_int (big_int_of_nat (power_base_int 10 8), big_int_of_int 100000000)
-;;
-test 3
-eq_big_int (big_int_of_nat (power_base_int 2 (length_of_int + 2)),
- big_int_of_nat (let nat = make_nat 2 in
- set_digit_nat nat 1 1;
- nat))
-;;
-
-testing_function "base_power_big_int";;
-
-test 1
-eq_big_int (base_power_big_int 10 0 (big_int_of_int 2), big_int_of_int 2);;
-test 2
-eq_big_int (base_power_big_int 10 2 (big_int_of_int 2), big_int_of_int 200);;
-test 3
-eq_big_int (base_power_big_int 10 1 (big_int_of_int 123), big_int_of_int 1230)
-;;
-
-testing_function "power_int_positive_big_int";;
-
-test 1
-eq_big_int (power_int_positive_big_int 2 (big_int_of_int 10),
- big_int_of_int 1024);;
-test 2
-eq_big_int
- (power_int_positive_big_int 2 (big_int_of_int 65),
- big_int_of_string "36893488147419103232");;
-
-test 3
-eq_big_int
- (power_int_positive_big_int 3 (big_int_of_string "47"),
- big_int_of_string "26588814358957503287787");;
-
-test 4
-eq_big_int
- (power_int_positive_big_int 1 (big_int_of_string "1000000000000000000000"),
- big_int_of_int 1);;
-
-test 5
-eq_big_int
- (power_int_positive_big_int (-1) (big_int_of_string "1000000000000000000000"),
- big_int_of_int 1);;
-
-test 6
-eq_big_int
- (power_int_positive_big_int (-1) (big_int_of_string "1000000000000000000001"),
- big_int_of_int (-1));;
-
-test 7
-eq_big_int
- (power_int_positive_big_int 0 (big_int_of_string "1000000000000000000000"),
- big_int_of_int 0);;
-
-testing_function "power_big_int_positive_int";;
-
-test 1
-eq_big_int (power_big_int_positive_int (big_int_of_int 2) 10,
- big_int_of_int 1024);;
-test 2
-eq_big_int
- (power_big_int_positive_int (big_int_of_int 100) 20,
- big_int_of_string "10000000000000000000000000000000000000000");;
-
-test 3
-eq_big_int
- (power_big_int_positive_int (big_int_of_string "3") 47,
- big_int_of_string "26588814358957503287787");;
-
-test 4
-eq_big_int
- (power_big_int_positive_int (big_int_of_string "200000000000000") 34,
- big_int_of_string
-"17179869184000000000000000000000000000000000000000000000000000000000\
-00000000000000000000000000000000000000000000000000000000000000000000\
-00000000000000000000000000000000000000000000000000000000000000000000\
-00000000000000000000000000000000000000000000000000000000000000000000\
-00000000000000000000000000000000000000000000000000000000000000000000\
-00000000000000000000000000000000000000000000000000000000000000000000\
-00000000000000000000000000000000000000000000000000000000000000000000\
-00000000000");;
-
-test 5
-eq_big_int
- (power_big_int_positive_int (big_int_of_string "2197609328765") 243,
- big_int_of_string
-"12415638672345366257764851943822299490113545698929764576040102857365\
-27920436565335427676982530274588056944387957287793378051852205028658\
-73008292720317554332284838709453634119919368441951233982592586680844\
-20765201140575612595182857026804842796931784944918059630667794516774\
-58498235838834599150657873894983300999081942159304585449505963892008\
-97855706440206825609657816209327492197604711437269361628626691080334\
-38432768885637928268354258860147333786379766583179851226375449161073\
-10396958979998161989562418169797611757651190037273397850239552735199\
-63719988832594486235837899145390948533078339399890545062510060406048\
-61331200657727576638170520036143007285549092686618686739320973444703\
-33342725604091818763255601206325426337211467746377586080108631634250\
-11232258578207762608797108802386708549785680783113606089879687396654\
-54004281165259352412815385041917713969718327109245777066079665194617\
-29230093411050053217775067781725651590160086483960457766025246936489\
-92234225900994076609973190516835778346886551506344097474301175288686\
-25662752919718480402972207084177612056491949911377568680526080633587\
-33230060757162252611388973328501680433819585006035301408574879645573\
-47126018243568976860515247053858204554293343161581801846081341003624\
-22906934772131205632200433218165757307182816260714026614324014553342\
-77303133877636489457498062819003614421295692889321460150481573909330\
-77301946991278225819671075907191359721824291923283322225480199446258\
-03302645587072103949599624444368321734975586414930425964782010567575\
-43333331963876294983400462908871215572514487548352925949663431718284\
-14589547315559936497408670231851521193150991888789948397029796279240\
-53117024758684807981605608837291399377902947471927467827290844733264\
-70881963357258978768427852958888430774360783419404195056122644913454\
-24537375432013012467418602205343636983874410969339344956536142566292\
-67710105053213729008973121773436382170956191942409859915563249876601\
-97309463059908818473774872128141896864070835259683384180928526600888\
-17480854811931632353621014638284918544379784608050029606475137979896\
-79160729736625134310450643341951675749112836007180865039256361941093\
-99844921135320096085772541537129637055451495234892640418746420370197\
-76655592198723057553855194566534999101921182723711243608938705766658\
-35660299983828999383637476407321955462859142012030390036241831962713\
-40429407146441598507165243069127531565881439971034178400174881243483\
-00001434950666035560134867554719667076133414445044258086968145695386\
-00575860256380332451841441394317283433596457253185221717167880159573\
-60478649571700878049257386910142909926740023800166057094445463624601\
-79490246367497489548435683835329410376623483996271147060314994344869\
-89606855219181727424853876740423210027967733989284801813769926906846\
-45570461348452758744643550541290031199432061998646306091218518879810\
-17848488755494879341886158379140088252013009193050706458824793551984\
-39285914868159111542391208521561221610797141925061986437418522494485\
-59871215531081904861310222368465288125816137210222223075106739997863\
-76953125");;
-
-testing_function "power_big_int_positive_big_int";;
-
-test 1
-eq_big_int
- (power_big_int_positive_big_int (big_int_of_int 2) (big_int_of_int 10),
- big_int_of_int 1024);;
-
-test 2
-eq_big_int
- (power_big_int_positive_big_int (big_int_of_int 2) (big_int_of_int 65),
- big_int_of_string "36893488147419103232");;
-
-test 3
-eq_big_int
- (power_big_int_positive_big_int
- (big_int_of_string "3") (big_int_of_string "47"),
- big_int_of_string "26588814358957503287787");;
-
-test 4
-eq_big_int
- (power_big_int_positive_big_int
- (big_int_of_string "200000000000000") (big_int_of_int 34),
- big_int_of_string
-"17179869184000000000000000000000000000000000000000000000000000000000\
-00000000000000000000000000000000000000000000000000000000000000000000\
-00000000000000000000000000000000000000000000000000000000000000000000\
-00000000000000000000000000000000000000000000000000000000000000000000\
-00000000000000000000000000000000000000000000000000000000000000000000\
-00000000000000000000000000000000000000000000000000000000000000000000\
-00000000000000000000000000000000000000000000000000000000000000000000\
-00000000000");;
-
-test 5
-eq_big_int
- (power_big_int_positive_big_int (big_int_of_string "2197609328765")
- (big_int_of_string "243"),
- big_int_of_string
-"12415638672345366257764851943822299490113545698929764576040102857365\
-27920436565335427676982530274588056944387957287793378051852205028658\
-73008292720317554332284838709453634119919368441951233982592586680844\
-20765201140575612595182857026804842796931784944918059630667794516774\
-58498235838834599150657873894983300999081942159304585449505963892008\
-97855706440206825609657816209327492197604711437269361628626691080334\
-38432768885637928268354258860147333786379766583179851226375449161073\
-10396958979998161989562418169797611757651190037273397850239552735199\
-63719988832594486235837899145390948533078339399890545062510060406048\
-61331200657727576638170520036143007285549092686618686739320973444703\
-33342725604091818763255601206325426337211467746377586080108631634250\
-11232258578207762608797108802386708549785680783113606089879687396654\
-54004281165259352412815385041917713969718327109245777066079665194617\
-29230093411050053217775067781725651590160086483960457766025246936489\
-92234225900994076609973190516835778346886551506344097474301175288686\
-25662752919718480402972207084177612056491949911377568680526080633587\
-33230060757162252611388973328501680433819585006035301408574879645573\
-47126018243568976860515247053858204554293343161581801846081341003624\
-22906934772131205632200433218165757307182816260714026614324014553342\
-77303133877636489457498062819003614421295692889321460150481573909330\
-77301946991278225819671075907191359721824291923283322225480199446258\
-03302645587072103949599624444368321734975586414930425964782010567575\
-43333331963876294983400462908871215572514487548352925949663431718284\
-14589547315559936497408670231851521193150991888789948397029796279240\
-53117024758684807981605608837291399377902947471927467827290844733264\
-70881963357258978768427852958888430774360783419404195056122644913454\
-24537375432013012467418602205343636983874410969339344956536142566292\
-67710105053213729008973121773436382170956191942409859915563249876601\
-97309463059908818473774872128141896864070835259683384180928526600888\
-17480854811931632353621014638284918544379784608050029606475137979896\
-79160729736625134310450643341951675749112836007180865039256361941093\
-99844921135320096085772541537129637055451495234892640418746420370197\
-76655592198723057553855194566534999101921182723711243608938705766658\
-35660299983828999383637476407321955462859142012030390036241831962713\
-40429407146441598507165243069127531565881439971034178400174881243483\
-00001434950666035560134867554719667076133414445044258086968145695386\
-00575860256380332451841441394317283433596457253185221717167880159573\
-60478649571700878049257386910142909926740023800166057094445463624601\
-79490246367497489548435683835329410376623483996271147060314994344869\
-89606855219181727424853876740423210027967733989284801813769926906846\
-45570461348452758744643550541290031199432061998646306091218518879810\
-17848488755494879341886158379140088252013009193050706458824793551984\
-39285914868159111542391208521561221610797141925061986437418522494485\
-59871215531081904861310222368465288125816137210222223075106739997863\
-76953125");;
-
-test 6
-eq_big_int
- (power_big_int_positive_big_int (big_int_of_int 1)
- (big_int_of_string "1000000000000000000000"),
- big_int_of_int 1);;
-
-test 7
-eq_big_int
- (power_big_int_positive_big_int (big_int_of_int (-1))
- (big_int_of_string "1000000000000000000000"),
- big_int_of_int 1);;
-
-test 8
-eq_big_int
- (power_big_int_positive_big_int (big_int_of_int (-1))
- (big_int_of_string "1000000000000000000001"),
- big_int_of_int (-1));;
-
-test 9
-eq_big_int
- (power_big_int_positive_big_int (big_int_of_int 0)
- (big_int_of_string "1000000000000000000000"),
- big_int_of_int 0);;
-
-testing_function "square_big_int";;
-
-test 1 eq_big_int
- (square_big_int (big_int_of_string "0"), big_int_of_string "0");;
-test 2 eq_big_int
- (square_big_int (big_int_of_string "1"), big_int_of_string "1");;
-test 3 eq_big_int
- (square_big_int (big_int_of_string "-1"), big_int_of_string "1");;
-test 4 eq_big_int
- (square_big_int (big_int_of_string "-7"), big_int_of_string "49");;
-
-
-testing_function "big_int_of_nativeint";;
-
-test 1 eq_big_int
- (big_int_of_nativeint 0n, zero_big_int);;
-test 2 eq_big_int
- (big_int_of_nativeint 1234n, big_int_of_string "1234");;
-test 3 eq_big_int
- (big_int_of_nativeint (-1234n), big_int_of_string "-1234");;
-
-testing_function "nativeint_of_big_int";;
-
-test 1 eq_nativeint
- (nativeint_of_big_int zero_big_int, 0n);;
-test 2 eq_nativeint
- (nativeint_of_big_int (big_int_of_string "1234"), 1234n);;
-test 2 eq_nativeint
- (nativeint_of_big_int (big_int_of_string "-1234"), -1234n);;
-
-testing_function "big_int_of_int32";;
-
-test 1 eq_big_int
- (big_int_of_int32 0l, zero_big_int);;
-test 2 eq_big_int
- (big_int_of_int32 2147483647l, big_int_of_string "2147483647");;
-test 3 eq_big_int
- (big_int_of_int32 (-2147483648l), big_int_of_string "-2147483648");;
-
-testing_function "int32_of_big_int";;
-
-test 1 eq_int32
- (int32_of_big_int zero_big_int, 0l);;
-test 2 eq_int32
- (int32_of_big_int (big_int_of_string "2147483647"), 2147483647l);;
-test 3 eq_int32
- (int32_of_big_int (big_int_of_string "-2147483648"), -2147483648l);;
-test 4 eq_int32
- (int32_of_big_int (big_int_of_string "-2147"), -2147l);;
-let should_fail s =
- try ignore (int32_of_big_int (big_int_of_string s)); 0
- with Failure _ -> 1;;
-test 5 eq_int
- (should_fail "2147483648", 1);;
-test 6 eq_int
- (should_fail "-2147483649", 1);;
-test 7 eq_int
- (should_fail "4294967296", 1);;
-test 8 eq_int
- (should_fail "18446744073709551616", 1);;
-
-testing_function "big_int_of_int64";;
-
-test 1 eq_big_int
- (big_int_of_int64 0L, zero_big_int);;
-test 2 eq_big_int
- (big_int_of_int64 9223372036854775807L,
- big_int_of_string "9223372036854775807");;
-test 3 eq_big_int
- (big_int_of_int64 (-9223372036854775808L),
- big_int_of_string "-9223372036854775808");;
-test 4 eq_big_int (*PR#4792*)
- (big_int_of_int64 (Int64.of_int32 Int32.min_int),
- big_int_of_string "-2147483648");;
-test 5 eq_big_int
- (big_int_of_int64 1234L, big_int_of_string "1234");;
-test 6 eq_big_int
- (big_int_of_int64 0x1234567890ABCDEFL,
- big_int_of_string "1311768467294899695");;
-test 7 eq_big_int
- (big_int_of_int64 (-1234L), big_int_of_string "-1234");;
-test 8 eq_big_int
- (big_int_of_int64 (-0x1234567890ABCDEFL),
- big_int_of_string "-1311768467294899695");;
-
-testing_function "int64_of_big_int";;
-
-test 1 eq_int64
- (int64_of_big_int zero_big_int, 0L);;
-test 2 eq_int64
- (int64_of_big_int (big_int_of_string "9223372036854775807"),
- 9223372036854775807L);;
-test 3 eq_int64
- (int64_of_big_int (big_int_of_string "-9223372036854775808"),
- -9223372036854775808L);;
-test 4 eq_int64
- (int64_of_big_int (big_int_of_string "-9223372036854775"),
- -9223372036854775L);;
-test 5 eq_int64 (* PR#4804 *)
- (int64_of_big_int (big_int_of_string "2147483648"), 2147483648L);;
-let should_fail s =
- try ignore (int64_of_big_int (big_int_of_string s)); 0
- with Failure _ -> 1;;
-test 6 eq_int
- (should_fail "9223372036854775808", 1);;
-test 7 eq_int
- (should_fail "-9223372036854775809", 1);;
-test 8 eq_int
- (should_fail "18446744073709551616", 1);;
-
-(* build a 128-bit big int from two int64 *)
-
-let big_int_128 hi lo =
- add_big_int (mult_big_int (big_int_of_int64 hi)
- (big_int_of_string "18446744073709551616"))
- (big_int_of_int64 lo);;
-let h1 = 0x7fd05b7ee46a29f8L
-and h2 = 0x64b28b8ee70b6e6dL
-and h3 = 0x58546e563f5b44f0L
-and h4 = 0x1db72f6377ff3ec6L
-and h5 = 0x4f9bb0a19c543cb1L;;
-
-testing_function "and_big_int";;
-
-test 1 eq_big_int
- (and_big_int unit_big_int zero_big_int, zero_big_int);;
-test 2 eq_big_int
- (and_big_int zero_big_int unit_big_int, zero_big_int);;
-test 3 eq_big_int
- (and_big_int unit_big_int unit_big_int, unit_big_int);;
-test 4 eq_big_int
- (and_big_int (big_int_128 h1 h2) (big_int_128 h3 h4),
- big_int_128 (Int64.logand h1 h3) (Int64.logand h2 h4));;
-test 5 eq_big_int
- (and_big_int (big_int_128 h1 h2) (big_int_of_int64 h5),
- big_int_of_int64 (Int64.logand h2 h5));;
-test 6 eq_big_int
- (and_big_int (big_int_of_int64 h5) (big_int_128 h3 h4) ,
- big_int_of_int64 (Int64.logand h5 h4));;
-
-testing_function "or_big_int";;
-
-test 1 eq_big_int
- (or_big_int unit_big_int zero_big_int, unit_big_int);;
-test 2 eq_big_int
- (or_big_int zero_big_int unit_big_int, unit_big_int);;
-test 3 eq_big_int
- (or_big_int unit_big_int unit_big_int, unit_big_int);;
-test 4 eq_big_int
- (or_big_int (big_int_128 h1 h2) (big_int_128 h3 h4),
- big_int_128 (Int64.logor h1 h3) (Int64.logor h2 h4));;
-test 5 eq_big_int
- (or_big_int (big_int_128 h1 h2) (big_int_of_int64 h5),
- big_int_128 h1 (Int64.logor h2 h5));;
-test 6 eq_big_int
- (or_big_int (big_int_of_int64 h5) (big_int_128 h3 h4) ,
- big_int_128 h3 (Int64.logor h5 h4));;
-
-testing_function "xor_big_int";;
-
-test 1 eq_big_int
- (xor_big_int unit_big_int zero_big_int, unit_big_int);;
-test 2 eq_big_int
- (xor_big_int zero_big_int unit_big_int, unit_big_int);;
-test 3 eq_big_int
- (xor_big_int unit_big_int unit_big_int, zero_big_int);;
-test 4 eq_big_int
- (xor_big_int (big_int_128 h1 h2) (big_int_128 h3 h4),
- big_int_128 (Int64.logxor h1 h3) (Int64.logxor h2 h4));;
-test 5 eq_big_int
- (xor_big_int (big_int_128 h1 h2) (big_int_of_int64 h5),
- big_int_128 h1 (Int64.logxor h2 h5));;
-test 6 eq_big_int
- (xor_big_int (big_int_of_int64 h5) (big_int_128 h3 h4) ,
- big_int_128 h3 (Int64.logxor h5 h4));;
-
-testing_function "shift_left_big_int";;
-
-test 1 eq_big_int
- (shift_left_big_int unit_big_int 0,
- unit_big_int);;
-test 2 eq_big_int
- (shift_left_big_int unit_big_int 1,
- big_int_of_int 2);;
-test 2 eq_big_int
- (shift_left_big_int unit_big_int 31,
- big_int_of_string "2147483648");;
-test 3 eq_big_int
- (shift_left_big_int unit_big_int 64,
- big_int_of_string "18446744073709551616");;
-test 4 eq_big_int
- (shift_left_big_int unit_big_int 95,
- big_int_of_string "39614081257132168796771975168");;
-test 5 eq_big_int
- (shift_left_big_int (big_int_of_string "39614081257132168796771975168") 67,
- big_int_of_string "5846006549323611672814739330865132078623730171904");;
-test 6 eq_big_int
- (shift_left_big_int (big_int_of_string "-39614081257132168796771975168") 67,
- big_int_of_string "-5846006549323611672814739330865132078623730171904");;
-
-testing_function "shift_right_big_int";;
-
-test 1 eq_big_int
- (shift_right_big_int unit_big_int 0,
- unit_big_int);;
-test 2 eq_big_int
- (shift_right_big_int (big_int_of_int 12345678) 3,
- big_int_of_int 1543209);;
-test 3 eq_big_int
- (shift_right_big_int (big_int_of_string "5299989648942") 32,
- big_int_of_int 1234);;
-test 4 eq_big_int
- (shift_right_big_int (big_int_of_string
- "5846006549323611672814739330865132078623730171904")
- 67,
- big_int_of_string "39614081257132168796771975168");;
-test 5 eq_big_int
- (shift_right_big_int (big_int_of_string "-5299989648942") 32,
- big_int_of_int (-1235));;
-test 6 eq_big_int
- (shift_right_big_int (big_int_of_string "-16570089876543209725755392") 27,
- big_int_of_string "-123456790123456789");;
-
-testing_function "shift_right_towards_zero_big_int";;
-
-test 1 eq_big_int
- (shift_right_towards_zero_big_int (big_int_of_string "-5299989648942") 32,
- big_int_of_int (-1234));;
-test 2 eq_big_int
- (shift_right_towards_zero_big_int (big_int_of_string
- "-16570089876543209725755392")
- 27,
- big_int_of_string "-123456790123456789");;
-
-testing_function "extract_big_int";;
-
-test 1 eq_big_int
- (extract_big_int (big_int_of_int64 0x123456789ABCDEFL) 3 13,
- big_int_of_int 6589);;
-test 2 eq_big_int
- (extract_big_int (big_int_128 h1 h2) 67 12,
- big_int_of_int 1343);;
-test 3 eq_big_int
- (extract_big_int (big_int_of_string "-1844674407370955178") 37 9,
- big_int_of_int 307);;
-test 4 eq_big_int
- (extract_big_int unit_big_int 2048 254,
- zero_big_int);;
-test 5 eq_big_int
- (extract_big_int (big_int_of_int64 0x123456789ABCDEFL) 0 32,
- big_int_of_int64 2309737967L);;
-test 6 eq_big_int
- (extract_big_int (big_int_of_int (-1)) 0 16,
- big_int_of_int 0xFFFF);;
-test 7 eq_big_int
- (extract_big_int (big_int_of_int (-1)) 1027 12,
- big_int_of_int 0xFFF);;
-test 8 eq_big_int
- (extract_big_int (big_int_of_int (-1234567)) 0 16,
- big_int_of_int 10617);;
-test 9 eq_big_int
- (extract_big_int (minus_big_int (power_int_positive_int 2 64)) 64 20,
- big_int_of_int 0xFFFFF);;
-test 10 eq_big_int
- (extract_big_int (pred_big_int (minus_big_int (power_int_positive_int 2 64)))
- 64 20,
- big_int_of_int 0xFFFFE);;
-
-testing_function "hashing of big integers";;
-
-test 1 eq_int (Hashtbl.hash zero_big_int,
- 955772237);;
-test 2 eq_int (Hashtbl.hash unit_big_int,
- 992063522);;
-test 3 eq_int (Hashtbl.hash (minus_big_int unit_big_int),
- 161678167);;
-test 4 eq_int (Hashtbl.hash (big_int_of_string "123456789123456789"),
- 755417385);;
-test 5 eq_int (Hashtbl.hash (sub_big_int
- (big_int_of_string "123456789123456789")
- (big_int_of_string "123456789123456789")),
- 955772237);;
-test 6 eq_int (Hashtbl.hash (sub_big_int
- (big_int_of_string "123456789123456789")
- (big_int_of_string "123456789123456788")),
- 992063522);;
-
-testing_function "float_of_big_int";;
-
-test 1 eq_float (float_of_big_int zero_big_int, 0.0);;
-test 2 eq_float (float_of_big_int unit_big_int, 1.0);;
-test 3 eq_float (float_of_big_int (minus_big_int unit_big_int), -1.0);;
-test 4 eq_float (float_of_big_int (shift_left_big_int unit_big_int 1024),
- infinity);;
-test 5 eq_float (float_of_big_int (shift_left_big_int unit_big_int 1023),
- ldexp 1.0 1023);;
-(* Some random int64 values *)
-let ok = ref true in
-for i = 1 to 100 do
- let n = Random.int64 Int64.max_int in
- if not (eq_float (float_of_big_int (big_int_of_int64 n)) (Int64.to_float n))
- then ok := false;
- let n = Int64.neg n in
- if not (eq_float (float_of_big_int (big_int_of_int64 n)) (Int64.to_float n))
- then ok := false
-done;
-test 6 eq (!ok, true);;
-(* Some random int64 values scaled by some random power of 2 *)
-let ok = ref true in
-for i = 1 to 1000 do
- let n = Random.int64 Int64.max_int in
- let exp = Random.int 1200 in
- if not (eq_float
- (float_of_big_int
- (shift_left_big_int (big_int_of_int64 n) exp))
- (ldexp (Int64.to_float n) exp))
- then ok := false;
- let n = Int64.neg n in
- if not (eq_float
- (float_of_big_int
- (shift_left_big_int (big_int_of_int64 n) exp))
- (ldexp (Int64.to_float n) exp))
- then ok := false
-done;
-test 7 eq (!ok, true);;
-(* Round to nearest even *)
-let ok = ref true in
-for i = 0 to 15 do
- let n = Int64.(add 0xfffffffffffff0L (of_int i)) in
- if not (eq_float
- (float_of_big_int
- (shift_left_big_int (big_int_of_int64 n) 32))
- (ldexp (Int64.to_float n) 32))
- then ok := false
-done;
-test 8 eq (!ok, true);;
+++ /dev/null
-open Test
-open Nat
-open Big_int
-open Num
-
-let intern_extern obj =
- let f = Filename.temp_file "testnum" ".data" in
- let oc = open_out_bin f in
- output_value oc obj;
- close_out oc;
- let ic = open_in_bin f in
- let res = input_value ic in
- close_in ic;
- Sys.remove f;
- res
-;;
-
-testing_function "output_value/input_value on nats";;
-
-let equal_nat n1 n2 =
- eq_nat n1 0 (length_nat n1) n2 0 (length_nat n2)
-;;
-
-List.iter
- (fun (i, s) ->
- let n = nat_of_string s in
- ignore(test i equal_nat (n, intern_extern n)))
- [1, "0";
- 2, "1234";
- 3, "8589934592";
- 4, "340282366920938463463374607431768211455";
- 5, String.make 100 '3';
- 6, String.make 1000 '9';
- 7, String.make 20000 '8']
-;;
-
-testing_function "output_value/input_value on big ints";;
-
-List.iter
- (fun (i, s) ->
- let b = big_int_of_string s in
- ignore(test i eq_big_int (b, intern_extern b)))
- [1, "0";
- 2, "1234";
- 3, "-1234";
- 4, "1040259735709286400";
- 5, "-" ^ String.make 20000 '7']
-;;
-
-testing_function "output_value/input_value on nums";;
-
-List.iter
- (fun (i, s) ->
- let n = num_of_string s in
- ignore(test i eq_num (n, intern_extern n)))
- [1, "0";
- 2, "1234";
- 3, "-1234";
- 4, "159873568791325097646845892426782";
- 5, "1/4";
- 6, "-15/2";
- 7, "159873568791325097646845892426782/24098772507410987265987";
- 8, String.make 10000 '3' ^ "/" ^ String.make 5000 '7']
-;;
+++ /dev/null
-open Test;;
-open Nat;;
-
-(* Can compare nats less than 2**32 *)
-let equal_nat n1 n2 =
- eq_nat n1 0 (num_digits_nat n1 0 1)
- n2 0 (num_digits_nat n2 0 1);;
-
-testing_function "num_digits_nat";;
-
-test (-1) eq (false,not true);;
-test 0 eq (true,not false);;
-
-test 1
-eq_int
-(let r = make_nat 2 in
- set_digit_nat r 1 1;
- num_digits_nat r 0 1,1);;
-
-testing_function "length_nat";;
-
-test 1
-eq_int
-(let r = make_nat 2 in
- set_digit_nat r 0 1;
- length_nat r,2);;
-
-testing_function "equal_nat";;
-
-let zero_nat = make_nat 1 in
-
-test 1
-equal_nat (zero_nat,zero_nat);;
-test 2
-equal_nat (nat_of_int 1,nat_of_int 1);;
-
-test 3
-equal_nat (nat_of_string "2",nat_of_string "2");;
-test 4
-eq (equal_nat (nat_of_string "2")(nat_of_string "3"),false);;
-
-testing_function "incr_nat";;
-
-let zero = nat_of_int 0 in
-let res = incr_nat zero 0 1 1 in
- test 1
- equal_nat (zero, nat_of_int 1) &&
- test 2
- eq (res,0);;
-
-let n = nat_of_int 1 in
-let res = incr_nat n 0 1 1 in
- test 3
- equal_nat (n, nat_of_int 2) &&
- test 4
- eq (res,0);;
-
-
-testing_function "decr_nat";;
-
-let n = nat_of_int 1 in
-let res = decr_nat n 0 1 0 in
- test 1
- equal_nat (n, nat_of_int 0) &&
- test 2
- eq (res,1);;
-
-let n = nat_of_int 2 in
-let res = decr_nat n 0 1 0 in
- test 3
- equal_nat (n, nat_of_int 1) &&
- test 4
- eq (res,1);;
-
-testing_function "is_zero_nat";;
-
-let n = nat_of_int 1 in
-test 1 eq (is_zero_nat n 0 1,false) &&
-test 2 eq (is_zero_nat (make_nat 1) 0 1, true) &&
-test 3 eq (is_zero_nat (make_nat 2) 0 2, true) &&
-(let r = make_nat 2 in
- set_digit_nat r 1 1;
- test 4 eq (is_zero_nat r 0 1, true))
-;;
-
-testing_function "string_of_nat";;
-
-let n = make_nat 4;;
-
-test 1 eq_string (string_of_nat n, "0");;
-
-complement_nat n 0 (if sixtyfour then 2 else 4);;
-
-test 2 eq_string (string_of_nat n, "340282366920938463463374607431768211455");;
-
-testing_function "string_of_nat && nat_of_string";;
-
-for i = 1 to 20 do
- let s = String.init i (function 0 -> '1' | _ -> '0') in
- ignore (test i eq_string (string_of_nat (nat_of_string s), s))
-done;;
-
-let set_mult_digit_nat n1 d1 l1 n2 d2 l2 n3 d3 =
- ignore (mult_digit_nat n1 d1 l1 n2 d2 l2 n3 d3)
-;;
-
-let s =
- "33333333333333333333333333333333333333333333333333333333333333333333\
- 33333333333333333333333333333333333333333333333333333333333333333333"
-in
-test 21 equal_nat (
-nat_of_string s,
-(let nat = make_nat 15 in
- set_digit_nat nat 0 3;
- set_mult_digit_nat nat 0 15
- (nat_of_string (String.sub s 0 135)) 0 14
- (nat_of_int 10) 0;
- nat))
-;;
-
-test 22 eq_string (string_of_nat(nat_of_string "1073741824"), "1073741824");;
-
-testing_function "gcd_nat";;
-
-for i = 1 to 20 do
- let n1 = Random.int 1000000000
- and n2 = Random.int 100000 in
- let nat1 = nat_of_int n1
- and nat2 = nat_of_int n2 in
- ignore (gcd_nat nat1 0 1 nat2 0 1);
- ignore (test i eq (int_of_nat nat1, gcd_int n1 n2))
-done
-;;
-
-testing_function "sqrt_nat";;
-
-test 1 equal_nat (sqrt_nat (nat_of_int 1) 0 1, nat_of_int 1);;
-test 2 equal_nat (let n = nat_of_string "8589934592" in
- sqrt_nat n 0 (length_nat n),
- nat_of_string "92681");;
-test 3 equal_nat (let n = nat_of_string "4294967295" in
- sqrt_nat n 0 (length_nat n),
- nat_of_string "65535");;
-test 4 equal_nat (let n = nat_of_string "18446744065119617025" in
- sqrt_nat n 0 (length_nat n),
- nat_of_string "4294967295");;
-test 5 equal_nat (sqrt_nat (nat_of_int 15) 0 1,
- nat_of_int 3);;
+++ /dev/null
-open Test;;
-open Nat;;
-open Big_int;;
-open Ratio;;
-open Num;;
-open Arith_status;;
-
-testing_function "add_num";;
-
-test 1
-eq_num (add_num (Int 1) (Int 3), Int 4);;
-test 2
-eq_num (add_num (Int 1) (Big_int (big_int_of_int 3)), Int 4);;
-test 3
-eq_num (add_num (Int 1) (Ratio (ratio_of_string "3/4")),
- Ratio (ratio_of_string "7/4"));;
-test 4
-eq_num (add_num (Big_int (big_int_of_int 1)) (Ratio (ratio_of_string "3/4")),
- Ratio (ratio_of_string "7/4"));;
-test 5
-eq_num (add_num (Big_int (big_int_of_int 1)) (Big_int (big_int_of_int 3)),
- Int 4);;
-test 6
-eq_num (add_num (Big_int (big_int_of_int 1)) (Ratio (ratio_of_string "3/4")),
- Ratio (ratio_of_string "7/4"));;
-test 7
-eq_num (add_num (Ratio (ratio_of_string "2/3")) (Ratio (ratio_of_string "3/4")),
- Ratio (ratio_of_string "17/12"));;
-test 8
-eq_num (add_num (Int least_int) (Int 1),
- Int (- (pred biggest_int)));;
-test 9
-eq_num (add_num (Int biggest_int) (Int 1),
- Big_int (minus_big_int (pred_big_int (big_int_of_int least_int))));;
-
-testing_function "sub_num";;
-
-test 1
-eq_num (sub_num (Int 1) (Int 3), Int (-2));;
-test 2
-eq_num (sub_num (Int 1) (Big_int (big_int_of_int 3)), Int (-2));;
-test 3
-eq_num (sub_num (Int 1) (Ratio (ratio_of_string "3/4")),
- Ratio (ratio_of_string "1/4"));;
-test 4
-eq_num (sub_num (Big_int (big_int_of_int 1)) (Ratio (ratio_of_string "3/4")),
- Ratio (ratio_of_string "1/4"));;
-test 5
-eq_num (sub_num (Big_int (big_int_of_int 1)) (Big_int (big_int_of_int 3)),
- Int (-2));;
-test 7
-eq_num (sub_num (Big_int (big_int_of_int 1)) (Ratio (ratio_of_string "3/4")),
- Ratio (ratio_of_string "1/4"));;
-test 8
-eq_num (sub_num (Ratio (ratio_of_string "2/3")) (Ratio (ratio_of_string "3/4")),
- Ratio (ratio_of_string "-1/12"));;
-test 9
-eq_num (sub_num (Int least_int) (Int (-1)),
- Int (- (pred biggest_int)));;
-test 10
-eq_num (sub_num (Int (-1)) (Int biggest_int), pred_num (Int least_int));;
-
-testing_function "mult_num";;
-
-test 1
-eq_num (mult_num (Int 2) (Int 3), Int 6);;
-test 2
-eq_num (mult_num (Int 127) (Int (int_of_string "257")),
- Int (int_of_string "32639"));;
-test 3
-eq_num (mult_num (Int 257) (Int (int_of_string "260")),
- Big_int (big_int_of_string "66820"));;
-test 4
-eq_num (mult_num (Int 2) (Big_int (big_int_of_int 3)), Int 6);;
-test 5
-eq_num (mult_num (Int 10) (Ratio (ratio_of_string "3/4")),
- Ratio (ratio_of_string "15/2"));;
-test 6
-eq_num (mult_num (Big_int (big_int_of_int 10)) (Ratio (ratio_of_string "3/4")),
- Ratio (ratio_of_string "15/2"));;
-test 7
-eq_num (mult_num (Big_int (big_int_of_int 2)) (Big_int (big_int_of_int 3)),
- Int 6);;
-test 8
-eq_num (mult_num (Big_int (big_int_of_int 10)) (Ratio (ratio_of_string "3/4")),
- Ratio (ratio_of_string "15/2"));;
-test 9
-eq_num (mult_num (Ratio (ratio_of_string "2/3")) (Ratio (ratio_of_string "3/4"))
- , Ratio (ratio_of_string "1/2"));;
-
-testing_function "div_num";;
-
-test 1
-eq_num (div_num (Int 6) (Int 3), Int 2);;
-test 2
-eq_num (div_num (Int (int_of_string "32639"))
- (Int (int_of_string "257")), Int 127);;
-test 3
-eq_num (div_num (Big_int (big_int_of_string "66820"))
- (Int (int_of_string "257")),
- Int 260);;
-test 4
-eq_num (div_num (Int 6) (Big_int (big_int_of_int 3)), Int 2);;
-test 5
-eq_num (div_num (Ratio (ratio_of_string "15/2"))
- (Int 10),
- Ratio (ratio_of_string "3/4"));;
-test 6
-eq_num (div_num (Big_int (big_int_of_int 6)) (Big_int (big_int_of_int 3)),
- Int 2);;
-test 7
-eq_num (div_num (Ratio (ratio_of_string "15/2"))
- (Big_int (big_int_of_int 10)),
- Ratio (ratio_of_string "3/4"));;
-test 8
-eq_num (div_num (Ratio (ratio_of_string "15/2"))
- (Ratio (ratio_of_string "3/4")),
- Big_int (big_int_of_int 10));;
-test 9
-eq_num (div_num (Ratio (ratio_of_string "1/2"))
- (Ratio (ratio_of_string "3/4")),
- Ratio (ratio_of_string "2/3"));;
-
-testing_function "is_integer_num";;
-
-test 1
-eq (is_integer_num (Int 3),true);;
-test 2
-eq (is_integer_num (Big_int (big_int_of_string "1234567890")),true);;
-test 3
-eq (not (is_integer_num (Ratio (ratio_of_string "1/2"))),true);;
-test 4
-eq (is_integer_num (Ratio (ratio_of_string "1073774590/32770")),true);;
-
-testing_function "num_of_ratio";;
-
-test 1
-eq_num (num_of_ratio (ratio_of_string "4/2"), Int 2);;
-test 2
-eq_num (num_of_ratio (ratio_of_string "11811160075/11"),
- Big_int (big_int_of_string "1073741825"));;
-test 3
-eq_num (num_of_ratio (ratio_of_string "123456789012/1234"),
- Ratio (ratio_of_string "61728394506/617"));;
-
-testing_function "num_of_string";;
-
-test 1
-eq_num (num_of_string "123/3456", Ratio (ratio_of_string "123/3456"));;
-(*********
-test 2
-eq_num (num_of_string "12.3/34.56", Ratio (ratio_of_string "1230/3456"));;
-test 3
-eq_num (num_of_string "1.23/325.6", Ratio (ratio_of_string "123/32560"));;
-test 4
-eq_num (num_of_string "12.3/345.6", Ratio (ratio_of_string "123/3456"));;
-set_error_when_null_denominator false;;
-test 5
-eq_num (num_of_string "12.3/0.0", Ratio (ratio_of_string "123/0"));;
-test 6
-eq_num (num_of_string "0/0", Ratio (ratio_of_string "0/0"));;
-set_error_when_null_denominator true;;
-*********)
-test 7
-eq_num (num_of_string "1234567890",
- Big_int (big_int_of_string "1234567890"));;
-test 8
-eq_num (num_of_string "12345", Int (int_of_string "12345"));;
-(*********
-test 9
-eq_num (num_of_string "0.23", Ratio (ratio_of_string "23/100"));;
-test 10
-eq_num (num_of_string "0.23", Ratio (ratio_of_string "0.23/1"));;
-********)
-
-failwith_test 11
-num_of_string ("frlshjkurty") (Failure "num_of_string");;
-
-test 12
-eq_num (num_of_string "0xAbCdEf",
- Big_int (big_int_of_int 0xabcdef));;
-
-test 13
-eq_num (num_of_string "0b1101/0O1765",
- Ratio (ratio_of_string "0b1101/0o1765"));;
-
-test 14
-eq_num (num_of_string "-12_34_56",
- Big_int (big_int_of_int (-123456)));;
-
-test 15
-eq_num (num_of_string "0B101010", Big_int (big_int_of_int 42));;
-
-(*******
-
-testing_function "immediate numbers";;
-
-standard arith false;;
-
-let x = (1/2) in
-test 0 eq_string (string_of_num x, "1/2");;
-
-let y = 12345678901 in
-test 1 eq_string (string_of_num y, "12345678901");;
-testing_function "immediate numbers";;
-
-let x = (1/2) in
-test 0 eq_string (string_of_num x, "1/2");;
-
-let y = 12345678901 in
-test 1 eq_string (string_of_num y, "12345678901");;
-
-testing_function "pattern_matching on nums";;
-
-let f1 = function 0 -> true | _ -> false;;
-
-test 1 eq (f1 0, true);;
-
-test 2 eq (f1 1, false);;
-
-test 3 eq (f1 (0/1), true);;
-
-test 4 eq (f1 (let n = num_of_string "2000000000000000000000000" in n-n) ,
- true);;
-
-test 5 eq (f1 (let n = num_of_string "2000000000000000000000000" in n/n-1) ,
- true);;
-
-test 6 eq (f1 (let n = num_of_string "2000000000000000000000000" in n+1) ,
- false);;
-
-test 7 eq (f1 (1/2), false);;
-
-**************)
+++ /dev/null
-open Test;;
-open Nat;;
-open Big_int;;
-open Ratio;;
-open Arith_status;;
-
-set_error_when_null_denominator false
-;;
-
-let infinite_failure = "infinite or undefined rational number";;
-
-testing_function "create_ratio"
-;;
-
-let r = create_ratio (big_int_of_int 1) (big_int_of_int (-2)) in
-test 1 eq_big_int (numerator_ratio r, big_int_of_int (-1)) &&
-test 2 eq_big_int (denominator_ratio r, big_int_of_int 2)
-;;
-
-let r = create_ratio (big_int_of_int 2) (big_int_of_int 3) in
-test 3 eq_big_int (numerator_ratio r, big_int_of_int 2) &&
-test 4 eq_big_int (denominator_ratio r, big_int_of_int 3)
-;;
-
-set_normalize_ratio true
-;;
-
-let r = create_ratio (big_int_of_int 12) (big_int_of_int (-16)) in
-test 5 eq_big_int (numerator_ratio r, big_int_of_int (-3)) &&
-test 6 eq_big_int (denominator_ratio r, big_int_of_int 4)
-;;
-
-set_normalize_ratio false
-;;
-
-let r = create_ratio (big_int_of_int 0) (big_int_of_int 0) in
-test 7 eq_big_int (numerator_ratio r, big_int_of_int 0) &&
-test 8 eq_big_int (denominator_ratio r, big_int_of_int 0)
-;;
-
-testing_function "create_normalized_ratio"
-;;
-
-let r = create_normalized_ratio (big_int_of_int 1) (big_int_of_int (-2)) in
-test 1 eq_big_int (numerator_ratio r, big_int_of_int (-1)) &&
-test 2 eq_big_int (denominator_ratio r, big_int_of_int 2)
-;;
-
-let r = create_normalized_ratio (big_int_of_int 2) (big_int_of_int 3) in
-test 3 eq_big_int (numerator_ratio r, big_int_of_int 2) &&
-test 4 eq_big_int (denominator_ratio r, big_int_of_int 3)
-;;
-
-set_normalize_ratio true
-;;
-
-let r = create_normalized_ratio (big_int_of_int 12) (big_int_of_int (-16)) in
-test 5 eq_big_int (numerator_ratio r, big_int_of_int (-12)) &&
-test 6 eq_big_int (denominator_ratio r, big_int_of_int 16)
-;;
-
-set_normalize_ratio false
-;;
-
-let r = create_normalized_ratio (big_int_of_int 1) (big_int_of_int 0) in
-test 7 eq_big_int (numerator_ratio r, big_int_of_int 1) &&
-test 8 eq_big_int (denominator_ratio r, big_int_of_int 0)
-;;
-
-let r = create_normalized_ratio (big_int_of_int 0) (big_int_of_int 0) in
-test 9 eq_big_int (numerator_ratio r, big_int_of_int 0) &&
-test 10 eq_big_int (denominator_ratio r, big_int_of_int 0)
-;;
-
-testing_function "null_denominator"
-;;
-
-test 1
- eq (null_denominator (create_ratio (big_int_of_int 1) (big_int_of_int (-2))),
- false)
-;;
-test 2 eq
- (null_denominator (create_ratio (big_int_of_int 1) zero_big_int),true)
-;;
-
-(*****
-testing_function "verify_null_denominator"
-;;
-
-test 1
- eq (verify_null_denominator (ratio_of_string "0/1"), false)
-;;
-test 2
- eq (verify_null_denominator (ratio_of_string "0/0"), true)
-;;
-*****)
-
-testing_function "sign_ratio"
-;;
-
-test 1
-eq_int (sign_ratio (create_ratio (big_int_of_int (-2)) (big_int_of_int (-3))),
- 1)
-;;
-test 2
-eq_int (sign_ratio (create_ratio (big_int_of_int 2) (big_int_of_int (-3))),
- (-1))
-;;
-test 3
-eq_int (sign_ratio (create_ratio zero_big_int (big_int_of_int (-3))), 0)
-;;
-
-testing_function "normalize_ratio"
-;;
-
-let r = create_ratio (big_int_of_int 12) (big_int_of_int (-16)) in
-ignore (normalize_ratio r);
-test 1 eq_big_int (numerator_ratio r, big_int_of_int (-3)) &&
-test 2 eq_big_int (denominator_ratio r, big_int_of_int 4)
-;;
-
-let r = create_ratio (big_int_of_int (-1)) zero_big_int in
-ignore (normalize_ratio r);
-test 3 eq_big_int (numerator_ratio r, big_int_of_int (-1)) &&
-test 4 eq_big_int (denominator_ratio r, zero_big_int)
-;;
-
-testing_function "report_sign_ratio"
-;;
-
-test 1
-eq_big_int (report_sign_ratio
- (create_ratio (big_int_of_int 2) (big_int_of_int (-3)))
- (big_int_of_int 1),
- big_int_of_int (-1))
-;;
-test 2
-eq_big_int (report_sign_ratio
- (create_ratio (big_int_of_int 2) (big_int_of_int 3))
- (big_int_of_int 1),
- big_int_of_int 1)
-;;
-
-testing_function "is_integer_ratio"
-;;
-
-test 1 eq
- (is_integer_ratio (create_ratio (big_int_of_int 2) (big_int_of_int (-1))),
- true)
-;;
-test 2 eq
- (is_integer_ratio (create_ratio (big_int_of_int 2) (big_int_of_int 3)),
- false)
-;;
-
-testing_function "add_ratio"
-;;
-
-let r = add_ratio (create_ratio (big_int_of_int 1) (big_int_of_int 2))
- (create_ratio (big_int_of_int 2) (big_int_of_int 3)) in
-test 1 eq_big_int (numerator_ratio r, big_int_of_int 7) &&
-test 2 eq_big_int (denominator_ratio r, big_int_of_int 6)
-;;
-
-let r = add_ratio (create_ratio (big_int_of_int 2) (big_int_of_int 3))
- (create_ratio (big_int_of_int 1) (big_int_of_int (-2))) in
-test 3 eq_big_int (numerator_ratio r, big_int_of_int 1) &&
-test 4 eq_big_int (denominator_ratio r, big_int_of_int 6)
-;;
-
-let r = add_ratio (create_ratio (big_int_of_int 2) zero_big_int)
- (create_ratio (big_int_of_int 1) (big_int_of_int (-2))) in
-test 5 eq_big_int (numerator_ratio r, big_int_of_int 4) &&
-test 6 eq_big_int (denominator_ratio r, zero_big_int)
-;;
-
-let r = add_ratio (create_ratio (big_int_of_int 2) (big_int_of_int 3))
- (create_ratio (big_int_of_int 1) zero_big_int) in
-test 7 eq_big_int (numerator_ratio r, big_int_of_int 3) &&
-test 8 eq_big_int (denominator_ratio r, zero_big_int)
-;;
-
-let r = add_ratio (create_ratio (big_int_of_int 2) zero_big_int)
- (create_ratio (big_int_of_int 1) zero_big_int) in
-test 9 eq_big_int (numerator_ratio r, zero_big_int) &&
-test 10 eq_big_int (denominator_ratio r, zero_big_int)
-;;
-
-let r = add_ratio (create_ratio (big_int_of_string "12724951")
- (big_int_of_string "26542080"))
- (create_ratio (big_int_of_string "-1")
- (big_int_of_string "81749606400")) in
-test 11 eq_big_int (numerator_ratio r,
- big_int_of_string "1040259735682744320") &&
-test 12 eq_big_int (denominator_ratio r,
- big_int_of_string "2169804593037312000")
-;;
-
-let r1,r2 =
- (create_ratio (big_int_of_string "12724951")
- (big_int_of_string "26542080"),
- create_ratio (big_int_of_string "-1")
- (big_int_of_string "81749606400")) in
-
-let bi1 = mult_big_int (numerator_ratio r1) (denominator_ratio r2)
-and bi2 = mult_big_int (numerator_ratio r2) (denominator_ratio r1)
-in
-test 1
-eq_big_int (bi1,
- big_int_of_string "1040259735709286400")
-&&
-test 2
-eq_big_int (bi2,
- big_int_of_string "-26542080")
-&& test 3
-eq_big_int (mult_big_int (denominator_ratio r1) (denominator_ratio r2),
- big_int_of_string "2169804593037312000")
-&& test 4
-eq_big_int (add_big_int bi1 bi2,
- big_int_of_string "1040259735682744320")
-;;
-
-testing_function "sub_ratio"
-;;
-
-let r = sub_ratio (create_ratio (big_int_of_int 2) (big_int_of_int 3))
- (create_ratio (big_int_of_int 1) (big_int_of_int 2)) in
-test 1 eq_big_int (numerator_ratio r, big_int_of_int 1) &&
-test 2 eq_big_int (denominator_ratio r, big_int_of_int 6)
-;;
-
-let r = sub_ratio (create_ratio (big_int_of_int 2) zero_big_int)
- (create_ratio (big_int_of_int 1) (big_int_of_int (-2))) in
-test 3 eq_big_int (numerator_ratio r, big_int_of_int 4) &&
-test 4 eq_big_int (denominator_ratio r, zero_big_int)
-;;
-
-let r = sub_ratio (create_ratio (big_int_of_int 2) (big_int_of_int 3))
- (create_ratio (big_int_of_int 1) zero_big_int) in
-test 5 eq_big_int (numerator_ratio r, big_int_of_int (-3)) &&
-test 6 eq_big_int (denominator_ratio r, zero_big_int)
-;;
-
-let r = sub_ratio (create_ratio (big_int_of_int 2) zero_big_int)
- (create_ratio (big_int_of_int 1) zero_big_int) in
-test 7 eq_big_int (numerator_ratio r, zero_big_int) &&
-test 8 eq_big_int (denominator_ratio r, zero_big_int)
-;;
-
-testing_function "mult_ratio"
-;;
-
-let r = mult_ratio (create_ratio (big_int_of_int 2) (big_int_of_int 3))
- (create_ratio (big_int_of_int 7) (big_int_of_int 5)) in
-test 1 eq_big_int (numerator_ratio r, big_int_of_int 14) &&
-test 2 eq_big_int (denominator_ratio r, big_int_of_int 15)
-;;
-
-let r = mult_ratio (create_ratio (big_int_of_int 2) zero_big_int)
- (create_ratio (big_int_of_int 1) (big_int_of_int (-2))) in
-test 3 eq_big_int (numerator_ratio r, big_int_of_int (-2)) &&
-test 4 eq_big_int (denominator_ratio r, zero_big_int)
-;;
-
-let r = mult_ratio (create_ratio (big_int_of_int 2) (big_int_of_int 3))
- (create_ratio (big_int_of_int 1) zero_big_int) in
-test 5 eq_big_int (numerator_ratio r, big_int_of_int 2) &&
-test 6 eq_big_int (denominator_ratio r, zero_big_int)
-;;
-
-let r = mult_ratio (create_ratio (big_int_of_int 2) zero_big_int)
- (create_ratio (big_int_of_int 1) zero_big_int) in
-test 7 eq_big_int (numerator_ratio r, big_int_of_int 2) &&
-test 8 eq_big_int (denominator_ratio r, zero_big_int)
-;;
-
-testing_function "div_ratio"
-;;
-
-let r = div_ratio (create_ratio (big_int_of_int 2) (big_int_of_int 3))
- (create_ratio (big_int_of_int 5) (big_int_of_int 7)) in
-test 1 eq_big_int (numerator_ratio r, big_int_of_int 14) &&
-test 2 eq_big_int (denominator_ratio r, big_int_of_int 15)
-;;
-
-let r = div_ratio (create_ratio (big_int_of_int 2) zero_big_int)
- (create_ratio (big_int_of_int 1) (big_int_of_int (-2))) in
-test 3 eq_big_int (numerator_ratio r, big_int_of_int (-4)) &&
-test 4 eq_big_int (denominator_ratio r, zero_big_int)
-;;
-
-let r = div_ratio (create_ratio (big_int_of_int 2) (big_int_of_int 3))
- (create_ratio (big_int_of_int 1) zero_big_int) in
-test 5 eq_big_int (numerator_ratio r, zero_big_int) &&
-test 6 eq_big_int (denominator_ratio r, big_int_of_int 3)
-;;
-
-let r = div_ratio (create_ratio (big_int_of_int 2) zero_big_int)
- (create_ratio (big_int_of_int 1) zero_big_int) in
-test 7 eq_big_int (numerator_ratio r, zero_big_int) &&
-test 8 eq_big_int (denominator_ratio r, zero_big_int)
-;;
-
-testing_function "integer_ratio"
-;;
-
-test 1
-eq_big_int (integer_ratio
- (create_ratio (big_int_of_int 5) (big_int_of_int 3)),
- big_int_of_int 1)
-;;
-test 2
-eq_big_int (integer_ratio
- (create_ratio (big_int_of_int 5) (big_int_of_int (-3))),
- big_int_of_int (-1))
-;;
-test 3
-eq_big_int (integer_ratio
- (create_ratio (big_int_of_int 3) (big_int_of_int 2)),
- big_int_of_int 1)
-;;
-test 4
-eq_big_int (integer_ratio
- (create_ratio (big_int_of_int 3) (big_int_of_int (-2))),
- big_int_of_int (-1))
-;;
-
-failwith_test 5
-integer_ratio (create_ratio (big_int_of_int 3) zero_big_int)
-(Failure("integer_ratio "^infinite_failure))
-;;
-
-testing_function "floor_ratio"
-;;
-
-test 1
-eq_big_int (floor_ratio
- (create_ratio (big_int_of_int 5) (big_int_of_int 3)),
- big_int_of_int 1)
-;;
-test 2
-eq_big_int (floor_ratio
- (create_ratio (big_int_of_int 5) (big_int_of_int (-3))),
- big_int_of_int (-2))
-;;
-test 3
-eq_big_int (floor_ratio
- (create_ratio (big_int_of_int 3) (big_int_of_int 2)),
- big_int_of_int 1)
-;;
-test 4
-eq_big_int (floor_ratio
- (create_ratio (big_int_of_int 3) (big_int_of_int (-2))),
- big_int_of_int (-2))
-;;
-
-failwith_test 5 floor_ratio (create_ratio (big_int_of_int 3) zero_big_int)
-Division_by_zero
-;;
-
-
-testing_function "round_ratio"
-;;
-
-test 1
-eq_big_int (round_ratio
- (create_ratio (big_int_of_int 5) (big_int_of_int 3)),
- big_int_of_int 2)
-;;
-test 2
-eq_big_int (round_ratio
- (create_ratio (big_int_of_int 5) (big_int_of_int (-3))),
- big_int_of_int (-2))
-;;
-test 3
-eq_big_int (round_ratio
- (create_ratio (big_int_of_int 3) (big_int_of_int 2)),
- big_int_of_int 2)
-;;
-test 4
-eq_big_int (round_ratio
- (create_ratio (big_int_of_int 3) (big_int_of_int (-2))),
- big_int_of_int (-2))
-;;
-
-failwith_test 5
-round_ratio (create_ratio (big_int_of_int 3) zero_big_int)
-Division_by_zero
-;;
-
-
-testing_function "ceiling_ratio"
-;;
-
-test 1
-eq_big_int (ceiling_ratio
- (create_ratio (big_int_of_int 5) (big_int_of_int 3)),
- big_int_of_int 2)
-;;
-test 2
-eq_big_int (ceiling_ratio
- (create_ratio (big_int_of_int 5) (big_int_of_int (-3))),
- big_int_of_int (-1))
-;;
-test 3
-eq_big_int (ceiling_ratio
- (create_ratio (big_int_of_int 3) (big_int_of_int 2)),
- big_int_of_int 2)
-;;
-test 4
-eq_big_int (ceiling_ratio
- (create_ratio (big_int_of_int 3) (big_int_of_int (-2))),
- big_int_of_int (-1))
-;;
-test 5
-eq_big_int (ceiling_ratio
- (create_ratio (big_int_of_int 4) (big_int_of_int 2)),
- big_int_of_int 2)
-;;
-failwith_test 6
-ceiling_ratio (create_ratio (big_int_of_int 3) zero_big_int)
-Division_by_zero
-;;
-
-testing_function "eq_ratio"
-;;
-
-test 1
-eq_ratio (create_ratio (big_int_of_int 5) (big_int_of_int 3),
- create_ratio (big_int_of_int (-20)) (big_int_of_int (-12)))
-;;
-test 2
-eq_ratio (create_ratio (big_int_of_int 1) zero_big_int,
- create_ratio (big_int_of_int 2) zero_big_int)
-;;
-
-let neq_ratio x y = not (eq_ratio x y);;
-
-test 3
-neq_ratio (create_ratio (big_int_of_int 1) zero_big_int,
- create_ratio (big_int_of_int (-1)) zero_big_int)
-;;
-test 4
-neq_ratio (create_ratio (big_int_of_int 1) zero_big_int,
- create_ratio zero_big_int zero_big_int)
-;;
-test 5
-eq_ratio (create_ratio zero_big_int zero_big_int,
- create_ratio zero_big_int zero_big_int)
-;;
-
-testing_function "compare_ratio"
-;;
-
-test 1
-eq_int (compare_ratio (create_ratio (big_int_of_int 0) (big_int_of_int 0))
- (create_ratio (big_int_of_int 0) (big_int_of_int 0)),
- 0)
-;;
-test 2
-eq_int (compare_ratio (create_ratio (big_int_of_int 0) (big_int_of_int 0))
- (create_ratio (big_int_of_int 1) (big_int_of_int 0)),
- 0)
-;;
-test 3
-eq_int (compare_ratio (create_ratio (big_int_of_int 0) (big_int_of_int 0))
- (create_ratio (big_int_of_int (-1)) (big_int_of_int 0)),
- 0)
-;;
-test 4
-eq_int (compare_ratio (create_ratio (big_int_of_int 1) (big_int_of_int 0))
- (create_ratio (big_int_of_int 0) (big_int_of_int 0)),
- 0)
-;;
-test 5
-eq_int (compare_ratio (create_ratio (big_int_of_int (-1)) (big_int_of_int 0))
- (create_ratio (big_int_of_int 0) (big_int_of_int 0)),
- 0)
-;;
-test 6
-eq_int (compare_ratio (create_ratio (big_int_of_int 0) (big_int_of_int 0))
- (create_ratio (big_int_of_int 5) (big_int_of_int 3)),
- 0)
-;;
-test 7
-eq_int (compare_ratio (create_ratio (big_int_of_int 5) (big_int_of_int 3))
- (create_ratio (big_int_of_int 0) (big_int_of_int 0)),
- 0)
-;;
-test 8
-eq_int (compare_ratio (create_ratio (big_int_of_int 0) (big_int_of_int 0))
- (create_ratio (big_int_of_int (-5)) (big_int_of_int 3)),
- 0)
-;;
-test 9
-eq_int (compare_ratio (create_ratio (big_int_of_int (-5)) (big_int_of_int 3))
- (create_ratio (big_int_of_int 0) (big_int_of_int 0)),
- 0)
-;;
-test 10
-eq_int (compare_ratio (create_ratio (big_int_of_int 0) (big_int_of_int 0))
- (create_ratio (big_int_of_int 0) (big_int_of_int 1)),
- 0)
-;;
-test 11
-eq_int (compare_ratio (create_ratio (big_int_of_int 0) (big_int_of_int 1))
- (create_ratio (big_int_of_int 0) (big_int_of_int 0)),
- 0)
-;;
-test 12
-eq_int (compare_ratio (create_ratio (big_int_of_int 1) (big_int_of_int 0))
- (create_ratio (big_int_of_int 1) (big_int_of_int 0)),
- 0)
-;;
-test 13
-eq_int (compare_ratio (create_ratio (big_int_of_int 1) (big_int_of_int 0))
- (create_ratio (big_int_of_int 2) (big_int_of_int 0)),
- 0)
-;;
-test 14
-eq_int (compare_ratio (create_ratio (big_int_of_int 1) (big_int_of_int 0))
- (create_ratio (big_int_of_int (-1)) (big_int_of_int 0)),
- 1)
-;;
-test 15
-eq_int (compare_ratio (create_ratio (big_int_of_int (-1)) (big_int_of_int 0))
- (create_ratio (big_int_of_int 1) (big_int_of_int 0)),
- (-1))
-;;
-test 16
-eq_int (compare_ratio (create_ratio (big_int_of_int 5) (big_int_of_int 3))
- (create_ratio (big_int_of_int 1) (big_int_of_int 0)),
- (-1))
-;;
-test 17
-eq_int (compare_ratio (create_ratio (big_int_of_int 1) (big_int_of_int 0))
- (create_ratio (big_int_of_int 5) (big_int_of_int 3)),
- 1)
-;;
-test 18
-eq_int (compare_ratio (create_ratio (big_int_of_int (-5)) (big_int_of_int 3))
- (create_ratio (big_int_of_int 1) (big_int_of_int 0)),
- (-1))
-;;
-test 19
-eq_int (compare_ratio (create_ratio (big_int_of_int 1) (big_int_of_int 0))
- (create_ratio (big_int_of_int (-5)) (big_int_of_int 3)),
- 1)
-;;
-test 20
-eq_int (compare_ratio (create_ratio (big_int_of_int 1) (big_int_of_int 0))
- (create_ratio (big_int_of_int 0) (big_int_of_int 3)),
- 1)
-;;
-test 21
-eq_int (compare_ratio (create_ratio (big_int_of_int (-1)) (big_int_of_int 0))
- (create_ratio (big_int_of_int (-1)) (big_int_of_int 0)),
- 0)
-;;
-test 22
-eq_int (compare_ratio (create_ratio (big_int_of_int (-1)) (big_int_of_int 0))
- (create_ratio (big_int_of_int (-2)) (big_int_of_int 0)),
- 0)
-;;
-test 23
-eq_int (compare_ratio (create_ratio (big_int_of_int 5) (big_int_of_int 3))
- (create_ratio (big_int_of_int (-1)) (big_int_of_int 0)),
- 1)
-;;
-test 24
-eq_int (compare_ratio (create_ratio (big_int_of_int (-1)) (big_int_of_int 0))
- (create_ratio (big_int_of_int 5) (big_int_of_int 3)),
- (-1))
-;;
-test 25
-eq_int (compare_ratio (create_ratio (big_int_of_int (-5)) (big_int_of_int 3))
- (create_ratio (big_int_of_int (-1)) (big_int_of_int 0)),
- 1)
-;;
-test 26
-eq_int (compare_ratio (create_ratio (big_int_of_int (-1)) (big_int_of_int 0))
- (create_ratio (big_int_of_int (-5)) (big_int_of_int 3)),
- (-1))
-;;
-test 27
-eq_int (compare_ratio (create_ratio (big_int_of_int (-1)) (big_int_of_int 0))
- (create_ratio (big_int_of_int 0) (big_int_of_int 3)),
- (-1))
-;;
-test 28
-eq_int (compare_ratio (create_ratio (big_int_of_int 5) (big_int_of_int 3))
- (create_ratio (big_int_of_int 3) (big_int_of_int 2)),
- 1)
-;;
-test 29
-eq_int (compare_ratio (create_ratio (big_int_of_int 3) (big_int_of_int 2))
- (create_ratio (big_int_of_int 5) (big_int_of_int 3)),
- (-1))
-;;
-test 30
-eq_int (compare_ratio (create_ratio (big_int_of_int 5) (big_int_of_int 3))
- (create_ratio (big_int_of_int (-3)) (big_int_of_int 2)),
- 1)
-;;
-test 31
-eq_int (compare_ratio (create_ratio (big_int_of_int (-3)) (big_int_of_int 2))
- (create_ratio (big_int_of_int 5) (big_int_of_int 3)),
- (-1))
-;;
-test 32
-eq_int (compare_ratio (create_ratio (big_int_of_int 3) (big_int_of_int 2))
- (create_ratio (big_int_of_int 0) (big_int_of_int 3)),
- 1)
-;;
-test 33
-eq_int (compare_ratio (create_ratio (big_int_of_int 0) (big_int_of_int 2))
- (create_ratio (big_int_of_int 5) (big_int_of_int 3)),
- (-1))
-;;
-test 34
-eq_int (compare_ratio (create_ratio (big_int_of_int (-3)) (big_int_of_int 2))
- (create_ratio (big_int_of_int 0) (big_int_of_int 3)),
- (-1))
-;;
-test 35
-eq_int (compare_ratio (create_ratio (big_int_of_int 0) (big_int_of_int 2))
- (create_ratio (big_int_of_int (-5)) (big_int_of_int 3)),
- 1)
-;;
-test 36
-eq_int (compare_ratio (create_ratio (big_int_of_int 0) (big_int_of_int 2))
- (create_ratio (big_int_of_int 0) (big_int_of_int 3)),
- 0)
-;;
-
-testing_function "eq_big_int_ratio"
-;;
-
-test 1
-eq_big_int_ratio (big_int_of_int 3,
- (create_ratio (big_int_of_int 3) (big_int_of_int 1)))
-;;
-test 2
-eq
-(not (eq_big_int_ratio (big_int_of_int 1)
- (create_ratio (big_int_of_int 3) (big_int_of_int 1))),
-true)
-;;
-
-test 3
-eq
-(not (eq_big_int_ratio (big_int_of_int 1)
- (create_ratio (big_int_of_int 3) (big_int_of_int 2))),
- true)
-;;
-
-test 4
-eq
-(not (eq_big_int_ratio (big_int_of_int 1)
- (create_ratio (big_int_of_int 3) (big_int_of_int 0))),
- true)
-;;
-
-test 5
-eq
-(not (eq_big_int_ratio (big_int_of_int 1)
- (create_ratio (big_int_of_int (-3)) (big_int_of_int 2))),
- true)
-;;
-
-testing_function "compare_big_int_ratio"
-;;
-
-test 1
-eq_int (compare_big_int_ratio
- (big_int_of_int 1)
- (create_ratio (big_int_of_int 3) (big_int_of_int 0)), (-1))
-;;
-test 2
-eq_int (compare_big_int_ratio
- (big_int_of_int 1)
- (create_ratio (big_int_of_int 0) (big_int_of_int 0)), 0)
-;;
-test 3
-eq_int (compare_big_int_ratio
- (big_int_of_int 1)
- (create_ratio (big_int_of_int (-3)) (big_int_of_int 0)), 1)
-;;
-test 4
-eq_int (compare_big_int_ratio
- (big_int_of_int (-1))
- (create_ratio (big_int_of_int 3) (big_int_of_int 0)), (-1))
-;;
-test 5
-eq_int (compare_big_int_ratio
- (big_int_of_int (-1))
- (create_ratio (big_int_of_int 0) (big_int_of_int 0)), 0)
-;;
-test 6
-eq_int (compare_big_int_ratio
- (big_int_of_int (-1))
- (create_ratio (big_int_of_int (-3)) (big_int_of_int 0)), 1)
-;;
-test 7
-eq_int (compare_big_int_ratio
- (big_int_of_int 1)
- (create_ratio (big_int_of_int 1) (big_int_of_int 1)), 0)
-;;
-test 8
-eq_int (compare_big_int_ratio
- (big_int_of_int 1)
- (create_ratio (big_int_of_int 3) (big_int_of_int 2)), (-1))
-;;
-test 9
-eq_int (compare_big_int_ratio
- (big_int_of_int 1)
- (create_ratio (big_int_of_int 2) (big_int_of_int 3)), 1)
-;;
-
-
-
-testing_function "int_of_ratio"
-;;
-
-test 1
-eq_int (int_of_ratio (create_ratio (big_int_of_int 4) (big_int_of_int 2)),
- 2)
-;;
-
-test 2
-eq_int (int_of_ratio
- (create_ratio (big_int_of_int biggest_int) (big_int_of_int 1)),
- biggest_int)
-;;
-
-failwith_test 3
-int_of_ratio (create_ratio (big_int_of_int 4) (big_int_of_int 0))
-(Failure "integer argument required")
-;;
-
-failwith_test 4
-int_of_ratio (create_ratio (succ_big_int (big_int_of_int biggest_int))
- (big_int_of_int 1))
-(Failure "integer argument required")
-;;
-
-failwith_test 5
-int_of_ratio (create_ratio (big_int_of_int 4) (big_int_of_int 3))
-(Failure "integer argument required")
-;;
-
-testing_function "ratio_of_int"
-;;
-
-test 1
-eq_ratio (ratio_of_int 3,
- create_ratio (big_int_of_int 3) (big_int_of_int 1))
-;;
-
-test 2
-eq_ratio (ratio_of_nat (nat_of_int 2),
- create_ratio (big_int_of_int 2) (big_int_of_int 1))
-;;
-
-testing_function "nat_of_ratio"
-;;
-
-let nat1 = nat_of_ratio (create_ratio (big_int_of_int 3) (big_int_of_int 1))
-and nat2 = nat_of_int 3 in
-test 1
-eq (eq_nat nat1 0 (length_nat nat1) nat2 0 (length_nat nat2), true)
-;;
-
-failwith_test 2
-nat_of_ratio (create_ratio (big_int_of_int 3) (big_int_of_int 0))
-(Failure "nat_of_ratio")
-;;
-
-failwith_test 3
-nat_of_ratio (create_ratio (big_int_of_int (-3)) (big_int_of_int 1))
-(Failure "nat_of_ratio")
-;;
-
-failwith_test 4
-nat_of_ratio (create_ratio (big_int_of_int 3) (big_int_of_int 2))
-(Failure "nat_of_ratio")
-;;
-
-testing_function "ratio_of_big_int"
-;;
-
-test 1
-eq_ratio (ratio_of_big_int (big_int_of_int 3),
- create_ratio (big_int_of_int 3) (big_int_of_int 1))
-;;
-
-testing_function "big_int_of_ratio"
-;;
-
-test 1
-eq_big_int (big_int_of_ratio
- (create_ratio (big_int_of_int 3) (big_int_of_int 1)),
- big_int_of_int 3)
-;;
-test 2
-eq_big_int (big_int_of_ratio
- (create_ratio (big_int_of_int (-3)) (big_int_of_int 1)),
- big_int_of_int (-3))
-;;
-
-failwith_test 3
-big_int_of_ratio (create_ratio (big_int_of_int 3) (big_int_of_int 0))
-(Failure "big_int_of_ratio")
-;;
-
-testing_function "string_of_ratio"
-;;
-
-test 1
-eq_string (string_of_ratio
- (create_ratio (big_int_of_int 43) (big_int_of_int 35)),
- "43/35")
-;;
-test 2
-eq_string (string_of_ratio
- (create_ratio (big_int_of_int 42) (big_int_of_int 0)),
- "1/0")
-;;
-
-set_normalize_ratio_when_printing false
-;;
-
-test 3
-eq_string (string_of_ratio
- (create_ratio (big_int_of_int 42) (big_int_of_int 35)),
- "42/35")
-;;
-
-set_normalize_ratio_when_printing true
-;;
-
-test 4
-eq_string (string_of_ratio
- (create_ratio (big_int_of_int 42) (big_int_of_int 35)),
- "6/5")
-;;
-
-testing_function "ratio_of_string"
-;;
-
-test 1
-eq_ratio (ratio_of_string ("123/3456"),
- create_ratio (big_int_of_int 123) (big_int_of_int 3456))
-;;
-
-(***********
-test 2
-eq_ratio (ratio_of_string ("12.3/34.56"),
- create_ratio (big_int_of_int 1230) (big_int_of_int 3456))
-;;
-test 3
-eq_ratio (ratio_of_string ("1.23/325.6"),
- create_ratio (big_int_of_int 123) (big_int_of_int 32560))
-;;
-test 4
-eq_ratio (ratio_of_string ("12.3/345.6"),
- create_ratio (big_int_of_int 123) (big_int_of_int 3456))
-;;
-test 5
-eq_ratio (ratio_of_string ("12.3/0.0"),
- create_ratio (big_int_of_int 123) (big_int_of_int 0))
-;;
-***********)
-test 6
-eq_ratio (ratio_of_string ("0/0"),
- create_ratio (big_int_of_int 0) (big_int_of_int 0))
-;;
-
-test 7
-eq_ratio (ratio_of_string "1234567890",
- create_ratio (big_int_of_string "1234567890") unit_big_int)
-;;
-failwith_test 8
-ratio_of_string "frlshjkurty" (Failure "invalid digit");;
-
-(***********
-testing_function "msd_ratio"
-;;
-
-test 1
-eq_int (msd_ratio (create_ratio (big_int_of_int 0) (big_int_of_int 1)),
- 0)
-;;
-test 2
-eq_int (msd_ratio (create_ratio (big_int_of_int 1) (big_int_of_int 12)),
- (-2))
-;;
-test 3
-eq_int (msd_ratio (create_ratio (big_int_of_int 12) (big_int_of_int 1)),
- 1)
-;;
-test 4
-eq_int (msd_ratio (create_ratio (big_int_of_int 1) (big_int_of_int 2)),
- (-1))
-;;
-test 5
-eq_int (msd_ratio (create_ratio (big_int_of_int 2) (big_int_of_int 1)),
- 0)
-;;
-test 6
-eq_int (msd_ratio (create_ratio (big_int_of_int 25) (big_int_of_int 21)),
- 0)
-;;
-test 7
-eq_int (msd_ratio (create_ratio (big_int_of_int 35) (big_int_of_int 21)),
- 0)
-;;
-test 8
-eq_int (msd_ratio (create_ratio (big_int_of_int 215) (big_int_of_int 31)),
- 0)
-;;
-test 9
-eq_int (msd_ratio (create_ratio (big_int_of_int 2) (big_int_of_int 30)),
- (-2))
-;;
-test 10
-eq_int (msd_ratio (create_ratio (big_int_of_int 2345)
- (big_int_of_int 23456)),
- (-2))
-;;
-test 11
-eq_int (msd_ratio (create_ratio (big_int_of_int 2345)
- (big_int_of_int 2346)),
- (-1))
-;;
-test 12
-eq_int (msd_ratio (create_ratio (big_int_of_int 2345)
- (big_int_of_int 2344)),
- 0)
-;;
-test 13
-eq_int (msd_ratio (create_ratio (big_int_of_int 23456)
- (big_int_of_int 2345)),
- 1)
-;;
-test 14
-eq_int (msd_ratio (create_ratio (big_int_of_int 23467)
- (big_int_of_int 2345)),
- 1)
-;;
-failwith_test 15
-msd_ratio (create_ratio (big_int_of_int 1) (big_int_of_int 0))
-("msd_ratio "^infinite_failure)
-;;
-failwith_test 16
-msd_ratio (create_ratio (big_int_of_int (-1)) (big_int_of_int 0))
-("msd_ratio "^infinite_failure)
-;;
-failwith_test 17
-msd_ratio (create_ratio (big_int_of_int 0) (big_int_of_int 0))
-("msd_ratio "^infinite_failure)
-;;
-*************************)
-
-testing_function "round_futur_last_digit"
-;;
-
-let s = Bytes.of_string "+123456" in
-test 1 eq (round_futur_last_digit s 1 (pred (Bytes.length s)),
- false) &&
-test 2 eq_bytes (s, Bytes.of_string "+123466")
-;;
-
-let s = Bytes.of_string "123456" in
-test 3 eq (round_futur_last_digit s 0 (Bytes.length s), false) &&
-test 4 eq_bytes (s, Bytes.of_string "123466")
-;;
-
-let s = Bytes.of_string "-123456" in
-test 5 eq (round_futur_last_digit s 1 (pred (Bytes.length s)),
- false) &&
-test 6 eq_bytes (s, Bytes.of_string "-123466")
-;;
-
-let s = Bytes.of_string "+123496" in
-test 7 eq (round_futur_last_digit s 1 (pred (Bytes.length s)),
- false) &&
-test 8 eq_bytes (s, Bytes.of_string "+123506")
-;;
-
-let s = Bytes.of_string "123496" in
-test 9 eq (round_futur_last_digit s 0 (Bytes.length s), false) &&
-test 10 eq_bytes (s, Bytes.of_string "123506")
-;;
-
-let s = Bytes.of_string "-123496" in
-test 11 eq (round_futur_last_digit s 1 (pred (Bytes.length s)),
- false) &&
-test 12 eq_bytes (s, Bytes.of_string "-123506")
-;;
-
-let s = Bytes.of_string "+996" in
-test 13 eq (round_futur_last_digit s 1 (pred (Bytes.length s)),
- true) &&
-test 14 eq_bytes (s, Bytes.of_string "+006")
-;;
-
-let s = Bytes.of_string "996" in
-test 15 eq (round_futur_last_digit s 0 (Bytes.length s), true) &&
-test 16 eq_bytes (s, Bytes.of_string "006")
-;;
-
-let s = Bytes.of_string "-996" in
-test 17 eq (round_futur_last_digit s 1 (pred (Bytes.length s)),
- true) &&
-test 18 eq_bytes (s, Bytes.of_string "-006")
-;;
-
-let s = Bytes.of_string "+6666666" in
-test 19 eq (round_futur_last_digit s 1 (pred (Bytes.length s)),
- false) &&
-test 20 eq_bytes (s, Bytes.of_string "+6666676")
-;;
-
-let s = Bytes.of_string "6666666" in
-test 21 eq (round_futur_last_digit s 0 (Bytes.length s), false) &&
-test 22 eq_bytes (s, Bytes.of_string "6666676")
-;;
-
-let s = Bytes.of_string "-6666666" in
-test 23 eq (round_futur_last_digit s 1 (pred (Bytes.length s)),
- false) &&
-test 24 eq_bytes (s, Bytes.of_string "-6666676")
-;;
-
-testing_function "approx_ratio_fix"
-;;
-
-let s = approx_ratio_fix 5
- (create_ratio (big_int_of_int 2)
- (big_int_of_int 3)) in
-test 1
-eq_string (s, "+0.66667")
-;;
-
-test 2
-eq_string (approx_ratio_fix 5
- (create_ratio (big_int_of_int 20)
- (big_int_of_int 3)),
- "+6.66667")
-;;
-test 3
-eq_string (approx_ratio_fix 5
- (create_ratio (big_int_of_int 2)
- (big_int_of_int 30)),
- "+0.06667")
-;;
-test 4
-eq_string (approx_ratio_fix 5
- (create_ratio (big_int_of_string "999996")
- (big_int_of_string "1000000")),
- "+1.00000")
-;;
-test 5
-eq_string (approx_ratio_fix 5
- (create_ratio (big_int_of_string "299996")
- (big_int_of_string "100000")),
- "+2.99996")
-;;
-test 6
-eq_string (approx_ratio_fix 5
- (create_ratio (big_int_of_string "2999996")
- (big_int_of_string "1000000")),
- "+3.00000")
-;;
-test 7
-eq_string (approx_ratio_fix 4
- (create_ratio (big_int_of_string "299996")
- (big_int_of_string "100000")),
- "+3.0000")
-;;
-test 8
-eq_string (approx_ratio_fix 5
- (create_ratio (big_int_of_int 29996)
- (big_int_of_string "100000")),
- "+0.29996")
-;;
-test 9
-eq_string (approx_ratio_fix 5
- (create_ratio (big_int_of_int 0)
- (big_int_of_int 1)),
- "+0")
-;;
-failwith_test 10
-(approx_ratio_fix 5) (create_ratio (big_int_of_int 1) (big_int_of_int 0))
-(Failure "approx_ratio_fix infinite or undefined rational number")
-;;
-failwith_test 11
-(approx_ratio_fix 5) (create_ratio (big_int_of_int 0) (big_int_of_int 0))
-(Failure "approx_ratio_fix infinite or undefined rational number")
-;;
-
-(* PR#4566 *)
-test 12
-eq_string (approx_ratio_fix 8
- (create_ratio (big_int_of_int 9603)
- (big_int_of_string "100000000000")),
-
- "+0.00000010")
-;;
-test 13
-eq_string (approx_ratio_fix 1
- (create_ratio (big_int_of_int 94)
- (big_int_of_int 1000)),
- "+0.1")
-;;
-test 14
-eq_string (approx_ratio_fix 1
- (create_ratio (big_int_of_int 49)
- (big_int_of_int 1000)),
- "+0.0")
-;;
-
-testing_function "approx_ratio_exp"
-;;
-
-test 1
-eq_string (approx_ratio_exp 5
- (create_ratio (big_int_of_int 2)
- (big_int_of_int 3)),
- "+0.66667e0")
-;;
-test 2
-eq_string (approx_ratio_exp 5
- (create_ratio (big_int_of_int 20)
- (big_int_of_int 3)),
- "+0.66667e1")
-;;
-test 3
-eq_string (approx_ratio_exp 5
- (create_ratio (big_int_of_int 2)
- (big_int_of_int 30)),
- "+0.66667e-1")
-;;
-test 4
-eq_string (approx_ratio_exp 5
- (create_ratio (big_int_of_string "999996")
- (big_int_of_string "1000000")),
- "+1.00000e0")
-;;
-test 5
-eq_string (approx_ratio_exp 5
- (create_ratio (big_int_of_string "299996")
- (big_int_of_string "100000")),
- "+0.30000e1")
-;;
-test 6
-eq_string (approx_ratio_exp 5
- (create_ratio (big_int_of_int 29996)
- (big_int_of_string "100000")),
- "+0.29996e0")
-;;
-test 7
-eq_string (approx_ratio_exp 5
- (create_ratio (big_int_of_int 0)
- (big_int_of_int 1)),
- "+0.00000e0")
-;;
-failwith_test 8
-(approx_ratio_exp 5) (create_ratio (big_int_of_int 1) (big_int_of_int 0))
-(Failure "approx_ratio_exp infinite or undefined rational number")
-;;
-failwith_test 9
-(approx_ratio_exp 5) (create_ratio (big_int_of_int 0) (big_int_of_int 0))
-(Failure "approx_ratio_exp infinite or undefined rational number")
-;;
-
-testing_function "float_of_ratio";;
-let ok = ref true in
-for i = 1 to 100 do
- let p = Random.int64 0x20000000000000L
- and pexp = Random.int 100
- and q = Random.int64 0x20000000000000L
- and qexp = Random.int 100 in
- if not (eq_float
- (float_of_ratio
- (create_ratio
- (shift_left_big_int (big_int_of_int64 p) pexp)
- (shift_left_big_int (big_int_of_int64 q) qexp)))
- (ldexp (Int64.to_float p) pexp /.
- ldexp (Int64.to_float q) qexp))
- then ok := false
-done;
-test 1 eq (!ok, true)
-;;
printf "\nB\n%!";
test (sprintf "%B" true = "true");
+ test (sprintf "%8B" true = " true");
test (sprintf "%B" false = "false");
+ test (sprintf "%-8B" false = "false ");
printf "\nld/li positive\n%!";
test (sprintf "%ld/%li" 42l 43l = "42/43");
E
132 133 134 135 136 137 138 139 140 141 142 143 144 145
B
- 146 147
+ 146 147 148 149
ld/li positive
- 148 149 150 151 152 153 154
+ 150 151 152 153 154 155 156
ld/li negative
- 155 156 157 158 159 160 161
+ 157 158 159 160 161 162 163
lu positive
- 162 163 164 165 166
+ 164 165 166 167 168
lu negative
- 167
+ 169
lx positive
- 168 169 170 171 172 173
+ 170 171 172 173 174 175
lx negative
- 174
+ 176
lX positive
- 175 176 177 178 179 180
+ 177 178 179 180 181 182
lx negative
- 181
+ 183
lo positive
- 182 183 184 185 186 187
+ 184 185 186 187 188 189
lo negative
- 188
+ 190
Ld/Li positive
- 189 190 191 192 193
+ 191 192 193 194 195
Ld/Li negative
- 194 195 196 197 198
+ 196 197 198 199 200
Lu positive
- 199 200 201 202 203
+ 201 202 203 204 205
Lu negative
- 204
+ 206
Lx positive
- 205 206 207 208 209 210
+ 207 208 209 210 211 212
Lx negative
- 211
+ 213
LX positive
- 212 213 214 215 216 217
+ 214 215 216 217 218 219
Lx negative
- 218
+ 220
Lo positive
- 219 220 221 222 223 224
+ 221 222 223 224 225 226
Lo negative
- 225
+ 227
a
- 226
+ 228
t
- 227
+ 229
{...%}
- 228
+ 230
(...%)
- 229
+ 231
! % @ , and constants
- 230 231 232 233 234 235 236
+ 232 233 234 235 236 237 238
end of tests
All tests succeeded.
checkbool "find_first_opt"
(let (l, p, r) = M.split x s1 in
+ let find_first_opt_result = M.find_first_opt (fun k -> k >= x) s1 in
if p = None && M.is_empty r then
- match M.find_first_opt (fun k -> k >= x) s1 with
+ match find_first_opt_result with
None -> true
| _ -> false
else
- let Some (k, v) = M.find_first_opt (fun k -> k >= x) s1 in
- match p with
- None -> (k, v) = M.min_binding r
- | Some v1 -> (k, v) = (x, v1));
+ match find_first_opt_result with
+ | None -> false
+ | Some (k, v) ->
+ (match p with
+ | None -> (k, v) = M.min_binding r
+ | Some v1 -> (k, v) = (x, v1)));
checkbool "find_last"
(let (l, p, r) = M.split x s1 in
checkbool "find_last_opt"
(let (l, p, r) = M.split x s1 in
+ let find_last_opt_result = M.find_last_opt (fun k -> k <= x) s1 in
if p = None && M.is_empty l then
- match M.find_last_opt (fun k -> k <= x) s1 with
+ match find_last_opt_result with
None -> true
| _ -> false
else
- let Some (k, v) = M.find_last_opt (fun k -> k <= x) s1 in
- match p with
- None -> (k, v) = M.max_binding l
- | Some v1 -> (k, v) = (x, v1));
+ (match find_last_opt_result with
+ | None -> false
+ | Some (k, v) ->
+ (match p with
+ | None -> (k, v) = M.max_binding l
+ | Some v1 -> (k, v) = (x, v1))));
check "split"
(let (l, p, r) = M.split x s1 in
checkbool "find_first_opt"
(let (l, p, r) = S.split x s1 in
+ let find_first_opt_result = S.find_first_opt (fun k -> k >= x) s1 in
if not p && S.is_empty r then
- match S.find_first_opt (fun k -> k >= x) s1 with
+ match find_first_opt_result with
None -> true
| _ -> false
else
- let Some e = S.find_first_opt (fun k -> k >= x) s1 in
- if p then
- e = x
- else
- e = S.min_elt r);
+ (match find_first_opt_result with
+ | None -> false
+ | Some e -> if p then e = x else e = S.min_elt r));
checkbool "find_last"
(let (l, p, r) = S.split x s1 in
checkbool "find_last_opt"
(let (l, p, r) = S.split x s1 in
+ let find_last_opt_result = S.find_last_opt (fun k -> k <= x) s1 in
if not p && S.is_empty l then
- match S.find_last_opt (fun k -> k <= x) s1 with
+ match find_last_opt_result with
None -> true
| _ -> false
else
- let Some e = S.find_last_opt (fun k -> k <= x) s1 in
- if p then
- e = x
- else
- e = S.max_elt l);
+ (match find_last_opt_result with
+ | None -> false
+ | Some e -> if p then e = x else e = S.max_elt l));
check "split"
(let (l, p, r) = S.split x s1 in
;;
let () =
- let s1 = S.create () and s2 = S.create () in
+ let s1 = S.create () in
for i = 1 to 4 do S.push i s1 done;
assert (S.length s1 = 4); assert (S.to_list s1 = [1; 2; 3; 4]);
let s2 = S.copy s1 in
with Not_found ->
()
done
- with Invalid_argument "Str.matched_group" -> (*yuck*)
- ()
+ with Invalid_argument str as exn ->
+ if str="Str.matched_group" then () else raise exn
end;
print_newline()
with Not_found ->
--- /dev/null
+#**************************************************************************
+#* *
+#* OCaml *
+#* *
+#* Xavier Clerc, SED, 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 GNU Lesser General Public License version 2.1, with the *
+#* special exception on linking described in the file LICENSE. *
+#* *
+#**************************************************************************
+
+BASEDIR=../..
+include $(BASEDIR)/makefiles/Makefile.several
+include $(BASEDIR)/makefiles/Makefile.common
+
+# Not really generated sources but temp files that need cleaning
+GENERATED_SOURCES=file1.dat file2.dat
--- /dev/null
+(* Test the Sys.rename function *)
+
+let writefile filename contents =
+ let oc = open_out_bin filename in
+ output_string oc contents;
+ close_out oc
+
+let readfile filename =
+ let ic = open_in_bin filename in
+ let sz = in_channel_length ic in
+ let contents = really_input_string ic sz in
+ close_in ic;
+ contents
+
+let safe_remove filename =
+ try Sys.remove filename with Sys_error _ -> ()
+
+let testrename f1 f2 contents =
+ try
+ Sys.rename f1 f2;
+ if readfile f2 <> contents then print_string "wrong contents!"
+ else if Sys.file_exists f1 then print_string "initial file still exists!"
+ else print_string "passed"
+ with Sys_error msg ->
+ print_string "Sys_error exception: "; print_string msg
+
+let testfailure f1 f2 =
+ try
+ Sys.rename f1 f2; print_string "should fail but doesn't!"
+ with Sys_error _ ->
+ print_string "fails as expected"
+
+let _ =
+ let f1 = "file1.dat" and f2 = "file2.dat" in
+ safe_remove f1; safe_remove f2;
+ print_string "Rename to nonexisting file: ";
+ writefile f1 "abc";
+ testrename f1 f2 "abc";
+ print_newline();
+ print_string "Rename to existing file: ";
+ writefile f1 "def";
+ writefile f2 "xyz";
+ testrename f1 f2 "def";
+ print_newline();
+ print_string "Renaming a nonexisting file: ";
+ testfailure f1 f2;
+ print_newline();
+ print_string "Renaming to a nonexisting directory: ";
+ writefile f1 "abc";
+ testfailure f1 (Filename.concat "nosuchdir" f2);
+ print_newline();
+ safe_remove f1; safe_remove f2
--- /dev/null
+Rename to nonexisting file: passed
+Rename to existing file: passed
+Renaming a nonexisting file: fails as expected
+Renaming to a nonexisting directory: fails as expected
let () =
let bt =
try
- Hashtbl.find (Hashtbl.create 1) 1;
+ let h = (Hashtbl.create 1 : (int, unit) Hashtbl.t) in
+ Hashtbl.find h 1;
assert false
with Not_found ->
Printexc.get_raw_backtrace ()
Unix.close wr;
)
() in
- let buf = String.create 10 in
+ let buf = Bytes.create 10 in
print_endline "reading...";
begin try ignore (Unix.read rd buf 0 10) with Unix.Unix_error _ -> () end;
print_endline "read returned";
(* File copy with constant-sized chunks *)
let copy_file sz (ic, oc) =
- let buffer = String.create sz in
+ let buffer = Bytes.create sz in
let rec copy () =
let n = input ic buffer 0 sz in
if n = 0 then () else begin
(* File copy with random-sized chunks *)
let copy_random sz (ic, oc) =
- let buffer = String.create sz in
+ let buffer = Bytes.create sz in
let rec copy () =
let s = 1 + Random.int sz in
let n = input ic buffer 0 s in
--- /dev/null
+(* MPR#7638 repro case *)
+
+let crashme v =
+ match Sys.getenv v with
+ | exception Not_found -> print_string "OK\n"
+ | s -> print_string "Surprising but OK\n"
+
+let _ =
+ let th = Thread.create crashme "no such variable" in
+ Thread.join th
#* *
#**************************************************************************
-sed -e 1q signal.result | grep -q '^[ab]*Got ctrl-C, exiting...$'
+sed -e 1q signal.result | grep -q '^[ab]*Got ctrl-C, exiting...[ab]\{0,2\}$'
+++ /dev/null
-#**************************************************************************
-#* *
-#* OCaml *
-#* *
-#* Xavier Clerc, SED, 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 GNU Lesser General Public License version 2.1, with the *
-#* special exception on linking described in the file LICENSE. *
-#* *
-#**************************************************************************
-
-sed -e 1q signal2.result | grep -q '^[ab]*'
+++ /dev/null
-let print_message delay c =
- while true do
- print_char c; flush stdout; Thread.delay delay
- done
-
-let _ =
- ignore (Thread.sigmask Unix.SIG_BLOCK [Sys.sigint; Sys.sigterm]);
- ignore (Thread.create (print_message 0.6666666666) 'a');
- ignore (Thread.create (print_message 1.0) 'b');
- let s = Thread.wait_signal [Sys.sigint; Sys.sigterm] in
- Printf.printf "Got signal %d, exiting...\n" s
+++ /dev/null
-#**************************************************************************
-#* *
-#* OCaml *
-#* *
-#* Damien Doligez, projet Gallium, INRIA Rocquencourt *
-#* *
-#* Copyright 2013 Institut National de Recherche en Informatique et *
-#* en Automatique. *
-#* *
-#* All rights reserved. This file is distributed under the terms of *
-#* the GNU Lesser General Public License version 2.1, with the *
-#* special exception on linking described in the file LICENSE. *
-#* *
-#**************************************************************************
-
-test "$TOOLCHAIN" != "msvc" -a "$TOOLCHAIN" != "mingw"
+++ /dev/null
-#**************************************************************************
-#* *
-#* OCaml *
-#* *
-#* Xavier Clerc, SED, 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 GNU Lesser General Public License version 2.1, with the *
-#* special exception on linking described in the file LICENSE. *
-#* *
-#**************************************************************************
-
-$RUNTIME ./program >signal2.result &
-pid=$!
-sleep 2
-kill -INT $pid
-sleep 1
-kill -9 $pid 2>&- || true
let test_constants () =
assert (Uchar.(to_int min) = 0x0000);
assert (Uchar.(to_int max) = 0x10FFFF);
+ assert (Uchar.(to_int bom) = 0xFEFF);
+ assert (Uchar.(to_int rep) = 0xFFFD);
()
let test_succ () =
+++ /dev/null
-#**************************************************************************
-#* *
-#* OCaml *
-#* *
-#* Xavier Clerc, SED, 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 GNU Lesser General Public License version 2.1, with the *
-#* special exception on linking described in the file LICENSE. *
-#* *
-#**************************************************************************
-
-BASEDIR=../..
-LIBRARIES=unix
-ADD_COMPFLAGS=-I $(OTOPDIR)/otherlibs/$(UNIXLIBVAR)unix
-LD_PATH=$(TOPDIR)/otherlibs/$(UNIXLIBVAR)unix
-
-ifeq ($(OS),Windows_NT)
-ADD_BYTERUN_FLAGS="-I $(OTOPDIR)/otherlibs/win32unix"
-endif
-
-default: reflector.exe fdstatus.exe cmdline_prog.exe
- @$(MAKE) check
-
-include $(BASEDIR)/makefiles/Makefile.several
-include $(BASEDIR)/makefiles/Makefile.common
-
-%.exe: %.c
-ifeq ($(CCOMPTYPE),msvc)
- @set -o pipefail ; $(BYTECC) /Fe$*.exe $*.c | tail -n +2
-else
- @$(BYTECC) -o $*.exe $*.c
-endif
+++ /dev/null
-(* This is a terrible hack that plays on the internal representation
- of file descriptors. The result is a number (as a string)
- that the fdstatus.exe auxiliary program can use to check whether
- the fd is open. *)
-
-let string_of_fd (fd: Unix.file_descr) : string =
- match Sys.os_type with
- | "Unix" | "Cygwin" -> string_of_int (Obj.magic fd : int)
- | "Win32" ->
- if Sys.word_size = 32 then
- Int32.to_string (Obj.magic fd : int32)
- else
- Int64.to_string (Obj.magic fd : int64)
- | _ -> assert false
-
-let _ =
- let f0 = Unix.(openfile "tmp.txt" [O_WRONLY; O_CREAT; O_TRUNC] 0o600) in
- let f1 = Unix.(openfile "tmp.txt" [O_RDONLY; O_KEEPEXEC] 0) in
- let f2 = Unix.(openfile "tmp.txt" [O_RDONLY; O_CLOEXEC] 0) in
- let d0 = Unix.dup f0 in
- let d1 = Unix.dup ~cloexec:false f1 in
- let d2 = Unix.dup ~cloexec:true f2 in
- let (p0, p0') = Unix.pipe () in
- let (p1, p1') = Unix.pipe ~cloexec:false () in
- let (p2, p2') = Unix.pipe ~cloexec:true () in
- let s0 = Unix.(socket PF_INET SOCK_STREAM 0) in
- let s1 = Unix.(socket ~cloexec:false PF_INET SOCK_STREAM 0) in
- let s2 = Unix.(socket ~cloexec:true PF_INET SOCK_STREAM 0) in
- let (x0, x0') =
- try Unix.(socketpair PF_UNIX SOCK_STREAM 0)
- with Invalid_argument _ -> (p0, p0') in
- (* socketpair not available under Win32; keep the same output *)
- let (x1, x1') =
- try Unix.(socketpair ~cloexec:false PF_UNIX SOCK_STREAM 0)
- with Invalid_argument _ -> (p1, p1') in
- let (x2, x2') =
- try Unix.(socketpair ~cloexec:true PF_UNIX SOCK_STREAM 0)
- with Invalid_argument _ -> (p2, p2') in
-
- let fds = [| f0;f1;f2; d0;d1;d2;
- p0;p0';p1;p1';p2;p2';
- s0;s1;s2;
- x0;x0';x1;x1';x2;x2' |] in
- let pid =
- Unix.create_process
- (Filename.concat Filename.current_dir_name "fdstatus.exe")
- (Array.append [| "fdstatus" |] (Array.map string_of_fd fds))
- Unix.stdin Unix.stdout Unix.stderr in
- ignore (Unix.waitpid [] pid);
- Array.iter (fun fd -> try Unix.close fd with Unix.Unix_error _ -> ()) fds;
- Sys.remove "tmp.txt"
+++ /dev/null
-#1: open
-#2: open
-#3: closed
-#4: open
-#5: open
-#6: closed
-#7: open
-#8: open
-#9: open
-#10: open
-#11: closed
-#12: closed
-#13: open
-#14: open
-#15: closed
-#16: open
-#17: open
-#18: open
-#19: open
-#20: closed
-#21: closed
+++ /dev/null
-#include <stdio.h>
-
-int main (int argc, char *argv[])
-{
- int i;
- for (i = 1; i < argc; i ++) {
- printf ("%s\n", argv[i]);
- }
- return 0;
-}
--- /dev/null
+#**************************************************************************
+#* *
+#* OCaml *
+#* *
+#* Xavier Clerc, SED, 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 GNU Lesser General Public License version 2.1, with the *
+#* special exception on linking described in the file LICENSE. *
+#* *
+#**************************************************************************
+
+BASEDIR=../../..
+LIBRARIES=unix
+ADD_COMPFLAGS=-I $(OTOPDIR)/otherlibs/$(UNIXLIBVAR)unix
+LD_PATH=$(TOPDIR)/otherlibs/$(UNIXLIBVAR)unix
+
+ifeq ($(OS),Windows_NT)
+ADD_BYTERUN_FLAGS="-I $(OTOPDIR)/otherlibs/win32unix"
+endif
+
+default: reflector.exe fdstatus.exe cmdline_prog.exe
+ @$(MAKE) check
+
+include $(BASEDIR)/makefiles/Makefile.several
+include $(BASEDIR)/makefiles/Makefile.common
+
+%.exe: %.c
+ifeq ($(CCOMPTYPE),msvc)
+ @set -o pipefail ; \
+ $(CC) $(CFLAGS) $(CPPFLAGS) /Fe$*.exe $*.c | tail -n +2
+else
+ @$(CC) $(CFLAGS) $(CPPFLAGS) -o $*.exe $*.c
+endif
--- /dev/null
+(* This is a terrible hack that plays on the internal representation
+ of file descriptors. The result is a number (as a string)
+ that the fdstatus.exe auxiliary program can use to check whether
+ the fd is open. *)
+
+let string_of_fd (fd: Unix.file_descr) : string =
+ match Sys.os_type with
+ | "Unix" | "Cygwin" -> string_of_int (Obj.magic fd : int)
+ | "Win32" ->
+ if Sys.word_size = 32 then
+ Int32.to_string (Obj.magic fd : int32)
+ else
+ Int64.to_string (Obj.magic fd : int64)
+ | _ -> assert false
+
+let _ =
+ let f0 = Unix.(openfile "tmp.txt" [O_WRONLY; O_CREAT; O_TRUNC] 0o600) in
+ let f1 = Unix.(openfile "tmp.txt" [O_RDONLY; O_KEEPEXEC] 0) in
+ let f2 = Unix.(openfile "tmp.txt" [O_RDONLY; O_CLOEXEC] 0) in
+ let d0 = Unix.dup f0 in
+ let d1 = Unix.dup ~cloexec:false f1 in
+ let d2 = Unix.dup ~cloexec:true f2 in
+ let (p0, p0') = Unix.pipe () in
+ let (p1, p1') = Unix.pipe ~cloexec:false () in
+ let (p2, p2') = Unix.pipe ~cloexec:true () in
+ let s0 = Unix.(socket PF_INET SOCK_STREAM 0) in
+ let s1 = Unix.(socket ~cloexec:false PF_INET SOCK_STREAM 0) in
+ let s2 = Unix.(socket ~cloexec:true PF_INET SOCK_STREAM 0) in
+ let (x0, x0') =
+ try Unix.(socketpair PF_UNIX SOCK_STREAM 0)
+ with Invalid_argument _ -> (p0, p0') in
+ (* socketpair not available under Win32; keep the same output *)
+ let (x1, x1') =
+ try Unix.(socketpair ~cloexec:false PF_UNIX SOCK_STREAM 0)
+ with Invalid_argument _ -> (p1, p1') in
+ let (x2, x2') =
+ try Unix.(socketpair ~cloexec:true PF_UNIX SOCK_STREAM 0)
+ with Invalid_argument _ -> (p2, p2') in
+
+ let fds = [| f0;f1;f2; d0;d1;d2;
+ p0;p0';p1;p1';p2;p2';
+ s0;s1;s2;
+ x0;x0';x1;x1';x2;x2' |] in
+ let pid =
+ Unix.create_process
+ (Filename.concat Filename.current_dir_name "fdstatus.exe")
+ (Array.append [| "fdstatus" |] (Array.map string_of_fd fds))
+ Unix.stdin Unix.stdout Unix.stderr in
+ ignore (Unix.waitpid [] pid);
+ Array.iter (fun fd -> try Unix.close fd with Unix.Unix_error _ -> ()) fds;
+ Sys.remove "tmp.txt"
--- /dev/null
+#1: open
+#2: open
+#3: closed
+#4: open
+#5: open
+#6: closed
+#7: open
+#8: open
+#9: open
+#10: open
+#11: closed
+#12: closed
+#13: open
+#14: open
+#15: closed
+#16: open
+#17: open
+#18: open
+#19: open
+#20: closed
+#21: closed
--- /dev/null
+#include <stdio.h>
+
+int main (int argc, char *argv[])
+{
+ int i;
+ for (i = 1; i < argc; i ++) {
+ printf ("%s\n", argv[i]);
+ }
+ return 0;
+}
--- /dev/null
+let _ =
+ let f = Unix.dup ~cloexec:true Unix.stdout in
+ let txt = "Some output\n" in
+ ignore (Unix.write_substring f txt 0 (String.length txt));
+ Unix.close f
--- /dev/null
+Some output
--- /dev/null
+let cat file =
+ let fd = Unix.openfile file [Unix.O_RDONLY] 0 in
+ let buf = Bytes.create 1024 in
+ let rec cat () =
+ let n = Unix.read fd buf 0 (Bytes.length buf) in
+ if n > 0 then (ignore(Unix.write Unix.stdout buf 0 n); cat ())
+ in cat (); Unix.close fd
+
+let out fd txt =
+ ignore (Unix.write_substring fd txt 0 (String.length txt))
+
+let _ =
+ let fd =
+ Unix.(openfile "./tmp.txt"
+ [O_WRONLY;O_TRUNC;O_CREAT;O_SHARE_DELETE]
+ 0o600) in
+ out fd "---\n";
+ Unix.dup2 ~cloexec:true fd Unix.stderr;
+ Unix.close fd;
+ out Unix.stderr "Some output\n";
+ cat "./tmp.txt";
+ Sys.remove "./tmp.txt"
+
+
--- /dev/null
+---
+Some output
--- /dev/null
+/* Check if file descriptors are open or not */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef _WIN32
+
+#define WIN32_LEAN_AND_MEAN
+#include <wtypes.h>
+#include <winbase.h>
+#include <winerror.h>
+
+void process_fd(char * s)
+{
+ int fd;
+ HANDLE h;
+ DWORD flags;
+
+#ifdef _WIN64
+ h = (HANDLE) _atoi64(s);
+#else
+ h = (HANDLE) atoi(s);
+#endif
+ if (GetHandleInformation(h, &flags)) {
+ printf("open\n");
+ } else if (GetLastError() == ERROR_INVALID_HANDLE) {
+ printf("closed\n");
+ } else {
+ printf("error %lu\n", (unsigned long)(GetLastError()));
+ }
+}
+
+#else
+
+#include <limits.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+void process_fd(char * s)
+{
+ long n;
+ int fd;
+ char * endp;
+ struct stat st;
+ n = strtol(s, &endp, 0);
+ if (*endp != 0 || n < 0 || n > (long) INT_MAX) {
+ printf("parsing error\n");
+ return;
+ }
+ fd = (int) n;
+ if (fstat(fd, &st) != -1) {
+ printf("open\n");
+ } else if (errno == EBADF) {
+ printf("closed\n");
+ } else {
+ printf("error %s\n", strerror(errno));
+ }
+}
+
+#endif
+
+int main(int argc, char ** argv)
+{
+ int i;
+ for (i = 1; i < argc; i++) {
+ printf("#%d: ", i);
+ process_fd(argv[i]);
+ }
+ return 0;
+}
--- /dev/null
+let drain pipe =
+ let max = 2048 in
+ let buf = Buffer.create 2048 in
+ let tmp = Bytes.create max in
+ while begin
+ try
+ let len = Unix.read pipe tmp 0 max in
+ Buffer.add_subbytes buf tmp 0 len;
+ len > 0
+ with Unix.Unix_error (Unix.EPIPE, _, _) when false ->
+ false
+ end do () done;
+ Buffer.contents buf
+;;
+
+let run exe args =
+ let out_in, out_out = Unix.pipe () in
+ let err_in, err_out = Unix.pipe () in
+ let args = Array.append [| exe |] args in
+ let pid = Unix.create_process exe args Unix.stdin out_out err_out in
+ Unix.close out_out;
+ Unix.close err_out;
+ let output = drain out_in in
+ let error = drain err_in in
+ Unix.close out_in;
+ Unix.close err_in;
+ let _pid, status = Unix.waitpid [ ] pid in
+ status, output, error
+;;
+
+let _ =
+ ignore (run "cp" [||]);
+ print_endline "success"
+;;
--- /dev/null
+let cat file =
+ let fd = Unix.openfile file [Unix.O_RDONLY] 0 in
+ let buf = Bytes.create 1024 in
+ let rec cat () =
+ let n = Unix.read fd buf 0 (Bytes.length buf) in
+ if n > 0 then (ignore(Unix.write Unix.stdout buf 0 n); cat ())
+ in cat (); Unix.close fd
+
+let out fd txt =
+ ignore (Unix.write_substring fd txt 0 (String.length txt))
+
+let refl =
+ Filename.concat Filename.current_dir_name "reflector.exe"
+
+let test_createprocess () =
+ let f_out =
+ Unix.(openfile "./tmpout.txt" [O_WRONLY;O_TRUNC;O_CREAT;O_CLOEXEC] 0o600) in
+ let f_err =
+ Unix.(openfile "./tmperr.txt" [O_WRONLY;O_TRUNC;O_CREAT;O_CLOEXEC] 0o600) in
+ let (p_exit, p_entrance) =
+ Unix.pipe ~cloexec:true () in
+ let pid =
+ Unix.create_process_env
+ refl
+ [| refl; "i2o"; "i2e"; "o"; "123"; "e"; "456"; "i2o"; "v"; "XVAR" |]
+ [| "XVAR=xvar" |]
+ p_exit f_out f_err in
+ out p_entrance "aaaa\n";
+ out p_entrance "bbbb\n";
+ Unix.close p_entrance;
+ let (_, status) = Unix.waitpid [] pid in
+ Unix.close p_exit; Unix.close f_out; Unix.close f_err;
+ if status <> Unix.WEXITED 0 then
+ out Unix.stdout "!!! reflector exited with an error\n";
+ out Unix.stdout "---- File tmpout.txt\n";
+ cat "./tmpout.txt";
+ out Unix.stdout "---- File tmperr.txt\n";
+ cat "./tmperr.txt";
+ Sys.remove "./tmpout.txt";
+ Sys.remove "./tmperr.txt"
+
+let test_2ampsup1 () = (* 2>&1 redirection, cf. GPR#1105 *)
+ let pid =
+ Unix.create_process
+ refl
+ [| refl; "o"; "123"; "e"; "456"; "o"; "789" |]
+ Unix.stdin Unix.stdout Unix.stdout in
+ let (_, status) = Unix.waitpid [] pid in
+ if status <> Unix.WEXITED 0 then
+ out Unix.stdout "!!! reflector exited with an error\n"
+
+let test_swap12 () = (* swapping stdout and stderr *)
+ (* The test harness doesn't let us check contents of stderr,
+ so just output on stdout (after redirection) *)
+ let pid =
+ Unix.create_process
+ refl
+ [| refl; "e"; "123" |]
+ Unix.stdin Unix.stderr Unix.stdout in
+ let (_, status) = Unix.waitpid [] pid in
+ if status <> Unix.WEXITED 0 then
+ out Unix.stdout "!!! reflector exited with an error\n"
+
+let test_open_process_in () =
+ let ic = Unix.open_process_in (refl ^ " o 123 o 456") in
+ out Unix.stdout (input_line ic ^ "\n");
+ out Unix.stdout (input_line ic ^ "\n");
+ let status = Unix.close_process_in ic in
+ if status <> Unix.WEXITED 0 then
+ out Unix.stdout "!!! reflector exited with an error\n"
+
+let test_open_process_out () =
+ let oc = Unix.open_process_out (refl ^ " i2o i2o i2o") in
+ output_string oc "aa\nbbbb\n"; close_out oc;
+ let status = Unix.close_process_out oc in
+ if status <> Unix.WEXITED 0 then
+ out Unix.stdout "!!! reflector exited with an error\n"
+
+let test_open_process_full () =
+ let ((o, i, e) as res) =
+ Unix.open_process_full
+ (refl ^ " o 123 i2o e 456 i2e v XVAR")
+ [|"XVAR=xvar"|] in
+ output_string i "aa\nbbbb\n"; close_out i;
+ for _i = 1 to 3 do
+ out Unix.stdout (input_line o ^ "\n")
+ done;
+ for _i = 1 to 2 do
+ out Unix.stdout (input_line e ^ "\n")
+ done;
+ let status = Unix.close_process_full res in
+ if status <> Unix.WEXITED 0 then
+ out Unix.stdout "!!! reflector exited with an error\n"
+
+let _ =
+ (* The following 'close' makes things more difficult.
+ Under Unix it works fine, but under Win32 create_process
+ gives an error if one of the standard handles is closed. *)
+ (* Unix.close Unix.stdin; *)
+ out Unix.stdout "** create_process\n";
+ test_createprocess();
+ out Unix.stdout "** create_process 2>&1 redirection\n";
+ test_2ampsup1();
+ out Unix.stdout "** create_process swap 1-2\n";
+ test_swap12();
+ out Unix.stdout "** open_process_in\n";
+ test_open_process_in();
+ out Unix.stdout "** open_process_out\n";
+ test_open_process_out();
+ out Unix.stdout "** open_process_full\n";
+ test_open_process_full()
+
+
--- /dev/null
+** create_process
+---- File tmpout.txt
+aaaa
+123
+<end of file>
+xvar
+---- File tmperr.txt
+bbbb
+456
+** create_process 2>&1 redirection
+123
+456
+789
+** create_process swap 1-2
+123
+** open_process_in
+123
+456
+** open_process_out
+aa
+bbbb
+<end of file>
+** open_process_full
+123
+aa
+xvar
+456
+bbbb
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#if defined(_WIN32)
+#include <fcntl.h>
+#include <io.h>
+#endif
+
+/* A tool to read data from standard input and send it to standard
+ output or standard error. */
+
+void copyline(FILE * in, FILE * out)
+{
+ int c;
+ do {
+ c = getc(in);
+ if (c == EOF) {
+ fputs("<end of file>\n", out);
+ break;
+ }
+ putc(c, out);
+ } while (c != '\n');
+ fflush(out);
+}
+
+/* Command language:
+ i2o copy one line from stdin to stdout
+ i2e copy one line from stdin to stderr
+ o <txt> write <txt> plus newline to stdout
+ e <txt> write <txt> plus newline to stderr
+ v <var> write value of environment variable <env> to stdout
+*/
+
+int main(int argc, char ** argv)
+{
+ int i;
+ char * cmd;
+#if defined(_WIN32)
+ _setmode(_fileno(stdin), _O_BINARY);
+ _setmode(_fileno(stdout), _O_BINARY);
+ _setmode(_fileno(stderr), _O_BINARY);
+#endif
+ i = 1;
+ while (i < argc) {
+ cmd = argv[i];
+ if (strcmp(cmd, "i2o") == 0) {
+ copyline(stdin, stdout);
+ i++;
+ } else if (strcmp(cmd, "i2e") == 0) {
+ copyline(stdin, stderr);
+ i++;
+ } else if (strcmp(cmd, "o") == 0 && i + 1 < argc) {
+ fputs(argv[i + 1], stdout);
+ fputc('\n', stdout);
+ fflush(stdout);
+ i += 2;
+ } else if (strcmp(cmd, "e") == 0 && i + 1 < argc) {
+ fputs(argv[i + 1], stderr);
+ fputc('\n', stderr);
+ fflush(stderr);
+ i += 2;
+ } else if (strcmp(cmd, "v") == 0 && i + 1 < argc) {
+ char * v = getenv(argv[i + 1]);
+ fputs((v == NULL ? "<no such variable>" : v), stdout);
+ fputc('\n', stdout);
+ fflush(stdout);
+ i += 2;
+ } else {
+ fputs("<bad argument>\n", stderr);
+ return 2;
+ }
+ }
+ return 0;
+}
--- /dev/null
+(* Test the Unix.rename function *)
+
+let writefile filename contents =
+ let oc = open_out_bin filename in
+ output_string oc contents;
+ close_out oc
+
+let readfile filename =
+ let ic = open_in_bin filename in
+ let sz = in_channel_length ic in
+ let contents = really_input_string ic sz in
+ close_in ic;
+ contents
+
+let safe_remove filename =
+ try Sys.remove filename with Sys_error _ -> ()
+
+let testrename f1 f2 contents =
+ try
+ Unix.rename f1 f2;
+ if readfile f2 <> contents then print_string "wrong contents!"
+ else if Sys.file_exists f1 then print_string "initial file still exists!"
+ else print_string "passed"
+ with Unix.Unix_error(err, _, _) ->
+ print_string "Unix_error exception: "; print_string (Unix.error_message err)
+
+let testfailure f1 f2 =
+ try
+ Unix.rename f1 f2; print_string "should fail but doesn't!"
+ with Unix.Unix_error _ ->
+ print_string "fails as expected"
+
+let _ =
+ let f1 = "file1.dat" and f2 = "file2.dat" in
+ safe_remove f1; safe_remove f2;
+ print_string "Rename to nonexisting file: ";
+ writefile f1 "abc";
+ testrename f1 f2 "abc";
+ print_newline();
+ print_string "Rename to existing file: ";
+ writefile f1 "def";
+ writefile f2 "xyz";
+ testrename f1 f2 "def";
+ print_newline();
+ print_string "Renaming a nonexisting file: ";
+ testfailure f1 f2;
+ print_newline();
+ print_string "Renaming to a nonexisting directory: ";
+ writefile f1 "abc";
+ testfailure f1 (Filename.concat "nosuchdir" f2);
+ print_newline();
+ safe_remove f1; safe_remove f2
--- /dev/null
+Rename to nonexisting file: passed
+Rename to existing file: passed
+Renaming a nonexisting file: fails as expected
+Renaming to a nonexisting directory: fails as expected
--- /dev/null
+open Unix
+
+let prog_name = "cmdline_prog.exe"
+
+let run args =
+ let out, inp = pipe () in
+ let in_chan = in_channel_of_descr out in
+ set_binary_mode_in in_chan false;
+ let pid = create_process ("./" ^ prog_name) (Array.of_list (prog_name :: args)) Unix.stdin inp Unix.stderr in
+ List.iter (fun arg ->
+ let s = input_line in_chan in
+ Printf.printf "%S -> %S [%s]\n" arg s (if s = arg then "OK" else "FAIL")
+ ) args;
+ close_in in_chan;
+ let _, exit = waitpid [] pid in
+ assert (exit = WEXITED 0)
+
+let () =
+ List.iter run
+ [
+ [""; ""; "\t \011"];
+ ["a"; "b"; "c.txt@!"];
+ ["\""];
+ [" "; " a "; " \" \\\" "];
+ [" \\ \\ \\\\\\"];
+ [" \"hola \""];
+ ["a\tb"];
+ ]
--- /dev/null
+"" -> "" [OK]
+"" -> "" [OK]
+"\t \011" -> "\t \011" [OK]
+"a" -> "a" [OK]
+"b" -> "b" [OK]
+"c.txt@!" -> "c.txt@!" [OK]
+"\"" -> "\"" [OK]
+" " -> " " [OK]
+" a " -> " a " [OK]
+" \" \\\" " -> " \" \\\" " [OK]
+" \\ \\ \\\\\\" -> " \\ \\ \\\\\\" [OK]
+" \"hola \"" -> " \"hola \"" [OK]
+"a\tb" -> "a\tb" [OK]
--- /dev/null
+let () =
+ let fd = Unix.openfile "plop" [O_CREAT; O_WRONLY] 0o666 in
+ let pid =
+ Unix.create_process "echo" [|"echo"; "toto"|] Unix.stdin fd Unix.stderr
+ in
+ Unix.close fd;
+ while fst (Unix.waitpid [WNOHANG] pid) = 0 do
+ Unix.sleepf 0.001
+ done;
+ match Sys.remove "plop" with
+ | () -> print_endline "OK"
+ | exception (Sys_error _) -> print_endline "ERROR"
+++ /dev/null
-let _ =
- let f = Unix.dup ~cloexec:true Unix.stdout in
- let txt = "Some output\n" in
- ignore (Unix.write_substring f txt 0 (String.length txt));
- Unix.close f
+++ /dev/null
-Some output
+++ /dev/null
-let cat file =
- let fd = Unix.openfile file [Unix.O_RDONLY] 0 in
- let buf = Bytes.create 1024 in
- let rec cat () =
- let n = Unix.read fd buf 0 (Bytes.length buf) in
- if n > 0 then (ignore(Unix.write Unix.stdout buf 0 n); cat ())
- in cat (); Unix.close fd
-
-let out fd txt =
- ignore (Unix.write_substring fd txt 0 (String.length txt))
-
-let _ =
- let fd =
- Unix.(openfile "./tmp.txt"
- [O_WRONLY;O_TRUNC;O_CREAT;O_SHARE_DELETE]
- 0o600) in
- out fd "---\n";
- Unix.dup2 ~cloexec:true fd Unix.stderr;
- Unix.close fd;
- out Unix.stderr "Some output\n";
- cat "./tmp.txt";
- Sys.remove "./tmp.txt"
-
-
+++ /dev/null
----
-Some output
+++ /dev/null
-/* Check if file descriptors are open or not */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#ifdef _WIN32
-
-#define WIN32_LEAN_AND_MEAN
-#include <wtypes.h>
-#include <winbase.h>
-#include <winerror.h>
-
-void process_fd(char * s)
-{
- int fd;
- HANDLE h;
- DWORD flags;
-
-#ifdef _WIN64
- h = (HANDLE) _atoi64(s);
-#else
- h = (HANDLE) atoi(s);
-#endif
- if (GetHandleInformation(h, &flags)) {
- printf("open\n");
- } else if (GetLastError() == ERROR_INVALID_HANDLE) {
- printf("closed\n");
- } else {
- printf("error %d\n", GetLastError());
- }
-}
-
-#else
-
-#include <limits.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-void process_fd(char * s)
-{
- long n;
- int fd;
- char * endp;
- struct stat st;
- n = strtol(s, &endp, 0);
- if (*endp != 0 || n < 0 || n > (long) INT_MAX) {
- printf("parsing error\n");
- return;
- }
- fd = (int) n;
- if (fstat(fd, &st) != -1) {
- printf("open\n");
- } else if (errno == EBADF) {
- printf("closed\n");
- } else {
- printf("error %s\n", strerror(errno));
- }
-}
-
-#endif
-
-int main(int argc, char ** argv)
-{
- int i;
- for (i = 1; i < argc; i++) {
- printf("#%d: ", i);
- process_fd(argv[i]);
- }
- return 0;
-}
--- /dev/null
+BASEDIR=../../..
+LIBRARIES=unix
+ADD_COMPFLAGS=-I $(OTOPDIR)/otherlibs/$(UNIXLIBVAR)unix
+LD_PATH=$(TOPDIR)/otherlibs/$(UNIXLIBVAR)unix
+MAIN_MODULE=isatty
+PROGRAM_ARGS=2>/dev/null </dev/null
+
+include $(BASEDIR)/makefiles/Makefile.several
+include $(BASEDIR)/makefiles/Makefile.common
--- /dev/null
+Printf.printf
+ "Unix.isatty Unix.stdin = %b\n\
+ Unix.isatty Unix.stdout = %b\n\
+ Unix.isatty Unix.stderr = %b\n"
+ (Unix.isatty Unix.stdin)
+ (Unix.isatty Unix.stdout)
+ (Unix.isatty Unix.stderr)
--- /dev/null
+Unix.isatty Unix.stdin = false
+Unix.isatty Unix.stdout = false
+Unix.isatty Unix.stderr = false
--- /dev/null
+let console =
+ try
+ Unix.(openfile "/dev/tty" [O_RDWR] 0)
+ with _ ->
+ Unix.(openfile "CONIN$" [O_RDWR] 0)
+in
+Printf.printf "/dev/tty = %b\n" (Unix.isatty console)
--- /dev/null
+test "$TOOLCHAIN" = "msvc" || test "$TOOLCHAIN" = "mingw"
--- /dev/null
+/dev/tty = true
+++ /dev/null
-let drain pipe =
- let max = 2048 in
- let buf = Buffer.create 2048 in
- let tmp = Bytes.create max in
- while begin
- try
- let len = Unix.read pipe tmp 0 max in
- Buffer.add_subbytes buf tmp 0 len;
- len > 0
- with Unix.Unix_error (Unix.EPIPE, _, _) when false ->
- false
- end do () done;
- Buffer.contents buf
-;;
-
-let run exe args =
- let out_in, out_out = Unix.pipe () in
- let err_in, err_out = Unix.pipe () in
- let args = Array.append [| exe |] args in
- let pid = Unix.create_process exe args Unix.stdin out_out err_out in
- Unix.close out_out;
- Unix.close err_out;
- let output = drain out_in in
- let error = drain err_in in
- Unix.close out_in;
- Unix.close err_in;
- let _pid, status = Unix.waitpid [ ] pid in
- status, output, error
-;;
-
-let _ =
- ignore (run "cp" [||]);
- print_endline "success"
-;;
+++ /dev/null
-let cat file =
- let fd = Unix.openfile file [Unix.O_RDONLY] 0 in
- let buf = Bytes.create 1024 in
- let rec cat () =
- let n = Unix.read fd buf 0 (Bytes.length buf) in
- if n > 0 then (ignore(Unix.write Unix.stdout buf 0 n); cat ())
- in cat (); Unix.close fd
-
-let out fd txt =
- ignore (Unix.write_substring fd txt 0 (String.length txt))
-
-let refl =
- Filename.concat Filename.current_dir_name "reflector.exe"
-
-let test_createprocess () =
- let f_out =
- Unix.(openfile "./tmpout.txt" [O_WRONLY;O_TRUNC;O_CREAT;O_CLOEXEC] 0o600) in
- let f_err =
- Unix.(openfile "./tmperr.txt" [O_WRONLY;O_TRUNC;O_CREAT;O_CLOEXEC] 0o600) in
- let (p_exit, p_entrance) =
- Unix.pipe ~cloexec:true () in
- let pid =
- Unix.create_process_env
- refl
- [| refl; "i2o"; "i2e"; "o"; "123"; "e"; "456"; "i2o"; "v"; "XVAR" |]
- [| "XVAR=xvar" |]
- p_exit f_out f_err in
- out p_entrance "aaaa\n";
- out p_entrance "bbbb\n";
- Unix.close p_entrance;
- let (_, status) = Unix.waitpid [] pid in
- Unix.close p_exit; Unix.close f_out; Unix.close f_err;
- if status <> Unix.WEXITED 0 then
- out Unix.stdout "!!! reflector exited with an error\n";
- out Unix.stdout "---- File tmpout.txt\n";
- cat "./tmpout.txt";
- out Unix.stdout "---- File tmperr.txt\n";
- cat "./tmperr.txt";
- Sys.remove "./tmpout.txt";
- Sys.remove "./tmperr.txt"
-
-let test_2ampsup1 () = (* 2>&1 redirection, cf. GPR#1105 *)
- let pid =
- Unix.create_process
- refl
- [| refl; "o"; "123"; "e"; "456"; "o"; "789" |]
- Unix.stdin Unix.stdout Unix.stdout in
- let (_, status) = Unix.waitpid [] pid in
- if status <> Unix.WEXITED 0 then
- out Unix.stdout "!!! reflector exited with an error\n"
-
-let test_swap12 () = (* swapping stdout and stderr *)
- (* The test harness doesn't let us check contents of stderr,
- so just output on stdout (after redirection) *)
- let pid =
- Unix.create_process
- refl
- [| refl; "e"; "123" |]
- Unix.stdin Unix.stderr Unix.stdout in
- let (_, status) = Unix.waitpid [] pid in
- if status <> Unix.WEXITED 0 then
- out Unix.stdout "!!! reflector exited with an error\n"
-
-let test_open_process_in () =
- let ic = Unix.open_process_in (refl ^ " o 123 o 456") in
- out Unix.stdout (input_line ic ^ "\n");
- out Unix.stdout (input_line ic ^ "\n");
- let status = Unix.close_process_in ic in
- if status <> Unix.WEXITED 0 then
- out Unix.stdout "!!! reflector exited with an error\n"
-
-let test_open_process_out () =
- let oc = Unix.open_process_out (refl ^ " i2o i2o i2o") in
- output_string oc "aa\nbbbb\n"; close_out oc;
- let status = Unix.close_process_out oc in
- if status <> Unix.WEXITED 0 then
- out Unix.stdout "!!! reflector exited with an error\n"
-
-let test_open_process_full () =
- let ((o, i, e) as res) =
- Unix.open_process_full
- (refl ^ " o 123 i2o e 456 i2e v XVAR")
- [|"XVAR=xvar"|] in
- output_string i "aa\nbbbb\n"; close_out i;
- for _i = 1 to 3 do
- out Unix.stdout (input_line o ^ "\n")
- done;
- for _i = 1 to 2 do
- out Unix.stdout (input_line e ^ "\n")
- done;
- let status = Unix.close_process_full res in
- if status <> Unix.WEXITED 0 then
- out Unix.stdout "!!! reflector exited with an error\n"
-
-let _ =
- (* The following 'close' makes things more difficult.
- Under Unix it works fine, but under Win32 create_process
- gives an error if one of the standard handles is closed. *)
- (* Unix.close Unix.stdin; *)
- out Unix.stdout "** create_process\n";
- test_createprocess();
- out Unix.stdout "** create_process 2>&1 redirection\n";
- test_2ampsup1();
- out Unix.stdout "** create_process swap 1-2\n";
- test_swap12();
- out Unix.stdout "** open_process_in\n";
- test_open_process_in();
- out Unix.stdout "** open_process_out\n";
- test_open_process_out();
- out Unix.stdout "** open_process_full\n";
- test_open_process_full()
-
-
+++ /dev/null
-** create_process
----- File tmpout.txt
-aaaa
-123
-<end of file>
-xvar
----- File tmperr.txt
-bbbb
-456
-** create_process 2>&1 redirection
-123
-456
-789
-** create_process swap 1-2
-123
-** open_process_in
-123
-456
-** open_process_out
-aa
-bbbb
-<end of file>
-** open_process_full
-123
-aa
-xvar
-456
-bbbb
+++ /dev/null
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#if defined(_WIN32)
-#include <fcntl.h>
-#include <io.h>
-#endif
-
-/* A tool to read data from standard input and send it to standard
- output or standard error. */
-
-void copyline(FILE * in, FILE * out)
-{
- int c;
- do {
- c = getc(in);
- if (c == EOF) {
- fputs("<end of file>\n", out);
- break;
- }
- putc(c, out);
- } while (c != '\n');
- fflush(out);
-}
-
-/* Command language:
- i2o copy one line from stdin to stdout
- i2e copy one line from stdin to stderr
- o <txt> write <txt> plus newline to stdout
- e <txt> write <txt> plus newline to stderr
- v <var> write value of environment variable <env> to stdout
-*/
-
-int main(int argc, char ** argv)
-{
- int i;
- char * cmd;
-#if defined(_WIN32)
- _setmode(_fileno(stdin), _O_BINARY);
- _setmode(_fileno(stdout), _O_BINARY);
- _setmode(_fileno(stderr), _O_BINARY);
-#endif
- i = 1;
- while (i < argc) {
- cmd = argv[i];
- if (strcmp(cmd, "i2o") == 0) {
- copyline(stdin, stdout);
- i++;
- } else if (strcmp(cmd, "i2e") == 0) {
- copyline(stdin, stderr);
- i++;
- } else if (strcmp(cmd, "o") == 0 && i + 1 < argc) {
- fputs(argv[i + 1], stdout);
- fputc('\n', stdout);
- fflush(stdout);
- i += 2;
- } else if (strcmp(cmd, "e") == 0 && i + 1 < argc) {
- fputs(argv[i + 1], stderr);
- fputc('\n', stderr);
- fflush(stderr);
- i += 2;
- } else if (strcmp(cmd, "v") == 0 && i + 1 < argc) {
- char * v = getenv(argv[i + 1]);
- fputs((v == NULL ? "<no such variable>" : v), stdout);
- fputc('\n', stdout);
- fflush(stdout);
- i += 2;
- } else {
- fputs("<bad argument>\n", stderr);
- return 2;
- }
- }
- return 0;
-}
+++ /dev/null
-open Unix
-
-let prog_name = "cmdline_prog.exe"
-
-let run args =
- let out, inp = pipe () in
- let in_chan = in_channel_of_descr out in
- set_binary_mode_in in_chan false;
- let pid = create_process ("./" ^ prog_name) (Array.of_list (prog_name :: args)) Unix.stdin inp Unix.stderr in
- List.iter (fun arg ->
- let s = input_line in_chan in
- Printf.printf "%S -> %S [%s]\n" arg s (if s = arg then "OK" else "FAIL")
- ) args;
- close_in in_chan;
- let _, exit = waitpid [] pid in
- assert (exit = WEXITED 0)
-
-let () =
- List.iter run
- [
- [""; ""; "\t \011"];
- ["a"; "b"; "c.txt@!"];
- ["\""];
- [" "; " a "; " \" \\\" "];
- [" \\ \\ \\\\\\"];
- [" \"hola \""];
- ["a\tb"];
- ]
+++ /dev/null
-"" -> "" [OK]
-"" -> "" [OK]
-"\t \011" -> "\t \011" [OK]
-"a" -> "a" [OK]
-"b" -> "b" [OK]
-"c.txt@!" -> "c.txt@!" [OK]
-"\"" -> "\"" [OK]
-" " -> " " [OK]
-" a " -> " a " [OK]
-" \" \\\" " -> " \" \\\" " [OK]
-" \\ \\ \\\\\\" -> " \\ \\ \\\\\\" [OK]
-" \"hola \"" -> " \"hola \"" [OK]
-"a\tb" -> "a\tb" [OK]
--- /dev/null
+BASEDIR=../../..
+LIBRARIES=unix
+ADD_COMPFLAGS=-I $(OTOPDIR)/otherlibs/$(UNIXLIBVAR)unix
+LD_PATH=$(TOPDIR)/otherlibs/$(UNIXLIBVAR)unix
+MAIN_MODULE=exec
+
+test:
+ @if grep -q HAS_EXECVPE $(OTOPDIR)/byterun/caml/s.h; \
+ then echo " ... testing => skipped (using the system-provided execvpe())"; \
+ else $(MAKE) compile && $(SET_LD_PATH) $(MAKE) myrun; \
+ fi
+
+myrun:
+ @printf " ... testing with"
+ @if $(NATIVECODE_ONLY); then : ; else \
+ printf " ocamlc"; \
+ ./exec.run "$(MYRUNTIME) ./program.byte$(EXE)" $(EXEC_ARGS) \
+ >$(MAIN_MODULE).result \
+ && $(DIFF) $(MAIN_MODULE).reference $(MAIN_MODULE).result \
+ >/dev/null; \
+ fi \
+ && if $(BYTECODE_ONLY); then : ; else \
+ printf " ocamlopt"; \
+ ./exec.run ./program.native$(EXE) $(EXEC_ARGS) \
+ > $(MAIN_MODULE).result \
+ && $(DIFF) $(MAIN_MODULE).reference $(MAIN_MODULE).result \
+ >/dev/null; \
+ fi \
+ && echo " => passed" || echo " => failed"
+
+include $(BASEDIR)/makefiles/Makefile.one
+include $(BASEDIR)/makefiles/Makefile.common
--- /dev/null
+open Printf
+
+let _ =
+ let arg = Array.sub Sys.argv 1 (Array.length Sys.argv - 1) in
+ let env = Array.append [|"FOO=foo"|] (Unix.environment()) in
+ try
+ Unix.execvpe arg.(0) arg env
+ with
+ | Unix.Unix_error(Unix.ENOENT, _, arg) ->
+ eprintf "No such file %s\n" arg; exit 2
+ | Unix.Unix_error(Unix.EACCES, _, arg) ->
+ eprintf "Permission denied %s\n" arg; exit 2
+ | Unix.Unix_error(err, fn, arg) ->
+ eprintf "Other error %s - %s - %s\n" (Unix.error_message err) fn arg;
+ exit 4
--- /dev/null
+## Test 1: a binary program in the path
+## Test 2: a #! script in the path
+--- subdir/script1
+FOO is foo, BAR is bar, BUZ is
+3 arguments: 2 3 4
+## Test 3: a script without #! in the path
+--- subdir/script2
+FOO is foo, BAR is bar, BUZ is
+3 arguments: 5 6 7
+## Test 4: a script in the current directory
+--- ./script3
+FOO is foo, BAR is bar, BUZ is
+2 arguments: 8 9
+## Test 5: a non-existent program
+No such file nosuchprogram
+## Test 6: a non-executable program
+Permission denied nonexec
+## Test 7: a script in the current directory
+No such file script3
--- /dev/null
+#!/bin/sh
+
+program=$1
+if test -z "$program"; then echo "Usage: exec.run <program>" 1&>2; exit 2; fi
+
+exec 2>&1
+
+export PATH="/bin:/usr/bin:./subdir:"
+export BAR=bar
+
+echo "## Test 1: a binary program in the path"
+$program ls / > /dev/null || echo "ls failed"
+echo "## Test 2: a #! script in the path"
+$program script1 2 3 4 || echo "script1 failed"
+echo "## Test 3: a script without #! in the path"
+$program script2 5 6 7 || echo "script2 failed"
+echo "## Test 4: a script in the current directory"
+$program script3 8 9 || echo "script3 failed"
+echo "## Test 5: a non-existent program"
+$program nosuchprogram
+echo "## Test 6: a non-executable program"
+$program nonexec
+
+export PATH="/bin:/usr/bin:./subdir"
+echo "## Test 7: a script in the current directory"
+$program script3 9 && echo "script3 should have failed"
+exit 0
--- /dev/null
+#!/bin/sh
+echo "--- ./script3"
+echo "FOO is $FOO, BAR is $BAR, BUZ is $BUZ"
+echo "$# arguments: $*"
+
--- /dev/null
+echo "This script lacks the x bit and should not run!"
+
--- /dev/null
+#!/bin/sh
+echo "--- subdir/script1"
+echo "FOO is $FOO, BAR is $BAR, BUZ is $BUZ"
+echo "$# arguments: $*"
--- /dev/null
+echo "--- subdir/script2"
+echo "FOO is $FOO, BAR is $BAR, BUZ is $BUZ"
+echo "$# arguments: $*"
--- /dev/null
+BASEDIR=../../..
+LIBRARIES=unix
+ADD_COMPFLAGS= \
+ -I $(OTOPDIR)/otherlibs/$(UNIXLIBVAR)unix \
+ -strict-sequence -safe-string -w A -warn-error A
+LD_PATH=$(TOPDIR)/otherlibs/$(UNIXLIBVAR)unix
+C_FILES=stubs
+
+.PHONY: test
+test:
+ @if echo 'let () = exit (if Sys.win32 then 0 else 1)' | $(OCAML) -stdin; then \
+ $(MAKE) check; \
+ else \
+ $(MAKE) SKIP=true C_FILES= run-all; \
+ fi
+
+include $(BASEDIR)/makefiles/Makefile.several
+include $(BASEDIR)/makefiles/Makefile.common
--- /dev/null
+#define CAML_INTERNALS
+
+#include <caml/mlvalues.h>
+#include <caml/alloc.h>
+#include <caml/memory.h>
+#include <caml/fail.h>
+#include <caml/osdeps.h>
+
+#include <windows.h>
+
+CAMLprim value caml_SetEnvironmentVariable(value s1, value s2)
+{
+ WCHAR *w1, *w2;
+ w1 = caml_stat_strdup_to_utf16(String_val(s1));
+ w2 = caml_stat_strdup_to_utf16(String_val(s2));
+ SetEnvironmentVariableW(w1, w2);
+ caml_stat_free(w1);
+ caml_stat_free(w2);
+ return Val_unit;
+}
--- /dev/null
+external set_environment_variable: string -> string -> unit = "caml_SetEnvironmentVariable"
+
+let find_env s =
+ let env = Unix.environment () in
+ let rec loop i =
+ if i >= Array.length env then
+ None
+ else begin
+ let e = env.(i) in
+ let pos = String.index e '=' in
+ if String.sub e 0 pos = s then
+ Some (String.sub e (pos+1) (String.length e - pos - 1))
+ else
+ loop (i+1)
+ end
+ in
+ loop 0
+
+let print title = function
+ | None ->
+ Printf.printf "%s -> None\n%!" title
+ | Some s ->
+ Printf.printf "%s -> Some %S\n%!" title s
+
+let foo = "FOO"
+
+let () =
+ set_environment_variable foo "BAR";
+ print "Sys.getenv FOO" (Sys.getenv_opt foo);
+ print "Unix.environment FOO" (find_env foo)
--- /dev/null
+Sys.getenv FOO -> None
+Unix.environment FOO -> None
--- /dev/null
+(* This test is disabled (see test_env2.precheck) as it fails due to MPR#4499:
+ the Windows POSIX environment does not get updated when using the native
+ Windows API SetEnvironmentVariable. *)
+
+external set_environment_variable: string -> string -> unit = "caml_SetEnvironmentVariable"
+
+let print title = function
+ | None ->
+ Printf.printf "%s -> None\n%!" title
+ | Some s ->
+ Printf.printf "%s -> Some %S\n%!" title s
+
+let foo = "FOO"
+
+let () =
+ set_environment_variable foo "BAR";
+ print "Sys.getenv FOO" (Sys.getenv_opt foo)
--- /dev/null
+# test_env2.ml disabled because it fails due to the fact that
+# Windows POSIX environment is not updated when using the native
+# API SetEnvironmentVariable (see MPR#4499)
+exit 1
--- /dev/null
+Sys.getenv FOO -> Some "BAR"
--- /dev/null
+BASEDIR=../../..
+LIBRARIES=unix
+ADD_COMPFLAGS=-I $(OTOPDIR)/otherlibs/$(UNIXLIBVAR)unix
+LD_PATH=$(TOPDIR)/otherlibs/$(UNIXLIBVAR)unix
+C_FILES=fakeclock
+MAIN_MODULE=test
+TEST_TEMP_FILES=dst-file non-dst-file
+
+ifeq ($(OS),Windows_NT)
+test:
+ @TZ=utc touch -m -t 201707011200 dst-file
+ @TZ=utc touch -m -t 201702011200 non-dst-file
+ @$(MAKE) default
+else
+skip:
+ @echo " ... testing => skipped (not on Windows)"
+endif
+
+include $(BASEDIR)/makefiles/Makefile.one
+include $(BASEDIR)/makefiles/Makefile.common
--- /dev/null
+/**************************************************************************/
+/* */
+/* OCaml */
+/* */
+/* David Allsopp, OCaml Labs, Cambridge. */
+/* */
+/* Copyright 2017 MetaStack Solutions Ltd. */
+/* */
+/* All rights reserved. This file is distributed under the terms of */
+/* the GNU Lesser General Public License version 2.1, with the */
+/* special exception on linking described in the file LICENSE. */
+/* */
+/**************************************************************************/
+
+#include <windows.h>
+
+typedef union ufiletime_int64
+{
+ unsigned __int64 scalar;
+ FILETIME ft;
+} filetime_int64;
+
+static filetime_int64 clk;
+static DWORD wall = 0;
+static unsigned __int64 bias = 0LL;
+
+BOOL WINAPI FakeConvert(const FILETIME* lpFileTime, LPFILETIME lpLocalFileTime)
+{
+ filetime_int64 result;
+ memcpy(&result.ft, lpFileTime, sizeof(FILETIME));
+ result.scalar += bias;
+ memcpy(lpLocalFileTime, &result.ft, sizeof(FILETIME));
+ return TRUE;
+}
+
+void WINAPI FakeClock(LPFILETIME result)
+{
+ DWORD now = GetTickCount();
+ /* Take a risk on this: GetTickCount64 is not available in Windows XP... */
+ /* GetTickCount is in ms, clk.scalar is in 100ns intervals */
+ clk.scalar += ((now - wall) * 10000);
+ wall = now;
+
+ memcpy(result, &clk.ft, sizeof(FILETIME));
+
+ return;
+}
+
+/* Assuming that nowhere transitions DST in February... */
+static short mon_days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+void SetBias(void)
+{
+ TIME_ZONE_INFORMATION tzInfo;
+ filetime_int64 dst;
+ SYSTEMTIME dst_start;
+
+ switch (GetTimeZoneInformation(&tzInfo)) {
+ case TIME_ZONE_ID_INVALID:
+ case TIME_ZONE_ID_UNKNOWN:
+ /* Default to GMT */
+ tzInfo.DaylightDate.wYear = 0;
+ tzInfo.DaylightDate.wMonth = 3;
+ tzInfo.DaylightDate.wDay = 5;
+ tzInfo.DaylightDate.wDayOfWeek = 0;
+ tzInfo.DaylightDate.wHour = 1;
+ tzInfo.StandardBias = 0;
+ tzInfo.DaylightBias = -60;
+ }
+
+ /* If wYear is given, then DaylightDate is a date, otherwise the transition
+ * is the wDay'th wDayOfWeek of wMonth (where the 5th wDayOfWeek means last
+ * when there are only 4 wDayOfWeek's in wMonth)
+ */
+ if (!tzInfo.DaylightDate.wYear) {
+ int wday;
+ /* Get the clock date in order to determine wYear */
+ FileTimeToSystemTime(&clk.ft, &dst_start);
+ /* Back-up DST transition details */
+ dst_start.wDay = tzInfo.DaylightDate.wDay;
+ dst_start.wDayOfWeek = tzInfo.DaylightDate.wDayOfWeek;
+ /* Set tzInfo to be first day of month on DST change */
+ tzInfo.DaylightDate.wYear = dst_start.wYear;
+ tzInfo.DaylightDate.wDay = 1;
+ /* Normalise tzInfo.DaylightDate (need wDayOfWeek) */
+ SystemTimeToFileTime(&tzInfo.DaylightDate, &dst.ft);
+ FileTimeToSystemTime(&dst.ft, &tzInfo.DaylightDate);
+ /* First to first weekday of DST transition */
+ if ((wday = dst_start.wDayOfWeek - tzInfo.DaylightDate.wDayOfWeek) < 0)
+ tzInfo.DaylightDate.wDay += wday + 7;
+ else
+ tzInfo.DaylightDate.wDay += wday;
+ tzInfo.DaylightDate.wDayOfWeek =
+ (mon_days[tzInfo.DaylightDate.wMonth] - tzInfo.DaylightDate.wDay) / 7;
+ if (dst_start.wDay > tzInfo.DaylightDate.wDayOfWeek)
+ dst_start.wDay = tzInfo.DaylightDate.wDayOfWeek;
+ tzInfo.DaylightDate.wDay += 7 * dst_start.wDay;
+ }
+ SystemTimeToFileTime(&tzInfo.DaylightDate, &dst.ft);
+ bias = -(clk.scalar >= dst.scalar ? tzInfo.DaylightBias
+ : tzInfo.StandardBias) * 600000000LL;
+ return;
+}
+
+void ReplaceFunction(char* fn, char* module, void* pNew)
+{
+ HMODULE hModule = LoadLibrary(module);
+ void* pCode;
+ DWORD dwOldProtect = 0;
+#ifdef _M_X64
+ SIZE_T jmpSize = 13;
+ BYTE jump[13];
+#else
+ SIZE_T jmpSize = 5;
+ BYTE jump[5];
+#endif
+ SIZE_T bytesWritten;
+
+ /* Patching is permitted to fail (missing API, etc.) */
+ if (!hModule) return;
+ pCode = GetProcAddress(hModule, fn);
+ if (!pCode) return;
+
+ /* Overwrite the code with a jump to our function */
+ if (VirtualProtect(pCode, jmpSize, PAGE_EXECUTE_READWRITE, &dwOldProtect)) {
+#ifdef _M_X64
+ jump[0] = 0x49; /* REX.WB prefix */
+ jump[1] = 0xBB; /* MOV r11, ... */
+ memcpy(jump + 2, &pNew, 8); /* imm64 */
+ jump[10] = 0x41; /* REX.B prefix */
+ jump[11] = 0xFF; /* JMP */
+ jump[12] = 0xE3; /* r11 */
+#else
+ /* JMP rel32 to FakeClock */
+ DWORD dwRelativeAddr = (DWORD)pNew - ((DWORD)pCode + 5);
+ jump[0] = 0xE9;
+ memcpy(jump + 1, &dwRelativeAddr, 4);
+#endif
+
+ if (WriteProcessMemory(GetCurrentProcess(), pCode, jump, jmpSize, NULL)) {
+ VirtualProtect(pCode, jmpSize, dwOldProtect, &dwOldProtect);
+ }
+ }
+
+ return;
+}
+
+#define CAML_NAME_SPACE
+#include <caml/mlvalues.h>
+#include <caml/memory.h>
+
+static int patched = 0;
+
+CAMLprim value set_fake_clock(value time)
+{
+ CAMLparam1(time);
+
+ clk.scalar = Int64_val(time);
+ wall = GetTickCount();
+ SetBias();
+
+ if (!patched) {
+ patched = 1;
+ /* Patch Windows 8 and later (UCRT) */
+ ReplaceFunction("GetSystemTimePreciseAsFileTime",
+ "api-ms-win-core-sysinfo-l1-2-1.dll", &FakeClock);
+ ReplaceFunction("GetSystemTimeAsFileTime",
+ "api-ms-win-core-sysinfo-l1-2-1.dll", &FakeClock);
+ /* Patch Windows 7 API Set */
+ ReplaceFunction("GetSystemTimeAsFileTime",
+ "api-ms-win-core-sysinfo-l1-1-0.dll", &FakeClock);
+ /* Patch Windows 7 and previous (standard CRT) */
+ ReplaceFunction("GetSystemTimeAsFileTime",
+ "kernel32.dll", &FakeClock);
+ ReplaceFunction("FileTimeToLocalFileTime", "kernel32.dll", &FakeConvert);
+ }
+
+ CAMLreturn(Val_unit);
+}
--- /dev/null
+open Unix
+
+external set_fake_clock : int64 -> unit = "set_fake_clock"
+
+let real_time tm = {tm with tm_year = tm.tm_year + 1900; tm_mon = tm.tm_mon + 1}
+
+let print_time () =
+ let time = Unix.time () |> Unix.gmtime |> real_time in
+ Printf.printf "System clock: %04d/%02d/%02d %02d:%02d\n" time.tm_year
+ time.tm_mon
+ time.tm_mday
+ time.tm_hour
+ time.tm_min
+
+let test_mtime file =
+ let time = (Unix.stat file).st_mtime |> Unix.gmtime |> real_time in
+ Printf.printf "Read mtime for %s = %04d/%02d/%02d %02d:%02d:%02d\n"
+ file
+ time.tm_year time.tm_mon time.tm_mday time.tm_hour time.tm_min time.tm_sec
+
+let _ =
+ (* 1-Jun-2017 20:33:10.42+0000 *)
+ set_fake_clock 0x1D2DB1648916FA0L;
+ print_time ();
+ test_mtime "dst-file";
+ test_mtime "non-dst-file";
+ (* 1-Feb-2017 20:33:10.42+0000 *)
+ set_fake_clock 0x1D27CCA66FF6FA0L;
+ print_time ();
+ test_mtime "dst-file";
+ test_mtime "non-dst-file"
--- /dev/null
+System clock: 2017/06/01 20:33
+Read mtime for dst-file = 2017/07/01 12:00:00
+Read mtime for non-dst-file = 2017/02/01 12:00:00
+System clock: 2017/02/01 20:33
+Read mtime for dst-file = 2017/07/01 12:00:00
+Read mtime for non-dst-file = 2017/02/01 12:00:00
--- /dev/null
+BASEDIR=../../..
+LIBRARIES=unix
+ADD_COMPFLAGS=-I $(OTOPDIR)/otherlibs/$(UNIXLIBVAR)unix
+LD_PATH=$(TOPDIR)/otherlibs/$(UNIXLIBVAR)unix
+MAIN_MODULE=test
+TEST_TEMP_FILES=link1 link2 test.txt
+
+test:
+ @if $(OCAML) $(ADD_COMPFLAGS) unix.cma precheck.ml; then \
+ $(MAKE) default; \
+ else \
+ echo " ... testing => skipped (not on Windows and/or symlinks not allowed)"; \
+ fi
+
+include $(BASEDIR)/makefiles/Makefile.one
+include $(BASEDIR)/makefiles/Makefile.common
--- /dev/null
+let () =
+ exit (if Sys.win32 && Unix.has_symlink () then 0 else 1)
--- /dev/null
+let link1 = "link1"
+let link2 = "link2"
+
+let link_exists s =
+ try (Unix.lstat s).Unix.st_kind = Unix.S_LNK with _ -> false
+
+let main () =
+ close_out (open_out "test.txt");
+ if link_exists link1 then Sys.remove link1;
+ if link_exists link2 then Sys.remove link2;
+ Unix.symlink ~to_dir:false ".\\test.txt" link1;
+ assert ((Unix.stat link1).Unix.st_kind = Unix.S_REG);
+ print_endline "Unix.symlink works with backwards slashes";
+ Unix.symlink ~to_dir:false "./test.txt" link2;
+ assert ((Unix.stat link2).Unix.st_kind = Unix.S_REG);
+ print_endline "Unix.symlink works with forward slashes"
+
+let () =
+ Unix.handle_unix_error main ()
--- /dev/null
+Unix.symlink works with backwards slashes
+Unix.symlink works with forward slashes
| exception Failure _ -> "failure"
| exception Invalid_argument _ -> "invalid argument"
| None -> "None"
- ) in
+ ) [@ocaml.warning "-8"] in
assert false
with
Match_failure _ ->
[%%expect{|
type t = Foo of unit | Bar
Line _, characters 0-6:
-Warning 3: deprecated: Foo
-Line _:
-Error: Some fatal warnings were triggered (1 occurrences)
+Error (warning 3): deprecated: Foo
|}];;
function
Foo _ -> () | Bar -> ();;
(* "Foo _", the whole construct is deprecated *)
[%%expect{|
Line _, characters 0-5:
-Warning 3: deprecated: Foo
-Line _:
-Error: Some fatal warnings were triggered (1 occurrences)
+Error (warning 3): deprecated: Foo
|}];;
on "open List" as whole rather than "List" *)
[%%expect{|
Line _, characters 0-9:
-Warning 33: unused open List.
-Line _:
-Error: Some fatal warnings were triggered (1 occurrences)
+Error (warning 33): unused open List.
|}];;
type unknown += Foo;;
let dae = ref ((am -. !ae +. de *. sin !ae) /. (1.0 -. de *. cos !ae)) in
ae := !ae +. !dae;
incr k;
- while !k < 10 or abs_float !dae >= 1e-12 do
+ while !k < 10 || abs_float !dae >= 1e-12 do
dae := (am -. !ae +. de *. sin !ae) /. (1.0 -. de *. cos !ae);
ae := !ae +. !dae;
incr k
type move = { x1: int; y1: int; x2: int; y2: int }
-let moves = Array.create 31 {x1=0;y1=0;x2=0;y2=0}
+let moves = Array.make 31 {x1=0;y1=0;x2=0;y2=0}
let counter = ref 0
let rec pp_form fmt = function
| Constant b ->
- fprintf fmt "%b" b
+ fprintf fmt "%B" b
| And a ->
fprintf fmt "And[@[%a@]]" (fun fmt -> Array.iter (pp_var fmt)) a
| Or a ->
let test_keep_last d d' =
Printf.printf "## Keep last %i alive, check each %i ##\n%!" (n/d) (n/d');
- let keep_alive = Array.create (n/d) Int64.zero in
+ let keep_alive = Array.make (n/d) Int64.zero in
let next x =
let x' = hashcons (Int64.of_int x) in
Array.set keep_alive (x mod (n/d)) x';
type t = Leaf of int | Branch of t * t
-let a = [| 0.0 |]
+type floatref = { mutable f : float }
+
+let a = { f = 0.0 }
let rec allocate_lots m = function
| 0 -> Leaf m
c -. a
let () =
- let n = measure (fun () -> a.(0) <- Gc.minor_words ()) in
+ let n = measure (fun () -> a.f <- Gc.minor_words ()) in
(* Gc.minor_words should not allocate, although bytecode
generally boxes the floats *)
assert (n < 10.);
let rand_string () =
let len = Random.int 10 in
- let s = String.create len in
+ let s = Bytes.create len in
for i = 0 to len-1 do
- s.[i] <- Char.chr (Random.int 256);
+ Bytes.set s i (Char.chr (Random.int 256));
done;
s
;;
(************************************************************************)
let lold = [
- "Sort.list", Sort.list, true;
"lmerge_3", lmerge_3, false;
"lmerge_4a", lmerge_4a, true;
];;
done;
Printf.printf "\n";
- ignore (String.create (1048576 * !mem));
+ ignore (Bytes.create (1048576 * !mem));
Gc.full_major ();
(*
let a2l = Array.to_list in
let (_, f2, _) = List.nth lold i in
testonly name stable f1 f2 ll ll;
done;
- testonly "Sort.array" false Sort.array Sort.array al al;
for i = 0 to List.length lnew - 1 do
let (name, f1, stable) = List.nth lnew i in
let (_, f2, _) = List.nth lnew i in
let (name, f, stable) = List.nth lold i in bb name f ll;
let (name, f, stable) = List.nth lold i in bc name f ll;
done;
- ba "Sort.array" Sort.array al;
- bb "Sort.array" Sort.array al;
- bc "Sort.array" Sort.array al;
for i = 0 to List.length lnew - 1 do
let (name, f, stable) = List.nth lnew i in ba name f lc;
let (name, f, stable) = List.nth lnew i in bb name f lc;
for i = 0 to List.length lold - 1 do
let (name, f, stable) = List.nth lold i in b name f ll;
done;
- b "Sort.array" Sort.array al;
for i = 0 to List.length lnew - 1 do
let (name, f, stable) = List.nth lnew i in b name f lc;
done;
--- /dev/null
+#**************************************************************************
+#* *
+#* OCaml *
+#* *
+#* Xavier Clerc, SED, 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 GNU Lesser General Public License version 2.1, with the *
+#* special exception on linking described in the file LICENSE. *
+#* *
+#**************************************************************************
+
+BASEDIR=../..
+SHOULD_FAIL=
+
+
+compile:
+ @for file in *.ml; do \
+ printf " ... testing '$$file' with native"; \
+ if $(BYTECODE_ONLY); then \
+ echo " => skipped"; \
+ else \
+ rm -f log $${file}.exe.$(O) $${file}_stub$(EXE); \
+ ( set -x; \
+ $(OCAMLOPT) -w a -output-complete-obj -o $${file}.exe.$(O) \
+ $${file} && \
+ $(MKEXE) -I$(CTOPDIR)/byterun -o $${file}_stub$(EXE) \
+ $${file}.exe.$(O) $(NATIVECCLIBS) $${file}_stub.c && \
+ ./$${file}_stub$(EXE) ) > log 2>&1 \
+ && echo " => passed" || (echo " => failed" && cat log); \
+ fi \
+ done
+ @for file in *.ml; do \
+ printf " ... testing '$$file' with byte"; \
+ if [ $(TOOLCHAIN) = msvc ]; then \
+ echo " => skipped"; \
+ else \
+ rm -f log $${file}.bc.$(O) $${file}_bc_stub$(EXE); \
+ ( set -x; \
+ $(OCAMLC) -ccopt "-I$(CTOPDIR)/byterun" -w a -output-complete-obj\
+ -o $${file}.bc.$(O) $${file} && \
+ $(MKEXE) -I$(CTOPDIR)/byterun -o $${file}_bc_stub$(EXE) \
+ $${file}.bc.$(O) $(BYTECCLIBS) $${file}_stub.c && \
+ ./$${file}_bc_stub$(EXE) ) > log 2>&1 \
+ && echo " => passed" || (echo " => failed" && cat log); \
+ fi; \
+ done
+ @rm -f log
+
+promote:
+
+clean: defaultclean
+ @rm -f ./a.out
+
+include $(BASEDIR)/makefiles/Makefile.common
--- /dev/null
+let () = Printf.printf "Test!!\n%!"
--- /dev/null
+#include <caml/mlvalues.h>
+#include <caml/alloc.h>
+#include <caml/callback.h>
+#include <caml/memory.h>
+
+int main(int argc, char ** argv){
+
+ caml_startup(argv);
+ return 0;
+}
let i = int_inj 3 in
let s = string_inj "abc" in
- Printf.printf "%b\n%!" (int_proj i = None);
- Printf.printf "%b\n%!" (int_proj s = None);
- Printf.printf "%b\n%!" (string_proj i = None);
- Printf.printf "%b\n%!" (string_proj s = None)
+ Printf.printf "%B\n%!" (int_proj i = None);
+ Printf.printf "%B\n%!" (int_proj s = None);
+ Printf.printf "%B\n%!" (string_proj i = None);
+ Printf.printf "%B\n%!" (string_proj s = None)
;;
let sort_uniq (type s) cmp l =
let ( ~$ ) x y = (x, y)
let g x y =
~$ (x.contents) (y.contents)
+
+
+
+(* PR#7506: attributes on list tail *)
+
+let tail1 = ([1; 2])[@hello]
+let tail2 = 0::(([1; 2])[@hello])
+let tail3 = 0::(([])[@hello])
+
+let f ~l:(l[@foo]) = l;;
+let test x y = ((+)[@foo]) x y;;
+let test x = ((~-)[@foo]) x;;
+let test contents = { contents = contents[@foo] };;
+class type t = object(_[@foo]) end;;
+let test f x = f ~x:(x[@foo]);;
+let f = function ((`A|`B)[@bar]) | `C -> ();;
+let f = function _::(_::_ [@foo]) -> () | _ -> ();;
+function {contents=contents[@foo]} -> ();;
+fun contents -> {contents=contents[@foo]};;
+((); (((); ())[@foo]));;
+
+(* https://github.com/LexiFi/gen_js_api/issues/61 *)
+
+let () = foo##.bar := ();;
+
+(* "let open" in classes and class types *)
+
+class c =
+ let open M in
+ object
+ method f : t = x
+ end
+;;
+class type ct =
+ let open M in
+ object
+ method f : t
+ end
+;;
+
+(* M.(::) notation *)
+module Exotic_list = struct
+ module Inner = struct
+ type ('a,'b) t = [] | (::) of 'a * 'b * ('a,'b) t
+ end
+
+ let Inner.(::)(x,y, Inner.[]) = Inner.(::)(1,"one",Inner.[])
+end
+
+(** Extended index operators *)
+module Indexop = struct
+ module Def = struct
+ let ( .%[] ) = Hashtbl.find
+ let ( .%[] <- ) = Hashtbl.add
+ let ( .%() ) = Hashtbl.find
+ let ( .%() <- ) = Hashtbl.add
+ let ( .%{} ) = Hashtbl.find
+ let ( .%{} <- ) = Hashtbl.add
+ end
+ ;;
+ let h = Hashtbl.create 17 in
+ h.Def.%["one"] <- 1;
+ h.Def.%("two") <- 2;
+ h.Def.%{"three"} <- 3
+ let x,y,z = Def.(h.%["one"], h.%("two"), h.%{"three"})
+end
| _ -> "diff -u"
let report_err exn =
- match exn with
- | Sys_error msg ->
- Format.printf "@[I/O error:@ %s@]@." msg
- | x ->
- match Location.error_of_exn x with
- | Some err ->
- Format.printf "@[%a@]@."
- Location.report_error err
- | None -> raise x
+ Location.report_exception Format.std_formatter exn
let remove_locs =
let open Ast_mapper in
[]
Pmod_ident "M" (attributes.ml[26,254+27]..[26,254+28])
[
- Pwith_typesubst
+ Pwith_typesubst "t" (attributes.ml[26,254+53]..[26,254+54])
type_declaration "t" (attributes.ml[26,254+53]..[26,254+54]) (attributes.ml[26,254+48]..[26,254+61])
ptype_params =
[]
--- /dev/null
+let (.?[]) = Hashtbl.find_opt
+let (.@[]) = Hashtbl.find
+let ( .@[]<- ) = Hashtbl.add
+let (.@{}) = Hashtbl.find
+let ( .@{}<- ) = Hashtbl.add
+let (.@()) = Hashtbl.find
+let ( .@()<- ) = Hashtbl.add
+
+let h = Hashtbl.create 17
+
+;;
+ h.@("One") <- 1
+; assert (h.@{"One"} = 1)
+; print_int h.@{"One"}
+; assert (h.?["Two"] = None)
+
+
+(* from GPR#1392 *)
+let ( #? ) x y = (x, y);;
+let ( .%() ) x y = x.(y);;
+let x = [| 0 |];;
+let _ = 1 #? x.(0);;
+let _ = 1 #? x.%(0);;
--- /dev/null
+[
+ structure_item (extended_indexoperators.ml[1,0+0]..[1,0+29])
+ Pstr_value Nonrec
+ [
+ <def>
+ pattern (extended_indexoperators.ml[1,0+4]..[1,0+10])
+ Ppat_var ".?[]" (extended_indexoperators.ml[1,0+4]..[1,0+10])
+ expression (extended_indexoperators.ml[1,0+13]..[1,0+29])
+ Pexp_ident "Hashtbl.find_opt" (extended_indexoperators.ml[1,0+13]..[1,0+29])
+ ]
+ structure_item (extended_indexoperators.ml[2,30+0]..[2,30+25])
+ Pstr_value Nonrec
+ [
+ <def>
+ pattern (extended_indexoperators.ml[2,30+4]..[2,30+10])
+ Ppat_var ".@[]" (extended_indexoperators.ml[2,30+4]..[2,30+10])
+ expression (extended_indexoperators.ml[2,30+13]..[2,30+25])
+ Pexp_ident "Hashtbl.find" (extended_indexoperators.ml[2,30+13]..[2,30+25])
+ ]
+ structure_item (extended_indexoperators.ml[3,56+0]..[3,56+28])
+ Pstr_value Nonrec
+ [
+ <def>
+ pattern (extended_indexoperators.ml[3,56+4]..[3,56+14])
+ Ppat_var ".@[]<-" (extended_indexoperators.ml[3,56+4]..[3,56+14])
+ expression (extended_indexoperators.ml[3,56+17]..[3,56+28])
+ Pexp_ident "Hashtbl.add" (extended_indexoperators.ml[3,56+17]..[3,56+28])
+ ]
+ structure_item (extended_indexoperators.ml[4,85+0]..[4,85+25])
+ Pstr_value Nonrec
+ [
+ <def>
+ pattern (extended_indexoperators.ml[4,85+4]..[4,85+10])
+ Ppat_var ".@{}" (extended_indexoperators.ml[4,85+4]..[4,85+10])
+ expression (extended_indexoperators.ml[4,85+13]..[4,85+25])
+ Pexp_ident "Hashtbl.find" (extended_indexoperators.ml[4,85+13]..[4,85+25])
+ ]
+ structure_item (extended_indexoperators.ml[5,111+0]..[5,111+28])
+ Pstr_value Nonrec
+ [
+ <def>
+ pattern (extended_indexoperators.ml[5,111+4]..[5,111+14])
+ Ppat_var ".@{}<-" (extended_indexoperators.ml[5,111+4]..[5,111+14])
+ expression (extended_indexoperators.ml[5,111+17]..[5,111+28])
+ Pexp_ident "Hashtbl.add" (extended_indexoperators.ml[5,111+17]..[5,111+28])
+ ]
+ structure_item (extended_indexoperators.ml[6,140+0]..[6,140+25])
+ Pstr_value Nonrec
+ [
+ <def>
+ pattern (extended_indexoperators.ml[6,140+4]..[6,140+10])
+ Ppat_var ".@()" (extended_indexoperators.ml[6,140+4]..[6,140+10])
+ expression (extended_indexoperators.ml[6,140+13]..[6,140+25])
+ Pexp_ident "Hashtbl.find" (extended_indexoperators.ml[6,140+13]..[6,140+25])
+ ]
+ structure_item (extended_indexoperators.ml[7,166+0]..[7,166+28])
+ Pstr_value Nonrec
+ [
+ <def>
+ pattern (extended_indexoperators.ml[7,166+4]..[7,166+14])
+ Ppat_var ".@()<-" (extended_indexoperators.ml[7,166+4]..[7,166+14])
+ expression (extended_indexoperators.ml[7,166+17]..[7,166+28])
+ Pexp_ident "Hashtbl.add" (extended_indexoperators.ml[7,166+17]..[7,166+28])
+ ]
+ structure_item (extended_indexoperators.ml[9,196+0]..[9,196+25])
+ Pstr_value Nonrec
+ [
+ <def>
+ pattern (extended_indexoperators.ml[9,196+4]..[9,196+5])
+ Ppat_var "h" (extended_indexoperators.ml[9,196+4]..[9,196+5])
+ expression (extended_indexoperators.ml[9,196+8]..[9,196+25])
+ Pexp_apply
+ expression (extended_indexoperators.ml[9,196+8]..[9,196+22])
+ Pexp_ident "Hashtbl.create" (extended_indexoperators.ml[9,196+8]..[9,196+22])
+ [
+ <arg>
+ Nolabel
+ expression (extended_indexoperators.ml[9,196+23]..[9,196+25])
+ Pexp_constant PConst_int (17,None)
+ ]
+ ]
+ structure_item (extended_indexoperators.ml[12,226+2]..[15,293+28])
+ Pstr_eval
+ expression (extended_indexoperators.ml[12,226+2]..[15,293+28])
+ Pexp_sequence
+ expression (extended_indexoperators.ml[12,226+2]..[12,226+17])
+ Pexp_apply
+ expression (extended_indexoperators.ml[12,226+2]..[12,226+17])
+ Pexp_ident ".@()<-" (extended_indexoperators.ml[12,226+2]..[12,226+17]) ghost
+ [
+ <arg>
+ Nolabel
+ expression (extended_indexoperators.ml[12,226+2]..[12,226+3])
+ Pexp_ident "h" (extended_indexoperators.ml[12,226+2]..[12,226+3])
+ <arg>
+ Nolabel
+ expression (extended_indexoperators.ml[12,226+6]..[12,226+11])
+ Pexp_constant PConst_string("One",None)
+ <arg>
+ Nolabel
+ expression (extended_indexoperators.ml[12,226+16]..[12,226+17])
+ Pexp_constant PConst_int (1,None)
+ ]
+ expression (extended_indexoperators.ml[13,244+2]..[15,293+28])
+ Pexp_sequence
+ expression (extended_indexoperators.ml[13,244+2]..[13,244+25])
+ Pexp_assert
+ expression (extended_indexoperators.ml[13,244+9]..[13,244+25])
+ Pexp_apply
+ expression (extended_indexoperators.ml[13,244+21]..[13,244+22])
+ Pexp_ident "=" (extended_indexoperators.ml[13,244+21]..[13,244+22])
+ [
+ <arg>
+ Nolabel
+ expression (extended_indexoperators.ml[13,244+10]..[13,244+20])
+ Pexp_apply
+ expression (extended_indexoperators.ml[13,244+10]..[13,244+20])
+ Pexp_ident ".@{}" (extended_indexoperators.ml[13,244+10]..[13,244+20]) ghost
+ [
+ <arg>
+ Nolabel
+ expression (extended_indexoperators.ml[13,244+10]..[13,244+11])
+ Pexp_ident "h" (extended_indexoperators.ml[13,244+10]..[13,244+11])
+ <arg>
+ Nolabel
+ expression (extended_indexoperators.ml[13,244+14]..[13,244+19])
+ Pexp_constant PConst_string("One",None)
+ ]
+ <arg>
+ Nolabel
+ expression (extended_indexoperators.ml[13,244+23]..[13,244+24])
+ Pexp_constant PConst_int (1,None)
+ ]
+ expression (extended_indexoperators.ml[14,270+2]..[15,293+28])
+ Pexp_sequence
+ expression (extended_indexoperators.ml[14,270+2]..[14,270+22])
+ Pexp_apply
+ expression (extended_indexoperators.ml[14,270+2]..[14,270+11])
+ Pexp_ident "print_int" (extended_indexoperators.ml[14,270+2]..[14,270+11])
+ [
+ <arg>
+ Nolabel
+ expression (extended_indexoperators.ml[14,270+12]..[14,270+22])
+ Pexp_apply
+ expression (extended_indexoperators.ml[14,270+12]..[14,270+22])
+ Pexp_ident ".@{}" (extended_indexoperators.ml[14,270+12]..[14,270+22]) ghost
+ [
+ <arg>
+ Nolabel
+ expression (extended_indexoperators.ml[14,270+12]..[14,270+13])
+ Pexp_ident "h" (extended_indexoperators.ml[14,270+12]..[14,270+13])
+ <arg>
+ Nolabel
+ expression (extended_indexoperators.ml[14,270+16]..[14,270+21])
+ Pexp_constant PConst_string("One",None)
+ ]
+ ]
+ expression (extended_indexoperators.ml[15,293+2]..[15,293+28])
+ Pexp_assert
+ expression (extended_indexoperators.ml[15,293+9]..[15,293+28])
+ Pexp_apply
+ expression (extended_indexoperators.ml[15,293+21]..[15,293+22])
+ Pexp_ident "=" (extended_indexoperators.ml[15,293+21]..[15,293+22])
+ [
+ <arg>
+ Nolabel
+ expression (extended_indexoperators.ml[15,293+10]..[15,293+20])
+ Pexp_apply
+ expression (extended_indexoperators.ml[15,293+10]..[15,293+20])
+ Pexp_ident ".?[]" (extended_indexoperators.ml[15,293+10]..[15,293+20]) ghost
+ [
+ <arg>
+ Nolabel
+ expression (extended_indexoperators.ml[15,293+10]..[15,293+11])
+ Pexp_ident "h" (extended_indexoperators.ml[15,293+10]..[15,293+11])
+ <arg>
+ Nolabel
+ expression (extended_indexoperators.ml[15,293+14]..[15,293+19])
+ Pexp_constant PConst_string("Two",None)
+ ]
+ <arg>
+ Nolabel
+ expression (extended_indexoperators.ml[15,293+23]..[15,293+27])
+ Pexp_construct "None" (extended_indexoperators.ml[15,293+23]..[15,293+27])
+ None
+ ]
+ structure_item (extended_indexoperators.ml[19,344+0]..[19,344+23])
+ Pstr_value Nonrec
+ [
+ <def>
+ pattern (extended_indexoperators.ml[19,344+4]..[19,344+10])
+ Ppat_var "#?" (extended_indexoperators.ml[19,344+4]..[19,344+10])
+ expression (extended_indexoperators.ml[19,344+11]..[19,344+23]) ghost
+ Pexp_fun
+ Nolabel
+ None
+ pattern (extended_indexoperators.ml[19,344+11]..[19,344+12])
+ Ppat_var "x" (extended_indexoperators.ml[19,344+11]..[19,344+12])
+ expression (extended_indexoperators.ml[19,344+13]..[19,344+23]) ghost
+ Pexp_fun
+ Nolabel
+ None
+ pattern (extended_indexoperators.ml[19,344+13]..[19,344+14])
+ Ppat_var "y" (extended_indexoperators.ml[19,344+13]..[19,344+14])
+ expression (extended_indexoperators.ml[19,344+17]..[19,344+23])
+ Pexp_tuple
+ [
+ expression (extended_indexoperators.ml[19,344+18]..[19,344+19])
+ Pexp_ident "x" (extended_indexoperators.ml[19,344+18]..[19,344+19])
+ expression (extended_indexoperators.ml[19,344+21]..[19,344+22])
+ Pexp_ident "y" (extended_indexoperators.ml[19,344+21]..[19,344+22])
+ ]
+ ]
+ structure_item (extended_indexoperators.ml[20,370+0]..[20,370+24])
+ Pstr_value Nonrec
+ [
+ <def>
+ pattern (extended_indexoperators.ml[20,370+4]..[20,370+12])
+ Ppat_var ".%()" (extended_indexoperators.ml[20,370+4]..[20,370+12])
+ expression (extended_indexoperators.ml[20,370+13]..[20,370+24]) ghost
+ Pexp_fun
+ Nolabel
+ None
+ pattern (extended_indexoperators.ml[20,370+13]..[20,370+14])
+ Ppat_var "x" (extended_indexoperators.ml[20,370+13]..[20,370+14])
+ expression (extended_indexoperators.ml[20,370+15]..[20,370+24]) ghost
+ Pexp_fun
+ Nolabel
+ None
+ pattern (extended_indexoperators.ml[20,370+15]..[20,370+16])
+ Ppat_var "y" (extended_indexoperators.ml[20,370+15]..[20,370+16])
+ expression (extended_indexoperators.ml[20,370+19]..[20,370+24])
+ Pexp_apply
+ expression (extended_indexoperators.ml[20,370+19]..[20,370+24]) ghost
+ Pexp_ident "Array.get" (extended_indexoperators.ml[20,370+19]..[20,370+24]) ghost
+ [
+ <arg>
+ Nolabel
+ expression (extended_indexoperators.ml[20,370+19]..[20,370+20])
+ Pexp_ident "x" (extended_indexoperators.ml[20,370+19]..[20,370+20])
+ <arg>
+ Nolabel
+ expression (extended_indexoperators.ml[20,370+22]..[20,370+23])
+ Pexp_ident "y" (extended_indexoperators.ml[20,370+22]..[20,370+23])
+ ]
+ ]
+ structure_item (extended_indexoperators.ml[21,397+0]..[21,397+15])
+ Pstr_value Nonrec
+ [
+ <def>
+ pattern (extended_indexoperators.ml[21,397+4]..[21,397+5])
+ Ppat_var "x" (extended_indexoperators.ml[21,397+4]..[21,397+5])
+ expression (extended_indexoperators.ml[21,397+8]..[21,397+15])
+ Pexp_array
+ [
+ expression (extended_indexoperators.ml[21,397+11]..[21,397+12])
+ Pexp_constant PConst_int (0,None)
+ ]
+ ]
+ structure_item (extended_indexoperators.ml[22,415+0]..[22,415+18])
+ Pstr_value Nonrec
+ [
+ <def>
+ pattern (extended_indexoperators.ml[22,415+4]..[22,415+5])
+ Ppat_any
+ expression (extended_indexoperators.ml[22,415+8]..[22,415+18])
+ Pexp_apply
+ expression (extended_indexoperators.ml[22,415+10]..[22,415+12])
+ Pexp_ident "#?" (extended_indexoperators.ml[22,415+10]..[22,415+12])
+ [
+ <arg>
+ Nolabel
+ expression (extended_indexoperators.ml[22,415+8]..[22,415+9])
+ Pexp_constant PConst_int (1,None)
+ <arg>
+ Nolabel
+ expression (extended_indexoperators.ml[22,415+13]..[22,415+18])
+ Pexp_apply
+ expression (extended_indexoperators.ml[22,415+13]..[22,415+18]) ghost
+ Pexp_ident "Array.get" (extended_indexoperators.ml[22,415+13]..[22,415+18]) ghost
+ [
+ <arg>
+ Nolabel
+ expression (extended_indexoperators.ml[22,415+13]..[22,415+14])
+ Pexp_ident "x" (extended_indexoperators.ml[22,415+13]..[22,415+14])
+ <arg>
+ Nolabel
+ expression (extended_indexoperators.ml[22,415+16]..[22,415+17])
+ Pexp_constant PConst_int (0,None)
+ ]
+ ]
+ ]
+ structure_item (extended_indexoperators.ml[23,436+0]..[23,436+19])
+ Pstr_value Nonrec
+ [
+ <def>
+ pattern (extended_indexoperators.ml[23,436+4]..[23,436+5])
+ Ppat_any
+ expression (extended_indexoperators.ml[23,436+8]..[23,436+19])
+ Pexp_apply
+ expression (extended_indexoperators.ml[23,436+10]..[23,436+12])
+ Pexp_ident "#?" (extended_indexoperators.ml[23,436+10]..[23,436+12])
+ [
+ <arg>
+ Nolabel
+ expression (extended_indexoperators.ml[23,436+8]..[23,436+9])
+ Pexp_constant PConst_int (1,None)
+ <arg>
+ Nolabel
+ expression (extended_indexoperators.ml[23,436+13]..[23,436+19])
+ Pexp_apply
+ expression (extended_indexoperators.ml[23,436+13]..[23,436+19])
+ Pexp_ident ".%()" (extended_indexoperators.ml[23,436+13]..[23,436+19]) ghost
+ [
+ <arg>
+ Nolabel
+ expression (extended_indexoperators.ml[23,436+13]..[23,436+14])
+ Pexp_ident "x" (extended_indexoperators.ml[23,436+13]..[23,436+14])
+ <arg>
+ Nolabel
+ expression (extended_indexoperators.ml[23,436+17]..[23,436+18])
+ Pexp_constant PConst_int (0,None)
+ ]
+ ]
+ ]
+]
+
--- /dev/null
+BASEDIR=../..
+
+INCLUDES=\
+ -I $(OTOPDIR)/parsing \
+ -I $(OTOPDIR)/utils \
+ -I $(OTOPDIR)/compilerlibs
+
+myppx=$(shell $(CYGPATH) '$(OCAMLRUN)') ./program$(EXE)
+
+.PHONY: run
+run: program$(EXE) test.reference
+ @echo " ... testing -thread and -vmthread are propagated to PPX:"
+ @( $(OCAMLC) -c -thread -ppx '$(myppx)' test.ml \
+ && $(OCAMLC) -c -vmthread -ppx '$(myppx)' test.ml ) 2> test.result
+ @$(DIFF) test.reference test.result >/dev/null \
+ && echo " => passed" || echo " => failed"
+
+program$(EXE): program.ml Makefile
+ @$(OCAMLC) -o program$(EXE) $(INCLUDES) ocamlcommon.cma ./program.ml
+
+.PHONY: promote
+promote: defaultpromote
+
+.PHONY: clean
+clean: defaultclean
+ @rm -f program$(EXE) test.result *.cm*
+
+include $(BASEDIR)/makefiles/Makefile.common
--- /dev/null
+(* A simple PPX *)
+
+open Ast_mapper
+
+let () =
+ register "test" (fun _ ->
+ Printf.eprintf "use_threads=%b\n" !Clflags.use_threads;
+ Printf.eprintf "use_vmthreads=%b\n" !Clflags.use_vmthreads;
+ default_mapper);
+
--- /dev/null
+(* empty *)
--- /dev/null
+use_threads=true
+use_vmthreads=false
+use_threads=false
+use_vmthreads=true
ignore(f v1 v2);
assert false
with
- | Invalid_argument("index out of bounds") -> ()
+ | Invalid_argument _ -> ()
let assert_bound_check3 f v1 v2 v3 =
try
ignore(f v1 v2 v3);
assert false
with
- | Invalid_argument("index out of bounds") -> ()
+ | Invalid_argument _ -> ()
let () =
assert_bound_check2 caml_bigstring_get_16 s (-1);
ignore(f v1 v2);
assert false
with
- | Invalid_argument("index out of bounds") -> ()
+ | Invalid_argument _ -> ()
let assert_bound_check3 f v1 v2 v3 =
try
ignore(f v1 v2 v3);
assert false
with
- | Invalid_argument("index out of bounds") -> ()
+ | Invalid_argument _ -> ()
let () =
assert_bound_check2 caml_string_get_16 s (-1);
--- /dev/null
+BASEDIR=../..
+include $(BASEDIR)/makefiles/Makefile.toplevel
+include $(BASEDIR)/makefiles/Makefile.common
--- /dev/null
+(** Test that weak variables keep their names long enough *)
+
+let f y = fun x -> x
+let blah = f 0
+let splash () = blah (failwith "coucou")
+let blurp = f 0;;
+
+blah 1;;
+
+let g = f ();;
+
+g (fun x -> x);;
+let h = g (f ());;
--- /dev/null
+
+# val f : 'a -> 'b -> 'b = <fun>
+val blah : '_weak1 -> '_weak1 = <fun>
+val splash : unit -> '_weak1 = <fun>
+val blurp : '_weak2 -> '_weak2 = <fun>
+# - : int = 1
+# val g : '_weak3 -> '_weak3 = <fun>
+# - : '_weak4 -> '_weak4 = <fun>
+# val h : '_weak4 -> '_weak4 = <fun>
+#
$(OCAMLOPT) -w a -o $$F.native$(EXE) $$f; \
fi; \
done
- @grep -q HAS_STACK_OVERFLOW_DETECTION $(TOPDIR)/config/s.h \
- || rm -f stackoverflow.native$(EXE)
+ $(if $(findstring win32,$(UNIX_OR_WIN32)),:, \
+ @grep -q HAS_STACK_OVERFLOW_DETECTION $(TOPDIR)/byterun/caml/s.h \
+ || rm -f stackoverflow.native$(EXE))
# Cygwin doesn't allow the stack limit to be changed - the 4096 is
# intended to be larger than the its default stack size. The logic
x = 10000
x = 0
Stack overflow caught
+x = 20000
+x = 10000
+x = 0
+second Stack overflow caught
raise Stack_overflow
let _ =
+ begin
try
ignore(f 0)
with Stack_overflow ->
print_string "Stack overflow caught"; print_newline()
+ end ;
+ (* GPR#1289 *)
+ Printexc.record_backtrace true;
+ begin
+ try
+ ignore(f 0)
+ with Stack_overflow ->
+ print_string "second Stack overflow caught"; print_newline()
+ end
x = 10000
x = 0
Stack overflow caught
+x = 20000
+x = 10000
+x = 0
+second Stack overflow caught
;
header:
Taction
- { $1 }
+ { $1 (* '"' test that ocamlyacc can
+ handle comments correctly"*)" "(*" *) }
|
{ Location(0,0) }
;
--- /dev/null
+BASEDIR=../..
+
+.PHONY: default
+default:
+ @printf " ... testing -compat-32"
+ @if ($(OCAMLC) -config | grep "word_size: *64") \
+ then $(MAKE) run; \
+ else echo ' => skipped (not compiled in 64bit)'; \
+ fi
+
+.PHONY: run
+run:
+ @$(OCAMLC) -compat-32 -c a.ml > test.result 2>&1 || true
+ @$(OCAMLC) -c a.ml
+ @$(OCAMLC) -compat-32 -a a.cmo -o a.cma >> test.result 2>&1 || true
+ @$(OCAMLC) -a a.cmo -o a.cma
+ @$(OCAMLC) -compat-32 a.cma -o a.byte -linkall >> test.result 2>&1 || true
+ @$(DIFF) test.reference test.result >/dev/null \
+ && echo " => passed" || echo " => failed"; \
+
+promote: defaultpromote
+
+clean: defaultclean
+
+include $(BASEDIR)/makefiles/Makefile.common
--- /dev/null
+let a = 0xffffffffffff
--- /dev/null
+File "a.ml", line 1:
+Error: Generated bytecode unit "a.cmo" cannot be used on a 32-bit platform
+File "_none_", line 1:
+Error: Generated bytecode library "a.cma" cannot be used on a 32-bit platform
+File "_none_", line 1:
+Error: Generated bytecode executable "a.byte" cannot be used on a 32-bit platform
COMPFLAGS=-I $(OTOPDIR)/ocamldoc
LD_PATH=$(TOPDIR)/otherlibs/$(UNIXLIBVAR)unix:$(TOPDIR)/otherlibs/str
DOCFLAGS=-I $(OTOPDIR)/stdlib $(COMPFLAGS)\
+ -latextitle "1,subsection*" \
+ -latextitle "2,subsubsection*" \
-latextitle "6,subsection*" \
-latextitle "7,subsubsection*" \
-latex-type-prefix "TYP" \
-(** Testing display of extensible variant types.
+(** Testing display of extensible variant types and exceptions.
@test_types_display
*)
+(** Also check reference for {!M.A}, {!M.B}, {!M.C} and {!E} *)
+
+(** Extensible type *)
type e = ..
module M = struct
| B (** B doc *)
| C (** C doc *)
end
+
+exception E
\usepackage{ocamldoc}
\begin{document}
\tableofcontents
-\section{Module {\tt{Extensible\_variant}} : Testing display of extensible variant types.}
+\section{Module {\tt{Extensible\_variant}} : Testing display of extensible variant types and exceptions.}
\label{Extensible-underscorevariant}\index{Extensible-underscorevariant@\verb`Extensible_variant`}
+Also check reference for {\tt{Extensible\_variant.M.A}}[\ref{extension:Extensible-underscorevariant.M.A}], {\tt{Extensible\_variant.M.B}}[\ref{extension:Extensible-underscorevariant.M.B}], {\tt{Extensible\_variant.M.C}}[\ref{extension:Extensible-underscorevariant.M.C}] and {\tt{Extensible\_variant.E}}[\ref{exception:Extensible-underscorevariant.E}]
+
+
+
\label{TYPExtensible-underscorevariant.e}\begin{ocamldoccode}
type e = ..
\end{ocamldoccode}
\index{e@\verb`e`}
+\begin{ocamldocdescription}
+Extensible type
+
+
+\end{ocamldocdescription}
-\end{document}
\ No newline at end of file
+
+
+\label{exception:Extensible-underscorevariant.E}\begin{ocamldoccode}
+exception E
+\end{ocamldoccode}
+\index{E@\verb`E`}
+
+
+\end{document}
-\begin{ocamldoccode}
+\label{exception:Inline-underscorerecords.Simple}\begin{ocamldoccode}
exception Simple
\end{ocamldoccode}
\index{Simple@\verb`Simple`}
-\begin{ocamldoccode}
+\label{exception:Inline-underscorerecords.Less}\begin{ocamldoccode}
exception Less of int
\end{ocamldoccode}
\index{Less@\verb`Less`}
-\begin{ocamldoccode}
+\label{exception:Inline-underscorerecords.Error}\begin{ocamldoccode}
exception Error of {\char123} name : string ;
\end{ocamldoccode}
\begin{ocamldoccomment}
\end{ocamldocdescription}
-\end{document}
\ No newline at end of file
+\end{document}
-\begin{ocamldoccode}
+\label{exception:Inline-underscorerecords-underscorebis.Simple}\begin{ocamldoccode}
exception Simple
\end{ocamldoccode}
\index{Simple@\verb`Simple`}
-\begin{ocamldoccode}
+\label{exception:Inline-underscorerecords-underscorebis.Less}\begin{ocamldoccode}
exception Less of int
\end{ocamldoccode}
\index{Less@\verb`Less`}
-\begin{ocamldoccode}
+\label{exception:Inline-underscorerecords-underscorebis.Error}\begin{ocamldoccode}
exception Error of {\char123} name : string ;
\end{ocamldoccode}
\begin{ocamldoccomment}
Two new constructors for ext
-\end{document}
\ No newline at end of file
+\end{document}
--- /dev/null
+(** Test for level 0 headings
+
+ {1 Level 1}
+
+ Standard heading levels start at 1.
+
+ {0 Level 0}
+ A level 0 heading is guaranted to be at the same level that
+ the main heading of the module.
+
+ This setup allows users to start their standard heading at level 1 rather
+ than 2, without losing the ability to add global level heading,
+ when, if ever, such heading is warranted
+
+ *)
--- /dev/null
+\documentclass[11pt]{article}
+\usepackage[latin1]{inputenc}
+\usepackage[T1]{fontenc}
+\usepackage{textcomp}
+\usepackage{fullpage}
+\usepackage{url}
+\usepackage{ocamldoc}
+\begin{document}
+\tableofcontents
+\section{Module {\tt{Level\_0}} : Test for level 0 headings }
+\label{Level-underscore0}\index{Level-underscore0@\verb`Level_0`}
+
+
+
+ \subsection*{Level 1}
+
+
+
+ Standard heading levels start at 1.
+
+
+ \section{Level 0}
+
+ A level 0 heading is guaranted to be at the same level that
+ the main heading of the module.
+
+
+ This setup allows users to start their standard heading at level 1 rather
+ than 2, without losing the ability to add global level heading,
+ when, if ever, such heading is warranted
+
+
+
+\ocamldocvspace{0.5cm}
+
+\end{document}
-\end{document}
\ No newline at end of file
+\end{document}
-\end{document}
\ No newline at end of file
+\end{document}
-\end{document}
\ No newline at end of file
+\end{document}
\index{no-underscoredocumentation@\verb`no_documentation`}
-\end{document}
\ No newline at end of file
+\end{document}
--- /dev/null
+(** Test the html rendering of ocamldoc documentation tags *)
+
+val heterological: unit
+(**
+ @author yes
+ @param no No description
+ @param neither see no description
+ @deprecated since the start of time
+ @return ()
+ @see "Documentation_tags.mli" Self reference
+ @since Now
+ @before Time not implemented
+*)
+
+val noop: unit
+(**
+ @raise Not_found Never
+ @raise Invalid_argument Never
+*)
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<link rel="stylesheet" href="style.css" type="text/css">
+<meta content="text/html; charset=iso-8859-1" http-equiv="Content-Type">
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<link rel="Start" href="index.html">
+<link rel="Up" href="index.html">
+<link title="Index of values" rel=Appendix href="index_values.html">
+<link title="Index of modules" rel=Appendix href="index_modules.html">
+<link title="Documentation_tags" rel="Chapter" href="Documentation_tags.html"><title>Documentation_tags</title>
+</head>
+<body>
+<div class="navbar"> <a class="up" href="index.html" title="Index">Up</a>
+ </div>
+<h1>Module <a href="type_Documentation_tags.html">Documentation_tags</a></h1>
+
+<pre><span id="MODULEDocumentation_tags"><span class="keyword">module</span> Documentation_tags</span>: <code class="code"><span class="keyword">sig</span></code> <a href="Documentation_tags.html">..</a> <code class="code"><span class="keyword">end</span></code></pre><div class="info module top">
+<div class="info-desc">
+<p>Test the html rendering of ocamldoc documentation tags</p>
+</div>
+</div>
+<hr width="100%">
+
+<pre><span id="VALheterological"><span class="keyword">val</span> heterological</span> : <code class="type">unit</code></pre><div class="info ">
+<div class="info-deprecated">
+<span class="warning">Deprecated.</span>since the start of time</div>
+<ul class="info-attributes">
+<li><b>Author(s):</b> yes</li>
+<li><b>Before Time </b> not implemented</li>
+<li><b>Since</b> Now</li>
+<li><b>Returns</b> ()</li>
+<li><b>See also</b> <i>Documentation_tags.mli</i> Self reference</li>
+</ul>
+</div>
+
+<pre><span id="VALnoop"><span class="keyword">val</span> noop</span> : <code class="type">unit</code></pre><div class="info ">
+<ul class="info-attributes">
+<li><b>Raises</b><ul><li><code>Not_found</code> Never</li>
+<li><code>Invalid_argument</code> Never</li>
+</ul></li>
+</ul>
+</div>
+</body></html>
\ No newline at end of file
</div>
<h1>Module <a href="type_Inline_records.html">Inline_records</a></h1>
-<pre><span class="keyword">module</span> Inline_records: <code class="code"><span class="keyword">sig</span></code> <a href="Inline_records.html">..</a> <code class="code"><span class="keyword">end</span></code></pre><div class="info module top">
-This test focuses on the printing of documentation for inline record
- within the latex generator.<br>
+<pre><span id="MODULEInline_records"><span class="keyword">module</span> Inline_records</span>: <code class="code"><span class="keyword">sig</span></code> <a href="Inline_records.html">..</a> <code class="code"><span class="keyword">end</span></code></pre><div class="info module top">
+<div class="info-desc">
+<p>This test focuses on the printing of documentation for inline record
+ within the latex generator.</p>
+</div>
</div>
<hr width="100%">
<pre><span id="EXCEPTIONSimple"><span class="keyword">exception</span> Simple</span></pre>
<div class="info ">
-A nice exception<br>
+<div class="info-desc">
+<p>A nice exception</p>
+</div>
</div>
<pre><span id="TYPEext"><span class="keyword">type</span> <code class="type"></code>ext</span> = ..</pre>
<div class="info ">
-An open sum type<br>
+<div class="info-desc">
+<p>An open sum type</p>
+</div>
</div>
<td align="left" valign="top" >
<code><span id="TYPEELTr.lbl">lbl</span> : <code class="type">int</code>;</code></td>
<td class="typefieldcomment" align="left" valign="top" ><code>(*</code></td><td class="typefieldcomment" align="left" valign="top" ><div class="info ">
-Field documentation for non-inline, <code class="code">lbl : int</code><br>
+<div class="info-desc">
+<p>Field documentation for non-inline, <code class="code">lbl : int</code></p>
+</div>
</div>
</td><td class="typefieldcomment" align="left" valign="bottom" ><code>*)</code></td>
</tr>
<td align="left" valign="top" >
<code><span id="TYPEELTr.more">more</span> : <code class="type">int list</code>;</code></td>
<td class="typefieldcomment" align="left" valign="top" ><code>(*</code></td><td class="typefieldcomment" align="left" valign="top" ><div class="info ">
-More documentation for r, <code class="code">more : int list</code><br>
+<div class="info-desc">
+<p>More documentation for r, <code class="code">more : int list</code></p>
+</div>
</div>
</td><td class="typefieldcomment" align="left" valign="bottom" ><code>*)</code></td>
</tr></table>
}
<div class="info ">
-A simple record type for reference<br>
+<div class="info-desc">
+<p>A simple record type for reference</p>
+</div>
</div>
<td align="left" valign="top" >
<code><span id="TYPEELTInline_records.A.lbl">lbl</span> : <code class="type">int</code>;</code></td>
<td class="typefieldcomment" align="left" valign="top" ><code>(*</code></td><td class="typefieldcomment" align="left" valign="top" ><div class="info ">
-<code class="code"><span class="constructor">A</span></code> field documentation<br>
+<div class="info-desc">
+<p><code class="code"><span class="constructor">A</span></code> field documentation</p>
+</div>
</div>
</td><td class="typefieldcomment" align="left" valign="bottom" ><code>*)</code></td>
</tr>
<td align="left" valign="top" >
<code><span id="TYPEELTInline_records.A.more">more</span> : <code class="type">int list</code>;</code></td>
<td class="typefieldcomment" align="left" valign="top" ><code>(*</code></td><td class="typefieldcomment" align="left" valign="top" ><div class="info ">
-More <code class="code"><span class="constructor">A</span></code> field documentation<br>
+<div class="info-desc">
+<p>More <code class="code"><span class="constructor">A</span></code> field documentation</p>
+</div>
</div>
</td><td class="typefieldcomment" align="left" valign="bottom" ><code>*)</code></td>
</tr></table>
}
</code></td>
<td class="typefieldcomment" align="left" valign="top" ><code>(*</code></td><td class="typefieldcomment" align="left" valign="top" ><div class="info ">
-Constructor documentation<br>
+<div class="info-desc">
+<p>Constructor documentation</p>
+</div>
</div>
</td><td class="typefieldcomment" align="left" valign="bottom" ><code>*)</code></td>
</tr></table>
<div class="info ">
-A sum type with one inline record<br>
+<div class="info-desc">
+<p>A sum type with one inline record</p>
+</div>
</div>
<td align="left" valign="top" >
<code><span id="TYPEELTInline_records.B.a_label_for_B">a_label_for_B</span> : <code class="type">int</code>;</code></td>
<td class="typefieldcomment" align="left" valign="top" ><code>(*</code></td><td class="typefieldcomment" align="left" valign="top" ><div class="info ">
-<code class="code"><span class="constructor">B</span></code> field documentation<br>
+<div class="info-desc">
+<p><code class="code"><span class="constructor">B</span></code> field documentation</p>
+</div>
</div>
</td><td class="typefieldcomment" align="left" valign="bottom" ><code>*)</code></td>
</tr>
<td align="left" valign="top" >
<code><span id="TYPEELTInline_records.B.more_label_for_B">more_label_for_B</span> : <code class="type">int list</code>;</code></td>
<td class="typefieldcomment" align="left" valign="top" ><code>(*</code></td><td class="typefieldcomment" align="left" valign="top" ><div class="info ">
-More <code class="code"><span class="constructor">B</span></code> field documentation<br>
+<div class="info-desc">
+<p>More <code class="code"><span class="constructor">B</span></code> field documentation</p>
+</div>
</div>
</td><td class="typefieldcomment" align="left" valign="bottom" ><code>*)</code></td>
</tr></table>
}
</code></td>
<td class="typefieldcomment" align="left" valign="top" ><code>(*</code></td><td class="typefieldcomment" align="left" valign="top" ><div class="info ">
-Constructor B documentation<br>
+<div class="info-desc">
+<p>Constructor B documentation</p>
+</div>
</div>
</td><td class="typefieldcomment" align="left" valign="bottom" ><code>*)</code></td>
</tr>
<td align="left" valign="top" >
<code><span id="TYPEELTInline_records.C.c_has_label_too">c_has_label_too</span> : <code class="type">float</code>;</code></td>
<td class="typefieldcomment" align="left" valign="top" ><code>(*</code></td><td class="typefieldcomment" align="left" valign="top" ><div class="info ">
-<code class="code"><span class="constructor">C</span></code> field documentation<br>
+<div class="info-desc">
+<p><code class="code"><span class="constructor">C</span></code> field documentation</p>
+</div>
</div>
</td><td class="typefieldcomment" align="left" valign="bottom" ><code>*)</code></td>
</tr>
<td align="left" valign="top" >
<code><span id="TYPEELTInline_records.C.more_than_one">more_than_one</span> : <code class="type">unit</code>;</code></td>
<td class="typefieldcomment" align="left" valign="top" ><code>(*</code></td><td class="typefieldcomment" align="left" valign="top" ><div class="info ">
-... documentations<br>
+<div class="info-desc">
+<p>... documentations</p>
+</div>
</div>
</td><td class="typefieldcomment" align="left" valign="bottom" ><code>*)</code></td>
</tr></table>
}
</code></td>
<td class="typefieldcomment" align="left" valign="top" ><code>(*</code></td><td class="typefieldcomment" align="left" valign="top" ><div class="info ">
-Constructor C documentation<br>
+<div class="info-desc">
+<p>Constructor C documentation</p>
+</div>
</div>
</td><td class="typefieldcomment" align="left" valign="bottom" ><code>*)</code></td>
</tr></table>
<div class="info ">
-A sum type with two inline records<br>
+<div class="info-desc">
+<p>A sum type with two inline records</p>
+</div>
</div>
<td align="left" valign="top" >
<code><span id="TYPEELTInline_records.D.any">any</span> : <code class="type">'a</code>;</code></td>
<td class="typefieldcomment" align="left" valign="top" ><code>(*</code></td><td class="typefieldcomment" align="left" valign="top" ><div class="info ">
-<code class="code"><span class="constructor">A</span></code> field <code class="code">any:<span class="keywordsign">'</span>a</code> for <code class="code"><span class="constructor">D</span></code> in <code class="code">any</code>.<br>
+<div class="info-desc">
+<p><code class="code"><span class="constructor">A</span></code> field <code class="code">any:<span class="keywordsign">'</span>a</code> for <code class="code"><span class="constructor">D</span></code> in <code class="code">any</code>.</p>
+</div>
</div>
</td><td class="typefieldcomment" align="left" valign="bottom" ><code>*)</code></td>
</tr></table>
}
<span class="keyword">-></span> <code class="type"><a href="Inline_records.html#TYPEany">any</a></code></code></td>
<td class="typefieldcomment" align="left" valign="top" ><code>(*</code></td><td class="typefieldcomment" align="left" valign="top" ><div class="info ">
-Constructor D documentation<br>
+<div class="info-desc">
+<p>Constructor D documentation</p>
+</div>
</div>
</td><td class="typefieldcomment" align="left" valign="bottom" ><code>*)</code></td>
</tr></table>
<div class="info ">
-A gadt constructor<br>
+<div class="info-desc">
+<p>A gadt constructor</p>
+</div>
</div>
<td align="left" valign="top" >
<code><span id="TYPEELTInline_records.Error.name">name</span> : <code class="type">string</code>;</code></td>
<td class="typefieldcomment" align="left" valign="top" ><code>(*</code></td><td class="typefieldcomment" align="left" valign="top" ><div class="info ">
-Error field documentation <code class="code">name:string</code><br>
+<div class="info-desc">
+<p>Error field documentation <code class="code">name:string</code></p>
+</div>
</div>
</td><td class="typefieldcomment" align="left" valign="bottom" ><code>*)</code></td>
</tr></table>
<td align="left" valign="top" >
<code><span id="TYPEELTInline_records.E.yet_another_field">yet_another_field</span> : <code class="type">unit</code>;</code></td>
<td class="typefieldcomment" align="left" valign="top" ><code>(*</code></td><td class="typefieldcomment" align="left" valign="top" ><div class="info ">
-Field documentation for <code class="code"><span class="constructor">E</span></code> in ext<br>
+<div class="info-desc">
+<p>Field documentation for <code class="code"><span class="constructor">E</span></code> in ext</p>
+</div>
</div>
</td><td class="typefieldcomment" align="left" valign="bottom" ><code>*)</code></td>
</tr></table>
}
</code></td>
<td class="typefieldcomment" align="left" valign="top" ><code>(*</code></td><td class="typefieldcomment" align="left" valign="top" ><div class="info ">
-Constructor E documentation<br>
+<div class="info-desc">
+<p>Constructor E documentation</p>
+</div>
</div>
</td><td class="typefieldcomment" align="left" valign="bottom" ><code>*)</code></td>
</tr>
<td align="left" valign="top" >
<code><span id="TYPEELTInline_records.F.even_more">even_more</span> : <code class="type">int -> int</code>;</code></td>
<td class="typefieldcomment" align="left" valign="top" ><code>(*</code></td><td class="typefieldcomment" align="left" valign="top" ><div class="info ">
-Some field documentations for <code class="code"><span class="constructor">F</span></code><br>
+<div class="info-desc">
+<p>Some field documentations for <code class="code"><span class="constructor">F</span></code></p>
+</div>
</div>
</td><td class="typefieldcomment" align="left" valign="bottom" ><code>*)</code></td>
</tr></table>
}
</code></td>
<td class="typefieldcomment" align="left" valign="top" ><code>(*</code></td><td class="typefieldcomment" align="left" valign="top" ><div class="info ">
-Constructor F documentation<br>
+<div class="info-desc">
+<p>Constructor F documentation</p>
+</div>
</div>
</td><td class="typefieldcomment" align="left" valign="bottom" ><code>*)</code></td>
</tr>
<td align="left" valign="top" >
<code><span id="TYPEELTInline_records.G.last">last</span> : <code class="type">int -> int</code>;</code></td>
<td class="typefieldcomment" align="left" valign="top" ><code>(*</code></td><td class="typefieldcomment" align="left" valign="top" ><div class="info ">
-The last and least field documentation<br>
+<div class="info-desc">
+<p>The last and least field documentation</p>
+</div>
</div>
</td><td class="typefieldcomment" align="left" valign="bottom" ><code>*)</code></td>
</tr></table>
}
</code></td>
<td class="typefieldcomment" align="left" valign="top" ><code>(*</code></td><td class="typefieldcomment" align="left" valign="top" ><div class="info ">
-Constructor G documentation<br>
+<div class="info-desc">
+<p>Constructor G documentation</p>
+</div>
</div>
</td><td class="typefieldcomment" align="left" valign="bottom" ><code>*)</code></td>
</tr></table>
<div class="info ">
-Two new constructors for ext<br>
+<div class="info-desc">
+<p>Two new constructors for ext</p>
+</div>
</div>
</body></html>
\ No newline at end of file
--- /dev/null
+(** Check that all toplevel items are given a unique id. *)
+
+exception Ex
+type t
+val x: t
+type ext = ..
+type ext += A
+class c: object end
+class type ct= object end
+[@@@attribute]
+module M: sig end
+module type s = sig end
+
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<link rel="stylesheet" href="style.css" type="text/css">
+<meta content="text/html; charset=iso-8859-1" http-equiv="Content-Type">
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<link rel="Start" href="index.html">
+<link rel="Up" href="index.html">
+<link title="Index of types" rel=Appendix href="index_types.html">
+<link title="Index of extensions" rel=Appendix href="index_extensions.html">
+<link title="Index of exceptions" rel=Appendix href="index_exceptions.html">
+<link title="Index of values" rel=Appendix href="index_values.html">
+<link title="Index of classes" rel=Appendix href="index_classes.html">
+<link title="Index of class types" rel=Appendix href="index_class_types.html">
+<link title="Index of modules" rel=Appendix href="index_modules.html">
+<link title="Index of module types" rel=Appendix href="index_module_types.html">
+<link title="Item_ids" rel="Chapter" href="Item_ids.html"><title>Item_ids</title>
+</head>
+<body>
+<div class="navbar"> <a class="up" href="index.html" title="Index">Up</a>
+ </div>
+<h1>Module <a href="type_Item_ids.html">Item_ids</a></h1>
+
+<pre><span id="MODULEItem_ids"><span class="keyword">module</span> Item_ids</span>: <code class="code"><span class="keyword">sig</span></code> <a href="Item_ids.html">..</a> <code class="code"><span class="keyword">end</span></code></pre><div class="info module top">
+<div class="info-desc">
+<p>Check that all toplevel items are given a unique id.</p>
+</div>
+</div>
+<hr width="100%">
+
+<pre><span id="EXCEPTIONEx"><span class="keyword">exception</span> Ex</span></pre>
+
+<pre><span id="TYPEt"><span class="keyword">type</span> <code class="type"></code>t</span> </pre>
+
+
+<pre><span id="VALx"><span class="keyword">val</span> x</span> : <code class="type"><a href="Item_ids.html#TYPEt">t</a></code></pre>
+<pre><span id="TYPEext"><span class="keyword">type</span> <code class="type"></code>ext</span> = ..</pre>
+
+<pre><code><span class="keyword">type</span> <code class="type"></code><a href="Item_ids.html#TYPEext">ext</a> += </code></pre><table class="typetable">
+<tr>
+<td align="left" valign="top" >
+<code><span class="keyword">|</span></code></td>
+<td align="left" valign="top" >
+<code><span id="EXTENSIONA">A</span></code></td>
+
+</tr></table>
+
+
+
+<pre><span id="TYPEc"><span class="keyword">class</span> <a href="Item_ids.c-c.html">c</a></span> : <code class="type"></code><code class="code"><span class="keyword">object</span></code> <a href="Item_ids.c-c.html">..</a> <code class="code"><span class="keyword">end</span></code></pre>
+<pre><span id="TYPEct"><span class="keyword">class type</span> <a href="Item_ids.ct-c.html">ct</a></span> = <code class="code"><span class="keyword">object</span></code> <a href="Item_ids.ct-c.html">..</a> <code class="code"><span class="keyword">end</span></code></pre>
+<pre><span id="MODULEM"><span class="keyword">module</span> <a href="Item_ids.M.html">M</a></span>: <code class="code"><span class="keyword">sig</span></code> <a href="Item_ids.M.html">..</a> <code class="code"><span class="keyword">end</span></code></pre>
+<pre><span id="MODULETYPEs"><span class="keyword">module type</span> <a href="Item_ids.s-c.html">s</a></span> = <code class="code"><span class="keyword">sig</span></code> <a href="Item_ids.s-c.html">..</a> <code class="code"><span class="keyword">end</span></code></pre></body></html>
\ No newline at end of file
]}
See {{:http://caml.inria.fr/mantis/view.php?id=6341} MPR#6341} for more
details or the file Linebreaks.html generated by ocamldoc from this file.
-
- -Second, outside of a "pre" tags, blank characters in embedded code
+ - Second, outside of a "pre" tags, blank characters in embedded code
should be escaped, in order to make them render in a "pre"-like fashion.
A good example should be the files type_{i Modulename}.html generated by
ocamldoc that should contains the signature of the module [Modulename] in
</div>
<h1>Module <a href="type_Linebreaks.html">Linebreaks</a></h1>
-<pre><span class="keyword">module</span> Linebreaks: <code class="code"><span class="keyword">sig</span></code> <a href="Linebreaks.html">..</a> <code class="code"><span class="keyword">end</span></code></pre><div class="info module top">
-This file tests the encoding of linebreak inside OCaml code by the
- ocamldoc html backend.
-<p>
+<pre><span id="MODULELinebreaks"><span class="keyword">module</span> Linebreaks</span>: <code class="code"><span class="keyword">sig</span></code> <a href="Linebreaks.html">..</a> <code class="code"><span class="keyword">end</span></code></pre><div class="info module top">
+<div class="info-desc">
+<p>This file tests the encoding of linebreak inside OCaml code by the
+ ocamldoc html backend.</p>
+
+<p>Two slightly different aspects are tested in this very file.</p>
- Two slightly different aspects are tested in this very file.
-<p>
<ul>
<li>First, inside a "pre" tags, blanks character should not be escaped.
For instance, the generated html code for this test fragment should not
</code></pre>
See <a href="http://caml.inria.fr/mantis/view.php?id=6341"> MPR#6341</a> for more
details or the file Linebreaks.html generated by ocamldoc from this file.</li>
-</ul>
-
- -Second, outside of a "pre" tags, blank characters in embedded code
+<li>Second, outside of a "pre" tags, blank characters in embedded code
should be escaped, in order to make them render in a "pre"-like fashion.
A good example should be the files type_<i>Modulename</i>.html generated by
ocamldoc that should contains the signature of the module <code class="code"><span class="constructor">Modulename</span></code> in
a "code" tags.
- For instance with the following type definitions,<br>
+ For instance with the following type definitions,</li>
+</ul>
+</div>
</div>
<hr width="100%">
<pre><span id="VALx"><span class="keyword">val</span> x</span> : <code class="type"><a href="Linebreaks.html#TYPEa">a</a></code></pre>
-<pre><span class="keyword">module</span> <a href="Linebreaks.S.html">S</a>: <code class="code"><span class="keyword">sig</span></code> <a href="Linebreaks.S.html">..</a> <code class="code"><span class="keyword">end</span></code></pre>
-<pre><span class="keyword">module type</span> <a href="Linebreaks.s-c.html">s</a> = <code class="code"><span class="keyword">sig</span></code> <a href="Linebreaks.s-c.html">..</a> <code class="code"><span class="keyword">end</span></code></pre>
+<pre><span id="MODULES"><span class="keyword">module</span> <a href="Linebreaks.S.html">S</a></span>: <code class="code"><span class="keyword">sig</span></code> <a href="Linebreaks.S.html">..</a> <code class="code"><span class="keyword">end</span></code></pre>
+<pre><span id="MODULETYPEs"><span class="keyword">module type</span> <a href="Linebreaks.s-c.html">s</a></span> = <code class="code"><span class="keyword">sig</span></code> <a href="Linebreaks.s-c.html">..</a> <code class="code"><span class="keyword">end</span></code></pre>
<pre><span id="TYPEd"><span class="keyword">class type</span> <a href="Linebreaks.d-c.html">d</a></span> = <code class="code"><span class="keyword">object</span></code> <a href="Linebreaks.d-c.html">..</a> <code class="code"><span class="keyword">end</span></code></pre>
<pre><span id="EXCEPTIONE"><span class="keyword">exception</span> E</span> <span class="keyword">of</span> <code>{</code><table class="typetable">
<tr>
</tr></table>
}
</pre>
-<br>
-type_Linebreaks.html should contain
-<p>
+<p>type_Linebreaks.html should contain</p>
<pre class="codepre"><code class="code"><span class="keyword">sig</span>
<span class="keyword">type</span> a = <span class="constructor">A</span>
<span class="keyword">exception</span> <span class="constructor">E</span> <span class="keyword">of</span> { inline : int; }
<span class="keyword">end</span>
</code></pre>
-<p>
-
-with <br> tags used for linebreaks.
+<p>with <br> tags used for linebreaks.
Another example would be <code class="code"> <span class="keyword">let</span> f x =<br>
-x</code> which is rendered with a <br> linebreak inside Linebreaks.html.
-<p>
+x</code> which is rendered with a <br> linebreak inside Linebreaks.html.</p>
-See <a href="http://caml.inria.fr/mantis/view.php?id=7272">MPR#7272</a> for more
-information.<br>
+<p>See <a href="http://caml.inria.fr/mantis/view.php?id=7272">MPR#7272</a> for more
+information.</p>
</body></html>
\ No newline at end of file
</div>
<h1>Module <a href="type_Loop.html">Loop</a></h1>
-<pre><span class="keyword">module</span> Loop: <code class="code"><span class="keyword">sig</span></code> <a href="Loop.html">..</a> <code class="code"><span class="keyword">end</span></code></pre><hr width="100%">
+<pre><span id="MODULELoop"><span class="keyword">module</span> Loop</span>: <code class="code"><span class="keyword">sig</span></code> <a href="Loop.html">..</a> <code class="code"><span class="keyword">end</span></code></pre><hr width="100%">
-<pre><span class="keyword">module</span> <a href="Loop.A.html">A</a>: <code class="type"><a href="Loop.B.html">B</a></code></pre>
-<pre><span class="keyword">module</span> <a href="Loop.B.html">B</a>: <code class="type"><a href="Loop.A.html">A</a></code></pre></body></html>
\ No newline at end of file
+<pre><span id="MODULEA"><span class="keyword">module</span> <a href="Loop.A.html">A</a></span>: <code class="type"><a href="Loop.B.html">B</a></code></pre>
+<pre><span id="MODULEB"><span class="keyword">module</span> <a href="Loop.B.html">B</a></span>: <code class="type"><a href="Loop.A.html">A</a></code></pre></body></html>
\ No newline at end of file
</div>
<h1>Module <a href="type_Module_whitespace.html">Module_whitespace</a></h1>
-<pre><span class="keyword">module</span> Module_whitespace: <code class="code"><span class="keyword">sig</span></code> <a href="Module_whitespace.html">..</a> <code class="code"><span class="keyword">end</span></code></pre><hr width="100%">
+<pre><span id="MODULEModule_whitespace"><span class="keyword">module</span> Module_whitespace</span>: <code class="code"><span class="keyword">sig</span></code> <a href="Module_whitespace.html">..</a> <code class="code"><span class="keyword">end</span></code></pre><hr width="100%">
-<pre><span class="keyword">module</span> <a href="Module_whitespace.M.html">M</a>: <code class="type">Set.Make</code><code class="code">(</code><code class="code"><span class="keyword">sig</span></code></pre><div class="sig_block">
+<pre><span id="MODULEM"><span class="keyword">module</span> <a href="Module_whitespace.M.html">M</a></span>: <code class="type">Set.Make</code><code class="code">(</code><code class="code"><span class="keyword">sig</span></code></pre><div class="sig_block">
<pre><span id="TYPEt"><span class="keyword">type</span> <code class="type"></code>t</span> = <code class="type">int</code> </pre>
--- /dev/null
+
+open String
+
+(** This is a documentation comment for [x], not a module preamble. *)
+val x: unit
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<link rel="stylesheet" href="style.css" type="text/css">
+<meta content="text/html; charset=iso-8859-1" http-equiv="Content-Type">
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<link rel="Start" href="index.html">
+<link rel="Up" href="index.html">
+<link title="Index of values" rel=Appendix href="index_values.html">
+<link title="Index of modules" rel=Appendix href="index_modules.html">
+<link title="No_preamble" rel="Chapter" href="No_preamble.html"><title>No_preamble</title>
+</head>
+<body>
+<div class="navbar"> <a class="up" href="index.html" title="Index">Up</a>
+ </div>
+<h1>Module <a href="type_No_preamble.html">No_preamble</a></h1>
+
+<pre><span id="MODULENo_preamble"><span class="keyword">module</span> No_preamble</span>: <code class="code"><span class="keyword">sig</span></code> <a href="No_preamble.html">..</a> <code class="code"><span class="keyword">end</span></code></pre><hr width="100%">
+
+<pre><span id="VALx"><span class="keyword">val</span> x</span> : <code class="type">unit</code></pre><div class="info ">
+<div class="info-desc">
+<p>This is a documentation comment for <code class="code">x</code>, not a module preamble.</p>
+</div>
+</div>
+</body></html>
\ No newline at end of file
--- /dev/null
+(** This file tests the generation of paragraph within module comments.
+
+
+ At least three points should be exercised in this tests
+
+ - First, all text should be tagged
+ - Second, no paragraph should contain only spaces characters
+ - Third, the mixing of different text style should not create
+ invalid p tags
+
+
+ See also {{: http://caml.inria.fr/mantis/view.php?id=7352} MPR:7352},
+ {{: http://caml.inria.fr/mantis/view.php?id=7353} MPR:7353}
+
+ {2:here Testing non-text elements }
+
+ [code x ] {i should } be inside a p.
+
+
+ {e But} {b not}
+ {[
+ let complex_code = ()
+ ]}
+ here.
+
+ + An enumerated list first element
+ + second element
+
+ {L Alignement test: left}
+ {R Right}
+ {C Center}
+
+
+ Other complex text{_ in subscript }{^ and superscript}
+ {V Verbatim V}
+
+ There is also {%html: html specific %} elements.
+
+ @author: Florian Angeletti
+ @version: 1
+*)
+
+(** *)
+
+type t
+(**
+ And cross-reference {! t}.
+ {!modules: Paragraph}
+ {!indexlist}
+*)
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<link rel="stylesheet" href="style.css" type="text/css">
+<meta content="text/html; charset=iso-8859-1" http-equiv="Content-Type">
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<link rel="Start" href="index.html">
+<link rel="Up" href="index.html">
+<link title="Index of types" rel=Appendix href="index_types.html">
+<link title="Index of modules" rel=Appendix href="index_modules.html">
+<link title="Paragraph" rel="Chapter" href="Paragraph.html"><title>Paragraph</title>
+</head>
+<body>
+<div class="navbar"> <a class="up" href="index.html" title="Index">Up</a>
+ </div>
+<h1>Module <a href="type_Paragraph.html">Paragraph</a></h1>
+
+<pre><span id="MODULEParagraph"><span class="keyword">module</span> Paragraph</span>: <code class="code"><span class="keyword">sig</span></code> <a href="Paragraph.html">..</a> <code class="code"><span class="keyword">end</span></code></pre><div class="info module top">
+<div class="info-desc">
+<p>This file tests the generation of paragraph within module comments.</p>
+
+<p>At least three points should be exercised in this tests</p>
+
+<ul>
+<li>First, all text should be tagged</li>
+<li>Second, no paragraph should contain only spaces characters</li>
+<li>Third, the mixing of different text style should not create
+ invalid p tags</li>
+</ul>
+<p>See also <a href=" http://caml.inria.fr/mantis/view.php?id=7352"> MPR:7352</a>,
+ <a href=" http://caml.inria.fr/mantis/view.php?id=7353"> MPR:7353</a></p>
+
+<h3 id="here">Testing non-text elements </h3>
+<p><code class="code">code x </code> <i>should </i> be inside a p.</p>
+
+<p><em>But</em> <b>not</b></p>
+<pre class="codepre"><code class="code"> <span class="keyword">let</span> complex_code = ()
+ </code></pre><p>here.</p>
+
+<OL>
+<li>An enumerated list first element</li>
+<li>second element</li>
+</OL>
+<div align=left>Alignement test: left</div><div align=right>Right</div><center>Center</center>
+<p>Other complex text<sub class="subscript">in subscript </sub><sup class="superscript">and superscript</sup></p>
+
+<p>There is also html specific elements.</p>
+</div>
+<ul class="info-attributes">
+<li><b>Author(s):</b> : Florian Angeletti</li>
+<li><b>Version:</b> : 1</li>
+</ul>
+</div>
+<hr width="100%">
+
+<pre><span id="TYPEt"><span class="keyword">type</span> <code class="type"></code>t</span> </pre>
+<div class="info ">
+<div class="info-desc">
+<p>And cross-reference <a href="Paragraph.html#TYPEt"><code class="code"><span class="constructor">Paragraph</span>.t</code></a>.
+
+<table class="indextable module-list">
+<tr><td class="module"><a href="Paragraph.html">Paragraph</a></td><td><div class="info">
+<p>This file tests the generation of paragraph within module comments.</p>
+
+</div>
+</td></tr>
+</table></p>
+<ul class="indexlist">
+<li><a href="index_types.html">Index of types</a></li>
+<li><a href="index_modules.html">Index of modules</a></li>
+</ul>
+</div>
+</div>
+
+</body></html>
\ No newline at end of file
type t =
| A
- (** doc for A *)
+ (** doc for A.
+ {[0]}
+ With three paragraphs.
+ {[1]}
+ To check styling
+ *)
| B
(** doc for B *)
</div>
<h1>Module <a href="type_Variants.html">Variants</a></h1>
-<pre><span class="keyword">module</span> Variants: <code class="code"><span class="keyword">sig</span></code> <a href="Variants.html">..</a> <code class="code"><span class="keyword">end</span></code></pre><div class="info module top">
-This test is here to check the latex code generated for variants<br>
+<pre><span id="MODULEVariants"><span class="keyword">module</span> Variants</span>: <code class="code"><span class="keyword">sig</span></code> <a href="Variants.html">..</a> <code class="code"><span class="keyword">end</span></code></pre><div class="info module top">
+<div class="info-desc">
+<p>This test is here to check the latex code generated for variants</p>
+</div>
</div>
<hr width="100%">
<td align="left" valign="top" >
<code><span id="TYPEELTs.B"><span class="constructor">B</span></span></code></td>
<td class="typefieldcomment" align="left" valign="top" ><code>(*</code></td><td class="typefieldcomment" align="left" valign="top" ><div class="info ">
-only B is documented here<br>
+<div class="info-desc">
+<p>only B is documented here</p>
+</div>
</div>
</td><td class="typefieldcomment" align="left" valign="bottom" ><code>*)</code></td>
</tr>
<td align="left" valign="top" >
<code><span id="TYPEELTt.A"><span class="constructor">A</span></span></code></td>
<td class="typefieldcomment" align="left" valign="top" ><code>(*</code></td><td class="typefieldcomment" align="left" valign="top" ><div class="info ">
-doc for A<br>
+<div class="info-desc">
+<p>doc for A.</p>
+<pre class="codepre"><code class="code">0</code></pre><p>With three paragraphs.</p>
+<pre class="codepre"><code class="code">1</code></pre><p>To check styling</p>
+</div>
</div>
</td><td class="typefieldcomment" align="left" valign="bottom" ><code>*)</code></td>
</tr>
<td align="left" valign="top" >
<code><span id="TYPEELTt.B"><span class="constructor">B</span></span></code></td>
<td class="typefieldcomment" align="left" valign="top" ><code>(*</code></td><td class="typefieldcomment" align="left" valign="top" ><div class="info ">
-doc for B<br>
+<div class="info-desc">
+<p>doc for B</p>
+</div>
</div>
</td><td class="typefieldcomment" align="left" valign="bottom" ><code>*)</code></td>
</tr></table>
<td align="left" valign="top" >
<code><span id="TYPEELTu.A"><span class="constructor">A</span></span></code></td>
<td class="typefieldcomment" align="left" valign="top" ><code>(*</code></td><td class="typefieldcomment" align="left" valign="top" ><div class="info ">
-doc for A<br>
+<div class="info-desc">
+<p>doc for A</p>
+</div>
</div>
</td><td class="typefieldcomment" align="left" valign="bottom" ><code>*)</code></td>
</tr>
<td align="left" valign="top" >
<code><span id="TYPEELTu.B"><span class="constructor">B</span></span> <span class="keyword">of</span> <code class="type">unit</code></code></td>
<td class="typefieldcomment" align="left" valign="top" ><code>(*</code></td><td class="typefieldcomment" align="left" valign="top" ><div class="info ">
-doc for B<br>
+<div class="info-desc">
+<p>doc for B</p>
+</div>
</div>
</td><td class="typefieldcomment" align="left" valign="bottom" ><code>*)</code></td>
</tr></table>
<div class="info ">
-Some documentation for u<br>
+<div class="info-desc">
+<p>Some documentation for u</p>
+</div>
</div>
}
</code></td>
<td class="typefieldcomment" align="left" valign="top" ><code>(*</code></td><td class="typefieldcomment" align="left" valign="top" ><div class="info ">
-doc for A<br>
+<div class="info-desc">
+<p>doc for A</p>
+</div>
</div>
</td><td class="typefieldcomment" align="left" valign="bottom" ><code>*)</code></td>
</tr>
}
</code></td>
<td class="typefieldcomment" align="left" valign="top" ><code>(*</code></td><td class="typefieldcomment" align="left" valign="top" ><div class="info ">
-doc for B<br>
+<div class="info-desc">
+<p>doc for B</p>
+</div>
</div>
</td><td class="typefieldcomment" align="left" valign="bottom" ><code>*)</code></td>
</tr></table>
<div class="info ">
-With records<br>
+<div class="info-desc">
+<p>With records</p>
+</div>
</div>
<td align="left" valign="top" >
<code><span id="TYPEELTz.A"><span class="constructor">A</span></span> <span class="keyword">of</span> <code class="type">int</code></code></td>
<td class="typefieldcomment" align="left" valign="top" ><code>(*</code></td><td class="typefieldcomment" align="left" valign="top" ><div class="info ">
-doc for A<br>
+<div class="info-desc">
+<p>doc for A</p>
+</div>
</div>
</td><td class="typefieldcomment" align="left" valign="bottom" ><code>*)</code></td>
</tr>
<td align="left" valign="top" >
<code><span id="TYPEELTz.B"><span class="constructor">B</span></span> <span class="keyword">of</span> <code class="type">int</code></code></td>
<td class="typefieldcomment" align="left" valign="top" ><code>(*</code></td><td class="typefieldcomment" align="left" valign="top" ><div class="info ">
-doc for B<br>
+<div class="info-desc">
+<p>doc for B</p>
+</div>
</div>
</td><td class="typefieldcomment" align="left" valign="bottom" ><code>*)</code></td>
</tr></table>
<div class="info ">
-With args<br>
+<div class="info-desc">
+<p>With args</p>
+</div>
</div>
<td align="left" valign="top" >
<code><span id="TYPEELTa.A"><span class="constructor">A</span></span> <span class="keyword">:</span> <code class="type"><a href="Variants.html#TYPEa">a</a></code></code></td>
<td class="typefieldcomment" align="left" valign="top" ><code>(*</code></td><td class="typefieldcomment" align="left" valign="top" ><div class="info ">
-doc for A<br>
+<div class="info-desc">
+<p>doc for A</p>
+</div>
</div>
</td><td class="typefieldcomment" align="left" valign="bottom" ><code>*)</code></td>
</tr></table>
<div class="info ">
-Gadt notation<br>
+<div class="info-desc">
+<p>Gadt notation</p>
+</div>
</div>
<td align="left" valign="top" >
<code><span id="TYPEELTb.B"><span class="constructor">B</span></span></code></td>
<td class="typefieldcomment" align="left" valign="top" ><code>(*</code></td><td class="typefieldcomment" align="left" valign="top" ><div class="info ">
-doc for B<br>
+<div class="info-desc">
+<p>doc for B</p>
+</div>
</div>
</td><td class="typefieldcomment" align="left" valign="bottom" ><code>*)</code></td>
</tr></table>
<div class="info ">
-Lonely constructor<br>
+<div class="info-desc">
+<p>Lonely constructor</p>
+</div>
</div>
\end{ocamldocdescription}
-\end{document}
\ No newline at end of file
+\end{document}
(string * string * string) -> unit
val y : int
+ type ob = < f : int >
+
type obj_type =
- < foo : int ; bar : float -> string ; gee : int -> (int * string) >
+ < foo : int ; bar : float -> string ; ob ; gee : int -> (int * string) >
+
+ type g = [`A]
+ type h = [`B of int | g | `C of string]
end
string * string * string ->
string * string * string -> string * string * string -> unit
val y : int
+ type ob = < f : int >
type obj_type =
- < bar : float -> string; foo : int; gee : int -> int * string >
+ < bar : float -> string; f : int; foo : int;
+ gee : int -> int * string >
+ type g = [ `A ]
+ type h = [ `A | `B of int | `C of string ]
end]>
# type T01.MT.t:
# manifest (Odoc_info.string_of_type_expr):
string ->
string * string * string ->
string * string * string -> string * string * string -> unit]>
+# type T01.MT.ob:
+# manifest (Odoc_info.string_of_type_expr):
+<[< f: int ; >]>
# type T01.MT.obj_type:
# manifest (Odoc_info.string_of_type_expr):
-<[< bar: float -> string ; foo: int ; gee: int -> int * string ; >]>
+<[< bar: float -> string ; f: int ; foo: int ; gee: int -> int * string ; >]>
+# type T01.MT.g:
+# manifest (Odoc_info.string_of_type_expr):
+<[[ `A ]]>
+# type T01.MT.h:
+# manifest (Odoc_info.string_of_type_expr):
+<[[ `A | `B of int | `C of string ]]>
--- /dev/null
+BASEDIR=../..
+
+LD_PATH=
+
+# This test ensures that ocamlobjinfo is behaving as the configuration
+# expects and is a guard against the breakage fixed in 17fc532
+
+.PHONY: default
+default:
+ @printf " ... testing 'ocamlobjinfo'"
+ @if ! $(SUPPORTS_SHARED_LIBRARIES) || $(BYTECODE_ONLY) ; then \
+ echo ' => skipped (.cmxs not built)'; \
+ elif ! grep -q HAS_LIBBFD $(TOPDIR)/byterun/caml/s.h ; then \
+ echo ' => skipped (BFD library not available)'; \
+ else \
+ $(SET_LD_PATH) OCAMLLIB=$(TOPDIR)/tools $(MAKE) run; \
+ fi
+
+.PHONY: run
+run:
+ @rm -f $(MAIN_MODULE).result
+ @$(OCAMLOPT) -shared -o question.cmxs question.ml
+ @$(OCAMLRUN) `$(CYGPATH) $(TOPDIR)/tools/ocamlobjinfo` \
+ question.cmxs \
+ > test.raw.result 2>&1 \
+ && sed -e 's/\([^0-9a-z]\)[0-9a-z]\{32\}\([^0-9a-z]\|$$\)/\1<MD5>\2/' \
+ test.raw.result > test.result \
+ && $(DIFF) test.reference test.result > /dev/null \
+ && echo " => passed" || echo " => failed"
+
+.PHONY: promote
+promote: defaultpromote
+
+.PHONY: clean
+clean: defaultclean
+ @rm -f *.result
+
+include $(BASEDIR)/makefiles/Makefile.common
--- /dev/null
+let answer = 42
--- /dev/null
+File question.cmxs
+Name: Question
+CRC of implementation: <MD5>
+Globals defined:
+ Question
+Interfaces imported:
+ <MD5> Question
+ <MD5> Pervasives
+ <MD5> CamlinternalFormatBasics
+Implementations imported:
--- /dev/null
+module L = struct
+ type ('a,'b) t = [] | (::) of 'a * ('b,'a) t
+end;;
+L.[([1;2]:int list);"2";[3;4];"4";[5]];;
+open L;;
+[1;"2";3;"4";5];;
+
+module L = struct
+ type 'a t = 'a list = [] | (::) of 'a * 'a t
+end;;
+L.[[1];[2];[3];[4];[5]];;
+open L;;
+[1;2;3;4;5];;
+
+
--- /dev/null
+
+# module L : sig type ('a, 'b) t = [] | (::) of 'a * ('b, 'a) t end
+# - : (int list, string) L.t =
+L.(::) ([1; 2],
+ L.(::) ("2", L.(::) ([3; 4], L.(::) ("4", L.(::) ([5], L.[])))))
+# # - : (int, string) L.t =
+(::) (1, (::) ("2", (::) (3, (::) ("4", (::) (5, [])))))
+# module L : sig type 'a t = 'a list = [] | (::) of 'a * 'a t end
+# - : int L.t L.t =
+L.(::) (L.(::) (1, L.[]),
+ L.(::) (L.(::) (2, L.[]),
+ L.(::) (L.(::) (3, L.[]),
+ L.(::) (L.(::) (4, L.[]), L.(::) (L.(::) (5, L.[]), L.[])))))
+# # - : int L.t = (::) (1, (::) (2, (::) (3, (::) (4, (::) (5, [])))))
+#
--- /dev/null
+(* Test the printing of strings in the terminal *)
+"\n\t\r\b";;
+
+{|"\'|};;
+
+" !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~";;
+
+"\x00\x01\x02\x03\x04\x05\x06\x07\x0B\x0C\x0E\x0F\
+ \x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\
+ \x7F";;
+
+"\"Ἀχιλλεύς\r\n天照\tब्रह्मन्\t𒄑 𒂆 𒈦 𒄑 𒂆 𒈦\\";;
+
+"ایدهآل";;
--- /dev/null
+
+# - : string = "\n\t\r\b"
+# - : string = "\"\\'"
+# - : string =
+" !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~"
+# - : string =
+"\000\001\002\003\004\005\006\007\011\012\014\015\016\017\018\019\020\021\022\023\024\025\026\027\028\029\030\031\127"
+# - : string =
+"\"Ἀχιλλεύς\r\n天照\tब्रह्मन्\t𒄑 𒂆 𒈦 𒄑 𒂆 𒈦\\"
+# - : string = "ایدهآل"
+#
+newdefault: array_spec.ml.reference module_coercion.ml.reference
+ $(MAKE) default
+
BASEDIR=../..
TOPFLAGS+=-dlambda
include $(BASEDIR)/makefiles/Makefile.dlambda
include $(BASEDIR)/makefiles/Makefile.common
+
+GENERATED_SOURCES = array_spec.ml.reference module_coercion.ml.reference \
+ *.flat-float
+
+ifeq "$(FLAT_FLOAT_ARRAY)" "true"
+suffix = -flat
+else
+suffix = -noflat
+endif
+
+array_spec.ml.reference: array_spec.ml.reference$(suffix) \
+ $(FLAT_FLOAT_ARRAY).flat-float
+ cp $< $@
+
+module_coercion.ml.reference: module_coercion.ml.reference$(suffix) \
+ $(FLAT_FLOAT_ARRAY).flat-float
+ cp $< $@
+
+%.flat-float:
+ @rm -f $(GENERATED_SOURCES)
+ @touch $@
+++ /dev/null
-(setglobal Array_spec!
- (let
- (int_a = (makearray[int] 1 2 3)
- float_a = (makearray[float] 1. 2. 3.)
- addr_a = (makearray[addr] "a" "b" "c"))
- (seq (array.length[int] int_a) (array.length[float] float_a)
- (array.length[addr] addr_a)
- (function a (array.length[gen] a))
- (array.get[int] int_a 0) (array.get[float] float_a 0)
- (array.get[addr] addr_a 0)
- (function a (array.get[gen] a 0))
- (array.unsafe_get[int] int_a 0)
- (array.unsafe_get[float] float_a 0)
- (array.unsafe_get[addr] addr_a 0)
- (function a (array.unsafe_get[gen] a 0))
- (array.set[int] int_a 0 1) (array.set[float] float_a 0 1.)
- (array.set[addr] addr_a 0 "a")
- (function a x (array.set[gen] a 0 x))
- (array.unsafe_set[int] int_a 0 1)
- (array.unsafe_set[float] float_a 0 1.)
- (array.unsafe_set[addr] addr_a 0 "a")
- (function a x (array.unsafe_set[gen] a 0 x))
- (let
- (eta_gen_len =
- (function prim stub (array.length[gen] prim))
- eta_gen_safe_get =
- (function prim prim stub
- (array.get[gen] prim prim))
- eta_gen_unsafe_get =
- (function prim prim stub
- (array.unsafe_get[gen] prim prim))
- eta_gen_safe_set =
- (function prim prim prim stub
- (array.set[gen] prim prim prim))
- eta_gen_unsafe_set =
- (function prim prim prim stub
- (array.unsafe_set[gen] prim prim prim))
- eta_int_len =
- (function prim stub (array.length[int] prim))
- eta_int_safe_get =
- (function prim prim stub
- (array.get[int] prim prim))
- eta_int_unsafe_get =
- (function prim prim stub
- (array.unsafe_get[int] prim prim))
- eta_int_safe_set =
- (function prim prim prim stub
- (array.set[int] prim prim prim))
- eta_int_unsafe_set =
- (function prim prim prim stub
- (array.unsafe_set[int] prim prim prim))
- eta_float_len =
- (function prim stub (array.length[float] prim))
- eta_float_safe_get =
- (function prim prim stub
- (array.get[float] prim prim))
- eta_float_unsafe_get =
- (function prim prim stub
- (array.unsafe_get[float] prim prim))
- eta_float_safe_set =
- (function prim prim prim stub
- (array.set[float] prim prim prim))
- eta_float_unsafe_set =
- (function prim prim prim stub
- (array.unsafe_set[float] prim prim prim))
- eta_addr_len =
- (function prim stub (array.length[addr] prim))
- eta_addr_safe_get =
- (function prim prim stub
- (array.get[addr] prim prim))
- eta_addr_unsafe_get =
- (function prim prim stub
- (array.unsafe_get[addr] prim prim))
- eta_addr_safe_set =
- (function prim prim prim stub
- (array.set[addr] prim prim prim))
- eta_addr_unsafe_set =
- (function prim prim prim stub
- (array.unsafe_set[addr] prim prim prim)))
- (makeblock 0 int_a float_a addr_a eta_gen_len
- eta_gen_safe_get eta_gen_unsafe_get eta_gen_safe_set
- eta_gen_unsafe_set eta_int_len eta_int_safe_get
- eta_int_unsafe_get eta_int_safe_set
- eta_int_unsafe_set eta_float_len eta_float_safe_get
- eta_float_unsafe_get eta_float_safe_set
- eta_float_unsafe_set eta_addr_len eta_addr_safe_get
- eta_addr_unsafe_get eta_addr_safe_set
- eta_addr_unsafe_set)))))
--- /dev/null
+(setglobal Array_spec!
+ (let
+ (int_a = (makearray[int] 1 2 3)
+ float_a = (makearray[float] 1. 2. 3.)
+ addr_a = (makearray[addr] "a" "b" "c"))
+ (seq (array.length[int] int_a) (array.length[float] float_a)
+ (array.length[addr] addr_a)
+ (function a (array.length[gen] a))
+ (array.get[int] int_a 0) (array.get[float] float_a 0)
+ (array.get[addr] addr_a 0)
+ (function a (array.get[gen] a 0))
+ (array.unsafe_get[int] int_a 0)
+ (array.unsafe_get[float] float_a 0)
+ (array.unsafe_get[addr] addr_a 0)
+ (function a (array.unsafe_get[gen] a 0))
+ (array.set[int] int_a 0 1) (array.set[float] float_a 0 1.)
+ (array.set[addr] addr_a 0 "a")
+ (function a x (array.set[gen] a 0 x))
+ (array.unsafe_set[int] int_a 0 1)
+ (array.unsafe_set[float] float_a 0 1.)
+ (array.unsafe_set[addr] addr_a 0 "a")
+ (function a x (array.unsafe_set[gen] a 0 x))
+ (let
+ (eta_gen_len =
+ (function prim stub (array.length[gen] prim))
+ eta_gen_safe_get =
+ (function prim prim stub
+ (array.get[gen] prim prim))
+ eta_gen_unsafe_get =
+ (function prim prim stub
+ (array.unsafe_get[gen] prim prim))
+ eta_gen_safe_set =
+ (function prim prim prim stub
+ (array.set[gen] prim prim prim))
+ eta_gen_unsafe_set =
+ (function prim prim prim stub
+ (array.unsafe_set[gen] prim prim prim))
+ eta_int_len =
+ (function prim stub (array.length[int] prim))
+ eta_int_safe_get =
+ (function prim prim stub
+ (array.get[int] prim prim))
+ eta_int_unsafe_get =
+ (function prim prim stub
+ (array.unsafe_get[int] prim prim))
+ eta_int_safe_set =
+ (function prim prim prim stub
+ (array.set[int] prim prim prim))
+ eta_int_unsafe_set =
+ (function prim prim prim stub
+ (array.unsafe_set[int] prim prim prim))
+ eta_float_len =
+ (function prim stub (array.length[float] prim))
+ eta_float_safe_get =
+ (function prim prim stub
+ (array.get[float] prim prim))
+ eta_float_unsafe_get =
+ (function prim prim stub
+ (array.unsafe_get[float] prim prim))
+ eta_float_safe_set =
+ (function prim prim prim stub
+ (array.set[float] prim prim prim))
+ eta_float_unsafe_set =
+ (function prim prim prim stub
+ (array.unsafe_set[float] prim prim prim))
+ eta_addr_len =
+ (function prim stub (array.length[addr] prim))
+ eta_addr_safe_get =
+ (function prim prim stub
+ (array.get[addr] prim prim))
+ eta_addr_unsafe_get =
+ (function prim prim stub
+ (array.unsafe_get[addr] prim prim))
+ eta_addr_safe_set =
+ (function prim prim prim stub
+ (array.set[addr] prim prim prim))
+ eta_addr_unsafe_set =
+ (function prim prim prim stub
+ (array.unsafe_set[addr] prim prim prim)))
+ (makeblock 0 int_a float_a addr_a eta_gen_len
+ eta_gen_safe_get eta_gen_unsafe_get eta_gen_safe_set
+ eta_gen_unsafe_set eta_int_len eta_int_safe_get
+ eta_int_unsafe_get eta_int_safe_set
+ eta_int_unsafe_set eta_float_len eta_float_safe_get
+ eta_float_unsafe_get eta_float_safe_set
+ eta_float_unsafe_set eta_addr_len eta_addr_safe_get
+ eta_addr_unsafe_get eta_addr_safe_set
+ eta_addr_unsafe_set)))))
--- /dev/null
+(setglobal Array_spec!
+ (let
+ (int_a = (makearray[int] 1 2 3)
+ float_a = (makearray[addr] 1. 2. 3.)
+ addr_a = (makearray[addr] "a" "b" "c"))
+ (seq (array.length[int] int_a) (array.length[addr] float_a)
+ (array.length[addr] addr_a)
+ (function a (array.length[addr] a))
+ (array.get[int] int_a 0) (array.get[addr] float_a 0)
+ (array.get[addr] addr_a 0)
+ (function a (array.get[addr] a 0))
+ (array.unsafe_get[int] int_a 0)
+ (array.unsafe_get[addr] float_a 0)
+ (array.unsafe_get[addr] addr_a 0)
+ (function a (array.unsafe_get[addr] a 0))
+ (array.set[int] int_a 0 1) (array.set[addr] float_a 0 1.)
+ (array.set[addr] addr_a 0 "a")
+ (function a x (array.set[addr] a 0 x))
+ (array.unsafe_set[int] int_a 0 1)
+ (array.unsafe_set[addr] float_a 0 1.)
+ (array.unsafe_set[addr] addr_a 0 "a")
+ (function a x (array.unsafe_set[addr] a 0 x))
+ (let
+ (eta_gen_len =
+ (function prim stub (array.length[addr] prim))
+ eta_gen_safe_get =
+ (function prim prim stub
+ (array.get[addr] prim prim))
+ eta_gen_unsafe_get =
+ (function prim prim stub
+ (array.unsafe_get[addr] prim prim))
+ eta_gen_safe_set =
+ (function prim prim prim stub
+ (array.set[addr] prim prim prim))
+ eta_gen_unsafe_set =
+ (function prim prim prim stub
+ (array.unsafe_set[addr] prim prim prim))
+ eta_int_len =
+ (function prim stub (array.length[int] prim))
+ eta_int_safe_get =
+ (function prim prim stub
+ (array.get[int] prim prim))
+ eta_int_unsafe_get =
+ (function prim prim stub
+ (array.unsafe_get[int] prim prim))
+ eta_int_safe_set =
+ (function prim prim prim stub
+ (array.set[int] prim prim prim))
+ eta_int_unsafe_set =
+ (function prim prim prim stub
+ (array.unsafe_set[int] prim prim prim))
+ eta_float_len =
+ (function prim stub (array.length[addr] prim))
+ eta_float_safe_get =
+ (function prim prim stub
+ (array.get[addr] prim prim))
+ eta_float_unsafe_get =
+ (function prim prim stub
+ (array.unsafe_get[addr] prim prim))
+ eta_float_safe_set =
+ (function prim prim prim stub
+ (array.set[addr] prim prim prim))
+ eta_float_unsafe_set =
+ (function prim prim prim stub
+ (array.unsafe_set[addr] prim prim prim))
+ eta_addr_len =
+ (function prim stub (array.length[addr] prim))
+ eta_addr_safe_get =
+ (function prim prim stub
+ (array.get[addr] prim prim))
+ eta_addr_unsafe_get =
+ (function prim prim stub
+ (array.unsafe_get[addr] prim prim))
+ eta_addr_safe_set =
+ (function prim prim prim stub
+ (array.set[addr] prim prim prim))
+ eta_addr_unsafe_set =
+ (function prim prim prim stub
+ (array.unsafe_set[addr] prim prim prim)))
+ (makeblock 0 int_a float_a addr_a eta_gen_len
+ eta_gen_safe_get eta_gen_unsafe_get eta_gen_safe_set
+ eta_gen_unsafe_set eta_int_len eta_int_safe_get
+ eta_int_unsafe_get eta_int_safe_set
+ eta_int_unsafe_set eta_float_len eta_float_safe_get
+ eta_float_unsafe_get eta_float_safe_set
+ eta_float_unsafe_set eta_addr_len eta_addr_safe_get
+ eta_addr_unsafe_get eta_addr_safe_set
+ eta_addr_unsafe_set)))))
(apply f (field 0 param) (field 1 param)))
map =
(function f l
- (apply (field 15 (global List!)) (apply uncurry f)
+ (apply (field 16 (global List!)) (apply uncurry f)
l)))
(makeblock 0
(makeblock 0 (apply map gen_cmp vec)
(apply f (field 0 param) (field 1 param)))
map =
(function f l
- (apply (field 15 (global List!))
+ (apply (field 16 (global List!))
(apply uncurry f) l)))
(makeblock 0
(makeblock 0 (apply map eta_gen_cmp vec)
+++ /dev/null
-(setglobal Module_coercion!
- (let (M = (makeblock 0))
- (makeblock 0 M
- (makeblock 0 (function prim stub (array.length[int] prim))
- (function prim prim stub
- (array.get[int] prim prim))
- (function prim prim stub
- (array.unsafe_get[int] prim prim))
- (function prim prim prim stub
- (array.set[int] prim prim prim))
- (function prim prim prim stub
- (array.unsafe_set[int] prim prim prim))
- (function prim prim stub
- (caml_int_compare prim prim))
- (function prim prim stub (== prim prim))
- (function prim prim stub (!= prim prim))
- (function prim prim stub (< prim prim))
- (function prim prim stub (> prim prim))
- (function prim prim stub (<= prim prim))
- (function prim prim stub (>= prim prim)))
- (makeblock 0 (function prim stub (array.length[float] prim))
- (function prim prim stub
- (array.get[float] prim prim))
- (function prim prim stub
- (array.unsafe_get[float] prim prim))
- (function prim prim prim stub
- (array.set[float] prim prim prim))
- (function prim prim prim stub
- (array.unsafe_set[float] prim prim prim))
- (function prim prim stub
- (caml_float_compare prim prim))
- (function prim prim stub (==. prim prim))
- (function prim prim stub (!=. prim prim))
- (function prim prim stub (<. prim prim))
- (function prim prim stub (>. prim prim))
- (function prim prim stub (<=. prim prim))
- (function prim prim stub (>=. prim prim)))
- (makeblock 0 (function prim stub (array.length[addr] prim))
- (function prim prim stub
- (array.get[addr] prim prim))
- (function prim prim stub
- (array.unsafe_get[addr] prim prim))
- (function prim prim prim stub
- (array.set[addr] prim prim prim))
- (function prim prim prim stub
- (array.unsafe_set[addr] prim prim prim))
- (function prim prim stub
- (caml_string_compare prim prim))
- (function prim prim stub
- (caml_string_equal prim prim))
- (function prim prim stub
- (caml_string_notequal prim prim))
- (function prim prim stub
- (caml_string_lessthan prim prim))
- (function prim prim stub
- (caml_string_greaterthan prim prim))
- (function prim prim stub
- (caml_string_lessequal prim prim))
- (function prim prim stub
- (caml_string_greaterequal prim prim)))
- (makeblock 0 (function prim stub (array.length[addr] prim))
- (function prim prim stub
- (array.get[addr] prim prim))
- (function prim prim stub
- (array.unsafe_get[addr] prim prim))
- (function prim prim prim stub
- (array.set[addr] prim prim prim))
- (function prim prim prim stub
- (array.unsafe_set[addr] prim prim prim))
- (function prim prim stub
- (caml_int32_compare prim prim))
- (function prim prim stub (Int32.== prim prim))
- (function prim prim stub (Int32.!= prim prim))
- (function prim prim stub (Int32.< prim prim))
- (function prim prim stub (Int32.> prim prim))
- (function prim prim stub (Int32.<= prim prim))
- (function prim prim stub (Int32.>= prim prim)))
- (makeblock 0 (function prim stub (array.length[addr] prim))
- (function prim prim stub
- (array.get[addr] prim prim))
- (function prim prim stub
- (array.unsafe_get[addr] prim prim))
- (function prim prim prim stub
- (array.set[addr] prim prim prim))
- (function prim prim prim stub
- (array.unsafe_set[addr] prim prim prim))
- (function prim prim stub
- (caml_int64_compare prim prim))
- (function prim prim stub (Int64.== prim prim))
- (function prim prim stub (Int64.!= prim prim))
- (function prim prim stub (Int64.< prim prim))
- (function prim prim stub (Int64.> prim prim))
- (function prim prim stub (Int64.<= prim prim))
- (function prim prim stub (Int64.>= prim prim)))
- (makeblock 0 (function prim stub (array.length[addr] prim))
- (function prim prim stub
- (array.get[addr] prim prim))
- (function prim prim stub
- (array.unsafe_get[addr] prim prim))
- (function prim prim prim stub
- (array.set[addr] prim prim prim))
- (function prim prim prim stub
- (array.unsafe_set[addr] prim prim prim))
- (function prim prim stub
- (caml_nativeint_compare prim prim))
- (function prim prim stub
- (Nativeint.== prim prim))
- (function prim prim stub
- (Nativeint.!= prim prim))
- (function prim prim stub (Nativeint.< prim prim))
- (function prim prim stub (Nativeint.> prim prim))
- (function prim prim stub
- (Nativeint.<= prim prim))
- (function prim prim stub
- (Nativeint.>= prim prim))))))
--- /dev/null
+(setglobal Module_coercion!
+ (let
+ (M = (module-defn(M) module_coercion.ml(1):0-699 (makeblock 0)))
+ (makeblock 0 M
+ (module-defn(M_int) module_coercion.ml(32):1116-1155
+ (makeblock 0 (function prim stub (array.length[int] prim))
+ (function prim prim stub
+ (array.get[int] prim prim))
+ (function prim prim stub
+ (array.unsafe_get[int] prim prim))
+ (function prim prim prim stub
+ (array.set[int] prim prim prim))
+ (function prim prim prim stub
+ (array.unsafe_set[int] prim prim prim))
+ (function prim prim stub
+ (caml_int_compare prim prim))
+ (function prim prim stub (== prim prim))
+ (function prim prim stub (!= prim prim))
+ (function prim prim stub (< prim prim))
+ (function prim prim stub (> prim prim))
+ (function prim prim stub (<= prim prim))
+ (function prim prim stub (>= prim prim))))
+ (module-defn(M_float) module_coercion.ml(33):1158-1201
+ (makeblock 0
+ (function prim stub (array.length[float] prim))
+ (function prim prim stub
+ (array.get[float] prim prim))
+ (function prim prim stub
+ (array.unsafe_get[float] prim prim))
+ (function prim prim prim stub
+ (array.set[float] prim prim prim))
+ (function prim prim prim stub
+ (array.unsafe_set[float] prim prim prim))
+ (function prim prim stub
+ (caml_float_compare prim prim))
+ (function prim prim stub (==. prim prim))
+ (function prim prim stub (!=. prim prim))
+ (function prim prim stub (<. prim prim))
+ (function prim prim stub (>. prim prim))
+ (function prim prim stub (<=. prim prim))
+ (function prim prim stub (>=. prim prim))))
+ (module-defn(M_string) module_coercion.ml(34):1204-1249
+ (makeblock 0 (function prim stub (array.length[addr] prim))
+ (function prim prim stub
+ (array.get[addr] prim prim))
+ (function prim prim stub
+ (array.unsafe_get[addr] prim prim))
+ (function prim prim prim stub
+ (array.set[addr] prim prim prim))
+ (function prim prim prim stub
+ (array.unsafe_set[addr] prim prim prim))
+ (function prim prim stub
+ (caml_string_compare prim prim))
+ (function prim prim stub
+ (caml_string_equal prim prim))
+ (function prim prim stub
+ (caml_string_notequal prim prim))
+ (function prim prim stub
+ (caml_string_lessthan prim prim))
+ (function prim prim stub
+ (caml_string_greaterthan prim prim))
+ (function prim prim stub
+ (caml_string_lessequal prim prim))
+ (function prim prim stub
+ (caml_string_greaterequal prim prim))))
+ (module-defn(M_int32/1104) module_coercion.ml(35):1252-1295
+ (makeblock 0 (function prim stub (array.length[addr] prim))
+ (function prim prim stub
+ (array.get[addr] prim prim))
+ (function prim prim stub
+ (array.unsafe_get[addr] prim prim))
+ (function prim prim prim stub
+ (array.set[addr] prim prim prim))
+ (function prim prim prim stub
+ (array.unsafe_set[addr] prim prim prim))
+ (function prim prim stub
+ (caml_int32_compare prim prim))
+ (function prim prim stub (Int32.== prim prim))
+ (function prim prim stub (Int32.!= prim prim))
+ (function prim prim stub (Int32.< prim prim))
+ (function prim prim stub (Int32.> prim prim))
+ (function prim prim stub (Int32.<= prim prim))
+ (function prim prim stub (Int32.>= prim prim))))
+ (module-defn(M_int64/1129) module_coercion.ml(36):1298-1341
+ (makeblock 0 (function prim stub (array.length[addr] prim))
+ (function prim prim stub
+ (array.get[addr] prim prim))
+ (function prim prim stub
+ (array.unsafe_get[addr] prim prim))
+ (function prim prim prim stub
+ (array.set[addr] prim prim prim))
+ (function prim prim prim stub
+ (array.unsafe_set[addr] prim prim prim))
+ (function prim prim stub
+ (caml_int64_compare prim prim))
+ (function prim prim stub (Int64.== prim prim))
+ (function prim prim stub (Int64.!= prim prim))
+ (function prim prim stub (Int64.< prim prim))
+ (function prim prim stub (Int64.> prim prim))
+ (function prim prim stub (Int64.<= prim prim))
+ (function prim prim stub (Int64.>= prim prim))))
+ (module-defn(M_nativeint) module_coercion.ml(37):1344-1395
+ (makeblock 0 (function prim stub (array.length[addr] prim))
+ (function prim prim stub
+ (array.get[addr] prim prim))
+ (function prim prim stub
+ (array.unsafe_get[addr] prim prim))
+ (function prim prim prim stub
+ (array.set[addr] prim prim prim))
+ (function prim prim prim stub
+ (array.unsafe_set[addr] prim prim prim))
+ (function prim prim stub
+ (caml_nativeint_compare prim prim))
+ (function prim prim stub
+ (Nativeint.== prim prim))
+ (function prim prim stub
+ (Nativeint.!= prim prim))
+ (function prim prim stub
+ (Nativeint.< prim prim))
+ (function prim prim stub
+ (Nativeint.> prim prim))
+ (function prim prim stub
+ (Nativeint.<= prim prim))
+ (function prim prim stub
+ (Nativeint.>= prim prim)))))))
--- /dev/null
+(setglobal Module_coercion!
+ (let
+ (M = (module-defn(M) module_coercion.ml(1):0-699 (makeblock 0)))
+ (makeblock 0 M
+ (module-defn(M_int) module_coercion.ml(32):1116-1155
+ (makeblock 0 (function prim stub (array.length[int] prim))
+ (function prim prim stub
+ (array.get[int] prim prim))
+ (function prim prim stub
+ (array.unsafe_get[int] prim prim))
+ (function prim prim prim stub
+ (array.set[int] prim prim prim))
+ (function prim prim prim stub
+ (array.unsafe_set[int] prim prim prim))
+ (function prim prim stub
+ (caml_int_compare prim prim))
+ (function prim prim stub (== prim prim))
+ (function prim prim stub (!= prim prim))
+ (function prim prim stub (< prim prim))
+ (function prim prim stub (> prim prim))
+ (function prim prim stub (<= prim prim))
+ (function prim prim stub (>= prim prim))))
+ (module-defn(M_float) module_coercion.ml(33):1158-1201
+ (makeblock 0 (function prim stub (array.length[addr] prim))
+ (function prim prim stub
+ (array.get[addr] prim prim))
+ (function prim prim stub
+ (array.unsafe_get[addr] prim prim))
+ (function prim prim prim stub
+ (array.set[addr] prim prim prim))
+ (function prim prim prim stub
+ (array.unsafe_set[addr] prim prim prim))
+ (function prim prim stub
+ (caml_float_compare prim prim))
+ (function prim prim stub (==. prim prim))
+ (function prim prim stub (!=. prim prim))
+ (function prim prim stub (<. prim prim))
+ (function prim prim stub (>. prim prim))
+ (function prim prim stub (<=. prim prim))
+ (function prim prim stub (>=. prim prim))))
+ (module-defn(M_string) module_coercion.ml(34):1204-1249
+ (makeblock 0 (function prim stub (array.length[addr] prim))
+ (function prim prim stub
+ (array.get[addr] prim prim))
+ (function prim prim stub
+ (array.unsafe_get[addr] prim prim))
+ (function prim prim prim stub
+ (array.set[addr] prim prim prim))
+ (function prim prim prim stub
+ (array.unsafe_set[addr] prim prim prim))
+ (function prim prim stub
+ (caml_string_compare prim prim))
+ (function prim prim stub
+ (caml_string_equal prim prim))
+ (function prim prim stub
+ (caml_string_notequal prim prim))
+ (function prim prim stub
+ (caml_string_lessthan prim prim))
+ (function prim prim stub
+ (caml_string_greaterthan prim prim))
+ (function prim prim stub
+ (caml_string_lessequal prim prim))
+ (function prim prim stub
+ (caml_string_greaterequal prim prim))))
+ (module-defn(M_int32/1104) module_coercion.ml(35):1252-1295
+ (makeblock 0 (function prim stub (array.length[addr] prim))
+ (function prim prim stub
+ (array.get[addr] prim prim))
+ (function prim prim stub
+ (array.unsafe_get[addr] prim prim))
+ (function prim prim prim stub
+ (array.set[addr] prim prim prim))
+ (function prim prim prim stub
+ (array.unsafe_set[addr] prim prim prim))
+ (function prim prim stub
+ (caml_int32_compare prim prim))
+ (function prim prim stub (Int32.== prim prim))
+ (function prim prim stub (Int32.!= prim prim))
+ (function prim prim stub (Int32.< prim prim))
+ (function prim prim stub (Int32.> prim prim))
+ (function prim prim stub (Int32.<= prim prim))
+ (function prim prim stub (Int32.>= prim prim))))
+ (module-defn(M_int64/1129) module_coercion.ml(36):1298-1341
+ (makeblock 0 (function prim stub (array.length[addr] prim))
+ (function prim prim stub
+ (array.get[addr] prim prim))
+ (function prim prim stub
+ (array.unsafe_get[addr] prim prim))
+ (function prim prim prim stub
+ (array.set[addr] prim prim prim))
+ (function prim prim prim stub
+ (array.unsafe_set[addr] prim prim prim))
+ (function prim prim stub
+ (caml_int64_compare prim prim))
+ (function prim prim stub (Int64.== prim prim))
+ (function prim prim stub (Int64.!= prim prim))
+ (function prim prim stub (Int64.< prim prim))
+ (function prim prim stub (Int64.> prim prim))
+ (function prim prim stub (Int64.<= prim prim))
+ (function prim prim stub (Int64.>= prim prim))))
+ (module-defn(M_nativeint) module_coercion.ml(37):1344-1395
+ (makeblock 0 (function prim stub (array.length[addr] prim))
+ (function prim prim stub
+ (array.get[addr] prim prim))
+ (function prim prim stub
+ (array.unsafe_get[addr] prim prim))
+ (function prim prim prim stub
+ (array.set[addr] prim prim prim))
+ (function prim prim prim stub
+ (array.unsafe_set[addr] prim prim prim))
+ (function prim prim stub
+ (caml_nativeint_compare prim prim))
+ (function prim prim stub
+ (Nativeint.== prim prim))
+ (function prim prim stub
+ (Nativeint.!= prim prim))
+ (function prim prim stub
+ (Nativeint.< prim prim))
+ (function prim prim stub
+ (Nativeint.> prim prim))
+ (function prim prim stub
+ (Nativeint.<= prim prim))
+ (function prim prim stub
+ (Nativeint.>= prim prim)))))))
--- /dev/null
+#**************************************************************************
+#* *
+#* OCaml *
+#* *
+#* Xavier Clerc, SED, 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 GNU Lesser General Public License version 2.1, with the *
+#* special exception on linking described in the file LICENSE. *
+#* *
+#**************************************************************************
+
+BASEDIR=../..
+include $(BASEDIR)/makefiles/Makefile.expect
+include $(BASEDIR)/makefiles/Makefile.common
--- /dev/null
+[@@@ocaml.warning "+3"];;
+
+module X: sig
+ type t [@@ocaml.deprecated]
+ type s [@@ocaml.deprecated]
+ type u [@@ocaml.deprecated]
+ val x: t [@@ocaml.deprecated]
+end = struct
+ type t = int
+ type s
+ type u
+ let x = 0
+end;;
+[%%expect{|
+Line _, characters 9-10:
+Warning 3: deprecated: t
+module X : sig type t type s type u val x : t end
+|}]
+
+type t = X.t
+;;
+[%%expect{|
+Line _, characters 9-12:
+Warning 3: deprecated: X.t
+type t = X.t
+|}]
+
+let x = X.x
+;;
+[%%expect{|
+Line _, characters 8-11:
+Warning 3: deprecated: X.x
+val x : X.t = <abstr>
+|}]
+
+(* Type declarations *)
+
+type t = X.t * X.s
+;;
+[%%expect{|
+Line _, characters 9-12:
+Warning 3: deprecated: X.t
+Line _, characters 15-18:
+Warning 3: deprecated: X.s
+type t = X.t * X.s
+|}]
+
+type t = X.t * X.s [@@ocaml.warning "-3"]
+;;
+[%%expect{|
+type t = X.t * X.s
+|}]
+
+type t1 = X.t [@@ocaml.warning "-3"]
+and t2 = X.s
+;;
+[%%expect{|
+Line _, characters 9-12:
+Warning 3: deprecated: X.s
+type t1 = X.t
+and t2 = X.s
+|}]
+
+type t = A of t [@@ocaml.deprecated]
+;;
+[%%expect{|
+Line _, characters 14-15:
+Warning 3: deprecated: t
+type t = A of t
+|}]
+
+type t = A of t
+ [@@ocaml.deprecated]
+ [@@ocaml.warning "-3"]
+;;
+[%%expect{|
+type t = A of t
+|}]
+
+(* Type expressions *)
+
+type t = (X.t * X.s) [@ocaml.warning "-3"]
+;;
+[%%expect{|
+type t = X.t * X.s
+|}]
+
+type t = (X.t [@ocaml.warning "-3"]) * X.s
+;;
+[%%expect{|
+Line _, characters 39-42:
+Warning 3: deprecated: X.s
+type t = X.t * X.s
+|}]
+
+
+type t = A of (t [@ocaml.warning "-3"])
+ [@@ocaml.deprecated]
+;;
+[%%expect{|
+type t = A of t
+|}]
+
+(* Pattern expressions *)
+
+let _ = function (_ : X.t) -> ()
+;;
+[%%expect{|
+Line _, characters 22-25:
+Warning 3: deprecated: X.t
+- : X.t -> unit = <fun>
+|}]
+
+let _ = function (_ : X.t)[@ocaml.warning "-3"] -> ()
+;;
+[%%expect{|
+- : X.t -> unit = <fun>
+|}]
+
+
+(* Module expressions and module declarations *)
+
+module M = struct let x = X.x end
+;;
+[%%expect{|
+Line _, characters 26-29:
+Warning 3: deprecated: X.x
+module M : sig val x : X.t end
+|}]
+
+module M = (struct let x = X.x end)[@ocaml.warning "-3"]
+;;
+[%%expect{|
+module M : sig val x : X.t end
+|}]
+
+module M = struct let x = X.x end [@@ocaml.warning "-3"]
+;;
+[%%expect{|
+module M : sig val x : X.t end
+|}]
+
+
+module rec M : sig val x: X.t end = struct let x = X.x end
+[%%expect{|
+Line _, characters 26-29:
+Warning 3: deprecated: X.t
+Line _, characters 51-54:
+Warning 3: deprecated: X.x
+module rec M : sig val x : X.t end
+|}]
+
+module rec M : sig val x: X.t end = struct let x = X.x end [@@ocaml.warning "-3"]
+[%%expect{|
+module rec M : sig val x : X.t end
+|}]
+
+module rec M :
+ (sig val x: X.t end)[@ocaml.warning "-3"] =
+ (struct let x = X.x end)[@ocaml.warning "-3"]
+[%%expect{|
+module rec M : sig val x : X.t end
+|}]
+
+module rec M :
+ (sig val x: X.t end)[@ocaml.warning "-3"] =
+ struct let x = X.x end
+[%%expect{|
+Line _, characters 17-20:
+Warning 3: deprecated: X.x
+module rec M : sig val x : X.t end
+|}]
+
+(* Module type expressions and module type declarations *)
+
+module type S = sig type t = X.t end
+;;
+[%%expect{|
+Line _, characters 29-32:
+Warning 3: deprecated: X.t
+module type S = sig type t = X.t end
+|}]
+
+module type S = (sig type t = X.t end)[@ocaml.warning "-3"]
+;;
+[%%expect{|
+module type S = sig type t = X.t end
+|}]
+
+module type S = sig type t = X.t end[@@ocaml.warning "-3"]
+;;
+[%%expect{|
+module type S = sig type t = X.t end
+|}]
+
+
+(* Class expressions, class declarations and class fields *)
+
+class c = object method x = X.x end
+;;
+[%%expect{|
+Line _, characters 28-31:
+Warning 3: deprecated: X.x
+class c : object method x : X.t end
+|}]
+
+class c = object method x = X.x end[@@ocaml.warning "-3"]
+;;
+[%%expect{|
+class c : object method x : X.t end
+|}]
+
+class c = (object method x = X.x end)[@ocaml.warning "-3"]
+;;
+[%%expect{|
+class c : object method x : X.t end
+|}]
+
+class c = object method x = X.x [@@ocaml.warning "-3"] end
+;;
+[%%expect{|
+class c : object method x : X.t end
+|}]
+
+(* Class type expressions, class type declarations
+ and class type fields *)
+
+class type c = object method x : X.t end
+;;
+[%%expect{|
+Line _, characters 33-36:
+Warning 3: deprecated: X.t
+class type c = object method x : X.t end
+|}]
+
+class type c = object method x : X.t end[@@ocaml.warning "-3"]
+;;
+[%%expect{|
+class type c = object method x : X.t end
+|}]
+
+class type c = object method x : X.t end[@ocaml.warning "-3"]
+;;
+[%%expect{|
+class type c = object method x : X.t end
+|}]
+
+class type c = object method x : X.t [@@ocaml.warning "-3"] end
+;;
+[%%expect{|
+class type c = object method x : X.t end
+|}]
+
+
+
+(* External declarations *)
+
+external foo: unit -> X.t = "foo"
+;;
+[%%expect{|
+Line _, characters 22-25:
+Warning 3: deprecated: X.t
+external foo : unit -> X.t = "foo"
+|}]
+
+external foo: unit -> X.t = "foo"[@@ocaml.warning "-3"]
+;;
+[%%expect{|
+external foo : unit -> X.t = "foo"
+|}]
+
+
+(* Eval *)
+;;
+X.x
+;;
+[%%expect{|
+Line _, characters 0-3:
+Warning 3: deprecated: X.x
+- : X.t = <abstr>
+|}]
+
+;;
+X.x [@@ocaml.warning "-3"]
+;;
+[%%expect{|
+- : X.t = <abstr>
+|}]
+
+(* Open / include *)
+
+module D = struct end[@@ocaml.deprecated]
+
+open D
+;;
+[%%expect{|
+module D : sig end
+Line _, characters 5-6:
+Warning 3: deprecated: module D
+|}]
+
+open D [@@ocaml.warning "-3"]
+;;
+[%%expect{|
+|}]
+
+include D
+;;
+[%%expect{|
+Line _, characters 8-9:
+Warning 3: deprecated: module D
+|}]
+
+include D [@@ocaml.warning "-3"]
+;;
+[%%expect{|
+|}]
+
+
+(* Type extensions *)
+
+type ext = ..
+;;
+[%%expect{|
+type ext = ..
+|}]
+
+type ext +=
+ | A of X.t
+ | B of (X.s [@ocaml.warning "-3"])
+ | C of X.u [@ocaml.warning "-3"]
+;;
+[%%expect{|
+Line _, characters 9-12:
+Warning 3: deprecated: X.t
+type ext += A of X.t | B of X.s | C of X.u
+|}]
+
+type ext +=
+ | C of X.t
+ [@@ocaml.warning "-3"]
+;;
+[%%expect{|
+type ext += C of X.t
+|}]
+
+
+exception Foo of X.t
+;;
+[%%expect{|
+Line _, characters 17-20:
+Warning 3: deprecated: X.t
+exception Foo of X.t
+|}]
+
+exception Foo of X.t [@ocaml.warning "-3"]
+;;
+[%%expect{|
+exception Foo of X.t
+|}]
+
+
+(* Labels/constructors/fields *)
+
+type t =
+ | A of X.t
+ | B of X.s [@ocaml.warning "-3"]
+ | C of (X.u [@ocaml.warning "-3"])
+;;
+[%%expect{|
+Line _, characters 9-12:
+Warning 3: deprecated: X.t
+type t = A of X.t | B of X.s | C of X.u
+|}]
+
+type t =
+ {
+ a: X.t;
+ b: X.s [@ocaml.warning "-3"];
+ c: (X.u [@ocaml.warning "-3"]);
+ }
+;;
+[%%expect{|
+Line _, characters 7-10:
+Warning 3: deprecated: X.t
+type t = { a : X.t; b : X.s; c : X.u; }
+|}]
+
+
+type t =
+ <
+ a: X.t;
+ b: X.s [@ocaml.warning "-3"];
+ c: (X.u [@ocaml.warning "-3"]);
+ >
+;;
+[%%expect{|
+Line _, characters 7-10:
+Warning 3: deprecated: X.t
+type t = < a : X.t; b : X.s; c : X.u >
+|}]
+
+
+type t =
+ [
+ | `A of X.t
+ | `B of X.s [@ocaml.warning "-3"]
+ | `C of (X.u [@ocaml.warning "-3"])
+ ]
+;;
+[%%expect{|
+Line _, characters 10-13:
+Warning 3: deprecated: X.t
+type t = [ `A of X.t | `B of X.s | `C of X.u ]
+|}]
+
+
+(* Test for ocaml.ppwarning, and its interactions with ocaml.warning *)
+
+
+[@@@ocaml.ppwarning "Pp warning!"]
+;;
+[%%expect{|
+Line _, characters 20-33:
+Warning 22: Pp warning!
+|}]
+
+
+let x = () [@ocaml.ppwarning "Pp warning 1!"]
+ [@@ocaml.ppwarning "Pp warning 2!"]
+;;
+[%%expect{|
+Line _, characters 24-39:
+Warning 22: Pp warning 2!
+Line _, characters 29-44:
+Warning 22: Pp warning 1!
+val x : unit = ()
+|}]
+
+type t = unit
+ [@ocaml.ppwarning "Pp warning!"]
+;;
+[%%expect{|
+Line _, characters 22-35:
+Warning 22: Pp warning!
+type t = unit
+|}]
+
+module X = struct
+ [@@@ocaml.warning "-22"]
+
+ [@@@ocaml.ppwarning "Pp warning1!"]
+
+ [@@@ocaml.warning "+22"]
+
+ [@@@ocaml.ppwarning "Pp warning2!"]
+end
+;;
+[%%expect{|
+Line _, characters 22-36:
+Warning 22: Pp warning2!
+module X : sig end
+|}]
+
+let x = ((() [@ocaml.ppwarning "Pp warning 1!"]) [@ocaml.warning "-22"]) [@ocaml.ppwarning "Pp warning 2!"]
+;;
+[%%expect{|
+Line _, characters 93-108:
+Warning 22: Pp warning 2!
+val x : unit = ()
+|}]
+
+type t = ((unit [@ocaml.ppwarning "Pp warning 1!"]) [@ocaml.warning "-22"]) [@ocaml.ppwarning "Pp warning 2!"]
+ [@@ocaml.ppwarning "Pp warning 3!"]
+;;
+[%%expect{|
+Line _, characters 21-36:
+Warning 22: Pp warning 3!
+Line _, characters 96-111:
+Warning 22: Pp warning 2!
+type t = unit
+|}]
+
+let ([][@ocaml.ppwarning "XX"]) = []
+;;
+[%%expect{|
+Line _, characters 25-29:
+Warning 22: XX
+Line _, characters 4-31:
+Warning 8: this pattern-matching is not exhaustive.
+Here is an example of a case that is not matched:
+_::_
+|}]
+let[@ocaml.warning "-8-22"] ([][@ocaml.ppwarning "XX"]) = []
+;;
+[%%expect{|
+|}]
type foo += A of int (* Error type is not open *)
;;
+(* The type must be public to create extension *)
+
+type foo = private ..
+;;
+
+type foo += A of int (* Error type is private *)
+;;
+
(* The type parameters must match *)
type 'a foo = ..
type ('a, 'b) foo += A of int (* Error: type parameter mismatch *)
;;
-(* In a signature the type does not have to be open *)
+(* In a signature the type can be private *)
module type S =
sig
- type foo
+ type foo = private ..
type foo += A of float
end
;;
module type S =
sig
- type foo = A of int
- type foo += B of float (* Error foo does not have an extensible type *)
+ type foo
+ type foo += B of float (* Error: foo does not have an extensible type *)
end
;;
type foo += C = Unknown (* Error: unbound extension *)
;;
-(* Extensions can be rebound even if type is closed *)
+(* Extensions can be rebound even if type is private *)
-module M : sig type foo type foo += A1 of int end
+module M : sig type foo = private .. type foo += A1 of int end
= struct type foo = .. type foo += A1 of int end
type M.foo += A2 = M.A1
# type foo += A | B of int
# val is_a : foo -> bool = <fun>
# type foo
-# Characters 13-21:
+# Characters 1-21:
type foo += A of int (* Error type is not open *)
+ ^^^^^^^^^^^^^^^^^^^^
+Error: Type definition foo is not extensible
+# type foo = private ..
+# Characters 13-21:
+ type foo += A of int (* Error type is private *)
^^^^^^^^
-Error: Cannot extend type definition foo
+Error: Cannot extend private type definition foo
# type 'a foo = ..
# Characters 1-30:
type ('a, 'b) foo += A of int (* Error: type parameter mismatch *)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error: This extension does not match the definition of type foo
They have different arities.
-# module type S = sig type foo type foo += A of float end
-# Characters 84-106:
- type foo += B of float (* Error foo does not have an extensible type *)
+# module type S = sig type foo = private .. type foo += A of float end
+# Characters 73-95:
+ type foo += B of float (* Error: foo does not have an extensible type *)
^^^^^^^^^^^^^^^^^^^^^^
-Error: Type foo is not extensible
+Error: Type definition foo is not extensible
# type foo = ..
# module M :
sig
type foo += C = Unknown (* Error: unbound extension *)
^^^^^^^
Error: Unbound constructor Unknown
-# module M : sig type foo type foo += A1 of int end
+# module M : sig type foo = private .. type foo += A1 of int end
type M.foo += A2 of int
type 'a foo = ..
# type 'a foo1 = 'a foo = ..
module Msg : sig
- type 'a tag
+ type 'a tag = private ..
type result = Result : 'a tag * 'a -> result
# module Msg :
sig
- type 'a tag
+ type 'a tag = private ..
type result = Result : 'a tag * 'a -> result
val write : 'a tag -> 'a -> unit
val read : unit -> result
type ('a, 'b) bar = ('a, 'a) foo = .. (* Error: constraints do not match *)
;;
-(* Private abstract types cannot be open *)
+(* Check that signatures can hide exstensibility *)
-type foo = ..
+module M = struct type foo = .. end
+;;
+
+module type S = sig type foo end
+;;
+
+module M_S = (M : S)
;;
-type bar = private foo = .. (* ERROR: Private abstract types cannot be open *)
+type M_S.foo += Foo (* ERROR: Cannot extend a type that isn't "open" *)
;;
-(* Check that signatures can hide open-ness *)
+(* Check that signatures cannot add extensibility *)
+
+module M = struct type foo end
+;;
+
+module type S = sig type foo = .. end
+;;
+
+module M_S = (M : S) (* ERROR: Signatures are not compatible *)
+;;
+
+(* Check that signatures can make exstensibility private *)
module M = struct type foo = .. end
;;
-module type S = sig type foo end
+module type S = sig type foo = private .. end
;;
module M_S = (M : S)
;;
-type M_S.foo += Foo (* ERROR: Cannot extend a type that isn't "open" *)
+type M_S.foo += Foo (* ERROR: Cannot extend a private extensible type *)
;;
-(* Check that signatures cannot add open-ness *)
+(* Check that signatures cannot make private extensibility public *)
-module M = struct type foo end
+module M = struct type foo = private .. end
;;
module type S = sig type foo = .. end
module M_S = (M : S) (* ERROR: Signatures are not compatible *)
;;
+
(* Check that signatures maintain variances *)
module M = struct type +'a foo = .. type 'a bar = 'a foo = .. end
# module M_S : S
# type foo = ..
# type bar = foo
-# Characters 13-23:
+# Characters 1-23:
type bar += Bar of int (* Error: type is not open *)
- ^^^^^^^^^^
-Error: Cannot extend type definition bar
+ ^^^^^^^^^^^^^^^^^^^^^^
+Error: Type definition bar is not extensible
# Characters 1-20:
type baz = bar = .. (* Error: type kinds don't match *)
^^^^^^^^^^^^^^^^^^^
Error: This variant or record definition does not match that of type
('a, 'a) foo
Their constraints differ.
-# type foo = ..
-# Characters 24-25:
- type bar = private foo = .. (* ERROR: Private abstract types cannot be open *)
- ^
-Error: Syntax error
# module M : sig type foo = .. end
# module type S = sig type foo end
# module M_S : S
-# Characters 17-20:
+# Characters 1-20:
type M_S.foo += Foo (* ERROR: Cannot extend a type that isn't "open" *)
- ^^^
-Error: Cannot extend type definition M_S.foo
+ ^^^^^^^^^^^^^^^^^^^
+Error: Type definition M_S.foo is not extensible
# module M : sig type foo end
# module type S = sig type foo = .. end
# Characters 15-16:
is not included in
type foo = ..
Their kinds differ.
-# module M : sig type +'a foo = .. type 'a bar = 'a foo = .. end
+# module M : sig type foo = .. end
+# module type S = sig type foo = private .. end
+# module M_S : S
+# Characters 17-20:
+ type M_S.foo += Foo (* ERROR: Cannot extend a private extensible type *)
+ ^^^
+Error: Cannot extend private type definition M_S.foo
+# module M : sig type foo = private .. end
+# module type S = sig type foo = .. end
+# Characters 15-16:
+ module M_S = (M : S) (* ERROR: Signatures are not compatible *)
+ ^
+Error: Signature mismatch:
+ Modules do not match:
+ sig type foo = M.foo = private .. end
+ is not included in
+ S
+ Type declarations do not match:
+ type foo = M.foo = private ..
+ is not included in
+ type foo = ..
+ A private type would be revealed.
+# module M : sig type +'a foo = .. type 'a bar = 'a foo = .. end
# module type S = sig type 'a foo = .. type 'a bar = 'a foo = .. end
# Characters 15-16:
module M_S = (M : S) (* ERROR: Signatures are not compatible *)
val suc :
(('a, 'b, (suc, int -> int, 'c) rcons) rcons, int) lam ->
(('a, 'b, (suc, int -> int, 'c) rcons) rcons, int) lam = <fun>
-val _1 : ((zero, int, (suc, int -> int, '_a) rcons) rcons, int) lam =
+val _1 : ((zero, int, (suc, int -> int, '_weak1) rcons) rcons, int) lam =
App (Shift (Var Suc), Var Zero)
-val _2 : ((zero, int, (suc, int -> int, '_a) rcons) rcons, int) lam =
+val _2 : ((zero, int, (suc, int -> int, '_weak2) rcons) rcons, int) lam =
App (Shift (Var Suc), App (Shift (Var Suc), Var Zero))
-val _3 : ((zero, int, (suc, int -> int, '_a) rcons) rcons, int) lam =
+val _3 : ((zero, int, (suc, int -> int, '_weak3) rcons) rcons, int) lam =
App (Shift (Var Suc),
App (Shift (Var Suc), App (Shift (Var Suc), Var Zero)))
val add :
Abs (<poly>,
App (App (Shift (Shift (Shift (Var Add))), Var <poly>), Var <poly>))
val ex3 :
- ((zero, int, (suc, int -> int, (add, int -> int -> int, '_a) rcons) rcons)
+ ((zero, int,
+ (suc, int -> int, (add, int -> int -> int, '_weak4) rcons) rcons)
rcons, int)
lam =
App
--- /dev/null
+type nonrec t = A : t;;
+[%%expect{|
+Line _, characters 16-21:
+Error: GADT case syntax cannot be used in a 'nonrec' block.
+|}]
+
--- /dev/null
+type _ t = I : int t;;
+let f (type a) (x : a t) (y : int) =
+ match x, y with
+ | I, (_:a) -> ()
+;;
+[%%expect{|
+type _ t = I : int t
+val f : 'a t -> int -> unit = <fun>
+|}]
+
+type ('a, 'b) eq = Refl : ('a, 'a) eq;;
+let ok (type a b) (x : (a, b) eq) =
+ match x, [] with
+ | Refl, [(_ : a) | (_ : b)] -> []
+;;
+[%%expect{|
+type ('a, 'b) eq = Refl : ('a, 'a) eq
+Line _, characters 2-54:
+Warning 8: this pattern-matching is not exhaustive.
+Here is an example of a case that is not matched:
+(Refl, _::_::_)
+Line _, characters 22-23:
+Warning 12: this sub-pattern is unused.
+val ok : ('a, 'b) eq -> 'c list = <fun>
+|}]
+let fails (type a b) (x : (a, b) eq) =
+ match x, [] with
+ | Refl, [(_ : a) | (_ : b)] -> []
+ | Refl, [(_ : b) | (_ : a)] -> []
+;;
+[%%expect{|
+Line _, characters 2-90:
+Warning 8: this pattern-matching is not exhaustive.
+Here is an example of a case that is not matched:
+(Refl, _::_::_)
+Line _, characters 22-23:
+Warning 12: this sub-pattern is unused.
+Line _, characters 4-29:
+Warning 11: this match case is unused.
+val fails : ('a, 'b) eq -> 'c list = <fun>
+|}]
+
+(* branches must be unified! *)
+let x = match [] with ["1"] -> 1 | [1.0] -> 2 | [1] -> 3 | _ -> 4;;
+[%%expect{|
+Line _, characters 35-40:
+Error: This pattern matches values of type float list
+ but a pattern was expected which matches values of type string list
+ Type float is not compatible with type string
+|}]
[%%expect{|
val s : 'a succ succ succ term = Fork (Var FZ, Fork (Var (FS (FS FZ)), Leaf))
val t : 'a succ succ term = Fork (Var (FS FZ), Var (FS FZ))
-val d : '_a succ succ succ ealist =
+val d : '_weak1 succ succ succ ealist =
EAlist (Asnoc (Asnoc (Anil, Fork (Var FZ, Leaf), FZ), Var FZ, FZ))
-val s' : '_a succ succ succ term =
+val s' : '_weak1 succ succ succ term =
Fork (Fork (Var FZ, Leaf), Fork (Var FZ, Leaf))
-val t' : '_a succ succ succ term =
+val t' : '_weak1 succ succ succ term =
Fork (Fork (Var FZ, Leaf), Fork (Var FZ, Leaf))
|}];;
val is_empty : 'a t -> bool
val mem : key -> 'a t -> bool
val add : key -> 'a -> 'a t -> 'a t
+ val update : key -> ('a option -> 'a option) -> 'a t -> 'a t
val singleton : key -> 'a -> 'a t
val remove : key -> 'a t -> 'a t
val merge :
val is_empty : 'a t -> bool
val mem : key -> 'a t -> bool
val add : key -> 'a -> 'a t -> 'a t
+ val update : key -> ('a option -> 'a option) -> 'a t -> 'a t
val singleton : key -> 'a -> 'a t
val remove : key -> 'a t -> 'a t
val merge :
#* *
#**************************************************************************
+all: pr6939.ml
+ $(MAKE) default
+
BASEDIR=../..
include $(BASEDIR)/makefiles/Makefile.expect
include $(BASEDIR)/makefiles/Makefile.common
+
+GENERATED_SOURCES = pr6939.ml *.flat-float
+
+ifeq "$(FLAT_FLOAT_ARRAY)" "true"
+suffix = -flat
+else
+suffix = -noflat
+endif
+
+pr6939.ml: pr6939.ml$(suffix) $(FLAT_FLOAT_ARRAY).flat-float
+ cp $< $@
+
+%.flat-float:
+ @rm -f $(GENERATED_SOURCES)
+ @touch $@
val revapply : 'a -> ('a -> 'b) -> 'b = <fun>
val f : 'a -> [< `Foo ] -> 'a = <fun>
|}];;
+
+(* PR#6124 *)
+let f : ([`A | `B ] as 'a) -> [> 'a] -> unit = fun x (y : [> 'a]) -> ();;
+let f (x : [`A | `B] as 'a) (y : [> 'a]) = ();;
+[%%expect{|
+Line _, characters 61-63:
+Error: The type 'a does not expand to a polymorphic variant type
+Hint: Did you mean `a?
+|}]
+
+(* PR#5927 *)
+type 'a foo = 'a constraint 'a = [< `Tag of & int];;
+[%%expect{|
+type 'a foo = 'a constraint 'a = [< `Tag of & int ]
+|}]
+++ /dev/null
-let rec x = [| x |]; 1.;;
-[%%expect{|
-Line _, characters 12-19:
-Warning 10: this expression should have type unit.
-Line _, characters 12-23:
-Error: This kind of expression is not allowed as right-hand side of `let rec'
-|}];;
-
-let rec x = let u = [|y|] in 10. and y = 1.;;
-[%%expect{|
-Line _, characters 16-17:
-Warning 26: unused variable u.
-Line _, characters 12-32:
-Error: This kind of expression is not allowed as right-hand side of `let rec'
-|}];;
--- /dev/null
+let rec x = [| x |]; 1.;;
+[%%expect{|
+Line _, characters 12-19:
+Warning 10: this expression should have type unit.
+Line _, characters 12-23:
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+|}];;
+
+let rec x = let u = [|y|] in 10. and y = 1.;;
+[%%expect{|
+Line _, characters 12-32:
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+|}];;
--- /dev/null
+let rec x = [| x |]; 1.;;
+[%%expect{|
+Line _, characters 12-19:
+Warning 10: this expression should have type unit.
+val x : float = 1.
+|}];;
+
+let rec x = let u = [|y|] in 10. and y = 1.;;
+[%%expect{|
+Line _, characters 16-17:
+Warning 26: unused variable u.
+val x : float = 10.
+val y : float = 1.
+|}];;
type t = [ 'A_name | `Hi ];;
[%%expect{|
Line _, characters 11-18:
-Error: The type 'A_name is not a polymorphic variant type
+Error: The type 'A_name does not expand to a polymorphic variant type
Hint: Did you mean `A_name?
|}];;
[%%expect{|
val f : 'Id_arg -> 'Id_arg = <fun>
|}];;
+
+(* GPR#1204, GPR#1329 *)
+type 'a id = 'a
+let f (x : [< [`Foo] id]) = ();;
+[%%expect{|
+type 'a id = 'a
+val f : [< [ `Foo ] id ] -> unit = <fun>
+|}];;
+
+module M = struct module N = struct type t = [`A] end end;;
+let f x = (x :> M.N.t);;
+[%%expect{|
+module M : sig module N : sig type t = [ `A ] end end
+val f : [< M.N.t ] -> M.N.t = <fun>
+|}]
+module G = M.N;;
+let f x = (x :> G.t);;
+[%%expect{|
+module G = M.N
+val f : [< G.t ] -> G.t = <fun>
+|}]
--- /dev/null
+(** Check that rebinding module preserves private type aliases *)
+
+module String_id : sig
+ module type S = sig
+ type t = private string
+ val of_string : string -> t
+ end
+
+ include S
+
+ module Make (M : sig val module_name : string end) : S
+end = struct
+ module type S = sig
+ type t = private string
+ val of_string : string -> t
+ end
+
+ module String = struct
+ type t = string
+ end
+
+ module Make (M : sig val module_name : string end) = struct
+ include String
+
+ let of_string s =
+ Printf.printf "converting %s\n" M.module_name;
+ s
+ end
+
+ include Make (struct let module_name = "String_id" end)
+end
+
+let () =
+ let foo = String_id.of_string "foo" in
+ Printf.printf "foo = %s\n" (foo :> string)
+
+let () =
+ let module Bar = String_id.Make(struct let module_name="Bar" end) in
+ let bar = Bar.of_string "bar" in
+ Printf.printf "bar = %s\n" (bar :> string)
+
+let () =
+ let module String_id2 = String_id in
+ let module Baz = String_id2.Make(struct let module_name="Baz" end) in
+ let baz = Baz.of_string "baz" in
+ Printf.printf "baz = %s\n" (baz :> string)
+
--- /dev/null
+module type S = sig type 'a t end
+module type Sp = sig type 'a t = private 'a array end
+
+module Id (S : S) = S
+
+module M : Sp = struct
+ include Id (struct type 'a t = 'a array end)
+end
--- /dev/null
+module Gen_spec = struct type 't extra = unit end
+
+module type S = sig
+ module Spec : sig type 't extra = unit end
+
+ type t
+ val make : unit -> t Spec.extra
+end (* S *)
+
+module Make () : S with module Spec := Gen_spec = struct
+ type t = int
+ let make () = ()
+end (* Make *)
+
+let () =
+ let module M = Make () in
+ M.make ()
+ (* (M.make () : unit) *)
--- /dev/null
+(**************************************************************************)
+(* *)
+(* Crude slicer for preprocessing reachability verification tasks *)
+(* *)
+(* Copyright (C) 2016-2017 Mikhail Mandrykin, ISP RAS *)
+(* *)
+(**************************************************************************)
+
+module type Analysis = sig
+ type t
+ type 'a maybe_region =
+ [< `Location of t
+ | `Value of t
+ | `None ] as 'a
+ val of_var : ?f:string -> string -> [ `Location of _ | `Value of _ | `None ] maybe_region
+end
+
+module Make (Analysis : Analysis) = struct
+ include Analysis
+ let of_var = of_var ~f:""
+end
+
--- /dev/null
+module type Param1 = sig
+ type 'a r = [< `A of int ] as 'a
+ val f : ?a:string -> string -> [ `A of _ ] r
+end
+
+module Make1 (M : Param1) = struct
+ include M
+ let f = f ~a:""
+end
+
+module type Param2 = sig
+ type t
+ type 'a r = [< `A of t ] as 'a
+ val f : ?a:string -> string -> [ `A of _ ] r
+end
+
+module Make2 (M : Param2) = struct
+ include M
+ let f = f ~a:""
+end
+
#**************************************************************************
BASEDIR=../..
-GENERATED= a.ml b.ml c.ml
+GENERATED= a.ml b.ml c.ml d.mli e.ml f.ml g.ml test
-default: pr7325
+default: pr7325 pr6372 pr7563
pr7325:
- @printf " ... testing pr7325:"
+ @printf " ... testing 'pr7325':"
@echo "type _ t = T" > a.ml
@echo "type 'a t = 'a A.t" > b.ml
@echo 'external f : unit -> unit B.t = "%identity"' > c.ml
@$(OCAMLC) -c a.ml b.ml && rm a.cmi && $(OCAMLC) -c c.ml \
&& echo " => passed" || echo " => failed"
+pr6372:
+ @printf " ... testing 'pr6372':"
+ @echo "type _ t = C: { f: ('a -> [<\`X]) t } -> [<\`X] t" > d.mli
+ @echo "open D;; let f (C {f}) = ()" > e.ml
+ @$(OCAMLC) -c d.mli e.ml \
+ && echo " => passed" || echo " => failed"
+
+pr7563:
+ @printf " ... testing 'pr7563':"
+ @echo "module A = struct end" > f.ml
+ @echo "module Alias = A" >> f.ml
+ @echo "exception Alias" >> f.ml
+ @echo "let alias = Alias" >> f.ml
+ @echo "exit (if F.Alias = F.alias then 0 else 1)" > g.ml
+ @$(OCAMLC) f.ml g.ml -o test && $(OCAMLRUN) ./test \
+ && echo " => passed" || echo " => failed"
+
clean: defaultclean
@rm -f $(GENERATED)
constraint 'b = 'a * < x : 'b > * 'c * 'd
method f : 'a -> 'b -> unit
end
-# val x : '_a list ref = {contents = []}
+# val x : '_weak1 list ref = {contents = []}
# Characters 0-50:
class ['a] c () = object
method f = (x : 'a)
end..
Error: The type of this class,
class ['a] c :
- unit -> object constraint 'a = '_b list ref method f : 'a end,
+ unit -> object constraint 'a = '_weak1 list ref method f : 'a end,
contains type variables that cannot be generalized
# Characters 21-53:
type 'a c = <f : 'a c; g : 'a d>
Type bool is not a subtype of int
# - : < > -> < > = <fun>
# - : < .. > -> < > = <fun>
-# val x : '_a list ref = {contents = []}
+# val x : '_weak2 list ref = {contents = []}
# module F : functor (X : sig end) -> sig type t = int end
# - : < m : int > list ref = {contents = []}
# type 'a t
constraint 'b = 'a * < x : 'b > * 'c * 'd
method f : 'a -> 'b -> unit
end
-# val x : '_a list ref = {contents = []}
+# val x : '_weak1 list ref = {contents = []}
# Characters 0-50:
class ['a] c () = object
method f = (x : 'a)
end..
Error: The type of this class,
class ['a] c :
- unit -> object constraint 'a = '_b list ref method f : 'a end,
+ unit -> object constraint 'a = '_weak1 list ref method f : 'a end,
contains type variables that cannot be generalized
# Characters 21-53:
type 'a c = <f : 'a c; g : 'a d>
Type bool is not a subtype of int
# - : < > -> < > = <fun>
# - : < .. > -> < > = <fun>
-# val x : '_a list ref = {contents = []}
+# val x : '_weak2 list ref = {contents = []}
# module F : functor (X : sig end) -> sig type t = int end
# - : < m : int > list ref = {contents = []}
# type 'a t
--- /dev/null
+module M = struct
+ type t = int
+ let x = 42
+end
+;;
+class c =
+ let open M in
+ object
+ method f : t = x
+ end
+;;
+class type ct =
+ let open M in
+ object
+ method f : t
+ end
+;;
--- /dev/null
+
+# module M : sig type t = int val x : int end
+# class c : object method f : M.t end
+# class type ct = object method f : M.t end
+#
--- /dev/null
+# Check ocamlc -i
+
+SOURCES = pr7620_bad.ml
+
+all:
+ @printf " ... testing '$(SOURCES)'"
+ @$(OCAMLC) -i $(SOURCES) 2> /dev/null \
+ && echo " => failed" || echo " => passed"
+
+clean: defaultclean
+ @rm -f *~
+
+BASEDIR=../..
+include $(BASEDIR)/makefiles/Makefile.common
+
--- /dev/null
+let t =
+ (function `A | `B -> () : 'a) (`A : [`A]);
+ (failwith "dummy" : 'a) (* to know how 'a is unified *)
class ['c] clss : object method mthod : 'c -> 't t -> ('c, 't) pvariant end
val f2 : 'a -> 'b -> 'c t -> 'c t = <fun>
val f1 :
- < mthod : 't. 'a -> 't t -> [< ('a, 't) pvariant ]; .. > ->
+ < mthod : 't. 'a -> 't t -> [< `V of 'a * 't t ]; .. > ->
'a -> 'b t -> 'b t = <fun>
|}]
[%%expect{|
type (+'a, -'b) foo = private int
val f : int -> ('a, 'a) foo = <fun>
-val x : ('_a, '_a) foo = 3
+val x : ('_weak1, '_weak1) foo = 3
+|}]
+
+
+(* PR#7344*)
+let rec f : unit -> < m: 'a. 'a -> 'a> = fun () ->
+ let x = f () in
+ ignore (x#m 1);
+ ignore (x#m "hello");
+ assert false;;
+[%%expect{|
+val f : unit -> < m : 'a. 'a -> 'a > = <fun>
|}]
(* PR#7395 *)
type 'a t = u
val c : (u -> u) -> < apply : 'a. 'a t -> 'a t > = <fun>
|}]
+
+(* PR#7496 *)
+let f (x : < m: 'a. ([< `Foo of int & float] as 'a) -> unit>)
+ : < m: 'a. ([< `Foo of int & float] as 'a) -> unit> = x;;
+
+type t = { x : 'a. ([< `Foo of int & float ] as 'a) -> unit };;
+let f t = { x = t.x };;
+[%%expect{|
+val f :
+ < m : 'a. ([< `Foo of int & float ] as 'a) -> unit > ->
+ < m : 'b. ([< `Foo of int & float ] as 'b) -> unit > = <fun>
+type t = { x : 'a. ([< `Foo of int & float ] as 'a) -> unit; }
+val f : t -> t = <fun>
+|}]
+
+type t = <m:int>
+type g = <n:string; t>
+type h = <x:string; y:int; g>
+[%%expect{|
+type t = < m : int >
+type g = < m : int; n : string >
+type h = < m : int; n : string; x : string; y : int >
+|}]
+
+type t = <g>
+and g = <a:t>
+[%%expect{|
+Line _, characters 10-11:
+Error: The type constructor g
+is not yet completely defined
+|}]
+
+type t = int
+type g = <t>
+[%%expect{|
+type t = int
+Line _, characters 10-11:
+Error: The type int is not an object type
+|}]
+
+type t = <a:int>
+type g = <t; t; t;>
+[%%expect{|
+type t = < a : int >
+type g = < a : int >
+|}]
+
+type c = <a:int; d:string>
+let s:c = object method a=1; method d="123" end
+[%%expect{|
+type c = < a : int; d : string >
+val s : c = <obj>
+|}]
+
+type 'a t = < m: 'a >
+type s = < int t >
+module M = struct type t = < m: int > end
+type u = < M.t >
+type r = < a : int; < b : int > >
+type e = < >
+type r1 = < a : int; e >
+type r2 = < a : int; < < < > > > >
+[%%expect{|
+type 'a t = < m : 'a >
+type s = < m : int >
+module M : sig type t = < m : int > end
+type u = < m : int >
+type r = < a : int; b : int >
+type e = < >
+type r1 = < a : int >
+type r2 = < a : int >
+|}]
+
+type gg = <a:int->float; a:int>
+[%%expect{|
+Line _, characters 27-30:
+Error: Method 'a' has type int, which should be int -> float
+|}]
+
+type t = <a:int; b:string>
+type g = <b:float; t;>
+[%%expect{|
+type t = < a : int; b : string >
+Line _, characters 19-20:
+Error: Method 'b' has type string, which should be float
+|}]
+
+module A = struct
+ class type ['a] t1 = object method f : 'a end
+end
+type t = < int A.t1 >
+[%%expect{|
+module A : sig class type ['a] t1 = object method f : 'a end end
+type t = < f : int >
+|}]
+
+type t = < int #A.t1 >
+[%%expect{|
+Line _, characters 11-20:
+Error: Illegal open object type
+|}]
+
+let g = fun (y : ('a * 'b)) x -> (x : < <m: 'a> ; <m: 'b> >)
+[%%expect{|
+val g : 'a * 'a -> < m : 'a > -> < m : 'a > = <fun>
+|}]
+
+type 'a t = <m: 'a ; m: int>
+[%%expect{|
+type 'a t = < m : 'a > constraint 'a = int
+|}]
+
+(* GPR#1142 *)
+module M () = struct
+ let f : 'a -> 'a = assert false
+ let g : 'a -> 'a = raise Not_found
+end
+
+[%%expect{|
+module M : functor () -> sig val f : 'a -> 'a val g : 'a -> 'a end
+|}]
BASEDIR=../..
include $(BASEDIR)/makefiles/Makefile.common
-
-# The second test (`A.y`) is unnecessary, indeed cannot be compiled, under -safe-string
-ifeq ($(SAFE_STRING),true)
-ADD_COMPFLAGS=-pp "sed -e '\$$d'"
-endif
type _ t =
X of string
| Y : bytes t
-
-(* It is important that the line below is the last line of the file (see Makefile) *)
-let y : string t = Y
include $(BASEDIR)/makefiles/Makefile.toplevel
include $(BASEDIR)/makefiles/Makefile.common
TOPFLAGS = -short-paths
+
+default: gpr1223_foo.cmi gpr1223_bar.cmi
+
+gpr1223_bar.cmi: gpr1223_foo.cmi
--- /dev/null
+
+let y = Gpr1223_bar.N.O.T;;
+
+let x = Gpr1223_bar.M.T;;
--- /dev/null
+
+# val y : Gpr1223_bar.N.O.t = Gpr1223_bar.N.O.T
+# val x : Gpr1223_bar.M.t = Gpr1223_bar.M.T
+#
--- /dev/null
+
+module M : Gpr1223_foo.S
+
+module N : sig
+
+ module O : sig
+
+ type t = T
+
+ end
+
+end
--- /dev/null
+
+module type S = sig
+
+ type t = T
+
+end
--- /dev/null
+(** Test that short-path printtyp does not fail on packed module.
+
+ Packed modules does not respect the arity of type constructor, which can break
+ the path normalization within the short-path code path.
+*)
+module type S = sig type t end;;
+module N = struct type 'a t = 'a end;;
+let f (module M:S with type t = unit) = ();;
+let () = f (module N);;
--- /dev/null
+
+# * * * * module type S = sig type t end
+# module N : sig type 'a t = 'a end
+# val f : (module S with type t = unit) -> unit = <fun>
+# Characters 19-20:
+ let () = f (module N);;
+ ^
+Error: Signature mismatch:
+ Modules do not match:
+ sig type 'a t = 'a end
+ is not included in
+ sig type t = N.t end
+ Type declarations do not match:
+ type 'a t = 'a
+ is not included in
+ type t = N.t
+ They have different arities.
+#
val is_empty : 'a t -> bool
val mem : key -> 'a t -> bool
val add : key -> 'a -> 'a t -> 'a t
+ val update : key -> ('a option -> 'a option) -> 'a t -> 'a t
val singleton : key -> 'a -> 'a t
val remove : key -> 'a t -> 'a t
val merge :
#**************************************************************************
BASEDIR=../..
-include $(BASEDIR)/makefiles/Makefile.toplevel
+include $(BASEDIR)/makefiles/Makefile.expect
include $(BASEDIR)/makefiles/Makefile.common
module type Printable = sig
type t
val print : Format.formatter -> t -> unit
-end;;
+end
+[%%expect {|
+module type Printable =
+ sig type t val print : Format.formatter -> t -> unit end
+|}]
module type Comparable = sig
type t
val compare : t -> t -> int
-end;;
+end
+[%%expect {|
+module type Comparable = sig type t val compare : t -> t -> int end
+|}]
module type PrintableComparable = sig
include Printable
include Comparable with type t = t
-end;; (* Fails *)
+end
+[%%expect {|
+Line _, characters 2-36:
+Error: Multiple definition of the type name t.
+ Names must be unique in a given structure or signature.
+|}]
+
+module type Sunderscore = sig
+ type (_, _) t
+end with type (_, 'a) t = int * 'a
+[%%expect {|
+module type Sunderscore = sig type (_, 'a) t = int * 'a end
+|}]
+
+
+(* Valid substitutions in a recursive module may fail due to the ordering of
+ the modules. *)
+
+module type S0 = sig
+ module rec M : sig type t = M2.t end
+ and M2 : sig type t = int end
+end with type M.t = int
+[%%expect {|
+Line _, characters 17-115:
+Error: In this `with' constraint, the new definition of M.t
+ does not match its original definition in the constrained signature:
+ Type declarations do not match:
+ type t = int
+ is not included in
+ type t = M2.t
+|}]
+
+
module type PrintableComparable = sig
type t
include Printable with type t := t
include Comparable with type t := t
-end;;
+end
+[%%expect {|
+module type PrintableComparable =
+ sig
+ type t
+ val print : Format.formatter -> t -> unit
+ val compare : t -> t -> int
+ end
+|}]
module type PrintableComparable = sig
include Printable
include Comparable with type t := t
-end;;
-module type ComparableInt = Comparable with type t := int;;
-module type S = sig type t val f : t -> t end;;
-module type S' = S with type t := int;;
+end
+[%%expect {|
+module type PrintableComparable =
+ sig
+ type t
+ val print : Format.formatter -> t -> unit
+ val compare : t -> t -> int
+ end
+|}]
+module type ComparableInt = Comparable with type t := int
+[%%expect {|
+module type ComparableInt = sig val compare : int -> int -> int end
+|}]
+module type S = sig type t val f : t -> t end
+[%%expect {|
+module type S = sig type t val f : t -> t end
+|}]
+module type S' = S with type t := int
+[%%expect {|
+module type S' = sig val f : int -> int end
+|}]
+
+module type S = sig type 'a t val map : ('a -> 'b) -> 'a t -> 'b t end
+module type S1 = S with type 'a t := 'a list
+[%%expect {|
+module type S = sig type 'a t val map : ('a -> 'b) -> 'a t -> 'b t end
+module type S1 = sig val map : ('a -> 'b) -> 'a list -> 'b list end
+|}]
+module type S2 = S with type 'a t := (string * 'a) list
+[%%expect {|
+module type S2 =
+ sig val map : ('a -> 'b) -> (string * 'a) list -> (string * 'b) list end
+|}]
+module type S3 = S with type _ t := int
+[%%expect {|
+module type S3 = sig val map : ('a -> 'b) -> int -> int end
+|}]
+
-module type S = sig type 'a t val map : ('a -> 'b) -> 'a t -> 'b t end;;
-module type S1 = S with type 'a t := 'a list;;
-module type S2 = sig
- type 'a dict = (string * 'a) list
- include S with type 'a t := 'a dict
-end;;
+module type S =
+ sig module T : sig type exp type arg end val f : T.exp -> T.arg end
+module M = struct type exp = string type arg = int end
+module type S' = S with module T := M
+[%%expect {|
+module type S =
+ sig module T : sig type exp type arg end val f : T.exp -> T.arg end
+module M : sig type exp = string type arg = int end
+module type S' = sig val f : M.exp -> M.arg end
+|}]
+
+
+module type S = sig type 'a t end with type 'a t := unit
+[%%expect {|
+module type S = sig end
+|}]
+module type S = sig
+ type t = [ `Foo ]
+ type s = private [< t ]
+end with type t := [ `Foo ]
+[%%expect {|
+module type S = sig type s = private [< `Foo ] end
+|}]
+module type S = sig
+ type t = ..
+ type t += A
+end with type t := exn
+[%%expect {|
+module type S = sig type exn += A end
+|}]
+
+(* We allow type constraints when replacing a path by a path. *)
+type 'a t constraint 'a = 'b list
+module type S = sig
+ type 'a t2 constraint 'a = 'b list
+ type 'a mylist = 'a list
+ val x : int mylist t2
+end with type 'a t2 := 'a t
+[%%expect {|
+type 'a t constraint 'a = 'b list
+module type S = sig type 'a mylist = 'a list val x : int mylist t end
+|}]
+
+(* but not when replacing a path by a type expression *)
+type 'a t constraint 'a = 'b list
+module type S = sig
+ type 'a t2 constraint 'a = 'b list
+ type 'a mylist = 'a list
+ val x : int mylist t2
+end with type 'a t2 := 'a t * bool
+[%%expect {|
+type 'a t constraint 'a = 'b list
+Line _, characters 16-142:
+Error: Destructive substitutions are not supported for constrained
+ types (other than when replacing a type constructor with
+ a type constructor with the same arguments).
+|}]
+
+(* Issue where the typer expands an alias, which breaks the typing of the rest
+ of the signature, but no error is given to the user. *)
+module type S = sig
+ module M1 : sig type t = int end
+ module M2 = M1
+ module M3 : sig module M = M2 end
+ module F(X : sig module M = M1 end) : sig type t end
+ type t = F(M3).t
+end with type M2.t = int
+[%%expect {|
module type S =
- sig module T : sig type exp type arg end val f : T.exp -> T.arg end;;
-module M = struct type exp = string type arg = int end;;
-module type S' = S with module T := M;;
+ sig
+ module M1 : sig type t = int end
+ module M2 : sig type t = int end
+ module M3 : sig module M = M2 end
+ module F : functor (X : sig module M = M1 end) -> sig type t end
+ type t = F(M3).t
+ end
+|}]
+
+(* Checking that the uses of M.t are rewritten regardless of how they
+ are named, but we don't rewrite other types by the same name. *)
+module type S = sig
+ module M : sig type t val x : t end
+ val y : M.t
+ module A : sig module M : sig type t val z : t -> M.t end end
+end with type M.t := float
+[%%expect {|
+module type S =
+ sig
+ module M : sig val x : float end
+ val y : float
+ module A : sig module M : sig type t val z : t -> float end end
+ end
+|}]
+
+(* Regression test: at some point, expanding S1 twice in the same
+ "with type" would result in a signature with duplicate ids, which
+ would confuse the rewriting (we would end with (M2.x : int)) and
+ only then get refreshened. *)
+module type S = sig
+ module type S1 = sig type t type a val x : t end
+ module M1 : S1
+ type a = M1.t
+ module M2 : S1
+ type b = M2.t
+end with type M1.a = int and type M2.a = int and type M1.t := int;;
+[%%expect {|
+module type S =
+ sig
+ module type S1 = sig type t type a val x : t end
+ module M1 : sig type a = int val x : int end
+ type a = int
+ module M2 : sig type t type a = int val x : t end
+ type b = M2.t
+ end
+|}]
+
+(* And now some corner cases with aliases: *)
+
+module type S = sig
+ module M : sig type t end
+ module A = M
+end with type M.t := float
+[%%expect {|
+Line _, characters 16-89:
+Error: This `with' constraint on M.t changes M, which is aliased
+ in the constrained signature (as A).
+|}]
+
+(* And more corner cases with applicative functors: *)
+
+module type S = sig
+ module M : sig type t type u end
+ module F(X : sig type t end) : sig type t end
+ type t = F(M).t
+end
+[%%expect {|
+module type S =
+ sig
+ module M : sig type t type u end
+ module F : functor (X : sig type t end) -> sig type t end
+ type t = F(M).t
+ end
+|}]
+
+(* This particular substitution cannot be made to work *)
+module type S2 = S with type M.t := float
+[%%expect {|
+Line _, characters 17-41:
+Error: This `with' constraint on M.t makes the applicative functor
+ type F(M).t ill-typed in the constrained signature:
+ Modules do not match:
+ sig type u = M.u end
+ is not included in
+ sig type t end
+ The type `t' is required but not provided
+|}]
+
+(* However if the applicative functor doesn't care about the type
+ we're removing, the typer accepts the removal. *)
+module type S2 = S with type M.u := float
+[%%expect {|
+module type S2 =
+ sig
+ module M : sig type t end
+ module F : functor (X : sig type t end) -> sig type t end
+ type t = F(M).t
+ end
+|}]
+
+(* In the presence of recursive modules, the use of a module can come before its
+ definition (in the typed tree). *)
+
+module Id(X : sig type t end) = struct type t = X.t end
+module type S3 = sig
+ module rec M : sig type t = A of Id(M2).t end
+ and M2 : sig type t end
+end with type M2.t := int
+[%%expect {|
+module Id : functor (X : sig type t end) -> sig type t = X.t end
+Line _, characters 17-120:
+Error: This `with' constraint on M2.t makes the applicative functor
+ type Id(M2).t ill-typed in the constrained signature:
+ Modules do not match: sig end is not included in sig type t end
+ The type `t' is required but not provided
+|}]
+
+
+(* Deep destructive module substitution: *)
+
+module A = struct module P = struct type t let x = 1 end end
+module type S = sig
+ module M : sig
+ module N : sig
+ module P : sig
+ type t
+ end
+ end
+ end
+ type t = M.N.P.t
+end with module M.N := A
+[%%expect {|
+module A : sig module P : sig type t val x : int end end
+module type S = sig module M : sig end type t = A.P.t end
+|}]
+(* Same as for types, not all substitutions are accepted *)
-module type S = sig type 'a t end with type 'a t := unit;; (* Fails *)
+module type S = sig
+ module M : sig
+ module N : sig
+ module P : sig
+ type t
+ end
+ end
+ end
+ module Alias = M
+end with module M.N := A
+[%%expect {|
+Line _, characters 16-159:
+Error: This `with' constraint on M.N changes M, which is aliased
+ in the constrained signature (as Alias).
+|}]
+++ /dev/null
-
-# module type Printable =
- sig type t val print : Format.formatter -> t -> unit end
-# module type Comparable = sig type t val compare : t -> t -> int end
-# Characters 60-94:
- include Comparable with type t = t
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Error: Multiple definition of the type name t.
- Names must be unique in a given structure or signature.
-# module type PrintableComparable =
- sig
- type t
- val print : Format.formatter -> t -> unit
- val compare : t -> t -> int
- end
-# module type PrintableComparable =
- sig
- type t
- val print : Format.formatter -> t -> unit
- val compare : t -> t -> int
- end
-# module type ComparableInt = sig val compare : int -> int -> int end
-# module type S = sig type t val f : t -> t end
-# module type S' = sig val f : int -> int end
-# module type S = sig type 'a t val map : ('a -> 'b) -> 'a t -> 'b t end
-# module type S1 = sig val map : ('a -> 'b) -> 'a list -> 'b list end
-# module type S2 =
- sig
- type 'a dict = (string * 'a) list
- val map : ('a -> 'b) -> 'a dict -> 'b dict
- end
-# module type S =
- sig module T : sig type exp type arg end val f : T.exp -> T.arg end
-# module M : sig type exp = string type arg = int end
-# module type S' = sig val f : M.exp -> M.arg end
-# Characters 41-58:
- module type S = sig type 'a t end with type 'a t := unit;; (* Fails *)
- ^^^^^^^^^^^^^^^^^
-Error: Only type constructors with identical parameters can be substituted.
-#
let i = int_inj 3 in
let s = string_inj "abc" in
- Printf.printf "%b\n%!" (int_proj i = None);
- Printf.printf "%b\n%!" (int_proj s = None);
- Printf.printf "%b\n%!" (string_proj i = None);
- Printf.printf "%b\n%!" (string_proj s = None)
+ Printf.printf "%B\n%!" (int_proj i = None);
+ Printf.printf "%B\n%!" (int_proj s = None);
+ Printf.printf "%B\n%!" (string_proj i = None);
+ Printf.printf "%B\n%!" (string_proj s = None)
;;
let sort_uniq (type s) cmp l =
+newdefault: test.ml.reference
+ @$(MAKE) default
+
BASEDIR=../..
include $(BASEDIR)/makefiles/Makefile.toplevel
include $(BASEDIR)/makefiles/Makefile.common
+
+GENERATED_SOURCES = test.ml.reference *.flat-float
+
+ifeq "$(FLAT_FLOAT_ARRAY)" "true"
+suffix = -flat
+else
+suffix = -noflat
+endif
+
+test.ml.reference: test.ml.reference$(suffix) $(FLAT_FLOAT_ARRAY).flat-float
+ @cp $< $@
+
+%.flat-float:
+ @rm -f $(GENERATED_SOURCES)
+ @touch $@
type _ s = S : 'a t -> _ s [@@unboxed]
and _ t = T : 'a -> 'a s t
;;
+
+
+(* Another corner case *)
+type 'a s
+type ('a, 'p) t = private 'a s
+type 'a packed = T : ('a, _) t -> 'a packed [@@unboxed]
+;;
+++ /dev/null
-
-# type t1 = A of string [@@unboxed]
-# - : bool = true
-# type t2 = { f : string; } [@@unboxed]
-# - : bool = true
-# type t3 = B of { g : string; } [@@unboxed]
-# - : bool = true
-# Characters 29-58:
- type t4 = C [@@ocaml.unboxed];; (* no argument *)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Error: This type cannot be unboxed because its constructor has no argument.
-# Characters 0-45:
- type t5 = D of int * string [@@ocaml.unboxed];; (* more than one argument *)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Error: This type cannot be unboxed because
- its constructor has more than one argument.
-# Characters 0-33:
- type t5 = E | F [@@ocaml.unboxed];; (* more than one constructor *)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Error: This type cannot be unboxed because it has more than one constructor.
-# Characters 0-40:
- type t6 = G of int | H [@@ocaml.unboxed];;
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Error: This type cannot be unboxed because it has more than one constructor.
-# Characters 0-51:
- type t7 = I of string | J of bool [@@ocaml.unboxed];;
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Error: This type cannot be unboxed because it has more than one constructor.
-# Characters 1-50:
- type t8 = { h : bool; i : int } [@@ocaml.unboxed];; (* more than one field *)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Error: This type cannot be unboxed because it has more than one field.
-# Characters 0-56:
- type t9 = K of { j : string; l : int } [@@ocaml.unboxed];;
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Error: This type cannot be unboxed because
- its constructor has more than one argument.
-# type t10 = A of t10 [@@unboxed]
-# Characters 12-15:
- let rec x = A x;;
- ^^^
-Error: This kind of expression is not allowed as right-hand side of `let rec'
-# Characters 121-172:
- ......struct
- type t = A of string [@@ocaml.unboxed]
- end..
-Error: Signature mismatch:
- Modules do not match:
- sig type t = A of string [@@unboxed] end
- is not included in
- sig type t = A of string end
- Type declarations do not match:
- type t = A of string [@@unboxed]
- is not included in
- type t = A of string
- Their internal representations differ:
- the first declaration uses unboxed representation.
-# Characters 63-96:
- ......struct
- type t = A of string
- end..
-Error: Signature mismatch:
- Modules do not match:
- sig type t = A of string end
- is not included in
- sig type t = A of string [@@unboxed] end
- Type declarations do not match:
- type t = A of string
- is not included in
- type t = A of string [@@unboxed]
- Their internal representations differ:
- the second declaration uses unboxed representation.
-# Characters 48-102:
- ......struct
- type t = { f : string } [@@ocaml.unboxed]
- end..
-Error: Signature mismatch:
- Modules do not match:
- sig type t = { f : string; } [@@unboxed] end
- is not included in
- sig type t = { f : string; } end
- Type declarations do not match:
- type t = { f : string; } [@@unboxed]
- is not included in
- type t = { f : string; }
- Their internal representations differ:
- the first declaration uses unboxed representation.
-# Characters 66-102:
- ......struct
- type t = { f : string }
- end..
-Error: Signature mismatch:
- Modules do not match:
- sig type t = { f : string; } end
- is not included in
- sig type t = { f : string; } [@@unboxed] end
- Type declarations do not match:
- type t = { f : string; }
- is not included in
- type t = { f : string; } [@@unboxed]
- Their internal representations differ:
- the second declaration uses unboxed representation.
-# Characters 53-112:
- ......struct
- type t = A of { f : string } [@@ocaml.unboxed]
- end..
-Error: Signature mismatch:
- Modules do not match:
- sig type t = A of { f : string; } [@@unboxed] end
- is not included in
- sig type t = A of { f : string; } end
- Type declarations do not match:
- type t = A of { f : string; } [@@unboxed]
- is not included in
- type t = A of { f : string; }
- Their internal representations differ:
- the first declaration uses unboxed representation.
-# Characters 71-112:
- ......struct
- type t = A of { f : string }
- end..
-Error: Signature mismatch:
- Modules do not match:
- sig type t = A of { f : string; } end
- is not included in
- sig type t = A of { f : string; } [@@unboxed] end
- Type declarations do not match:
- type t = A of { f : string; }
- is not included in
- type t = A of { f : string; } [@@unboxed]
- Their internal representations differ:
- the second declaration uses unboxed representation.
-# type t11 = L of float [@@unboxed]
-# - : unit = ()
-# type 'a t12 = M of 'a t12 [@@unboxed]
-# val f : int t12 array -> int t12 = <fun>
-# type t13 = A : 'a t12 -> t13 [@@unboxed]
-# type t14
-# type t15 = A of t14 [@@unboxed]
-# type 'a abs
-# Characters 0-45:
- type t16 = A : _ abs -> t16 [@@ocaml.unboxed];;
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Error: This type cannot be unboxed because
- it might contain both float and non-float values.
- You should annotate it with [@@ocaml.boxed].
-# Characters 19-69:
- type t18 = A : _ list abs -> t18 [@@ocaml.unboxed];;
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Error: This type cannot be unboxed because
- it might contain both float and non-float values.
- You should annotate it with [@@ocaml.boxed].
-# * Characters 176-256:
- ......struct
- type t = A of float [@@ocaml.unboxed]
- type u = { f1 : t; f2 : t }
- end..
-Error: Signature mismatch:
- ...
- Type declarations do not match:
- type u = { f1 : t; f2 : t; }
- is not included in
- type u = { f1 : t; f2 : t; }
- Their internal representations differ:
- the first declaration uses unboxed float representation.
-# * * module T : sig type t [@@immediate] end
-# * type 'a s = S : 'a -> 'a s [@@unboxed]
-# Characters 0-33:
- type t = T : _ s -> t [@@unboxed];;
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Error: This type cannot be unboxed because
- it might contain both float and non-float values.
- You should annotate it with [@@ocaml.boxed].
-# type 'a s = S : 'a -> 'a option s [@@unboxed]
-# Characters 0-33:
- type t = T : _ s -> t [@@unboxed];;
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Error: This type cannot be unboxed because
- it might contain both float and non-float values.
- You should annotate it with [@@ocaml.boxed].
-# module M :
- sig type 'a r constraint 'a = unit -> 'b val inj : 'b -> (unit -> 'b) r end
-# Characters 14-59:
- type t = T : (unit -> _) M.r -> t [@@unboxed];;
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Error: This type cannot be unboxed because
- it might contain both float and non-float values.
- You should annotate it with [@@ocaml.boxed].
-# type 'a s = S : (unit -> 'a) M.r -> 'a option s [@@unboxed]
-# Characters 14-47:
- type t = T : _ s -> t [@@unboxed];;
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Error: This type cannot be unboxed because
- it might contain both float and non-float values.
- You should annotate it with [@@ocaml.boxed].
-# type 'a t = T : 'a s -> 'a t [@@unboxed]
-# Characters 42-81:
- type _ s = S : 'a t -> _ s [@@unboxed]
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Error: This type cannot be unboxed because
- it might contain both float and non-float values.
- You should annotate it with [@@ocaml.boxed].
-#
--- /dev/null
+
+# type t1 = A of string [@@unboxed]
+# - : bool = true
+# type t2 = { f : string; } [@@unboxed]
+# - : bool = true
+# type t3 = B of { g : string; } [@@unboxed]
+# - : bool = true
+# Characters 29-58:
+ type t4 = C [@@ocaml.unboxed];; (* no argument *)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This type cannot be unboxed because its constructor has no argument.
+# Characters 0-45:
+ type t5 = D of int * string [@@ocaml.unboxed];; (* more than one argument *)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This type cannot be unboxed because
+ its constructor has more than one argument.
+# Characters 0-33:
+ type t5 = E | F [@@ocaml.unboxed];; (* more than one constructor *)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This type cannot be unboxed because it has more than one constructor.
+# Characters 0-40:
+ type t6 = G of int | H [@@ocaml.unboxed];;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This type cannot be unboxed because it has more than one constructor.
+# Characters 0-51:
+ type t7 = I of string | J of bool [@@ocaml.unboxed];;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This type cannot be unboxed because it has more than one constructor.
+# Characters 1-50:
+ type t8 = { h : bool; i : int } [@@ocaml.unboxed];; (* more than one field *)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This type cannot be unboxed because it has more than one field.
+# Characters 0-56:
+ type t9 = K of { j : string; l : int } [@@ocaml.unboxed];;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This type cannot be unboxed because
+ its constructor has more than one argument.
+# type t10 = A of t10 [@@unboxed]
+# Characters 12-15:
+ let rec x = A x;;
+ ^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 121-172:
+ ......struct
+ type t = A of string [@@ocaml.unboxed]
+ end..
+Error: Signature mismatch:
+ Modules do not match:
+ sig type t = A of string [@@unboxed] end
+ is not included in
+ sig type t = A of string end
+ Type declarations do not match:
+ type t = A of string [@@unboxed]
+ is not included in
+ type t = A of string
+ Their internal representations differ:
+ the first declaration uses unboxed representation.
+# Characters 63-96:
+ ......struct
+ type t = A of string
+ end..
+Error: Signature mismatch:
+ Modules do not match:
+ sig type t = A of string end
+ is not included in
+ sig type t = A of string [@@unboxed] end
+ Type declarations do not match:
+ type t = A of string
+ is not included in
+ type t = A of string [@@unboxed]
+ Their internal representations differ:
+ the second declaration uses unboxed representation.
+# Characters 48-102:
+ ......struct
+ type t = { f : string } [@@ocaml.unboxed]
+ end..
+Error: Signature mismatch:
+ Modules do not match:
+ sig type t = { f : string; } [@@unboxed] end
+ is not included in
+ sig type t = { f : string; } end
+ Type declarations do not match:
+ type t = { f : string; } [@@unboxed]
+ is not included in
+ type t = { f : string; }
+ Their internal representations differ:
+ the first declaration uses unboxed representation.
+# Characters 66-102:
+ ......struct
+ type t = { f : string }
+ end..
+Error: Signature mismatch:
+ Modules do not match:
+ sig type t = { f : string; } end
+ is not included in
+ sig type t = { f : string; } [@@unboxed] end
+ Type declarations do not match:
+ type t = { f : string; }
+ is not included in
+ type t = { f : string; } [@@unboxed]
+ Their internal representations differ:
+ the second declaration uses unboxed representation.
+# Characters 53-112:
+ ......struct
+ type t = A of { f : string } [@@ocaml.unboxed]
+ end..
+Error: Signature mismatch:
+ Modules do not match:
+ sig type t = A of { f : string; } [@@unboxed] end
+ is not included in
+ sig type t = A of { f : string; } end
+ Type declarations do not match:
+ type t = A of { f : string; } [@@unboxed]
+ is not included in
+ type t = A of { f : string; }
+ Their internal representations differ:
+ the first declaration uses unboxed representation.
+# Characters 71-112:
+ ......struct
+ type t = A of { f : string }
+ end..
+Error: Signature mismatch:
+ Modules do not match:
+ sig type t = A of { f : string; } end
+ is not included in
+ sig type t = A of { f : string; } [@@unboxed] end
+ Type declarations do not match:
+ type t = A of { f : string; }
+ is not included in
+ type t = A of { f : string; } [@@unboxed]
+ Their internal representations differ:
+ the second declaration uses unboxed representation.
+# type t11 = L of float [@@unboxed]
+# - : unit = ()
+# type 'a t12 = M of 'a t12 [@@unboxed]
+# val f : int t12 array -> int t12 = <fun>
+# type t13 = A : 'a t12 -> t13 [@@unboxed]
+# type t14
+# type t15 = A of t14 [@@unboxed]
+# type 'a abs
+# Characters 0-45:
+ type t16 = A : _ abs -> t16 [@@ocaml.unboxed];;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This type cannot be unboxed because
+ it might contain both float and non-float values.
+ You should annotate it with [@@ocaml.boxed].
+# Characters 19-69:
+ type t18 = A : _ list abs -> t18 [@@ocaml.unboxed];;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This type cannot be unboxed because
+ it might contain both float and non-float values.
+ You should annotate it with [@@ocaml.boxed].
+# * Characters 176-256:
+ ......struct
+ type t = A of float [@@ocaml.unboxed]
+ type u = { f1 : t; f2 : t }
+ end..
+Error: Signature mismatch:
+ ...
+ Type declarations do not match:
+ type u = { f1 : t; f2 : t; }
+ is not included in
+ type u = { f1 : t; f2 : t; }
+ Their internal representations differ:
+ the first declaration uses unboxed float representation.
+# * * module T : sig type t [@@immediate] end
+# * type 'a s = S : 'a -> 'a s [@@unboxed]
+# Characters 0-33:
+ type t = T : _ s -> t [@@unboxed];;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This type cannot be unboxed because
+ it might contain both float and non-float values.
+ You should annotate it with [@@ocaml.boxed].
+# type 'a s = S : 'a -> 'a option s [@@unboxed]
+# Characters 0-33:
+ type t = T : _ s -> t [@@unboxed];;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This type cannot be unboxed because
+ it might contain both float and non-float values.
+ You should annotate it with [@@ocaml.boxed].
+# module M :
+ sig type 'a r constraint 'a = unit -> 'b val inj : 'b -> (unit -> 'b) r end
+# Characters 14-59:
+ type t = T : (unit -> _) M.r -> t [@@unboxed];;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This type cannot be unboxed because
+ it might contain both float and non-float values.
+ You should annotate it with [@@ocaml.boxed].
+# type 'a s = S : (unit -> 'a) M.r -> 'a option s [@@unboxed]
+# Characters 14-47:
+ type t = T : _ s -> t [@@unboxed];;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This type cannot be unboxed because
+ it might contain both float and non-float values.
+ You should annotate it with [@@ocaml.boxed].
+# type 'a t = T : 'a s -> 'a t [@@unboxed]
+# Characters 42-81:
+ type _ s = S : 'a t -> _ s [@@unboxed]
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This type cannot be unboxed because
+ it might contain both float and non-float values.
+ You should annotate it with [@@ocaml.boxed].
+# type 'a s
+type ('a, 'p) t = private 'a s
+type 'a packed = T : ('a, 'b) t -> 'a packed [@@unboxed]
+#
--- /dev/null
+
+# type t1 = A of string [@@unboxed]
+# - : bool = true
+# type t2 = { f : string; } [@@unboxed]
+# - : bool = true
+# type t3 = B of { g : string; } [@@unboxed]
+# - : bool = true
+# Characters 29-58:
+ type t4 = C [@@ocaml.unboxed];; (* no argument *)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This type cannot be unboxed because its constructor has no argument.
+# Characters 0-45:
+ type t5 = D of int * string [@@ocaml.unboxed];; (* more than one argument *)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This type cannot be unboxed because
+ its constructor has more than one argument.
+# Characters 0-33:
+ type t5 = E | F [@@ocaml.unboxed];; (* more than one constructor *)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This type cannot be unboxed because it has more than one constructor.
+# Characters 0-40:
+ type t6 = G of int | H [@@ocaml.unboxed];;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This type cannot be unboxed because it has more than one constructor.
+# Characters 0-51:
+ type t7 = I of string | J of bool [@@ocaml.unboxed];;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This type cannot be unboxed because it has more than one constructor.
+# Characters 1-50:
+ type t8 = { h : bool; i : int } [@@ocaml.unboxed];; (* more than one field *)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This type cannot be unboxed because it has more than one field.
+# Characters 0-56:
+ type t9 = K of { j : string; l : int } [@@ocaml.unboxed];;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This type cannot be unboxed because
+ its constructor has more than one argument.
+# type t10 = A of t10 [@@unboxed]
+# Characters 12-15:
+ let rec x = A x;;
+ ^^^
+Error: This kind of expression is not allowed as right-hand side of `let rec'
+# Characters 121-172:
+ ......struct
+ type t = A of string [@@ocaml.unboxed]
+ end..
+Error: Signature mismatch:
+ Modules do not match:
+ sig type t = A of string [@@unboxed] end
+ is not included in
+ sig type t = A of string end
+ Type declarations do not match:
+ type t = A of string [@@unboxed]
+ is not included in
+ type t = A of string
+ Their internal representations differ:
+ the first declaration uses unboxed representation.
+# Characters 63-96:
+ ......struct
+ type t = A of string
+ end..
+Error: Signature mismatch:
+ Modules do not match:
+ sig type t = A of string end
+ is not included in
+ sig type t = A of string [@@unboxed] end
+ Type declarations do not match:
+ type t = A of string
+ is not included in
+ type t = A of string [@@unboxed]
+ Their internal representations differ:
+ the second declaration uses unboxed representation.
+# Characters 48-102:
+ ......struct
+ type t = { f : string } [@@ocaml.unboxed]
+ end..
+Error: Signature mismatch:
+ Modules do not match:
+ sig type t = { f : string; } [@@unboxed] end
+ is not included in
+ sig type t = { f : string; } end
+ Type declarations do not match:
+ type t = { f : string; } [@@unboxed]
+ is not included in
+ type t = { f : string; }
+ Their internal representations differ:
+ the first declaration uses unboxed representation.
+# Characters 66-102:
+ ......struct
+ type t = { f : string }
+ end..
+Error: Signature mismatch:
+ Modules do not match:
+ sig type t = { f : string; } end
+ is not included in
+ sig type t = { f : string; } [@@unboxed] end
+ Type declarations do not match:
+ type t = { f : string; }
+ is not included in
+ type t = { f : string; } [@@unboxed]
+ Their internal representations differ:
+ the second declaration uses unboxed representation.
+# Characters 53-112:
+ ......struct
+ type t = A of { f : string } [@@ocaml.unboxed]
+ end..
+Error: Signature mismatch:
+ Modules do not match:
+ sig type t = A of { f : string; } [@@unboxed] end
+ is not included in
+ sig type t = A of { f : string; } end
+ Type declarations do not match:
+ type t = A of { f : string; } [@@unboxed]
+ is not included in
+ type t = A of { f : string; }
+ Their internal representations differ:
+ the first declaration uses unboxed representation.
+# Characters 71-112:
+ ......struct
+ type t = A of { f : string }
+ end..
+Error: Signature mismatch:
+ Modules do not match:
+ sig type t = A of { f : string; } end
+ is not included in
+ sig type t = A of { f : string; } [@@unboxed] end
+ Type declarations do not match:
+ type t = A of { f : string; }
+ is not included in
+ type t = A of { f : string; } [@@unboxed]
+ Their internal representations differ:
+ the second declaration uses unboxed representation.
+# type t11 = L of float [@@unboxed]
+# - : unit = ()
+# type 'a t12 = M of 'a t12 [@@unboxed]
+# val f : int t12 array -> int t12 = <fun>
+# type t13 = A : 'a t12 -> t13 [@@unboxed]
+# type t14
+# type t15 = A of t14 [@@unboxed]
+# type 'a abs
+# type t16 = A : 'a abs -> t16 [@@unboxed]
+# type t18 = A : 'a list abs -> t18 [@@unboxed]
+# * Characters 176-256:
+ ......struct
+ type t = A of float [@@ocaml.unboxed]
+ type u = { f1 : t; f2 : t }
+ end..
+Error: Signature mismatch:
+ ...
+ Type declarations do not match:
+ type u = { f1 : t; f2 : t; }
+ is not included in
+ type u = { f1 : t; f2 : t; }
+ Their internal representations differ:
+ the first declaration uses unboxed float representation.
+# * * module T : sig type t [@@immediate] end
+# * type 'a s = S : 'a -> 'a s [@@unboxed]
+# type t = T : 'a s -> t [@@unboxed]
+# type 'a s = S : 'a -> 'a option s [@@unboxed]
+# type t = T : 'a s -> t [@@unboxed]
+# module M :
+ sig type 'a r constraint 'a = unit -> 'b val inj : 'b -> (unit -> 'b) r end
+# type t = T : (unit -> 'a) M.r -> t [@@unboxed]
+# type 'a s = S : (unit -> 'a) M.r -> 'a option s [@@unboxed]
+# type t = T : 'a s -> t [@@unboxed]
+# type 'a t = T : 'a s -> 'a t [@@unboxed]
+# type _ s = S : 'a t -> 'b s [@@unboxed]
+and _ t = T : 'a -> 'a s t
+# type 'a s
+type ('a, 'p) t = private 'a s
+type 'a packed = T : ('a, 'b) t -> 'a packed [@@unboxed]
+#
--- /dev/null
+
+module A: sig val f: fpclass -> fpclass end =
+ struct
+ let f _ = FP_normal
+ end;;
+
+type fpclass = A ;;
+
+module B: sig val f: fpclass -> fpclass end =
+ struct
+ let f A = FP_normal
+ end
+ ;;
--- /dev/null
+
+# module A : sig val f : fpclass -> fpclass end
+# type fpclass = A
+# Characters 49-85:
+ ..struct
+ let f A = FP_normal
+ end
+Error: Signature mismatch:
+ Modules do not match:
+ sig val f : fpclass -> Pervasives.fpclass end
+ is not included in
+ sig val f : fpclass -> fpclass end
+ Values do not match:
+ val f : fpclass -> Pervasives.fpclass
+ is not included in
+ val f : fpclass -> fpclass
+#
--- /dev/null
+type foo =
+ Foo: [> `Bla ] as 'b ) * 'b -> foo;;
+type foo =
+ Foo: 'b * 'b -> foo constraint 'b = [> `Bla ];;
--- /dev/null
+
+# Characters 30-32:
+ Foo: [> `Bla ] as 'b ) * 'b -> foo;;
+ ^^
+Error: Syntax error
+# Characters 46-60:
+ Foo: 'b * 'b -> foo constraint 'b = [> `Bla ];;
+ ^^^^^^^^^^^^^^
+Warning 62: Type constraints do not apply to GADT cases of variant types.
+type foo = Foo : 'b * 'b -> foo
+#
--- /dev/null
+module A = struct type foo end;;
+
+module rec B : sig
+ open A
+ type bar = Bar of foo
+end = B;;
+
+module rec C : sig
+ open A
+end = C;;
+
+module rec D : sig
+ module M : module type of struct
+ module X : sig end = struct
+ open A
+ let None = None
+ end
+ end
+end = D;;
+
--- /dev/null
+
+# module A : sig type foo end
+# module rec B : sig type bar = Bar of A.foo end
+# Characters 22-28:
+ open A
+ ^^^^^^
+Warning 33: unused open A.
+module rec C : sig end
+# Characters 110-114:
+ let None = None
+ ^^^^
+Warning 8: this pattern-matching is not exhaustive.
+Here is an example of a case that is not matched:
+Some _
+Characters 93-99:
+ open A
+ ^^^^^^
+Warning 33: unused open A.
+module rec D : sig module M : sig module X : sig end end end
+#
/**************************************************************************/
#include <caml/mlvalues.h>
-#include <bigarray.h>
+#include <caml/bigarray.h>
char *ocaml_buffer;
char *c_buffer;
@$(OCAMLOPT) -c -opaque mylib.mli
@$(OCAMLOPT) -c driver.ml
@$(OCAMLOPT) -c mylib.ml
- @$(OCAMLOPT) -ccopt "-I$(CTOPDIR)/byterun" -c stack_walker.c
+ @$(OCAMLOPT) -ccopt -I -ccopt $(CTOPDIR)/byterun -c stack_walker.c
@$(OCAMLOPT) -cclib -Wl,-keep_dwarf_unwind -o unwind_test mylib.cmx \
driver.cmx stack_walker.o
run-all:
@$(OCAMLC) $(FLAGS) -c deprecated_module.mli
@$(OCAMLC) $(FLAGS) -c module_without_cmx.mli
+ @$(OCAMLC) $(FLAGS) -c w32.mli
@$(OCAMLC) $(FLAGS) -c w60.mli
@for file in *.ml; do \
printf " ... testing '$$file':"; \
--- /dev/null
+(* Values *)
+
+module X : sig
+ val x : int [@@deprecated "DEPRECATED"]
+end = struct
+ let x = 7
+end
+
+module Y : sig val x : int end = X
+
+module Z : sig val x : int [@@deprecated "..."] end = X
+
+module F(A : sig val x : int end) = struct end
+
+module B = F(X)
+
+
+
+module XX = struct let x = 7 end
+module YY : sig val x : int [@@deprecated "..."] end = XX
+
+
+(* Constructors *)
+
+module CSTR : sig type t = A | B end = struct type t = A [@deprecated] | B end
+
+module CSTR1 = struct
+ type t = A [@deprecated] | B
+ type s = t = A | B
+end
+
+
+(* Fields *)
+
+module FIELD :
+sig type t = {mutable x: int} end =
+struct type t = {mutable x: int [@deprecated_mutable]} end
+
+module FIELD1 = struct
+ type t = {mutable x: int [@deprecated_mutable]}
+ type s = t = {mutable x: int}
+end
+
+(* Types *)
+
+module TYPE : sig type t = int end = struct type t = int [@@deprecated] end
+
+(* Class, class types *)
+
+module CL :
+sig class c : object end end =
+struct class c = object end [@@deprecated "FOO"] end
+
+module CLT :
+sig class type c = object end end =
+struct class type c = object end [@@deprecated "FOO"] end
+
+
+(* Module types *)
+
+module MT :
+sig module type S = sig end end =
+struct module type S = sig end [@@deprecated "FOO"] end
+
+module MT_OK :
+sig module type S = sig end [@@deprecated] end =
+struct module type S = sig end [@@deprecated "FOO"] end
+
+
+(* Modules *)
+
+module MD :
+sig module M : sig end end =
+struct module M = struct end [@@deprecated "FOO"] end
+
+module MD_OK :
+sig module M : sig end [@@deprecated] end =
+struct module M = struct end [@@deprecated "FOO"] end
--- /dev/null
+File "deprecated_module_assigment.ml", line 9, characters 33-34:
+Warning 3: deprecated: x
+DEPRECATED
+ File "deprecated_module_assigment.ml", line 4, characters 2-41:
+ Definition
+ File "deprecated_module_assigment.ml", line 9, characters 15-26:
+ Expected signature
+File "deprecated_module_assigment.ml", line 15, characters 13-14:
+Warning 3: deprecated: x
+DEPRECATED
+ File "deprecated_module_assigment.ml", line 4, characters 2-41:
+ Definition
+ File "deprecated_module_assigment.ml", line 13, characters 17-28:
+ Expected signature
+File "deprecated_module_assigment.ml", line 25, characters 39-78:
+Warning 3: deprecated: A
+ File "deprecated_module_assigment.ml", line 25, characters 55-70:
+ Definition
+ File "deprecated_module_assigment.ml", line 25, characters 27-28:
+ Expected signature
+File "deprecated_module_assigment.ml", line 29, characters 2-20:
+Warning 3: deprecated: A
+ File "deprecated_module_assigment.ml", line 28, characters 11-26:
+ Definition
+ File "deprecated_module_assigment.ml", line 29, characters 15-16:
+ Expected signature
+File "deprecated_module_assigment.ml", line 37, characters 0-58:
+Warning 3: deprecated: mutating field x
+ File "deprecated_module_assigment.ml", line 37, characters 17-53:
+ Definition
+ File "deprecated_module_assigment.ml", line 36, characters 14-28:
+ Expected signature
+File "deprecated_module_assigment.ml", line 41, characters 2-31:
+Warning 3: deprecated: mutating field x
+ File "deprecated_module_assigment.ml", line 40, characters 12-48:
+ Definition
+ File "deprecated_module_assigment.ml", line 41, characters 16-30:
+ Expected signature
+File "deprecated_module_assigment.ml", line 46, characters 37-75:
+Warning 3: deprecated: t
+ File "deprecated_module_assigment.ml", line 46, characters 44-71:
+ Definition
+ File "deprecated_module_assigment.ml", line 46, characters 18-30:
+ Expected signature
+File "deprecated_module_assigment.ml", line 52, characters 0-52:
+Warning 3: deprecated: c
+FOO
+ File "deprecated_module_assigment.ml", line 52, characters 7-48:
+ Definition
+ File "deprecated_module_assigment.ml", line 51, characters 4-24:
+ Expected signature
+File "deprecated_module_assigment.ml", line 56, characters 0-57:
+Warning 3: deprecated: c
+FOO
+ File "deprecated_module_assigment.ml", line 56, characters 7-53:
+ Definition
+ File "deprecated_module_assigment.ml", line 55, characters 4-29:
+ Expected signature
+File "deprecated_module_assigment.ml", line 63, characters 0-55:
+Warning 3: deprecated: S
+FOO
+ File "deprecated_module_assigment.ml", line 63, characters 7-51:
+ Definition
+ File "deprecated_module_assigment.ml", line 62, characters 4-27:
+ Expected signature
+File "deprecated_module_assigment.ml", line 74, characters 0-53:
+Warning 3: deprecated: M
+FOO
+ File "deprecated_module_assigment.ml", line 74, characters 7-49:
+ Definition
+ File "deprecated_module_assigment.ml", line 73, characters 4-22:
+ Expected signature
--- /dev/null
+(* from MPR#7624 *)
+
+let[@warning "-32"] f x = x
+
+let g x = x
+
+let h x = x
+
+
+(* multiple bindings *)
+
+let[@warning "-32"] i x = x
+and j x = x
+
+let k x = x
+and[@warning "-32"] l x = x
+
+let[@warning "-32"] m x = x
+and n x = x
+
+let o x = x
+and[@warning "-32"] p x = x
+
+
+(* recursive bindings *)
+
+let[@warning "-32"] rec q x = x
+and r x = x
+
+let[@warning "-32"] rec s x = x
+and[@warning "-39"] t x = x
+
+let[@warning "-39"] rec u x = x
+and v x = v x
+
+
+(* disabled then re-enabled warnings *)
+
+module M = struct
+ [@@@warning "-32"]
+ let f x = x
+ let[@warning "+32"] g x = x
+ let[@warning "+32"] h x = x
+ and i x = x
+ let j x = x
+ and[@warning "+32"] k x = x
+end
--- /dev/null
+(* from MPR#7624 *)
+
+val g : 'a -> 'a
+
+
+(* multiple bindings *)
+val n : 'a -> 'a
+
+val o : 'a -> 'a
--- /dev/null
+File "w32.ml", line 27, characters 24-25:
+Warning 39: unused rec flag.
+File "w32.ml", line 30, characters 24-25:
+Warning 39: unused rec flag.
+File "w32.ml", line 7, characters 4-5:
+Warning 32: unused value h.
+File "w32.ml", line 13, characters 4-5:
+Warning 32: unused value j.
+File "w32.ml", line 15, characters 4-5:
+Warning 32: unused value k.
+File "w32.ml", line 28, characters 4-5:
+Warning 32: unused value r.
+File "w32.ml", line 31, characters 20-21:
+Warning 32: unused value t.
+File "w32.ml", line 33, characters 24-25:
+Warning 32: unused value u.
+File "w32.ml", line 34, characters 4-5:
+Warning 32: unused value v.
+File "w32.ml", line 42, characters 22-23:
+Warning 32: unused value g.
+File "w32.ml", line 43, characters 22-23:
+Warning 32: unused value h.
+File "w32.ml", line 46, characters 22-23:
+Warning 32: unused value k.
+File "w32.ml", line 39, characters 0-174:
+Warning 60: unused module M.
Warning 59: A potential assignment to a non-mutable value was detected
in this source file. Such assignments may generate incorrect code
when using Flambda.
-File "w59.opt_backend.ml", line 35, characters 2-7:
-Warning 59: A potential assignment to a non-mutable value was detected
-in this source file. Such assignments may generate incorrect code
-when using Flambda.
-File "w59.opt_backend.ml", line 25, characters 2-43:
-Warning 59: A potential assignment to a non-mutable value was detected
-in this source file. Such assignments may generate incorrect code
-when using Flambda.
-File "w59.opt_backend.ml", line 26, characters 2-43:
-Warning 59: A potential assignment to a non-mutable value was detected
-in this source file. Such assignments may generate incorrect code
-when using Flambda.
-File "w59.opt_backend.ml", line 27, characters 2-43:
-Warning 59: A potential assignment to a non-mutable value was detected
-in this source file. Such assignments may generate incorrect code
-when using Flambda.
-File "w59.opt_backend.ml", line 28, characters 2-43:
-Warning 59: A potential assignment to a non-mutable value was detected
-in this source file. Such assignments may generate incorrect code
-when using Flambda.
-File "w59.opt_backend.ml", line 35, characters 2-7:
-Warning 59: A potential assignment to a non-mutable value was detected
-in this source file. Such assignments may generate incorrect code
-when using Flambda.
--- /dev/null
+BASEDIR=../..
+LIBRARIES=unix
+ADD_COMPFLAGS= \
+ -I $(OTOPDIR)/otherlibs/$(UNIXLIBVAR)unix \
+ -strict-sequence -safe-string -w A -warn-error A
+LD_PATH=$(TOPDIR)/otherlibs/$(UNIXLIBVAR)unix
+C_FILES=mkfiles
+
+.PHONY: test
+test:
+ @if echo 'let () = exit (if Config.windows_unicode then 0 else 1)' | $(OCAML) -I $(OTOPDIR)/utils config.cmo -stdin; then \
+ $(MAKE) printargv.exe printenv.exe symlink_tests.precheck && \
+ $(MAKE) check; \
+ else \
+ $(MAKE) SKIP=true C_FILES= run-all; \
+ fi
+
+.PHONY: symlink_tests.precheck
+symlink_tests.precheck:
+ @echo 'echo "let () = exit (if Unix.has_symlink () then 0 else 1)" | $(OCAML) $(ADD_COMPFLAGS) unix.cma -stdin' > $@
+
+include $(BASEDIR)/makefiles/Makefile.several
+include $(BASEDIR)/makefiles/Makefile.common
+
+GENERATED_SOURCES=symlink_tests.precheck
+
+%.exe: %.c
+ @$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(if $(filter msvc,$(CCOMPTYPE)),/Fe$*.exe,-o$*.exe) $*.c
--- /dev/null
+let values =
+ [
+ "\xD0\xB2\xD0\xB5\xD1\x80\xD0\xB1\xD0\xBB\xD1\x8E\xD0\xB4\xD1\x8B"; (* "верблюды" *)
+ "\xE9\xAA\x86\xE9\xA9\xBC"; (* "骆驼" *)
+ "\215\167\215\162\215\158\215\156"; (* "קעמל" *)
+ "\216\167\217\136\217\134\217\185"; (* "اونٹ" *)
+ ]
+
+let env0 =
+ List.sort compare (List.mapi (fun i v -> Printf.sprintf "OCAML_UTF8_VAR%d=%s" i v) values)
+
+let split sep s =
+ match String.index s sep with
+ | i ->
+ String.sub s 0 i, String.sub s (i + 1) (String.length s - i - 1)
+ | exception Not_found ->
+ s, ""
+
+let test_environment () =
+ print_endline "test_environment";
+ let vars = List.map (fun s -> fst (split '=' s)) env0 in
+ let f s = List.mem (fst (split '=' s)) vars in
+ let env = List.filter f (Array.to_list (Unix.environment ())) in
+ assert (List.length env0 = List.length env);
+ List.iter2 (fun s1 s2 -> assert (s1 = s2)) env0 env
+
+let test0 () =
+ print_endline "test0";
+ Unix.execve Sys.executable_name [|Sys.executable_name; "1"|] (Array.of_list env0)
+
+let test_argv () =
+ print_endline "test_argv";
+ let argv = match Array.to_list Sys.argv with _ :: _ :: argv -> argv | _ -> assert false in
+ List.iter2 (fun s1 s2 -> assert (s1 = s2)) argv values
+
+let test1 () =
+ print_endline "test1";
+ Unix.execv Sys.executable_name (Array.of_list (Sys.executable_name :: "2" :: values))
+
+let restart = function
+ | 0 -> test0 ()
+ | 1 -> test_environment (); test1 ()
+ | 2 -> test_argv ()
+ | _ -> assert false
+
+let main () =
+ match Array.length Sys.argv with
+ | 1 ->
+ let pid = Unix.create_process Sys.executable_name [|Sys.executable_name; "0"|] Unix.stdin Unix.stdout Unix.stderr in
+ begin match Unix.waitpid [] pid with
+ | _, Unix.WEXITED 0 -> ()
+ | _, (Unix.WEXITED _ | Unix.WSIGNALED _ | Unix.WSTOPPED _) -> failwith "Child process error"
+ end
+ | _ ->
+ restart (int_of_string Sys.argv.(1))
+
+let () =
+ match main () with
+ | () ->
+ Printf.printf "OK\n%!"
+ | exception e ->
+ Printf.printf "BAD: %s\n%!" (Printexc.to_string e);
+ exit 1
--- /dev/null
+# exec_tests.ml disabled because it fails non-deterministically (at least under CI)
+# seems to be a problem redirecting handles
+exit 1
--- /dev/null
+test0
+OK
+test_environment
+test1
+test_argv
+OK
--- /dev/null
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <caml/mlvalues.h>
+#include <caml/alloc.h>
+#include <caml/memory.h>
+#include <caml/fail.h>
+
+#include <Windows.h>
+#include <io.h>
+
+/* Returns an OCaml string with the UTF-16 representation of [s], *including* the final (2-byte) NULL */
+CAMLprim value caml_to_utf16(value s)
+{
+ CAMLparam1(s);
+ CAMLlocal1(w);
+ int size;
+ size = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, String_val(s), caml_string_length(s), NULL, 0);
+ if (size == 0) caml_failwith("Invalid UTF-8");
+ w = caml_alloc_string((size + 1) * sizeof(wchar_t));
+ ((wchar_t *)String_val(w))[size] = 0;
+ size = MultiByteToWideChar(CP_UTF8, 0, String_val(s), caml_string_length(s), (wchar_t *)String_val(w), size);
+ assert(size != 0);
+ CAMLreturn(w);
+}
+
+CAMLprim value caml_create_file(value s, value contents)
+{
+ CAMLparam2(s, contents);
+ FILE * f;
+ f = _wfopen((wchar_t *)String_val(s), _T("w"));
+ if (f == NULL) caml_failwith("fopen failed");
+ fwrite(String_val(contents), 1, caml_string_length(contents), f);
+ fclose(f);
+ CAMLreturn(Val_unit);
+}
--- /dev/null
+let total = ref 0
+let failed = ref 0
+let num = ref 0
+
+external to_utf16 : string -> string = "caml_to_utf16"
+external create_file : string -> string -> unit = "caml_create_file"
+
+let foreign_names =
+ List.sort compare
+ [
+ "simple";
+ "\xE4\xBD\xA0\xE5\xA5\xBD"; (* "你好" *)
+ "\x73\xC5\x93\x75\x72"; (* "sœur" *)
+ "e\204\129te\204\129"; (* "été" *)
+ ]
+
+let test_files =
+ List.map (fun s -> s ^ ".txt") foreign_names
+
+let to_create_and_delete_files =
+ [
+ "\xD0\xB2\xD0\xB5\xD1\x80\xD0\xB1\xD0\xBB\xD1\x8E\xD0\xB4\xD1\x8B"; (* "верблюды" *)
+ "\xE9\xAA\x86\xE9\xA9\xBC"; (* "骆驼" *)
+ "\215\167\215\162\215\158\215\156"; (* "קעמל" *)
+ "\216\167\217\136\217\134\217\185"; (* "اونٹ" *)
+ "L\225\186\161c \196\145\195\160"; (* "Lạc đà" *)
+ "\224\176\146\224\176\130\224\176\159\224\177\134"; (* "ఒంటె" *)
+ "\224\174\146\224\174\159\224\175\141\224\174\159\224\174\149\224\
+ \174\174\224\175\141"; (* "ஒட்டகம்" *)
+ "\217\136\216\180\216\170\216\177"; (* "وشتر" *)
+ "\224\164\137\224\164\183\224\165\141\224\164\159\224\165\141\224\
+ \164\176\224\164\131"; (* "उष्ट्रः" *)
+ "\216\167\217\186"; (* "اٺ" *)
+ ]
+
+let rec take n l =
+ if n = 0 then []
+ else List.hd l :: take (n-1) (List.tl l)
+
+let foreign_names2 =
+ take (List.length foreign_names) to_create_and_delete_files
+
+let env0 =
+ List.sort compare (List.mapi (fun i v -> Printf.sprintf "OCAML_UTF8_VAR%d=%s" i v) foreign_names2)
+
+let read_all ic =
+ set_binary_mode_in ic false;
+ let rec loop acc =
+ match input_line ic with
+ | exception End_of_file ->
+ List.rev acc
+ | s ->
+ loop (s :: acc)
+ in
+ loop []
+
+let split sep s =
+ match String.index s sep with
+ | i ->
+ String.sub s 0 i, String.sub s (i+1) (String.length s - i - 1)
+ | exception Not_found ->
+ s, ""
+
+(** WRAPPERS *)
+
+let quote s = "\"" ^ s ^ "\""
+
+let ok _ = "OK"
+
+let unit _ = "()"
+
+let list f l = String.concat " " (List.map f l)
+
+let ell _ = "..."
+
+let file_kind = function
+ | Unix.S_REG -> "S_REG"
+ | Unix.S_DIR -> "S_DIR"
+ | Unix.S_CHR -> "S_CHR"
+ | Unix.S_BLK -> "S_BLK"
+ | Unix.S_LNK -> "S_LNK"
+ | Unix.S_FIFO -> "S_FIFO"
+ | Unix.S_SOCK -> "S_SOCK"
+
+let wrap s f quote_in x quote_out =
+ Printf.printf "%s %s ... " s (quote_in x);
+ match f x with
+ | x ->
+ Printf.printf "%s\n%!" (quote_out x);
+ x
+ | exception e ->
+ Printf.printf "FAILED: %s\n%!" (Printexc.to_string e);
+ raise e
+
+let wrap2 s f quote_in1 quote_in2 x y quote_out =
+ Printf.printf "%s %s %s ... " s (quote_in1 x) (quote_in2 y);
+ match f x y with
+ | x ->
+ Printf.printf "%s\n%!" (quote_out x);
+ x
+ | exception e ->
+ Printf.printf "FAILED: %s\n%!" (Printexc.to_string e);
+ raise e
+
+let getenv s =
+ wrap "Sys.getenv" Sys.getenv quote s quote
+
+let getenvironmentenv s =
+ let get s =
+ let env = Unix.environment () in
+ let rec loop i =
+ if i >= Array.length env then
+ ""
+ else begin
+ let e = env.(i) in
+ let pos = String.index e '=' in
+ if String.sub e 0 pos = s then
+ String.sub e (pos+1) (String.length e - pos - 1)
+ else
+ loop (i+1)
+ end
+ in
+ loop 0
+ in
+ wrap "Unix.environment" get quote s quote
+
+let putenv s x =
+ wrap2 "Unix.putenv" Unix.putenv quote quote s x ok
+
+let sys_rename s x =
+ wrap2 "Sys.rename" Sys.rename quote quote s x ok
+
+let unix_rename s x =
+ wrap2 "Unix.rename" Unix.rename quote quote s x ok
+
+let mkdir s mode =
+ wrap2 "Unix.mkdir" Unix.mkdir quote string_of_int s mode ok
+
+let file_exists s =
+ wrap "Sys.file_exists" Sys.file_exists quote s string_of_bool
+
+let is_directory s =
+ wrap "Sys.is_directory" Sys.is_directory quote s string_of_bool
+
+let unix_chdir s =
+ wrap "Unix.chdir" Unix.chdir quote s ok
+
+let sys_chdir s =
+ wrap "Sys.chdir" Sys.chdir quote s ok
+
+let unix_getcwd () =
+ wrap "Unix.getcwd" (fun s -> Filename.basename (Unix.getcwd s)) unit () quote
+
+let sys_getcwd () =
+ wrap "Sys.getcwd" (fun s -> Filename.basename (Sys.getcwd s)) unit () quote
+
+let rmdir s =
+ wrap "Unix.rmdir" Unix.rmdir quote s ok
+
+let remove s =
+ wrap "Sys.remove" Sys.remove quote s ok
+
+let unlink s =
+ wrap "Unix.unlink" Unix.unlink quote s ok
+
+let stat s =
+ let f s = (Unix.stat s).Unix.st_kind in
+ wrap "Unix.stat" f quote s file_kind
+
+let lstat s =
+ let f s = (Unix.lstat s).Unix.st_kind in
+ wrap "Unix.lstat" f quote s file_kind
+
+let large_stat s =
+ let f s = (Unix.LargeFile.stat s).Unix.LargeFile.st_kind in
+ wrap "Unix.LargeFile.stat" f quote s file_kind
+
+let large_lstat s =
+ let f s = (Unix.LargeFile.lstat s).Unix.LargeFile.st_kind in
+ wrap "Unix.LargeFile.lstat" f quote s file_kind
+
+let access s =
+ let f s = Unix.access s [Unix.F_OK] in
+ wrap "Unix.access" f quote s ok
+
+let unix_readdir f s =
+ let f s =
+ let h = Unix.opendir s in
+ let rec loop acc =
+ match Unix.readdir h with
+ | s ->
+ if f s then
+ loop (s :: acc)
+ else
+ loop acc
+ | exception End_of_file ->
+ Unix.closedir h;
+ List.sort compare acc
+ in
+ loop []
+ in
+ wrap "Unix.{opendir,readdir}" f quote s (list quote)
+
+let sys_readdir f s =
+ let f s =
+ let entries = Sys.readdir s in
+ List.sort compare (List.filter f (Array.to_list entries))
+ in
+ wrap "Sys.readdir" f quote s (list quote)
+
+let open_in s =
+ wrap "open_in" open_in quote s ok
+
+let open_out s =
+ wrap "open_out" open_out quote s ok
+
+let open_process_in cmdline =
+ let f cmdline =
+ let ic as proc = Unix.open_process_in cmdline in
+ let l = List.tl (read_all ic) in
+ ignore (Unix.close_process_in proc);
+ l
+ in
+ wrap "Unix.open_process_in" f ell cmdline (list quote)
+
+let open_process_full filter cmdline env =
+ let f cmdline env =
+ let (ic, _, _) as proc = Unix.open_process_full cmdline (Array.of_list env) in
+ let l = read_all ic in
+ ignore (Unix.close_process_full proc);
+ List.sort compare (List.filter filter l)
+ in
+ wrap2 "Unix.open_process_full" f ell (list quote) cmdline env (list quote)
+
+(** TESTS *)
+
+let title s =
+ let s = Printf.sprintf "Testing %s" s in
+ let u = String.make (String.length s) '=' in
+ Printf.printf "\n#%02d. %s\n%s\n\n%!" !num s u
+
+let expect_gen quote x b =
+ total := !total + 1;
+ if x <> b then begin
+ Printf.printf "** ERROR: EXPECTED RESULT = %s ACTUAL RESULT = %s\n%!" (quote x) (quote b);
+ failed := !failed + 1
+ end
+
+let expect_file_kind x b =
+ expect_gen file_kind x b
+
+let expect_string x s =
+ expect_gen quote x s
+
+let expect_bool x b =
+ expect_gen string_of_bool x b
+
+let expect_int x b =
+ expect_gen string_of_int x b
+
+let test_readdir readdir =
+ let filter s = List.mem s test_files in
+ let entries = readdir filter Filename.current_dir_name in
+ let entries = List.filter (fun s -> Filename.check_suffix s ".txt") entries in
+ expect_int (List.length entries) (List.length test_files);
+ List.iter2 expect_string entries test_files
+
+let test_open_in () =
+ let dump_file s =
+ let ic = open_in s in
+ let l = input_line ic in
+ close_in ic;
+ expect_string s l
+ in
+ let filter s = List.mem s test_files in
+ let files = sys_readdir filter Filename.current_dir_name in
+ List.iter dump_file files
+
+let test_getenv () =
+ let doit key s =
+ putenv key s;
+ expect_string (getenv key) s;
+ expect_string (getenvironmentenv key) s
+ in
+ List.iter2 doit foreign_names foreign_names2
+
+let test_mkdir () =
+ let doit s =
+ mkdir s 0o755;
+ expect_bool (file_exists s) true;
+ expect_bool (is_directory s) true
+ in
+ List.iter doit foreign_names
+
+let test_chdir chdir getcwd =
+ let doit s =
+ chdir s;
+ expect_string (getcwd ()) s;
+ chdir Filename.parent_dir_name
+ in
+ List.iter doit foreign_names
+
+let test_rmdir () =
+ let doit s =
+ rmdir s;
+ expect_bool (file_exists s) false
+ in
+ List.iter doit foreign_names
+
+let test_stat () =
+ let doit s =
+ expect_file_kind (stat s) Unix.S_REG;
+ expect_file_kind (lstat s) Unix.S_REG;
+ expect_file_kind (large_stat s) Unix.S_REG;
+ expect_file_kind (large_lstat s) Unix.S_REG
+ in
+ List.iter doit to_create_and_delete_files
+
+let test_access () =
+ List.iter access to_create_and_delete_files
+
+let test_rename rename =
+ let doit s =
+ let s' = s ^ "-1" in
+ rename s s';
+ expect_bool (file_exists s) false;
+ expect_bool (file_exists s') true;
+ rename s' s;
+ expect_bool (file_exists s) true;
+ expect_bool (file_exists s') false
+ in
+ List.iter doit to_create_and_delete_files
+
+let test_open_out () =
+ let doit s =
+ let oc = open_out s in
+ Printf.fprintf oc "Hello, %s\n" s;
+ close_out oc
+ in
+ List.iter doit to_create_and_delete_files
+
+let test_file_exists expected =
+ let doit s =
+ expect_bool (file_exists s) expected;
+ in
+ List.iter doit to_create_and_delete_files
+
+let test_remove remove =
+ let doit s =
+ remove s;
+ expect_bool (file_exists s) false
+ in
+ List.iter doit to_create_and_delete_files
+
+let test_open_process_in () =
+ let cmdline =
+ String.concat " " (Filename.concat Filename.current_dir_name "printargv.exe" :: List.map Filename.quote to_create_and_delete_files)
+ in
+ let l = open_process_in cmdline in
+ List.iter2 expect_string l to_create_and_delete_files
+
+let test_open_process_full () =
+ let vars = List.map (fun s -> fst (split '=' s)) env0 in
+ let filter s = List.mem (fst (split '=' s)) vars in
+ let l = open_process_full filter (Filename.concat Filename.current_dir_name "printenv.exe") env0 in
+ expect_int (List.length env0) (List.length l);
+ List.iter2 expect_string env0 l
+
+(* Order matters *)
+let tests =
+ [|
+ "test_readdir unix_readdir", (fun () -> test_readdir unix_readdir);
+ "test_readdir sys_readdir", (fun () -> test_readdir sys_readdir);
+ "test_open_in", test_open_in;
+ "test_open_out", test_open_out;
+ "test_file_exists", (fun () -> test_file_exists true);
+ "test_stat", test_stat;
+ "test_access", test_access;
+ "test_rename unix_rename", (fun () -> test_rename unix_rename);
+ "test_rename sys_rename", (fun () -> test_rename sys_rename);
+ "test_remove remove", (fun () -> test_remove remove);
+ "test_file_exists", (fun () -> test_file_exists false);
+ "test_mkdir", test_mkdir;
+ "test_chdir sys_chdir sys_getcwd", (fun () -> test_chdir sys_chdir sys_getcwd);
+ "test_chdir unix_chdir unix_getcwd", (fun () -> test_chdir unix_chdir unix_getcwd);
+ "test_rmdir", test_rmdir;
+ "test_getenv", test_getenv;
+ "test_open_process_in", test_open_process_in;
+ "test_open_process_full", test_open_process_full;
+ |]
+
+(** MAIN *)
+
+let prepare () =
+ List.iter (fun s -> create_file (to_utf16 s) s) test_files
+
+let cleanup () =
+ List.iter Sys.remove test_files
+
+let main () =
+ for i = 0 to Array.length tests - 1 do
+ num := !num + 1;
+ let s, f = tests.(i) in
+ title s;
+ f ()
+ done;
+ Printf.printf "\n\n*** ALL TESTS DONE (%d/%d OK) ***\n%!" (!total - !failed) !total
+
+let () =
+ try
+ prepare ();
+ main ();
+ cleanup ()
+ with e ->
+ Printf.printf "** ERROR: %s\n%!" (Printexc.to_string e);
+ exit 1
--- /dev/null
+
+#01. Testing test_readdir unix_readdir
+=================================
+
+Unix.{opendir,readdir} "." ... "été.txt" "simple.txt" "sœur.txt" "你好.txt"
+
+#02. Testing test_readdir sys_readdir
+================================
+
+Sys.readdir "." ... "été.txt" "simple.txt" "sœur.txt" "你好.txt"
+
+#03. Testing test_open_in
+====================
+
+Sys.readdir "." ... "été.txt" "simple.txt" "sœur.txt" "你好.txt"
+open_in "été.txt" ... OK
+open_in "simple.txt" ... OK
+open_in "sœur.txt" ... OK
+open_in "你好.txt" ... OK
+
+#04. Testing test_open_out
+=====================
+
+open_out "верблюды" ... OK
+open_out "骆驼" ... OK
+open_out "קעמל" ... OK
+open_out "اونٹ" ... OK
+open_out "Lạc đà" ... OK
+open_out "ఒంటె" ... OK
+open_out "ஒட்டகம்" ... OK
+open_out "وشتر" ... OK
+open_out "उष्ट्रः" ... OK
+open_out "اٺ" ... OK
+
+#05. Testing test_file_exists
+========================
+
+Sys.file_exists "верблюды" ... true
+Sys.file_exists "骆驼" ... true
+Sys.file_exists "קעמל" ... true
+Sys.file_exists "اونٹ" ... true
+Sys.file_exists "Lạc đà" ... true
+Sys.file_exists "ఒంటె" ... true
+Sys.file_exists "ஒட்டகம்" ... true
+Sys.file_exists "وشتر" ... true
+Sys.file_exists "उष्ट्रः" ... true
+Sys.file_exists "اٺ" ... true
+
+#06. Testing test_stat
+=================
+
+Unix.stat "верблюды" ... S_REG
+Unix.lstat "верблюды" ... S_REG
+Unix.LargeFile.stat "верблюды" ... S_REG
+Unix.LargeFile.lstat "верблюды" ... S_REG
+Unix.stat "骆驼" ... S_REG
+Unix.lstat "骆驼" ... S_REG
+Unix.LargeFile.stat "骆驼" ... S_REG
+Unix.LargeFile.lstat "骆驼" ... S_REG
+Unix.stat "קעמל" ... S_REG
+Unix.lstat "קעמל" ... S_REG
+Unix.LargeFile.stat "קעמל" ... S_REG
+Unix.LargeFile.lstat "קעמל" ... S_REG
+Unix.stat "اونٹ" ... S_REG
+Unix.lstat "اونٹ" ... S_REG
+Unix.LargeFile.stat "اونٹ" ... S_REG
+Unix.LargeFile.lstat "اونٹ" ... S_REG
+Unix.stat "Lạc đà" ... S_REG
+Unix.lstat "Lạc đà" ... S_REG
+Unix.LargeFile.stat "Lạc đà" ... S_REG
+Unix.LargeFile.lstat "Lạc đà" ... S_REG
+Unix.stat "ఒంటె" ... S_REG
+Unix.lstat "ఒంటె" ... S_REG
+Unix.LargeFile.stat "ఒంటె" ... S_REG
+Unix.LargeFile.lstat "ఒంటె" ... S_REG
+Unix.stat "ஒட்டகம்" ... S_REG
+Unix.lstat "ஒட்டகம்" ... S_REG
+Unix.LargeFile.stat "ஒட்டகம்" ... S_REG
+Unix.LargeFile.lstat "ஒட்டகம்" ... S_REG
+Unix.stat "وشتر" ... S_REG
+Unix.lstat "وشتر" ... S_REG
+Unix.LargeFile.stat "وشتر" ... S_REG
+Unix.LargeFile.lstat "وشتر" ... S_REG
+Unix.stat "उष्ट्रः" ... S_REG
+Unix.lstat "उष्ट्रः" ... S_REG
+Unix.LargeFile.stat "उष्ट्रः" ... S_REG
+Unix.LargeFile.lstat "उष्ट्रः" ... S_REG
+Unix.stat "اٺ" ... S_REG
+Unix.lstat "اٺ" ... S_REG
+Unix.LargeFile.stat "اٺ" ... S_REG
+Unix.LargeFile.lstat "اٺ" ... S_REG
+
+#07. Testing test_access
+===================
+
+Unix.access "верблюды" ... OK
+Unix.access "骆驼" ... OK
+Unix.access "קעמל" ... OK
+Unix.access "اونٹ" ... OK
+Unix.access "Lạc đà" ... OK
+Unix.access "ఒంటె" ... OK
+Unix.access "ஒட்டகம்" ... OK
+Unix.access "وشتر" ... OK
+Unix.access "उष्ट्रः" ... OK
+Unix.access "اٺ" ... OK
+
+#08. Testing test_rename unix_rename
+===============================
+
+Unix.rename "верблюды" "верблюды-1" ... OK
+Sys.file_exists "верблюды" ... false
+Sys.file_exists "верблюды-1" ... true
+Unix.rename "верблюды-1" "верблюды" ... OK
+Sys.file_exists "верблюды" ... true
+Sys.file_exists "верблюды-1" ... false
+Unix.rename "骆驼" "骆驼-1" ... OK
+Sys.file_exists "骆驼" ... false
+Sys.file_exists "骆驼-1" ... true
+Unix.rename "骆驼-1" "骆驼" ... OK
+Sys.file_exists "骆驼" ... true
+Sys.file_exists "骆驼-1" ... false
+Unix.rename "קעמל" "קעמל-1" ... OK
+Sys.file_exists "קעמל" ... false
+Sys.file_exists "קעמל-1" ... true
+Unix.rename "קעמל-1" "קעמל" ... OK
+Sys.file_exists "קעמל" ... true
+Sys.file_exists "קעמל-1" ... false
+Unix.rename "اونٹ" "اونٹ-1" ... OK
+Sys.file_exists "اونٹ" ... false
+Sys.file_exists "اونٹ-1" ... true
+Unix.rename "اونٹ-1" "اونٹ" ... OK
+Sys.file_exists "اونٹ" ... true
+Sys.file_exists "اونٹ-1" ... false
+Unix.rename "Lạc đà" "Lạc đà-1" ... OK
+Sys.file_exists "Lạc đà" ... false
+Sys.file_exists "Lạc đà-1" ... true
+Unix.rename "Lạc đà-1" "Lạc đà" ... OK
+Sys.file_exists "Lạc đà" ... true
+Sys.file_exists "Lạc đà-1" ... false
+Unix.rename "ఒంటె" "ఒంటె-1" ... OK
+Sys.file_exists "ఒంటె" ... false
+Sys.file_exists "ఒంటె-1" ... true
+Unix.rename "ఒంటె-1" "ఒంటె" ... OK
+Sys.file_exists "ఒంటె" ... true
+Sys.file_exists "ఒంటె-1" ... false
+Unix.rename "ஒட்டகம்" "ஒட்டகம்-1" ... OK
+Sys.file_exists "ஒட்டகம்" ... false
+Sys.file_exists "ஒட்டகம்-1" ... true
+Unix.rename "ஒட்டகம்-1" "ஒட்டகம்" ... OK
+Sys.file_exists "ஒட்டகம்" ... true
+Sys.file_exists "ஒட்டகம்-1" ... false
+Unix.rename "وشتر" "وشتر-1" ... OK
+Sys.file_exists "وشتر" ... false
+Sys.file_exists "وشتر-1" ... true
+Unix.rename "وشتر-1" "وشتر" ... OK
+Sys.file_exists "وشتر" ... true
+Sys.file_exists "وشتر-1" ... false
+Unix.rename "उष्ट्रः" "उष्ट्रः-1" ... OK
+Sys.file_exists "उष्ट्रः" ... false
+Sys.file_exists "उष्ट्रः-1" ... true
+Unix.rename "उष्ट्रः-1" "उष्ट्रः" ... OK
+Sys.file_exists "उष्ट्रः" ... true
+Sys.file_exists "उष्ट्रः-1" ... false
+Unix.rename "اٺ" "اٺ-1" ... OK
+Sys.file_exists "اٺ" ... false
+Sys.file_exists "اٺ-1" ... true
+Unix.rename "اٺ-1" "اٺ" ... OK
+Sys.file_exists "اٺ" ... true
+Sys.file_exists "اٺ-1" ... false
+
+#09. Testing test_rename sys_rename
+==============================
+
+Sys.rename "верблюды" "верблюды-1" ... OK
+Sys.file_exists "верблюды" ... false
+Sys.file_exists "верблюды-1" ... true
+Sys.rename "верблюды-1" "верблюды" ... OK
+Sys.file_exists "верблюды" ... true
+Sys.file_exists "верблюды-1" ... false
+Sys.rename "骆驼" "骆驼-1" ... OK
+Sys.file_exists "骆驼" ... false
+Sys.file_exists "骆驼-1" ... true
+Sys.rename "骆驼-1" "骆驼" ... OK
+Sys.file_exists "骆驼" ... true
+Sys.file_exists "骆驼-1" ... false
+Sys.rename "קעמל" "קעמל-1" ... OK
+Sys.file_exists "קעמל" ... false
+Sys.file_exists "קעמל-1" ... true
+Sys.rename "קעמל-1" "קעמל" ... OK
+Sys.file_exists "קעמל" ... true
+Sys.file_exists "קעמל-1" ... false
+Sys.rename "اونٹ" "اونٹ-1" ... OK
+Sys.file_exists "اونٹ" ... false
+Sys.file_exists "اونٹ-1" ... true
+Sys.rename "اونٹ-1" "اونٹ" ... OK
+Sys.file_exists "اونٹ" ... true
+Sys.file_exists "اونٹ-1" ... false
+Sys.rename "Lạc đà" "Lạc đà-1" ... OK
+Sys.file_exists "Lạc đà" ... false
+Sys.file_exists "Lạc đà-1" ... true
+Sys.rename "Lạc đà-1" "Lạc đà" ... OK
+Sys.file_exists "Lạc đà" ... true
+Sys.file_exists "Lạc đà-1" ... false
+Sys.rename "ఒంటె" "ఒంటె-1" ... OK
+Sys.file_exists "ఒంటె" ... false
+Sys.file_exists "ఒంటె-1" ... true
+Sys.rename "ఒంటె-1" "ఒంటె" ... OK
+Sys.file_exists "ఒంటె" ... true
+Sys.file_exists "ఒంటె-1" ... false
+Sys.rename "ஒட்டகம்" "ஒட்டகம்-1" ... OK
+Sys.file_exists "ஒட்டகம்" ... false
+Sys.file_exists "ஒட்டகம்-1" ... true
+Sys.rename "ஒட்டகம்-1" "ஒட்டகம்" ... OK
+Sys.file_exists "ஒட்டகம்" ... true
+Sys.file_exists "ஒட்டகம்-1" ... false
+Sys.rename "وشتر" "وشتر-1" ... OK
+Sys.file_exists "وشتر" ... false
+Sys.file_exists "وشتر-1" ... true
+Sys.rename "وشتر-1" "وشتر" ... OK
+Sys.file_exists "وشتر" ... true
+Sys.file_exists "وشتر-1" ... false
+Sys.rename "उष्ट्रः" "उष्ट्रः-1" ... OK
+Sys.file_exists "उष्ट्रः" ... false
+Sys.file_exists "उष्ट्रः-1" ... true
+Sys.rename "उष्ट्रः-1" "उष्ट्रः" ... OK
+Sys.file_exists "उष्ट्रः" ... true
+Sys.file_exists "उष्ट्रः-1" ... false
+Sys.rename "اٺ" "اٺ-1" ... OK
+Sys.file_exists "اٺ" ... false
+Sys.file_exists "اٺ-1" ... true
+Sys.rename "اٺ-1" "اٺ" ... OK
+Sys.file_exists "اٺ" ... true
+Sys.file_exists "اٺ-1" ... false
+
+#10. Testing test_remove remove
+==========================
+
+Sys.remove "верблюды" ... OK
+Sys.file_exists "верблюды" ... false
+Sys.remove "骆驼" ... OK
+Sys.file_exists "骆驼" ... false
+Sys.remove "קעמל" ... OK
+Sys.file_exists "קעמל" ... false
+Sys.remove "اونٹ" ... OK
+Sys.file_exists "اونٹ" ... false
+Sys.remove "Lạc đà" ... OK
+Sys.file_exists "Lạc đà" ... false
+Sys.remove "ఒంటె" ... OK
+Sys.file_exists "ఒంటె" ... false
+Sys.remove "ஒட்டகம்" ... OK
+Sys.file_exists "ஒட்டகம்" ... false
+Sys.remove "وشتر" ... OK
+Sys.file_exists "وشتر" ... false
+Sys.remove "उष्ट्रः" ... OK
+Sys.file_exists "उष्ट्रः" ... false
+Sys.remove "اٺ" ... OK
+Sys.file_exists "اٺ" ... false
+
+#11. Testing test_file_exists
+========================
+
+Sys.file_exists "верблюды" ... false
+Sys.file_exists "骆驼" ... false
+Sys.file_exists "קעמל" ... false
+Sys.file_exists "اونٹ" ... false
+Sys.file_exists "Lạc đà" ... false
+Sys.file_exists "ఒంటె" ... false
+Sys.file_exists "ஒட்டகம்" ... false
+Sys.file_exists "وشتر" ... false
+Sys.file_exists "उष्ट्रः" ... false
+Sys.file_exists "اٺ" ... false
+
+#12. Testing test_mkdir
+==================
+
+Unix.mkdir "été" 493 ... OK
+Sys.file_exists "été" ... true
+Sys.is_directory "été" ... true
+Unix.mkdir "simple" 493 ... OK
+Sys.file_exists "simple" ... true
+Sys.is_directory "simple" ... true
+Unix.mkdir "sœur" 493 ... OK
+Sys.file_exists "sœur" ... true
+Sys.is_directory "sœur" ... true
+Unix.mkdir "你好" 493 ... OK
+Sys.file_exists "你好" ... true
+Sys.is_directory "你好" ... true
+
+#13. Testing test_chdir sys_chdir sys_getcwd
+=======================================
+
+Sys.chdir "été" ... OK
+Sys.getcwd () ... "été"
+Sys.chdir ".." ... OK
+Sys.chdir "simple" ... OK
+Sys.getcwd () ... "simple"
+Sys.chdir ".." ... OK
+Sys.chdir "sœur" ... OK
+Sys.getcwd () ... "sœur"
+Sys.chdir ".." ... OK
+Sys.chdir "你好" ... OK
+Sys.getcwd () ... "你好"
+Sys.chdir ".." ... OK
+
+#14. Testing test_chdir unix_chdir unix_getcwd
+=========================================
+
+Unix.chdir "été" ... OK
+Unix.getcwd () ... "été"
+Unix.chdir ".." ... OK
+Unix.chdir "simple" ... OK
+Unix.getcwd () ... "simple"
+Unix.chdir ".." ... OK
+Unix.chdir "sœur" ... OK
+Unix.getcwd () ... "sœur"
+Unix.chdir ".." ... OK
+Unix.chdir "你好" ... OK
+Unix.getcwd () ... "你好"
+Unix.chdir ".." ... OK
+
+#15. Testing test_rmdir
+==================
+
+Unix.rmdir "été" ... OK
+Sys.file_exists "été" ... false
+Unix.rmdir "simple" ... OK
+Sys.file_exists "simple" ... false
+Unix.rmdir "sœur" ... OK
+Sys.file_exists "sœur" ... false
+Unix.rmdir "你好" ... OK
+Sys.file_exists "你好" ... false
+
+#16. Testing test_getenv
+===================
+
+Unix.putenv "été" "верблюды" ... OK
+Sys.getenv "été" ... "верблюды"
+Unix.environment "été" ... "верблюды"
+Unix.putenv "simple" "骆驼" ... OK
+Sys.getenv "simple" ... "骆驼"
+Unix.environment "simple" ... "骆驼"
+Unix.putenv "sœur" "קעמל" ... OK
+Sys.getenv "sœur" ... "קעמל"
+Unix.environment "sœur" ... "קעמל"
+Unix.putenv "你好" "اونٹ" ... OK
+Sys.getenv "你好" ... "اونٹ"
+Unix.environment "你好" ... "اونٹ"
+
+#17. Testing test_open_process_in
+============================
+
+Unix.open_process_in ... ... "верблюды" "骆驼" "קעמל" "اونٹ" "Lạc đà" "ఒంటె" "ஒட்டகம்" "وشتر" "उष्ट्रः" "اٺ"
+
+#18. Testing test_open_process_full
+==============================
+
+Unix.open_process_full ... "OCAML_UTF8_VAR0=верблюды" "OCAML_UTF8_VAR1=骆驼" "OCAML_UTF8_VAR2=קעמל" "OCAML_UTF8_VAR3=اونٹ" ... "OCAML_UTF8_VAR0=верблюды" "OCAML_UTF8_VAR1=骆驼" "OCAML_UTF8_VAR2=קעמל" "OCAML_UTF8_VAR3=اونٹ"
+
+
+*** ALL TESTS DONE (207/207 OK) ***
--- /dev/null
+#include <stdio.h>
+#include <locale.h>
+#include <assert.h>
+
+#include <Windows.h>
+
+int wmain(int argc, wchar_t ** argv)
+{
+ int len;
+ char * p;
+
+ int i;
+ for (i = 0; i < argc; i ++) {
+ /* printf("%S\n", argv[i]); */
+ len = WideCharToMultiByte(CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL);
+ assert(len != 0);
+ p = malloc(len);
+ len = WideCharToMultiByte(CP_UTF8, 0, argv[i], -1, p, len, NULL, NULL);
+ assert(len != 0);
+ printf("%s\n", p);
+ free(p);
+ }
+ fflush(stdout);
+ return 0;
+}
--- /dev/null
+#include <stdio.h>
+#include <assert.h>
+
+#ifdef _WIN32
+
+#include <Windows.h>
+
+int wmain(int argc, char ** argv, wchar_t ** envp)
+{
+ wchar_t * p;
+ char * s;
+ int i = 0, len;
+ while (envp[i]) {
+ p = envp[i++];
+ len = WideCharToMultiByte(CP_UTF8, 0, p, -1, NULL, 0, NULL, NULL);
+ assert(len != 0);
+ s = malloc(len);
+ len = WideCharToMultiByte(CP_UTF8, 0, p, -1, s, len, NULL, NULL);
+ assert(len != 0);
+ printf("%s\n", s);
+ free(s);
+ }
+ return 0;
+}
+
+#else
+
+int main(int argc, char ** argv, char ** env)
+{
+ int i = 0;
+ while (env[i])
+ printf("%s\n", env[i++]);
+ return 0;
+}
+
+#endif
--- /dev/null
+external to_utf16 : string -> string = "caml_to_utf16"
+external create_file : string -> string -> unit = "caml_create_file"
+
+let foodir = "UNIQU\xE4\xBD\xA0\xE5\xA5\xBD" (* "UNIQU你好" *)
+let foofile = "UNIQU\xE4\xBD\xA0\xE5\xA5\xBD/\xE4\xBD\xA0\xE5\xA5\xBD.txt" (* "UNIQU你好/你好.txt" *)
+let foofile2 = "UNIQU\xE4\xBD\xA0\xE5\xA5\xBD\\\xE4\xBD\xA0\xE5\xA5\xBD.txt" (* "UNIQU你好\\你好.txt" *)
+let fileln = "\xE4\xBD\xA0\xE5\xA5\xBD-file-ln-s" (* "你好-file-ln-s" *)
+let dirln = "\xE4\xBD\xA0\xE5\xA5\xBD-dir-ln-s" (* "你好-dir-ln-s" *)
+
+open Unix
+
+let () =
+ mkdir foodir 0o777;
+ create_file (to_utf16 foofile) foofile;
+ symlink ~to_dir:true foodir dirln;
+ symlink ~to_dir:false (if Sys.win32 then foofile2 else foofile) fileln; (* workaround MPR#7564 *)
+ assert ((stat fileln).st_kind = S_REG);
+ assert ((stat dirln).st_kind = S_DIR);
+ assert ((lstat fileln).st_kind = S_LNK);
+ assert ((lstat dirln).st_kind = S_LNK);
+ Sys.remove foofile;
+ Sys.remove fileln;
+ rmdir dirln;
+ rmdir foodir
+
+let () =
+ print_endline "OK."
Format.fprintf ppf "Line _";
if startchar >= 0 then
Format.fprintf ppf ", characters %d-%d" startchar endchar;
- Format.fprintf ppf ":@."
-
- let rec error_reporter ppf ({loc; msg; sub; if_highlight=_} : Location.error)=
- print_loc ppf loc;
- Format.fprintf ppf "%a %s" Location.print_error_prefix () msg;
- List.iter sub ~f:(fun err ->
- Format.fprintf ppf "@\n@[<2>%a@]" error_reporter err)
-
- let warning_printer loc ppf w =
- if Warnings.is_active w then begin
- print_loc ppf loc;
- Format.fprintf ppf "Warning %a@." Warnings.print w
- end
+ Format.fprintf ppf ":@,"
let capture ppf ~f =
Misc.protect_refs
- [ R (Location.formatter_for_warnings , ppf )
- ; R (Location.warning_printer , warning_printer)
- ; R (Location.error_reporter , error_reporter )
+ [ R (Location.formatter_for_warnings , ppf)
+ ; R (Location.printer , print_loc)
]
f
end
let collect_formatters buf pps ~f =
+ let ppb = Format.formatter_of_buffer buf in
+ let out_functions = Format.pp_get_formatter_out_functions ppb () in
+
List.iter (fun pp -> Format.pp_print_flush pp ()) pps;
let save =
List.map (fun pp -> Format.pp_get_formatter_out_functions pp ()) pps
Format.pp_set_formatter_out_functions pp out_functions)
pps save
in
- let out_string str ofs len = Buffer.add_substring buf str ofs len
- and out_flush = ignore
- and out_newline () = Buffer.add_char buf '\n'
- and out_spaces n = for i = 1 to n do Buffer.add_char buf ' ' done in
- let out_functions =
- { Format.out_string; out_flush; out_newline; out_spaces }
- in
List.iter
(fun pp -> Format.pp_set_formatter_out_functions pp out_functions)
pps;
options are:"
let () =
+ Clflags.error_size := 0;
try
Arg.parse args main usage;
Printf.eprintf "expect_test: no input file\n";
ocaml299to3.cmx :
ocamlcp.cmo : ../driver/main_args.cmi
ocamlcp.cmx : ../driver/main_args.cmx
-ocamldep.cmo : ../driver/pparse.cmi ../parsing/parsetree.cmi \
- ../parsing/parser.cmi ../parsing/parse.cmi ../utils/misc.cmi \
- ../parsing/longident.cmi ../parsing/location.cmi ../parsing/lexer.cmi \
- ../parsing/depend.cmi ../utils/config.cmi ../driver/compplugin.cmi \
- ../driver/compenv.cmi ../utils/clflags.cmi
-ocamldep.cmx : ../driver/pparse.cmx ../parsing/parsetree.cmi \
- ../parsing/parser.cmx ../parsing/parse.cmx ../utils/misc.cmx \
- ../parsing/longident.cmx ../parsing/location.cmx ../parsing/lexer.cmx \
- ../parsing/depend.cmx ../utils/config.cmx ../driver/compplugin.cmx \
- ../driver/compenv.cmx ../utils/clflags.cmx
+ocamldep.cmo : ../driver/makedepend.cmi
+ocamldep.cmx : ../driver/makedepend.cmx
ocamlmklib.cmo : ocamlmklibconfig.cmo ../utils/misc.cmi ../utils/config.cmi
ocamlmklib.cmx : ocamlmklibconfig.cmx ../utils/misc.cmx ../utils/config.cmx
ocamlmklibconfig.cmo :
profiling.cmo : profiling.cmi
profiling.cmx : profiling.cmi
profiling.cmi :
-read_cmt.cmo : ../typing/cmt_format.cmi cmt2annot.cmo ../utils/clflags.cmi
-read_cmt.cmx : ../typing/cmt_format.cmx cmt2annot.cmx ../utils/clflags.cmx
+read_cmt.cmo : ../parsing/location.cmi ../driver/compmisc.cmi \
+ ../typing/cmt_format.cmi cmt2annot.cmo ../utils/clflags.cmi
+read_cmt.cmx : ../parsing/location.cmx ../driver/compmisc.cmx \
+ ../typing/cmt_format.cmx cmt2annot.cmx ../utils/clflags.cmx
scrapelabels.cmo :
scrapelabels.cmx :
stripdebug.cmo : ../utils/misc.cmi ../bytecomp/bytesections.cmi
$(call byte_and_opt,ocamlprof,$(CSLPROF_IMPORTS) profiling.cmo $(CSLPROF),)
-ocamlcp_cmos = misc.cmo warnings.cmo config.cmo identifiable.cmo numbers.cmo \
- arg_helper.cmo clflags.cmo main_args.cmo
+ocamlcp_cmos = misc.cmo profile.cmo warnings.cmo config.cmo identifiable.cmo \
+ numbers.cmo arg_helper.cmo clflags.cmo main_args.cmo
$(call byte_and_opt,ocamlcp,$(ocamlcp_cmos) ocamlcp.cmo,)
$(call byte_and_opt,ocamloptp,$(ocamlcp_cmos) ocamloptp.cmo,)
ocamlmklibconfig.ml: ../config/Makefile Makefile
(echo 'let bindir = "$(BINDIR)"'; \
echo 'let supports_shared_libraries = $(SUPPORTS_SHARED_LIBRARIES)';\
- echo 'let byteccrpath = "$(BYTECCRPATH)"'; \
- echo 'let nativeccrpath = "$(NATIVECCRPATH)"'; \
+ echo 'let default_rpath = "$(RPATH)"'; \
echo 'let mksharedlibrpath = "$(MKSHAREDLIBRPATH)"'; \
echo 'let toolpref = "$(TOOLPREF)"'; \
sed -n -e 's/^#ml //p' ../config/Makefile) \
# Reading cmt files
$(call byte_and_opt,read_cmt,$(READ_CMT),)
+install::
+ if test -f read_cmt.opt; then \
+ cp read_cmt.opt "$(INSTALL_BINDIR)/ocamlcmt$(EXE)"; \
+ else \
+ cp read_cmt "$(INSTALL_BINDIR)/ocamlcmt$(EXE)"; \
+ fi
+
# The bytecode disassembler
DEF_SYMBOL_PREFIX = '-Dsymbol_prefix=""'
endif
-ifeq "$(CCOMPTYPE)" "msvc"
-CCOUT = -Fe
-else
-EMPTY =
-CCOUT = -o $(EMPTY)
-endif
-
-objinfo_helper$(EXE): objinfo_helper.c ../config/s.h
- $(BYTECC) $(CCOUT)objinfo_helper$(EXE) $(BYTECCCOMPOPTS) \
- $(DEF_SYMBOL_PREFIX) $(LIBBFD_INCLUDE) objinfo_helper.c $(LIBBFD_LINK)
+objinfo_helper$(EXE): objinfo_helper.c ../byterun/caml/s.h
+ $(CC) $(CFLAGS) $(CPPFLAGS) -I../byterun $(OUTPUTEXE)$@ \
+ $(DEF_SYMBOL_PREFIX) $(LIBBFD_INCLUDE) $< $(LIBBFD_LINK)
OBJINFO=../compilerlibs/ocamlcommon.cma \
../compilerlibs/ocamlbytecomp.cma \
--- /dev/null
+#!/bin/bash
+
+#**************************************************************************
+#* *
+#* OCaml *
+#* *
+#* Stephen Dolan, University of Cambridge *
+#* *
+#* Copyright 2016 Stephen Dolan. *
+#* *
+#* All rights reserved. This file is distributed under the terms of *
+#* the GNU Lesser General Public License version 2.1, with the *
+#* special exception on linking described in the file LICENSE. *
+#* *
+#**************************************************************************
+
+set -o pipefail
+
+[ -z "$*" ] && { echo "Usage: $0 libfoo.a" 1>&2; exit 2; }
+
+nm -A -P "$@" | awk '
+# ignore caml_foo, camlFoo_bar, _caml_foo, _camlFoo_bar
+$2 ~ /^(_?caml[_A-Z])/ { next }
+# ignore local and undefined symbols
+$3 ~ /^[rbdtsU]$/ { next }
+# ignore "main", which should be externally linked
+$2 ~ /^_?main$/ { next }
+# print the rest
+{ found=1; print $1 " " $2 " " $3 }
+# fail if there were any results
+END { exit found ? 1 : 0 }
+'
+exit $?
(cat "$f" | tr -d '\r'; echo) \
| awk -v rules="$rules" -v svnrules="$svnrules" -v file="$f" \
'
+ function is_err(name) {
+ return (("," rules svnrules ",") !~ ("[, ]" name "[, ]"));
+ }
+
function err(name, msg) {
++ counts[name];
- if (("," rules svnrules ",") !~ ("[, ]" name "[, ]") \
- && counts[name] <= 10){
+ if (is_err(name) && counts[name] <= 10){
printf ("%s:%d.%d:", file, NR, RSTART + RLENGTH);
printf (" [%s] %s\n", name, msg);
got_errors = 1;
}
}
- match($0, /[\200-\377]/) {
+ match($0, /[\200-\377]/) \
+ && state != "authors" && state != "copyright" {
err("non-ascii", "non-ASCII character(s)");
+ if (header_utf8 && !is_err("non-ascii")) {
+ err("non-ascii-utf8", \
+ "non-ASCII character(s) AND UTF-8 encountered");
+ }
}
match($0, /[^\t\200-\377 -~]/) {
}
$0 !~ /\t/ && length($0) > 80 {
- RSTART = 81;
- RLENGTH = 0;
- err("long-line", "line is over 80 columns");
+ t = $0;
+ sub(/https?:[A-Za-z0-9._~:/?#\[\]@!$&\047()*+,;=%-]{73,}$/, "", t);
+ if (length(t) > 80) {
+ RSTART = 81;
+ RLENGTH = 0;
+ err("long-line", "line is over 80 columns");
+ }
}
$0 !~ /\t/ && length($0) > 132 {
err("very-long-line", "line is over 132 columns");
}
+ # Record that the header contained UTF-8 sequences
+ match($0, /[\300-\367][\200-\277]+/) \
+ && (state == "authors" || state == "copyright") {
+ header_utf8 = 1;
+ if (counts["non-ascii"] > 0 && is_err("non-ascii")) {
+ err("non-ascii-utf8", \
+ "non-ASCII character(s) AND UTF-8 encountered");
+ }
+ }
+
# Header-recognition automaton. Read this from bottom to top.
+ # Valid UTF-8 chars are recognised in copyright and authors
+ # TODO: ensure all files are valid UTF-8 before awking them.
+ # Note that this code also assumes that combining characters are NOT
+ # used (i.e. that every Unicode code-point corresponds to exactly
+ # one displayed character, i.e. no Camels and no including
+ # weird-and-wonderful ways of encoded accented letters).
state == "close" && $0 ~ /\*{74}/ { state = "OK"; }
state == "close" { state = "(last line)"; }
{ state = "blurb"; }
state == "blurb1" { state = "(blurb line 1)"; }
state == "copyright" && $0 ~ /\* {72}\*/ { state = "blurb1"; }
- state == "copyright" && $0 !~ /\* Copyright [0-9]{4}.{54} \*/ \
- && $0 !~ /\* .{66} \*/ \
+ state == "copyright" \
+ && $0 !~ /\* Copyright [0-9]{4}([\300-\367][\200-\277]+|.){54} \*/ \
+ && $0 !~ /\* ([\300-\367][\200-\277]+|.){66} \*/ \
{ state = "(copyright lines)"; }
state == "authors" && $0 ~ /\* {72}\*/ { state = "copyright"; }
- state == "authors" && $0 !~ /\* .{70} \*/ { state = "(authors)"; }
+ state == "authors" \
+ && $0 !~ /\* ([\300-\367][\200-\277]+|.){70} \*/ \
+ { state = "(authors)"; }
state == "blank2" && $0 ~ /\* {72}\*/ { state = "authors"; }
state == "blank2" { state = "(blank line 2)"; }
state == "title" && $0 ~ /\* {33}OCaml {34}\*/ { state = "blank2"; }
# in Jenkins at the following address:
# https://ci.inria.fr/ocaml/computer/NODE/configure
-# arguments:
+# Other environments variables that are honored:
+# OCAML_CONFIGURE_OPTIONS additional options for configure
+# OCAML_JOBS number of jobs to run in parallel (make -j)
+
+# Command-line arguments:
# -conf configure-option add configure-option to configure cmd line
# -patch1 file-name apply patch with -p1
# -no-native do not build "opt" and "opt.opt"
+# -jNN pass "-jNN" option to make for parallel builds
error () {
echo "$1" >&2
#########################################################################
+# be considerate towards other potential users of the test machine
+case "${OCAML_ARCH}" in
+ bsd|macos|linux) renice 10 $$ ;;
+esac
+
# be verbose and stop on error
set -ex
confoptions="${OCAML_CONFIGURE_OPTIONS}"
make_native=true
cleanup=false
+check_make_alldepend=false
+dorebase=false
+jobs=''
case "${OCAML_ARCH}" in
bsd) make=gmake ;;
macos) ;;
linux)
confoptions="${confoptions} -with-instrumented-runtime"
+ check_make_alldepend=true
;;
cygwin)
- cleanup=true;;
+ cleanup=true
+ check_make_alldepend=true
+ dorebase=true
+ ;;
mingw)
instdir='C:/ocamlmgw'
configure=nt
cleanup=true
+ check_make_alldepend=true
;;
mingw64)
instdir='C:/ocamlmgw64'
configure=nt
cleanup=true
+ check_make_alldepend=true
;;
msvc)
instdir='C:/ocamlms'
# Make sure two builds won't use the same install directory
instdir="$instdir-$$"
+case "${OCAML_JOBS}" in
+ [1-9]|[1-9][0-9]) jobs="-j${OCAML_JOBS}" ;;
+esac
+
#########################################################################
# On Windows, cleanup processes that may remain from previous run
-conf) confoptions="$confoptions `quote1 "$2"`"; shift;;
-patch1) patch -f -p1 <"$2"; shift;;
-no-native) make_native=false;;
+ -j[1-9]|-j[1-9][0-9]) jobs="$1";;
*) error "unknown option $1";;
esac
shift
# Tell gcc to use only ASCII in its diagnostic outputs.
export LC_ALL=C
-$make distclean || :
+$make -s distclean || :
# `make distclean` does not clean the files from previous versions that
# are not produced by the current version, so use `git clean` in addition.
eval "./configure -prefix '$instdir' $confoptions"
;;
nt)
- cp config/m-nt.h config/m.h
- cp config/s-nt.h config/s.h
+ cp config/m-nt.h byterun/caml/m.h
+ cp config/s-nt.h byterun/caml/s.h
cp config/Makefile.${OCAML_ARCH} config/Makefile
sed -i "s%PREFIX=\(.\+\)%PREFIX=${instdir}%" config/Makefile
sed -i 's%RUNTIMED=.\+%RUNTIMED=true%' config/Makefile
*) error "internal error";;
esac
-$make coldstart
-$make core
-$make coreboot
-$make world
+$make $jobs coldstart
+$make $jobs core
+$make $jobs coreboot
+$make $jobs world
if $make_native; then
- $make opt
- $make opt.opt
+ $make $jobs opt
+ $make $jobs opt.opt
+ if $check_make_alldepend; then $make alldepend; fi
+fi
+if $dorebase; then
+ # temporary solution to the cygwin fork problem
+ rebase -b 0x7cd20000 otherlibs/unix/dllunix.so
+ rebase -b 0x7cdc0000 otherlibs/systhreads/dllthreads.so
fi
$make install
--- /dev/null
+#!/bin/sh
+#**************************************************************************
+#* *
+#* OCaml *
+#* *
+#* Sebastien Hinderer, projet Gallium, INRIA Paris *
+#* *
+#* Copyright 2017 Institut National de Recherche en Informatique et *
+#* en Automatique. *
+#* *
+#* All rights reserved. This file is distributed under the terms of *
+#* the GNU Lesser General Public License version 2.1, with the *
+#* special exception on linking described in the file LICENSE. *
+#* *
+#**************************************************************************
+
+# Commands to run for the 'other-configs' job on Inria's CI
+
+./tools/ci-build -conf -no-native-compiler -no-native
+./tools/ci-build -conf -no-naked-pointers
+./tools/ci-build -conf -flambda -conf -no-naked-pointers
+++ /dev/null
-#!/bin/sed -f
-
-#**************************************************************************
-#* *
-#* OCaml *
-#* *
-#* Xavier Leroy, projet Cristal, INRIA Rocquencourt *
-#* *
-#* Copyright 2002 Institut National de Recherche en Informatique et *
-#* en Automatique. *
-#* *
-#* All rights reserved. This file is distributed under the terms of *
-#* the GNU Lesser General Public License version 2.1, with the *
-#* special exception on linking described in the file LICENSE. *
-#* *
-#**************************************************************************
-
-# Remove private parts from runtime include files, before installation
-# in /usr/local/lib/ocaml/caml
-
-/\/\* <include \.\.\/config\/m\.h> \*\// {
- r ../config/m.h
- d
-}
-/\/\* <include \.\.\/config\/s\.h> \*\// {
- r ../config/s.h
- d
-}
-/\/\* <private> \*\//,/\/\* <\/private> \*\//d
Annot.Idef scope))
| _ -> ()
end;
- super.pat sub p;
+ super.pat sub p
in
{super with pat}
)
l
+let record_module_binding scope mb =
+ Stypes.record (Stypes.An_ident
+ (mb.mb_name.loc,
+ mb.mb_name.txt,
+ Annot.Idef scope))
+
let rec iterator ~scope rebuild_env =
let super = Tast_mapper.default in
let class_expr sub node =
| Texp_function { cases = f; }
| Texp_try (_, f) ->
bind_cases f
+ | Texp_letmodule (_, modname, _, body ) ->
+ Stypes.record (Stypes.An_ident
+ (modname.loc,modname.txt,Annot.Idef body.exp_loc))
| _ -> ()
end;
Stypes.record (Stypes.Ti_expr exp);
super.pat sub p
in
- let structure_item_rem sub s rem =
- begin match s with
- | {str_desc = Tstr_value (rec_flag, bindings); str_loc = loc} ->
- let open Location in
+ let structure_item_rem sub str rem =
+ let open Location in
+ let loc = str.str_loc in
+ begin match str.str_desc with
+ | Tstr_value (rec_flag, bindings) ->
let doit loc_start = bind_bindings {scope with loc_start} bindings in
begin match rec_flag, rem with
| Recursive, _ -> doit loc.loc_start
| Nonrecursive, [] -> doit loc.loc_end
| Nonrecursive, {str_loc = loc2} :: _ -> doit loc2.loc_start
end
+ | Tstr_module mb ->
+ record_module_binding
+ { scope with Location.loc_start = loc.loc_end } mb
+ | Tstr_recmodule mbs ->
+ List.iter (record_module_binding
+ { scope with Location.loc_start = loc.loc_start }) mbs
| _ ->
()
end;
- Stypes.record_phrase s.str_loc;
- super.structure_item sub s
+ Stypes.record_phrase loc;
+ super.structure_item sub str
in
let structure_item sub s =
(* This will be used for Partial_structure_item.
| Partial_signature_item x -> app iter.signature_item x
| Partial_module_type x -> app iter.module_type x
-let gen_annot target_filename filename
- {Cmt_format.cmt_loadpath; cmt_annots; cmt_use_summaries; _} =
+(* Save cmt information as faked annotations, attached to
+ Location.none, on top of the .annot file. Only when -save-cmt-info is
+ provided to ocaml_cmt.
+*)
+let record_cmt_info cmt =
+ let location_none = {
+ Location.none with Location.loc_ghost = false }
+ in
+ let location_file file = {
+ Location.none with
+ Location.loc_start = {
+ Location.none.Location.loc_start with
+ Lexing.pos_fname = file }}
+ in
+ let record_info name value =
+ let ident = Printf.sprintf ".%s" name in
+ Stypes.record (Stypes.An_ident (location_none, ident,
+ Annot.Idef (location_file value)))
+ in
+ let open Cmt_format in
+ (* record in reverse order to get them in correct order... *)
+ List.iter (fun dir -> record_info "include" dir) (List.rev cmt.cmt_loadpath);
+ record_info "chdir" cmt.cmt_builddir;
+ (match cmt.cmt_sourcefile with
+ None -> () | Some file -> record_info "source" file)
+
+let gen_annot ?(save_cmt_info=false) target_filename filename cmt =
let open Cmt_format in
Envaux.reset_cache ();
- Config.load_path := cmt_loadpath;
+ Config.load_path := cmt.cmt_loadpath @ !Config.load_path;
let target_filename =
match target_filename with
| None -> Some (filename ^ ".annot")
| Some "-" -> None
| Some _ -> target_filename
in
- let iterator = iterator ~scope:Location.none cmt_use_summaries in
- match cmt_annots with
+ if save_cmt_info then record_cmt_info cmt;
+ let iterator = iterator ~scope:Location.none cmt.cmt_use_summaries in
+ match cmt.cmt_annots with
| Implementation typedtree ->
ignore (iterator.structure iterator typedtree);
Stypes.dump target_filename
| Partial_implementation parts ->
Array.iter (binary_part iterator) parts;
Stypes.dump target_filename
- | _ ->
+ | Packed _ ->
+ Printf.fprintf stderr "Packed files not yet supported\n%!";
+ Stypes.dump target_filename
+ | Partial_interface _ ->
Printf.fprintf stderr "File was generated with an error\n%!";
exit 2
-
-
let gen_ml target_filename filename cmt =
let (printer, ext) =
match cmt.Cmt_format.cmt_annots with
| Cmt_format.Implementation typedtree ->
- (fun ppf -> Pprintast.structure ppf
+ (fun ppf -> Pprintast.structure ppf
(Untypeast.untype_structure typedtree)),
- ".ml"
+ ".ml"
| Cmt_format.Interface typedtree ->
- (fun ppf -> Pprintast.signature ppf
+ (fun ppf -> Pprintast.signature ppf
(Untypeast.untype_signature typedtree)),
- ".mli"
+ ".mli"
| _ ->
Printf.fprintf stderr "File was generated with an error\n%!";
- exit 2
+ exit 2
in
let target_filename = match target_filename with
None -> Some (filename ^ ext)
else if tag = Obj.double_tag then
printf "%.12g" (Obj.magic x : float)
else if tag = Obj.double_array_tag then begin
- let a = (Obj.magic x : float array) in
+ let a = (Obj.magic x : floatarray) in
printf "[|";
- for i = 0 to Array.length a - 1 do
+ for i = 0 to Array.Floatarray.length a - 1 do
if i > 0 then printf ", ";
- printf "%.12g" a.(i)
+ printf "%.12g" (Array.Floatarray.get a i)
done;
printf "|]"
end else if tag = Obj.custom_tag && same_custom x 0l then
(* *)
(* OCaml *)
(* *)
+(* Edwin Török *)
+(* *)
(* Copyright 2016--2017 Edwin Török *)
(* *)
(* All rights reserved. This file is distributed under the terms of *)
-(***********************************************************************)
-(* *)
-(* OCaml *)
-(* *)
-(* Nicolas Ojeda Bar, LexiFi *)
-(* *)
-(* Copyright 2016 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. *)
-(* *)
-(***********************************************************************)
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Nicolas Ojeda Bar, LexiFi *)
+(* *)
+(* Copyright 2016 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
let ident = ['a'-'z''A'-'Z''_']['a'-'z''A'-'Z''0'-'9''_']*
let space = [' ''\n''\r''\t']*
/* */
/**************************************************************************/
-#include "../config/s.h"
+#include "caml/s.h"
#include <stdio.h>
#ifdef HAS_LIBBFD
let _dflambda = option "-dflambda"
let _dinstr = option "-dinstr"
let _dtimings = option "-dtimings"
+ let _dprofile = option "-dprofile"
let _args = Arg.read_arg
let _args0 = Arg.read_arg0
let anonymous = process_file
-(**************************************************************************)
-(* *)
-(* OCaml *)
-(* *)
-(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
-(* *)
-(* Copyright 1999 Institut National de Recherche en Informatique et *)
-(* en Automatique. *)
-(* *)
-(* All rights reserved. This file is distributed under the terms of *)
-(* the GNU Lesser General Public License version 2.1, with the *)
-(* special exception on linking described in the file LICENSE. *)
-(* *)
-(**************************************************************************)
-
-open Compenv
-open Parsetree
-module StringMap = Depend.StringMap
-
-let ppf = Format.err_formatter
-(* Print the dependencies *)
-
-type file_kind = ML | MLI;;
-
-let load_path = ref ([] : (string * string array) list)
-let ml_synonyms = ref [".ml"]
-let mli_synonyms = ref [".mli"]
-let native_only = ref false
-let bytecode_only = ref false
-let error_occurred = ref false
-let raw_dependencies = ref false
-let sort_files = ref false
-let all_dependencies = ref false
-let one_line = ref false
-let files = ref []
-let allow_approximation = ref false
-let map_files = ref []
-let module_map = ref StringMap.empty
-let debug = ref false
-
-(* Fix path to use '/' as directory separator instead of '\'.
- Only under Windows. *)
-
-let fix_slash s =
- if Sys.os_type = "Unix" then s else begin
- String.map (function '\\' -> '/' | c -> c) s
- end
-
-(* Since we reinitialize load_path after reading OCAMLCOMP,
- we must use a cache instead of calling Sys.readdir too often. *)
-let dirs = ref StringMap.empty
-let readdir dir =
- try
- StringMap.find dir !dirs
- with Not_found ->
- let contents =
- try
- Sys.readdir dir
- with Sys_error msg ->
- Format.fprintf Format.err_formatter "@[Bad -I option: %s@]@." msg;
- error_occurred := true;
- [||]
- in
- dirs := StringMap.add dir contents !dirs;
- contents
-
-let add_to_list li s =
- li := s :: !li
-
-let add_to_load_path dir =
- try
- let dir = Misc.expand_directory Config.standard_library dir in
- let contents = readdir dir in
- add_to_list load_path (dir, contents)
- with Sys_error msg ->
- Format.fprintf Format.err_formatter "@[Bad -I option: %s@]@." msg;
- error_occurred := true
-
-let add_to_synonym_list synonyms suffix =
- if (String.length suffix) > 1 && suffix.[0] = '.' then
- add_to_list synonyms suffix
- else begin
- Format.fprintf Format.err_formatter "@[Bad suffix: '%s'@]@." suffix;
- error_occurred := true
- end
-
-(* Find file 'name' (capitalized) in search path *)
-let find_file name =
- let uname = String.uncapitalize_ascii name in
- let rec find_in_array a pos =
- if pos >= Array.length a then None else begin
- let s = a.(pos) in
- if s = name || s = uname then Some s else find_in_array a (pos + 1)
- end in
- let rec find_in_path = function
- [] -> raise Not_found
- | (dir, contents) :: rem ->
- match find_in_array contents 0 with
- Some truename ->
- if dir = "." then truename else Filename.concat dir truename
- | None -> find_in_path rem in
- find_in_path !load_path
-
-let rec find_file_in_list = function
- [] -> raise Not_found
-| x :: rem -> try find_file x with Not_found -> find_file_in_list rem
-
-
-let find_dependency target_kind modname (byt_deps, opt_deps) =
- try
- let candidates = List.map ((^) modname) !mli_synonyms in
- let filename = find_file_in_list candidates in
- let basename = Filename.chop_extension filename in
- let cmi_file = basename ^ ".cmi" in
- let cmx_file = basename ^ ".cmx" in
- let ml_exists =
- List.exists (fun ext -> Sys.file_exists (basename ^ ext)) !ml_synonyms in
- let new_opt_dep =
- if !all_dependencies then
- match target_kind with
- | MLI -> [ cmi_file ]
- | ML ->
- cmi_file :: (if ml_exists then [ cmx_file ] else [])
- else
- (* this is a make-specific hack that makes .cmx to be a 'proxy'
- target that would force the dependency on .cmi via transitivity *)
- if ml_exists
- then [ cmx_file ]
- else [ cmi_file ]
- in
- ( cmi_file :: byt_deps, new_opt_dep @ opt_deps)
- with Not_found ->
- try
- (* "just .ml" case *)
- let candidates = List.map ((^) modname) !ml_synonyms in
- let filename = find_file_in_list candidates in
- let basename = Filename.chop_extension filename in
- let cmi_file = basename ^ ".cmi" in
- let cmx_file = basename ^ ".cmx" in
- let bytenames =
- if !all_dependencies then
- match target_kind with
- | MLI -> [ cmi_file ]
- | ML -> [ cmi_file ]
- else
- (* again, make-specific hack *)
- [basename ^ (if !native_only then ".cmx" else ".cmo")] in
- let optnames =
- if !all_dependencies
- then match target_kind with
- | MLI -> [ cmi_file ]
- | ML -> [ cmi_file; cmx_file ]
- else [ cmx_file ]
- in
- (bytenames @ byt_deps, optnames @ opt_deps)
- with Not_found ->
- (byt_deps, opt_deps)
-
-let (depends_on, escaped_eol) = (":", " \\\n ")
-
-let print_filename s =
- let s = if !Clflags.force_slash then fix_slash s else s in
- if not (String.contains s ' ') then begin
- print_string s;
- end else begin
- let rec count n i =
- if i >= String.length s then n
- else if s.[i] = ' ' then count (n+1) (i+1)
- else count n (i+1)
- in
- let spaces = count 0 0 in
- let result = Bytes.create (String.length s + spaces) in
- let rec loop i j =
- if i >= String.length s then ()
- else if s.[i] = ' ' then begin
- Bytes.set result j '\\';
- Bytes.set result (j+1) ' ';
- loop (i+1) (j+2);
- end else begin
- Bytes.set result j s.[i];
- loop (i+1) (j+1);
- end
- in
- loop 0 0;
- print_bytes result;
- end
-;;
-
-let print_dependencies target_files deps =
- let rec print_items pos = function
- [] -> print_string "\n"
- | dep :: rem ->
- if !one_line || (pos + 1 + String.length dep <= 77) then begin
- if pos <> 0 then print_string " "; print_filename dep;
- print_items (pos + String.length dep + 1) rem
- end else begin
- print_string escaped_eol; print_filename dep;
- print_items (String.length dep + 4) rem
- end in
- print_items 0 (target_files @ [depends_on] @ deps)
-
-let print_raw_dependencies source_file deps =
- print_filename source_file; print_string depends_on;
- Depend.StringSet.iter
- (fun dep ->
- (* filter out "*predef*" *)
- if (String.length dep > 0)
- && (match dep.[0] with
- | 'A'..'Z' | '\128'..'\255' -> true
- | _ -> false) then
- begin
- print_char ' ';
- print_string dep
- end)
- deps;
- print_char '\n'
-
-
-(* Process one file *)
-
-let report_err exn =
- error_occurred := true;
- match exn with
- | Sys_error msg ->
- Format.fprintf Format.err_formatter "@[I/O error:@ %s@]@." msg
- | x ->
- match Location.error_of_exn x with
- | Some err ->
- Format.fprintf Format.err_formatter "@[%a@]@."
- Location.report_error err
- | None -> raise x
-
-let tool_name = "ocamldep"
-
-let rec lexical_approximation lexbuf =
- (* Approximation when a file can't be parsed.
- Heuristic:
- - first component of any path starting with an uppercase character is a
- dependency.
- - always skip the token after a dot, unless dot is preceded by a
- lower-case identifier
- - always skip the token after a backquote
- *)
- try
- let rec process after_lident lexbuf =
- match Lexer.token lexbuf with
- | Parser.UIDENT name ->
- Depend.free_structure_names :=
- Depend.StringSet.add name !Depend.free_structure_names;
- process false lexbuf
- | Parser.LIDENT _ -> process true lexbuf
- | Parser.DOT when after_lident -> process false lexbuf
- | Parser.DOT | Parser.BACKQUOTE -> skip_one lexbuf
- | Parser.EOF -> ()
- | _ -> process false lexbuf
- and skip_one lexbuf =
- match Lexer.token lexbuf with
- | Parser.DOT | Parser.BACKQUOTE -> skip_one lexbuf
- | Parser.EOF -> ()
- | _ -> process false lexbuf
-
- in
- process false lexbuf
- with Lexer.Error _ -> lexical_approximation lexbuf
-
-let read_and_approximate inputfile =
- error_occurred := false;
- Depend.free_structure_names := Depend.StringSet.empty;
- let ic = open_in_bin inputfile in
- try
- seek_in ic 0;
- Location.input_name := inputfile;
- let lexbuf = Lexing.from_channel ic in
- Location.init lexbuf inputfile;
- lexical_approximation lexbuf;
- close_in ic;
- !Depend.free_structure_names
- with exn ->
- close_in ic;
- report_err exn;
- !Depend.free_structure_names
-
-let read_parse_and_extract parse_function extract_function def ast_kind
- source_file =
- Depend.free_structure_names := Depend.StringSet.empty;
- try
- let input_file = Pparse.preprocess source_file in
- begin try
- let ast =
- Pparse.file ~tool_name Format.err_formatter
- input_file parse_function ast_kind
- in
- let bound_vars =
- List.fold_left
- (fun bv modname ->
- Depend.open_module bv (Longident.parse modname))
- !module_map ((* PR#7248 *) List.rev !Clflags.open_modules)
- in
- let r = extract_function bound_vars ast in
- Pparse.remove_preprocessed input_file;
- (!Depend.free_structure_names, r)
- with x ->
- Pparse.remove_preprocessed input_file;
- raise x
- end
- with x -> begin
- report_err x;
- if not !allow_approximation
- then (Depend.StringSet.empty, def)
- else (read_and_approximate source_file, def)
- end
-
-let print_ml_dependencies source_file extracted_deps =
- let basename = Filename.chop_extension source_file in
- let byte_targets = [ basename ^ ".cmo" ] in
- let native_targets =
- if !all_dependencies
- then [ basename ^ ".cmx"; basename ^ ".o" ]
- else [ basename ^ ".cmx" ] in
- let init_deps = if !all_dependencies then [source_file] else [] in
- let cmi_name = basename ^ ".cmi" in
- let init_deps, extra_targets =
- if List.exists (fun ext -> Sys.file_exists (basename ^ ext))
- !mli_synonyms
- then (cmi_name :: init_deps, cmi_name :: init_deps), []
- else (init_deps, init_deps),
- (if !all_dependencies then [cmi_name] else [])
- in
- let (byt_deps, native_deps) =
- Depend.StringSet.fold (find_dependency ML)
- extracted_deps init_deps in
- if not !native_only then
- print_dependencies (byte_targets @ extra_targets) byt_deps;
- if not !bytecode_only then
- print_dependencies (native_targets @ extra_targets) native_deps
-
-let print_mli_dependencies source_file extracted_deps =
- let basename = Filename.chop_extension source_file in
- let (byt_deps, _opt_deps) =
- Depend.StringSet.fold (find_dependency MLI)
- extracted_deps ([], []) in
- print_dependencies [basename ^ ".cmi"] byt_deps
-
-let print_file_dependencies (source_file, kind, extracted_deps) =
- if !raw_dependencies then begin
- print_raw_dependencies source_file extracted_deps
- end else
- match kind with
- | ML -> print_ml_dependencies source_file extracted_deps
- | MLI -> print_mli_dependencies source_file extracted_deps
-
-
-let ml_file_dependencies source_file =
- let parse_use_file_as_impl lexbuf =
- let f x =
- match x with
- | Ptop_def s -> s
- | Ptop_dir _ -> []
- in
- List.flatten (List.map f (Parse.use_file lexbuf))
- in
- let (extracted_deps, ()) =
- read_parse_and_extract parse_use_file_as_impl Depend.add_implementation ()
- Pparse.Structure source_file
- in
- files := (source_file, ML, extracted_deps) :: !files
-
-let mli_file_dependencies source_file =
- let (extracted_deps, ()) =
- read_parse_and_extract Parse.interface Depend.add_signature ()
- Pparse.Signature source_file
- in
- files := (source_file, MLI, extracted_deps) :: !files
-
-let process_file_as process_fun def source_file =
- Compenv.readenv ppf (Before_compile source_file);
- load_path := [];
- List.iter add_to_load_path (
- (!Compenv.last_include_dirs @
- !Clflags.include_dirs @
- !Compenv.first_include_dirs
- ));
- Location.input_name := source_file;
- try
- if Sys.file_exists source_file then process_fun source_file else def
- with x -> report_err x; def
-
-let process_file source_file ~ml_file ~mli_file ~def =
- if List.exists (Filename.check_suffix source_file) !ml_synonyms then
- process_file_as ml_file def source_file
- else if List.exists (Filename.check_suffix source_file) !mli_synonyms then
- process_file_as mli_file def source_file
- else def
-
-let file_dependencies source_file =
- process_file source_file ~def:()
- ~ml_file:ml_file_dependencies
- ~mli_file:mli_file_dependencies
-
-let file_dependencies_as kind =
- match kind with
- | ML -> process_file_as ml_file_dependencies ()
- | MLI -> process_file_as mli_file_dependencies ()
-
-let sort_files_by_dependencies files =
- let h = Hashtbl.create 31 in
- let worklist = ref [] in
-
-(* Init Hashtbl with all defined modules *)
- let files = List.map (fun (file, file_kind, deps) ->
- let modname =
- String.capitalize_ascii (Filename.chop_extension (Filename.basename file))
- in
- let key = (modname, file_kind) in
- let new_deps = ref [] in
- Hashtbl.add h key (file, new_deps);
- worklist := key :: !worklist;
- (modname, file_kind, deps, new_deps)
- ) files in
-
-(* Keep only dependencies to defined modules *)
- List.iter (fun (modname, file_kind, deps, new_deps) ->
- let add_dep modname kind =
- new_deps := (modname, kind) :: !new_deps;
- in
- Depend.StringSet.iter (fun modname ->
- match file_kind with
- ML -> (* ML depends both on ML and MLI *)
- if Hashtbl.mem h (modname, MLI) then add_dep modname MLI;
- if Hashtbl.mem h (modname, ML) then add_dep modname ML
- | MLI -> (* MLI depends on MLI if exists, or ML otherwise *)
- if Hashtbl.mem h (modname, MLI) then add_dep modname MLI
- else if Hashtbl.mem h (modname, ML) then add_dep modname ML
- ) deps;
- if file_kind = ML then (* add dep from .ml to .mli *)
- if Hashtbl.mem h (modname, MLI) then add_dep modname MLI
- ) files;
-
-(* Print and remove all files with no remaining dependency. Iterate
- until all files have been removed (worklist is empty) or
- no file was removed during a turn (cycle). *)
- let printed = ref true in
- while !printed && !worklist <> [] do
- let files = !worklist in
- worklist := [];
- printed := false;
- List.iter (fun key ->
- let (file, deps) = Hashtbl.find h key in
- let set = !deps in
- deps := [];
- List.iter (fun key ->
- if Hashtbl.mem h key then deps := key :: !deps
- ) set;
- if !deps = [] then begin
- printed := true;
- Printf.printf "%s " file;
- Hashtbl.remove h key;
- end else
- worklist := key :: !worklist
- ) files
- done;
-
- if !worklist <> [] then begin
- Format.fprintf Format.err_formatter
- "@[Warning: cycle in dependencies. End of list is not sorted.@]@.";
- let sorted_deps =
- let li = ref [] in
- Hashtbl.iter (fun _ file_deps -> li := file_deps :: !li) h;
- List.sort (fun (file1, _) (file2, _) -> String.compare file1 file2) !li
- in
- List.iter (fun (file, deps) ->
- Format.fprintf Format.err_formatter "\t@[%s: " file;
- List.iter (fun (modname, kind) ->
- Format.fprintf Format.err_formatter "%s.%s " modname
- (if kind=ML then "ml" else "mli");
- ) !deps;
- Format.fprintf Format.err_formatter "@]@.";
- Printf.printf "%s " file) sorted_deps;
- end;
- Printf.printf "\n%!";
- ()
-
-(* Map *)
-
-let rec dump_map s0 ppf m =
- let open Depend in
- StringMap.iter
- (fun key (Node(s1,m')) ->
- let s = StringSet.diff s1 s0 in
- if StringSet.is_empty s then
- Format.fprintf ppf "@ @[<hv2>module %s : sig%a@;<1 -2>end@]"
- key (dump_map (StringSet.union s1 s0)) m'
- else
- Format.fprintf ppf "@ module %s = %s" key (StringSet.choose s))
- m
-
-let process_ml_map =
- read_parse_and_extract Parse.implementation Depend.add_implementation_binding
- StringMap.empty Pparse.Structure
-
-let process_mli_map =
- read_parse_and_extract Parse.interface Depend.add_signature_binding
- StringMap.empty Pparse.Signature
-
-let parse_map fname =
- map_files := fname :: !map_files ;
- let old_transp = !Clflags.transparent_modules in
- Clflags.transparent_modules := true;
- let (deps, m) =
- process_file fname ~def:(Depend.StringSet.empty, StringMap.empty)
- ~ml_file:process_ml_map
- ~mli_file:process_mli_map
- in
- Clflags.transparent_modules := old_transp;
- let modname =
- String.capitalize_ascii
- (Filename.basename (Filename.chop_extension fname)) in
- if StringMap.is_empty m then
- report_err (Failure (fname ^ " : empty map file or parse error"));
- let mm = Depend.make_node m in
- if !debug then begin
- Format.printf "@[<v>%s:%t%a@]@." fname
- (fun ppf -> Depend.StringSet.iter (Format.fprintf ppf " %s") deps)
- (dump_map deps) (StringMap.add modname mm StringMap.empty)
- end;
- let mm = Depend.(weaken_map (StringSet.singleton modname) mm) in
- module_map := StringMap.add modname mm !module_map
-;;
-
-
-(* Entry point *)
-
-let usage = "Usage: ocamldep [options] <source files>\nOptions are:"
-
-let print_version () =
- Format.printf "ocamldep, version %s@." Sys.ocaml_version;
- exit 0;
-;;
-
-let print_version_num () =
- Format.printf "%s@." Sys.ocaml_version;
- exit 0;
-;;
-
-let _ =
- Clflags.classic := false;
- add_to_list first_include_dirs Filename.current_dir_name;
- Compenv.readenv ppf Before_args;
- Clflags.add_arguments __LOC__ [
- "-absname", Arg.Set Location.absname,
- " Show absolute filenames in error messages";
- "-all", Arg.Set all_dependencies,
- " Generate dependencies on all files";
- "-allow-approx", Arg.Set allow_approximation,
- " Fallback to a lexer-based approximation on unparseable files";
- "-as-map", Arg.Set Clflags.transparent_modules,
- " Omit delayed dependencies for module aliases (-no-alias-deps -w -49)";
- (* "compiler uses -no-alias-deps, and no module is coerced"; *)
- "-debug-map", Arg.Set debug,
- " Dump the delayed dependency map for each map file";
- "-I", Arg.String (add_to_list Clflags.include_dirs),
- "<dir> Add <dir> to the list of include directories";
- "-impl", Arg.String (file_dependencies_as ML),
- "<f> Process <f> as a .ml file";
- "-intf", Arg.String (file_dependencies_as MLI),
- "<f> Process <f> as a .mli file";
- "-map", Arg.String parse_map,
- "<f> Read <f> and propagate delayed dependencies to following files";
- "-ml-synonym", Arg.String(add_to_synonym_list ml_synonyms),
- "<e> Consider <e> as a synonym of the .ml extension";
- "-mli-synonym", Arg.String(add_to_synonym_list mli_synonyms),
- "<e> Consider <e> as a synonym of the .mli extension";
- "-modules", Arg.Set raw_dependencies,
- " Print module dependencies in raw form (not suitable for make)";
- "-native", Arg.Set native_only,
- " Generate dependencies for native-code only (no .cmo files)";
- "-bytecode", Arg.Set bytecode_only,
- " Generate dependencies for bytecode-code only (no .cmx files)";
- "-one-line", Arg.Set one_line,
- " Output one line per file, regardless of the length";
- "-open", Arg.String (add_to_list Clflags.open_modules),
- "<module> Opens the module <module> before typing";
- "-plugin", Arg.String Compplugin.load,
- "<plugin> Load dynamic plugin <plugin>";
- "-pp", Arg.String(fun s -> Clflags.preprocessor := Some s),
- "<cmd> Pipe sources through preprocessor <cmd>";
- "-ppx", Arg.String (add_to_list first_ppx),
- "<cmd> Pipe abstract syntax trees through preprocessor <cmd>";
- "-slash", Arg.Set Clflags.force_slash,
- " (Windows) Use forward slash / instead of backslash \\ in file paths";
- "-sort", Arg.Set sort_files,
- " Sort files according to their dependencies";
- "-version", Arg.Unit print_version,
- " Print version and exit";
- "-vnum", Arg.Unit print_version_num,
- " Print version number and exit";
- "-args", Arg.Expand Arg.read_arg,
- "<file> Read additional newline separated command line arguments \n\
- \ from <file>";
- "-args0", Arg.Expand Arg.read_arg0,
- "<file> Read additional NUL separated command line arguments from \n\
- \ <file>"
- ];
- Clflags.parse_arguments file_dependencies usage;
- Compenv.readenv ppf Before_link;
- if !sort_files then sort_files_by_dependencies !files
- else List.iter print_file_dependencies (List.sort compare !files);
- exit (if !error_occurred then 2 else 0)
+let () = Makedepend.main ()
else if s = "-linkall" then
caml_opts := s :: !caml_opts
else if starts_with s "-l" then
+ let s =
+ if Config.ccomp_type = "msvc" then
+ String.sub s 2 (String.length s - 2) ^ ".lib"
+ else
+ s
+ in
c_libs := s :: !c_libs
else if starts_with s "-L" then
(c_Lopts := s :: !c_Lopts;
(Filename.basename !output_c)
(Filename.basename !output_c)
(String.concat " " (prefix_list "-ccopt " !c_opts))
- (make_rpath_ccopt byteccrpath)
+ (make_rpath_ccopt default_rpath)
(String.concat " " (prefix_list "-cclib " !c_libs))
(String.concat " " !caml_libs));
if !native_objs <> [] then
(String.concat " " !native_objs)
(Filename.basename !output_c)
(String.concat " " (prefix_list "-ccopt " !c_opts))
- (make_rpath_ccopt nativeccrpath)
+ (make_rpath_ccopt default_rpath)
(String.concat " " (prefix_list "-cclib " !c_libs))
(String.concat " " !caml_libs))
let _color s = option_with_arg "-color" s
let _where = option "-where"
+ let _linscan = option "-linscan"
let _nopervasives = option "-nopervasives"
let _dsource = option "-dsource"
let _dparsetree = option "-dparsetree"
let _dcombine = option "-dcombine"
let _dcse = option "-dcse"
let _dlive = option "-dlive"
+ let _davail = option "-davail"
+ let _drunavail = option "-drunavail"
let _dspill = option "-dspill"
let _dsplit = option "-dsplit"
let _dinterf = option "-dinterf"
let _dscheduling = option "-dscheduling"
let _dlinear = option "-dlinear"
let _dstartup = option "-dstartup"
+ let _dinterval = option "-dinterval"
let _dtimings = option "-dtimings"
+ let _dprofile = option "-dprofile"
let _opaque = option "-opaque"
let _args = Arg.read_arg
| Pcl_let (_, spat_sexp_list, cexpr) ->
rewrite_patexp_list iflag spat_sexp_list;
rewrite_class_expr iflag cexpr
+ | Pcl_open (_, _, cexpr)
| Pcl_constraint (cexpr, _) ->
rewrite_class_expr iflag cexpr
| Pcl_extension _ -> ()
let gen_ml = ref false
let print_info_arg = ref false
let target_filename = ref None
+let save_cmt_info = ref false
-let arg_list = [
+let arg_list = Arg.align [
"-o", Arg.String (fun s -> target_filename := Some s),
- " FILE (or -) : dump to file FILE (or stdout)";
- "-annot", Arg.Set gen_annot, " : generate the corresponding .annot file";
+ "<file> Dump to file <file> (or stdout if -)";
+ "-annot", Arg.Set gen_annot,
+ " Generate the corresponding .annot file";
+ "-save-cmt-info", Arg.Set save_cmt_info,
+ " Encapsulate additional cmt information in annotations";
"-src", Arg.Set gen_ml,
- " : convert .cmt or .cmti back to source code (without comments)";
+ " Convert .cmt or .cmti back to source code (without comments)";
"-info", Arg.Set print_info_arg, " : print information on the file";
"-args", Arg.Expand Arg.read_arg,
- " <file> Read additional newline separated command line arguments \n\
+ "<file> Read additional newline separated command line arguments \n\
\ from <file>";
"-args0", Arg.Expand Arg.read_arg0,
"<file> Read additional NUL separated command line arguments from \n\
\ <file>";
+ "-I", Arg.String (fun s ->
+ Clflags.include_dirs := s :: !Clflags.include_dirs),
+ "<dir> Add <dir> to the list of include directories";
]
let arg_usage =
let dummy_crc = String.make 32 '-'
let print_info cmt =
+ let oc = match !target_filename with
+ | None -> stdout
+ | Some filename -> open_out filename
+ in
let open Cmt_format in
- Printf.printf "module name: %s\n" cmt.cmt_modname;
- begin match cmt.cmt_annots with
- Packed (_, list) ->
- Printf.printf "pack: %s\n" (String.concat " " list)
- | Implementation _ -> Printf.printf "kind: implementation\n"
- | Interface _ -> Printf.printf "kind: interface\n"
- | Partial_implementation _ ->
- Printf.printf "kind: implementation with errors\n"
- | Partial_interface _ -> Printf.printf "kind: interface with errors\n"
- end;
- Printf.printf "command: %s\n"
- (String.concat " " (Array.to_list cmt.cmt_args));
- begin match cmt.cmt_sourcefile with
- None -> ()
- | Some name ->
- Printf.printf "sourcefile: %s\n" name;
- end;
- Printf.printf "build directory: %s\n" cmt.cmt_builddir;
- List.iter (Printf.printf "load path: %s\n%!") cmt.cmt_loadpath;
- begin
- match cmt.cmt_source_digest with
- None -> ()
- | Some digest ->
- Printf.printf "source digest: %s\n" (Digest.to_hex digest);
- end;
- begin
- match cmt.cmt_interface_digest with
- None -> ()
- | Some digest ->
- Printf.printf "interface digest: %s\n" (Digest.to_hex digest);
- end;
- List.iter (fun (name, crco) ->
- let crc =
- match crco with
- None -> dummy_crc
- | Some crc -> Digest.to_hex crc
- in
- Printf.printf "import: %s %s\n" name crc;
- ) (List.sort compare cmt.cmt_imports);
- Printf.printf "%!";
- ()
+ Printf.fprintf oc "module name: %s\n" cmt.cmt_modname;
+ begin match cmt.cmt_annots with
+ Packed (_, list) ->
+ Printf.fprintf oc "pack: %s\n" (String.concat " " list)
+ | Implementation _ -> Printf.fprintf oc "kind: implementation\n"
+ | Interface _ -> Printf.fprintf oc "kind: interface\n"
+ | Partial_implementation _ ->
+ Printf.fprintf oc "kind: implementation with errors\n"
+ | Partial_interface _ -> Printf.fprintf oc "kind: interface with errors\n"
+ end;
+ Printf.fprintf oc "command: %s\n"
+ (String.concat " " (Array.to_list cmt.cmt_args));
+ begin match cmt.cmt_sourcefile with
+ None -> ()
+ | Some name ->
+ Printf.fprintf oc "sourcefile: %s\n" name;
+ end;
+ Printf.fprintf oc "build directory: %s\n" cmt.cmt_builddir;
+ List.iter (Printf.fprintf oc "load path: %s\n%!") cmt.cmt_loadpath;
+ begin
+ match cmt.cmt_source_digest with
+ None -> ()
+ | Some digest ->
+ Printf.fprintf oc "source digest: %s\n" (Digest.to_hex digest);
+ end;
+ begin
+ match cmt.cmt_interface_digest with
+ None -> ()
+ | Some digest ->
+ Printf.fprintf oc "interface digest: %s\n" (Digest.to_hex digest);
+ end;
+ List.iter (fun (name, crco) ->
+ let crc =
+ match crco with
+ None -> dummy_crc
+ | Some crc -> Digest.to_hex crc
+ in
+ Printf.fprintf oc "import: %s %s\n" name crc;
+ ) (List.sort compare cmt.cmt_imports);
+ Printf.fprintf oc "%!";
+ begin match !target_filename with
+ | None -> ()
+ | Some _ -> close_out oc
+ end;
+ ()
-let _ =
+let main () =
Clflags.annotations := true;
Arg.parse_expand arg_list (fun filename ->
Filename.check_suffix filename ".cmt" ||
Filename.check_suffix filename ".cmti"
then begin
- (* init_path(); *)
+ Compmisc.init_path false;
let cmt = Cmt_format.read_cmt filename in
- if !gen_annot then Cmt2annot.gen_annot !target_filename filename cmt;
+ if !gen_annot then
+ Cmt2annot.gen_annot ~save_cmt_info: !save_cmt_info
+ !target_filename filename cmt;
if !gen_ml then Cmt2annot.gen_ml !target_filename filename cmt;
if !print_info_arg || not (!gen_ml || !gen_annot) then print_info cmt;
end else begin
Arg.usage arg_list arg_usage
end
) arg_usage
+
+
+let () =
+ try
+ main ()
+ with x ->
+ Printf.eprintf "Exception in main ()\n%!";
+ Location.report_exception Format.err_formatter x;
+ Format.fprintf Format.err_formatter "@.";
+ exit 2
module type OBJ =
sig
type t
+ val repr : 'a -> t
val obj : t -> 'a
val is_block : t -> bool
val tag : t -> int
val size : t -> int
val field : t -> int -> t
+ val double_array_tag : int
+ val double_field : t -> int -> float
end
module type EVALPATH =
(* Note: this could be a char or a constant constructor... *)
else if O.tag arg = Obj.string_tag then
list :=
- Oval_string (String.escaped (O.obj arg : string)) :: !list
+ Oval_string ((O.obj arg : string), max_int, Ostr_string) :: !list
else if O.tag arg = Obj.double_tag then
list := Oval_float (O.obj arg : float) :: !list
else
( Pident(Ident.create "print_char"),
Simple (Predef.type_char,
(fun x -> Oval_char (O.obj x : char))) );
- ( Pident(Ident.create "print_string"),
- Simple (Predef.type_string,
- (fun x -> Oval_string (O.obj x : string))) );
( Pident(Ident.create "print_int32"),
Simple (Predef.type_int32,
(fun x -> Oval_int32 (O.obj x : int32))) );
Oval_array (List.rev (tree_of_items [] 0))
else
Oval_array []
+
+ | Tconstr(path, [], _)
+ when Path.same path Predef.path_string ->
+ Oval_string ((O.obj obj : string), !printer_steps, Ostr_string)
+
+ | Tconstr (path, [], _)
+ when Path.same path Predef.path_bytes ->
+ let s = Bytes.to_string (O.obj obj : bytes) in
+ Oval_string (s, !printer_steps, Ostr_bytes)
+
| Tconstr (path, [ty_arg], _)
when Path.same path Predef.path_lazy_t ->
let obj_tag = O.tag obj in
if pos = 0 then tree_of_label env path name
else Oide_ident name
and v =
- if unboxed
- then tree_of_val (depth - 1) obj ty_arg
- else nest tree_of_val (depth - 1) (O.field obj pos) ty_arg
+ if unboxed then
+ tree_of_val (depth - 1) obj ty_arg
+ else begin
+ let fld =
+ if O.tag obj = O.double_array_tag then
+ O.repr (O.double_field obj pos)
+ else
+ O.field obj pos
+ in
+ nest tree_of_val (depth - 1) fld ty_arg
+ end
in
(lid, v) :: tree_of_fields (pos + 1) remainder
in
module type OBJ =
sig
type t
+ val repr : 'a -> t
val obj : t -> 'a
val is_block : t -> bool
val tag : t -> int
val size : t -> int
val field : t -> int -> t
+ val double_array_tag : int
+ val double_field : t -> int -> float
end
module type EVALPATH =
in
let fn = Filename.chop_extension dll in
if not Config.flambda then
- Asmgen.compile_implementation_clambda ~source_provenance:Timings.Toplevel
+ Asmgen.compile_implementation_clambda
~toplevel:need_symbol fn ppf
{ Lambda.code=slam ; main_module_block_size=size;
module_ident; required_globals }
else
- Asmgen.compile_implementation_flambda ~source_provenance:Timings.Toplevel
+ Asmgen.compile_implementation_flambda
~required_globals ~backend ~toplevel:need_symbol fn ppf
- (Middle_end.middle_end ppf
- ~source_provenance:Timings.Toplevel ~prefixname:"" ~backend ~size
+ (Middle_end.middle_end ppf ~prefixname:"" ~backend ~size
~module_ident ~module_initializer:slam ~filename:"toplevel");
Asmlink.call_linker_shared [fn ^ ext_obj] dll;
Sys.remove (fn ^ ext_obj);
let oldenv = !toplevel_env in
incr phrase_seqid;
phrase_name := Printf.sprintf "TOP%i" !phrase_seqid;
- Compilenv.reset ~source_provenance:Timings.Toplevel
- ?packname:None !phrase_name;
+ Compilenv.reset ?packname:None !phrase_name;
Typecore.reset_delayed_checks ();
let sstr, rewritten =
match sstr with
let _labels = clear classic
let _alias_deps = clear transparent_modules
let _no_alias_deps = set transparent_modules
+ let _dlinscan = set use_linscan
let _app_funct = set applicative_functors
let _no_app_funct = clear applicative_functors
let _noassert = set noassert
let _dcombine = set dump_combine
let _dcse = set dump_cse
let _dlive () = dump_live := true; Printmach.print_live := true
+ let _davail () = dump_avail := true
+ let _drunavail () = debug_runavail := true
let _dspill = set dump_spill
let _dsplit = set dump_split
let _dinterf = set dump_interf
let _dreload = set dump_reload
let _dscheduling = set dump_scheduling
let _dlinear = set dump_linear
+ let _dinterval = set dump_interval
let _dstartup = set keep_startup_file
let _safe_string = clear unsafe_string
let _unsafe_string = set unsafe_string
let _open s = open_modules := s :: !open_modules
- let _plugin p = Compplugin.load p
let _args = wrap_expand Arg.read_arg
let _args0 = wrap_expand Arg.read_arg0
| Arg.Help msg -> Format.fprintf Format.std_formatter "%s%!" msg; exit 0
end;
if not (prepare Format.err_formatter) then exit 2;
+ Compmisc.init_path true;
Opttoploop.loop Format.std_formatter
{
section = section_env;
doc = "Print the signatures of components \
- from any of the above categories.";
+ from any of the categories below.";
}
let _ = add_directive "trace"
let _nopromptcont = set nopromptcont
let _nostdlib = set no_std_include
let _open s = open_modules := s :: !open_modules
- let _plugin p = Compplugin.load p
let _ppx s = first_ppx := s :: !first_ppx
let _principal = set principal
let _no_principal = clear principal
let _drawlambda = set dump_rawlambda
let _dlambda = set dump_lambda
let _dflambda = set dump_flambda
- let _dtimings = set print_timings
+ let _dtimings () = profile_columns := [ `Time ]
+ let _dprofile () = profile_columns := Profile.all_columns
let _dinstr = set dump_instr
let _args = wrap_expand Arg.read_arg
end;
Compenv.readenv ppf Before_link;
if not (prepare ppf) then exit 2;
+ Compmisc.init_path false;
Toploop.loop Format.std_formatter
inference. Here is a reading list to ease your discovery of the
typechecker:
-http://caml.inria.fr/pub/docs/u3-ocaml/index.html[Using, Understanding, and Unraveling the OCaml Language by Didier Rémy] ::
+http://caml.inria.fr/pub/docs/u3-ocaml/index.html[Using, Understanding, and Unraveling the OCaml Language by Didier Rémy] ::
This book provides (among other things) a formal description of parts
of the core OCaml language, starting with a simple Core ML.
let save_cmt filename modname binary_annots sourcefile initial_env cmi =
if !Clflags.binary_annotations && not !Clflags.print_types then begin
- let oc = open_out_bin filename in
- let this_crc =
- match cmi with
- | None -> None
- | Some cmi -> Some (output_cmi filename oc cmi)
- in
- let source_digest = Misc.may_map Digest.file sourcefile in
- let cmt = {
- cmt_modname = modname;
- cmt_annots = clear_env binary_annots;
- cmt_value_dependencies = !value_deps;
- cmt_comments = Lexer.comments ();
- cmt_args = Sys.argv;
- cmt_sourcefile = sourcefile;
- cmt_builddir = Sys.getcwd ();
- cmt_loadpath = !Config.load_path;
- cmt_source_digest = source_digest;
- cmt_initial_env = if need_to_clear_env then
- keep_only_summary initial_env else initial_env;
- cmt_imports = List.sort compare (Env.imports ());
- cmt_interface_digest = this_crc;
- cmt_use_summaries = need_to_clear_env;
- } in
- output_cmt oc cmt;
- close_out oc;
+ Misc.output_to_file_via_temporary
+ ~mode:[Open_binary] filename
+ (fun temp_file_name oc ->
+ let this_crc =
+ match cmi with
+ | None -> None
+ | Some cmi -> Some (output_cmi temp_file_name oc cmi)
+ in
+ let source_digest = Misc.may_map Digest.file sourcefile in
+ let cmt = {
+ cmt_modname = modname;
+ cmt_annots = clear_env binary_annots;
+ cmt_value_dependencies = !value_deps;
+ cmt_comments = Lexer.comments ();
+ cmt_args = Sys.argv;
+ cmt_sourcefile = sourcefile;
+ cmt_builddir = Sys.getcwd ();
+ cmt_loadpath = !Config.load_path;
+ cmt_source_digest = source_digest;
+ cmt_initial_env = if need_to_clear_env then
+ keep_only_summary initial_env else initial_env;
+ cmt_imports = List.sort compare (Env.imports ());
+ cmt_interface_digest = this_crc;
+ cmt_use_summaries = need_to_clear_env;
+ } in
+ output_cmt oc cmt)
end;
clear ()
If one wants to manipulate a type after type inference (for
instance, during code generation or in the debugger), one must
first make sure that the type levels are correct, using the
- function [correct_levels]. Then, this type can be correctely
+ function [correct_levels]. Then, this type can be correctly
manipulated by [apply], [expand_head] and [moregeneral].
*)
normalize_package_path env (Path.Pdot (p1', s, n))
| _ -> p
-let rec update_level env level ty =
+let rec update_level env level expand ty =
let ty = repr ty in
if ty.level > level then begin
begin match Env.gadt_instance_level env ty with
begin try
(* if is_newtype env p then raise Cannot_expand; *)
link_type ty (!forward_try_expand_once env ty);
- update_level env level ty
+ update_level env level expand ty
with Cannot_expand ->
(* +++ Levels should be restored... *)
(* Format.printf "update_level: %i < %i@." level (get_level env p); *)
if level < get_level env p then raise (Unify [(ty, newvar2 level)]);
- iter_type_expr (update_level env level) ty
+ iter_type_expr (update_level env level expand) ty
end
+ | Tconstr(_, _ :: _, _) when expand ->
+ begin try
+ link_type ty (!forward_try_expand_once env ty);
+ update_level env level expand ty
+ with Cannot_expand ->
+ set_level ty level;
+ iter_type_expr (update_level env level expand) ty
+ end
| Tpackage (p, nl, tl) when level < Path.binding_time p ->
let p' = normalize_package_path env p in
if Path.same p p' then raise (Unify [(ty, newvar2 level)]);
log_type ty; ty.desc <- Tpackage (p', nl, tl);
- update_level env level ty
+ update_level env level expand ty
| Tobject(_, ({contents=Some(p, _tl)} as nm))
when level < get_level env p ->
set_name nm None;
- update_level env level ty
+ update_level env level expand ty
| Tvariant row ->
let row = row_repr row in
begin match row.row_name with
| _ -> ()
end;
set_level ty level;
- iter_type_expr (update_level env level) ty
+ iter_type_expr (update_level env level expand) ty
| Tfield(lab, _, ty1, _)
when lab = dummy_method && (repr ty1).level > level ->
raise (Unify [(ty1, newvar2 level)])
| _ ->
set_level ty level;
(* XXX what about abbreviations in Tconstr ? *)
- iter_type_expr (update_level env level) ty
+ iter_type_expr (update_level env level expand) ty
+ end
+
+(* First try without expanding, then expand everything,
+ to avoid combinatorial blow-up *)
+let update_level env level ty =
+ let ty = repr ty in
+ if ty.level > level then begin
+ let snap = snapshot () in
+ try
+ update_level env level false ty
+ with Unify _ ->
+ backtrack snap;
+ update_level env level true ty
end
(* Generalize and lower levels of contravariant branches simultaneously *)
cleanup_types ();
(params', cty')
-(**** Instanciation for types with free universal variables ****)
+(**** Instantiation for types with free universal variables ****)
let rec diff_list l1 l2 =
if l1 == l2 then [] else
raise exn
(*
- Only the shape of the type matters, not whether is is generic or
+ Only the shape of the type matters, not whether it is generic or
not. [generic_level] might be somewhat slower, but it ensures
- invariants on types are enforced (decreasing levels.), and we don't
+ invariants on types are enforced (decreasing levels), and we don't
care about efficiency here.
*)
let apply env params body args =
with
Unify _ -> raise Cannot_apply
+let () = Subst.ctype_apply_env_empty := apply Env.empty
(****************************)
(* Abbreviation expansion *)
(****************************)
(*
- If the environnement has changed, memorized expansions might not
+ If the environment has changed, memorized expansions might not
be correct anymore, and so we flush the cache. This is safe but
quite pessimistic: it would be enough to flush the cache when a
- type or module definition is overridden in the environnement.
+ type or module definition is overridden in the environment.
*)
let previous_env = ref Env.empty
(*let string_of_kind = function Public -> "public" | Private -> "private"*)
(* prerr_endline
("add a "^string_of_kind kind^" expansion for "^Path.name path);*)
let ty' = subst env level kind abbrev (Some ty) params args body in
- (* Hack to name the variant type *)
- begin match repr ty' with
- {desc=Tvariant row} as ty when static_row row ->
- ty.desc <- Tvariant { row with row_name = Some (path, args) }
- | _ -> ()
- end;
(* For gadts, remember type as non exportable *)
(* The ambiguous level registered for ty' should be the highest *)
if !trace_gadt_instances then begin
end
| [] -> raise (Unify [])
-(* Test the occurence of free univars in a type *)
-(* that's way too expansive. Must do some kind of cacheing *)
+(* Test the occurrence of free univars in a type *)
+(* that's way too expensive. Must do some kind of caching *)
let occur_univar env ty =
let visited = ref TypeMap.empty in
let rec occur_rec bound ty =
types are kept distincts, but they are made to (temporally)
expand to the same type.
2. Abbreviations with at least one parameter are systematically
- expanded. The overhead does not seem to high, and that way
+ expanded. The overhead does not seem too high, and that way
abbreviations where some parameters does not appear in the
expansion, such as ['a t = int], are correctly handled. In
particular, for this example, unifying ['a t] with ['b t] keeps
&& !package_subtype env p2 n2 tl2 p1 n1 tl1 then () else raise Not_found
-(* force unification in Reither when one side has as non-conjunctive type *)
+(* force unification in Reither when one side has a non-conjunctive type *)
let rigid_variants = ref false
(* drop not force unification in Reither, even in fixed case
end;
(* The following test is not principal... should rather use Tnil *)
let rm = row_more row in
- if !trace_gadt_instances && rm.desc = Tnil then () else
+ (*if !trace_gadt_instances && rm.desc = Tnil then () else*)
if !trace_gadt_instances then
update_level !env rm.level (newgenty (Tvariant row));
if row_fixed row then
raise (Unify ((mkvariant [l,f1] true,
mkvariant [l,f2] true) :: trace)))
pairs;
+ if static_row row1 then begin
+ let rm = row_more row1 in
+ if is_Tvar rm then link_type rm (newty2 rm.level Tnil)
+ end
with exn ->
log_type rm1; rm1.desc <- md1; log_type rm2; rm2.desc <- md2; raise exn
end
| Rpresent None, Rpresent None -> ()
| Reither(c1, tl1, m1, e1), Reither(c2, tl2, m2, e2) ->
if e1 == e2 then () else
- let redo =
+ if (fixed1 || fixed2) && not (c1 || c2)
+ && List.length tl1 = List.length tl2 then begin
+ (* PR#7496 *)
+ let f = Reither (c1 || c2, [], m1 || m2, ref None) in
+ set_row_field e1 f; set_row_field e2 f;
+ List.iter2 (unify env) tl1 tl2
+ end
+ else let redo =
not !passive_variants &&
(m1 || m2 || fixed1 || fixed2 ||
!rigid_variants && (List.length tl1 = 1 || List.length tl2 = 1)) &&
moregen inst_nongen type_pairs env patt subj
(*
- Non-generic variable can be instanciated only if [inst_nongen] is
+ Non-generic variable can be instantiated only if [inst_nongen] is
true. So, [inst_nongen] should be set to false if the subject might
contain non-generic variables (and we do not want them to be
- instanciated).
+ instantiated).
Usually, the subject is given by the user, and the pattern
is unimportant. So, no need to propagate abbreviations.
*)
match row_field_repr f1, row_field_repr f2 with
Rpresent(Some t1), Rpresent(Some t2) ->
eqtype rename type_pairs subst env t1 t2
- | Reither(true, [], _, _), Reither(true, [], _, _) ->
+ | Reither(c1, [], _, _), Reither(c2, [], _, _) when c1 = c2 ->
()
- | Reither(false, t1::tl1, _, _), Reither(false, t2::tl2, _, _) ->
+ | Reither(c1, t1::tl1, _, _), Reither(c2, t2::tl2, _, _) when c1 = c2 ->
eqtype rename type_pairs subst env t1 t2;
if List.length tl1 = List.length tl2 then
(* if same length allow different types (meaning?) *)
ty1, tl1
| _ -> raise Not_found
in
- (* Fix PR4505: do not set ty to Tvar when it appears in tl1,
- as this occurence might break the occur check.
+ (* Fix PR#4505: do not set ty to Tvar when it appears in tl1,
+ as this occurrence might break the occur check.
XXX not clear whether this correct anyway... *)
if List.exists (deep_occur ty) tl1 then raise Not_found;
ty.desc <- Tvar None;
in
List.fold_left
(fun cstrs (_, _k1, t1, _k2, t2) ->
- (* Theses fields are always present *)
+ (* These fields are always present *)
subtype_rec env ((t1, t2)::trace) t1 t2 cstrs)
cstrs pairs
clear_hash ();
decl
-(* collapse conjonctive types in class parameters *)
+(* collapse conjunctive types in class parameters *)
let rec collapse_conj env visited ty =
let ty = repr ty in
if List.memq ty visited then () else
val subtype: Env.t -> type_expr -> type_expr -> unit -> unit
(* [subtype env t1 t2] checks that [t1] is a subtype of [t2].
It accumulates the constraints the type variables must
- enforce and returns a function that inforce this
+ enforce and returns a function that enforces this
constraints. *)
val nondep_type: Env.t -> Ident.t -> type_expr -> type_expr
label_descrs (newgenconstr ty_path decl.type_params)
labels rep decl.type_private
| Type_variant _ | Type_abstract | Type_open -> []
+
+(* Set row_name in Env, cf. GPR#1204/1329 *)
+let set_row_name decl path =
+ match decl.type_manifest with
+ None -> ()
+ | Some ty ->
+ let ty = repr ty in
+ match ty.desc with
+ Tvariant row when static_row row ->
+ let row = {(row_repr row) with
+ row_name = Some (path, decl.type_params)} in
+ ty.desc <- Tvariant row
+ | _ -> ()
- the types of the constructor's arguments
- the existential variables introduced by the constructor
*)
+
+
+(* Set the polymorphic variant row_name field *)
+val set_row_name : type_declaration -> Path.t -> unit
module EnvLazy : sig
type ('a,'b) t
+ type log
+
val force : ('a -> 'b) -> ('a,'b) t -> 'b
val create : 'a -> ('a,'b) t
val get_arg : ('a,'b) t -> 'a option
+ (* [force_logged log f t] is equivalent to [force f t] but if [f] returns [None] then
+ [t] is recorded in [log]. [backtrack log] will then reset all the recorded [t]s back
+ to their original state. *)
+ val log : unit -> log
+ val force_logged : log -> ('a -> 'b option) -> ('a,'b option) t -> 'b option
+ val backtrack : log -> unit
+
end = struct
type ('a,'b) t = ('a,'b) eval ref
and ('a,'b) eval =
- Done of 'b
+ | Done of 'b
| Raise of exn
| Thunk of 'a
+ type undo =
+ | Nil
+ | Cons : ('a, 'b) t * 'a * undo -> undo
+
+ type log = undo ref
+
let force f x =
match !x with
- Done x -> x
- | Raise e -> raise e
- | Thunk e ->
- try
- let y = f e in
- x := Done y;
- y
- with e ->
- x := Raise e;
- raise e
+ | Done x -> x
+ | Raise e -> raise e
+ | Thunk e ->
+ match f e with
+ | y ->
+ x := Done y;
+ y
+ | exception e ->
+ x := Raise e;
+ raise e
let get_arg x =
match !x with Thunk a -> Some a | _ -> None
let create x =
ref (Thunk x)
+ let log () =
+ ref Nil
+
+ let force_logged log f x =
+ match !x with
+ | Done x -> x
+ | Raise e -> raise e
+ | Thunk e ->
+ match f e with
+ | None ->
+ x := Done None;
+ log := Cons(x, e, !log);
+ None
+ | Some _ as y ->
+ x := Done y;
+ y
+ | exception e ->
+ x := Raise e;
+ raise e
+
+ let backtrack log =
+ let rec loop = function
+ | Nil -> ()
+ | Cons(x, e, rest) ->
+ x := Thunk e;
+ loop rest
+ in
+ loop !log
+
end
module PathMap = Map.Make(Path)
| Env_open of summary * Path.t
| Env_functor_arg of summary * Ident.t
| Env_constraints of summary * type_declaration PathMap.t
+ | Env_copy_types of summary * string list
-module EnvTbl =
+module TycompTbl =
struct
- (* A table indexed by identifier, with an extra slot to record usage. *)
- type 'a t = ('a * (unit -> unit)) Ident.tbl
+ (** This module is used to store components of types (i.e. labels
+ and constructors). We keep a representation of each nested
+ "open" and the set of local bindings between each of them. *)
- let empty = Ident.empty
- let nothing = fun () -> ()
+ type 'a t = {
+ current: 'a Ident.tbl;
+ (** Local bindings since the last open. *)
+
+ opened: 'a opened option;
+ (** Symbolic representation of the last (innermost) open, if any. *)
+ }
+
+ and 'a opened = {
+ components: (string, 'a list) Tbl.t;
+ (** Components from the opened module. We keep a list of
+ bindings for each name, as in comp_labels and
+ comp_constrs. *)
+
+ using: (string -> ('a * 'a) option -> unit) option;
+ (** A callback to be applied when a component is used from this
+ "open". This is used to detect unused "opens". The
+ arguments are used to detect shadowing. *)
+
+ next: 'a t;
+ (** The table before opening the module. *)
+ }
- let already_defined wrap s tbl x =
- wrap (try Some (fst (Ident.find_name s tbl), x) with Not_found -> None)
+ let empty = { current = Ident.empty; opened = None }
- let add slot wrap id x tbl ref_tbl =
- let slot =
+ let add id x tbl =
+ {tbl with current = Ident.add id x tbl.current}
+
+ let add_open slot wrap components next =
+ let using =
match slot with
- | None -> nothing
- | Some f ->
+ | None -> None
+ | Some f -> Some (fun s x -> f s (wrap x))
+ in
+ {
+ current = Ident.empty;
+ opened = Some {using; components; next};
+ }
+
+ let rec find_same id tbl =
+ try Ident.find_same id tbl.current
+ with Not_found as exn ->
+ begin match tbl.opened with
+ | Some {next; _} -> find_same id next
+ | None -> raise exn
+ end
+
+ let nothing = fun () -> ()
+
+ let mk_callback rest name desc = function
+ | None -> nothing
+ | Some f ->
(fun () ->
- let s = Ident.name id in
- f s (already_defined wrap s ref_tbl x)
+ match rest with
+ | [] -> f name None
+ | (hidden, _) :: _ -> f name (Some (desc, hidden))
)
+
+ let rec find_all name tbl =
+ List.map (fun (_id, desc) -> desc, nothing)
+ (Ident.find_all name tbl.current) @
+ match tbl.opened with
+ | None -> []
+ | Some {using; next; components} ->
+ let rest = find_all name next in
+ match Tbl.find_str name components with
+ | exception Not_found -> rest
+ | opened ->
+ List.map
+ (fun desc -> desc, mk_callback rest name desc using)
+ opened
+ @ rest
+
+ let rec fold_name f tbl acc =
+ let acc = Ident.fold_name (fun _id d -> f d) tbl.current acc in
+ match tbl.opened with
+ | Some {using = _; next; components} ->
+ acc
+ |> Tbl.fold
+ (fun _name -> List.fold_right (fun desc -> f desc))
+ components
+ |> fold_name f next
+ | None ->
+ acc
+
+ let rec local_keys tbl acc =
+ let acc = Ident.fold_all (fun k _ accu -> k::accu) tbl.current acc in
+ match tbl.opened with
+ | Some o -> local_keys o.next acc
+ | None -> acc
+
+ let diff_keys is_local tbl1 tbl2 =
+ let keys2 = local_keys tbl2 [] in
+ List.filter
+ (fun id ->
+ is_local (find_same id tbl2) &&
+ try ignore (find_same id tbl1); false
+ with Not_found -> true)
+ keys2
+
+ end
+
+
+module IdTbl =
+ struct
+ (** This module is used to store all kinds of components except
+ (labels and constructors) in environments. We keep a
+ representation of each nested "open" and the set of local
+ bindings between each of them. *)
+
+
+ type 'a t = {
+ current: 'a Ident.tbl;
+ (** Local bindings since the last open *)
+
+ opened: 'a opened option;
+ (** Symbolic representation of the last (innermost) open, if any. *)
+ }
+
+ and 'a opened = {
+ root: Path.t;
+ (** The path of the opened module, to be prefixed in front of
+ its local names to produce a valid path in the current
+ environment. *)
+
+ components: (string, 'a * int) Tbl.t;
+ (** Components from the opened module. *)
+
+ using: (string -> ('a * 'a) option -> unit) option;
+ (** A callback to be applied when a component is used from this
+ "open". This is used to detect unused "opens". The
+ arguments are used to detect shadowing. *)
+
+ next: 'a t;
+ (** The table before opening the module. *)
+ }
+
+ let empty = { current = Ident.empty; opened = None }
+
+ let add id x tbl =
+ {tbl with current = Ident.add id x tbl.current}
+
+ let add_open slot wrap root components next =
+ let using =
+ match slot with
+ | None -> None
+ | Some f -> Some (fun s x -> f s (wrap x))
in
- Ident.add id (x, slot) tbl
+ {
+ current = Ident.empty;
+ opened = Some {using; root; components; next};
+ }
+
+ let rec find_same id tbl =
+ try Ident.find_same id tbl.current
+ with Not_found as exn ->
+ begin match tbl.opened with
+ | Some {next; _} -> find_same id next
+ | None -> raise exn
+ end
+
+ let rec find_name mark name tbl =
+ try
+ let (id, desc) = Ident.find_name name tbl.current in
+ Pident id, desc
+ with Not_found as exn ->
+ begin match tbl.opened with
+ | Some {using; root; next; components} ->
+ begin try
+ let (descr, pos) = Tbl.find_str name components in
+ let res = Pdot (root, name, pos), descr in
+ if mark then begin match using with
+ | None -> ()
+ | Some f ->
+ begin try f name (Some (snd (find_name false name next), snd res))
+ with Not_found -> f name None
+ end
+ end;
+ res
+ with Not_found ->
+ find_name mark name next
+ end
+ | None ->
+ raise exn
+ end
+
+ let find_name name tbl = find_name true name tbl
+
+ let rec update name f tbl =
+ try
+ let (id, desc) = Ident.find_name name tbl.current in
+ let new_desc = f desc in
+ {tbl with current = Ident.add id new_desc tbl.current}
+ with Not_found ->
+ begin match tbl.opened with
+ | Some {root; using; next; components} ->
+ begin try
+ let (desc, pos) = Tbl.find_str name components in
+ let new_desc = f desc in
+ let components = Tbl.add name (new_desc, pos) components in
+ {tbl with opened = Some {root; using; next; components}}
+ with Not_found ->
+ let next = update name f next in
+ {tbl with opened = Some {root; using; next; components}}
+ end
+ | None ->
+ tbl
+ end
+
+
- let find_same_not_using id tbl =
- fst (Ident.find_same id tbl)
+ let rec find_all name tbl =
+ List.map (fun (id, desc) -> Pident id, desc) (Ident.find_all name tbl.current) @
+ match tbl.opened with
+ | None -> []
+ | Some {root; using = _; next; components} ->
+ try
+ let (desc, pos) = Tbl.find_str name components in
+ (Pdot (root, name, pos), desc) :: find_all name next
+ with Not_found ->
+ find_all name next
+
+ let rec fold_name f tbl acc =
+ let acc = Ident.fold_name (fun id d -> f (Ident.name id) (Pident id, d)) tbl.current acc in
+ match tbl.opened with
+ | Some {root; using = _; next; components} ->
+ acc
+ |> Tbl.fold
+ (fun name (desc, pos) -> f name (Pdot (root, name, pos), desc))
+ components
+ |> fold_name f next
+ | None ->
+ acc
+
+ let rec local_keys tbl acc =
+ let acc = Ident.fold_all (fun k _ accu -> k::accu) tbl.current acc in
+ match tbl.opened with
+ | Some o -> local_keys o.next acc
+ | None -> acc
- let find_same id tbl =
- let (x, slot) = Ident.find_same id tbl in
- slot ();
- x
- let find_name s tbl =
- let (x, slot) = Ident.find_name s tbl in
- slot ();
- x
+ let rec iter f tbl =
+ Ident.iter (fun id desc -> f id (Pident id, desc)) tbl.current;
+ match tbl.opened with
+ | Some {root; using = _; next; components} ->
+ Tbl.iter
+ (fun s (x, pos) -> f (Ident.hide (Ident.create s) (* ??? *)) (Pdot (root, s, pos), x))
+ components;
+ iter f next
+ | None -> ()
+
+ let diff_keys tbl1 tbl2 =
+ let keys2 = local_keys tbl2 [] in
+ List.filter
+ (fun id ->
+ try ignore (find_same id tbl1); false
+ with Not_found -> true)
+ keys2
- let find_all s tbl =
- Ident.find_all s tbl
- let fold_name f = Ident.fold_name (fun k (d,_) -> f k d)
- let keys tbl = Ident.fold_all (fun k _ accu -> k::accu) tbl []
end
type type_descriptions =
let implicit_coercion_flag = 0x02
type t = {
- values: (Path.t * value_description) EnvTbl.t;
- constrs: constructor_description EnvTbl.t;
- labels: label_description EnvTbl.t;
- types: (Path.t * (type_declaration * type_descriptions)) EnvTbl.t;
- modules: (Path.t * module_declaration) EnvTbl.t;
- modtypes: (Path.t * modtype_declaration) EnvTbl.t;
- components: (Path.t * module_components) EnvTbl.t;
- classes: (Path.t * class_declaration) EnvTbl.t;
- cltypes: (Path.t * class_type_declaration) EnvTbl.t;
+ values: value_description IdTbl.t;
+ constrs: constructor_description TycompTbl.t;
+ labels: label_description TycompTbl.t;
+ types: (type_declaration * type_descriptions) IdTbl.t;
+ modules: (Subst.t * module_declaration, module_declaration) EnvLazy.t IdTbl.t;
+ modtypes: modtype_declaration IdTbl.t;
+ components: module_components IdTbl.t;
+ classes: class_declaration IdTbl.t;
+ cltypes: class_type_declaration IdTbl.t;
functor_args: unit Ident.tbl;
summary: summary;
local_constraints: type_declaration PathMap.t;
{
deprecated: string option;
loc: Location.t;
- comps: (t * Subst.t * Path.t * Types.module_type, module_components_repr)
- EnvLazy.t;
+ comps:
+ (t * Subst.t * Path.t * Types.module_type, module_components_repr option)
+ EnvLazy.t;
}
and module_components_repr =
Structure_comps of structure_components
| Functor_comps of functor_components
+and 'a comp_tbl = (string, ('a * int)) Tbl.t
+
and structure_components = {
- mutable comp_values: (string, (value_description * int)) Tbl.t;
- mutable comp_constrs: (string, (constructor_description * int) list) Tbl.t;
- mutable comp_labels: (string, (label_description * int) list) Tbl.t;
- mutable comp_types:
- (string, ((type_declaration * type_descriptions) * int)) Tbl.t;
+ mutable comp_values: value_description comp_tbl;
+ mutable comp_constrs: (string, constructor_description list) Tbl.t;
+ mutable comp_labels: (string, label_description list) Tbl.t;
+ mutable comp_types: (type_declaration * type_descriptions) comp_tbl;
mutable comp_modules:
- (string, ((Subst.t * Types.module_type,module_type) EnvLazy.t * int)) Tbl.t;
- mutable comp_modtypes: (string, (modtype_declaration * int)) Tbl.t;
- mutable comp_components: (string, (module_components * int)) Tbl.t;
- mutable comp_classes: (string, (class_declaration * int)) Tbl.t;
- mutable comp_cltypes: (string, (class_type_declaration * int)) Tbl.t
+ (Subst.t * module_declaration, module_declaration) EnvLazy.t comp_tbl;
+ mutable comp_modtypes: modtype_declaration comp_tbl;
+ mutable comp_components: module_components comp_tbl;
+ mutable comp_classes: class_declaration comp_tbl;
+ mutable comp_cltypes: class_type_declaration comp_tbl;
}
and functor_components = {
| `Class None | `Class_type None | `Component None ->
None
-let subst_modtype_maker (subst, mty) = Subst.modtype subst mty
+let subst_modtype_maker (subst, md) =
+ if subst == Subst.identity then md
+ else {md with md_type = Subst.modtype subst md.md_type}
let empty = {
- values = EnvTbl.empty; constrs = EnvTbl.empty;
- labels = EnvTbl.empty; types = EnvTbl.empty;
- modules = EnvTbl.empty; modtypes = EnvTbl.empty;
- components = EnvTbl.empty; classes = EnvTbl.empty;
- cltypes = EnvTbl.empty;
+ values = IdTbl.empty; constrs = TycompTbl.empty;
+ labels = TycompTbl.empty; types = IdTbl.empty;
+ modules = IdTbl.empty; modtypes = IdTbl.empty;
+ components = IdTbl.empty; classes = IdTbl.empty;
+ cltypes = IdTbl.empty;
summary = Env_empty; local_constraints = PathMap.empty; gadt_instances = [];
flags = 0;
functor_args = Ident.empty;
let is_in_signature env = env.flags land in_signature_flag <> 0
let is_implicit_coercion env = env.flags land implicit_coercion_flag <> 0
-let diff_keys is_local tbl1 tbl2 =
- let keys2 = EnvTbl.keys tbl2 in
- List.filter
- (fun id ->
- is_local (EnvTbl.find_same_not_using id tbl2) &&
- try ignore (EnvTbl.find_same_not_using id tbl1); false
- with Not_found -> true)
- keys2
-
let is_ident = function
Pident _ -> true
| Pdot _ | Papply _ -> false
-let is_local (p, _) = is_ident p
-
let is_local_ext = function
| {cstr_tag = Cstr_extension(p, _)} -> is_ident p
| _ -> false
let diff env1 env2 =
- diff_keys is_local env1.values env2.values @
- diff_keys is_local_ext env1.constrs env2.constrs @
- diff_keys is_local env1.modules env2.modules @
- diff_keys is_local env1.classes env2.classes
+ IdTbl.diff_keys env1.values env2.values @
+ TycompTbl.diff_keys is_local_ext env1.constrs env2.constrs @
+ IdTbl.diff_keys env1.modules env2.modules @
+ IdTbl.diff_keys env1.classes env2.classes
+
+type can_load_cmis =
+ | Can_load_cmis
+ | Cannot_load_cmis of EnvLazy.log
+
+let can_load_cmis = ref Can_load_cmis
+
+let without_cmis f x =
+ let log = EnvLazy.log () in
+ let res =
+ Misc.(protect_refs
+ [R (can_load_cmis, Cannot_load_cmis log)]
+ (fun () -> f x))
+ in
+ EnvLazy.backtrack log;
+ res
(* Forward declarations *)
module_components)
let components_of_module_maker' =
ref ((fun (_env, _sub, _path, _mty) -> assert false) :
- t * Subst.t * Path.t * module_type -> module_components_repr)
+ t * Subst.t * Path.t * module_type -> module_components_repr option)
let components_of_functor_appl' =
ref ((fun _f _env _p1 _p2 -> assert false) :
functor_components -> t -> Path.t -> Path.t -> module_components)
let check_modtype_inclusion =
(* to be filled with Includemod.check_modtype_inclusion *)
- ref ((fun _env _mty1 _path1 _mty2 -> assert false) :
- t -> module_type -> Path.t -> module_type -> unit)
+ ref ((fun ~loc:_ _env _mty1 _path1 _mty2 -> assert false) :
+ loc:Location.t -> t -> module_type -> Path.t -> module_type -> unit)
let strengthen =
(* to be filled with Mtype.strengthen *)
ref ((fun ~aliasable:_ _env _mty _path -> assert false) :
let md md_type =
{md_type; md_attributes=[]; md_loc=Location.none}
-let get_components c =
- EnvLazy.force !components_of_module_maker' c.comps
+let get_components_opt c =
+ match !can_load_cmis with
+ | Can_load_cmis ->
+ EnvLazy.force !components_of_module_maker' c.comps
+ | Cannot_load_cmis log ->
+ EnvLazy.force_logged log !components_of_module_maker' c.comps
+
+let empty_structure =
+ Structure_comps {
+ comp_values = Tbl.empty;
+ comp_constrs = Tbl.empty;
+ comp_labels = Tbl.empty;
+ comp_types = Tbl.empty;
+ comp_modules = Tbl.empty; comp_modtypes = Tbl.empty;
+ comp_components = Tbl.empty; comp_classes = Tbl.empty;
+ comp_cltypes = Tbl.empty }
+let get_components c =
+ match get_components_opt c with
+ | None -> empty_structure
+ | Some c -> c
(* The name of the compilation unit currently compiled.
"" if outside a compilation unit. *)
acknowledge_pers_struct check modname
{ Persistent_signature.filename; cmi }
-let can_load_cmis = ref true
-let without_cmis f x =
- Misc.(protect_refs [R (can_load_cmis, false)] (fun () -> f x))
-
let find_pers_struct check name =
if name = "*predef*" then raise Not_found;
match Hashtbl.find persistent_structures name with
| Some ps -> ps
| None -> raise Not_found
- | exception Not_found when !can_load_cmis ->
- let ps =
- match !Persistent_signature.load ~unit_name:name with
- | Some ps -> ps
- | None ->
- Hashtbl.add persistent_structures name None;
- raise Not_found
- in
- add_import name;
- acknowledge_pers_struct check name ps
+ | exception Not_found ->
+ match !can_load_cmis with
+ | Cannot_load_cmis _ -> raise Not_found
+ | Can_load_cmis ->
+ let ps =
+ match !Persistent_signature.load ~unit_name:name with
+ | Some ps -> ps
+ | None ->
+ Hashtbl.add persistent_structures name None;
+ raise Not_found
+ in
+ add_import name;
+ acknowledge_pers_struct check name ps
(* Emits a warning if there is no valid cmi for name *)
let check_pers_struct name =
let check_pers_struct name =
if not (Hashtbl.mem persistent_structures name) then begin
(* PR#6843: record the weak dependency ([add_import]) regardless of
- whether the check suceeds, to help make builds more
+ whether the check succeeds, to help make builds more
deterministic. *)
add_import name;
if (Warnings.is_active (Warnings.No_cmi_file("", None))) then
match path with
Pident id ->
begin try
- let (_p, desc) = EnvTbl.find_same id env.components
- in desc
+ IdTbl.find_same id env.components
with Not_found ->
if Ident.persistent id && not (Ident.name id = !current_unit)
then (find_pers_struct (Ident.name id)).ps_comps
| Pdot(p, s, _pos) ->
begin match get_components (find_module_descr p env) with
Structure_comps c ->
- let (descr, _pos) = Tbl.find s c.comp_components in
+ let (descr, _pos) = Tbl.find_str s c.comp_components in
descr
| Functor_comps _ ->
raise Not_found
let find proj1 proj2 path env =
match path with
Pident id ->
- let (_p, data) = EnvTbl.find_same id (proj1 env)
- in data
+ IdTbl.find_same id (proj1 env)
| Pdot(p, s, _pos) ->
begin match get_components (find_module_descr p env) with
Structure_comps c ->
- let (data, _pos) = Tbl.find s (proj2 c) in data
+ let (data, _pos) = Tbl.find_str s (proj2 c) in data
| Functor_comps _ ->
raise Not_found
end
type_of_cstr path cstr
| LocalExt id ->
let cstr =
- try EnvTbl.find_same id env.constrs
+ try TycompTbl.find_same id env.constrs
with Not_found -> assert false
in
type_of_cstr path cstr
in
let exts =
List.filter
- (function ({cstr_tag=Cstr_extension _}, _) -> true | _ -> false)
- (try Tbl.find s comps.comp_constrs
+ (function {cstr_tag=Cstr_extension _} -> true | _ -> false)
+ (try Tbl.find_str s comps.comp_constrs
with Not_found -> assert false)
in
match exts with
- | [(cstr, _)] -> type_of_cstr path cstr
+ | [cstr] -> type_of_cstr path cstr
| _ -> assert false
let find_type p env =
match path with
Pident id ->
begin try
- let (_p, data) = EnvTbl.find_same id env.modules
- in data
+ let data = IdTbl.find_same id env.modules in
+ EnvLazy.force subst_modtype_maker data
with Not_found ->
if Ident.persistent id && not (Ident.name id = !current_unit) then
let ps = find_pers_struct (Ident.name id) in
| Pdot(p, s, _pos) ->
begin match get_components (find_module_descr p env) with
Structure_comps c ->
- let (data, _pos) = Tbl.find s c.comp_modules in
- md (EnvLazy.force subst_modtype_maker data)
+ let (data, _pos) = Tbl.find_str s c.comp_modules in
+ EnvLazy.force subst_modtype_maker data
| Functor_comps _ ->
raise Not_found
end
match loc, deprecated with
| Some loc, Some txt ->
let txt = if txt = "" then "" else "\n" ^ txt in
- Location.prerr_warning loc
- (Warnings.Deprecated (Printf.sprintf "module %s%s"
- (Path.name p) txt))
+ Location.deprecated loc (Printf.sprintf "module %s%s" (Path.name p) txt)
| _ -> ()
let mark_module_used env name loc =
match lid with
Lident s ->
begin try
- EnvTbl.find_name s env.components
+ IdTbl.find_name s env.components
with Not_found ->
if s = !current_unit then raise Not_found;
let ps = find_pers_struct s in
let (p, descr) = lookup_module_descr ?loc l env in
begin match get_components descr with
Structure_comps c ->
- let (descr, pos) = Tbl.find s c.comp_components in
+ let (descr, pos) = Tbl.find_str s c.comp_components in
(Pdot(p, s, pos), descr)
| Functor_comps _ ->
raise Not_found
let {md_type=mty2} = find_module p2 env in
begin match get_components desc1 with
Functor_comps f ->
- Misc.may (!check_modtype_inclusion env mty2 p2) f.fcomp_arg;
+ let loc = match loc with Some l -> l | None -> Location.none in
+ Misc.may (!check_modtype_inclusion ~loc env mty2 p2) f.fcomp_arg;
(Papply(p1, p2), !components_of_functor_appl' f env p1 p2)
| Structure_comps _ ->
raise Not_found
match lid with
Lident s ->
begin try
- let (p, {md_type; md_attributes; md_loc}) =
- EnvTbl.find_name s env.modules
+ let (p, data) = IdTbl.find_name s env.modules in
+ let {md_loc; md_attributes; md_type} =
+ EnvLazy.force subst_modtype_maker data
in
mark_module_used env s md_loc;
begin match md_type with
let (p, descr) = lookup_module_descr ?loc l env in
begin match get_components descr with
Structure_comps c ->
- let (_data, pos) = Tbl.find s c.comp_modules in
- let (comps, _) = Tbl.find s c.comp_components in
+ let (_data, pos) = Tbl.find_str s c.comp_modules in
+ let (comps, _) = Tbl.find_str s c.comp_components in
mark_module_used env s comps.loc;
let p = Pdot(p, s, pos) in
report_deprecated ?loc p comps.deprecated;
let p = Papply(p1, p2) in
begin match get_components desc1 with
Functor_comps f ->
- Misc.may (!check_modtype_inclusion env mty2 p2) f.fcomp_arg;
+ let loc = match loc with Some l -> l | None -> Location.none in
+ Misc.may (!check_modtype_inclusion ~loc env mty2 p2) f.fcomp_arg;
p
| Structure_comps _ ->
raise Not_found
let lookup proj1 proj2 ?loc lid env =
match lid with
Lident s ->
- EnvTbl.find_name s (proj1 env)
+ IdTbl.find_name s (proj1 env)
| Ldot(l, s) ->
let (p, desc) = lookup_module_descr ?loc l env in
begin match get_components desc with
Structure_comps c ->
- let (data, pos) = Tbl.find s (proj2 c) in
+ let (data, pos) = Tbl.find_str s (proj2 c) in
(Pdot(p, s, pos), data)
| Functor_comps _ ->
raise Not_found
let lookup_all_simple proj1 proj2 shadow ?loc lid env =
match lid with
Lident s ->
- let xl = EnvTbl.find_all s (proj1 env) in
+ let xl = TycompTbl.find_all s (proj1 env) in
let rec do_shadow =
function
| [] -> []
begin match get_components desc with
Structure_comps c ->
let comps =
- try Tbl.find s (proj2 c) with Not_found -> []
+ try Tbl.find_str s (proj2 c) with Not_found -> []
in
List.map
- (fun (data, _pos) -> (data, (fun () -> ())))
+ (fun data -> (data, (fun () -> ())))
comps
| Functor_comps _ ->
raise Not_found
let lookup_value =
lookup (fun env -> env.values) (fun sc -> sc.comp_values)
-and lookup_all_constructors =
+let lookup_all_constructors =
lookup_all_simple (fun env -> env.constrs) (fun sc -> sc.comp_constrs)
cstr_shadow
-and lookup_all_labels =
+let lookup_all_labels =
lookup_all_simple (fun env -> env.labels) (fun sc -> sc.comp_labels)
lbl_shadow
-and lookup_type =
+let lookup_type =
lookup (fun env -> env.types) (fun sc -> sc.comp_types)
-and lookup_modtype =
+let lookup_modtype =
lookup (fun env -> env.modtypes) (fun sc -> sc.comp_modtypes)
-and lookup_class =
+let lookup_class =
lookup (fun env -> env.classes) (fun sc -> sc.comp_classes)
-and lookup_cltype =
+let lookup_cltype =
lookup (fun env -> env.cltypes) (fun sc -> sc.comp_cltypes)
-let update_value s f env =
- try
- let ((p, vd), slot) = Ident.find_name s env.values in
- match p with
- | Pident id ->
- let vd2 = f vd in
- {env with values = Ident.add id ((p, vd2), slot) env.values;
- summary = Env_value(env.summary, id, vd2)}
- | _ ->
- env
- with Not_found ->
- env
+let copy_types l env =
+ let f desc = {desc with val_type = Subst.type_expr Subst.identity desc.val_type} in
+ let values = List.fold_left (fun env s -> IdTbl.update s f env) env.values l in
+ {env with values; summary = Env_copy_types (env.summary, l)}
let mark_value_used env name vd =
if not (is_implicit_coercion env) then
| _ -> true
let iter_env proj1 proj2 f env () =
- Ident.iter (fun id (x,_) -> f (Pident id) x) (proj1 env);
+ IdTbl.iter (fun id x -> f (Pident id) x) (proj1 env);
let rec iter_components path path' mcomps =
let cont () =
let visit =
let id = Pident (Ident.create_persistent s) in
iter_components id id ps.ps_comps)
persistent_structures;
- Ident.iter
- (fun id ((path, comps), _) -> iter_components (Pident id) path comps)
+ IdTbl.iter
+ (fun id (path, comps) -> iter_components (Pident id) path comps)
env.components
let run_iter_cont l =
match get_components mcomps with
Functor_comps _ -> []
| Structure_comps comps ->
- try let (c,n) = Tbl.find s (proj comps) in [Pdot(p,s,n), c]
+ try let (c,n) = Tbl.find_str s (proj comps) in [Pdot(p,s,n), c]
with Not_found -> []
let rec find_shadowed_comps path env =
match path with
Pident id ->
- List.map fst (Ident.find_all (Ident.name id) env.components)
+ IdTbl.find_all (Ident.name id) env.components
| Pdot (p, s, _) ->
let l = find_shadowed_comps p env in
let l' =
let find_shadowed proj1 proj2 path env =
match path with
Pident id ->
- List.map fst (Ident.find_all (Ident.name id) (proj1 env))
+ IdTbl.find_all (Ident.name id) (proj1 env)
| Pdot (p, s, _) ->
let l = find_shadowed_comps p env in
let l' = List.map (find_all_comps proj2 s) l in
| Papply _ -> []
let find_shadowed_types path env =
- let l =
- find_shadowed
- (fun env -> env.types) (fun comps -> comps.comp_types) path env
- in
- List.map fst l
+ List.map fst
+ (find_shadowed
+ (fun env -> env.types) (fun comps -> comps.comp_types) path env)
(* GADT instance tracking *)
prefix_idents root pos (Subst.add_type id p sub) rem in
(p::pl, final_sub)
-let subst_signature sub sg =
- List.map
- (fun item ->
- match item with
- | Sig_value(id, decl) ->
- Sig_value (id, Subst.value_description sub decl)
- | Sig_type(id, decl, x) ->
- Sig_type(id, Subst.type_declaration sub decl, x)
- | Sig_typext(id, ext, es) ->
- Sig_typext (id, Subst.extension_constructor sub ext, es)
- | Sig_module(id, mty, x) ->
- Sig_module(id, Subst.module_declaration sub mty,x)
- | Sig_modtype(id, decl) ->
- Sig_modtype(id, Subst.modtype_declaration sub decl)
- | Sig_class(id, decl, x) ->
- Sig_class(id, Subst.class_declaration sub decl, x)
- | Sig_class_type(id, decl, x) ->
- Sig_class_type(id, Subst.cltype_declaration sub decl, x)
- )
- sg
-
-
-let prefix_idents_and_subst root sub sg =
- let (pl, sub) = prefix_idents root 0 sub sg in
- pl, sub, lazy (subst_signature sub sg)
-
-let prefix_idents_and_subst root sub sg =
+let prefix_idents root sub sg =
if sub = Subst.identity then
let sgs =
try
try
List.assq sg !sgs
with Not_found ->
- let r = prefix_idents_and_subst root sub sg in
+ let r = prefix_idents root 0 sub sg in
sgs := (sg, r) :: !sgs;
r
else
- prefix_idents_and_subst root sub sg
+ prefix_idents root 0 sub sg
(* Compute structure descriptions *)
let add_to_tbl id decl tbl =
let decls =
- try Tbl.find id tbl with Not_found -> [] in
+ try Tbl.find_str id tbl with Not_found -> [] in
Tbl.add id (decl :: decls) tbl
let rec components_of_module ~deprecated ~loc env sub path mty =
}
and components_of_module_maker (env, sub, path, mty) =
- (match scrape_alias env mty with
+ match scrape_alias env mty with
Mty_signature sg ->
let c =
{ comp_values = Tbl.empty;
comp_modules = Tbl.empty; comp_modtypes = Tbl.empty;
comp_components = Tbl.empty; comp_classes = Tbl.empty;
comp_cltypes = Tbl.empty } in
- let pl, sub, _ = prefix_idents_and_subst path sub sg in
+ let pl, sub = prefix_idents path sub sg in
let env = ref env in
let pos = ref 0 in
List.iter2 (fun item path ->
end
| Sig_type(id, decl, _) ->
let decl' = Subst.type_declaration sub decl in
+ Datarepr.set_row_name decl' (Subst.type_path sub (Path.Pident id));
let constructors =
List.map snd (Datarepr.constructors_of_type path decl') in
let labels =
List.iter
(fun descr ->
c.comp_constrs <-
- add_to_tbl descr.cstr_name (descr, nopos) c.comp_constrs)
+ add_to_tbl descr.cstr_name descr c.comp_constrs)
constructors;
List.iter
(fun descr ->
c.comp_labels <-
- add_to_tbl descr.lbl_name (descr, nopos) c.comp_labels)
+ add_to_tbl descr.lbl_name descr c.comp_labels)
labels;
- env := store_type_infos None id (Pident id) decl !env !env
+ env := store_type_infos id decl !env
| Sig_typext(id, ext, _) ->
let ext' = Subst.extension_constructor sub ext in
let descr = Datarepr.extension_descr path ext' in
c.comp_constrs <-
- add_to_tbl (Ident.name id) (descr, !pos) c.comp_constrs;
+ add_to_tbl (Ident.name id) descr c.comp_constrs;
incr pos
| Sig_module(id, md, _) ->
- let mty = md.md_type in
- let mty' = EnvLazy.create (sub, mty) in
+ let md' = EnvLazy.create (sub, md) in
c.comp_modules <-
- Tbl.add (Ident.name id) (mty', !pos) c.comp_modules;
+ Tbl.add (Ident.name id) (md', !pos) c.comp_modules;
let deprecated =
Builtin_attributes.deprecated_of_attrs md.md_attributes
in
let comps =
- components_of_module ~deprecated ~loc:md.md_loc !env sub path mty
+ components_of_module ~deprecated ~loc:md.md_loc !env sub path
+ md.md_type
in
c.comp_components <-
Tbl.add (Ident.name id) (comps, !pos) c.comp_components;
- env := store_module ~check:false None id (Pident id) md !env !env;
+ env := store_module ~check:false id md !env;
incr pos
| Sig_modtype(id, decl) ->
let decl' = Subst.modtype_declaration sub decl in
c.comp_modtypes <-
Tbl.add (Ident.name id) (decl', nopos) c.comp_modtypes;
- env := store_modtype None id (Pident id) decl !env !env
+ env := store_modtype id decl !env
| Sig_class(id, decl, _) ->
let decl' = Subst.class_declaration sub decl in
c.comp_classes <-
c.comp_cltypes <-
Tbl.add (Ident.name id) (decl', !pos) c.comp_cltypes)
sg pl;
- Structure_comps c
+ Some (Structure_comps c)
| Mty_functor(param, ty_arg, ty_res) ->
- Functor_comps {
+ Some (Functor_comps {
fcomp_param = param;
(* fcomp_arg and fcomp_res must be prefixed eagerly, because
they are interpreted in the outer environment *)
fcomp_arg = may_map (Subst.modtype sub) ty_arg;
fcomp_res = Subst.modtype sub ty_res;
fcomp_cache = Hashtbl.create 17;
- fcomp_subst_cache = Hashtbl.create 17 }
+ fcomp_subst_cache = Hashtbl.create 17 })
| Mty_ident _
- | Mty_alias _ ->
- Structure_comps {
- comp_values = Tbl.empty;
- comp_constrs = Tbl.empty;
- comp_labels = Tbl.empty;
- comp_types = Tbl.empty;
- comp_modules = Tbl.empty; comp_modtypes = Tbl.empty;
- comp_components = Tbl.empty; comp_classes = Tbl.empty;
- comp_cltypes = Tbl.empty })
+ | Mty_alias _ -> None
(* Insertion of bindings by identifier + path *)
done
-and store_value ?check slot id path decl env renv =
+and store_value ?check id decl env =
check_value_name (Ident.name id) decl.val_loc;
may (fun f -> check_usage decl.val_loc id f value_declarations) check;
{ env with
- values = EnvTbl.add slot (fun x -> `Value x) id (path, decl)
- env.values renv.values;
+ values = IdTbl.add id decl env.values;
summary = Env_value(env.summary, id, decl) }
-and store_type ~check slot id path info env renv =
+and store_type ~check id info env =
let loc = info.type_loc in
if check then
check_usage loc id (fun s -> Warnings.Unused_type_declaration s)
type_declarations;
+ let path = Pident id in
let constructors = Datarepr.constructors_of_type path info in
let labels = Datarepr.labels_of_type path info in
let descrs = (List.map snd constructors, List.map snd labels) in
{ env with
constrs =
List.fold_right
- (fun (id, descr) constrs ->
- EnvTbl.add slot (fun x -> `Constructor x) id descr constrs
- renv.constrs)
+ (fun (id, descr) constrs -> TycompTbl.add id descr constrs)
constructors
env.constrs;
labels =
List.fold_right
- (fun (id, descr) labels ->
- EnvTbl.add slot (fun x -> `Label x) id descr labels renv.labels)
+ (fun (id, descr) labels -> TycompTbl.add id descr labels)
labels
env.labels;
types =
- EnvTbl.add slot (fun x -> `Type x) id (path, (info, descrs)) env.types
- renv.types;
+ IdTbl.add id (info, descrs) env.types;
summary = Env_type(env.summary, id, info) }
-and store_type_infos slot id path info env renv =
+and store_type_infos id info env =
(* Simplified version of store_type that doesn't compute and store
constructor and label infos, but simply record the arity and
manifest-ness of the type. Used in components_of_module to
keep track of type abbreviations (e.g. type t = float) in the
computation of label representations. *)
{ env with
- types = EnvTbl.add slot (fun x -> `Type x) id (path, (info,([],[])))
- env.types renv.types;
+ types = IdTbl.add id (info,([],[]))
+ env.types;
summary = Env_type(env.summary, id, info) }
-and store_extension ~check slot id path ext env renv =
+and store_extension ~check id ext env =
let loc = ext.ext_loc in
if check && not loc.Location.loc_ghost &&
Warnings.is_active (Warnings.Unused_extension ("", false, false, false))
end;
end;
{ env with
- constrs = EnvTbl.add slot (fun x -> `Constructor x) id
- (Datarepr.extension_descr path ext)
- env.constrs renv.constrs;
+ constrs = TycompTbl.add id
+ (Datarepr.extension_descr (Pident id) ext)
+ env.constrs;
summary = Env_extension(env.summary, id, ext) }
-and store_module ~check slot id path md env renv =
+and store_module ~check id md env =
let loc = md.md_loc in
if check then
check_usage loc id (fun s -> Warnings.Unused_module s)
let deprecated = Builtin_attributes.deprecated_of_attrs md.md_attributes in
{ env with
- modules = EnvTbl.add slot (fun x -> `Module x) id (path, md)
- env.modules renv.modules;
+ modules = IdTbl.add id (EnvLazy.create (Subst.identity, md)) env.modules;
components =
- EnvTbl.add slot (fun x -> `Component x) id
- (path, components_of_module ~deprecated ~loc:md.md_loc
- env Subst.identity path md.md_type)
- env.components renv.components;
+ IdTbl.add id
+ (components_of_module ~deprecated ~loc:md.md_loc
+ env Subst.identity (Pident id) md.md_type)
+ env.components;
summary = Env_module(env.summary, id, md) }
-and store_modtype slot id path info env renv =
+and store_modtype id info env =
{ env with
- modtypes = EnvTbl.add slot (fun x -> `Module_type x) id (path, info)
- env.modtypes renv.modtypes;
+ modtypes = IdTbl.add id info env.modtypes;
summary = Env_modtype(env.summary, id, info) }
-and store_class slot id path desc env renv =
+and store_class id desc env =
{ env with
- classes = EnvTbl.add slot (fun x -> `Class x) id (path, desc)
- env.classes renv.classes;
+ classes = IdTbl.add id desc env.classes;
summary = Env_class(env.summary, id, desc) }
-and store_cltype slot id path desc env renv =
+and store_cltype id desc env =
{ env with
- cltypes = EnvTbl.add slot (fun x -> `Class_type x) id (path, desc)
- env.cltypes renv.cltypes;
+ cltypes = IdTbl.add id desc env.cltypes;
summary = Env_cltype(env.summary, id, desc) }
(* Compute the components of a functor application in a path. *)
summary = Env_functor_arg (env.summary, id)}
let add_value ?check id desc env =
- store_value None ?check id (Pident id) desc env env
+ store_value ?check id desc env
let add_type ~check id info env =
- store_type ~check None id (Pident id) info env env
+ store_type ~check id info env
and add_extension ~check id ext env =
- store_extension ~check None id (Pident id) ext env env
+ store_extension ~check id ext env
and add_module_declaration ?(arg=false) ~check id md env =
- let path =
- (*match md.md_type with
- Mty_alias path -> normalize_path env path
- | _ ->*) Pident id
- in
- let env = store_module ~check None id path md env env in
+ let env = store_module ~check id md env in
if arg then add_functor_arg id env else env
and add_modtype id info env =
- store_modtype None id (Pident id) info env env
+ store_modtype id info env
and add_class id ty env =
- store_class None id (Pident id) ty env env
+ store_class id ty env
and add_cltype id ty env =
- store_cltype None id (Pident id) ty env env
+ store_cltype id ty env
let add_module ?arg id mty env =
add_module_declaration ~check:false ?arg id (md mty) env
(* Insertion of bindings by name *)
let enter store_fun name data env =
- let id = Ident.create name in (id, store_fun None id (Pident id) data env env)
+ let id = Ident.create name in (id, store_fun id data env)
let enter_value ?check = enter (store_value ?check)
and enter_type = enter (store_type ~check:true)
(* Open a signature path *)
-let open_signature slot root sg env0 =
- (* First build the paths and substitution *)
- let (pl, _sub, sg) = prefix_idents_and_subst root Subst.identity sg in
- let sg = Lazy.force sg in
+let add_components slot root env0 comps =
+ let add_l w comps env0 =
+ TycompTbl.add_open slot w comps env0
+ in
- (* Then enter the components in the environment after substitution *)
+ let add w comps env0 = IdTbl.add_open slot w root comps env0 in
+
+ let constrs =
+ add_l (fun x -> `Constructor x) comps.comp_constrs env0.constrs
+ in
+ let labels =
+ add_l (fun x -> `Label x) comps.comp_labels env0.labels
+ in
+
+ let values =
+ add (fun x -> `Value x) comps.comp_values env0.values
+ in
+ let types =
+ add (fun x -> `Type x) comps.comp_types env0.types
+ in
+ let modtypes =
+ add (fun x -> `Module_type x) comps.comp_modtypes env0.modtypes
+ in
+ let classes =
+ add (fun x -> `Class x) comps.comp_classes env0.classes
+ in
+ let cltypes =
+ add (fun x -> `Class_type x) comps.comp_cltypes env0.cltypes
+ in
+ let components =
+ add (fun x -> `Component x) comps.comp_components env0.components
+ in
+
+ let modules =
+ add (fun x -> `Module x) comps.comp_modules env0.modules
+ in
+
+ { env0 with
+ summary = Env_open(env0.summary, root);
+ constrs;
+ labels;
+ values;
+ types;
+ modtypes;
+ classes;
+ cltypes;
+ components;
+ modules;
+ }
+
+let open_signature slot root env0 =
+ match get_components (find_module_descr root env0) with
+ | Functor_comps _ -> None
+ | Structure_comps comps -> Some (add_components slot root env0 comps)
- let newenv =
- List.fold_left2
- (fun env item p ->
- match item with
- Sig_value(id, decl) ->
- store_value slot (Ident.hide id) p decl env env0
- | Sig_type(id, decl, _) ->
- store_type ~check:false slot (Ident.hide id) p decl env env0
- | Sig_typext(id, ext, _) ->
- store_extension ~check:false slot (Ident.hide id) p ext env env0
- | Sig_module(id, mty, _) ->
- store_module ~check:false slot (Ident.hide id) p mty env env0
- | Sig_modtype(id, decl) ->
- store_modtype slot (Ident.hide id) p decl env env0
- | Sig_class(id, decl, _) ->
- store_class slot (Ident.hide id) p decl env env0
- | Sig_class_type(id, decl, _) ->
- store_cltype slot (Ident.hide id) p decl env env0
- )
- env0 sg pl in
- { newenv with summary = Env_open(env0.summary, root) }
(* Open a signature from a file *)
let open_pers_signature name env =
- let ps = find_pers_struct name in
- open_signature None (Pident(Ident.create_persistent name))
- (Lazy.force ps.ps_sig) env
+ match open_signature None (Pident(Ident.create_persistent name)) env with
+ | Some env -> env
+ | None -> assert false (* a compilation unit cannot refer to a functor *)
-let open_signature ?(loc = Location.none) ?(toplevel = false) ovf root sg env =
+let open_signature
+ ?(used_slot = ref false)
+ ?(loc = Location.none) ?(toplevel = false) ovf root env =
if not toplevel && ovf = Asttypes.Fresh && not loc.Location.loc_ghost
&& (Warnings.is_active (Warnings.Unused_open "")
|| Warnings.is_active (Warnings.Open_shadow_identifier ("", ""))
|| Warnings.is_active (Warnings.Open_shadow_label_constructor ("","")))
then begin
- let used = ref false in
+ let used = used_slot in
!add_delayed_check_forward
(fun () ->
- if not !used then
- Location.prerr_warning loc (Warnings.Unused_open (Path.name root))
+ if not !used then begin
+ used := true;
+ Location.prerr_warning loc (Warnings.Unused_open (Path.name root))
+ end
);
let shadowed = ref [] in
let slot s b =
end;
used := true
in
- open_signature (Some slot) root sg env
+ open_signature (Some slot) root env
end
- else open_signature None root sg env
+ else open_signature None root env
(* Read a signature from a file *)
(match deprecated with Some s -> [Deprecated s] | None -> []);
]
in
- let oc = open_out_bin filename in
try
let cmi = {
cmi_name = modname;
cmi_crcs = imports;
cmi_flags = flags;
} in
- let crc = output_cmi filename oc cmi in
- close_out oc;
+ let crc =
+ output_to_file_via_temporary (* see MPR#7472, MPR#4991 *)
+ ~mode: [Open_binary] filename
+ (fun temp_filename oc -> output_cmi temp_filename oc cmi) in
(* Enter signature in persistent table so that imported_unit()
will also return its crc *)
let comps =
save_pers_struct crc ps;
cmi
with exn ->
- close_out oc;
remove_file filename;
raise exn
let find_all proj1 proj2 f lid env acc =
match lid with
| None ->
- EnvTbl.fold_name
- (fun id (p, data) acc -> f (Ident.name id) p data acc)
+ IdTbl.fold_name
+ (fun name (p, data) acc -> f name p data acc)
(proj1 env) acc
| Some l ->
let p, desc = lookup_module_descr l env in
let find_all_simple_list proj1 proj2 f lid env acc =
match lid with
| None ->
- EnvTbl.fold_name
- (fun _id data acc -> f data acc)
+ TycompTbl.fold_name
+ (fun data acc -> f data acc)
(proj1 env) acc
| Some l ->
let (_p, desc) = lookup_module_descr l env in
(fun _s comps acc ->
match comps with
[] -> acc
- | (data, _pos) :: _ ->
+ | data :: _ ->
f data acc)
(proj2 c) acc
| Functor_comps _ ->
match lid with
| None ->
let acc =
- EnvTbl.fold_name
- (fun id (p, data) acc -> f (Ident.name id) p data acc)
+ IdTbl.fold_name
+ (fun name (p, data) acc ->
+ let data = EnvLazy.force subst_modtype_maker data in
+ f name p data acc
+ )
env.modules
acc
in
Tbl.fold
(fun s (data, pos) acc ->
f s (Pdot (p, s, pos))
- (md (EnvLazy.force subst_modtype_maker data)) acc)
+ (EnvLazy.force subst_modtype_maker data) acc)
c.comp_modules
acc
| Functor_comps _ ->
fprintf ppf
"@[<hov>Unit %s imports from %s, compiled with -unsafe-string.@ %s@]"
export import "This compiler has been configured in strict \
- -safe-string mode"
+ safe-string mode (-force-safe-string)"
| Missing_module(_, path1, path2) ->
fprintf ppf "@[@[<hov>";
if Path.same path1 path2 then
| Env_open of summary * Path.t
| Env_functor_arg of summary * Ident.t
| Env_constraints of summary * type_declaration PathMap.t
+ | Env_copy_types of summary * string list
type t
val lookup_cltype:
?loc:Location.t -> Longident.t -> t -> Path.t * class_type_declaration
-val update_value:
- string -> (value_description -> value_description) -> t -> t
+val copy_types: string list -> t -> t
(* Used only in Typecore.duplicate_ident_types. *)
exception Recmodule
val add_signature: signature -> t -> t
(* Insertion of all fields of a signature, relative to the given path.
- Used to implement open. *)
-
+ Used to implement open. Returns None if the path refers to a functor,
+ not a structure. *)
val open_signature:
+ ?used_slot:bool ref ->
?loc:Location.t -> ?toplevel:bool -> Asttypes.override_flag -> Path.t ->
- signature -> t -> t
+ t -> t option
+
val open_pers_signature: string -> t -> t
(* Insertion by name *)
(* Forward declaration to break mutual recursion with Includemod. *)
val check_modtype_inclusion:
- (t -> module_type -> Path.t -> module_type -> unit) ref
+ (loc:Location.t -> t -> module_type -> Path.t -> module_type -> unit) ref
(* Forward declaration to break mutual recursion with Typecore. *)
val add_delayed_check_forward: ((unit -> unit) -> unit) ref
(* Forward declaration to break mutual recursion with Mtype. *)
(* *)
(**************************************************************************)
-open Misc
-open Types
open Env
type error =
Hashtbl.clear env_cache;
Env.reset_cache()
-let extract_sig env mty =
- match Env.scrape_alias env mty with
- Mty_signature sg -> sg
- | _ -> fatal_error "Envaux.extract_sig"
-
let rec env_from_summary sum subst =
try
Hashtbl.find env_cache (sum, subst)
| Env_open(s, path) ->
let env = env_from_summary s subst in
let path' = Subst.module_path subst path in
- let md =
- try
- Env.find_module path' env
- with Not_found ->
- raise (Error (Module_not_found path'))
- in
- Env.open_signature Asttypes.Override path'
- (extract_sig env md.md_type) env
+ begin match Env.open_signature Asttypes.Override path' env with
+ | Some env -> env
+ | None -> assert false
+ end
| Env_functor_arg(Env_module(s, id, desc), id') when Ident.same id id' ->
Env.add_module_declaration ~check:false
id (Subst.module_declaration subst desc)
Env.add_local_type (Subst.type_path subst path)
(Subst.type_declaration subst info))
map (env_from_summary s subst)
+ | Env_copy_types (s, sl) ->
+ Env.copy_types sl (env_from_summary s subst)
in
Hashtbl.add env_cache (sum, subst) env;
env
| Node(l, k, r, _) ->
let c = compare name k.ident.name in
if c = 0 then
- k.data
+ k.ident, k.data
else
find_name name (if c < 0 then l else r)
let rec get_all = function
| None -> []
- | Some k -> k.data :: get_all k.previous
+ | Some k -> (k.ident, k.data) :: get_all k.previous
let rec find_all name = function
Empty ->
| Node(l, k, r, _) ->
let c = compare name k.ident.name in
if c = 0 then
- k.data :: get_all k.previous
+ (k.ident, k.data) :: get_all k.previous
else
find_all name (if c < 0 then l else r)
val empty: 'a tbl
val add: t -> 'a -> 'a tbl -> 'a tbl
val find_same: t -> 'a tbl -> 'a
-val find_name: string -> 'a tbl -> 'a
-val find_all: string -> 'a tbl -> 'a list
+val find_name: string -> 'a tbl -> t * 'a
+val find_all: string -> 'a tbl -> (t * 'a) list
val fold_name: (t -> 'a -> 'b -> 'b) -> 'a tbl -> 'b -> 'b
val fold_all: (t -> 'a -> 'b -> 'b) -> 'a tbl -> 'b -> 'b
val iter: (t -> 'a -> unit) -> 'a tbl -> unit
let class_types env cty1 cty2 =
Ctype.match_class_types env cty1 cty2
-let class_type_declarations env cty1 cty2 =
+let class_type_declarations ~loc env cty1 cty2 =
+ Builtin_attributes.check_deprecated_inclusion
+ ~def:cty1.clty_loc
+ ~use:cty2.clty_loc
+ loc
+ cty1.clty_attributes cty2.clty_attributes
+ (Path.last cty1.clty_path);
Ctype.match_class_declarations env
cty1.clty_params cty1.clty_type
cty2.clty_params cty2.clty_type
val class_types:
Env.t -> class_type -> class_type -> class_match_failure list
val class_type_declarations:
- Env.t -> class_type_declaration -> class_type_declaration ->
- class_match_failure list
+ loc:Location.t ->
+ Env.t -> class_type_declaration -> class_type_declaration ->
+ class_match_failure list
val class_declarations:
- Env.t -> class_declaration -> class_declaration ->
- class_match_failure list
+ Env.t -> class_declaration -> class_declaration ->
+ class_match_failure list
val report_error: formatter -> class_match_failure list -> unit
exception Dont_match
-let value_descriptions env vd1 vd2 =
+let value_descriptions ~loc env name
+ (vd1 : Types.value_description)
+ (vd2 : Types.value_description) =
+ Builtin_attributes.check_deprecated_inclusion
+ ~def:vd1.val_loc
+ ~use:vd2.val_loc
+ loc
+ vd1.val_attributes vd2.val_attributes
+ name;
if Ctype.moregeneral env true vd1.val_type vd2.val_type then begin
match (vd1.val_kind, vd2.val_kind) with
(Val_prim p1, Val_prim p2) ->
if err = Manifest then () else
Format.fprintf ppf "@ %a." (report_type_mismatch0 first second decl) err)
-let rec compare_constructor_arguments env cstr params1 params2 arg1 arg2 =
+let rec compare_constructor_arguments ~loc env cstr params1 params2 arg1 arg2 =
match arg1, arg2 with
| Types.Cstr_tuple arg1, Types.Cstr_tuple arg2 ->
if List.length arg1 <> List.length arg2 then [Field_arity cstr]
Ctype.equal env true (params1 @ arg1) (params2 @ arg2)
then [] else [Field_type cstr]
| Types.Cstr_record l1, Types.Cstr_record l2 ->
- compare_records env params1 params2 0 l1 l2
+ compare_records env ~loc params1 params2 0 l1 l2
| _ -> [Field_type cstr]
-and compare_variants env params1 params2 n cstrs1 cstrs2 =
+and compare_variants ~loc env params1 params2 n
+ (cstrs1 : Types.constructor_declaration list)
+ (cstrs2 : Types.constructor_declaration list) =
match cstrs1, cstrs2 with
[], [] -> []
| [], c::_ -> [Field_missing (true, c.Types.cd_id)]
| c::_, [] -> [Field_missing (false, c.Types.cd_id)]
- | {Types.cd_id=cstr1; cd_args=arg1; cd_res=ret1}::rem1,
- {Types.cd_id=cstr2; cd_args=arg2; cd_res=ret2}::rem2 ->
- if Ident.name cstr1 <> Ident.name cstr2 then
- [Field_names (n, cstr1, cstr2)]
- else
+ | cd1::rem1, cd2::rem2 ->
+ if Ident.name cd1.cd_id <> Ident.name cd2.cd_id then
+ [Field_names (n, cd1.cd_id, cd2.cd_id)]
+ else begin
+ Builtin_attributes.check_deprecated_inclusion
+ ~def:cd1.cd_loc
+ ~use:cd2.cd_loc
+ loc
+ cd1.cd_attributes cd2.cd_attributes
+ (Ident.name cd1.cd_id);
let r =
- match ret1, ret2 with
+ match cd1.cd_res, cd2.cd_res with
| Some r1, Some r2 ->
if Ctype.equal env true [r1] [r2] then
- compare_constructor_arguments env cstr1 [r1] [r2] arg1 arg2
- else [Field_type cstr1]
+ compare_constructor_arguments ~loc env cd1.cd_id [r1] [r2]
+ cd1.cd_args cd2.cd_args
+ else [Field_type cd1.cd_id]
| Some _, None | None, Some _ ->
- [Field_type cstr1]
+ [Field_type cd1.cd_id]
| _ ->
- compare_constructor_arguments env cstr1
- params1 params2 arg1 arg2
+ compare_constructor_arguments ~loc env cd1.cd_id
+ params1 params2 cd1.cd_args cd2.cd_args
in
if r <> [] then r
- else compare_variants env params1 params2 (n+1) rem1 rem2
+ else compare_variants ~loc env params1 params2 (n+1) rem1 rem2
+ end
-and compare_records env params1 params2 n labels1 labels2 =
+and compare_records ~loc env params1 params2 n
+ (labels1 : Types.label_declaration list)
+ (labels2 : Types.label_declaration list) =
match labels1, labels2 with
[], [] -> []
| [], l::_ -> [Field_missing (true, l.Types.ld_id)]
| l::_, [] -> [Field_missing (false, l.Types.ld_id)]
- | {Types.ld_id=lab1; ld_mutable=mut1; ld_type=arg1}::rem1,
- {Types.ld_id=lab2; ld_mutable=mut2; ld_type=arg2}::rem2 ->
- if Ident.name lab1 <> Ident.name lab2
- then [Field_names (n, lab1, lab2)]
- else if mut1 <> mut2 then [Field_mutable lab1] else
- if Ctype.equal env true (arg1::params1)
- (arg2::params2)
- then (* add arguments to the parameters, cf. PR#7378 *)
- compare_records env (arg1::params1) (arg2::params2) (n+1) rem1 rem2
- else [Field_type lab1]
+ | ld1::rem1, ld2::rem2 ->
+ if Ident.name ld1.ld_id <> Ident.name ld2.ld_id
+ then [Field_names (n, ld1.ld_id, ld2.ld_id)]
+ else if ld1.ld_mutable <> ld2.ld_mutable then [Field_mutable ld1.ld_id] else begin
+ Builtin_attributes.check_deprecated_mutable_inclusion
+ ~def:ld1.ld_loc
+ ~use:ld2.ld_loc
+ loc
+ ld1.ld_attributes ld2.ld_attributes
+ (Ident.name ld1.ld_id);
+ if Ctype.equal env true (ld1.ld_type::params1)(ld2.ld_type::params2)
+ then (* add arguments to the parameters, cf. PR#7378 *)
+ compare_records ~loc env
+ (ld1.ld_type::params1) (ld2.ld_type::params2)
+ (n+1)
+ rem1 rem2
+ else
+ [Field_type ld1.ld_id]
+ end
-let type_declarations ?(equality = false) env name decl1 id decl2 =
+let type_declarations ?(equality = false) ~loc env name decl1 id decl2 =
+ Builtin_attributes.check_deprecated_inclusion
+ ~def:decl1.type_loc
+ ~use:decl2.type_loc
+ loc
+ decl1.type_attributes decl2.type_attributes
+ name;
if decl1.type_arity <> decl2.type_arity then [Arity] else
if not (private_flags decl1 decl2) then [Privacy] else
let err = match (decl1.type_manifest, decl2.type_manifest) with
in
mark cstrs1 usage name decl1;
if equality then mark cstrs2 Env.Positive (Ident.name id) decl2;
- compare_variants env decl1.type_params decl2.type_params 1 cstrs1 cstrs2
+ compare_variants ~loc env decl1.type_params decl2.type_params 1 cstrs1 cstrs2
| (Type_record(labels1,rep1), Type_record(labels2,rep2)) ->
- let err = compare_records env decl1.type_params decl2.type_params
+ let err = compare_records ~loc env decl1.type_params decl2.type_params
1 labels1 labels2 in
if err <> [] || rep1 = rep2 then err else
[Record_representation (rep2 = Record_float)]
else []
in
if err <> [] then err else
+ let need_variance =
+ abstr || decl1.type_private = Private || decl1.type_kind = Type_open in
+ if not need_variance then [] else
let abstr = abstr || decl2.type_private = Private in
let opn = decl2.type_kind = Type_open && decl2.type_manifest = None in
let constrained ty = not (Btype.(is_Tvar (repr ty))) in
(* Inclusion between extension constructors *)
-let extension_constructors env id ext1 ext2 =
+let extension_constructors ~loc env id ext1 ext2 =
let usage =
if ext1.ext_private = Private || ext2.ext_private = Public
then Env.Positive else Env.Privatize
(ty1 :: ext1.ext_type_params)
(ty2 :: ext2.ext_type_params)
then
- if compare_constructor_arguments env (Ident.create "")
+ if compare_constructor_arguments ~loc env (Ident.create "")
ext1.ext_type_params ext2.ext_type_params
ext1.ext_args ext2.ext_args = [] then
if match ext1.ext_ret_type, ext2.ext_ret_type with
| Immediate
val value_descriptions:
- Env.t -> value_description -> value_description -> module_coercion
+ loc:Location.t -> Env.t -> string ->
+ value_description -> value_description -> module_coercion
+
val type_declarations:
- ?equality:bool ->
- Env.t -> string ->
- type_declaration -> Ident.t -> type_declaration -> type_mismatch list
+ ?equality:bool ->
+ loc:Location.t ->
+ Env.t -> string ->
+ type_declaration -> Ident.t -> type_declaration -> type_mismatch list
+
val extension_constructors:
- Env.t -> Ident.t -> extension_constructor -> extension_constructor -> bool
+ loc:Location.t ->
+ Env.t -> Ident.t ->
+ extension_constructor -> extension_constructor -> bool
(*
val class_types:
Env.t -> class_type -> class_type -> bool
(* Inclusion between value descriptions *)
-let value_descriptions env cxt subst id vd1 vd2 =
+let value_descriptions ~loc env cxt subst id vd1 vd2 =
Cmt_format.record_value_dependency vd1 vd2;
Env.mark_value_used env (Ident.name id) vd1;
let vd2 = Subst.value_description subst vd2 in
try
- Includecore.value_descriptions env vd1 vd2
+ Includecore.value_descriptions ~loc env (Ident.name id) vd1 vd2
with Includecore.Dont_match ->
raise(Error[cxt, env, Value_descriptions(id, vd1, vd2)])
(* Inclusion between type declarations *)
-let type_declarations env ?(old_env=env) cxt subst id decl1 decl2 =
+let type_declarations ~loc env ?(old_env=env) cxt subst id decl1 decl2 =
Env.mark_type_used env (Ident.name id) decl1;
let decl2 = Subst.type_declaration subst decl2 in
- let err = Includecore.type_declarations env (Ident.name id) decl1 id decl2 in
+ let err =
+ Includecore.type_declarations ~loc env (Ident.name id) decl1 id decl2
+ in
if err <> [] then
raise(Error[cxt, old_env, Type_declarations(id, decl1, decl2, err)])
(* Inclusion between extension constructors *)
-let extension_constructors env cxt subst id ext1 ext2 =
+let extension_constructors ~loc env cxt subst id ext1 ext2 =
let ext2 = Subst.extension_constructor subst ext2 in
- if Includecore.extension_constructors env id ext1 ext2
+ if Includecore.extension_constructors ~loc env id ext1 ext2
then ()
else raise(Error[cxt, env, Extension_constructors(id, ext1, ext2)])
(* Inclusion between class declarations *)
-let class_type_declarations ~old_env env cxt subst id decl1 decl2 =
+let class_type_declarations ~loc ~old_env env cxt subst id decl1 decl2 =
let decl2 = Subst.cltype_declaration subst decl2 in
- match Includeclass.class_type_declarations env decl1 decl2 with
+ match Includeclass.class_type_declarations ~loc env decl1 decl2 with
[] -> ()
| reason ->
raise(Error[cxt, old_env,
Return the restriction that transforms a value of the smaller type
into a value of the bigger type. *)
-let rec modtypes env cxt subst mty1 mty2 =
+let rec modtypes ~loc env cxt subst mty1 mty2 =
try
- try_modtypes env cxt subst mty1 mty2
+ try_modtypes ~loc env cxt subst mty1 mty2
with
Dont_match ->
raise(Error[cxt, env, Module_types(mty1, Subst.modtype subst mty2)])
raise(Error((cxt, env, Module_types(mty1, Subst.modtype subst mty2))
:: reasons))
-and try_modtypes env cxt subst mty1 mty2 =
+and try_modtypes ~loc env cxt subst mty1 mty2 =
match (mty1, mty2) with
| (Mty_alias(pres1, p1), Mty_alias(pres2, p2)) -> begin
if Env.is_functor_arg p2 env then
Mtype.strengthen ~aliasable:true env
(expand_module_alias env cxt p1) p1
in
- let cc = modtypes env cxt subst mty1 mty2 in
+ let cc = modtypes ~loc env cxt subst mty1 mty2 in
match pres1 with
| Mta_present -> cc
| Mta_absent -> Tcoerce_alias (p1, cc)
end
| (Mty_ident p1, _) when may_expand_module_path env p1 ->
- try_modtypes env cxt subst (expand_module_path env cxt p1) mty2
+ try_modtypes ~loc env cxt subst (expand_module_path env cxt p1) mty2
| (_, Mty_ident _) ->
- try_modtypes2 env cxt mty1 (Subst.modtype subst mty2)
+ try_modtypes2 ~loc env cxt mty1 (Subst.modtype subst mty2)
| (Mty_signature sig1, Mty_signature sig2) ->
- signatures env cxt subst sig1 sig2
+ signatures ~loc env cxt subst sig1 sig2
| (Mty_functor(param1, None, res1), Mty_functor(_param2, None, res2)) ->
- begin match modtypes env (Body param1::cxt) subst res1 res2 with
+ begin match modtypes ~loc env (Body param1::cxt) subst res1 res2 with
Tcoerce_none -> Tcoerce_none
| cc -> Tcoerce_functor (Tcoerce_none, cc)
end
| (Mty_functor(param1, Some arg1, res1),
Mty_functor(param2, Some arg2, res2)) ->
let arg2' = Subst.modtype subst arg2 in
- let cc_arg = modtypes env (Arg param1::cxt) Subst.identity arg2' arg1 in
+ let cc_arg = modtypes ~loc env (Arg param1::cxt) Subst.identity arg2' arg1 in
let cc_res =
- modtypes (Env.add_module param1 arg2' env) (Body param1::cxt)
+ modtypes ~loc (Env.add_module param1 arg2' env) (Body param1::cxt)
(Subst.add_module param2 (Pident param1) subst) res1 res2 in
begin match (cc_arg, cc_res) with
(Tcoerce_none, Tcoerce_none) -> Tcoerce_none
| (_, _) ->
raise Dont_match
-and try_modtypes2 env cxt mty1 mty2 =
+and try_modtypes2 ~loc env cxt mty1 mty2 =
(* mty2 is an identifier *)
match (mty1, mty2) with
(Mty_ident p1, Mty_ident p2)
(Env.normalize_path_prefix None env p2) ->
Tcoerce_none
| (_, Mty_ident p2) when may_expand_module_path env p2 ->
- try_modtypes env cxt Subst.identity mty1 (expand_module_path env cxt p2)
+ try_modtypes ~loc env cxt Subst.identity mty1 (expand_module_path env cxt p2)
| (_, _) ->
raise Dont_match
(* Inclusion between signatures *)
-and signatures env cxt subst sig1 sig2 =
+and signatures ~loc env cxt subst sig1 sig2 =
(* Environment used to check inclusion of components *)
let new_env =
Env.add_signature sig1 (Env.in_signature true env) in
begin match unpaired with
[] ->
let cc =
- signature_components env new_env cxt subst (List.rev paired)
+ signature_components ~loc env new_env cxt subst
+ (List.rev paired)
in
if len1 = len2 then (* see PR#5098 *)
simplify_structure_coercion cc id_pos_list
let name2, report =
match item2, name2 with
Sig_type (_, {type_manifest=None}, _), Field_type s
- when let l = String.length s in
- l >= 4 && String.sub s (l-4) 4 = "#row" ->
+ when Btype.is_row_name s ->
(* Do not report in case of failure,
as the main type will generate an error *)
Field_type (String.sub s 0 (String.length s - 4)), false
(* Inclusion between signature components *)
-and signature_components old_env env cxt subst paired =
- let comps_rec rem = signature_components old_env env cxt subst rem in
+and signature_components ~loc old_env env cxt subst paired =
+ let comps_rec rem = signature_components ~loc old_env env cxt subst rem in
match paired with
[] -> []
| (Sig_value(id1, valdecl1), Sig_value(_id2, valdecl2), pos) :: rem ->
- let cc = value_descriptions env cxt subst id1 valdecl1 valdecl2 in
+ let cc = value_descriptions ~loc env cxt subst id1 valdecl1 valdecl2 in
begin match valdecl2.val_kind with
Val_prim _ -> comps_rec rem
| _ -> (pos, cc) :: comps_rec rem
end
| (Sig_type(id1, tydecl1, _), Sig_type(_id2, tydecl2, _), _pos) :: rem ->
- type_declarations ~old_env env cxt subst id1 tydecl1 tydecl2;
+ type_declarations ~loc ~old_env env cxt subst id1 tydecl1 tydecl2;
comps_rec rem
| (Sig_typext(id1, ext1, _), Sig_typext(_id2, ext2, _), pos)
:: rem ->
- extension_constructors env cxt subst id1 ext1 ext2;
+ extension_constructors ~loc env cxt subst id1 ext1 ext2;
(pos, Tcoerce_none) :: comps_rec rem
| (Sig_module(id1, mty1, _), Sig_module(_id2, mty2, _), pos) :: rem ->
- let p1 = Pident id1 in
- Env.mark_module_used env (Ident.name id1) mty1.md_loc;
- let cc =
- modtypes env (Module id1::cxt) subst
- (Mtype.strengthen ~aliasable:true env mty1.md_type p1) mty2.md_type
- in
+ let cc = module_declarations ~loc env cxt subst id1 mty1 mty2 in
(pos, cc) :: comps_rec rem
| (Sig_modtype(id1, info1), Sig_modtype(_id2, info2), _pos) :: rem ->
- modtype_infos env cxt subst id1 info1 info2;
+ modtype_infos ~loc env cxt subst id1 info1 info2;
comps_rec rem
| (Sig_class(id1, decl1, _), Sig_class(_id2, decl2, _), pos) :: rem ->
class_declarations ~old_env env cxt subst id1 decl1 decl2;
(pos, Tcoerce_none) :: comps_rec rem
| (Sig_class_type(id1, info1, _),
Sig_class_type(_id2, info2, _), _pos) :: rem ->
- class_type_declarations ~old_env env cxt subst id1 info1 info2;
+ class_type_declarations ~loc ~old_env env cxt subst id1 info1 info2;
comps_rec rem
| _ ->
assert false
+and module_declarations ~loc env cxt subst id1 md1 md2 =
+ Builtin_attributes.check_deprecated_inclusion
+ ~def:md1.md_loc
+ ~use:md2.md_loc
+ loc
+ md1.md_attributes md2.md_attributes
+ (Ident.name id1);
+ let p1 = Pident id1 in
+ Env.mark_module_used env (Ident.name id1) md1.md_loc;
+ modtypes ~loc env (Module id1::cxt) subst
+ (Mtype.strengthen ~aliasable:true env md1.md_type p1) md2.md_type
+
(* Inclusion between module type specifications *)
-and modtype_infos env cxt subst id info1 info2 =
+and modtype_infos ~loc env cxt subst id info1 info2 =
+ Builtin_attributes.check_deprecated_inclusion
+ ~def:info1.mtd_loc
+ ~use:info2.mtd_loc
+ loc
+ info1.mtd_attributes info2.mtd_attributes
+ (Ident.name id);
let info2 = Subst.modtype_declaration subst info2 in
let cxt' = Modtype id :: cxt in
try
(None, None) -> ()
| (Some _, None) -> ()
| (Some mty1, Some mty2) ->
- check_modtype_equiv env cxt' mty1 mty2
+ check_modtype_equiv ~loc env cxt' mty1 mty2
| (None, Some mty2) ->
- check_modtype_equiv env cxt' (Mty_ident(Pident id)) mty2
+ check_modtype_equiv ~loc env cxt' (Mty_ident(Pident id)) mty2
with Error reasons ->
raise(Error((cxt, env, Modtype_infos(id, info1, info2)) :: reasons))
-and check_modtype_equiv env cxt mty1 mty2 =
+and check_modtype_equiv ~loc env cxt mty1 mty2 =
match
- (modtypes env cxt Subst.identity mty1 mty2,
- modtypes env cxt Subst.identity mty2 mty1)
+ (modtypes ~loc env cxt Subst.identity mty1 mty2,
+ modtypes ~loc env cxt Subst.identity mty2 mty1)
with
(Tcoerce_none, Tcoerce_none) -> ()
| (_c1, _c2) ->
in
no_apply path && not (Env.is_functor_arg path env)
-let check_modtype_inclusion env mty1 path1 mty2 =
+let check_modtype_inclusion ~loc env mty1 path1 mty2 =
try
let aliasable = can_alias env path1 in
- ignore(modtypes env [] Subst.identity
+ ignore(modtypes ~loc env [] Subst.identity
(Mtype.strengthen ~aliasable env mty1 path1) mty2)
with Error _ ->
raise Not_found
let compunit env impl_name impl_sig intf_name intf_sig =
try
- signatures env [] Subst.identity impl_sig intf_sig
+ signatures ~loc:(Location.in_file impl_name) env [] Subst.identity
+ impl_sig intf_sig
with Error reasons ->
raise(Error(([], Env.empty,Interface_mismatch(impl_name, intf_name))
:: reasons))
(* Hide the context and substitution parameters to the outside world *)
-let modtypes env mty1 mty2 = modtypes env [] Subst.identity mty1 mty2
-let signatures env sig1 sig2 = signatures env [] Subst.identity sig1 sig2
-let type_declarations env id decl1 decl2 =
- type_declarations env [] Subst.identity id decl1 decl2
+let modtypes ~loc env mty1 mty2 = modtypes ~loc env [] Subst.identity mty1 mty2
+let signatures env sig1 sig2 =
+ signatures ~loc:Location.none env [] Subst.identity sig1 sig2
+let type_declarations ~loc env id decl1 decl2 =
+ type_declarations ~loc env [] Subst.identity id decl1 decl2
(*
let modtypes env m1 m2 =
open Types
open Format
-val modtypes: Env.t -> module_type -> module_type -> module_coercion
+val modtypes:
+ loc:Location.t -> Env.t ->
+ module_type -> module_type -> module_coercion
+
val signatures: Env.t -> signature -> signature -> module_coercion
+
val compunit:
Env.t -> string -> signature -> string -> signature -> module_coercion
+
val type_declarations:
- Env.t -> Ident.t -> type_declaration -> type_declaration -> unit
+ loc:Location.t -> Env.t ->
+ Ident.t -> type_declaration -> type_declaration -> unit
+
val print_coercion: formatter -> module_coercion -> unit
type symptom =
try f ppf arg with
Ellipsis -> fprintf ppf "..."
+let print_lident ppf = function
+ | "::" -> pp_print_string ppf "(::)"
+ | s -> pp_print_string ppf s
+
let rec print_ident ppf =
function
- Oide_ident s -> pp_print_string ppf s
+ Oide_ident s -> print_lident ppf s
| Oide_dot (id, s) ->
- print_ident ppf id; pp_print_char ppf '.'; pp_print_string ppf s
+ print_ident ppf id; pp_print_char ppf '.'; print_lident ppf s
| Oide_apply (id1, id2) ->
fprintf ppf "%a(%a)" print_ident id1 print_ident id2
fprintf ppf fmt v;
if isneg then pp_print_char ppf ')'
+let escape_string s =
+ (* Escape only C0 control characters (bytes <= 0x1F), DEL(0x7F), '\\' and '"' *)
+ let n = ref 0 in
+ for i = 0 to String.length s - 1 do
+ n := !n +
+ (match String.unsafe_get s i with
+ | '\"' | '\\' | '\n' | '\t' | '\r' | '\b' -> 2
+ | '\x00' .. '\x1F'
+ | '\x7F' -> 4
+ | _ -> 1)
+ done;
+ if !n = String.length s then s else begin
+ let s' = Bytes.create !n in
+ n := 0;
+ for i = 0 to String.length s - 1 do
+ begin match String.unsafe_get s i with
+ | ('\"' | '\\') as c ->
+ Bytes.unsafe_set s' !n '\\'; incr n; Bytes.unsafe_set s' !n c
+ | '\n' ->
+ Bytes.unsafe_set s' !n '\\'; incr n; Bytes.unsafe_set s' !n 'n'
+ | '\t' ->
+ Bytes.unsafe_set s' !n '\\'; incr n; Bytes.unsafe_set s' !n 't'
+ | '\r' ->
+ Bytes.unsafe_set s' !n '\\'; incr n; Bytes.unsafe_set s' !n 'r'
+ | '\b' ->
+ Bytes.unsafe_set s' !n '\\'; incr n; Bytes.unsafe_set s' !n 'b'
+ | '\x00' .. '\x1F' | '\x7F' as c ->
+ let a = Char.code c in
+ Bytes.unsafe_set s' !n '\\';
+ incr n;
+ Bytes.unsafe_set s' !n (Char.chr (48 + a / 100));
+ incr n;
+ Bytes.unsafe_set s' !n (Char.chr (48 + (a / 10) mod 10));
+ incr n;
+ Bytes.unsafe_set s' !n (Char.chr (48 + a mod 10));
+ | c -> Bytes.unsafe_set s' !n c
+ end;
+ incr n
+ done;
+ Bytes.to_string s'
+ end
+
+
+let print_out_string ppf s =
+ let not_escaped =
+ (* let the user dynamically choose if strings should be escaped: *)
+ match Sys.getenv_opt "OCAMLTOP_UTF_8" with
+ | None -> true
+ | Some x ->
+ match bool_of_string_opt x with
+ | None -> true
+ | Some f -> f in
+ if not_escaped then
+ fprintf ppf "\"%s\"" (escape_string s)
+ else
+ fprintf ppf "%S" s
+
let print_out_value ppf tree =
let rec print_tree_1 ppf =
function
| Oval_int64 i -> parenthesize_if_neg ppf "%LiL" i (i < 0L)
| Oval_nativeint i -> parenthesize_if_neg ppf "%nin" i (i < 0n)
| Oval_float f -> parenthesize_if_neg ppf "%s" (float_repres f) (f < 0.0)
+ | Oval_string (_,_, Ostr_bytes) as tree ->
+ pp_print_char ppf '(';
+ print_simple_tree ppf tree;
+ pp_print_char ppf ')';
| tree -> print_simple_tree ppf tree
and print_simple_tree ppf =
function
| Oval_nativeint i -> fprintf ppf "%nin" i
| Oval_float f -> pp_print_string ppf (float_repres f)
| Oval_char c -> fprintf ppf "%C" c
- | Oval_string s ->
- begin try fprintf ppf "%S" s with
+ | Oval_string (s, maxlen, kind) ->
+ begin try
+ let len = String.length s in
+ let s = if len > maxlen then String.sub s 0 maxlen else s in
+ begin match kind with
+ | Ostr_bytes -> fprintf ppf "Bytes.of_string %S" s
+ | Ostr_string -> print_out_string ppf s
+ end;
+ (if len > maxlen then
+ fprintf ppf
+ "... (* string length %d; truncated *)" len
+ )
+ with
Invalid_argument _ (* "String.create" *)-> fprintf ppf "<huge string>"
end
| Oval_list tl ->
print_private td.otype_private
(print_list print_out_constr (fun ppf -> fprintf ppf "@ | ")) constrs
| Otyp_open ->
- fprintf ppf " = .."
+ fprintf ppf " =%a .."
+ print_private td.otype_private
| ty ->
fprintf ppf " =%a@;<1 2>%a"
print_private td.otype_private
| Oide_dot of out_ident * string
| Oide_ident of string
+type out_string =
+ | Ostr_string
+ | Ostr_bytes
+
type out_attribute =
{ oattr_name: string }
| Oval_list of out_value list
| Oval_printer of (Format.formatter -> unit)
| Oval_record of (out_ident * out_value) list
- | Oval_string of string
+ | Oval_string of string * int * out_string (* string, size-to-print, kind *)
| Oval_stuff of string
| Oval_tuple of out_value list
| Oval_variant of string * out_value option
| Tpat_tuple ps, Tpat_tuple qs -> compats ps qs
| Tpat_lazy p, Tpat_lazy q -> compat p q
| Tpat_construct (_, c1,ps1), Tpat_construct (_, c2,ps2) ->
- c1.cstr_tag = c2.cstr_tag && compats ps1 ps2
+ Types.equal_tag c1.cstr_tag c2.cstr_tag && compats ps1 ps2
| Tpat_variant(l1,Some p1, _r1), Tpat_variant(l2,Some p2,_) ->
l1=l2 && compat p1 p2
| Tpat_variant (l1,None, _r1), Tpat_variant(l2,None,_) ->
let simple_match p1 p2 =
match p1.pat_desc, p2.pat_desc with
| Tpat_construct(_, c1, _), Tpat_construct(_, c2, _) ->
- c1.cstr_tag = c2.cstr_tag
+ Types.equal_tag c1.cstr_tag c2.cstr_tag
| Tpat_variant(l1, _, _), Tpat_variant(l2, _, _) ->
l1 = l2
| Tpat_constant(c1), Tpat_constant(c2) -> const_compare c1 c2 = 0
let set_args q r = do_set_args false q r
and set_args_erase_mutable q r = do_set_args true q r
-(* filter pss acording to pattern q *)
+(* filter pss according to pattern q *)
let filter_one q pss =
let rec filter_rec = function
({pat_desc = Tpat_alias(p,_,_)}::ps)::pss ->
(*
Filter pss in the ``extra case''. This applies :
- According to an extra constructor (datatype case, non-complete signature).
- - Acordinng to anything (all-variables case).
+ - According to anything (all-variables case).
*)
let filter_extra pss =
let rec filter_rec = function
->
assert false
-(* Written as a non-fragile matching, PR7451 originated from a fragile matching below. *)
+(* Written as a non-fragile matching, PR#7451 originated from a fragile matching below. *)
let should_extend ext env = match ext with
| None -> false
| Some ext -> begin match env with
end
end
+module ConstructorTagHashtbl = Hashtbl.Make(
+ struct
+ type t = Types.constructor_tag
+ let hash = Hashtbl.hash
+ let equal = Types.equal_tag
+ end
+)
+
(* complement constructor tags *)
let complete_tags nconsts nconstrs tags =
let seen_const = Array.make nconsts false
| Cstr_block i -> seen_constr.(i) <- true
| _ -> assert false)
tags ;
- let r = ref [] in
+ let r = ConstructorTagHashtbl.create (nconsts+nconstrs) in
for i = 0 to nconsts-1 do
if not seen_const.(i) then
- r := Cstr_constant i :: !r
+ ConstructorTagHashtbl.add r (Cstr_constant i) ()
done ;
for i = 0 to nconstrs-1 do
if not seen_constr.(i) then
- r := Cstr_block i :: !r
+ ConstructorTagHashtbl.add r (Cstr_block i) ()
done ;
- !r
+ r
(* build a pattern from a constructor list *)
let pat_of_constr ex_pat cstr =
let not_tags = complete_tags c.cstr_consts c.cstr_nonconsts all_tags in
let constrs = get_variant_constructors p.pat_env c.cstr_res in
let others =
- List.filter (fun cnstr -> List.mem cnstr.cstr_tag not_tags) constrs in
+ List.filter
+ (fun cnstr -> ConstructorTagHashtbl.mem not_tags cnstr.cstr_tag)
+ constrs in
let const, nonconst =
List.partition (fun cnstr -> cnstr.cstr_arity = 0) others in
const @ nonconst
end
-(* Yet another satisfiable fonction *)
+(* Yet another satisfiable function *)
(*
This time every_satisfiable pss qs checks the
| _, Tpat_alias(q,_,_) -> le_pat p q
| Tpat_constant(c1), Tpat_constant(c2) -> const_compare c1 c2 = 0
| Tpat_construct(_,c1,ps), Tpat_construct(_,c2,qs) ->
- c1.cstr_tag = c2.cstr_tag && le_pats ps qs
+ Types.equal_tag c1.cstr_tag c2.cstr_tag && le_pats ps qs
| Tpat_variant(l1,Some p1,_), Tpat_variant(l2,Some p2,_) ->
(l1 = l2 && le_pat p1 p2)
| Tpat_variant(l1,None,_r1), Tpat_variant(l2,None,_) ->
let r = lub p q in
make_pat (Tpat_lazy r) p.pat_type p.pat_env
| Tpat_construct (lid, c1,ps1), Tpat_construct (_,c2,ps2)
- when c1.cstr_tag = c2.cstr_tag ->
+ when Types.equal_tag c1.cstr_tag c2.cstr_tag ->
let rs = lubs ps1 ps2 in
make_pat (Tpat_construct (lid, c1,rs))
p.pat_type p.pat_env
*)
begin match casel with
| [] -> ()
- | _ -> Location.prerr_warning loc Warnings.All_clauses_guarded
+ | _ ->
+ if Warnings.is_active Warnings.All_clauses_guarded then
+ Location.prerr_warning loc Warnings.All_clauses_guarded
end ;
Partial
| ps::_ ->
begin match v with
None -> Total
| Some v ->
- let errmsg =
- try
- let buf = Buffer.create 16 in
- let fmt = formatter_of_buffer buf in
- top_pretty fmt v;
- begin match check_partial_all v casel with
- | None -> ()
- | Some _ ->
- (* This is 'Some loc', where loc is the location of
- a possibly matching clause.
- Forget about loc, because printing two locations
- is a pain in the top-level *)
+ if Warnings.is_active (Warnings.Partial_match "") then begin
+ let errmsg =
+ try
+ let buf = Buffer.create 16 in
+ let fmt = formatter_of_buffer buf in
+ top_pretty fmt v;
+ begin match check_partial_all v casel with
+ | None -> ()
+ | Some _ ->
+ (* This is 'Some loc', where loc is the location of
+ a possibly matching clause.
+ Forget about loc, because printing two locations
+ is a pain in the top-level *)
+ Buffer.add_string buf
+ "\n(However, some guarded clause may match this value.)"
+ end;
+ if contains_extension v then
Buffer.add_string buf
- "\n(However, some guarded clause may match this value.)"
- end;
- if contains_extension v then
- Buffer.add_string buf
- "\nMatching over values of extensible variant types \
- (the *extension* above)\n\
- must include a wild card pattern in order to be exhaustive."
- ;
- Buffer.contents buf
- with _ ->
- ""
- in
- Location.prerr_warning loc (Warnings.Partial_match errmsg) ;
+ "\nMatching over values of extensible variant types \
+ (the *extension* above)\n\
+ must include a wild card pattern in order to be exhaustive."
+ ;
+ Buffer.contents buf
+ with _ ->
+ ""
+ in
+ Location.prerr_warning loc (Warnings.Partial_match errmsg)
+ end;
Partial
end
| _ ->
(*
Actual fragile check
1. Collect data types in the patterns of the match.
- 2. One exhautivity check per datatype, considering that
+ 2. One exhaustivity check per datatype, considering that
the type is extended.
*)
let irrefutable pat = le_pat pat omega
-(* An inactive pattern is a pattern whose matching needs only
- trivial computations (tag/equality tests).
- Patterns containing (lazy _) subpatterns are active. *)
-
-let rec inactive pat = match pat with
-| Tpat_lazy _ ->
- false
-| Tpat_any | Tpat_var _ | Tpat_constant _ | Tpat_variant (_, None, _) ->
- true
-| Tpat_tuple ps | Tpat_construct (_, _, ps) | Tpat_array ps ->
- List.for_all (fun p -> inactive p.pat_desc) ps
-| Tpat_alias (p,_,_) | Tpat_variant (_, Some p, _) ->
- inactive p.pat_desc
-| Tpat_record (ldps,_) ->
- List.exists (fun (_, _, p) -> inactive p.pat_desc) ldps
-| Tpat_or (p,q,_) ->
- inactive p.pat_desc && inactive q.pat_desc
-
-(* A `fluid' pattern is both irrefutable and inactive *)
-
-let fluid pat = irrefutable pat && inactive pat.pat_desc
-
+let inactive ~partial pat =
+ match partial with
+ | Partial -> false
+ | Total -> begin
+ let rec loop pat =
+ match pat.pat_desc with
+ | Tpat_lazy _ | Tpat_array _ ->
+ false
+ | Tpat_any | Tpat_var _ | Tpat_variant (_, None, _) ->
+ true
+ | Tpat_constant c -> begin
+ match c with
+ | Const_string _ -> Config.safe_string
+ | Const_int _ | Const_char _ | Const_float _
+ | Const_int32 _ | Const_int64 _ | Const_nativeint _ -> true
+ end
+ | Tpat_tuple ps | Tpat_construct (_, _, ps) ->
+ List.for_all (fun p -> loop p) ps
+ | Tpat_alias (p,_,_) | Tpat_variant (_, Some p, _) ->
+ loop p
+ | Tpat_record (ldps,_) ->
+ List.for_all
+ (fun (_, lbl, p) -> lbl.lbl_mut = Immutable && loop p)
+ ldps
+ | Tpat_or (p,q,_) ->
+ loop p && loop q
+ in
+ loop pat
+ end
-(********************************)
-(* Exported exhustiveness check *)
-(********************************)
+(*********************************)
+(* Exported exhaustiveness check *)
+(*********************************)
(*
Fragile check is performed when required and
*)
let check_partial_param do_check_partial do_check_fragile loc casel =
- if Warnings.is_active (Warnings.Partial_match "") then begin
- let pss = initial_matrix casel in
- let pss = get_mins le_pats pss in
- let total = do_check_partial loc casel pss in
- if
- total = Total && Warnings.is_active (Warnings.Fragile_match "")
- then begin
- do_check_fragile loc casel pss
- end ;
- total
- end else
- Partial
+ let pss = initial_matrix casel in
+ let pss = get_mins le_pats pss in
+ let total = do_check_partial loc casel pss in
+ if
+ total = Total && Warnings.is_active (Warnings.Fragile_match "")
+ then begin
+ do_check_fragile loc casel pss
+ end ;
+ total
(*let check_partial =
check_partial_param
| _ -> ()
(* Very hackish, detect unpack pattern compilation
- and perfom "indirect check for them" *)
+ and perform "indirect check for them" *)
let is_unpack exp =
List.exists
(fun (attr, _) -> attr.txt = "#modulepat") exp.exp_attributes
(* Irrefutability tests *)
val irrefutable : pattern -> bool
-val fluid : pattern -> bool
+
+(** An inactive pattern is a pattern, matching against which can be duplicated, erased or
+ delayed without change in observable behavior of the program. Patterns containing
+ (lazy _) subpatterns or reads of mutable fields are active. *)
+val inactive : partial:partial -> pattern -> bool
(* Ambiguous bindings *)
val check_ambiguous_bindings : case list -> unit
| Pdot(p, _s, _pos) -> head p
| Papply _ -> assert false
+let flatten =
+ let rec flatten acc = function
+ | Pident id -> `Ok (id, acc)
+ | Pdot (p, s, _) -> flatten (s :: acc) p
+ | Papply _ -> `Contains_apply
+ in
+ fun t -> flatten [] t
+
let heads p =
let rec heads p acc = match p with
| Pident id -> id :: acc
val compare: t -> t -> int
val isfree: Ident.t -> t -> bool
val binding_time: t -> int
+val flatten : t -> [ `Contains_apply | `Ok of Ident.t * string list ]
val nopos: int
and ident_lazy_t = ident_create "lazy_t"
and ident_string = ident_create "string"
and ident_extension_constructor = ident_create "extension_constructor"
+and ident_floatarray = ident_create "floatarray"
let path_int = Pident ident_int
and path_char = Pident ident_char
and path_lazy_t = Pident ident_lazy_t
and path_string = Pident ident_string
and path_extension_constructor = Pident ident_extension_constructor
+and path_floatarray = Pident ident_floatarray
let type_int = newgenty (Tconstr(path_int, [], ref Mnil))
and type_char = newgenty (Tconstr(path_char, [], ref Mnil))
and type_string = newgenty (Tconstr(path_string, [], ref Mnil))
and type_extension_constructor =
newgenty (Tconstr(path_extension_constructor, [], ref Mnil))
+and type_floatarray = newgenty (Tconstr(path_floatarray, [], ref Mnil))
let ident_match_failure = ident_create_predef_exn "Match_failure"
and ident_out_of_memory = ident_create_predef_exn "Out_of_memory"
add_type ident_char decl_abstr_imm (
add_type ident_int decl_abstr_imm (
add_type ident_extension_constructor decl_abstr (
- empty_env)))))))))))))))))))))))))))
+ add_type ident_floatarray decl_abstr (
+ empty_env))))))))))))))))))))))))))))
let build_initial_env add_type add_exception empty_env =
let common = common_initial_env add_type add_exception empty_env in
val type_int64: type_expr
val type_lazy_t: type_expr -> type_expr
val type_extension_constructor:type_expr
+val type_floatarray:type_expr
val path_int: Path.t
val path_char: Path.t
val path_int64: Path.t
val path_lazy_t: Path.t
val path_extension_constructor: Path.t
+val path_floatarray: Path.t
val path_match_failure: Path.t
val path_assert_failure : Path.t
explicit now (GPR#167): *)
let old_style_noalloc = old_style_noalloc || old_style_float in
if old_style_float then
- Location.prerr_warning valdecl.pval_loc
- (Warnings.Deprecated "[@@unboxed] + [@@noalloc] should be used instead \
- of \"float\"")
+ Location.deprecated valdecl.pval_loc
+ "[@@unboxed] + [@@noalloc] should be used instead of \"float\""
else if old_style_noalloc then
- Location.prerr_warning valdecl.pval_loc
- (Warnings.Deprecated "[@@noalloc] should be used instead of \
- \"noalloc\"");
+ Location.deprecated valdecl.pval_loc
+ "[@@noalloc] should be used instead of \"noalloc\"";
if native_name = "" &&
not (List.for_all is_ocaml_repr native_repr_args &&
is_ocaml_repr native_repr_res) then
(* Print a path *)
-let ident_pervasive = Ident.create_persistent "Pervasives"
+let ident_pervasives = Ident.create_persistent "Pervasives"
+let printing_env = ref Env.empty
+let non_shadowed_pervasive = function
+ | Pdot(Pident id, s, _pos) as path ->
+ Ident.same id ident_pervasives &&
+ (try Path.same path (Env.lookup_type (Lident s) !printing_env)
+ with Not_found -> true)
+ | _ -> false
let rec tree_of_path = function
| Pident id ->
Oide_ident (ident_name id)
- | Pdot(Pident id, s, _pos) when Ident.same id ident_pervasive ->
+ | Pdot(_, s, _pos) as path when non_shadowed_pervasive path ->
Oide_ident s
| Pdot(p, s, _pos) ->
Oide_dot (tree_of_path p, s)
let rec path ppf = function
| Pident id ->
ident ppf id
- | Pdot(Pident id, s, _pos) when Ident.same id ident_pervasive ->
+ | Pdot(_, s, _pos) as path when non_shadowed_pervasive path ->
pp_print_string ppf s
| Pdot(p, s, _pos) ->
path ppf p;
raw_type_list tl
| Tvariant row ->
fprintf ppf
- "@[<hov1>{@[%s@,%a;@]@ @[%s@,%a;@]@ %s%b;@ %s%b;@ @[<1>%s%t@]}@]"
+ "@[<hov1>{@[%s@,%a;@]@ @[%s@,%a;@]@ %s%B;@ %s%B;@ @[<1>%s%t@]}@]"
"row_fields="
(raw_list (fun ppf (l, f) ->
fprintf ppf "@[%s,@ %a@]" l raw_field f))
Rpresent None -> fprintf ppf "Rpresent None"
| Rpresent (Some t) -> fprintf ppf "@[<1>Rpresent(Some@,%a)@]" raw_type t
| Reither (c,tl,m,e) ->
- fprintf ppf "@[<hov1>Reither(%b,@,%a,@,%b,@,@[<1>ref%t@])@]" c
+ fprintf ppf "@[<hov1>Reither(%B,@,%a,@,%B,@,@[<1>ref%t@])@]" c
raw_type_list tl m
(fun ppf ->
match !e with None -> fprintf ppf " None"
| Nth n -> Nth (List.nth l1 n)
let apply_subst s1 tyl =
- match s1 with
- Nth n1 -> [List.nth tyl n1]
- | Map l1 -> List.map (List.nth tyl) l1
- | Id -> tyl
+ if tyl = [] then []
+ (* cf. PR#7543: Typemod.type_package doesn't respect type constructor arity *)
+ else
+ match s1 with
+ Nth n1 -> [List.nth tyl n1]
+ | Map l1 -> List.map (List.nth tyl) l1
+ | Id -> tyl
type best_path = Paths of Path.t list | Best of Path.t
-let printing_env = ref Env.empty
let printing_depth = ref 0
let printing_cont = ref ([] : Env.iter_cont list)
let printing_old = ref Env.empty
Env.same_types !printing_old env && Concr.equal !printing_pers used_pers
let set_printing_env env =
- printing_env := if !Clflags.real_paths then Env.empty else env;
- if !printing_env == Env.empty || same_printing_env env then () else
+ printing_env := env;
+ if !Clflags.real_paths
+ || !printing_env == Env.empty || same_printing_env env then () else
begin
(* printf "Reset printing_map@."; *)
printing_old := env;
let name_counter = ref 0
let named_vars = ref ([] : string list)
+let weak_counter = ref 1
+let weak_var_map = ref TypeMap.empty
+let named_weak_vars = ref StringSet.empty
+
let reset_names () = names := []; name_counter := 0; named_vars := []
let add_named_var ty =
match ty.desc with
named_vars := name :: !named_vars
| _ -> ()
+let name_is_already_used name =
+ List.mem name !named_vars
+ || List.exists (fun (_, name') -> name = name') !names
+ || StringSet.mem name !named_weak_vars
+
let rec new_name () =
let name =
if !name_counter < 26
else String.make 1 (Char.chr(97 + !name_counter mod 26)) ^
string_of_int(!name_counter / 26) in
incr name_counter;
- if List.mem name !named_vars
- || List.exists (fun (_, name') -> name = name') !names
- then new_name ()
- else name
+ if name_is_already_used name then new_name () else name
+
+let rec new_weak_name ty () =
+ let name = "weak" ^ string_of_int !weak_counter in
+ incr weak_counter;
+ if name_is_already_used name then new_weak_name ty ()
+ else begin
+ named_weak_vars := StringSet.add name !named_weak_vars;
+ weak_var_map := TypeMap.add ty name !weak_var_map;
+ name
+ end
-let name_of_type t =
+let name_of_type name_generator t =
(* We've already been through repr at this stage, so t is our representative
of the union-find class. *)
try List.assq t !names with Not_found ->
+ try TypeMap.find t !weak_var_map with Not_found ->
let name =
match t.desc with
Tvar (Some name) | Tunivar (Some name) ->
!current_name
| _ ->
(* No name available, create a new one *)
- new_name ()
+ name_generator ()
in
(* Exception for type declarations *)
if name <> "_" then names := (t, name) :: !names;
name
-let check_name_of_type t = ignore(name_of_type t)
+let check_name_of_type t = ignore(name_of_type new_name t)
let remove_names tyl =
let tyl = List.map repr tyl in
let px = proxy ty in
if List.mem_assq px !names && not (List.memq px !delayed) then
let mark = is_non_gen sch ty in
- Otyp_var (mark, name_of_type px) else
+ let name = name_of_type (if mark then new_weak_name ty else new_name) px in
+ Otyp_var (mark, name) else
let pr_typ () =
match ty.desc with
| Tvar _ ->
(*let lev =
if is_non_gen sch ty then "/" ^ string_of_int ty.level else "" in*)
- Otyp_var (is_non_gen sch ty, name_of_type ty)
+ let non_gen = is_non_gen sch ty in
+ let name_gen = if non_gen then new_weak_name ty else new_name in
+ Otyp_var (non_gen, name_of_type name_gen ty)
| Tarrow(l, ty1, ty2, _) ->
let pr_arrow l ty1 ty2 =
let lab =
| Tconstr(p, tyl, _abbrev) ->
let p', s = best_type_path p in
let tyl' = apply_subst s tyl in
- if is_nth s then tree_of_typexp sch (List.hd tyl') else
+ if is_nth s && not (tyl'=[]) then tree_of_typexp sch (List.hd tyl') else
Otyp_constr (tree_of_path p', tree_of_typlist sch tyl')
| Tvariant row ->
let row = row_repr row in
(* Make the names delayed, so that the real type is
printed once when used as proxy *)
List.iter add_delayed tyl;
- let tl = List.map name_of_type tyl in
+ let tl = List.map (name_of_type new_name) tyl in
let tr = Otyp_poly (tl, tree_of_typexp sch ty) in
(* Forget names when we leave scope *)
remove_names tyl;
delayed := old_delayed; tr
end
| Tunivar _ ->
- Otyp_var (false, name_of_type ty)
+ Otyp_var (false, name_of_type new_name ty)
| Tpackage (p, n, tyl) ->
let n =
List.map (fun li -> String.concat "." (Longident.flatten li)) n in
if List.memq px !delayed then delayed := List.filter ((!=) px) !delayed;
if is_aliased px && aliasable ty then begin
check_name_of_type px;
- Otyp_alias (pr_typ (), name_of_type px) end
+ Otyp_alias (pr_typ (), name_of_type new_name px) end
else pr_typ ()
and tree_of_row_field sch (l, f) =
decl.type_private
| Type_open ->
tree_of_manifest Otyp_open,
- Public
+ decl.type_private
in
let immediate =
Builtin_attributes.immediate decl.type_attributes
let sty = repr sign.csig_self in
let self_ty =
if is_aliased sty then
- Some (Otyp_var (false, name_of_type (proxy sty)))
+ Some (Otyp_var (false, name_of_type new_name (proxy sty)))
else None
in
let (fields, _) =
!Oprint.out_sig_item ppf (tree_of_modtype_declaration id decl)
(* For the toplevel: merge with tree_of_signature? *)
-let rec print_items showval env = function
+
+(* Refresh weak variable map in the toplevel *)
+let refresh_weak () =
+ let refresh t name (m,s) =
+ if is_non_gen true (repr t) then
+ begin
+ TypeMap.add t name m,
+ StringSet.add name s
+ end
+ else m, s in
+ let m, s =
+ TypeMap.fold refresh !weak_var_map (TypeMap.empty ,StringSet.empty) in
+ named_weak_vars := s;
+ weak_var_map := m
+
+let print_items showval env x =
+ refresh_weak();
+ let rec print showval env = function
| [] -> []
| item :: rem as items ->
let (_sg, rem) = filter_rem_sig item rem in
hide_rec_items items;
let trees = trees_of_sigitem item in
List.map (fun d -> (d, showval env item)) trees @
- print_items showval env rem
+ print showval env rem in
+ print showval env x
(* Print a signature body (used by -i when compiling a .ml) *)
| Labelled s -> line i ppf "Labelled \"%s\"\n" s
;;
+let record_representation i ppf = let open Types in function
+ | Record_regular -> line i ppf "Record_regular\n"
+ | Record_float -> line i ppf "Record_float\n"
+ | Record_unboxed b -> line i ppf "Record_unboxed %b\n" b
+ | Record_inlined i -> line i ppf "Record_inlined %d\n" i
+ | Record_extension -> line i ppf "Record_extension\n"
+
let attributes i ppf l =
let i = i + 1 in
List.iter
| Ttyp_object (l, c) ->
line i ppf "Ttyp_object %a\n" fmt_closed_flag c;
let i = i + 1 in
- List.iter
- (fun (s, attrs, t) ->
- line i ppf "method %s\n" s;
- attributes i ppf attrs;
- core_type (i + 1) ppf t
- )
- l
+ List.iter (function
+ | OTtag (s, attrs, t) ->
+ line i ppf "method %s\n" s.txt;
+ attributes i ppf attrs;
+ core_type (i + 1) ppf t
+ | OTinherit ct ->
+ line i ppf "OTinherit\n";
+ core_type (i + 1) ppf ct
+ ) l
| Ttyp_class (li, _, l) ->
line i ppf "Ttyp_class %a\n" fmt_path li;
list i core_type ppf l;
| Texp_variant (l, eo) ->
line i ppf "Texp_variant \"%s\"\n" l;
option i expression ppf eo;
- | Texp_record { fields; extended_expression; _ } ->
+ | Texp_record { fields; representation; extended_expression } ->
line i ppf "Texp_record\n";
- array i record_field ppf fields;
- option i expression ppf extended_expression;
+ let i = i+1 in
+ line i ppf "fields =\n";
+ array (i+1) record_field ppf fields;
+ line i ppf "representation =\n";
+ record_representation (i+1) ppf representation;
+ line i ppf "extended_expression =\n";
+ option (i+1) expression ppf extended_expression;
| Texp_field (e, li, _) ->
line i ppf "Texp_field\n";
expression i ppf e;
module_expr i ppf me;
expression i ppf e;
| Texp_letexception (cd, e) ->
- line i ppf "Pexp_letexception\n";
+ line i ppf "Texp_letexception\n";
extension_constructor i ppf cd;
expression i ppf e;
| Texp_assert (e) ->
arg_label i ppf l;
core_type i ppf co;
class_type i ppf cl;
+ | Tcty_open (ovf, m, _, _, e) ->
+ line i ppf "Tcty_open %a \"%a\"\n" fmt_override_flag ovf fmt_path m;
+ class_type i ppf e
and class_signature i ppf { csig_self = ct; csig_fields = l } =
line i ppf "class_signature\n";
class_expr i ppf ce;
class_type i ppf ct
| Tcl_constraint (ce, None, _, _, _) -> class_expr i ppf ce
+ | Tcl_open (ovf, m, _, _, e) ->
+ line i ppf "Tcty_open %a \"%a\"\n" fmt_override_flag ovf fmt_path m;
+ class_expr i ppf e
and class_structure i ppf { cstr_self = p; cstr_fields = l } =
line i ppf "class_structure\n";
and label_x_bool_x_core_type_list i ppf x =
match x with
Ttag (l, attrs, b, ctl) ->
- line i ppf "Rtag \"%s\" %s\n" l (string_of_bool b);
+ line i ppf "Ttag \"%s\" %s\n" l.txt (string_of_bool b);
attributes (i+1) ppf attrs;
list (i+1) core_type ppf ctl
| Tinherit (ct) ->
- line i ppf "Rinherit\n";
+ line i ppf "Tinherit\n";
core_type (i+1) ppf ct
;;
let dump filename =
if !Clflags.annotations then begin
- let info = get_info () in
- let pp =
- match filename with
- None -> stdout
- | Some filename -> open_out filename in
- sort_filter_phrases ();
- ignore (List.fold_left (print_info pp) Location.none info);
+ let do_dump _temp_filename pp =
+ let info = get_info () in
+ sort_filter_phrases ();
+ ignore (List.fold_left (print_info pp) Location.none info) in
begin match filename with
- | None -> ()
- | Some _ -> close_out pp
+ | None -> do_dump "" stdout
+ | Some filename ->
+ Misc.output_to_file_via_temporary ~mode:[Open_text] filename do_dump
end;
phrases := [];
end else begin
open Types
open Btype
+type type_replacement =
+ | Path of Path.t
+ | Type_function of { params : type_expr list; body : type_expr }
+
+module PathMap = Map.Make(Path)
+
type t =
- { types: (Ident.t, Path.t) Tbl.t;
- modules: (Ident.t, Path.t) Tbl.t;
+ { types: type_replacement PathMap.t;
+ modules: Path.t PathMap.t;
modtypes: (Ident.t, module_type) Tbl.t;
- for_saving: bool }
+ for_saving: bool;
+ }
let identity =
- { types = Tbl.empty; modules = Tbl.empty; modtypes = Tbl.empty;
- for_saving = false }
+ { types = PathMap.empty;
+ modules = PathMap.empty;
+ modtypes = Tbl.empty;
+ for_saving = false;
+ }
+
+let add_type_path id p s = { s with types = PathMap.add id (Path p) s.types }
+let add_type id p s = add_type_path (Pident id) p s
-let add_type id p s = { s with types = Tbl.add id p s.types }
+let add_type_function id ~params ~body s =
+ { s with types = PathMap.add id (Type_function { params; body }) s.types }
-let add_module id p s = { s with modules = Tbl.add id p s.modules }
+let add_module_path id p s = { s with modules = PathMap.add id p s.modules }
+let add_module id p s = add_module_path (Pident id) p s
let add_modtype id ty s = { s with modtypes = Tbl.add id ty s.modtypes }
then remove_loc.Ast_mapper.attributes remove_loc x
else x
-let rec module_path s = function
- Pident id as p ->
- begin try Tbl.find id s.modules with Not_found -> p end
- | Pdot(p, n, pos) ->
- Pdot(module_path s p, n, pos)
- | Papply(p1, p2) ->
- Papply(module_path s p1, module_path s p2)
+let rec module_path s path =
+ try PathMap.find path s.modules
+ with Not_found ->
+ match path with
+ | Pident _ -> path
+ | Pdot(p, n, pos) ->
+ Pdot(module_path s p, n, pos)
+ | Papply(p1, p2) ->
+ Papply(module_path s p1, module_path s p2)
let modtype_path s = function
Pident id as p ->
| Papply _ ->
fatal_error "Subst.modtype_path"
-let type_path s = function
- Pident id as p ->
- begin try Tbl.find id s.types with Not_found -> p end
- | Pdot(p, n, pos) ->
- Pdot(module_path s p, n, pos)
- | Papply _ ->
- fatal_error "Subst.type_path"
+let type_path s path =
+ match PathMap.find path s.types with
+ | Path p -> p
+ | Type_function _ -> assert false
+ | exception Not_found ->
+ match path with
+ | Pident _ -> path
+ | Pdot(p, n, pos) ->
+ Pdot(module_path s p, n, pos)
+ | Papply _ ->
+ fatal_error "Subst.type_path"
let type_path s p =
match Path.constructor_typath p with
| LocalExt _ -> type_path s p
| Ext (p, cstr) -> Pdot(module_path s p, cstr, nopos)
+let to_subst_by_type_function s p =
+ match PathMap.find p s.types with
+ | Path _ -> false
+ | Type_function _ -> true
+ | exception Not_found -> false
+
(* Special type ids for saved signatures *)
let new_id = ref (-1)
| Tunivar None -> tunivar_none
| d -> d
+let ctype_apply_env_empty = ref (fun _ -> assert false)
+
(* Similar to [Ctype.nondep_type_rec]. *)
let rec typexp s ty =
let ty = repr ty in
&& field_kind_repr k <> Fabsent && (repr ty).level < generic_level ->
(* do not copy the type of self when it is not generalized *)
ty
-(* cannot do it, since it would omit subsitution
+(* cannot do it, since it would omit substitution
| Tvariant row when not (static_row row) ->
ty
*)
Tconstr(type_path s (Pdot(m,i',pos)), tl, ref Mnil)
| _ -> assert false
else match desc with
- | Tconstr(p, tl, _abbrev) ->
- Tconstr(type_path s p, List.map (typexp s) tl, ref Mnil)
+ | Tconstr (p, args, _abbrev) ->
+ let args = List.map (typexp s) args in
+ begin match PathMap.find p s.types with
+ | exception Not_found -> Tconstr(type_path s p, args, ref Mnil)
+ | Path _ -> Tconstr(type_path s p, args, ref Mnil)
+ | Type_function { params; body } ->
+ (!ctype_apply_env_empty params body args).desc
+ end
| Tpackage(p, n, tl) ->
Tpackage(modtype_path s p, n, List.map (typexp s) tl)
| Tobject (t1, name) ->
ref (match !name with
None -> None
| Some (p, tl) ->
- Some (type_path s p, List.map (typexp s) tl)))
+ if to_subst_by_type_function s p
+ then None
+ else Some (type_path s p, List.map (typexp s) tl)))
| Tvariant row ->
let row = row_repr row in
let more = repr row.row_more in
let row =
copy_row (typexp s) true row (not dup) more' in
match row.row_name with
- Some (p, tl) ->
- Tvariant {row with row_name = Some (type_path s p, tl)}
+ | Some (p, tl) ->
+ Tvariant {row with row_name =
+ if to_subst_by_type_function s p
+ then None
+ else Some (type_path s p, tl)}
| None ->
Tvariant row
end
let merge_tbls f m1 m2 =
Tbl.fold (fun k d accu -> Tbl.add k (f d) accu) m1 m2
+let merge_path_maps f m1 m2 =
+ PathMap.fold (fun k d accu -> PathMap.add k (f d) accu) m1 m2
+
+let type_replacement s = function
+ | Path p -> Path (type_path s p)
+ | Type_function { params; body } ->
+ let params = List.map (typexp s) params in
+ let body = typexp s body in
+ Type_function { params; body }
+
(* Composition of substitutions:
apply (compose s1 s2) x = apply s2 (apply s1 x) *)
let compose s1 s2 =
- { types = merge_tbls (type_path s2) s1.types s2.types;
- modules = merge_tbls (module_path s2) s1.modules s2.modules;
+ { types = merge_path_maps (type_replacement s2) s1.types s2.types;
+ modules = merge_path_maps (module_path s2) s1.modules s2.modules;
modtypes = merge_tbls (modtype s2) s1.modtypes s2.modtypes;
- for_saving = s1.for_saving || s2.for_saving }
+ for_saving = s1.for_saving || s2.for_saving;
+ }
(*
Substitutions are used to translate a type from one context to
- another. This requires substituing paths for identifiers, and
+ another. This requires substituting paths for identifiers, and
possibly also lowering the level of non-generic variables so that
- it be inferior to the maximum level of the new context.
+ they are inferior to the maximum level of the new context.
Substitutions can also be used to create a "clean" copy of a type.
Indeed, non-variable node of a type are duplicated, with their
val identity: t
val add_type: Ident.t -> Path.t -> t -> t
+val add_type_path: Path.t -> Path.t -> t -> t
+val add_type_function:
+ Path.t -> params:type_expr list -> body:type_expr -> t -> t
val add_module: Ident.t -> Path.t -> t -> t
+val add_module_path: Path.t -> Path.t -> t -> t
val add_modtype: Ident.t -> module_type -> t -> t
val for_saving: t -> t
val reset_for_saving: unit -> unit
(* Composition of substitutions:
apply (compose s1 s2) x = apply s2 (apply s1 x) *)
val compose: t -> t -> t
+
+(* A forward reference to be filled in ctype.ml. *)
+val ctype_apply_env_empty:
+ (type_expr list -> type_expr -> type_expr list -> type_expr) ref
package_type: mapper -> package_type -> package_type;
pat: mapper -> pattern -> pattern;
row_field: mapper -> row_field -> row_field;
+ object_field: mapper -> object_field -> object_field;
signature: mapper -> signature -> signature;
signature_item: mapper -> signature_item -> signature_item;
structure: mapper -> structure -> structure;
)
| Tcl_ident (path, lid, tyl) ->
Tcl_ident (path, lid, List.map (sub.typ sub) tyl)
+ | Tcl_open (ovf, p, lid, env, e) ->
+ Tcl_open (ovf, p, lid, sub.env sub env, sub.class_expr sub e)
in
{x with cl_desc; cl_env}
sub.typ sub ct,
sub.class_type sub cl
)
+ | Tcty_open (ovf, p, lid, env, e) ->
+ Tcty_open (ovf, p, lid, sub.env sub env, sub.class_type sub e)
in
{x with cltyp_desc; cltyp_env}
| Ttyp_constr (path, lid, list) ->
Ttyp_constr (path, lid, List.map (sub.typ sub) list)
| Ttyp_object (list, closed) ->
- Ttyp_object (
- List.map (tuple3 id id (sub.typ sub)) list,
- closed
- )
+ Ttyp_object ((List.map (sub.object_field sub) list), closed)
| Ttyp_class (path, lid, list) ->
Ttyp_class
(path,
Ttag (label, attrs, b, List.map (sub.typ sub) list)
| Tinherit ct -> Tinherit (sub.typ sub ct)
+let object_field sub = function
+ | OTtag (label, attrs, ct) ->
+ OTtag (label, attrs, (sub.typ sub ct))
+ | OTinherit ct -> OTinherit (sub.typ sub ct)
+
let class_field_kind sub = function
| Tcfk_virtual ct -> Tcfk_virtual (sub.typ sub ct)
| Tcfk_concrete (ovf, e) -> Tcfk_concrete (ovf, sub.expr sub e)
package_type;
pat;
row_field;
+ object_field;
signature;
signature_item;
structure;
open Asttypes
open Typedtree
-(** {2 A generic Typedtree mapper} *)
+(** {1 A generic Typedtree mapper} *)
type mapper =
{
package_type: mapper -> package_type -> package_type;
pat: mapper -> pattern -> pattern;
row_field: mapper -> row_field -> row_field;
+ object_field: mapper -> object_field -> object_field;
signature: mapper -> signature -> signature;
signature_item: mapper -> signature_item -> signature_item;
structure: mapper -> structure -> structure;
so that we can get an immediate value. Is that correct ? Ask Jacques. *)
let returned_cty = ctyp Ttyp_any (Ctype.newty Tnil) val_env loc in
delayed_meth_specs :=
- lazy (
- let cty = transl_simple_type_univars val_env sty' in
- let ty = cty.ctyp_type in
- unif ty;
- returned_cty.ctyp_desc <- Ttyp_poly ([], cty);
- returned_cty.ctyp_type <- ty;
- ) ::
+ Warnings.mk_lazy (fun () ->
+ let cty = transl_simple_type_univars val_env sty' in
+ let ty = cty.ctyp_type in
+ unif ty;
+ returned_cty.ctyp_desc <- Ttyp_poly ([], cty);
+ returned_cty.ctyp_type <- ty;
+ ) ::
!delayed_meth_specs;
returned_cty
| _ ->
in
Vars.add lab (mut, virt, ty) val_sig
-let rec class_type_field env self_type meths
+let rec class_type_field env self_type meths arg ctf =
+ Builtin_attributes.warning_scope ctf.pctf_attributes
+ (fun () -> class_type_field_aux env self_type meths arg ctf)
+
+and class_type_field_aux env self_type meths
(fields, val_sig, concr_meths, inher) ctf =
+
let loc = ctf.pctf_loc in
let mkctf desc =
{ ctf_desc = desc; ctf_loc = loc; ctf_attributes = ctf.pctf_attributes }
val_sig, concr_meths, inher)
| Pctf_attribute x ->
- Builtin_attributes.warning_attribute [x];
+ Builtin_attributes.warning_attribute x;
(mkctf (Tctf_attribute x) :: fields,
val_sig, concr_meths, inher)
end;
(* Class type fields *)
- Builtin_attributes.warning_enter_scope ();
let (rev_fields, val_sig, concr_meths, inher) =
- List.fold_left (class_type_field env self_type meths)
- ([], Vars.empty, Concr.empty, [])
- sign
+ Builtin_attributes.warning_scope []
+ (fun () ->
+ List.fold_left (class_type_field env self_type meths)
+ ([], Vars.empty, Concr.empty, [])
+ sign
+ )
in
- Builtin_attributes.warning_leave_scope ();
let cty = {csig_self = self_type;
csig_vars = val_sig;
csig_concr = concr_meths;
}
and class_type env scty =
+ Builtin_attributes.warning_scope scty.pcty_attributes
+ (fun () -> class_type_aux env scty)
+
+and class_type_aux env scty =
let cltyp desc typ =
{
cltyp_desc = desc;
let clty = class_type env scty in
let typ = Cty_arrow (l, ty, clty.cltyp_type) in
cltyp (Tcty_arrow (l, cty, clty)) typ
+
+ | Pcty_open (ovf, lid, e) ->
+ let (path, newenv) = !Typecore.type_open ovf env scty.pcty_loc lid in
+ let clty = class_type newenv e in
+ cltyp (Tcty_open (ovf, path, lid, newenv, clty)) clty.cltyp_type
+
| Pcty_extension ext ->
raise (Error_forward (Builtin_attributes.error_of_extension ext))
(*******************************)
-let rec class_field self_loc cl_num self_type meths vars
+let rec class_field self_loc cl_num self_type meths vars arg cf =
+ Builtin_attributes.warning_scope cf.pcf_attributes
+ (fun () -> class_field_aux self_loc cl_num self_type meths vars arg cf)
+
+and class_field_aux self_loc cl_num self_type meths vars
(val_env, met_env, par_env, fields, concr_meths, warn_vals, inher,
- local_meths, local_vals)
- cf =
+ local_meths, local_vals) cf =
let loc = cf.pcf_loc in
let mkcf desc =
{ cf_desc = desc; cf_loc = loc; cf_attributes = cf.pcf_attributes }
let vars_local = !vars in
let field =
- lazy begin
- (* Read the generalized type *)
- let (_, ty) = Meths.find lab.txt !meths in
- let meth_type =
- Btype.newgenty (Tarrow(Nolabel, self_type, ty, Cok)) in
- Ctype.raise_nongen_level ();
- vars := vars_local;
- let texp = type_expect met_env meth_expr meth_type in
- Ctype.end_def ();
- mkcf (Tcf_method (lab, priv, Tcfk_concrete (ovf, texp)))
- end in
+ Warnings.mk_lazy
+ (fun () ->
+ (* Read the generalized type *)
+ let (_, ty) = Meths.find lab.txt !meths in
+ let meth_type =
+ Btype.newgenty (Tarrow(Nolabel, self_type, ty, Cok)) in
+ Ctype.raise_nongen_level ();
+ vars := vars_local;
+ let texp = type_expect met_env meth_expr meth_type in
+ Ctype.end_def ();
+ mkcf (Tcf_method (lab, priv, Tcfk_concrete (ovf, texp)))
+ )
+ in
(val_env, met_env, par_env, field::fields,
Concr.add lab.txt concr_meths, warn_vals, inher,
Concr.add lab.txt local_meths, local_vals)
(val_env, met_env, par_env, field::fields, concr_meths, warn_vals,
inher, local_meths, local_vals)
| Pcf_attribute x ->
- Builtin_attributes.warning_attribute [x];
+ Builtin_attributes.warning_attribute x;
(val_env, met_env, par_env,
lazy (mkcf (Tcf_attribute x)) :: fields,
concr_meths, warn_vals, inher, local_meths, local_vals)
end;
(* Typing of class fields *)
- Builtin_attributes.warning_enter_scope ();
let (_, _, _, fields, concr_meths, _, inher, _local_meths, _local_vals) =
- List.fold_left (class_field self_loc cl_num self_type meths vars)
- (val_env, meth_env, par_env, [], Concr.empty, Concr.empty, [],
- Concr.empty, Concr.empty)
- str
+ Builtin_attributes.warning_scope []
+ (fun () ->
+ List.fold_left (class_field self_loc cl_num self_type meths vars)
+ (val_env, meth_env, par_env, [], Concr.empty, Concr.empty, [],
+ Concr.empty, Concr.empty)
+ str
+ )
in
- Builtin_attributes.warning_leave_scope ();
Ctype.unify val_env self_type (Ctype.newvar ());
let sign =
{csig_self = public_self;
cstr_meths = meths}, sign (* redondant, since already in cstr_type *)
and class_expr cl_num val_env met_env scl =
+ Builtin_attributes.warning_scope scl.pcl_attributes
+ (fun () -> class_expr_aux cl_num val_env met_env scl)
+
+and class_expr_aux cl_num val_env met_env scl =
match scl.pcl_desc with
Pcl_constr (lid, styl) ->
let (path, decl) = Typetexp.find_class val_env scl.pcl_loc lid.txt in
([], met_env)
in
let cl = class_expr cl_num val_env met_env scl' in
+ let () = if rec_flag = Recursive then
+ check_recursive_bindings val_env defs
+ in
rc {cl_desc = Tcl_let (rec_flag, defs, vals, cl);
cl_loc = scl.pcl_loc;
cl_type = cl.cl_type;
cl_env = val_env;
cl_attributes = scl.pcl_attributes;
}
+ | Pcl_open (ovf, lid, e) ->
+ let used_slot = ref false in
+ let (path, new_val_env) = !Typecore.type_open ~used_slot ovf val_env scl.pcl_loc lid in
+ let (_path, new_met_env) = !Typecore.type_open ~used_slot ovf met_env scl.pcl_loc lid in
+ let cl = class_expr cl_num new_val_env new_met_env e in
+ rc {cl_desc = Tcl_open (ovf, path, lid, new_val_env, cl);
+ cl_loc = scl.pcl_loc;
+ cl_type = cl.cl_type;
+ cl_env = val_env;
+ cl_attributes = scl.pcl_attributes;
+ }
| Pcl_extension ext ->
raise (Error_forward (Builtin_attributes.error_of_extension ext))
})
(* (cl.pci_variance, cl.pci_loc)) *)
+let class_infos define_class kind
+ (cl, id, ty_id,
+ obj_id, obj_params, obj_ty,
+ cl_id, cl_params, cl_ty,
+ constr_type, dummy_class)
+ (res, env) =
+ Builtin_attributes.warning_scope cl.pci_attributes
+ (fun () ->
+ class_infos define_class kind
+ (cl, id, ty_id,
+ obj_id, obj_params, obj_ty,
+ cl_id, cl_params, cl_ty,
+ constr_type, dummy_class)
+ (res, env)
+ )
+
let extract_type_decls
(_id, _id_loc, clty, _ty_id, cltydef, obj_id, obj_abbr, _cl_id, cl_abbr,
_arity, _pub_meths, _coe, _expr, required) decls =
(expr, expr.cltyp_type)
let class_declarations env cls =
- type_classes true approx_declaration class_declaration env cls
+ let info, env =
+ type_classes true approx_declaration class_declaration env cls
+ in
+ let ids, exprs =
+ List.split
+ (List.map
+ (fun ci -> ci.cls_id, ci.cls_info.ci_expr)
+ info)
+ in
+ check_recursive_class_bindings env ids exprs;
+ info, env
let class_descriptions env cls =
type_classes true approx_description class_description env cls
| _exn -> assert false
end
| Tcl_structure st -> unify_parents_struct env ty st
+ | Tcl_open (_, _, _, _, cl)
| Tcl_fun (_, _, _, cl, _)
| Tcl_apply (cl, _)
| Tcl_let (_, _, _, cl)
| Not_an_extension_constructor
| Literal_overflow of string
| Unknown_literal of string * char
+ | Illegal_letrec_pat
+ | Illegal_letrec_expr
+ | Illegal_class_expr
exception Error of Location.t * Env.t * error
exception Error_forward of Location.error
(* Forward declaration, to be filled in by Typemod.type_open *)
-let type_open =
- ref (fun _ -> assert false)
+let type_open :
+ (?used_slot:bool ref -> override_flag -> Env.t -> Location.t ->
+ Longident.t loc -> Path.t * Env.t)
+ ref =
+ ref (fun ?used_slot:_ _ -> assert false)
(* Forward declaration, to be filled in by Typemod.type_package *)
class_expr ce; List.iter (fun (_, e) -> expr e) lel
| Pcl_let (_, pel, ce) ->
List.iter binding pel; class_expr ce
+ | Pcl_open (_, _, ce)
| Pcl_constraint (ce, _) -> class_expr ce
| Pcl_extension _ -> ()
explode > 0 => explode Ppat_any for gadts *)
let rec type_pat ~constrs ~labels ~no_existentials ~mode ~explode ~env
sp expected_ty k =
+ Builtin_attributes.warning_scope sp.ppat_attributes
+ (fun () ->
+ type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env
+ sp expected_ty k
+ )
+
+and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env
+ sp expected_ty k =
let mode' = if mode = Splitting_or then Normal else mode in
let type_pat ?(constrs=constrs) ?(labels=labels) ?(mode=mode')
?(explode=explode) ?(env=env) =
let type_pattern_list env spatl scope expected_tys allow =
reset_pattern scope allow;
let new_env = ref env in
- let patl = List.map2 (type_pat new_env) spatl expected_tys in
+ let type_pat (attrs, pat) ty =
+ Builtin_attributes.warning_scope ~ppwarning:false attrs
+ (fun () ->
+ type_pat new_env pat ty
+ )
+ in
+ let patl = List.map2 type_pat spatl expected_tys in
let new_env, unpacks = add_pattern_variables !new_env in
(patl, new_env, get_ref pattern_force, unpacks)
is_nonexpansive_mod mexp && is_nonexpansive e
| Texp_pack mexp ->
is_nonexpansive_mod mexp
+ (* Computations which raise exceptions are nonexpansive, since (raise e) is equivalent
+ to (raise e; diverge), and a nonexpansive "diverge" can be produced using lazy values
+ or the relaxed value restriction. See GPR#1142 *)
+ | Texp_assert exp ->
+ is_nonexpansive exp
+ | Texp_apply (
+ { exp_desc = Texp_ident (_, _, {val_kind =
+ Val_prim {Primitive.prim_name = "%raise"}}) },
+ [Nolabel, Some e]) ->
+ is_nonexpansive e
| _ -> false
and is_nonexpansive_mod mexp =
None -> true
| Some e -> is_nonexpansive e
+module Env' = Env
+module Rec_context =
+struct
+ type access =
+ Dereferenced
+ (** [Dereferenced] indicates that the value (not just the address) of a
+ variable is accessed *)
+
+ | Guarded
+ (** [Guarded] indicates that the address of a variable is used in a
+ guarded context, i.e. under a constructor. A variable that is
+ dereferenced within a function body or lazy context is also considered
+ guarded. *)
+
+ | Unguarded
+ (** [Unguarded] indicates that the address of a variable is used in an
+ unguarded context, i.e. not under a constructor. *)
+
+ (** [guard] represents guarded contexts such as [C -] and [{l = -}] *)
+ let guard : access -> access = function
+ | Dereferenced -> Dereferenced
+ | Guarded -> Guarded
+ | Unguarded -> Guarded
+
+ (** [inspect] represents elimination contexts such as [match - with cases],
+ [e -] and [- e] *)
+ let inspect : access -> access = function
+ | Dereferenced -> Dereferenced
+ | Guarded -> Dereferenced
+ | Unguarded -> Dereferenced
+
+ (** [delay] represents contexts that delay evaluation such as [fun p -> -]
+ or [lazy -] *)
+ let delay : access -> access = function
+ | Dereferenced -> Guarded
+ | Guarded -> Guarded
+ | Unguarded -> Guarded
+
+ module Use :
+ sig
+ type t
+ val guard : t -> t
+ (** An expression appears in a guarded context *)
+
+ val discard : t -> t
+ (** The address of a subexpression is not used, but may be bound *)
+
+ val inspect : t -> t
+ (** The value of a subexpression is inspected with match, application, etc. *)
+
+ val delay : t -> t
+ (** An expression appears under 'fun p ->' or 'lazy' *)
+
+ val join : t -> t -> t
+ (** Combine the access information of two expressions *)
+
+ val single : Ident.t -> access -> t
+ (** Combine the access information of two expressions *)
+
+ val empty : t
+ (** No variables are accessed in an expression; it might be a
+ constant or a global identifier *)
+
+ val unguarded : t -> Ident.t list
+ (** The list of identifiers that are used in an unguarded context *)
+
+ val dependent : t -> Ident.t list
+ (** The list of all used identifiers *)
+ end =
+ struct
+ module M = Map.Make(Ident)
+
+ (** A "t" maps each rec-bound variable to an access status *)
+ type t = access M.t
+
+ let map f tbl = M.map f tbl
+ let guard t = map guard t
+ let inspect t = map inspect t
+ let delay t = map delay t
+ let discard = guard
+
+ let prec x y =
+ match x, y with
+ | Dereferenced, _
+ | _, Dereferenced -> Dereferenced
+ | Unguarded, _
+ | _, Unguarded -> Unguarded
+ | _ -> Guarded
+
+ let join x y =
+ M.fold
+ (fun id v tbl ->
+ let v' = try M.find id tbl with Not_found -> Guarded in
+ M.add id (prec v v') tbl)
+ x y
+
+ let single id access = M.add id access M.empty
+
+ let empty = M.empty
+
+ let list_matching p t =
+ let r = ref [] in
+ M.iter (fun id v -> if p v then r := id :: !r) t;
+ !r
+
+ let unguarded =
+ list_matching (function Unguarded | Dereferenced -> true | _ -> false)
+
+ let dependent =
+ list_matching (function _ -> true)
+ end
+
+ module Env =
+ struct
+ (* A typing environment maps identifiers to types *)
+ type env = Use.t Ident.tbl
+
+ let empty = Ident.empty
+
+ let join x y =
+ let r =
+ Ident.fold_all
+ (fun id v tbl ->
+ let v' = try Ident.find_same id tbl with Not_found -> Use.empty in
+ Ident.add id (Use.join v v') tbl)
+ x
+ y
+ in
+ r
+ end
+end
+
+let rec pattern_variables : Typedtree.pattern -> Ident.t list =
+ fun pat -> match pat.pat_desc with
+ | Tpat_any -> []
+ | Tpat_var (id, _) -> [id]
+ | Tpat_alias (pat, id, _) -> id :: pattern_variables pat
+ | Tpat_constant _ -> []
+ | Tpat_tuple pats -> List.concat (List.map pattern_variables pats)
+ | Tpat_construct (_, _, pats) ->
+ List.concat (List.map pattern_variables pats)
+ | Tpat_variant (_, Some pat, _) -> pattern_variables pat
+ | Tpat_variant (_, None, _) -> []
+ | Tpat_record (fields, _) ->
+ List.concat (List.map (fun (_,_,p) -> pattern_variables p) fields)
+ | Tpat_array pats ->
+ List.concat (List.map pattern_variables pats)
+ | Tpat_or (l,r,_) ->
+ pattern_variables l @ pattern_variables r
+ | Tpat_lazy p ->
+ pattern_variables p
+
+module Rec_check =
+struct
+ open Rec_context
+
+ let build_unguarded_env : Ident.t list -> Env.env = fun idlist ->
+ List.fold_left
+ (fun env id -> Ident.add id (Use.single id Unguarded) env)
+ Env.empty
+ idlist
+
+ let is_ref : Types.value_description -> bool = function
+ | { Types.val_kind =
+ Types.Val_prim { Primitive.prim_name = "%makemutable";
+ prim_arity = 1 } } ->
+ true
+ | _ -> false
+
+ let scrape env ty =
+ (Ctype.repr (Ctype.expand_head_opt env (Ctype.correct_levels ty))).desc
+
+ let array_element_kind env ty =
+ match scrape env ty with
+ | Tvar _ | Tunivar _ ->
+ `Pgenarray
+ | Tconstr(p, _, _) ->
+ if Path.same p Predef.path_int || Path.same p Predef.path_char then
+ `Pintarray
+ else if Path.same p Predef.path_float then
+ `Pfloatarray
+ else if Path.same p Predef.path_string
+ || Path.same p Predef.path_array
+ || Path.same p Predef.path_nativeint
+ || Path.same p Predef.path_int32
+ || Path.same p Predef.path_int64 then
+ `Paddrarray
+ else begin
+ try
+ match Env'.find_type p env with
+ {type_kind = Type_abstract} ->
+ `Pgenarray
+ | {type_kind = Type_variant cstrs}
+ when List.for_all (fun c -> c.Types.cd_args = Types.Cstr_tuple [])
+ cstrs ->
+ `Pintarray
+ | {type_kind = _} ->
+ `Paddrarray
+ with Not_found ->
+ (* This can happen due to e.g. missing -I options,
+ causing some .cmi files to be unavailable.
+ Maybe we should emit a warning. *)
+ `Pgenarray
+ end
+ | _ ->
+ `Paddrarray
+
+ let array_type_kind env ty =
+ match scrape env ty with
+ | Tconstr(p, [elt_ty], _) | Tpoly({desc = Tconstr(p, [elt_ty], _)}, _)
+ when Path.same p Predef.path_array ->
+ array_element_kind env elt_ty
+ | _ ->
+ (* This can happen with e.g. Obj.field *)
+ `Pgenarray
+
+ let array_kind exp = array_type_kind exp.exp_env exp.exp_type
+
+ let has_concrete_element_type : Typedtree.expression -> bool =
+ fun e -> array_kind e <> `Pgenarray
+
+ type sd = Static | Dynamic
+
+ let rec classify_expression : Typedtree.expression -> sd =
+ fun exp -> match exp.exp_desc with
+ | Texp_let (_, _, e)
+ | Texp_letmodule (_, _, _, e)
+ | Texp_sequence (_, e)
+ | Texp_letexception (_, e) -> classify_expression e
+ | Texp_ident _
+ | Texp_for _
+ | Texp_constant _
+ | Texp_new _
+ | Texp_instvar _
+ | Texp_tuple _
+ | Texp_array _
+ | Texp_construct _
+ | Texp_variant _
+ | Texp_record _
+ | Texp_setfield _
+ | Texp_while _
+ | Texp_setinstvar _
+ | Texp_pack _
+ | Texp_object _
+ | Texp_function _
+ | Texp_lazy _
+ | Texp_unreachable
+ | Texp_extension_constructor _ -> Static
+ | Texp_apply ({exp_desc = Texp_ident (_, _, vd)}, _)
+ when is_ref vd -> Static
+ | Texp_apply _
+ | Texp_match _
+ | Texp_ifthenelse _
+ | Texp_send _
+ | Texp_field _
+ | Texp_assert _
+ | Texp_try _
+ | Texp_override _ -> Dynamic
+
+ let rec expression : Env.env -> Typedtree.expression -> Use.t =
+ fun env exp -> match exp.exp_desc with
+ | Texp_ident (pth, _, _) ->
+ (path env pth)
+ | Texp_let (rec_flag, bindings, body) ->
+ let env', ty = value_bindings rec_flag env bindings in
+ (* Here and in other binding constructs 'discard' is used in a
+ similar way to the way it's used in sequence: uses are
+ propagated, but unguarded access are not. *)
+ Use.join (Use.discard ty) (expression (Env.join env env') body)
+ | Texp_letmodule (x, _, m, e) ->
+ let ty = modexp env m in
+ Use.join (Use.discard ty) (expression (Ident.add x ty env) e)
+ | Texp_match (e, val_cases, exn_cases, _) ->
+ let t = expression env e in
+ let exn_case env {Typedtree.c_rhs} = expression env c_rhs in
+ let cs = list (case ~scrutinee:t) env val_cases
+ and es = list exn_case env exn_cases in
+ Use.(join cs es)
+ | Texp_for (_, _, e1, e2, _, e3) ->
+ Use.(join
+ (join
+ (inspect (expression env e1))
+ (inspect (expression env e2)))
+ (* The body is evaluated, but not used, and not available
+ for inclusion in another value *)
+ (discard (expression env e3)))
+
+ | Texp_constant _ ->
+ Use.empty
+ | Texp_new (pth, _, _) ->
+ Use.inspect (path env pth)
+ | Texp_instvar _ ->
+ Use.empty
+ | Texp_apply ({exp_desc = Texp_ident (_, _, vd)}, [_, Some arg])
+ when is_ref vd ->
+ Use.guard (expression env arg)
+ | Texp_apply (e, args) ->
+ let arg env (_, eo) = option expression env eo in
+ Use.(join
+ (inspect (expression env e))
+ (inspect (list arg env args)))
+ | Texp_tuple exprs ->
+ Use.guard (list expression env exprs)
+ | Texp_array exprs when array_kind exp = `Pfloatarray ->
+ Use.inspect (list expression env exprs)
+ | Texp_array exprs when has_concrete_element_type exp ->
+ Use.guard (list expression env exprs)
+ | Texp_array exprs ->
+ (* This is counted as a use, because constructing a generic array
+ involves inspecting the elements (PR#6939). *)
+ Use.inspect (list expression env exprs)
+ | Texp_construct (_, desc, exprs) ->
+ let access_constructor =
+ match desc.cstr_tag with
+ | Cstr_extension (pth, _) -> Use.inspect (path env pth)
+ | _ -> Use.empty
+ in
+ let use = match desc.cstr_tag with
+ | Cstr_unboxed -> (fun x -> x)
+ | Cstr_constant _ | Cstr_block _ | Cstr_extension _ -> Use.guard
+ in
+ Use.join access_constructor (use (list expression env exprs))
+ | Texp_variant (_, eo) ->
+ Use.guard (option expression env eo)
+ | Texp_record { fields = es; extended_expression = eo;
+ representation = rep } ->
+ let use = match rep with
+ | Record_float -> Use.inspect
+ | Record_unboxed _ -> (fun x -> x)
+ | Record_regular | Record_inlined _
+ | Record_extension -> Use.guard
+ in
+ let field env = function
+ _, Kept _ -> Use.empty
+ | _, Overridden (_, e) -> expression env e
+ in
+ Use.join
+ (use (array field env es))
+ (option expression env eo)
+ | Texp_ifthenelse (cond, ifso, ifnot) ->
+ Use.(join (inspect (expression env cond))
+ (join
+ (expression env ifso)
+ (option expression env ifnot)))
+ | Texp_setfield (e1, _, _, e2) ->
+ Use.(join (inspect (expression env e1))
+ (inspect (expression env e2)))
+ | Texp_sequence (e1, e2) ->
+ Use.(join (discard (expression env e1))
+ (expression env e2))
+ | Texp_while (e1, e2) ->
+ Use.(join (inspect (expression env e1))
+ (discard (expression env e2)))
+ | Texp_send (e1, _, eo) ->
+ Use.(join (inspect (expression env e1))
+ (inspect (option expression env eo)))
+ | Texp_field (e, _, _) ->
+ Use.(inspect (expression env e))
+ | Texp_setinstvar (_,_,_,e) ->
+ Use.(inspect (expression env e))
+ | Texp_letexception (_, e) ->
+ expression env e
+ | Texp_assert e ->
+ Use.inspect (expression env e)
+ | Texp_pack m ->
+ modexp env m
+ | Texp_object (clsstrct, _) ->
+ class_structure env clsstrct
+ | Texp_try (e, cases) ->
+ (* This is more permissive than the old check. *)
+ let case env {Typedtree.c_rhs} = expression env c_rhs in
+ Use.join (expression env e)
+ (list case env cases)
+ | Texp_override (_, fields) ->
+ let field env (_, _, e) = expression env e in
+ Use.inspect (list field env fields)
+ | Texp_function { cases } ->
+ Use.delay (list (case ~scrutinee:Use.empty) env cases)
+ | Texp_lazy e ->
+ begin match Typeopt.classify_lazy_argument e with
+ | `Constant_or_function
+ | `Identifier _
+ | `Float ->
+ expression env e
+ | `Other ->
+ Use.delay (expression env e)
+ end
+ | Texp_unreachable ->
+ Use.empty
+ | Texp_extension_constructor _ ->
+ Use.empty
+ and option : 'a. (Env.env -> 'a -> Use.t) -> Env.env -> 'a option -> Use.t =
+ fun f env -> Misc.Stdlib.Option.value_default (f env) ~default:Use.empty
+ and list : 'a. (Env.env -> 'a -> Use.t) -> Env.env -> 'a list -> Use.t =
+ fun f env ->
+ List.fold_left (fun typ item -> Use.join (f env item) typ) Use.empty
+ and array : 'a. (Env.env -> 'a -> Use.t) -> Env.env -> 'a array -> Use.t =
+ fun f env ->
+ Array.fold_left (fun typ item -> Use.join (f env item) typ) Use.empty
+ and class_structure : Env.env -> Typedtree.class_structure -> Use.t =
+ fun env cs -> Use.(inspect (list class_field env cs.cstr_fields))
+ and class_field : Env.env -> Typedtree.class_field -> Use.t =
+ fun env cf -> match cf.cf_desc with
+ | Tcf_inherit (_, ce, _super, _inh_vars, _inh_meths) ->
+ Use.inspect (class_expr env ce)
+ | Tcf_val (_lab, _mut, _, cfk, _) ->
+ class_field_kind env cfk
+ | Tcf_method (_, _, cfk) ->
+ class_field_kind env cfk
+ | Tcf_constraint _ ->
+ Use.empty
+ | Tcf_initializer e ->
+ Use.inspect (expression env e)
+ | Tcf_attribute _ ->
+ Use.empty
+ and class_field_kind : Env.env -> Typedtree.class_field_kind -> Use.t =
+ fun env cfk -> match cfk with
+ | Tcfk_virtual _ ->
+ Use.empty
+ | Tcfk_concrete (_, e) ->
+ Use.inspect (expression env e)
+ and modexp : Env.env -> Typedtree.module_expr -> Use.t =
+ fun env m -> match m.mod_desc with
+ | Tmod_ident (pth, _) ->
+ (path env pth)
+ | Tmod_structure s ->
+ structure env s
+ | Tmod_functor (_, _, _, e) ->
+ Use.delay (modexp env e)
+ | Tmod_apply (f, p, _) ->
+ Use.(join
+ (inspect (modexp env f))
+ (inspect (modexp env p)))
+ | Tmod_constraint (m, _, _, Tcoerce_none) ->
+ modexp env m
+ | Tmod_constraint (m, _, _, _) ->
+ Use.inspect (modexp env m)
+ | Tmod_unpack (e, _) ->
+ expression env e
+ and path : Env.env -> Path.t -> Use.t =
+ fun env pth -> match pth with
+ | Path.Pident x ->
+ (try Ident.find_same x env with Not_found -> Use.empty)
+ | Path.Pdot (t, _, _) ->
+ Use.inspect (path env t)
+ | Path.Papply (f, p) ->
+ Use.(inspect (join (path env f) (path env p)))
+ and structure : Env.env -> Typedtree.structure -> Use.t =
+ fun env s ->
+ let _, ty =
+ List.fold_left
+ (fun (env, ty) item ->
+ let env', ty' = structure_item env item in
+ Env.join env env', Use.join ty ty')
+ (env, Use.empty)
+ s.str_items
+ in
+ Use.guard ty
+ and structure_item : Env.env -> Typedtree.structure_item -> Env.env * Use.t =
+ fun env s -> match s.str_desc with
+ | Tstr_eval (e, _) ->
+ Env.empty, expression env e
+ | Tstr_value (rec_flag, valbinds) ->
+ value_bindings rec_flag env valbinds
+ | Tstr_module {mb_id; mb_expr} ->
+ let ty = modexp env mb_expr in
+ Ident.add mb_id ty Env.empty, ty
+ | Tstr_recmodule mbs ->
+ let modbind env {mb_expr} = modexp env mb_expr in
+ (* Over-approximate: treat any access as a use *)
+ Env.empty, Use.inspect (list modbind env mbs)
+ | Tstr_primitive _ ->
+ Env.empty, Use.empty
+ | Tstr_type _ ->
+ Env.empty, Use.empty
+ | Tstr_typext _ ->
+ Env.empty, Use.empty
+ | Tstr_exception _ ->
+ Env.empty, Use.empty
+ | Tstr_modtype _ ->
+ Env.empty, Use.empty
+ | Tstr_open _ ->
+ Env.empty, Use.empty
+ | Tstr_class classes ->
+ (* Any occurrence in a class definition is counted as a use,
+ so there's no need to add anything to the environment. *)
+ let cls env ({ci_expr=ce}, _) = class_expr env ce in
+ Env.empty, Use.inspect (list cls env classes)
+ | Tstr_class_type _ ->
+ Env.empty, Use.empty
+ | Tstr_include inc ->
+ (* This is a kind of projection. There's no need to add
+ anything to the environment because everything is used in
+ the type component already *)
+ Env.empty, Use.inspect (modexp env inc.incl_mod)
+ | Tstr_attribute _ ->
+ Env.empty, Use.empty
+ and class_expr : Env.env -> Typedtree.class_expr -> Use.t =
+ fun env ce -> match ce.cl_desc with
+ | Tcl_ident (pth, _, _) ->
+ Use.inspect (path env pth)
+ | Tcl_structure cs ->
+ class_structure env cs
+ | Tcl_fun (_, _, args, ce, _) ->
+ let arg env (_, _, e) = expression env e in
+ Use.inspect (Use.join (list arg env args)
+ (class_expr env ce))
+ | Tcl_apply (ce, args) ->
+ let arg env (_, eo) = option expression env eo in
+ Use.inspect (Use.join (class_expr env ce)
+ (list arg env args))
+ | Tcl_let (rec_flag, valbinds, _, ce) ->
+ let _, ty = value_bindings rec_flag env valbinds in
+ Use.(inspect (join ty (class_expr env ce)))
+ | Tcl_constraint (ce, _, _, _, _) ->
+ class_expr env ce
+ | Tcl_open (_, _, _, _, ce) ->
+ class_expr env ce
+ and case : Env.env -> Typedtree.case -> scrutinee:Use.t -> Use.t =
+ fun env { Typedtree.c_lhs; c_guard; c_rhs } ~scrutinee:ty ->
+ let ty =
+ if is_destructuring_pattern c_lhs then Use.inspect ty
+ else Use.discard ty (* as in 'let' *)
+ in
+ let vars = pattern_variables c_lhs in
+ let env =
+ List.fold_left
+ (fun env id -> Ident.add id ty env)
+ env
+ vars
+ in
+ Use.(join ty
+ (join (expression env c_rhs)
+ (inspect (option expression env c_guard))))
+ and value_bindings : rec_flag -> Env.env -> Typedtree.value_binding list -> Env.env * Use.t =
+ fun rec_flag env bindings ->
+ match rec_flag with
+ | Recursive ->
+ (* Approximation:
+ let rec y =
+ let rec x1 = e1
+ and x2 = e2
+ in e
+ treated as
+ let rec y =
+ let rec x = (e1, e2)[x1:=fst x, x2:=snd x] in
+ e[x1:=fst x, x2:=snd x]
+ Further, use the fact that x1,x2 cannot occur unguarded in e1, e2
+ to avoid recursive trickiness.
+ *)
+ let ids, ty =
+ List.fold_left
+ (fun (pats, tys) {vb_pat=p; vb_expr=e} ->
+ (pattern_variables p @ pats,
+ Use.join (expression env e) tys))
+ ([], Use.empty)
+ bindings
+ in
+ (List.fold_left (fun (env : Env.env) (id : Ident.t) ->
+ Ident.add id ty env) Env.empty ids,
+ ty)
+ | Nonrecursive ->
+ List.fold_left
+ (fun (env2, ty) binding ->
+ let env', ty' = value_binding env binding in
+ (Env.join env2 env', Use.join ty ty'))
+ (Env.empty, Use.empty)
+ bindings
+ and value_binding : Env.env -> Typedtree.value_binding -> Env.env * Use.t =
+ (* NB: returns new environment only *)
+ fun env { vb_pat; vb_expr } ->
+ let vars = pattern_variables vb_pat in
+ let ty = expression env vb_expr in
+ let ty = if is_destructuring_pattern vb_pat then Use.inspect ty else ty in
+ (List.fold_left
+ (fun env id -> Ident.add id ty env)
+ Env.empty
+ vars,
+ ty)
+ and is_destructuring_pattern : Typedtree.pattern -> bool =
+ fun pat -> match pat.pat_desc with
+ | Tpat_any -> false
+ | Tpat_var (_, _) -> false
+ | Tpat_alias (pat, _, _) -> is_destructuring_pattern pat
+ | Tpat_constant _ -> true
+ | Tpat_tuple _ -> true
+ | Tpat_construct (_, _, _) -> true
+ | Tpat_variant _ -> true
+ | Tpat_record (_, _) -> true
+ | Tpat_array _ -> true
+ | Tpat_or (l,r,_) -> is_destructuring_pattern l || is_destructuring_pattern r
+ | Tpat_lazy _ -> true
+
+ let check_recursive_expression env idlist expr =
+ let ty = expression (build_unguarded_env idlist) expr in
+ match Use.unguarded ty, Use.dependent ty, classify_expression expr with
+ | _ :: _, _, _ (* The expression inspects rec-bound variables *)
+ | _, _ :: _, Dynamic -> (* The expression depends on rec-bound variables
+ and its size is unknown *)
+ raise(Error(expr.exp_loc, env, Illegal_letrec_expr))
+ | [], _, Static (* The expression has known size *)
+ | [], [], Dynamic -> (* The expression has unknown size,
+ but does not depend on rec-bound variables *)
+ ()
+ let check_class_expr env idlist ce =
+ let rec class_expr : Env.env -> Typedtree.class_expr -> Use.t =
+ fun env ce -> match ce.cl_desc with
+ | Tcl_ident (_, _, _) -> Use.empty
+ | Tcl_structure _ -> Use.empty
+ | Tcl_fun (_, _, _, _, _) -> Use.empty
+ | Tcl_apply (_, _) -> Use.empty
+ | Tcl_let (rec_flag, valbinds, _, ce) ->
+ let _, ty = value_bindings rec_flag env valbinds in
+ Use.join ty (class_expr env ce)
+ | Tcl_constraint (ce, _, _, _, _) ->
+ class_expr env ce
+ | Tcl_open (_, _, _, _, ce) ->
+ class_expr env ce
+ in
+ match Use.unguarded (class_expr (build_unguarded_env idlist) ce) with
+ | [] -> ()
+ | _ :: _ -> raise(Error(ce.cl_loc, env, Illegal_class_expr))
+end
+
+let check_recursive_bindings env valbinds =
+ let ids = List.concat
+ (List.map (fun b -> pattern_variables b.vb_pat) valbinds) in
+ List.iter
+ (fun {vb_expr} ->
+ Rec_check.check_recursive_expression env ids vb_expr)
+ valbinds
+
+let check_recursive_class_bindings env ids exprs =
+ List.iter
+ (fun expr ->
+ Rec_check.check_class_expr env ids expr)
+ exprs
+
(* Approximate the type of an expression, for better recursion *)
let rec approx_type env sty =
let duplicate_ident_types caselist env =
let caselist =
List.filter (fun {pc_lhs} -> contains_gadt env pc_lhs) caselist in
- let idents = all_idents_cases caselist in
- let upd desc = {desc with val_type = correct_levels desc.val_type} in
- (* Be careful not the mark the original value as being used, and
- to keep the same internal 'slot' to track unused opens. *)
- List.fold_left (fun env s -> Env.update_value s upd env) env idents
-
+ Env.copy_types (all_idents_cases caselist) env
(* Getting proper location of already typed expressions.
and type_expect ?in_function ?recarg env sexp ty_expected =
let previous_saved_types = Cmt_format.get_saved_types () in
- Builtin_attributes.warning_enter_scope ();
- Builtin_attributes.warning_attribute sexp.pexp_attributes;
- let exp = type_expect_ ?in_function ?recarg env sexp ty_expected in
- Builtin_attributes.warning_leave_scope ();
+ let exp =
+ Builtin_attributes.warning_scope sexp.pexp_attributes
+ (fun () ->
+ type_expect_ ?in_function ?recarg env sexp ty_expected
+ )
+ in
Cmt_format.set_saved_types
(Cmt_format.Partial_expression exp :: previous_saved_types);
exp
type_let env rec_flag spat_sexp_list scp true in
let body =
type_expect new_env (wrap_unpacks sbody unpacks) ty_expected in
+ let () =
+ if rec_flag = Recursive then
+ check_recursive_bindings env pat_exp_list
+ in
re {
exp_desc = Texp_let(rec_flag, pat_exp_list, body);
exp_loc = loc; exp_extra = [];
i.e. if generative types rooted at id show up in the
type body.exp_type. Thus, this unification enforces the
scoping condition on "let module". *)
+ (* Note that this code will only be reached if ty_expected
+ is a generic type variable, otherwise the error will occur
+ above in type_expect *)
begin try
Ctype.unify_var new_env ty body.exp_type
with Unify _ ->
mk_constr "Ignored_int64" [ mk_iconv iconv; mk_int_opt pad_opt ]
| Ignored_float (pad_opt, prec_opt) ->
mk_constr "Ignored_float" [ mk_int_opt pad_opt; mk_int_opt prec_opt ]
- | Ignored_bool ->
- mk_constr "Ignored_bool" []
+ | Ignored_bool pad_opt ->
+ mk_constr "Ignored_bool" [ mk_int_opt pad_opt ]
| Ignored_format_arg (pad_opt, fmtty) ->
mk_constr "Ignored_format_arg" [ mk_int_opt pad_opt; mk_fmtty fmtty ]
| Ignored_format_subst (pad_opt, fmtty) ->
| Float (fconv, pad, prec, rest) ->
mk_constr "Float" [
mk_fconv fconv; mk_padding pad; mk_precision prec; mk_fmt rest ]
- | Bool rest ->
- mk_constr "Bool" [ mk_fmt rest ]
+ | Bool (pad, rest) ->
+ mk_constr "Bool" [ mk_padding pad; mk_fmt rest ]
| Flush rest ->
mk_constr "Flush" [ mk_fmt rest ]
| String_literal (s, rest) ->
(List.map (fun (l, _) -> Printtyp.string_of_label l) args));
if warn then Location.prerr_warning texp.exp_loc
(Warnings.Without_principality "eliminated optional argument");
- if is_nonexpansive texp then func texp else
(* let-expand to have side effects *)
let let_pat, let_var = var_pair "arg" texp.exp_type in
re { texp with exp_type = ty_fun; exp_desc =
[{pc_lhs}] when is_var pc_lhs -> false
| _ -> true in
if propagate then begin_def (); (* propagation of the argument *)
- let ty_arg' = newvar () in
let pattern_force = ref [] in
(* Format.printf "@[%i %i@ %a@]@." lev (get_current_level())
Printtyp.raw_type_expr ty_arg; *)
if !Clflags.principal then begin
end_def ();
iter_pattern (fun {pat_type=t} -> generalize_structure t) pat;
- { pat with pat_type = instance env pat.pat_type }
+ { pat with pat_type = instance ext_env pat.pat_type }
end else pat
in
(pat, (ext_env, unpacks)))
caselist in
- (* Unify cases (delayed to keep it order-free) *)
- let patl = List.map fst pat_env_list in
- List.iter (fun pat -> unify_pat env pat ty_arg') patl;
+ (* Unify all cases (delayed to keep it order-free) *)
+ let ty_arg' = newvar () in
+ let unify_pats ty =
+ List.iter (fun (pat, (ext_env, _)) -> unify_pat ext_env pat ty)
+ pat_env_list in
+ unify_pats ty_arg';
(* Check for polymorphic variants to close *)
+ let patl = List.map fst pat_env_list in
if List.exists has_variants patl then begin
Parmatch.pressure_variants env patl;
List.iter (iter_pattern finalize_variant) patl
(* `Contaminating' unifications start here *)
List.iter (fun f -> f()) !pattern_force;
(* Post-processing and generalization *)
- let unify_pats ty = List.iter (fun pat -> unify_pat env pat ty) patl in
+ if propagate || erase_either then unify_pats (instance env ty_arg);
if propagate then begin
List.iter
(iter_pattern (fun {pat_type=t} -> unify_var env t (newvar()))) patl;
- unify_pats (instance env ty_arg);
end_def ();
List.iter (iter_pattern (fun {pat_type=t} -> generalize t)) patl;
- end
- else if erase_either then unify_pats (instance env ty_arg);
+ end;
(* type bodies *)
let in_function = if List.length caselist = 1 then in_function else None in
let cases =
let spatl =
List.map
- (fun {pvb_pat=spat; pvb_expr=sexp; pvb_attributes=_} ->
+ (fun {pvb_pat=spat; pvb_expr=sexp; pvb_attributes=attrs} ->
+ attrs,
match spat.ppat_desc, sexp.pexp_desc with
(Ppat_any | Ppat_constraint _), _ -> spat
| _, Pexp_coerce (_, _, sty)
let nvs = List.map (fun _ -> newvar ()) spatl in
let (pat_list, new_env, force, unpacks) =
type_pattern_list env spatl scope nvs allow in
+ let attrs_list = List.map fst spatl in
let is_recursive = (rec_flag = Recursive) in
(* If recursive, first unify with an approximation of the expression *)
if is_recursive then
let current_slot = ref None in
let rec_needed = ref false in
- let warn_unused =
- Warnings.is_active (check "") || Warnings.is_active (check_strict "") ||
- (is_recursive && (Warnings.is_active Warnings.Unused_rec_flag))
+ let warn_about_unused_bindings =
+ List.exists
+ (fun attrs ->
+ Builtin_attributes.warning_scope ~ppwarning:false attrs (fun () ->
+ Warnings.is_active (check "") || Warnings.is_active (check_strict "") ||
+ (is_recursive && (Warnings.is_active Warnings.Unused_rec_flag))))
+ attrs_list
in
let pat_slot_list =
(* Algorithm to detect unused declarations in recursive bindings:
are unused. If this is the case, for local declarations, the issued
warning is 26, not 27.
*)
- List.map
- (fun pat ->
- if not warn_unused then pat, None
- else
- let some_used = ref false in
- (* has one of the identifier of this pattern been used? *)
- let slot = ref [] in
- List.iter
- (fun id ->
- let vd = Env.find_value (Path.Pident id) new_env in
- (* note: Env.find_value does not trigger the value_used event *)
- let name = Ident.name id in
- let used = ref false in
- if not (name = "" || name.[0] = '_' || name.[0] = '#') then
- add_delayed_check
- (fun () ->
- if not !used then
- Location.prerr_warning vd.Types.val_loc
- ((if !some_used then check_strict else check) name)
- );
- Env.set_value_used_callback
- name vd
- (fun () ->
- match !current_slot with
- | Some slot ->
- slot := (name, vd) :: !slot; rec_needed := true
- | None ->
- List.iter
- (fun (name, vd) -> Env.mark_value_used env name vd)
- (get_ref slot);
- used := true;
- some_used := true
- )
- )
- (Typedtree.pat_bound_idents pat);
- pat, Some slot
- )
+ List.map2
+ (fun attrs pat ->
+ Builtin_attributes.warning_scope ~ppwarning:false attrs (fun () ->
+ if not warn_about_unused_bindings then pat, None
+ else
+ let some_used = ref false in
+ (* has one of the identifier of this pattern been used? *)
+ let slot = ref [] in
+ List.iter
+ (fun id ->
+ let vd = Env.find_value (Path.Pident id) new_env in
+ (* note: Env.find_value does not trigger the value_used event *)
+ let name = Ident.name id in
+ let used = ref false in
+ if not (name = "" || name.[0] = '_' || name.[0] = '#') then
+ add_delayed_check
+ (fun () ->
+ if not !used then
+ Location.prerr_warning vd.Types.val_loc
+ ((if !some_used then check_strict else check) name)
+ );
+ Env.set_value_used_callback
+ name vd
+ (fun () ->
+ match !current_slot with
+ | Some slot ->
+ slot := (name, vd) :: !slot; rec_needed := true
+ | None ->
+ List.iter
+ (fun (name, vd) -> Env.mark_value_used env name vd)
+ (get_ref slot);
+ used := true;
+ some_used := true
+ )
+ )
+ (Typedtree.pat_bound_idents pat);
+ pat, Some slot
+ ))
+ attrs_list
pat_list
in
let exp_list =
generalize_structure ty'
end;
let exp =
- Builtin_attributes.with_warning_attribute pvb_attributes
+ Builtin_attributes.warning_scope pvb_attributes
(fun () -> type_expect exp_env sexp ty')
in
end_def ();
check_univars env true "definition" exp pat.pat_type vars;
{exp with exp_type = instance env exp.exp_type}
| _ ->
- Builtin_attributes.with_warning_attribute pvb_attributes (fun () ->
+ Builtin_attributes.warning_scope pvb_attributes (fun () ->
type_expect exp_env sexp pat.pat_type))
spat_sexp_list pat_slot_list in
current_slot := None;
&& Warnings.is_active Warnings.Unused_rec_flag then begin
let {pvb_pat; pvb_attributes} = List.hd spat_sexp_list in
(* See PR#6677 *)
- Builtin_attributes.with_warning_attribute pvb_attributes
+ Builtin_attributes.warning_scope ~ppwarning:false pvb_attributes
(fun () ->
Location.prerr_warning pvb_pat.ppat_loc Warnings.Unused_rec_flag
)
end;
List.iter2
- (fun pat exp ->
- ignore(check_partial env pat.pat_type pat.pat_loc [case pat exp]))
- pat_list exp_list;
+ (fun pat (attrs, exp) ->
+ Builtin_attributes.warning_scope ~ppwarning:false attrs
+ (fun () ->
+ ignore(check_partial env pat.pat_type pat.pat_loc
+ [case pat exp])
+ )
+ )
+ pat_list
+ (List.map2 (fun (attrs, _) e -> attrs, e) spatl exp_list);
end_def();
List.iter2
(fun pat exp ->
})
l spat_sexp_list
in
+ if is_recursive then
+ List.iter
+ (fun {vb_pat=pat} -> match pat.pat_desc with
+ Tpat_var _ -> ()
+ | Tpat_alias ({pat_desc=Tpat_any}, _, _) -> ()
+ | _ -> raise(Error(pat.pat_loc, env, Illegal_letrec_pat)))
+ l;
(l, new_env, unpacks)
(* Typing of toplevel bindings *)
integers of type %s" ty
| Unknown_literal (n, m) ->
fprintf ppf "Unknown modifier '%c' for literal %s%c" m n m
-
+ | Illegal_letrec_pat ->
+ fprintf ppf
+ "Only variables are allowed as left-hand side of `let rec'"
+ | Illegal_letrec_expr ->
+ fprintf ppf
+ "This kind of expression is not allowed as right-hand side of `let rec'"
+ | Illegal_class_expr ->
+ fprintf ppf "This kind of recursive class expression is not allowed"
let report_error env ppf err =
wrap_printing_env env (fun () -> report_error env ppf err)
| Not_an_extension_constructor
| Literal_overflow of string
| Unknown_literal of string * char
+ | Illegal_letrec_pat
+ | Illegal_letrec_expr
+ | Illegal_class_expr
exception Error of Location.t * Env.t * error
exception Error_forward of Location.error
val type_module: (Env.t -> Parsetree.module_expr -> Typedtree.module_expr) ref
(* Forward declaration, to be filled in by Typemod.type_open *)
val type_open:
- (override_flag -> Env.t -> Location.t -> Longident.t loc -> Path.t * Env.t)
+ (?used_slot:bool ref -> override_flag -> Env.t -> Location.t ->
+ Longident.t loc -> Path.t * Env.t)
ref
(* Forward declaration, to be filled in by Typeclass.class_structure *)
val type_object:
Path.t * (Longident.t * Typedtree.core_type) list * Types.type_expr
val constant: Parsetree.constant -> (Asttypes.constant, error) result
+
+val check_recursive_bindings : Env.t -> Typedtree.value_binding list -> unit
+val check_recursive_class_bindings :
+ Env.t -> Ident.t list -> Typedtree.class_expr list -> unit
| Null_arity_external
| Missing_native_external
| Unbound_type_var of type_expr * type_declaration
- | Not_open_type of Path.t
+ | Cannot_extend_private_type of Path.t
| Not_extensible_type of Path.t
| Extension_mismatch of Path.t * Includecore.type_mismatch list
| Rebind_wrong_type of Longident.t * Env.t * (type_expr * type_expr) list
| Bad_unboxed_attribute of string
| Wrong_unboxed_type_float
| Boxed_and_unboxed
+ | Nonrec_gadt
open Typedtree
let enter_type rec_flag env sdecl id =
let needed =
match rec_flag with
- | Asttypes.Nonrecursive -> Btype.is_row_name (Ident.name id)
+ | Asttypes.Nonrecursive ->
+ begin match sdecl.ptype_kind with
+ | Ptype_variant scds ->
+ List.iter (fun cd ->
+ if cd.pcd_res <> None then raise (Error(cd.pcd_loc, Nonrec_gadt)))
+ scds
+ | _ -> ()
+ end;
+ Btype.is_row_name (Ident.name id)
| Asttypes.Recursive -> true
in
if not needed then env else
lbls;
let mk {pld_name=name;pld_mutable=mut;pld_type=arg;pld_loc=loc;
pld_attributes=attrs} =
- let arg = Ast_helper.Typ.force_poly arg in
- let cty = transl_simple_type env closed arg in
- {ld_id = Ident.create name.txt; ld_name = name; ld_mutable = mut;
- ld_type = cty; ld_loc = loc; ld_attributes = attrs}
+ Builtin_attributes.warning_scope attrs
+ (fun () ->
+ let arg = Ast_helper.Typ.force_poly arg in
+ let cty = transl_simple_type env closed arg in
+ {ld_id = Ident.create name.txt; ld_name = name; ld_mutable = mut;
+ ld_type = cty; ld_loc = loc; ld_attributes = attrs}
+ )
in
let lbls = List.map mk lbls in
let lbls' =
let args, targs =
transl_constructor_arguments env true sargs
in
- targs, None, args, None
+ targs, None, args, None, type_params
| Some sret_type ->
(* if it's a generalized constructor we must first narrow and
then widen so as to not introduce any new constraints *)
in
let tret_type = transl_simple_type env false sret_type in
let ret_type = tret_type.ctyp_type in
- begin
+ let params =
match (Ctype.repr ret_type).desc with
- Tconstr (p', _, _) when Path.same type_path p' -> ()
+ | Tconstr (p', params, _) when Path.same type_path p' ->
+ params
| _ ->
raise (Error (sret_type.ptyp_loc, Constraint_failed
(ret_type, Ctype.newconstr type_path type_params)))
- end;
+ in
widen z;
- targs, Some tret_type, args, Some ret_type
+ targs, Some tret_type, args, Some ret_type, params
(* Check that the variable [id] is present in the [univ] list. *)
let check_type_var loc univ id =
| Ptype_abstract -> Ttype_abstract, Type_abstract
| Ptype_variant scstrs ->
assert (scstrs <> []);
+ if List.exists (fun cstr -> cstr.pcd_res <> None) scstrs then begin
+ match cstrs with
+ [] -> ()
+ | (_,_,loc)::_ ->
+ Location.prerr_warning loc Warnings.Constraint_on_gadt
+ end;
let all_constrs = ref StringSet.empty in
List.iter
(fun {pcd_name = {txt = name}} ->
raise(Error(sdecl.ptype_loc, Too_many_constructors));
let make_cstr scstr =
let name = Ident.create scstr.pcd_name.txt in
- let targs, tret_type, args, ret_type =
+ let targs, tret_type, args, ret_type, cstr_params =
make_constructor env (Path.Pident id) params
scstr.pcd_args scstr.pcd_res
in
- if unbox then begin
+ if Config.flat_float_array && unbox then begin
(* Cannot unbox a type when the argument can be both float and
non-float because it interferes with the dynamic float array
optimization. This can only happen when the type is a GADT
match Datarepr.constructor_existentials args ret_type with
| _, [] -> ()
| [argty], _ex ->
- check_unboxed_gadt_arg sdecl.ptype_loc params env argty
+ check_unboxed_gadt_arg sdecl.ptype_loc cstr_params env argty
| _ -> assert false
end;
let tcstr =
in
tcstr, cstr
in
+ let make_cstr scstr =
+ Builtin_attributes.warning_scope scstr.pcd_attributes
+ (fun () -> make_cstr scstr)
+ in
let tcstrs, cstrs = List.split (List.map make_cstr scstrs) in
Ttype_variant tcstrs, Type_variant cstrs
| Ptype_record lbls ->
else if not (Ctype.equal env false args decl.type_params)
then [Includecore.Constraint]
else
- Includecore.type_declarations ~equality:true env
+ Includecore.type_declarations ~loc ~equality:true env
(Path.last path)
decl'
id
(* Prepare *)
let params = List.map Btype.repr decl.type_params in
let tvl = ref TypeMap.empty in
- (* Compute occurences in body *)
+ (* Compute occurrences in the body *)
let open Variance in
List.iter
(fun (cn,ty) ->
let add_false = List.map (fun ty -> false, ty)
-(* A parameter is constrained if either is is instantiated,
+(* A parameter is constrained if it is either instantiated,
or it is a variable appearing in another parameter *)
let constrained vars ty =
match ty.desc with
id, None
in
let transl_declaration name_sdecl (id, slot) =
- current_slot := slot; transl_declaration temp_env name_sdecl id in
+ current_slot := slot;
+ Builtin_attributes.warning_scope
+ name_sdecl.ptype_attributes
+ (fun () -> transl_declaration temp_env name_sdecl id)
+ in
let tdecls =
List.map2 transl_declaration sdecl_list (List.map id_slots id_list) in
let decls =
decl to_check)
decls;
List.iter (check_abbrev_recursion newenv id_loc_list to_check) tdecls;
- (* Check that all type variable are closed *)
+ (* Check that all type variables are closed *)
List.iter2
(fun sdecl tdecl ->
let decl = tdecl.typ_type in
let args, ret_type, kind =
match sext.pext_kind with
Pext_decl(sargs, sret_type) ->
- let targs, tret_type, args, ret_type =
+ let targs, tret_type, args, ret_type, _ =
make_constructor env type_path typext_params
sargs sret_type
in
Typedtree.ext_loc = sext.pext_loc;
Typedtree.ext_attributes = sext.pext_attributes; }
-let transl_type_extension check_open env loc styext =
+let transl_extension_constructor env type_path type_params
+ typext_params priv sext =
+ Builtin_attributes.warning_scope sext.pext_attributes
+ (fun () -> transl_extension_constructor env type_path type_params
+ typext_params priv sext)
+
+let transl_type_extension extend env loc styext =
reset_type_variables();
Ctype.begin_def();
let (type_path, type_decl) =
in
begin
match type_decl.type_kind with
- Type_open -> ()
- | Type_abstract ->
- if check_open then begin
- try
- let {pext_loc} =
- List.find (function {pext_kind = Pext_decl _} -> true
- | {pext_kind = Pext_rebind _} -> false)
- styext.ptyext_constructors
- in
- raise (Error(pext_loc, Not_open_type type_path))
- with Not_found -> ()
- end
- | _ -> raise (Error(loc, Not_extensible_type type_path))
+ | Type_open -> begin
+ match type_decl.type_private with
+ | Private when extend -> begin
+ match
+ List.find
+ (function {pext_kind = Pext_decl _} -> true
+ | {pext_kind = Pext_rebind _} -> false)
+ styext.ptyext_constructors
+ with
+ | {pext_loc} ->
+ raise (Error(pext_loc, Cannot_extend_private_type type_path))
+ | exception Not_found -> ()
+ end
+ | _ -> ()
+ end
+ | _ ->
+ raise (Error(loc, Not_extensible_type type_path))
end;
let type_variance =
List.map (fun v ->
Btype.iter_type_expr_cstr_args Ctype.generalize ext.ext_type.ext_args;
may Ctype.generalize ext.ext_type.ext_ret_type)
constructors;
- (* Check that all type variable are closed *)
+ (* Check that all type variables are closed *)
List.iter
(fun ext ->
match Ctype.closed_extension_constructor ext.ext_type with
in
(tyext, newenv)
+let transl_type_extension extend env loc styext =
+ Builtin_attributes.warning_scope styext.ptyext_attributes
+ (fun () -> transl_type_extension extend env loc styext)
+
let transl_exception env sext =
reset_type_variables();
Ctype.begin_def();
(* Generalize types *)
Btype.iter_type_expr_cstr_args Ctype.generalize ext.ext_type.ext_args;
may Ctype.generalize ext.ext_type.ext_ret_type;
- (* Check that all type variable are closed *)
+ (* Check that all type variables are closed *)
begin match Ctype.closed_extension_constructor ext.ext_type with
Some ty ->
raise (Error(ext.ext_loc, Unbound_type_var_ext(ty, ext.ext_type)))
in
desc, newenv
+let transl_value_decl env loc valdecl =
+ Builtin_attributes.warning_scope valdecl.pval_attributes
+ (fun () -> transl_value_decl env loc valdecl)
+
(* Translate a "with" constraint -- much simplified version of
transl_type_decl. *)
let transl_with_constraint env id row_path orig_decl sdecl =
in
if arity_ok && orig_decl.type_kind <> Type_abstract
&& sdecl.ptype_private = Private then
- Location.prerr_warning sdecl.ptype_loc
- (Warnings.Deprecated "spurious use of private");
+ Location.deprecated sdecl.ptype_loc "spurious use of private";
let type_kind, type_unboxed =
if arity_ok && man <> None then
orig_decl.type_kind, orig_decl.type_unboxed
fprintf ppf "A type variable is unbound in this extension constructor";
let args = tys_of_constr_args ext.ext_args in
explain_unbound ppf ty args (fun c -> c) "type" (fun _ -> "")
- | Not_open_type path ->
+ | Cannot_extend_private_type path ->
fprintf ppf "@[%s@ %a@]"
- "Cannot extend type definition"
+ "Cannot extend private type definition"
Printtyp.path path
| Not_extensible_type path ->
fprintf ppf "@[%s@ %a@ %s@]"
- "Type"
+ "Type definition"
Printtyp.path path
"is not extensible"
| Extension_mismatch (path, errs) ->
You should annotate it with [%@%@ocaml.boxed].@]"
| Boxed_and_unboxed ->
fprintf ppf "@[A type cannot be boxed and unboxed at the same time.@]"
+ | Nonrec_gadt ->
+ fprintf ppf
+ "@[GADT case syntax cannot be used in a 'nonrec' block.@]"
let () =
Location.register_error_of_exn
| Null_arity_external
| Missing_native_external
| Unbound_type_var of type_expr * type_declaration
- | Not_open_type of Path.t
+ | Cannot_extend_private_type of Path.t
| Not_extensible_type of Path.t
| Extension_mismatch of Path.t * Includecore.type_mismatch list
| Rebind_wrong_type of Longident.t * Env.t * (type_expr * type_expr) list
| Bad_unboxed_attribute of string
| Wrong_unboxed_type_float
| Boxed_and_unboxed
+ | Nonrec_gadt
exception Error of Location.t * error
(Ident.t * string loc * expression) list * class_expr
| Tcl_constraint of
class_expr * class_type option * string list * string list * Concr.t
- (* Visible instance variables, methods and concretes methods *)
+ (* Visible instance variables, methods and concrete methods *)
+ | Tcl_open of override_flag * Path.t * Longident.t loc * Env.t * class_expr
and class_structure =
{
| Ttyp_arrow of arg_label * core_type * core_type
| Ttyp_tuple of core_type list
| Ttyp_constr of Path.t * Longident.t loc * core_type list
- | Ttyp_object of (string * attributes * core_type) list * closed_flag
+ | Ttyp_object of object_field list * closed_flag
| Ttyp_class of Path.t * Longident.t loc * core_type list
| Ttyp_alias of core_type * string
| Ttyp_variant of row_field list * closed_flag * label list option
}
and row_field =
- Ttag of label * attributes * bool * core_type list
+ Ttag of string loc * attributes * bool * core_type list
| Tinherit of core_type
+and object_field =
+ | OTtag of string loc * attributes * core_type
+ | OTinherit of core_type
+
and value_description =
{ val_id: Ident.t;
val_name: string loc;
Tcty_constr of Path.t * Longident.t loc * core_type list
| Tcty_signature of class_signature
| Tcty_arrow of arg_label * core_type * class_type
+ | Tcty_open of override_flag * Path.t * Longident.t loc * Env.t * class_type
and class_signature = {
csig_self: core_type;
type partial = Partial | Total
-(** {2 Extension points} *)
+(** {1 Extension points} *)
type attribute = Parsetree.attribute
type attributes = attribute list
-(** {2 Core language} *)
+(** {1 Core language} *)
type pattern =
{ pat_desc: pattern_desc;
(Ident.t * string loc * expression) list * class_expr
| Tcl_constraint of
class_expr * class_type option * string list * string list * Concr.t
- (* Visible instance variables, methods and concretes methods *)
+ (* Visible instance variables, methods and concrete methods *)
+ | Tcl_open of override_flag * Path.t * Longident.t loc * Env.t * class_expr
and class_structure =
{
(** Annotations for [Tmod_constraint]. *)
and module_type_constraint =
| Tmodtype_implicit
- (** The module type constraint has been synthesized during typecheking. *)
+ (** The module type constraint has been synthesized during typechecking. *)
| Tmodtype_explicit of module_type
(** The module type was in the source file. *)
| Ttyp_arrow of arg_label * core_type * core_type
| Ttyp_tuple of core_type list
| Ttyp_constr of Path.t * Longident.t loc * core_type list
- | Ttyp_object of (string * attributes * core_type) list * closed_flag
+ | Ttyp_object of object_field list * closed_flag
| Ttyp_class of Path.t * Longident.t loc * core_type list
| Ttyp_alias of core_type * string
| Ttyp_variant of row_field list * closed_flag * label list option
}
and row_field =
- Ttag of label * attributes * bool * core_type list
+ Ttag of string loc * attributes * bool * core_type list
| Tinherit of core_type
+and object_field =
+ | OTtag of string loc * attributes * core_type
+ | OTinherit of core_type
+
and value_description =
{ val_id: Ident.t;
val_name: string loc;
Tcty_constr of Path.t * Longident.t loc * core_type list
| Tcty_signature of class_signature
| Tcty_arrow of arg_label * core_type * class_type
+ | Tcty_open of override_flag * Path.t * Longident.t loc * Env.t * class_type
and class_signature = {
csig_self : core_type;
| Tcl_ident (_, _, tyl) ->
List.iter iter_core_type tyl
+
+ | Tcl_open (_, _, _, _, e) ->
+ iter_class_expr e
end;
Iter.leave_class_expr cexpr;
| Tcty_arrow (_label, ct, cl) ->
iter_core_type ct;
iter_class_type cl
+ | Tcty_open (_, _, _, _, e) ->
+ iter_class_type e
end;
Iter.leave_class_type ct;
| Ttyp_constr (_path, _, list) ->
List.iter iter_core_type list
| Ttyp_object (list, _o) ->
- List.iter (fun (_, _, t) -> iter_core_type t) list
+ List.iter iter_object_field list
| Ttyp_class (_path, _, list) ->
List.iter iter_core_type list
| Ttyp_alias (ct, _s) ->
List.iter iter_core_type list
| Tinherit ct -> iter_core_type ct
+ and iter_object_field ofield =
+ match ofield with
+ OTtag (_, _, ct) | OTinherit ct -> iter_core_type ct
+
and iter_class_field cf =
Iter.enter_class_field cf;
begin
Some (map_class_type clty), vals, meths, concrs)
| Tcl_ident (id, name, tyl) ->
- Tcl_ident (id, name, List.map map_core_type tyl)
+ Tcl_ident (id, name, List.map map_core_type tyl)
+ | Tcl_open (ovf, p, lid, env, e) ->
+ Tcl_open (ovf, p, lid, env, map_class_expr e)
in
Map.leave_class_expr { cexpr with cl_desc = cl_desc }
Tcty_constr (path, lid, List.map map_core_type list)
| Tcty_arrow (label, ct, cl) ->
Tcty_arrow (label, map_core_type ct, map_class_type cl)
+ | Tcty_open (ovf, p, lid, env, e) ->
+ Tcty_open (ovf, p, lid, env, map_class_type e)
in
Map.leave_class_type { ct with cltyp_desc = cltyp_desc }
Ttyp_constr (path, lid, List.map map_core_type list)
| Ttyp_object (list, o) ->
Ttyp_object
- (List.map (fun (s, a, t) -> (s, a, map_core_type t)) list, o)
+ (List.map map_object_field list, o)
| Ttyp_class (path, lid, list) ->
Ttyp_class (path, lid, List.map map_core_type list)
| Ttyp_alias (ct, s) -> Ttyp_alias (map_core_type ct, s)
Ttag (label, attrs, bool, List.map map_core_type list)
| Tinherit ct -> Tinherit (map_core_type ct)
+ and map_object_field ofield =
+ match ofield with
+ OTtag (label, attrs, ct) ->
+ OTtag (label, attrs, map_core_type ct)
+ | OTinherit ct -> OTinherit (map_core_type ct)
+
and map_class_field cf =
let cf = Map.enter_class_field cf in
let cf_desc =
| Structure_expected of module_type
| With_no_component of Longident.t
| With_mismatch of Longident.t * Includemod.error list
+ | With_makes_applicative_functor_ill_typed of
+ Longident.t * Path.t * Includemod.error list
+ | With_changes_module_alias of Longident.t * Ident.t * Path.t
+ | With_cannot_remove_constrained_type
| Repeated_name of string * string
| Non_generalizable of type_expr
| Non_generalizable_class of Ident.t * class_declaration
| Implementation_is_required of string
| Interface_not_compiled of string
| Not_allowed_in_functor_body
- | With_need_typeconstr
| Not_a_packed_module of type_expr
| Incomplete_packed_module of type_expr
| Scoping_pack of Longident.t * type_expr
(* Compute the environment after opening a module *)
-let type_open_ ?toplevel ovf env loc lid =
- let path, md = Typetexp.find_module env lid.loc lid.txt in
- let sg = extract_sig_open env lid.loc md.md_type in
- path, Env.open_signature ~loc ?toplevel ovf path sg env
+let type_open_ ?used_slot ?toplevel ovf env loc lid =
+ let path = Typetexp.lookup_module ~load:true env lid.loc lid.txt in
+ match Env.open_signature ~loc ?used_slot ?toplevel ovf path env with
+ | Some env -> path, env
+ | None ->
+ let md = Env.find_module path env in
+ ignore (extract_sig_open env lid.loc md.md_type);
+ assert false
let type_open ?toplevel env sod =
let (path, newenv) =
- type_open_ ?toplevel sod.popen_override env sod.popen_loc sod.popen_lid
+ Builtin_attributes.warning_scope sod.popen_attributes
+ (fun () ->
+ type_open_ ?toplevel sod.popen_override env sod.popen_loc
+ sod.popen_lid
+ )
in
let od =
{
| Some id -> Env.add_type ~check:false id newdecl env
in
let env = if rs = Trec_not then env else add_rec_types env rem in
- Includemod.type_declarations env id newdecl decl;
+ Includemod.type_declarations ~loc env id newdecl decl;
Typedecl.check_coherence env loc id newdecl
let update_rec_next rs rem =
let open Variance in
set May_pos p (set May_neg n (set May_weak n (set Inj i null)))
+let rec iter_path_apply p ~f =
+ match p with
+ | Pident _ -> ()
+ | Pdot (p, _, _) -> iter_path_apply p ~f
+ | Papply (p1, p2) ->
+ iter_path_apply p1 ~f;
+ iter_path_apply p2 ~f;
+ f p1 p2 (* after recursing, so we know both paths are well typed *)
+
+let path_is_strict_prefix =
+ let rec list_is_strict_prefix l ~prefix =
+ match l, prefix with
+ | [], [] -> false
+ | _ :: _, [] -> true
+ | [], _ :: _ -> false
+ | s1 :: t1, s2 :: t2 ->
+ String.equal s1 s2 && list_is_strict_prefix t1 ~prefix:t2
+ in
+ fun path ~prefix ->
+ match Path.flatten path, Path.flatten prefix with
+ | `Contains_apply, _ | _, `Contains_apply -> false
+ | `Ok (ident1, l1), `Ok (ident2, l2) ->
+ Ident.same ident1 ident2
+ && list_is_strict_prefix l1 ~prefix:l2
+
+let iterator_with_env env =
+ let env = ref env in
+ let super = Btype.type_iterators in
+ env, { super with
+ Btype.it_signature = (fun self sg ->
+ (* add all items to the env before recursing down, to handle recursive
+ definitions *)
+ let env_before = !env in
+ List.iter (fun i -> env := Env.add_item i !env) sg;
+ super.Btype.it_signature self sg;
+ env := env_before
+ );
+ Btype.it_module_type = (fun self -> function
+ | Mty_functor (param, mty_arg, mty_body) ->
+ may (self.Btype.it_module_type self) mty_arg;
+ let env_before = !env in
+ env := Env.add_module ~arg:true param (Btype.default_mty mty_arg) !env;
+ self.Btype.it_module_type self mty_body;
+ env := env_before;
+ | mty ->
+ super.Btype.it_module_type self mty
+ )
+ }
+
+let retype_applicative_functor_type ~loc env funct arg =
+ let mty_functor = (Env.find_module funct env).md_type in
+ let mty_arg = (Env.find_module arg env).md_type in
+ let mty_param =
+ match Env.scrape_alias env mty_functor with
+ | Mty_functor (_, Some mty_param, _) -> mty_param
+ | _ -> assert false (* could trigger due to MPR#7611 *)
+ in
+ let aliasable = not (Env.is_functor_arg arg env) in
+ ignore(Includemod.modtypes ~loc env
+ (Mtype.strengthen ~aliasable env mty_arg arg) mty_param)
+
+(* When doing a deep destructive substitution with type M.N.t := .., we change M
+ and M.N and so we have to check that uses of the modules other than just
+ extracting components from them still make sense. There are only two such
+ kinds of uses:
+ - applicative functor types: F(M).t might not be well typed anymore
+ - aliases: module A = M still makes sense but it doesn't mean the same thing
+ anymore, so it's forbidden until it's clear what we should do with it.
+ This function would be called with M.N.t and N.t to check for these uses. *)
+let check_usage_of_path_of_substituted_item paths env signature ~loc ~lid =
+ let iterator =
+ let env, super = iterator_with_env env in
+ { super with
+ Btype.it_signature_item = (fun self -> function
+ | Sig_module (id, { md_type = Mty_alias (_, aliased_path); _ }, _)
+ when List.exists
+ (fun path -> path_is_strict_prefix path ~prefix:aliased_path)
+ paths
+ ->
+ let e = With_changes_module_alias (lid.txt, id, aliased_path) in
+ raise(Error(loc, !env, e))
+ | sig_item ->
+ super.Btype.it_signature_item self sig_item
+ );
+ Btype.it_path = (fun referenced_path ->
+ iter_path_apply referenced_path ~f:(fun funct arg ->
+ if List.exists
+ (fun path -> path_is_strict_prefix path ~prefix:arg)
+ paths
+ then
+ let env = !env in
+ try retype_applicative_functor_type ~loc env funct arg
+ with Includemod.Error explanation ->
+ raise(Error(loc, env,
+ With_makes_applicative_functor_ill_typed
+ (lid.txt, referenced_path, explanation)))
+ )
+ );
+ }
+ in
+ iterator.Btype.it_signature iterator signature;
+ Btype.unmark_iterators.Btype.it_signature Btype.unmark_iterators signature
+
+let type_decl_is_alias sdecl = (* assuming no explicit constraint *)
+ match sdecl.ptype_manifest with
+ | Some {ptyp_desc = Ptyp_constr (lid, stl)}
+ when List.length stl = List.length sdecl.ptype_params ->
+ begin
+ match
+ List.iter2 (fun x (y, _) ->
+ match x, y with
+ {ptyp_desc=Ptyp_var sx}, {ptyp_desc=Ptyp_var sy}
+ when sx = sy -> ()
+ | _, _ -> raise Exit)
+ stl sdecl.ptype_params;
+ with
+ | exception Exit -> None
+ | () -> Some lid
+ end
+ | _ -> None
+;;
+
+let params_are_constrained =
+ let rec loop = function
+ | [] -> false
+ | hd :: tl ->
+ match (Btype.repr hd).desc with
+ | Tvar _ -> List.memq hd tl || loop tl
+ | _ -> true
+ in
+ loop
+;;
+
let merge_constraint initial_env loc sg constr =
let lid =
match constr with
- | Pwith_type (lid, _) | Pwith_module (lid, _) -> lid
- | Pwith_typesubst {ptype_name=s} | Pwith_modsubst (s, _) ->
- {loc = s.loc; txt=Lident s.txt}
+ | Pwith_type (lid, _) | Pwith_module (lid, _)
+ | Pwith_typesubst (lid, _) | Pwith_modsubst (lid, _) -> lid
in
- let real_id = ref None in
+ let destructive_substitution =
+ match constr with
+ | Pwith_type _ | Pwith_module _ -> false
+ | Pwith_typesubst _ | Pwith_modsubst _ -> true
+ in
+ let real_ids = ref [] in
let rec merge env sg namelist row_id =
match (sg, namelist, constr) with
([], _, _) ->
| (Sig_type(id, _, _) :: rem, [s], (Pwith_type _ | Pwith_typesubst _))
when Ident.name id = s ^ "#row" ->
merge env rem namelist (Some id)
- | (Sig_type(id, decl, rs) :: rem, [s], Pwith_typesubst sdecl)
+ | (Sig_type(id, decl, rs) :: rem, [s], Pwith_typesubst (_, sdecl))
when Ident.name id = s ->
(* Check as for a normal with constraint, but discard definition *)
let tdecl =
Typedecl.transl_with_constraint initial_env id None decl sdecl in
let newdecl = tdecl.typ_type in
check_type_decl env sdecl.ptype_loc id row_id newdecl decl rs rem;
- real_id := Some id;
+ real_ids := [Pident id];
(Pident id, lid, Twith_typesubst tdecl),
update_rec_next rs rem
| (Sig_module(id, md, rs) :: rem, [s], Pwith_module (_, lid'))
let path, md' = Typetexp.find_module initial_env loc lid'.txt in
let md'' = {md' with md_type = Mtype.remove_aliases env md'.md_type} in
let newmd = Mtype.strengthen_decl ~aliasable:false env md'' path in
- ignore(Includemod.modtypes env newmd.md_type md.md_type);
+ ignore(Includemod.modtypes ~loc env newmd.md_type md.md_type);
(Pident id, lid, Twith_module (path, lid')),
Sig_module(id, newmd, rs) :: rem
| (Sig_module(id, md, rs) :: rem, [s], Pwith_modsubst (_, lid'))
when Ident.name id = s ->
let path, md' = Typetexp.find_module initial_env loc lid'.txt in
let newmd = Mtype.strengthen_decl ~aliasable:false env md' path in
- ignore(Includemod.modtypes env newmd.md_type md.md_type);
- real_id := Some id;
+ ignore(Includemod.modtypes ~loc env newmd.md_type md.md_type);
+ real_ids := [Pident id];
(Pident id, lid, Twith_modsubst (path, lid')),
update_rec_next rs rem
| (Sig_module(id, md, rs) :: rem, s :: namelist, _)
when Ident.name id = s ->
let ((path, _path_loc, tcstr), newsg) =
merge env (extract_sig env loc md.md_type) namelist None in
- (path_concat id path, lid, tcstr),
- Sig_module(id, {md with md_type=Mty_signature newsg}, rs) :: rem
+ let path = path_concat id path in
+ real_ids := path :: !real_ids;
+ let item = Sig_module(id, {md with md_type=Mty_signature newsg}, rs) in
+ (path, lid, tcstr),
+ item :: rem
| (item :: rem, _, _) ->
let (cstr, items) = merge (Env.add_item item env) rem namelist row_id
in
try
let names = Longident.flatten lid.txt in
let (tcstr, sg) = merge initial_env sg names None in
+ if destructive_substitution then (
+ match List.rev !real_ids with
+ | [] -> assert false
+ | last :: rest ->
+ (* The last item is the one that's removed. We don't need to check how
+ it's used since it's replaced by a more specific type/module. *)
+ assert (match last with Pident _ -> true | _ -> false);
+ match rest with
+ | [] -> ()
+ | _ :: _ ->
+ check_usage_of_path_of_substituted_item
+ rest initial_env sg ~loc ~lid;
+ );
let sg =
- match names, constr with
- [_], Pwith_typesubst sdecl ->
- let id =
- match !real_id with None -> assert false | Some id -> id in
- let lid =
- try match sdecl.ptype_manifest with
- | Some {ptyp_desc = Ptyp_constr (lid, stl)}
- when List.length stl = List.length sdecl.ptype_params ->
- List.iter2 (fun x (y, _) ->
- match x, y with
- {ptyp_desc=Ptyp_var sx}, {ptyp_desc=Ptyp_var sy}
- when sx = sy -> ()
- | _, _ -> raise Exit)
- stl sdecl.ptype_params;
- lid
- | _ -> raise Exit
- with Exit ->
- raise(Error(sdecl.ptype_loc, initial_env, With_need_typeconstr))
- in
- let path =
- try Env.lookup_type lid.txt initial_env with Not_found -> assert false
- in
- let sub = Subst.add_type id path Subst.identity in
- Subst.signature sub sg
- | [_], Pwith_modsubst (_, lid) ->
- let id =
- match !real_id with None -> assert false | Some id -> id in
- let path = Typetexp.lookup_module initial_env loc lid.txt in
- let sub = Subst.add_module id path Subst.identity in
- Subst.signature sub sg
+ match tcstr with
+ | (_, _, Twith_typesubst tdecl) ->
+ let how_to_extend_subst =
+ let sdecl =
+ match constr with
+ | Pwith_typesubst (_, sdecl) -> sdecl
+ | _ -> assert false
+ in
+ match type_decl_is_alias sdecl with
+ | Some lid ->
+ let replacement =
+ try Env.lookup_type lid.txt initial_env
+ with Not_found -> assert false
+ in
+ fun s path -> Subst.add_type_path path replacement s
+ | None ->
+ let body =
+ match tdecl.typ_type.type_manifest with
+ | None -> assert false
+ | Some x -> x
+ in
+ let params = tdecl.typ_type.type_params in
+ if params_are_constrained params
+ then raise(Error(loc, initial_env, With_cannot_remove_constrained_type));
+ fun s path -> Subst.add_type_function path ~params ~body s
+ in
+ let sub = List.fold_left how_to_extend_subst Subst.identity !real_ids in
+ Subst.signature sub sg
+ | (_, _, Twith_modsubst (real_path, _)) ->
+ let sub =
+ List.fold_left
+ (fun s path -> Subst.add_module_path path real_path s)
+ Subst.identity
+ !real_ids
+ in
+ Subst.signature sub sg
| _ ->
- sg
+ sg
in
(tcstr, sg)
with Includemod.Error explanation ->
else
map_rec_type ~rec_flag fn decls rem
-(* Add type extension flags to extension contructors *)
+(* Add type extension flags to extension constructors *)
let map_ext fn exts rem =
match exts with
| [] -> rem
let smty = sincl.pincl_mod in
let mty = approx_modtype env smty in
let sg = Subst.signature Subst.identity
- (extract_sig env smty.pmty_loc mty) in
+ (extract_sig env smty.pmty_loc mty) in
let newenv = Env.add_signature sg env in
sg @ approx_sig newenv srem
| Psig_class sdecls | Psig_class_type sdecls ->
mtd_loc = sinfo.pmtd_loc;
}
+let approx_modtype env smty =
+ Warnings.without_warnings
+ (fun () -> approx_modtype env smty)
+
(* Additional validity checks on type definitions arising from
recursive modules *)
(* let signature sg = List.map (fun item -> item.sig_type) sg *)
let rec transl_modtype env smty =
+ Builtin_attributes.warning_scope smty.pmty_attributes
+ (fun () -> transl_modtype_aux env smty)
+
+and transl_modtype_aux env smty =
let loc = smty.pmty_loc in
match smty.pmty_desc with
Pmty_ident lid ->
match item.psig_desc with
| Psig_value sdesc ->
let (tdesc, newenv) =
- Builtin_attributes.with_warning_attribute sdesc.pval_attributes
- (fun () -> Typedecl.transl_value_decl env item.psig_loc sdesc)
+ Typedecl.transl_value_decl env item.psig_loc sdesc
in
let (trem,rem, final_env) = transl_sig newenv srem in
mksig (Tsig_value tdesc) env loc :: trem,
check_name check_module names pmd.pmd_name;
let id = Ident.create pmd.pmd_name.txt in
let tmty =
- Builtin_attributes.with_warning_attribute pmd.pmd_attributes
+ Builtin_attributes.warning_scope pmd.pmd_attributes
(fun () -> transl_modtype env pmd.pmd_type)
in
let md = {
final_env
| Psig_modtype pmtd ->
let newenv, mtd, sg =
- Builtin_attributes.with_warning_attribute pmtd.pmtd_attributes
- (fun () -> transl_modtype_decl names env pmtd)
+ transl_modtype_decl names env pmtd
in
let (trem, rem, final_env) = transl_sig newenv srem in
mksig (Tsig_modtype mtd) env loc :: trem,
| Psig_include sincl ->
let smty = sincl.pincl_mod in
let tmty =
- Builtin_attributes.with_warning_attribute sincl.pincl_attributes
+ Builtin_attributes.warning_scope sincl.pincl_attributes
(fun () -> transl_modtype env smty)
in
let mty = tmty.mty_type in
classes [rem]),
final_env
| Psig_attribute x ->
- Builtin_attributes.warning_attribute [x];
+ Builtin_attributes.warning_attribute x;
let (trem,rem, final_env) = transl_sig env srem in
mksig (Tsig_attribute x) env loc :: trem, rem, final_env
| Psig_extension (ext, _attrs) ->
raise (Error_forward (Builtin_attributes.error_of_extension ext))
in
let previous_saved_types = Cmt_format.get_saved_types () in
- Builtin_attributes.warning_enter_scope ();
- let (trem, rem, final_env) = transl_sig (Env.in_signature true env) sg in
- let rem = simplify_signature rem in
- let sg = { sig_items = trem; sig_type = rem; sig_final_env = final_env } in
- Builtin_attributes.warning_leave_scope ();
- Cmt_format.set_saved_types
- ((Cmt_format.Partial_signature sg) :: previous_saved_types);
- sg
+ Builtin_attributes.warning_scope []
+ (fun () ->
+ let (trem, rem, final_env) = transl_sig (Env.in_signature true env) sg in
+ let rem = simplify_signature rem in
+ let sg = { sig_items = trem; sig_type = rem; sig_final_env = final_env } in
+ Cmt_format.set_saved_types
+ ((Cmt_format.Partial_signature sg) :: previous_saved_types);
+ sg
+ )
-and transl_modtype_decl names env
+and transl_modtype_decl names env pmtd =
+ Builtin_attributes.warning_scope pmtd.pmtd_attributes
+ (fun () -> transl_modtype_decl_aux names env pmtd)
+
+and transl_modtype_decl_aux names env
{pmtd_name; pmtd_type; pmtd_attributes; pmtd_loc} =
check_name check_modtype names pmtd_name;
let tmty = Misc.may_map (transl_modtype env) pmtd_type in
List.map2
(fun pmd (id, id_loc, _mty) ->
let tmty =
- Builtin_attributes.with_warning_attribute pmd.pmd_attributes
+ Builtin_attributes.warning_scope pmd.pmd_attributes
(fun () -> transl_modtype env_c pmd.pmd_type)
in
(id, id_loc, tmty))
ids sdecls
in
let env0 = make_env init in
- let dcl1 = transition env0 init in
+ let dcl1 =
+ Warnings.without_warnings
+ (fun () -> transition env0 init)
+ in
let env1 = make_env2 dcl1 in
check_recmod_typedecls env1 sdecls dcl1;
let dcl2 = transition env1 dcl1 in
and mty_actual' = subst_and_strengthen env s id mty_actual in
let coercion =
try
- Includemod.modtypes env mty_actual' mty_decl'
+ Includemod.modtypes ~loc:modl.mod_loc env mty_actual' mty_decl'
with Includemod.Error msg ->
raise(Error(modl.mod_loc, env, Not_included msg)) in
let modl' =
modtype_of_package env Location.none p nl tl
in
let mty1 = mkmty p1 nl1 tl1 and mty2 = mkmty p2 nl2 tl2 in
- try Includemod.modtypes env mty1 mty2 = Tcoerce_none
+ try Includemod.modtypes ~loc:Location.none env mty1 mty2 = Tcoerce_none
with Includemod.Error _msg -> false
(* raise(Error(Location.none, env, Not_included msg)) *)
let wrap_constraint env arg mty explicit =
let coercion =
try
- Includemod.modtypes env arg.mod_type mty
+ Includemod.modtypes ~loc:arg.mod_loc env arg.mod_type mty
with Includemod.Error msg ->
raise(Error(arg.mod_loc, env, Not_included msg)) in
{ mod_desc = Tmod_constraint(arg, mty, explicit, coercion);
(* Type a module value expression *)
let rec type_module ?(alias=false) sttn funct_body anchor env smod =
+ Builtin_attributes.warning_scope smod.pmod_attributes
+ (fun () -> type_module_aux ~alias sttn funct_body anchor env smod)
+
+and type_module_aux ~alias sttn funct_body anchor env smod =
match smod.pmod_desc with
Pmod_ident lid ->
let path =
end;
let coercion =
try
- Includemod.modtypes env arg.mod_type mty_param
+ Includemod.modtypes ~loc:sarg.pmod_loc env arg.mod_type mty_param
with Includemod.Error msg ->
raise(Error(sarg.pmod_loc, env, Not_included msg)) in
let mty_appl =
match desc with
| Pstr_eval (sexpr, attrs) ->
let expr =
- Builtin_attributes.with_warning_attribute attrs
+ Builtin_attributes.warning_scope attrs
(fun () -> Typecore.type_expression env sexpr)
in
Tstr_eval (expr, attrs), [], env
in
let (defs, newenv) =
Typecore.type_binding env rec_flag sdefs scope in
+ let () = if rec_flag = Recursive then
+ Typecore.check_recursive_bindings env defs
+ in
(* Note: Env.find_value does not trigger the value_used event. Values
will be marked as being used during the signature inclusion test. *)
Tstr_value(rec_flag, defs),
check_name check_module names name;
let id = Ident.create name.txt in (* create early for PR#6752 *)
let modl =
- Builtin_attributes.with_warning_attribute attrs
+ Builtin_attributes.warning_scope attrs
(fun () ->
type_module ~alias:true true funct_body
(anchor_submodule name.txt anchor) env smodl
List.map2
(fun {md_id=id; md_type=mty} (name, _, smodl, attrs, loc) ->
let modl =
- Builtin_attributes.with_warning_attribute attrs
+ Builtin_attributes.warning_scope attrs
(fun () ->
type_module true funct_body (anchor_recmodule id)
newenv smodl
| Pstr_modtype pmtd ->
(* check that it is non-abstract *)
let newenv, mtd, sg =
- Builtin_attributes.with_warning_attribute pmtd.pmtd_attributes
- (fun () -> transl_modtype_decl names env pmtd)
+ transl_modtype_decl names env pmtd
in
Tstr_modtype mtd, [sg], newenv
| Pstr_open sod ->
| Pstr_include sincl ->
let smodl = sincl.pincl_mod in
let modl =
- Builtin_attributes.with_warning_attribute sincl.pincl_attributes
+ Builtin_attributes.warning_scope sincl.pincl_attributes
(fun () -> type_module true funct_body None env smodl)
in
(* Rename all identifiers bound by this signature to avoid clashes *)
| Pstr_extension (ext, _attrs) ->
raise (Error_forward (Builtin_attributes.error_of_extension ext))
| Pstr_attribute x ->
- Builtin_attributes.warning_attribute [x];
+ Builtin_attributes.warning_attribute x;
Tstr_attribute x, [], env
in
let rec type_struct env sstr =
(* moved to genannot *)
List.iter (function {pstr_loc = l} -> Stypes.record_phrase l) sstr;
let previous_saved_types = Cmt_format.get_saved_types () in
- if not toplevel then Builtin_attributes.warning_enter_scope ();
- let (items, sg, final_env) = type_struct env sstr in
- let str = { str_items = items; str_type = sg; str_final_env = final_env } in
- if not toplevel then Builtin_attributes.warning_leave_scope ();
- Cmt_format.set_saved_types
- (Cmt_format.Partial_structure str :: previous_saved_types);
- str, sg, final_env
+ let run () =
+ let (items, sg, final_env) = type_struct env sstr in
+ let str = { str_items = items; str_type = sg; str_final_env = final_env } in
+ Cmt_format.set_saved_types
+ (Cmt_format.Partial_structure str :: previous_saved_types);
+ str, sg, final_env
+ in
+ if toplevel then run ()
+ else Builtin_attributes.warning_scope [] run
let type_toplevel_phrase env s =
Env.reset_required_globals ();
- begin
- let iter = Builtin_attributes.emit_external_warnings in
- iter.Ast_iterator.structure iter s
- end;
let (str, sg, env) =
type_structure ~toplevel:true false None env s Location.none in
let (str, _coerce) = ImplementationHooks.apply_hooks
let tl' =
List.map
(fun name -> Btype.newgenty (Tconstr (mkpath mp name,[],ref Mnil)))
+ (* beware of interactions with Printtyp and short-path:
+ mp.name may have an arity > 0, cf. PR#7534 *)
nl in
(* go back to original level *)
Ctype.end_def ();
try
Typecore.reset_delayed_checks ();
Env.reset_required_globals ();
- begin
- let iter = Builtin_attributes.emit_external_warnings in
- iter.Ast_iterator.structure iter ast
- end;
-
+ if !Clflags.print_types then (* #7656 *)
+ Warnings.parse_options false "-32-34-37-38-60";
let (str, sg, finalenv) =
type_structure initial_env ast (Location.in_file sourcefile) in
let simple_sg = simplify_signature sg in
if !Clflags.print_types then begin
+ Typecore.force_delayed_checks ();
Printtyp.wrap_printing_env initial_env
(fun () -> fprintf std_formatter "%a@." Printtyp.signature simple_sg);
(str, Tcoerce_none) (* result is ignored by Compile.implementation *)
(Cmt_format.Implementation str) (Some sourcefile) initial_env None;
(str, coercion)
end else begin
- check_nongen_schemes finalenv sg;
- normalize_signature finalenv simple_sg;
let coercion =
Includemod.compunit initial_env sourcefile sg
"(inferred signature)" simple_sg in
+ check_nongen_schemes finalenv simple_sg;
+ normalize_signature finalenv simple_sg;
Typecore.force_delayed_checks ();
(* See comment above. Here the target signature contains all
the value being exported. We can still capture unused
(Cmt_format.Interface tsg) (Some source_file) initial_env (Some cmi)
let type_interface sourcefile env ast =
- begin
- let iter = Builtin_attributes.emit_external_warnings in
- iter.Ast_iterator.signature iter ast
- end;
InterfaceHooks.apply_hooks { Misc.sourcefile } (transl_signature env ast)
(* "Packaging" of several compilation units into one unit
in the constrained signature:@]@ \
%a@]"
longident lid Includemod.report_error explanation
+ | With_makes_applicative_functor_ill_typed(lid, path, explanation) ->
+ fprintf ppf
+ "@[<v>\
+ @[This `with' constraint on %a makes the applicative functor @ \
+ type %s ill-typed in the constrained signature:@]@ \
+ %a@]"
+ longident lid (Path.name path) Includemod.report_error explanation
+ | With_changes_module_alias(lid, id, path) ->
+ fprintf ppf
+ "@[<v>\
+ @[This `with' constraint on %a changes %s, which is aliased @ \
+ in the constrained signature (as %s)@].@]"
+ longident lid (Path.name path) (Ident.name id)
+ | With_cannot_remove_constrained_type ->
+ fprintf ppf
+ "@[<v>Destructive substitutions are not supported for constrained @ \
+ types (other than when replacing a type constructor with @ \
+ a type constructor with the same arguments).@]"
| Repeated_name(kind, name) ->
fprintf ppf
"@[Multiple definition of the %s name %s.@ \
fprintf ppf
"@[This expression creates fresh types.@ %s@]"
"It is not allowed inside applicative functors."
- | With_need_typeconstr ->
- fprintf ppf
- "Only type constructors with identical parameters can be substituted."
| Not_a_packed_module ty ->
fprintf ppf
"This expression is not a packed module. It has type@ %a"
(* *)
(**************************************************************************)
-(* Type-checking of the module language *)
+(** Type-checking of the module language and typed ast plugin hooks *)
open Types
open Format
val check_nongen_schemes:
Env.t -> Types.signature -> unit
val type_open_:
- ?toplevel:bool -> Asttypes.override_flag ->
+ ?used_slot:bool ref -> ?toplevel:bool -> Asttypes.override_flag ->
Env.t -> Location.t -> Longident.t Asttypes.loc -> Path.t * Env.t
val modtype_of_package:
Env.t -> Location.t ->
| Structure_expected of module_type
| With_no_component of Longident.t
| With_mismatch of Longident.t * Includemod.error list
+ | With_makes_applicative_functor_ill_typed of
+ Longident.t * Path.t * Includemod.error list
+ | With_changes_module_alias of Longident.t * Ident.t * Path.t
+ | With_cannot_remove_constrained_type
| Repeated_name of string * string
| Non_generalizable of type_expr
| Non_generalizable_class of Ident.t * class_declaration
| Implementation_is_required of string
| Interface_not_compiled of string
| Not_allowed_in_functor_body
- | With_need_typeconstr
| Not_a_packed_module of type_expr
| Incomplete_packed_module of type_expr
| Scoping_pack of Longident.t * type_expr
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 1998 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Auxiliaries for type-based optimizations, e.g. array kinds *)
+
+open Path
+open Types
+open Asttypes
+open Typedtree
+open Lambda
+
+let scrape_ty env ty =
+ let ty = Ctype.expand_head_opt env (Ctype.correct_levels ty) in
+ match ty.desc with
+ | Tconstr (p, _, _) ->
+ begin match Env.find_type p env with
+ | {type_unboxed = {unboxed = true; _}; _} ->
+ begin match Typedecl.get_unboxed_type_representation env ty with
+ | None -> ty
+ | Some ty2 -> ty2
+ end
+ | _ -> ty
+ | exception Not_found -> ty
+ end
+ | _ -> ty
+
+let scrape env ty =
+ (scrape_ty env ty).desc
+
+let is_function_type env ty =
+ match scrape env ty with
+ | Tarrow (_, lhs, rhs, _) -> Some (lhs, rhs)
+ | _ -> None
+
+let is_base_type env ty base_ty_path =
+ match scrape env ty with
+ | Tconstr(p, _, _) -> Path.same p base_ty_path
+ | _ -> false
+
+let maybe_pointer_type env ty =
+ if Ctype.maybe_pointer_type env ty then
+ Pointer
+ else
+ Immediate
+
+let maybe_pointer exp = maybe_pointer_type exp.exp_env exp.exp_type
+
+type classification =
+ | Int
+ | Float
+ | Lazy
+ | Addr (* anything except a float or a lazy *)
+ | Any
+
+let classify env ty =
+ let ty = scrape_ty env ty in
+ if maybe_pointer_type env ty = Immediate then Int
+ else match ty.desc with
+ | Tvar _ | Tunivar _ ->
+ Any
+ | Tconstr (p, _args, _abbrev) ->
+ if Path.same p Predef.path_float then Float
+ else if Path.same p Predef.path_lazy_t then Lazy
+ else if Path.same p Predef.path_string
+ || Path.same p Predef.path_bytes
+ || Path.same p Predef.path_array
+ || Path.same p Predef.path_nativeint
+ || Path.same p Predef.path_int32
+ || Path.same p Predef.path_int64 then Addr
+ else begin
+ try
+ match (Env.find_type p env).type_kind with
+ | Type_abstract ->
+ Any
+ | Type_record _ | Type_variant _ | Type_open ->
+ Addr
+ with Not_found ->
+ (* This can happen due to e.g. missing -I options,
+ causing some .cmi files to be unavailable.
+ Maybe we should emit a warning. *)
+ Any
+ end
+ | Tarrow _ | Ttuple _ | Tpackage _ | Tobject _ | Tnil | Tvariant _ ->
+ Addr
+ | Tlink _ | Tsubst _ | Tpoly _ | Tfield _ ->
+ assert false
+
+let array_type_kind env ty =
+ match scrape env ty with
+ | Tconstr(p, [elt_ty], _) | Tpoly({desc = Tconstr(p, [elt_ty], _)}, _)
+ when Path.same p Predef.path_array ->
+ begin match classify env elt_ty with
+ | Any -> if Config.flat_float_array then Pgenarray else Paddrarray
+ | Float -> if Config.flat_float_array then Pfloatarray else Paddrarray
+ | Addr | Lazy -> Paddrarray
+ | Int -> Pintarray
+ end
+ | Tconstr(p, [], _) | Tpoly({desc = Tconstr(p, [], _)}, _)
+ when Path.same p Predef.path_floatarray ->
+ Pfloatarray
+ | _ ->
+ (* This can happen with e.g. Obj.field *)
+ Pgenarray
+
+let array_kind exp = array_type_kind exp.exp_env exp.exp_type
+
+let array_pattern_kind pat = array_type_kind pat.pat_env pat.pat_type
+
+let bigarray_decode_type env ty tbl dfl =
+ match scrape env ty with
+ | Tconstr(Pdot(Pident mod_id, type_name, _), [], _)
+ when Ident.name mod_id = "CamlinternalBigarray" ->
+ begin try List.assoc type_name tbl with Not_found -> dfl end
+ | _ ->
+ dfl
+
+let kind_table =
+ ["float32_elt", Pbigarray_float32;
+ "float64_elt", Pbigarray_float64;
+ "int8_signed_elt", Pbigarray_sint8;
+ "int8_unsigned_elt", Pbigarray_uint8;
+ "int16_signed_elt", Pbigarray_sint16;
+ "int16_unsigned_elt", Pbigarray_uint16;
+ "int32_elt", Pbigarray_int32;
+ "int64_elt", Pbigarray_int64;
+ "int_elt", Pbigarray_caml_int;
+ "nativeint_elt", Pbigarray_native_int;
+ "complex32_elt", Pbigarray_complex32;
+ "complex64_elt", Pbigarray_complex64]
+
+let layout_table =
+ ["c_layout", Pbigarray_c_layout;
+ "fortran_layout", Pbigarray_fortran_layout]
+
+let bigarray_type_kind_and_layout env typ =
+ match scrape env typ with
+ | Tconstr(_p, [_caml_type; elt_type; layout_type], _abbrev) ->
+ (bigarray_decode_type env elt_type kind_table Pbigarray_unknown,
+ bigarray_decode_type env layout_type layout_table
+ Pbigarray_unknown_layout)
+ | _ ->
+ (Pbigarray_unknown, Pbigarray_unknown_layout)
+
+let value_kind env ty =
+ match scrape env ty with
+ | Tconstr(p, _, _) when Path.same p Predef.path_int ->
+ Pintval
+ | Tconstr(p, _, _) when Path.same p Predef.path_char ->
+ Pintval
+ | Tconstr(p, _, _) when Path.same p Predef.path_float ->
+ Pfloatval
+ | Tconstr(p, _, _) when Path.same p Predef.path_int32 ->
+ Pboxedintval Pint32
+ | Tconstr(p, _, _) when Path.same p Predef.path_int64 ->
+ Pboxedintval Pint64
+ | Tconstr(p, _, _) when Path.same p Predef.path_nativeint ->
+ Pboxedintval Pnativeint
+ | _ ->
+ Pgenval
+
+
+(** Whether a forward block is needed for a lazy thunk on a value, i.e.
+ if the value can be represented as a float/forward/lazy *)
+let lazy_val_requires_forward env ty =
+ match classify env ty with
+ | Any | Lazy -> true
+ | Float -> Config.flat_float_array
+ | Addr | Int -> false
+
+(** The compilation of the expression [lazy e] depends on the form of e:
+ constants, floats and identifiers are optimized. The optimization must be
+ taken into account when determining whether a recursive binding is safe. *)
+let classify_lazy_argument : Typedtree.expression ->
+ [`Constant_or_function
+ |`Float
+ |`Identifier of [`Forward_value|`Other]
+ |`Other] =
+ fun e -> match e.exp_desc with
+ | Texp_constant
+ ( Const_int _ | Const_char _ | Const_string _
+ | Const_int32 _ | Const_int64 _ | Const_nativeint _ )
+ | Texp_function _
+ | Texp_construct (_, {cstr_arity = 0}, _) ->
+ `Constant_or_function
+ | Texp_constant(Const_float _) ->
+ `Float
+ | Texp_ident _ when lazy_val_requires_forward e.exp_env e.exp_type ->
+ `Identifier `Forward_value
+ | Texp_ident _ ->
+ `Identifier `Other
+ | _ ->
+ `Other
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
+(* *)
+(* Copyright 1998 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Auxiliaries for type-based optimizations, e.g. array kinds *)
+
+val is_function_type :
+ Env.t -> Types.type_expr -> (Types.type_expr * Types.type_expr) option
+val is_base_type : Env.t -> Types.type_expr -> Path.t -> bool
+
+val maybe_pointer_type : Env.t -> Types.type_expr
+ -> Lambda.immediate_or_pointer
+val maybe_pointer : Typedtree.expression -> Lambda.immediate_or_pointer
+
+val array_type_kind : Env.t -> Types.type_expr -> Lambda.array_kind
+val array_kind : Typedtree.expression -> Lambda.array_kind
+val array_pattern_kind : Typedtree.pattern -> Lambda.array_kind
+val bigarray_type_kind_and_layout :
+ Env.t -> Types.type_expr -> Lambda.bigarray_kind * Lambda.bigarray_layout
+val value_kind : Env.t -> Types.type_expr -> Lambda.value_kind
+
+val classify_lazy_argument : Typedtree.expression ->
+ [ `Constant_or_function
+ | `Float
+ | `Identifier of [`Forward_value | `Other]
+ | `Other]
and modtype_declaration =
{
- mtd_type: module_type option; (* Nonte: abstract *)
+ mtd_type: module_type option; (* Note: abstract *)
mtd_attributes: Parsetree.attributes;
mtd_loc: Location.t;
}
| Cstr_extension of Path.t * bool (* Extension constructor
true if a constant false if a block*)
+let equal_tag t1 t2 =
+ match (t1, t2) with
+ | Cstr_constant i1, Cstr_constant i2 -> i2 = i1
+ | Cstr_block i1, Cstr_block i2 -> i2 = i1
+ | Cstr_unboxed, Cstr_unboxed -> true
+ | Cstr_extension (path1, b1), Cstr_extension (path2, b2) ->
+ Path.same path1 path2 && b1 = b2
+ | (Cstr_constant _|Cstr_block _|Cstr_unboxed|Cstr_extension _), _ -> false
+
type label_description =
{ lbl_name: string; (* Short name *)
lbl_res: type_expr; (* Type of the result *)
| Tpoly of type_expr * type_expr list
(** [Tpoly (ty,tyl)] ==> ['a1... 'an. ty],
where 'a1 ... 'an are names given to types in tyl
- and occurences of those types in ty. *)
+ and occurrences of those types in ty. *)
| Tpackage of Path.t * Longident.t list * type_expr list
(** Type of a first-class module (a.k.a package). *)
removing abbreviations.
*)
and abbrev_memo =
- | Mnil (** No known abbrevation *)
+ | Mnil (** No known abbreviation *)
| Mcons of private_flag * Path.t * type_expr * type_expr * abbrev_memo
(** Found one abbreviation.
module Variance : sig
type t
type f = May_pos | May_neg | May_weak | Inj | Pos | Neg | Inv
- val null : t (* no occurence *)
+ val null : t (* no occurrence *)
val full : t (* strictly invariant *)
val covariant : t (* strictly covariant *)
val may_inv : t (* maybe invariant *)
| Cstr_extension of Path.t * bool (* Extension constructor
true if a constant false if a block*)
+val equal_tag : constructor_tag -> constructor_tag -> bool
+
type label_description =
{ lbl_name: string; (* Short name *)
lbl_res: type_expr; (* Type of the result *)
| Invalid_variable_name of string
| Cannot_quantify of string * type_expr
| Multiple_constraints_on_type of Longident.t
- | Repeated_method_label of string
+ | Method_mismatch of string * type_expr * type_expr
| Unbound_value of Longident.t
| Unbound_constructor of Longident.t
| Unbound_label of Longident.t
| Access_functor_as_structure of Longident.t
| Apply_structure_as_functor of Longident.t
| Cannot_scrape_alias of Longident.t * Path.t
+ | Opened_object of Path.t option
+ | Not_an_object of type_expr
exception Error of Location.t * Env.t * error
exception Error_forward of Location.error
ctyp_loc = loc; ctyp_attributes = styp.ptyp_attributes; }
| _ -> assert false
+let transl_type_param env styp =
+ (* Currently useless, since type parameters cannot hold attributes
+ (but this could easily be lifted in the future). *)
+ Builtin_attributes.warning_scope styp.ptyp_attributes
+ (fun () -> transl_type_param env styp)
+
+
let new_pre_univar ?name () =
let v = newvar ?name () in pre_univars := v :: !pre_univars; v
type policy = Fixed | Extensible | Univars
let rec transl_type env policy styp =
+ Builtin_attributes.warning_scope styp.ptyp_attributes
+ (fun () -> transl_type_aux env policy styp)
+
+and transl_type_aux env policy styp =
let loc = styp.ptyp_loc in
let ctyp ctyp_desc ctyp_type =
{ ctyp_desc; ctyp_type; ctyp_env = env;
end;
ctyp (Ttyp_constr (path, lid, args)) constr
| Ptyp_object (fields, o) ->
- let fields =
- List.map (fun (s, a, t) -> (s.txt, a, transl_poly_type env policy t))
- fields
- in
- let ty = newobj (transl_fields loc env policy [] o fields) in
- ctyp (Ttyp_object (fields, o)) ty
+ let ty, fields = transl_fields env policy o fields in
+ ctyp (Ttyp_object (fields, o)) (newobj ty)
| Ptyp_class(lid, stl) ->
let (path, decl, _is_variant) =
try
check (Env.find_type path env)
| _ -> raise Not_found
in check decl;
- Location.prerr_warning styp.ptyp_loc
- (Warnings.Deprecated "old syntax for polymorphic variant type");
+ Location.deprecated styp.ptyp_loc
+ "old syntax for polymorphic variant type";
(path, decl,true)
with Not_found -> try
let lid2 =
let add_field = function
Rtag (l, attrs, c, stl) ->
name := None;
- let tl = List.map (transl_type env policy) stl in
+ let tl =
+ Builtin_attributes.warning_scope attrs
+ (fun () -> List.map (transl_type env policy) stl)
+ in
let f = match present with
- Some present when not (List.mem l present) ->
+ Some present when not (List.mem l.txt present) ->
let ty_tl = List.map (fun cty -> cty.ctyp_type) tl in
Reither(c, ty_tl, false, ref None)
| _ ->
if List.length stl > 1 || c && stl <> [] then
- raise(Error(styp.ptyp_loc, env, Present_has_conjunction l));
+ raise(Error(styp.ptyp_loc, env,
+ Present_has_conjunction l.txt));
match tl with [] -> Rpresent None
| st :: _ ->
Rpresent (Some st.ctyp_type)
in
- add_typed_field styp.ptyp_loc l f;
+ add_typed_field styp.ptyp_loc l.txt f;
Ttag (l,attrs,c,tl)
| Rinherit sty ->
let cty = transl_type env policy sty in
and transl_poly_type env policy t =
transl_type env policy (Ast_helper.Typ.force_poly t)
-and transl_fields loc env policy seen o =
- function
- [] ->
- begin match o, policy with
- | Closed, _ -> newty Tnil
- | Open, Univars -> new_pre_univar ()
- | Open, _ -> newvar ()
+and transl_fields env policy o fields =
+ let hfields = Hashtbl.create 17 in
+ let add_typed_field loc l ty =
+ try
+ let ty' = Hashtbl.find hfields l in
+ if equal env false [ty] [ty'] then () else
+ try unify env ty ty'
+ with Unify _trace ->
+ raise(Error(loc, env, Method_mismatch (l, ty, ty')))
+ with Not_found ->
+ Hashtbl.add hfields l ty in
+ let add_field = function
+ | Otag (s, a, ty1) -> begin
+ let ty1 =
+ Builtin_attributes.warning_scope a
+ (fun () -> transl_poly_type env policy ty1)
+ in
+ let field = OTtag (s, a, ty1) in
+ add_typed_field ty1.ctyp_loc s.txt ty1.ctyp_type;
+ field
end
- | (s, _attrs, ty1) :: l ->
- if List.mem s seen then raise (Error (loc, env, Repeated_method_label s));
- let ty2 = transl_fields loc env policy (s :: seen) o l in
- newty (Tfield (s, Fpresent, ty1.ctyp_type, ty2))
+ | Oinherit sty -> begin
+ let cty = transl_type env policy sty in
+ let nm =
+ match repr cty.ctyp_type with
+ {desc=Tconstr(p, _, _)} -> Some p
+ | _ -> None in
+ let t = expand_head env cty.ctyp_type in
+ match t, nm with
+ {desc=Tobject ({desc=(Tfield _ | Tnil) as tf}, _)}, _ -> begin
+ if opened_object t then
+ raise (Error (sty.ptyp_loc, env, Opened_object nm));
+ let rec iter_add = function
+ | Tfield (s, _k, ty1, ty2) -> begin
+ add_typed_field sty.ptyp_loc s ty1;
+ iter_add ty2.desc
+ end
+ | Tnil -> ()
+ | _ -> assert false in
+ iter_add tf;
+ OTinherit cty
+ end
+ | {desc=Tvar _}, Some p ->
+ raise (Error (sty.ptyp_loc, env, Unbound_type_constructor_2 p))
+ | _ -> raise (Error (sty.ptyp_loc, env, Not_an_object t))
+ end in
+ let object_fields = List.map add_field fields in
+ let fields = Hashtbl.fold (fun s ty l -> (s, ty) :: l) hfields [] in
+ let ty_init =
+ match o, policy with
+ | Closed, _ -> newty Tnil
+ | Open, Univars -> new_pre_univar ()
+ | Open, _ -> newvar () in
+ let ty = List.fold_left (fun ty (s, ty') ->
+ newty (Tfield (s, Fpresent, ty', ty))) ty_init fields in
+ ty, object_fields
+
(* Make the rows "fixed" in this type, to make universal check easier *)
let rec make_fixed_univars ty =
Printtyp.type_expr ty')
| Not_a_variant ty ->
Printtyp.reset_and_mark_loops ty;
- fprintf ppf "@[The type %a@ is not a polymorphic variant type@]"
+ fprintf ppf
+ "@[The type %a@ does not expand to a polymorphic variant type@]"
Printtyp.type_expr ty;
begin match ty.desc with
| Tvar (Some s) ->
else "it is not a variable")
| Multiple_constraints_on_type s ->
fprintf ppf "Multiple constraints for type %a" longident s
- | Repeated_method_label s ->
- fprintf ppf "@[This is the second method `%s' of this object type.@ %s@]"
- s "Multiple occurrences are not allowed."
+ | Method_mismatch (l, ty, ty') ->
+ wrap_printing_env env (fun () ->
+ Printtyp.reset_and_mark_loops_list [ty; ty'];
+ fprintf ppf "@[<hov>Method '%s' has type %a,@ which should be %a@]"
+ l Printtyp.type_expr ty Printtyp.type_expr ty')
| Unbound_value lid ->
fprintf ppf "Unbound value %a" longident lid;
spellcheck ppf fold_values env lid;
fprintf ppf
"The module %a is an alias for module %a, which is missing"
longident lid path p
+ | Opened_object nm ->
+ fprintf ppf
+ "Illegal open object type%a"
+ (fun ppf -> function
+ Some p -> fprintf ppf "@ %a" path p
+ | None -> fprintf ppf "") nm
+ | Not_an_object ty ->
+ Printtyp.reset_and_mark_loops ty;
+ fprintf ppf "@[The type %a@ is not an object type@]"
+ Printtyp.type_expr ty
let () =
Location.register_error_of_exn
| Invalid_variable_name of string
| Cannot_quantify of string * type_expr
| Multiple_constraints_on_type of Longident.t
- | Repeated_method_label of string
+ | Method_mismatch of string * type_expr * type_expr
| Unbound_value of Longident.t
| Unbound_constructor of Longident.t
| Unbound_label of Longident.t
| Access_functor_as_structure of Longident.t
| Apply_structure_as_functor of Longident.t
| Cannot_scrape_alias of Longident.t * Path.t
+ | Opened_object of Path.t option
+ | Not_an_object of type_expr
exception Error of Location.t * Env.t * error
open_description: mapper -> T.open_description -> open_description;
pat: mapper -> T.pattern -> pattern;
row_field: mapper -> T.row_field -> row_field;
+ object_field: mapper -> T.object_field -> object_field;
signature: mapper -> T.signature -> signature;
signature_item: mapper -> T.signature_item -> signature_item;
structure: mapper -> T.structure -> structure;
(sub.typ sub v.val_desc)
let module_binding sub mb =
- let loc = sub.location sub mb.mb_loc; in
+ let loc = sub.location sub mb.mb_loc in
let attrs = sub.attributes sub mb.mb_attributes in
Mb.mk ~loc ~attrs
(map_loc sub mb.mb_name)
let type_parameter sub (ct, v) = (sub.typ sub ct, v)
let type_declaration sub decl =
- let loc = sub.location sub decl.typ_loc; in
+ let loc = sub.location sub decl.typ_loc in
let attrs = sub.attributes sub decl.typ_attributes in
Type.mk ~loc ~attrs
~params:(List.map (type_parameter sub) decl.typ_params)
| Cstr_record l -> Pcstr_record (List.map (sub.label_declaration sub) l)
let constructor_declaration sub cd =
- let loc = sub.location sub cd.cd_loc; in
+ let loc = sub.location sub cd.cd_loc in
let attrs = sub.attributes sub cd.cd_attributes in
Type.constructor ~loc ~attrs
~args:(constructor_arguments sub cd.cd_args)
(map_loc sub cd.cd_name)
let label_declaration sub ld =
- let loc = sub.location sub ld.ld_loc; in
+ let loc = sub.location sub ld.ld_loc in
let attrs = sub.attributes sub ld.ld_attributes in
Type.field ~loc ~attrs
~mut:ld.ld_mutable
(List.map (sub.extension_constructor sub) tyext.tyext_constructors)
let extension_constructor sub ext =
- let loc = sub.location sub ext.ext_loc; in
+ let loc = sub.location sub ext.ext_loc in
let attrs = sub.attributes sub ext.ext_attributes in
Te.constructor ~loc ~attrs
(map_loc sub ext.ext_name)
)
let pattern sub pat =
- let loc = sub.location sub pat.pat_loc; in
+ let loc = sub.location sub pat.pat_loc in
(* todo: fix attributes on extras *)
let attrs = sub.attributes sub pat.pat_attributes in
let desc =
Pat.mk ~loc ~attrs desc
let exp_extra sub (extra, loc, attrs) sexp =
- let loc = sub.location sub loc; in
+ let loc = sub.location sub loc in
let attrs = sub.attributes sub attrs in
let desc =
match extra with
}
let value_binding sub vb =
- let loc = sub.location sub vb.vb_loc; in
+ let loc = sub.location sub vb.vb_loc in
let attrs = sub.attributes sub vb.vb_attributes in
Vb.mk ~loc ~attrs
(sub.pat sub vb.vb_pat)
(sub.expr sub vb.vb_expr)
let expression sub exp =
- let loc = sub.location sub exp.exp_loc; in
+ let loc = sub.location sub exp.exp_loc in
let attrs = sub.attributes sub exp.exp_attributes in
let desc =
match exp.exp_desc with
(s, sub.typ sub ct)) pack.pack_fields)
let module_type_declaration sub mtd =
- let loc = sub.location sub mtd.mtd_loc; in
+ let loc = sub.location sub mtd.mtd_loc in
let attrs = sub.attributes sub mtd.mtd_attributes in
Mtd.mk ~loc ~attrs
?typ:(map_opt (sub.module_type sub) mtd.mtd_type)
List.map (sub.signature_item sub) sg.sig_items
let signature_item sub item =
- let loc = sub.location sub item.sig_loc; in
+ let loc = sub.location sub item.sig_loc in
let desc =
match item.sig_desc with
Tsig_value v ->
Sig.mk ~loc desc
let module_declaration sub md =
- let loc = sub.location sub md.md_loc; in
+ let loc = sub.location sub md.md_loc in
let attrs = sub.attributes sub md.md_attributes in
Md.mk ~loc ~attrs
(map_loc sub md.md_name)
(sub.module_type sub md.md_type)
let include_infos f sub incl =
- let loc = sub.location sub incl.incl_loc; in
+ let loc = sub.location sub incl.incl_loc in
let attrs = sub.attributes sub incl.incl_attributes in
Incl.mk ~loc ~attrs
(f sub incl.incl_mod)
let include_description sub = include_infos sub.module_type sub
let class_infos f sub ci =
- let loc = sub.location sub ci.ci_loc; in
+ let loc = sub.location sub ci.ci_loc in
let attrs = sub.attributes sub ci.ci_attributes in
Ci.mk ~loc ~attrs
~virt:ci.ci_virt
let class_type_declaration sub = class_infos sub.class_type sub
let module_type sub mty =
- let loc = sub.location sub mty.mty_loc; in
+ let loc = sub.location sub mty.mty_loc in
let attrs = sub.attributes sub mty.mty_attributes in
let desc = match mty.mty_desc with
Tmty_ident (_path, lid) -> Pmty_ident (map_loc sub lid)
Pwith_type (map_loc sub lid, sub.type_declaration sub decl)
| Twith_module (_path, lid2) ->
Pwith_module (map_loc sub lid, map_loc sub lid2)
- | Twith_typesubst decl -> Pwith_typesubst (sub.type_declaration sub decl)
+ | Twith_typesubst decl ->
+ Pwith_typesubst (map_loc sub lid, sub.type_declaration sub decl)
| Twith_modsubst (_path, lid2) ->
- Pwith_modsubst
- ({loc = sub.location sub lid.loc; txt=Longident.last lid.txt},
- map_loc sub lid2)
+ Pwith_modsubst (map_loc sub lid, map_loc sub lid2)
let module_expr sub mexpr =
- let loc = sub.location sub mexpr.mod_loc; in
+ let loc = sub.location sub mexpr.mod_loc in
let attrs = sub.attributes sub mexpr.mod_attributes in
match mexpr.mod_desc with
Tmod_constraint (m, _, Tmodtype_implicit, _ ) ->
Mod.mk ~loc ~attrs desc
let class_expr sub cexpr =
- let loc = sub.location sub cexpr.cl_loc; in
+ let loc = sub.location sub cexpr.cl_loc in
let attrs = sub.attributes sub cexpr.cl_attributes in
let desc = match cexpr.cl_desc with
| Tcl_constraint ( { cl_desc = Tcl_ident (_path, lid, tyl); _ },
| Tcl_constraint (cl, Some clty, _vals, _meths, _concrs) ->
Pcl_constraint (sub.class_expr sub cl, sub.class_type sub clty)
+ | Tcl_open (ovf, _p, lid, _env, e) ->
+ Pcl_open (ovf, lid, sub.class_expr sub e)
+
| Tcl_ident _ -> assert false
| Tcl_constraint (_, None, _, _, _) -> assert false
in
Cl.mk ~loc ~attrs desc
let class_type sub ct =
- let loc = sub.location sub ct.cltyp_loc; in
+ let loc = sub.location sub ct.cltyp_loc in
let attrs = sub.attributes sub ct.cltyp_attributes in
let desc = match ct.cltyp_desc with
Tcty_signature csg -> Pcty_signature (sub.class_signature sub csg)
Pcty_constr (map_loc sub lid, List.map (sub.typ sub) list)
| Tcty_arrow (label, ct, cl) ->
Pcty_arrow (label, sub.typ sub ct, sub.class_type sub cl)
+ | Tcty_open (ovf, _p, lid, _env, e) ->
+ Pcty_open (ovf, lid, sub.class_type sub e)
in
Cty.mk ~loc ~attrs desc
}
let class_type_field sub ctf =
- let loc = sub.location sub ctf.ctf_loc; in
+ let loc = sub.location sub ctf.ctf_loc in
let attrs = sub.attributes sub ctf.ctf_attributes in
let desc = match ctf.ctf_desc with
Tctf_inherit ct -> Pctf_inherit (sub.class_type sub ct)
Ctf.mk ~loc ~attrs desc
let core_type sub ct =
- let loc = sub.location sub ct.ctyp_loc; in
+ let loc = sub.location sub ct.ctyp_loc in
let attrs = sub.attributes sub ct.ctyp_attributes in
let desc = match ct.ctyp_desc with
Ttyp_any -> Ptyp_any
List.map (sub.typ sub) list)
| Ttyp_object (list, o) ->
Ptyp_object
- (List.map (fun (s, a, t) ->
- (mkloc s loc, a, sub.typ sub t)) list, o)
+ (List.map (sub.object_field sub) list, o)
| Ttyp_class (_path, lid, list) ->
Ptyp_class (map_loc sub lid, List.map (sub.typ sub) list)
| Ttyp_alias (ct, s) ->
Rtag (label, sub.attributes sub attrs, bool, List.map (sub.typ sub) list)
| Tinherit ct -> Rinherit (sub.typ sub ct)
+let object_field sub ofield =
+ match ofield with
+ OTtag (label, attrs, ct) ->
+ Otag (label, sub.attributes sub attrs, sub.typ sub ct)
+ | OTinherit ct -> Oinherit (sub.typ sub ct)
+
and is_self_pat = function
| { pat_desc = Tpat_alias(_pat, id, _) } ->
string_is_prefix "self-" (Ident.name id)
| _ -> false
let class_field sub cf =
- let loc = sub.location sub cf.cf_loc; in
+ let loc = sub.location sub cf.cf_loc in
let attrs = sub.attributes sub cf.cf_attributes in
let desc = match cf.cf_desc with
Tcf_inherit (ovf, cl, super, _vals, _meths) ->
case = case;
location = location;
row_field = row_field ;
+ object_field = object_field ;
}
let untype_structure ?(mapper=default_mapper) structure =
open_description: mapper -> Typedtree.open_description -> open_description;
pat: mapper -> Typedtree.pattern -> pattern;
row_field: mapper -> Typedtree.row_field -> row_field;
+ object_field: mapper -> Typedtree.object_field -> object_field;
signature: mapper -> Typedtree.signature -> signature;
signature_item: mapper -> Typedtree.signature_item -> signature_item;
structure: mapper -> Typedtree.structure -> structure;
close_in c;
Sys.remove file
-let compile_file name =
+let compile_file ?output ?(opt="") name =
let (pipe, file) =
if Config.ccomp_type = "msvc" && not !Clflags.verbose then
try
let exit =
command
(Printf.sprintf
- "%s -c %s %s %s %s %s%s"
+ "%s %s %s -c %s %s %s %s %s%s"
(match !Clflags.c_compiler with
| Some cc -> cc
| None ->
- if !Clflags.native_code
- then Config.native_c_compiler
- else Config.bytecomp_c_compiler)
+ let (cflags, cppflags) =
+ if !Clflags.native_code
+ then (Config.ocamlopt_cflags, Config.ocamlopt_cppflags)
+ else (Config.ocamlc_cflags, Config.ocamlc_cppflags) in
+ (String.concat " " [Config.c_compiler; cflags; cppflags]))
+ (match output with
+ | None -> ""
+ | Some o -> Printf.sprintf "%s%s" Config.c_output_obj o)
+ opt
(if !Clflags.debug && Config.ccomp_type <> "msvc" then "-g" else "")
(String.concat " " (List.rev !Clflags.all_ccopts))
(quote_prefixed "-I" (List.rev !Clflags.include_dirs))
val command: string -> int
val run_command: string -> unit
-val compile_file: string -> int
+val compile_file: ?output:string -> ?opt:string -> string -> int
val create_archive: string -> string list -> int
val expand_libname: string -> string
val quote_files: string list -> string
and make_archive = ref false (* -a *)
and debug = ref false (* -g *)
and fast = ref false (* -unsafe *)
+and use_linscan = ref false (* -linscan *)
and link_everything = ref false (* -linkall *)
and custom_runtime = ref false (* -custom *)
and no_check_prims = ref false (* -no-check-prims *)
let dump_selection = ref false (* -dsel *)
let dump_cse = ref false (* -dcse *)
let dump_live = ref false (* -dlive *)
+let dump_avail = ref false (* -davail *)
let dump_spill = ref false (* -dspill *)
let dump_split = ref false (* -dsplit *)
let dump_interf = ref false (* -dinterf *)
let dump_reload = ref false (* -dreload *)
let dump_scheduling = ref false (* -dscheduling *)
let dump_linear = ref false (* -dlinear *)
+let dump_interval = ref false (* -dinterval *)
let keep_startup_file = ref false (* -dstartup *)
let dump_combine = ref false (* -dcombine *)
-let print_timings = ref false (* -dtimings *)
+let profile_columns : Profile.column list ref = ref [] (* -dprofile/-dtimings *)
+
+let debug_runavail = ref false (* -drunavail *)
let native_code = ref false (* set to true under ocamlopt *)
let runtime_variant = ref "";; (* -runtime-variant *)
let keep_docs = ref false (* -keep-docs *)
-let keep_locs = ref false (* -keep-locs *)
-let unsafe_string = ref (not Config.safe_string)
+let keep_locs = ref true (* -keep-locs *)
+let unsafe_string =
+ if Config.safe_string then ref false
+ else ref (not Config.default_safe_string)
(* -safe-string / -unsafe-string *)
let classic_inlining = ref false (* -Oclassic *)
let arg_spec = ref []
let arg_names = ref Misc.StringMap.empty
+
+let reset_arguments () =
+ arg_spec := [];
+ arg_names := Misc.StringMap.empty
+
let add_arguments loc args =
List.iter (function (arg_name, _, _) as arg ->
try
(* *)
(**************************************************************************)
+(** Command line flags *)
+
(** Optimization parameters represented as ints indexed by round number. *)
module Int_arg_helper : sig
type parsed
val make_archive : bool ref
val debug : bool ref
val fast : bool ref
+val use_linscan : bool ref
val link_everything : bool ref
val custom_runtime : bool ref
val no_check_prims : bool ref
val dump_selection : bool ref
val dump_cse : bool ref
val dump_live : bool ref
+val dump_avail : bool ref
+val debug_runavail : bool ref
val dump_spill : bool ref
val dump_split : bool ref
val dump_interf : bool ref
val dump_reload : bool ref
val dump_scheduling : bool ref
val dump_linear : bool ref
+val dump_interval : bool ref
val keep_startup_file : bool ref
val dump_combine : bool ref
val native_code : bool ref
val keep_locs : bool ref
val unsafe_string : bool ref
val opaque : bool ref
-val print_timings : bool ref
+val profile_columns : Profile.column list ref
val flambda_invariant_checks : bool ref
val unbox_closures : bool ref
val unbox_closures_factor : int ref
*)
val parse_arguments : Arg.anon_fun -> string -> unit
+(* [print_arguments usage] print the standard usage message *)
val print_arguments : string -> unit
+
+(* [reset_arguments ()] clear all declared arguments *)
+val reset_arguments : unit -> unit
(* The "kind" of the C compiler, assembler and linker used: one of
"cc" (for Unix-style C compilers)
"msvc" (for Microsoft Visual C++ and MASM) *)
-val bytecomp_c_compiler: string
- (* The C compiler to use for compiling C files
- with the bytecode compiler *)
+val c_compiler: string
+ (* The compiler to use for compiling C files *)
+val c_output_obj: string
+ (* Name of the option of the C compiler for specifying the output file *)
+val ocamlc_cflags : string
+ (* The flags ocamlc should pass to the C compiler *)
+val ocamlc_cppflags : string
+ (* The flags ocamlc should pass to the C preprocessor *)
+val ocamlopt_cflags : string
+ (* The flags ocamlopt should pass to the C compiler *)
+val ocamlopt_cppflags : string
+ (* The flags ocamlopt should pass to the C preprocessor *)
val bytecomp_c_libraries: string
(* The C libraries to link with custom runtimes *)
-val native_c_compiler: string
- (* The C compiler to use for compiling C files
- with the native-code compiler *)
val native_c_libraries: string
(* The C libraries to link with native-code programs *)
val native_pack_linker: string
val spacetime : bool
(* Whether the compiler was configured for Spacetime profiling *)
+val enable_call_counts : bool
+ (* Whether call counts are to be available when Spacetime profiling *)
val profinfo : bool
(* Whether the compiler was configured for profiling *)
val profinfo_width : int
(* Linker flags to use libunwind *)
val safe_string: bool
- (* Whether the compiler was configured with -safe-string *)
+ (* Whether the compiler was configured with -force-safe-string;
+ in that case, the -unsafe-string compile-time option is unavailable
+
+ @since 4.05.0 *)
+val default_safe_string: bool
+ (* Whether the compiler was configured to use the -safe-string
+ or -unsafe-string compile-time option by default.
+
+ @since 4.06.0 *)
+val flat_float_array : bool
+ (* Whether the compiler and runtime automagically flatten float
+ arrays *)
+val windows_unicode: bool
+ (* Whether Windows Unicode runtime is enabled *)
val afl_instrument : bool
(* Whether afl-fuzz instrumentation is generated by default *)
let standard_runtime = "%%BYTERUN%%"
let ccomp_type = "%%CCOMPTYPE%%"
-let bytecomp_c_compiler = "%%BYTECODE_C_COMPILER%%"
+let c_compiler = "%%CC%%"
+let c_output_obj = "%%OUTPUTOBJ%%"
+let ocamlc_cflags = "%%OCAMLC_CFLAGS%%"
+let ocamlc_cppflags = "%%OCAMLC_CPPFLAGS%%"
+let ocamlopt_cflags = "%%OCAMLOPT_CFLAGS%%"
+let ocamlopt_cppflags = "%%OCAMLOPT_CPPFLAGS%%"
let bytecomp_c_libraries = "%%BYTECCLIBS%%"
-let native_c_compiler = "%%NATIVE_C_COMPILER%%"
+(* bytecomp_c_compiler and native_c_compiler have been supported for a
+ long time and are retained for backwards compatibility.
+ For programs that don't need compatibility with older OCaml releases
+ the recommended approach is to use the constituent variables
+ c_compiler, ocamlc_cflags, ocamlc_cppflags etc., directly.
+*)
+let bytecomp_c_compiler =
+ c_compiler ^ " " ^ ocamlc_cflags ^ " " ^ ocamlc_cppflags
+let native_c_compiler =
+ c_compiler ^ " " ^ ocamlopt_cflags ^ " " ^ ocamlopt_cppflags
let native_c_libraries = "%%NATIVECCLIBS%%"
let native_pack_linker = "%%PACKLD%%"
let ranlib = "%%RANLIBCMD%%"
if c = '/' then '\\' else c in
(String.init (String.length flexlink) f) ^ " %%FLEXLINK_FLAGS%%" in
flexlink,
- flexlink ^ " -exe",
+ flexlink ^ " -exe%%FLEXLINK_LDFLAGS%%",
flexlink ^ " -maindll"
with Not_found ->
"%%MKDLL%%", "%%MKEXE%%", "%%MKMAINDLL%%"
let profiling = %%PROFILING%%
let flambda = %%FLAMBDA%%
-let safe_string = %%SAFE_STRING%%
+let safe_string = %%FORCE_SAFE_STRING%%
+let default_safe_string = %%DEFAULT_SAFE_STRING%%
+let windows_unicode = %%WINDOWS_UNICODE%% != 0
+
+let flat_float_array = %%FLAT_FLOAT_ARRAY%%
let afl_instrument = %%AFL_INSTRUMENT%%
let exec_magic_number = "Caml1999X011"
-and cmi_magic_number = "Caml1999I021"
-and cmo_magic_number = "Caml1999O011"
-and cma_magic_number = "Caml1999A012"
+and cmi_magic_number = "Caml1999I022"
+and cmo_magic_number = "Caml1999O022"
+and cma_magic_number = "Caml1999A022"
and cmx_magic_number =
if flambda then
- "Caml1999Y016"
+ "Caml1999y022"
else
- "Caml1999Y015"
+ "Caml1999Y022"
and cmxa_magic_number =
if flambda then
- "Caml1999Z015"
+ "Caml1999z022"
else
- "Caml1999Z014"
-and ast_impl_magic_number = "Caml1999M020"
-and ast_intf_magic_number = "Caml1999N018"
-and cmxs_magic_number = "Caml2007D002"
-and cmt_magic_number = "Caml2012T009"
+ "Caml1999Z022"
+and ast_impl_magic_number = "Caml1999M022"
+and ast_intf_magic_number = "Caml1999N022"
+and cmxs_magic_number = "Caml1999D022"
+ (* cmxs_magic_number is duplicated in otherlibs/dynlink/natdynlink.ml *)
+and cmt_magic_number = "Caml1999T022"
let load_path = ref ([] : string list)
let asm_cfi_supported = %%ASM_CFI_SUPPORTED%%
let with_frame_pointers = %%WITH_FRAME_POINTERS%%
let spacetime = %%WITH_SPACETIME%%
+let enable_call_counts = %%ENABLE_CALL_COUNTS%%
let libunwind_available = %%LIBUNWIND_AVAILABLE%%
let libunwind_link_flags = "%%LIBUNWIND_LINK_FLAGS%%"
let profinfo = %%WITH_PROFINFO%%
let profinfo_width = %%PROFINFO_WIDTH%%
-let ext_exe = "%%EXT_EXE%%"
+let ext_exe = "%%EXE%%"
let ext_obj = "%%EXT_OBJ%%"
let ext_asm = "%%EXT_ASM%%"
let ext_lib = "%%EXT_LIB%%"
p "standard_library" standard_library;
p "standard_runtime" standard_runtime;
p "ccomp_type" ccomp_type;
+ p "c_compiler" c_compiler;
+ p "ocamlc_cflags" ocamlc_cflags;
+ p "ocamlc_cppflags" ocamlc_cppflags;
+ p "ocamlopt_cflags" ocamlopt_cflags;
+ p "ocamlopt_cppflags" ocamlopt_cppflags;
p "bytecomp_c_compiler" bytecomp_c_compiler;
- p "bytecomp_c_libraries" bytecomp_c_libraries;
p "native_c_compiler" native_c_compiler;
+ p "bytecomp_c_libraries" bytecomp_c_libraries;
p "native_c_libraries" native_c_libraries;
p "native_pack_linker" native_pack_linker;
p "ranlib" ranlib;
p_bool "flambda" flambda;
p_bool "spacetime" spacetime;
p_bool "safe_string" safe_string;
+ p_bool "default_safe_string" default_safe_string;
+ p_bool "flat_float_array" flat_float_array;
+ p_bool "afl_instrument" afl_instrument;
+ p_bool "windows_unicode" windows_unicode;
(* print the magic number *)
p "exec_magic_number" exec_magic_number;
(* *)
(**************************************************************************)
-module Stdlib_map = Map
-module Stdlib_set = Set
-
module type Thing = sig
type t
val print : Format.formatter -> t -> unit
end
+module type Set = sig
+ module T : Set.OrderedType
+ include Set.S
+ with type elt = T.t
+ and type t = Set.Make (T).t
+
+ val output : out_channel -> t -> unit
+ val print : Format.formatter -> t -> unit
+ val to_string : t -> string
+ val of_list : elt list -> t
+ val map : (elt -> elt) -> t -> t
+end
+
+module type Map = sig
+ module T : Map.OrderedType
+ include Map.S
+ with type key = T.t
+ and type 'a t = 'a Map.Make (T).t
+
+ val filter_map : 'a t -> f:(key -> 'a -> 'b option) -> 'b t
+ val of_list : (key * 'a) list -> 'a t
+
+ val disjoint_union : ?eq:('a -> 'a -> bool) -> ?print:(Format.formatter -> 'a -> unit) -> 'a t -> 'a t -> 'a t
+
+ val union_right : 'a t -> 'a t -> 'a t
+
+ val union_left : 'a t -> 'a t -> 'a t
+
+ val union_merge : ('a -> 'a -> 'a) -> 'a t -> 'a t -> 'a t
+ val rename : key t -> key -> key
+ val map_keys : (key -> key) -> 'a t -> 'a t
+ val keys : 'a t -> Set.Make(T).t
+ val data : 'a t -> 'a list
+ val of_set : (key -> 'a) -> Set.Make(T).t -> 'a t
+ val transpose_keys_and_data : key t -> key t
+ val transpose_keys_and_data_set : key t -> Set.Make(T).t t
+ val print :
+ (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a t -> unit
+end
+
+module type Tbl = sig
+ module T : sig
+ type t
+ include Map.OrderedType with type t := t
+ include Hashtbl.HashedType with type t := t
+ end
+ include Hashtbl.S
+ with type key = T.t
+ and type 'a t = 'a Hashtbl.Make (T).t
+
+ val to_list : 'a t -> (T.t * 'a) list
+ val of_list : (T.t * 'a) list -> 'a t
+
+ val to_map : 'a t -> 'a Map.Make(T).t
+ val of_map : 'a Map.Make(T).t -> 'a t
+ val memoize : 'a t -> (key -> 'a) -> key -> 'a
+ val map : 'a t -> ('a -> 'b) -> 'b t
+end
+
module Pair (A : Thing) (B : Thing) : Thing with type t = A.t * B.t = struct
type t = A.t * B.t
module T : Thing with type t = t
include Thing with type t := T.t
- module Set : sig
- include Stdlib_set.S
- with type elt = T.t
- and type t = Make_set (T).t
-
- val output : out_channel -> t -> unit
- val print : Format.formatter -> t -> unit
- val to_string : t -> string
- val of_list : elt list -> t
- val map : (elt -> elt) -> t -> t
- end
-
- module Map : sig
- include Stdlib_map.S
- with type key = T.t
- and type 'a t = 'a Make_map (T).t
-
- val filter_map : 'a t -> f:(key -> 'a -> 'b option) -> 'b t
- val of_list : (key * 'a) list -> 'a t
- val disjoint_union : ?eq:('a -> 'a -> bool) -> ?print:(Format.formatter -> 'a -> unit) -> 'a t -> 'a t -> 'a t
- val union_right : 'a t -> 'a t -> 'a t
- val union_left : 'a t -> 'a t -> 'a t
- val union_merge : ('a -> 'a -> 'a) -> 'a t -> 'a t -> 'a t
- val rename : key t -> key -> key
- val map_keys : (key -> key) -> 'a t -> 'a t
- val keys : 'a t -> Make_set (T).t
- val data : 'a t -> 'a list
- val of_set : (key -> 'a) -> Make_set (T).t -> 'a t
- val transpose_keys_and_data : key t -> key t
- val transpose_keys_and_data_set : key t -> Set.t t
- val print :
- (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a t -> unit
- end
-
- module Tbl : sig
- include Hashtbl.S
- with type key = T.t
- and type 'a t = 'a Hashtbl.Make (T).t
-
- val to_list : 'a t -> (T.t * 'a) list
- val of_list : (T.t * 'a) list -> 'a t
-
- val to_map : 'a t -> 'a Make_map (T).t
- val of_map : 'a Make_map (T).t -> 'a t
- val memoize : 'a t -> (key -> 'a) -> key -> 'a
- val map : 'a t -> ('a -> 'b) -> 'b t
- end
+ module Set : Set with module T := T
+ module Map : Map with module T := T
+ module Tbl : Tbl with module T := T
end
module Make (T : Thing) = struct
module Pair : functor (A : Thing) (B : Thing) -> Thing with type t = A.t * B.t
-module type S = sig
- type t
+module type Set = sig
+ module T : Set.OrderedType
+ include Set.S
+ with type elt = T.t
+ and type t = Set.Make (T).t
- module T : Thing with type t = t
- include Thing with type t := T.t
+ val output : out_channel -> t -> unit
+ val print : Format.formatter -> t -> unit
+ val to_string : t -> string
+ val of_list : elt list -> t
+ val map : (elt -> elt) -> t -> t
+end
- module Set : sig
- include Set.S
- with type elt = T.t
- and type t = Set.Make (T).t
+module type Map = sig
+ module T : Map.OrderedType
+ include Map.S
+ with type key = T.t
+ and type 'a t = 'a Map.Make (T).t
+
+ val filter_map : 'a t -> f:(key -> 'a -> 'b option) -> 'b t
+ val of_list : (key * 'a) list -> 'a t
+
+ (** [disjoint_union m1 m2] contains all bindings from [m1] and
+ [m2]. If some binding is present in both and the associated
+ value is not equal, a Fatal_error is raised *)
+ val disjoint_union : ?eq:('a -> 'a -> bool) -> ?print:(Format.formatter -> 'a -> unit) -> 'a t -> 'a t -> 'a t
+
+ (** [union_right m1 m2] contains all bindings from [m1] and [m2]. If
+ some binding is present in both, the one from [m2] is taken *)
+ val union_right : 'a t -> 'a t -> 'a t
+
+ (** [union_left m1 m2 = union_right m2 m1] *)
+ val union_left : 'a t -> 'a t -> 'a t
+
+ val union_merge : ('a -> 'a -> 'a) -> 'a t -> 'a t -> 'a t
+ val rename : key t -> key -> key
+ val map_keys : (key -> key) -> 'a t -> 'a t
+ val keys : 'a t -> Set.Make(T).t
+ val data : 'a t -> 'a list
+ val of_set : (key -> 'a) -> Set.Make(T).t -> 'a t
+ val transpose_keys_and_data : key t -> key t
+ val transpose_keys_and_data_set : key t -> Set.Make(T).t t
+ val print :
+ (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a t -> unit
+end
- val output : out_channel -> t -> unit
- val print : Format.formatter -> t -> unit
- val to_string : t -> string
- val of_list : elt list -> t
- val map : (elt -> elt) -> t -> t
+module type Tbl = sig
+ module T : sig
+ type t
+ include Map.OrderedType with type t := t
+ include Hashtbl.HashedType with type t := t
end
+ include Hashtbl.S
+ with type key = T.t
+ and type 'a t = 'a Hashtbl.Make (T).t
- module Map : sig
- include Map.S
- with type key = T.t
- and type 'a t = 'a Map.Make (T).t
-
- val filter_map : 'a t -> f:(key -> 'a -> 'b option) -> 'b t
- val of_list : (key * 'a) list -> 'a t
-
- (** [disjoint_union m1 m2] contains all bindings from [m1] and
- [m2]. If some binding is present in both and the associated
- value is not equal, a Fatal_error is raised *)
- val disjoint_union : ?eq:('a -> 'a -> bool) -> ?print:(Format.formatter -> 'a -> unit) -> 'a t -> 'a t -> 'a t
-
- (** [union_right m1 m2] contains all bindings from [m1] and [m2]. If
- some binding is present in both, the one from [m2] is taken *)
- val union_right : 'a t -> 'a t -> 'a t
-
- (** [union_left m1 m2 = union_right m2 m1] *)
- val union_left : 'a t -> 'a t -> 'a t
-
- val union_merge : ('a -> 'a -> 'a) -> 'a t -> 'a t -> 'a t
- val rename : key t -> key -> key
- val map_keys : (key -> key) -> 'a t -> 'a t
- val keys : 'a t -> Set.t
- val data : 'a t -> 'a list
- val of_set : (key -> 'a) -> Set.t -> 'a t
- val transpose_keys_and_data : key t -> key t
- val transpose_keys_and_data_set : key t -> Set.t t
- val print :
- (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a t -> unit
- end
+ val to_list : 'a t -> (T.t * 'a) list
+ val of_list : (T.t * 'a) list -> 'a t
+
+ val to_map : 'a t -> 'a Map.Make(T).t
+ val of_map : 'a Map.Make(T).t -> 'a t
+ val memoize : 'a t -> (key -> 'a) -> key -> 'a
+ val map : 'a t -> ('a -> 'b) -> 'b t
+end
- module Tbl : sig
- include Hashtbl.S
- with type key = T.t
- and type 'a t = 'a Hashtbl.Make (T).t
+module type S = sig
+ type t
- val to_list : 'a t -> (T.t * 'a) list
- val of_list : (T.t * 'a) list -> 'a t
+ module T : Thing with type t = t
+ include Thing with type t := T.t
- val to_map : 'a t -> 'a Map.t
- val of_map : 'a Map.t -> 'a t
- val memoize : 'a t -> (key -> 'a) -> key -> 'a
- val map : 'a t -> ('a -> 'b) -> 'b t
- end
+ module Set : Set with module T := T
+ module Map : Map with module T := T
+ module Tbl : Tbl with module T := T
end
module Make (T : Thing) : S with type t := T.t
| None -> default
| Some a -> f a
end
+
+ module Array = struct
+ let exists2 p a1 a2 =
+ let n = Array.length a1 in
+ if Array.length a2 <> n then invalid_arg "Misc.Stdlib.Array.exists2";
+ let rec loop i =
+ if i = n then false
+ else if p (Array.unsafe_get a1 i) (Array.unsafe_get a2 i) then true
+ else loop (succ i) in
+ loop 0
+ end
end
let may = Stdlib.Option.iter
(Buffer.add_subbytes b buff 0 n; copy())
in copy()
+let output_to_file_via_temporary ?(mode = [Open_text]) filename fn =
+ let (temp_filename, oc) =
+ Filename.open_temp_file
+ ~mode ~perms:0o666 ~temp_dir:(Filename.dirname filename)
+ (Filename.basename filename) ".tmp" in
+ (* The 0o666 permissions will be modified by the umask. It's just
+ like what [open_out] and [open_out_bin] do.
+ With temp_dir = dirname filename, we ensure that the returned
+ temp file is in the same directory as filename itself, making
+ it safe to rename temp_filename to filename later.
+ With prefix = basename filename, we are almost certain that
+ the first generated name will be unique. A fixed prefix
+ would work too but might generate more collisions if many
+ files are being produced simultaneously in the same directory. *)
+ match fn temp_filename oc with
+ | res ->
+ close_out oc;
+ begin try
+ Sys.rename temp_filename filename; res
+ with exn ->
+ remove_file temp_filename; raise exn
+ end
+ | exception exn ->
+ close_out oc; remove_file temp_filename; raise exn
+
(* Integer operations *)
let rec log2 n =
let color_enabled = ref true
- (* either prints the tag of [s] or delegate to [or_else] *)
+ (* either prints the tag of [s] or delegates to [or_else] *)
let mark_open_tag ~or_else s =
try
let style = style_of_tag s in
val fold : ('a -> 'b -> 'b) -> 'a t -> 'b -> 'b
val value_default : ('a -> 'b) -> default:'b -> 'a t -> 'b
end
+
+ module Array : sig
+ val exists2 : ('a -> 'b -> bool) -> 'a array -> 'b array -> bool
+ (* Same as [Array.exists], but for a two-argument predicate. Raise
+ Invalid_argument if the two arrays are determined to have
+ different lengths. *)
+ end
end
val find_in_path: string list -> string -> string
val string_of_file: in_channel -> string
(* [string_of_file ic] reads the contents of file [ic] and copies
them to a string. It stops when encountering EOF on [ic]. *)
+val output_to_file_via_temporary:
+ ?mode:open_flag list -> string -> (string -> out_channel -> 'a) -> 'a
+ (* Produce output in temporary file, then rename it
+ (as atomically as possible) to the desired output file name.
+ [output_to_file_via_temporary filename fn] opens a temporary file
+ which is passed to [fn] (name + output channel). When [fn] returns,
+ the channel is closed and the temporary file is renamed to
+ [filename]. *)
+
val log2: int -> int
(* [log2 n] returns [s] such that [n = 1 lsl s]
if [n] is a power of 2*)
-(** {2 Hook machinery} *)
+(** {1 Hook machinery}
-(* Hooks machinery:
+ Hooks machinery:
[add_hook name f] will register a function that will be called on the
argument of a later call to [apply_hooks]. Hooks are applied in the
lexicographical order of their names.
if n < 0 then Set.empty else Set.add n (zero_to_n (n-1))
end
+module Int8 = struct
+ type t = int
+
+ let zero = 0
+ let one = 1
+
+ let of_int_exn i =
+ if i < -(1 lsl 7) || i > ((1 lsl 7) - 1) then
+ Misc.fatal_errorf "Int8.of_int_exn: %d is out of range" i
+ else
+ i
+
+ let to_int i = i
+end
+
+module Int16 = struct
+ type t = int
+
+ let of_int_exn i =
+ if i < -(1 lsl 15) || i > ((1 lsl 15) - 1) then
+ Misc.fatal_errorf "Int16.of_int_exn: %d is out of range" i
+ else
+ i
+
+ let lower_int64 = Int64.neg (Int64.shift_left Int64.one 15)
+ let upper_int64 = Int64.sub (Int64.shift_left Int64.one 15) Int64.one
+
+ let of_int64_exn i =
+ if Int64.compare i lower_int64 < 0
+ || Int64.compare i upper_int64 > 0
+ then
+ Misc.fatal_errorf "Int16.of_int64_exn: %Ld is out of range" i
+ else
+ Int64.to_int i
+
+ let to_int t = t
+end
+
module Float = struct
type t = float
(* *)
(**************************************************************************)
-(** Modules about numbers that satisfy {!Identifiable.S}. *)
+(** Modules about numbers, some of which satisfy {!Identifiable.S}. *)
module Int : sig
include Identifiable.S with type t = int
val zero_to_n : int -> Set.t
end
+module Int8 : sig
+ type t
+
+ val zero : t
+ val one : t
+
+ val of_int_exn : int -> t
+ val to_int : t -> int
+end
+
+module Int16 : sig
+ type t
+
+ val of_int_exn : int -> t
+ val of_int64_exn : Int64.t -> t
+
+ val to_int : t -> int
+end
+
module Float : Identifiable.S with type t = float
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Pierre Chambart, OCamlPro *)
+(* *)
+(* Copyright 2015 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+[@@@ocaml.warning "+a-18-40-42-48"]
+
+type file = string
+
+external time_include_children: bool -> float = "caml_sys_time_include_children"
+let cpu_time () = time_include_children true
+
+module Measure = struct
+ type t = {
+ time : float;
+ allocated_words : float;
+ top_heap_words : int;
+ }
+ let create () =
+ let stat = Gc.quick_stat () in
+ {
+ time = cpu_time ();
+ allocated_words = stat.minor_words +. stat.major_words;
+ top_heap_words = stat.top_heap_words;
+ }
+ let zero = { time = 0.; allocated_words = 0.; top_heap_words = 0 }
+end
+
+module Measure_diff = struct
+ let timestamp = let r = ref (-1) in fun () -> incr r; !r
+ type t = {
+ timestamp : int;
+ duration : float;
+ allocated_words : float;
+ top_heap_words_increase : int;
+ }
+ let zero () = {
+ timestamp = timestamp ();
+ duration = 0.;
+ allocated_words = 0.;
+ top_heap_words_increase = 0;
+ }
+ let accumulate t (m1 : Measure.t) (m2 : Measure.t) = {
+ timestamp = t.timestamp;
+ duration = t.duration +. (m2.time -. m1.time);
+ allocated_words =
+ t.allocated_words +. (m2.allocated_words -. m1.allocated_words);
+ top_heap_words_increase =
+ t.top_heap_words_increase + (m2.top_heap_words - m1.top_heap_words);
+ }
+ let of_diff m1 m2 =
+ accumulate (zero ()) m1 m2
+end
+
+type hierarchy =
+ | E of (string, Measure_diff.t * hierarchy) Hashtbl.t
+[@@unboxed]
+
+let create () = E (Hashtbl.create 2)
+let hierarchy = ref (create ())
+let initial_measure = ref None
+let reset () = hierarchy := create (); initial_measure := None
+
+let record_call ?(accumulate = false) name f =
+ let E prev_hierarchy = !hierarchy in
+ let start_measure = Measure.create () in
+ if !initial_measure = None then initial_measure := Some start_measure;
+ let this_measure_diff, this_table =
+ (* We allow the recording of multiple categories by the same name, for tools
+ like ocamldoc that use the compiler libs but don't care about profile
+ information, and so may record, say, "parsing" multiple times. *)
+ if accumulate
+ then
+ match Hashtbl.find prev_hierarchy name with
+ | exception Not_found -> Measure_diff.zero (), Hashtbl.create 2
+ | measure_diff, E table ->
+ Hashtbl.remove prev_hierarchy name;
+ measure_diff, table
+ else Measure_diff.zero (), Hashtbl.create 2
+ in
+ hierarchy := E this_table;
+ Misc.try_finally f
+ (fun () ->
+ hierarchy := E prev_hierarchy;
+ let end_measure = Measure.create () in
+ let measure_diff =
+ Measure_diff.accumulate this_measure_diff start_measure end_measure in
+ Hashtbl.add prev_hierarchy name (measure_diff, E this_table))
+
+let record ?accumulate pass f x = record_call ?accumulate pass (fun () -> f x)
+
+type display = {
+ to_string : max:float -> width:int -> string;
+ worth_displaying : max:float -> bool;
+}
+
+let time_display v : display =
+ (* Because indentation is meaningful, and because the durations are
+ the first element of each row, we can't pad them with spaces. *)
+ let to_string_without_unit v ~width = Printf.sprintf "%0*.03f" width v in
+ let to_string ~max:_ ~width =
+ to_string_without_unit v ~width:(width - 1) ^ "s" in
+ let worth_displaying ~max:_ =
+ float_of_string (to_string_without_unit v ~width:0) <> 0. in
+ { to_string; worth_displaying }
+
+let memory_word_display =
+ (* To make memory numbers easily comparable across rows, we choose a single
+ scale for an entire column. To keep the display compact and not overly
+ precise (no one cares about the exact number of bytes), we pick the largest
+ scale we can and we only show 3 digits. Avoiding showing tiny numbers also
+ allows us to avoid displaying passes that barely allocate compared to the
+ rest of the compiler. *)
+ let bytes_of_words words = words *. float_of_int (Sys.word_size / 8) in
+ let to_string_without_unit v ~width scale =
+ let precision = 3 and precision_power = 1e3 in
+ let v_rescaled = bytes_of_words v /. scale in
+ let v_rounded =
+ floor (v_rescaled *. precision_power +. 0.5) /. precision_power in
+ let v_str = Printf.sprintf "%.*f" precision v_rounded in
+ let index_of_dot = String.index v_str '.' in
+ let v_str_truncated =
+ String.sub v_str 0
+ (if index_of_dot >= precision
+ then index_of_dot
+ else precision + 1)
+ in
+ Printf.sprintf "%*s" width v_str_truncated
+ in
+ let choose_memory_scale =
+ let units = [|"B"; "kB"; "MB"; "GB"|] in
+ fun words ->
+ let bytes = bytes_of_words words in
+ let scale = ref (Array.length units - 1) in
+ while !scale > 0 && bytes < 1024. ** float_of_int !scale do
+ decr scale
+ done;
+ 1024. ** float_of_int !scale, units.(!scale)
+ in
+ fun ?previous v : display ->
+ let to_string ~max ~width =
+ let scale, scale_str = choose_memory_scale max in
+ let width = width - String.length scale_str in
+ to_string_without_unit v ~width scale ^ scale_str
+ in
+ let worth_displaying ~max =
+ let scale, _ = choose_memory_scale max in
+ float_of_string (to_string_without_unit v ~width:0 scale) <> 0.
+ && match previous with
+ | None -> true
+ | Some p ->
+ (* This branch is for numbers that represent absolute quantity, rather
+ than differences. It allows us to skip displaying the same absolute
+ quantity many times in a row. *)
+ to_string_without_unit p ~width:0 scale
+ <> to_string_without_unit v ~width:0 scale
+ in
+ { to_string; worth_displaying }
+
+let profile_list (E table) =
+ let l = Hashtbl.fold (fun k d l -> (k, d) :: l) table [] in
+ List.sort (fun (_, (p1, _)) (_, (p2, _)) ->
+ compare p1.Measure_diff.timestamp p2.Measure_diff.timestamp) l
+
+let compute_other_category (E table : hierarchy) (total : Measure_diff.t) =
+ let r = ref total in
+ Hashtbl.iter (fun _pass ((p2 : Measure_diff.t), _) ->
+ let p1 = !r in
+ r := {
+ timestamp = p1.timestamp;
+ duration = p1.duration -. p2.duration;
+ allocated_words = p1.allocated_words -. p2.allocated_words;
+ top_heap_words_increase =
+ p1.top_heap_words_increase - p2.top_heap_words_increase;
+ }
+ ) table;
+ !r
+
+type row = R of string * (float * display) list * row list
+type column = [ `Time | `Alloc | `Top_heap | `Abs_top_heap ]
+
+let rec rows_of_hierarchy ~nesting make_row name measure_diff hierarchy env =
+ let rows =
+ rows_of_hierarchy_list
+ ~nesting:(nesting + 1) make_row hierarchy measure_diff env in
+ let values, env =
+ make_row env measure_diff ~toplevel_other:(nesting = 0 && name = "other") in
+ R (name, values, rows), env
+
+and rows_of_hierarchy_list ~nesting make_row hierarchy total env =
+ let list = profile_list hierarchy in
+ let list =
+ if list <> [] || nesting = 0
+ then list @ [ "other", (compute_other_category hierarchy total, create ()) ]
+ else []
+ in
+ let env = ref env in
+ List.map (fun (name, (measure_diff, hierarchy)) ->
+ let a, env' =
+ rows_of_hierarchy ~nesting make_row name measure_diff hierarchy !env in
+ env := env';
+ a
+ ) list
+
+let rows_of_hierarchy hierarchy measure_diff initial_measure columns =
+ (* Computing top heap size is a bit complicated: if the compiler applies a
+ list of passes n times (rather than applying pass1 n times, then pass2 n
+ times etc), we only show one row for that pass but what does "top heap
+ size at the end of that pass" even mean?
+ It seems the only sensible answer is to pretend the compiler applied pass1
+ n times, pass2 n times by accumulating all the heap size increases that
+ happened during each pass, and then compute what the heap size would have
+ been. So that's what we do.
+ There's a bit of extra complication, which is that the heap can increase in
+ between measurements. So the heap sizes can be a bit off until the "other"
+ rows account for what's missing. We special case the toplevel "other" row
+ so that any increases that happened before the start of the compilation is
+ correctly reported, as a lot of code may run before the start of the
+ compilation (eg functor applications). *)
+ let make_row prev_top_heap_words (p : Measure_diff.t) ~toplevel_other =
+ let top_heap_words =
+ prev_top_heap_words
+ + p.top_heap_words_increase
+ - if toplevel_other
+ then initial_measure.Measure.top_heap_words
+ else 0
+ in
+ let make value ~f = value, f value in
+ List.map (function
+ | `Time ->
+ make p.duration ~f:time_display
+ | `Alloc ->
+ make p.allocated_words ~f:memory_word_display
+ | `Top_heap ->
+ make (float_of_int p.top_heap_words_increase) ~f:memory_word_display
+ | `Abs_top_heap ->
+ make (float_of_int top_heap_words)
+ ~f:(memory_word_display ~previous:(float_of_int prev_top_heap_words))
+ ) columns,
+ top_heap_words
+ in
+ rows_of_hierarchy_list ~nesting:0 make_row hierarchy measure_diff
+ initial_measure.top_heap_words
+
+let max_by_column ~n_columns rows =
+ let a = Array.make n_columns 0. in
+ let rec loop (R (_, values, rows)) =
+ List.iteri (fun i (v, _) -> a.(i) <- max a.(i) v) values;
+ List.iter loop rows
+ in
+ List.iter loop rows;
+ a
+
+let width_by_column ~n_columns ~display_cell rows =
+ let a = Array.make n_columns 1 in
+ let rec loop (R (_, values, rows)) =
+ List.iteri (fun i cell ->
+ let _, str = display_cell i cell ~width:0 in
+ a.(i) <- max a.(i) (String.length str)
+ ) values;
+ List.iter loop rows;
+ in
+ List.iter loop rows;
+ a
+
+let display_rows ppf rows =
+ let n_columns =
+ match rows with
+ | [] -> 0
+ | R (_, values, _) :: _ -> List.length values
+ in
+ let maxs = max_by_column ~n_columns rows in
+ let display_cell i (_, c) ~width =
+ let display_cell = c.worth_displaying ~max:maxs.(i) in
+ display_cell, if display_cell
+ then c.to_string ~max:maxs.(i) ~width
+ else String.make width '-'
+ in
+ let widths = width_by_column ~n_columns ~display_cell rows in
+ let rec loop (R (name, values, rows)) ~indentation =
+ let worth_displaying, cell_strings =
+ values
+ |> List.mapi (fun i cell -> display_cell i cell ~width:widths.(i))
+ |> List.split
+ in
+ if List.exists (fun b -> b) worth_displaying then
+ Format.fprintf ppf "%s%s %s@\n"
+ indentation (String.concat " " cell_strings) name;
+ List.iter (loop ~indentation:(" " ^ indentation)) rows;
+ in
+ List.iter (loop ~indentation:"") rows
+
+let print ppf columns =
+ match columns with
+ | [] -> ()
+ | _ :: _ ->
+ let initial_measure =
+ match !initial_measure with
+ | Some v -> v
+ | None -> Measure.zero
+ in
+ let total = Measure_diff.of_diff Measure.zero (Measure.create ()) in
+ display_rows ppf (rows_of_hierarchy !hierarchy total initial_measure columns)
+
+let column_mapping = [
+ "time", `Time;
+ "alloc", `Alloc;
+ "top-heap", `Top_heap;
+ "absolute-top-heap", `Abs_top_heap;
+]
+
+let column_names = List.map fst column_mapping
+
+let options_doc =
+ Printf.sprintf
+ " Print performance information for each pass\
+ \n The columns are: %s."
+ (String.concat " " column_names)
+
+let all_columns = List.map snd column_mapping
+
+let generate = "generate"
+let transl = "transl"
+let typing = "typing"
--- /dev/null
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Pierre Chambart, OCamlPro *)
+(* *)
+(* Copyright 2015 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(** Compiler performance recording *)
+
+type file = string
+
+val reset : unit -> unit
+(** erase all recorded profile information *)
+
+val record_call : ?accumulate:bool -> string -> (unit -> 'a) -> 'a
+(** [record_call pass f] calls [f] and records its profile information. *)
+
+val record : ?accumulate:bool -> string -> ('a -> 'b) -> 'a -> 'b
+(** [record pass f arg] records the profile information of [f arg] *)
+
+type column = [ `Time | `Alloc | `Top_heap | `Abs_top_heap ]
+
+val print : Format.formatter -> column list -> unit
+(** Prints the selected recorded profiling information to the formatter. *)
+
+(** Command line flags *)
+
+val options_doc : string
+val all_columns : column list
+
+(** A few pass names that are needed in several places, and shared to
+ avoid typos. *)
+
+val generate : string
+val transl : string
+val typing : string
(** Bitwise logical exclusive or. *)
val lognot : t -> t
-(** Bitwise logical negation *)
+(** Bitwise logical negation. *)
val shift_left : t -> int -> t
(** [Targetint.shift_left x y] shifts [x] to the left by [y] bits.
(* *)
(**************************************************************************)
-type ('a, 'b) t =
+type ('k, 'v) t =
Empty
- | Node of ('a, 'b) t * 'a * 'b * ('a, 'b) t * int
+ | Node of ('k, 'v) t * 'k * 'v * ('k, 'v) t * int
let empty = Empty
if c = 0 then d
else find x (if c < 0 then l else r)
+let rec find_str (x : string) = function
+ Empty ->
+ raise Not_found
+ | Node(l, v, d, r, _) ->
+ let c = compare x v in
+ if c = 0 then d
+ else find_str x (if c < 0 then l else r)
+
let rec mem x = function
Empty -> false
| Node(l, v, _d, r, _) ->
(* Association tables from any ordered type to any type.
We use the generic ordering to compare keys. *)
-type ('a, 'b) t
+type ('k, 'v) t
-val empty: ('a, 'b) t
-val add: 'a -> 'b -> ('a, 'b) t -> ('a, 'b) t
-val find: 'a -> ('a, 'b) t -> 'b
-val mem: 'a -> ('a, 'b) t -> bool
-val remove: 'a -> ('a, 'b) t -> ('a, 'b) t
-val iter: ('a -> 'b -> unit) -> ('a, 'b) t -> unit
-val map: ('a -> 'b -> 'c) -> ('a, 'b) t -> ('a, 'c) t
-val fold: ('a -> 'b -> 'c -> 'c) -> ('a, 'b) t -> 'c -> 'c
+val empty: ('k, 'v) t
+val add: 'k -> 'v -> ('k, 'v) t -> ('k, 'v) t
+val find: 'k -> ('k, 'v) t -> 'v
+val find_str: string -> (string, 'v) t -> 'v
+val mem: 'k -> ('k, 'v) t -> bool
+val remove: 'k -> ('k, 'v) t -> ('k, 'v) t
+val iter: ('k -> 'v -> unit) -> ('k, 'v) t -> unit
+val map: ('k -> 'v1 -> 'v2) -> ('k, 'v1) t -> ('k, 'v2) t
+val fold: ('k -> 'v -> 'acc -> 'acc) -> ('k, 'v) t -> 'acc -> 'acc
open Format
-val print: (formatter -> 'a -> unit) -> (formatter -> 'b -> unit) ->
- formatter -> ('a, 'b) t -> unit
+val print: (formatter -> 'k -> unit) -> (formatter -> 'v -> unit) ->
+ formatter -> ('k, 'v) t -> unit
+++ /dev/null
-(**************************************************************************)
-(* *)
-(* OCaml *)
-(* *)
-(* Pierre Chambart, OCamlPro *)
-(* *)
-(* Copyright 2015 Institut National de Recherche en Informatique et *)
-(* en Automatique. *)
-(* *)
-(* All rights reserved. This file is distributed under the terms of *)
-(* the GNU Lesser General Public License version 2.1, with the *)
-(* special exception on linking described in the file LICENSE. *)
-(* *)
-(**************************************************************************)
-
-type file = string
-
-type source_provenance =
- | File of file
- | Pack of string
- | Startup
- | Toplevel
-
-type compiler_pass =
- | All
- | Parsing of file
- | Parser of file
- | Dash_pp of file
- | Dash_ppx of file
- | Typing of file
- | Transl of file
- | Generate of file
- | Assemble of source_provenance
- | Clambda of source_provenance
- | Cmm of source_provenance
- | Compile_phrases of source_provenance
- | Selection of source_provenance
- | Comballoc of source_provenance
- | CSE of source_provenance
- | Liveness of source_provenance
- | Deadcode of source_provenance
- | Spill of source_provenance
- | Split of source_provenance
- | Regalloc of source_provenance
- | Linearize of source_provenance
- | Scheduling of source_provenance
- | Emit of source_provenance
- | Flambda_pass of string * source_provenance
-
-let timings : (compiler_pass, float * float option) Hashtbl.t =
- Hashtbl.create 20
-
-external time_include_children: bool -> float = "caml_sys_time_include_children"
-let cpu_time () = time_include_children true
-
-let reset () = Hashtbl.clear timings
-
-let start pass =
- (* Cannot assert it is not here: a source file can be compiled
- multiple times on the same command line *)
- (* assert(not (Hashtbl.mem timings pass)); *)
- let time = cpu_time () in
- Hashtbl.add timings pass (time, None)
-
-let stop pass =
- assert(Hashtbl.mem timings pass);
- let time = cpu_time () in
- let (start, stop) = Hashtbl.find timings pass in
- assert(stop = None);
- Hashtbl.replace timings pass (start, Some (time -. start))
-
-let time_call pass f =
- start pass;
- let r = f () in
- stop pass;
- r
-
-let time pass f x = time_call pass (fun () -> f x)
-
-let restart pass =
- let previous_duration =
- match Hashtbl.find timings pass with
- | exception Not_found -> 0.
- | (_, Some duration) -> duration
- | _, None -> assert false
- in
- let time = cpu_time () in
- Hashtbl.replace timings pass (time, Some previous_duration)
-
-let accumulate pass =
- let time = cpu_time () in
- match Hashtbl.find timings pass with
- | exception Not_found -> assert false
- | _, None -> assert false
- | (start, Some duration) ->
- let duration = duration +. (time -. start) in
- Hashtbl.replace timings pass (start, Some duration)
-
-let accumulate_time pass f x =
- restart pass;
- let r = f x in
- accumulate pass;
- r
-
-let get pass =
- match Hashtbl.find timings pass with
- | _start, Some duration -> Some duration
- | _, None -> None
- | exception Not_found -> None
-
-let kind_name = function
- | File f -> Printf.sprintf "sourcefile(%s)" f
- | Pack p -> Printf.sprintf "pack(%s)" p
- | Startup -> "startup"
- | Toplevel -> "toplevel"
-
-let pass_name = function
- | All -> "all"
- | Parsing file -> Printf.sprintf "parsing(%s)" file
- | Parser file -> Printf.sprintf "parser(%s)" file
- | Dash_pp file -> Printf.sprintf "-pp(%s)" file
- | Dash_ppx file -> Printf.sprintf "-ppx(%s)" file
- | Typing file -> Printf.sprintf "typing(%s)" file
- | Transl file -> Printf.sprintf "transl(%s)" file
- | Generate file -> Printf.sprintf "generate(%s)" file
- | Assemble k -> Printf.sprintf "assemble(%s)" (kind_name k)
- | Clambda k -> Printf.sprintf "clambda(%s)" (kind_name k)
- | Cmm k -> Printf.sprintf "cmm(%s)" (kind_name k)
- | Compile_phrases k -> Printf.sprintf "compile_phrases(%s)" (kind_name k)
- | Selection k -> Printf.sprintf "selection(%s)" (kind_name k)
- | Comballoc k -> Printf.sprintf "comballoc(%s)" (kind_name k)
- | CSE k -> Printf.sprintf "cse(%s)" (kind_name k)
- | Liveness k -> Printf.sprintf "liveness(%s)" (kind_name k)
- | Deadcode k -> Printf.sprintf "deadcode(%s)" (kind_name k)
- | Spill k -> Printf.sprintf "spill(%s)" (kind_name k)
- | Split k -> Printf.sprintf "split(%s)" (kind_name k)
- | Regalloc k -> Printf.sprintf "regalloc(%s)" (kind_name k)
- | Linearize k -> Printf.sprintf "linearize(%s)" (kind_name k)
- | Scheduling k -> Printf.sprintf "scheduling(%s)" (kind_name k)
- | Emit k -> Printf.sprintf "emit(%s)" (kind_name k)
- | Flambda_pass (pass, file) ->
- Printf.sprintf "flambda(%s)(%s)" pass (kind_name file)
-
-let timings_list () =
- let l = Hashtbl.fold (fun pass times l -> (pass, times) :: l) timings [] in
- List.sort (fun (pass1, (start1, _)) (pass2, (start2, _)) ->
- compare (start1, pass1) (start2, pass2)) l
-
-let print ppf =
- let current_time = cpu_time () in
- List.iter (fun (pass, (start, stop)) ->
- match stop with
- | Some duration ->
- Format.fprintf ppf "%s: %.03fs@." (pass_name pass) duration
- | None ->
- Format.fprintf ppf "%s: running for %.03fs@." (pass_name pass)
- (current_time -. start))
- (timings_list ())
+++ /dev/null
-(**************************************************************************)
-(* *)
-(* OCaml *)
-(* *)
-(* Pierre Chambart, OCamlPro *)
-(* *)
-(* Copyright 2015 Institut National de Recherche en Informatique et *)
-(* en Automatique. *)
-(* *)
-(* All rights reserved. This file is distributed under the terms of *)
-(* the GNU Lesser General Public License version 2.1, with the *)
-(* special exception on linking described in the file LICENSE. *)
-(* *)
-(**************************************************************************)
-
-(** Compiler performance recording *)
-
-type file = string
-
-type source_provenance =
- | File of file
- | Pack of string
- | Startup
- | Toplevel
-
-type compiler_pass =
- | All
- | Parsing of file
- | Parser of file
- | Dash_pp of file
- | Dash_ppx of file
- | Typing of file
- | Transl of file
- | Generate of file
- | Assemble of source_provenance
- | Clambda of source_provenance
- | Cmm of source_provenance
- | Compile_phrases of source_provenance
- | Selection of source_provenance
- | Comballoc of source_provenance
- | CSE of source_provenance
- | Liveness of source_provenance
- | Deadcode of source_provenance
- | Spill of source_provenance
- | Split of source_provenance
- | Regalloc of source_provenance
- | Linearize of source_provenance
- | Scheduling of source_provenance
- | Emit of source_provenance
- | Flambda_pass of string * source_provenance
-
-val reset : unit -> unit
-(** erase all recorded times *)
-
-val get : compiler_pass -> float option
-(** returns the runtime in seconds of a completed pass *)
-
-val time_call : compiler_pass -> (unit -> 'a) -> 'a
-(** [time_call pass f] calls [f] and records its runtime. *)
-
-val time : compiler_pass -> ('a -> 'b) -> 'a -> 'b
-(** [time pass f arg] records the runtime of [f arg] *)
-
-val accumulate_time : compiler_pass -> ('a -> 'b) -> 'a -> 'b
-(** Like time for passes that can run multiple times *)
-
-val print : Format.formatter -> unit
-(** Prints all recorded timings to the formatter. *)
- manual/manual/cmds/native.etex
*)
+type loc = {
+ loc_start: Lexing.position;
+ loc_end: Lexing.position;
+ loc_ghost: bool;
+}
+
type t =
| Comment_start (* 1 *)
| Comment_not_end (* 2 *)
- | Deprecated of string (* 3 *)
+ | Deprecated of string * loc * loc (* 3 *)
| Fragile_match of string (* 4 *)
| Partial_application (* 5 *)
| Labels_omitted of string list (* 6 *)
| Assignment_to_non_mutable_value (* 59 *)
| Unused_module of string (* 60 *)
| Unboxable_type_in_prim_decl of string (* 61 *)
+ | Constraint_on_gadt (* 62 *)
;;
(* If you remove a warning, leave a hole in the numbering. NEVER change
| Assignment_to_non_mutable_value -> 59
| Unused_module _ -> 60
| Unboxable_type_in_prim_decl _ -> 61
+ | Constraint_on_gadt -> 62
;;
-let last_warning_number = 61
+let last_warning_number = 62
;;
(* Must be the max number returned by the [number] function. *)
error = Array.make (last_warning_number + 1) false;
}
+let disabled = ref false
+
+let without_warnings f =
+ Misc.protect_refs [Misc.R(disabled, true)] f
+
let backup () = !current
let restore x = current := x
-let is_active x = (!current).active.(number x);;
-let is_error x = (!current).error.(number x);;
+let is_active x = not !disabled && (!current).active.(number x);;
+let is_error x = not !disabled && (!current).error.(number x);;
+
+let mk_lazy f =
+ let state = backup () in
+ lazy
+ (
+ let prev = backup () in
+ restore state;
+ try
+ let r = f () in
+ restore prev;
+ r
+ with exn ->
+ restore prev;
+ raise exn
+ )
let parse_opt error active flags s =
let set i = flags.(i) <- true in
current := {error; active}
(* If you change these, don't forget to change them in man/ocamlc.m *)
-let defaults_w = "+a-4-6-7-9-27-29-32..39-41..42-44-45-48-50-60";;
+let defaults_w = "+a-4-6-7-9-27-29-32..42-44-45-48-50-60";;
let defaults_warn_error = "-a+31";;
let () = parse_options false defaults_w;;
let message = function
| Comment_start -> "this is the start of a comment."
| Comment_not_end -> "this is not the end of a comment."
- | Deprecated s ->
+ | Deprecated (s, _, _) ->
(* Reduce \r\n to \n:
- Prevents any \r characters being printed on Unix when processing
Windows sources
unboxable. The representation of such types may change in future\n\
versions. You should annotate the declaration of %s with [@@boxed]\n\
or [@@unboxed]." t t
+ | Constraint_on_gadt ->
+ "Type constraints do not apply to GADT cases of variant types."
;;
+let sub_locs = function
+ | Deprecated (_, def, use) ->
+ [
+ def, "Definition";
+ use, "Expected signature";
+ ]
+ | _ -> []
+
let nerrors = ref 0;;
-let print ppf w =
- let msg = message w in
- let num = number w in
- Format.fprintf ppf "%d: %s" num msg;
- Format.pp_print_flush ppf ();
- if (!current).error.(num) then incr nerrors
+type reporting_information =
+ { number : int
+ ; message : string
+ ; is_error : bool
+ ; sub_locs : (loc * string) list;
+ }
+
+let report w =
+ match is_active w with
+ | false -> `Inactive
+ | true ->
+ if is_error w then incr nerrors;
+ `Active { number = number w; message = message w; is_error = is_error w;
+ sub_locs = sub_locs w;
+ }
;;
-exception Errors of int;;
+exception Errors;;
let reset_fatal () =
nerrors := 0
let check_fatal () =
if !nerrors > 0 then begin
- let e = Errors !nerrors in
nerrors := 0;
- raise e;
+ raise Errors;
end;
;;
23, "Useless record \"with\" clause.";
24, "Bad module name: the source file name is not a valid OCaml module \
name.";
- (* 25, "Pattern-matching with all clauses guarded. Exhaustiveness cannot \
- be\n\
- \ checked."; (* Now part of warning 8 *) *)
+ 25, "Deprecated: now part of warning 8.";
26, "Suspicious unused variable: unused variable that is bound\n\
\ with \"let\" or \"as\", and doesn't start with an underscore (\"_\")\n\
\ character.";
58, "Missing cmx file";
59, "Assignment to non-mutable value";
60, "Unused module declaration";
+ 61, "Unboxable type in primitive declaration";
+ 62, "Type constraint on GADT type declaration"
]
;;
(* *)
(**************************************************************************)
-open Format
+type loc = {
+ loc_start: Lexing.position;
+ loc_end: Lexing.position;
+ loc_ghost: bool;
+}
type t =
| Comment_start (* 1 *)
| Comment_not_end (* 2 *)
- | Deprecated of string (* 3 *)
+ | Deprecated of string * loc * loc (* 3 *)
| Fragile_match of string (* 4 *)
| Partial_application (* 5 *)
| Labels_omitted of string list (* 6 *)
| Preprocessor of string (* 22 *)
| Useless_record_with (* 23 *)
| Bad_module_name of string (* 24 *)
- | All_clauses_guarded (* 25 *)
+ | All_clauses_guarded (* 8, used to be 25 *)
| Unused_var of string (* 26 *)
| Unused_var_strict of string (* 27 *)
| Wildcard_arg_to_constant_constr (* 28 *)
| Assignment_to_non_mutable_value (* 59 *)
| Unused_module of string (* 60 *)
| Unboxable_type_in_prim_decl of string (* 61 *)
+ | Constraint_on_gadt (* 62 *)
;;
val parse_options : bool -> string -> unit;;
+val without_warnings : (unit -> 'a) -> 'a
+
val is_active : t -> bool;;
val is_error : t -> bool;;
val defaults_w : string;;
val defaults_warn_error : string;;
-val print : formatter -> t -> unit;;
+type reporting_information =
+ { number : int
+ ; message : string
+ ; is_error : bool
+ ; sub_locs : (loc * string) list;
+ }
+
+val report : t -> [ `Active of reporting_information | `Inactive ]
-exception Errors of int;;
+exception Errors;;
val check_fatal : unit -> unit;;
val reset_fatal: unit -> unit
type state
val backup: unit -> state
val restore: state -> unit
+val mk_lazy: (unit -> 'a) -> 'a Lazy.t
+ (** Like [Lazy.of_fun], but the function is applied with
+ the warning settings at the time [mk_lazy] is called. *)
include ../config/Makefile
-CC=$(BYTECC)
-CFLAGS=-DNDEBUG $(BYTECCCOMPOPTS)
-
-ifeq "$(TOOLCHAIN)" "mingw"
- CFLAGS += -DNO_UNIX
-else ifeq "$(TOOLCHAIN)" "msvc"
- CFLAGS += -DNO_UNIX
-endif
-
OBJS= closure.$(O) error.$(O) lalr.$(O) lr0.$(O) main.$(O) \
mkpar.$(O) output.$(O) reader.$(O) \
skeleton.$(O) symtab.$(O) verbose.$(O) warshall.$(O)
all: ocamlyacc$(EXE)
+ifeq ($(TOOLCHAIN),cc)
+MKEXE_ANSI=$(MKEXE)
+endif
+
ocamlyacc$(EXE): $(OBJS)
- $(MKEXE) -o ocamlyacc$(EXE) $(OBJS) $(EXTRALIBS)
+ $(MKEXE_ANSI) -o ocamlyacc$(EXE) $(OBJS) $(EXTRALIBS)
version.h : ../VERSION
echo "#define OCAML_VERSION \"`sed -e 1q $^ | tr -d '\r'`\"" > $@
# also works for .obj files.
%.$(O): %.c
- $(CC) $(CFLAGS) -c $<
+ $(CC) -c $(CFLAGS) $(CPPFLAGS) -I../byterun $(OUTPUTOBJ)$@ $<
/* Based on public-domain code from Berkeley Yacc */
+#ifndef DEBUG
+#define NDEBUG
+#endif
+
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
-#include "../config/s.h"
+#include "caml/s.h"
/* machine-dependent definitions */
/* the following definitions are for the Tahoe */
#define TEXT 5
#define TYPE 6
#define START 7
-#define UNION 8
-#define IDENT 9
/* symbol classes */
extern char *input_file_name;
extern char *output_file_name;
extern char *text_file_name;
-extern char *union_file_name;
extern char *verbose_file_name;
extern char *interface_file_name;
extern FILE *input_file;
extern FILE *output_file;
extern FILE *text_file;
-extern FILE *union_file;
extern FILE *verbose_file;
extern FILE *interface_file;
extern int nvars;
extern int ntags;
-extern char unionized;
extern char line_format[];
extern int start_symbol;
extern void no_space (void) Noreturn;
extern void open_error (char *filename) Noreturn;
extern void output (void);
-extern void over_unionized (char *u_cptr) Noreturn;
extern void prec_redeclared (void);
extern void polymorphic_entry_point(char *s) Noreturn;
extern void forbidden_conflicts (void);
extern void unterminated_comment (int c_lineno, char *c_line, char *c_cptr) Noreturn;
extern void unterminated_string (int s_lineno, char *s_line, char *s_cptr) Noreturn;
extern void unterminated_text (int t_lineno, char *t_line, char *t_cptr) Noreturn;
-extern void unterminated_union (int u_lineno, char *u_line, char *u_cptr) Noreturn;
extern void used_reserved (char *s) Noreturn;
extern void verbose (void);
extern void write_section (char **section);
}
-void unterminated_union(int u_lineno, char *u_line, char *u_cptr)
-{
- fprintf(stderr, "File \"%s\", line %d: unterminated %%union declaration\n",
- virtual_input_file_name, u_lineno);
- print_pos(u_line, u_cptr);
- done(1);
-}
-
-
-void over_unionized(char *u_cptr)
-{
- fprintf(stderr, "File \"%s\", line %d: too many %%union declarations\n",
- virtual_input_file_name, lineno);
- print_pos(line, u_cptr);
- done(1);
-}
-
-
void illegal_tag(int t_lineno, char *t_line, char *t_cptr)
{
fprintf(stderr, "File \"%s\", line %d: illegal tag\n",
char *myname = "yacc";
char temp_form[] = "yacc.XXXXXXX";
-#ifdef NO_UNIX
+#ifdef _WIN32
char dirsep = '\\';
#else
char dirsep = '/';
char *input_file_name = "";
char *output_file_name;
char *text_file_name;
-char *union_file_name;
char *verbose_file_name;
#ifdef HAS_MKSTEMP
-int action_fd = -1, entry_fd = -1, text_fd = -1, union_fd = -1;
+int action_fd = -1, entry_fd = -1, text_fd = -1;
#endif
FILE *action_file; /* a temp file, used to save actions associated */
FILE *output_file; /* y.tab.c */
FILE *text_file; /* a temp file, used to save text until all */
/* symbols have been defined */
-FILE *union_file; /* a temp file, used to save the union */
- /* definition until all symbol have been */
- /* defined */
FILE *verbose_file; /* y.output */
FILE *interface_file;
#if !defined(HAS_MKSTEMP)
extern char *mktemp(char *);
#endif
-#ifndef NO_UNIX
-extern char *getenv(const char *);
-#endif
void done(int k)
unlink(entry_file_name);
if (text_fd != -1)
unlink(text_file_name);
- if (union_fd != -1)
- unlink(union_file_name);
#else
if (action_file) { fclose(action_file); unlink(action_file_name); }
if (entry_file) { fclose(entry_file); unlink(entry_file_name); }
if (text_file) { fclose(text_file); unlink(text_file_name); }
- if (union_file) { fclose(union_file); unlink(union_file_name); }
#endif
if (output_file && k > 0) {
fclose(output_file); unlink(output_file_name);
int i, len;
char *tmpdir;
-#ifdef NO_UNIX
+#ifdef _WIN32
tmpdir = getenv("TEMP");
if (tmpdir == 0) tmpdir = ".";
#else
if (entry_file_name == 0) no_space();
text_file_name = MALLOC(i);
if (text_file_name == 0) no_space();
- union_file_name = MALLOC(i);
- if (union_file_name == 0) no_space();
strcpy(action_file_name, tmpdir);
strcpy(entry_file_name, tmpdir);
strcpy(text_file_name, tmpdir);
- strcpy(union_file_name, tmpdir);
if (len && tmpdir[len - 1] != dirsep)
{
action_file_name[len] = dirsep;
entry_file_name[len] = dirsep;
text_file_name[len] = dirsep;
- union_file_name[len] = dirsep;
++len;
}
strcpy(action_file_name + len, temp_form);
strcpy(entry_file_name + len, temp_form);
strcpy(text_file_name + len, temp_form);
- strcpy(union_file_name + len, temp_form);
action_file_name[len + 5] = 'a';
entry_file_name[len + 5] = 'e';
text_file_name[len + 5] = 't';
- union_file_name[len + 5] = 'u';
#ifdef HAS_MKSTEMP
action_fd = mkstemp(action_file_name);
text_fd = mkstemp(text_file_name);
if (text_fd == -1)
open_error(text_file_name);
- union_fd = mkstemp(union_file_name);
- if (union_fd == -1)
- open_error(union_file_name);
#else
mktemp(action_file_name);
mktemp(entry_file_name);
mktemp(text_file_name);
- mktemp(union_file_name);
#endif
len = strlen(file_prefix);
defines_file = fopen(defines_file_name, "w");
if (defines_file == 0)
open_error(defines_file_name);
-#ifdef HAS_MKSTEMP
- union_file = fdopen(union_fd, "w");
-#else
- union_file = fopen(union_file_name, "w");
-#endif
- if (union_file == 0)
- open_error(union_file_name);
}
output_file = fopen(output_file_name, "w");
int ntags, tagmax;
char **tag_table;
-char saw_eof, unionized;
+char saw_eof;
char *cptr, *line;
int linesize;
char line_format[] = "# %d \"%s\"\n";
+static unsigned char caml_ident_start[32] =
+"\000\000\000\000\000\000\000\000\376\377\377\207\376\377\377\007\000\000\000\000\000\000\000\000\377\377\177\377\377\377\177\377";
+static unsigned char caml_ident_body[32] =
+"\000\000\000\000\200\000\377\003\376\377\377\207\376\377\377\007\000\000\000\000\000\000\000\000\377\377\177\377\377\377\177\377";
+#define In_bitmap(bm,c) (bm[(unsigned char)(c) >> 3] & (1 << ((c) & 7)))
void start_rule (register bucket *bp, int s_lineno);
+static char *buffer;
+static size_t length;
+static size_t capacity;
+static void push_stack(char x) {
+ if (length - 1 >= capacity) {
+ buffer = realloc(buffer, capacity = 3*length/2 + 100);
+ if (!buffer) no_space();
+ }
+ buffer[++length] = x;
+ buffer[0] = '\1';
+}
+
+static void pop_stack(char x) {
+ if (!buffer || buffer[length--] != x) {
+ switch (x) {
+ case '{': x = '}'; break;
+ case '(': x = ')'; break;
+ default: break;
+ }
+ fprintf(stderr, "Mismatched parentheses or braces: '%c'\n", x);
+ syntax_error(lineno, line, cptr - 1);
+ }
+}
+
void cachec(int c)
{
assert(cinc >= 0);
}
}
+static void process_quoted_string(char c, FILE *const f)
+{
+ int s_lineno = lineno;
+ char *s_line = dup_line();
+ char *s_cptr = s_line + (cptr - line - 1);
+
+ char quote = c;
+ for (;;)
+ {
+ c = *cptr++;
+ putc(c, f);
+ if (c == quote)
+ {
+ FREE(s_line);
+ return;
+ }
+ if (c == '\n')
+ unterminated_string(s_lineno, s_line, s_cptr);
+ if (c == '\\')
+ {
+ c = *cptr++;
+ putc(c, f);
+ if (c == '\n')
+ {
+ get_line();
+ if (line == 0)
+ unterminated_string(s_lineno, s_line, s_cptr);
+ }
+ }
+ }
+}
+
+int process_apostrophe(FILE *const f)
+{
+ if (cptr[0] != 0 && cptr[0] != '\\' && cptr[1] == '\'') {
+ fwrite(cptr, 1, 2, f);
+ cptr += 2;
+ } else if (cptr[0] == '\\'
+ && (isdigit((unsigned char) cptr[1]) || cptr[1] == 'x')
+ && isdigit((unsigned char) cptr[2])
+ && isdigit((unsigned char) cptr[3])
+ && cptr[4] == '\'') {
+ fwrite(cptr, 1, 5, f);
+ cptr += 5;
+ } else if (cptr[0] == '\\' && cptr[2] == '\'') {
+ fwrite(cptr, 1, 3, f);
+ cptr += 3;
+ } else {
+ return 0;
+ }
+ return 1;
+}
+
+void process_apostrophe_body(FILE *f)
+{
+ if (!process_apostrophe(f)) {
+ while (In_bitmap(caml_ident_body, *cptr)) {
+ putc(*cptr, f);
+ cptr++;
+ }
+ }
+}
+
+
+static void process_open_curly_bracket(FILE *f) {
+ if (In_bitmap(caml_ident_start, *cptr) || *cptr == '|')
+ {
+ char *newcptr = cptr;
+ size_t size = 0;
+ char *buf;
+ while(In_bitmap(caml_ident_body, *newcptr)) { newcptr++; }
+ if (*newcptr == '|')
+ { /* Raw string */
+ int s_lineno;
+ char *s_line;
+ char *s_cptr;
+
+ size = newcptr - cptr;
+ buf = MALLOC(size + 2);
+ if (!buf) no_space();
+ memcpy(buf, cptr, size);
+ buf[size] = '}';
+ buf[size + 1] = '\0';
+ fwrite(cptr, 1, size + 1, f);
+ cptr = newcptr + 1;
+ s_lineno = lineno;
+ s_line = dup_line();
+ s_cptr = s_line + (cptr - line - 1);
+
+ for (;;)
+ {
+ char c = *cptr++;
+ putc(c, f);
+ if (c == '|')
+ {
+ int match = 1;
+ size_t i;
+ for (i = 0; i <= size; ++i) {
+ if (cptr[i] != buf[i]) {
+ newcptr--;
+ match = 0;
+ break;
+ }
+ }
+ if (match) {
+ FREE(s_line);
+ FREE(buf);
+ fwrite(cptr, 1, size, f);
+ cptr += size;
+ return;
+ }
+ }
+ if (c == '\n')
+ {
+ get_line();
+ if (line == 0)
+ unterminated_string(s_lineno, s_line, s_cptr);
+ }
+ }
+ FREE(buf);
+ return;
+ }
+ }
+ return;
+}
+
+static void process_comment(FILE *const f) {
+ char c = *cptr;
+ unsigned depth = 1;
+ if (c == '*')
+ {
+ int c_lineno = lineno;
+ char *c_line = dup_line();
+ char *c_cptr = c_line + (cptr - line - 1);
+
+ putc('*', f);
+ ++cptr;
+ for (;;)
+ {
+ c = *cptr++;
+ putc(c, f);
+
+ switch (c)
+ {
+ case '*':
+ if (*cptr == ')')
+ {
+ depth--;
+ if (depth == 0) {
+ FREE(c_line);
+ return;
+ }
+ }
+ continue;
+ case '\n':
+ get_line();
+ if (line == 0)
+ unterminated_comment(c_lineno, c_line, c_cptr);
+ continue;
+ case '(':
+ if (*cptr == '*') ++depth;
+ continue;
+ case '\'':
+ process_apostrophe(f);
+ continue;
+ case '"':
+ process_quoted_string(c, f);
+ continue;
+ case '{':
+ process_open_curly_bracket(f);
+ continue;
+ default:
+ continue;
+ }
+ }
+ }
+}
+
char *substring (char *str, int start, int len)
{
int i;
return (NONASSOC);
if (strcmp(cache, "start") == 0)
return (START);
- if (strcmp(cache, "union") == 0)
- return (UNION);
- if (strcmp(cache, "ident") == 0)
- return (IDENT);
}
else
{
return 0;
}
-
-void copy_ident(void)
-{
- register int c;
- register FILE *f = output_file;
-
- c = nextc();
- if (c == EOF) unexpected_EOF();
- if (c != '"') syntax_error(lineno, line, cptr);
- ++outline;
- fprintf(f, "#ident \"");
- for (;;)
- {
- c = *++cptr;
- if (c == '\n')
- {
- fprintf(f, "\"\n");
- return;
- }
- putc(c, f);
- if (c == '"')
- {
- putc('\n', f);
- ++cptr;
- return;
- }
- }
-}
-
-
void copy_text(void)
{
register int c;
- int quote;
register FILE *f = text_file;
int need_newline = 0;
int t_lineno = lineno;
unterminated_text(t_lineno, t_line, t_cptr);
case '"':
- {
- int s_lineno = lineno;
- char *s_line = dup_line();
- char *s_cptr = s_line + (cptr - line - 1);
-
- quote = c;
- putc(c, f);
- for (;;)
- {
- c = *cptr++;
- putc(c, f);
- if (c == quote)
- {
- need_newline = 1;
- FREE(s_line);
- goto loop;
- }
- if (c == '\n')
- unterminated_string(s_lineno, s_line, s_cptr);
- if (c == '\\')
- {
- c = *cptr++;
- putc(c, f);
- if (c == '\n')
- {
- get_line();
- if (line == 0)
- unterminated_string(s_lineno, s_line, s_cptr);
- }
- }
- }
- }
+ putc(c, f);
+ process_quoted_string(c, f);
+ goto loop;
case '\'':
putc(c, f);
- if (cptr[0] != 0 && cptr[0] != '\\' && cptr[1] == '\'') {
- fwrite(cptr, 1, 2, f);
- cptr += 2;
- } else
- if (cptr[0] == '\\'
- && isdigit((unsigned char) cptr[1])
- && isdigit((unsigned char) cptr[2])
- && isdigit((unsigned char) cptr[3])
- && cptr[4] == '\'') {
- fwrite(cptr, 1, 5, f);
- cptr += 5;
- } else
- if (cptr[0] == '\\' && cptr[2] == '\'') {
- fwrite(cptr, 1, 3, f);
- cptr += 3;
- }
+ process_apostrophe_body(f);
goto loop;
case '(':
putc(c, f);
need_newline = 1;
- c = *cptr;
- if (c == '*')
- {
- int c_lineno = lineno;
- char *c_line = dup_line();
- char *c_cptr = c_line + (cptr - line - 1);
-
- putc('*', f);
- ++cptr;
- for (;;)
- {
- c = *cptr++;
- putc(c, f);
- if (c == '*' && *cptr == ')')
- {
- putc(')', f);
- ++cptr;
- FREE(c_line);
- goto loop;
- }
- if (c == '\n')
- {
- get_line();
- if (line == 0)
- unterminated_comment(c_lineno, c_line, c_cptr);
- }
- }
- }
- need_newline = 1;
+ process_comment(f);
goto loop;
case '%':
}
/* fall through */
- default:
- putc(c, f);
- need_newline = 1;
- goto loop;
- }
-}
-
-
-void copy_union(void)
-{
- register int c;
- int quote;
- int depth;
- int u_lineno = lineno;
- char *u_line = dup_line();
- char *u_cptr = u_line + (cptr - line - 6);
-
- if (unionized) over_unionized(cptr - 6);
- unionized = 1;
-
- if (!lflag)
- fprintf(text_file, line_format, lineno, input_file_name);
-
- fprintf(text_file, "typedef union");
- if (dflag) fprintf(union_file, "typedef union");
-
- depth = 1;
- cptr++;
-
-loop:
- c = *cptr++;
- putc(c, text_file);
- if (dflag) putc(c, union_file);
- switch (c)
- {
- case '\n':
- get_line();
- if (line == 0) unterminated_union(u_lineno, u_line, u_cptr);
- goto loop;
-
case '{':
- ++depth;
- goto loop;
-
- case '}':
- --depth;
- if (c == '}' && depth == 0) {
- fprintf(text_file, " YYSTYPE;\n");
- FREE(u_line);
- return;
- }
- goto loop;
-
- case '\'':
- case '"':
- {
- int s_lineno = lineno;
- char *s_line = dup_line();
- char *s_cptr = s_line + (cptr - line - 1);
-
- quote = c;
- for (;;)
- {
- c = *cptr++;
- putc(c, text_file);
- if (dflag) putc(c, union_file);
- if (c == quote)
- {
- FREE(s_line);
- goto loop;
- }
- if (c == '\n')
- unterminated_string(s_lineno, s_line, s_cptr);
- if (c == '\\')
- {
- c = *cptr++;
- putc(c, text_file);
- if (dflag) putc(c, union_file);
- if (c == '\n')
- {
- get_line();
- if (line == 0)
- unterminated_string(s_lineno, s_line, s_cptr);
- }
- }
- }
- }
-
- case '(':
- c = *cptr;
- if (c == '*')
- {
- int c_lineno = lineno;
- char *c_line = dup_line();
- char *c_cptr = c_line + (cptr - line - 1);
-
- putc('*', text_file);
- if (dflag) putc('*', union_file);
- ++cptr;
- for (;;)
- {
- c = *cptr++;
- putc(c, text_file);
- if (dflag) putc(c, union_file);
- if (c == '*' && *cptr == ')')
- {
- putc(')', text_file);
- if (dflag) putc(')', union_file);
- ++cptr;
- FREE(c_line);
- goto loop;
- }
- if (c == '\n')
- {
- get_line();
- if (line == 0)
- unterminated_comment(c_lineno, c_line, c_cptr);
- }
- }
- }
+ putc(c, f);
+ process_open_curly_bracket(f);
goto loop;
-
default:
+ putc(c, f);
+ need_newline = 1;
goto loop;
}
}
-
int
hexval(int c)
{
case MARK:
return;
- case IDENT:
- copy_ident();
- break;
-
case TEXT:
copy_text();
break;
- case UNION:
- copy_union();
- break;
-
case TOKEN:
case LEFT:
case RIGHT:
register int c;
register int i, n;
int depth;
- int quote;
bucket *item;
char *tagres;
register FILE *f = action_file;
char *a_line = dup_line();
char *a_cptr = a_line + (cptr - line);
+ push_stack('{');
if (last_was_action) syntax_error (lineno, line, cptr);
last_was_action = 1;
goto loop;
}
}
- if (isalpha(c) || c == '_' || c == '$')
+ if (c == '_' || c == '$' || In_bitmap(caml_ident_start, c))
{
do
{
putc(c, f);
c = *++cptr;
- } while (isalnum(c) || c == '_' || c == '$');
+ } while (c == '_' || c == '$' || In_bitmap(caml_ident_body, c));
goto loop;
}
if (c == '}' && depth == 1) {
fprintf(f, ")\n# 0\n ");
cptr++;
+ pop_stack('{');
tagres = plhs[nrules]->tag;
if (tagres)
fprintf(f, " : %s))\n", tagres);
unterminated_action(a_lineno, a_line, a_cptr);
case '{':
+ process_open_curly_bracket(f);
+ /* Even if there is a raw string, we deliberately keep the
+ * closing '}' in the buffer */
+ push_stack('{');
++depth;
goto loop;
case '}':
--depth;
+ pop_stack('{');
goto loop;
case '"':
- {
- int s_lineno = lineno;
- char *s_line = dup_line();
- char *s_cptr = s_line + (cptr - line - 1);
-
- quote = c;
- for (;;)
- {
- c = *cptr++;
- putc(c, f);
- if (c == quote)
- {
- FREE(s_line);
- goto loop;
- }
- if (c == '\n')
- unterminated_string(s_lineno, s_line, s_cptr);
- if (c == '\\')
- {
- c = *cptr++;
- putc(c, f);
- if (c == '\n')
- {
- get_line();
- if (line == 0)
- unterminated_string(s_lineno, s_line, s_cptr);
- }
- }
- }
- }
+ process_quoted_string('"', f);
+ goto loop;
case '\'':
- if (cptr[0] != 0 && cptr[0] != '\\' && cptr[1] == '\'') {
- fwrite(cptr, 1, 2, f);
- cptr += 2;
- } else
- if (cptr[0] == '\\'
- && isdigit((unsigned char) cptr[1])
- && isdigit((unsigned char) cptr[2])
- && isdigit((unsigned char) cptr[3])
- && cptr[4] == '\'') {
- fwrite(cptr, 1, 5, f);
- cptr += 5;
- } else
- if (cptr[0] == '\\' && cptr[2] == '\'') {
- fwrite(cptr, 1, 3, f);
- cptr += 3;
- }
+ process_apostrophe_body(f);
goto loop;
case '(':
- c = *cptr;
- if (c == '*')
- {
- int c_lineno = lineno;
- char *c_line = dup_line();
- char *c_cptr = c_line + (cptr - line - 1);
+ push_stack('(');
+ process_comment(f);
+ goto loop;
- putc('*', f);
- ++cptr;
- for (;;)
- {
- c = *cptr++;
- putc(c, f);
- if (c == '*' && *cptr == ')')
- {
- putc(')', f);
- ++cptr;
- FREE(c_line);
- goto loop;
- }
- if (c == '\n')
- {
- get_line();
- if (line == 0)
- unterminated_comment(c_lineno, c_line, c_cptr);
- }
- }
- }
+ case ')':
+ pop_stack('(');
goto loop;
default:
FREE(v);
}
-static unsigned char caml_ident_start[32] =
-"\000\000\000\000\000\000\000\000\376\377\377\207\376\377\377\007\000\000\000\000\000\000\000\000\377\377\177\377\377\377\177\377";
-static unsigned char caml_ident_body[32] =
-"\000\000\000\000\200\000\377\003\376\377\377\207\376\377\377\007\000\000\000\000\000\000\000\000\377\377\177\377\377\377\177\377";
-
-#define In_bitmap(bm,c) (bm[(unsigned char)(c) >> 3] & (1 << ((c) & 7)))
-
static int is_polymorphic(char * s)
{
while (*s != 0) {