summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlain Frisch <alain@frisch.fr>2012-04-18 07:17:58 +0000
committerAlain Frisch <alain@frisch.fr>2012-04-18 07:17:58 +0000
commit061ed556888aed2c84267caca6a6ab832eb2da46 (patch)
treedd594255e06294b863e40a382af794adb60682aa
parent215e508e8bd53f7299ffd7d828794e2f4d4ba6f4 (diff)
parent3930c2fd79e43bd02e3bc79d6b047f3aeab0effe (diff)
downloadocaml-more_unboxing.tar.gz
Sync with trunk.more_unboxing
git-svn-id: http://caml.inria.fr/svn/ocaml/branches/more_unboxing@12369 f963ae5c-01c2-4b8c-9fe0-0dff7051ff02
-rw-r--r--Changes17
-rw-r--r--Makefile.nt6
-rw-r--r--VERSION4
-rw-r--r--asmcomp/cmmgen.ml5
-rw-r--r--bytecomp/bytelink.ml1
-rw-r--r--byterun/compact.c58
-rw-r--r--byterun/io.h2
-rw-r--r--byterun/memory.c2
-rw-r--r--camlp4/Camlp4Parsers/Camlp4OCamlParser.ml10
-rw-r--r--camlp4/Camlp4Parsers/Camlp4OCamlRevisedParser.ml18
-rw-r--r--camlp4/Camlp4Top/Top.ml58
-rw-r--r--config/Makefile.mingw4
-rwxr-xr-xconfigure5
-rw-r--r--debugger/program_loading.ml14
-rw-r--r--ocamlbuild/command.ml32
-rw-r--r--ocamlbuild/command.mli2
-rw-r--r--ocamlbuild/lexers.mli2
-rw-r--r--ocamlbuild/lexers.mll9
-rw-r--r--ocamlbuild/my_std.ml7
-rw-r--r--ocamlbuild/options.ml4
-rw-r--r--ocamlbuild/shell.ml7
-rw-r--r--ocamlbuild/shell.mli6
-rw-r--r--otherlibs/bigarray/bigarray.h4
-rw-r--r--otherlibs/bigarray/bigarray.ml8
-rw-r--r--otherlibs/bigarray/bigarray.mli58
-rw-r--r--otherlibs/bigarray/bigarray_stubs.c20
-rw-r--r--otherlibs/bigarray/mmap_unix.c95
-rw-r--r--otherlibs/num/ratio.mli10
-rw-r--r--otherlibs/systhreads/st_stubs.c5
-rw-r--r--parsing/location.ml9
-rw-r--r--parsing/location.mli2
-rw-r--r--parsing/parser.mly2
-rw-r--r--stdlib/gc.mli2
-rw-r--r--stdlib/printf.ml16
-rw-r--r--stdlib/printf.mli23
-rw-r--r--stdlib/random.ml7
-rw-r--r--stdlib/random.mli2
-rw-r--r--stdlib/scanf.ml2
-rw-r--r--testsuite/tests/basic-more/testrandom.ml7
-rw-r--r--testsuite/tests/basic-more/testrandom.reference4
-rw-r--r--testsuite/tests/lib-bigarray/bigarrays.ml41
-rw-r--r--testsuite/tests/lib-bigarray/bigarrays.reference8
-rw-r--r--testsuite/tests/tool-ocamldoc/odoc_test.ml2
-rw-r--r--typing/env.ml13
-rw-r--r--typing/includecore.ml3
-rw-r--r--typing/includecore.mli4
-rw-r--r--typing/includemod.ml2
-rw-r--r--typing/typedecl.ml4
-rw-r--r--utils/warnings.ml6
49 files changed, 462 insertions, 170 deletions
diff --git a/Changes b/Changes
index 9c31334fd3..c2cf259abe 100644
--- a/Changes
+++ b/Changes
@@ -57,7 +57,7 @@ Standard library:
with user-provided hash functions.
- Marshal: marshalling of function values (flag Marshal.Closures) now
also works for functions that come from dynamically-loaded modules (PR#5215)
-- Random:
+- Random:
. More random initialization (Random.self_init()), using /dev/urandom
when available (e.g. Linux, FreeBSD, MacOS X, Solaris)
. Faster implementation of Random.float
@@ -65,9 +65,14 @@ Standard library:
- Set and Map: more efficient implementation of "filter" and "partition"
- String: new function "map" (PR#3888)
+Other libraries:
+- Bigarray: added "release" functions that free memory and file mappings
+ just like GC finalization does eventually, but does it immediately.
+
Bug Fixes:
- PR#1643: functions of the Lazy module whose named started with 'lazy_' have
been deprecated, and new ones without the prefix added
+- PR#3571: in Bigarrays, call msync() before unmapping to commit changes
- PR#4549: Filename.dirname is not handling multiple / on Unix
- PR#4688: (Windows) special floating-point values aren't converted to strings
correctly
@@ -88,8 +93,11 @@ Bug Fixes:
- PR#5211: updated Genlex documentation to state that camlp4 is mandatory for
'parser' keyword and associated notation
- PR#5238, PR#5277: Sys_error when getting error location
+- PR#5295: OS threads: problem with caml_c_thread_unregister()
- PR#5301: camlp4r and exception equal to another one with parameters
- PR#5309: Queue.add is not thread/signal safe
+- PR#5310: Ratio.create_ratio/create_normalized_ratio have misleading names
+- PR#5311: better message for warning 23
- PR#5313: ocamlopt -g misses optimizations
- PR#5316: objinfo now shows ccopts/ccobjs/force_link when applicable
- PR#5322: type abbreviations expanding to a universal type variable
@@ -112,6 +120,7 @@ Bug Fixes:
- PR#5436: update object ids on unmarshaling
- PR#5453: configure doesn't find X11 under Ubuntu/MultiarchSpec
- PR#5461: Double linking of bytecode modules
+- PR#5463: Bigarray.*.map_file fail if empty array is requested
- PR#5469: private record type generated by functor loses abbreviation
- PR#5475: Wrapper script for interpreted LablTk wrongly handles command line
parameters
@@ -124,7 +133,9 @@ Bug Fixes:
- PR#5510: ocamldep has duplicate -ml{,i}-synonym options
- PR#5511: in Bigarray.reshape, unwarranted limitation on new array dimensions.
- PR#5513: Int64.div causes floating point exception (ocamlopt, x86)
-- PR#5516: in Bigarray C stubs, use C99 / GCC flexible array types if possible
+- PR#5516: in Bigarray C stubs, use C99 flexible array types if possible
+- PR#5543: in Bigarray.map_file, try to avoid using lseek() when growing file
+- PR#5538: combining -i and -annot in ocamlc
- PR#5560: incompatible type for tuple pattern with -principal
- problem with printing of string literals in camlp4 (reported on caml-list)
- emacs mode: colorization of comments and strings now works correctly
@@ -2891,5 +2902,3 @@ Caml Special Light 1.06:
------------------------
* First public release.
-
-$Id$
diff --git a/Makefile.nt b/Makefile.nt
index b435f70b66..0b9e4e7c2f 100644
--- a/Makefile.nt
+++ b/Makefile.nt
@@ -28,6 +28,9 @@ CAMLDEP=boot/ocamlrun tools/ocamldep
DEPFLAGS=$(INCLUDES)
CAMLRUN=byterun/ocamlrun
+CAMLP4OUT=$(CAMLP4:=out)
+CAMLP4OPT=$(CAMLP4:=opt)
+
INCLUDES=-I utils -I parsing -I typing -I bytecomp -I asmcomp -I driver \
-I toplevel
@@ -121,7 +124,8 @@ defaultentry:
@echo "Please refer to the installation instructions in file README.win32."
# Recompile the system using the bootstrap compiler
-all: runtime ocamlc ocamllex ocamlyacc ocamltools library ocaml otherlibraries ocamldoc.byte ocamlbuild.byte $(CAMLP4OUT) $(DEBUGGER)
+all: runtime ocamlc ocamllex ocamlyacc ocamltools library ocaml \
+ otherlibraries ocamldoc.byte ocamlbuild.byte $(CAMLP4OUT) $(DEBUGGER)
# The compilation of ocaml will fail if the runtime has changed.
# Never mind, just do make bootstrap to reach fixpoint again.
diff --git a/VERSION b/VERSION
index 56c02f784a..5662682c6c 100644
--- a/VERSION
+++ b/VERSION
@@ -1,6 +1,4 @@
-4.01.0+dev0 (2012-03-12)
+4.01.0+dev2_2012-04-17
# The version string is the first line of this file.
# It must be in the format described in stdlib/sys.mli
-
-# $Id$
diff --git a/asmcomp/cmmgen.ml b/asmcomp/cmmgen.ml
index fddf59862a..7d24f49700 100644
--- a/asmcomp/cmmgen.ml
+++ b/asmcomp/cmmgen.ml
@@ -78,7 +78,10 @@ let int_const n =
(Nativeint.add (Nativeint.shift_left (Nativeint.of_int n) 1) 1n)
let add_const c n =
- if n = 0 then c else Cop(Caddi, [c; Cconst_int n])
+ if n = 0 then c
+ else match c with
+ | Cconst_int x when no_overflow_add x n -> Cconst_int (x + n)
+ | c -> Cop(Caddi, [c; Cconst_int n])
let incr_int = function
Cconst_int n when n < max_int -> Cconst_int(n+1)
diff --git a/bytecomp/bytelink.ml b/bytecomp/bytelink.ml
index 9bc5790c2e..4f93f0c2b5 100644
--- a/bytecomp/bytelink.ml
+++ b/bytecomp/bytelink.ml
@@ -466,6 +466,7 @@ let link_bytecode_as_c ppf tolink outfile =
close_out outchan
with x ->
close_out outchan;
+ remove_file outfile;
raise x
end;
if !Clflags.debug then
diff --git a/byterun/compact.c b/byterun/compact.c
index d409492877..c310bbebb6 100644
--- a/byterun/compact.c
+++ b/byterun/compact.c
@@ -144,7 +144,7 @@ static char *compact_allocate (mlsize_t size)
return adr;
}
-void caml_compact_heap (void)
+static void do_compaction (void)
{
char *ch, *chend;
Assert (caml_gc_phase == Phase_idle);
@@ -395,6 +395,60 @@ void caml_compact_heap (void)
uintnat caml_percent_max; /* used in gc_ctrl.c and memory.c */
+void caml_compact_heap (void)
+{
+ uintnat target_size;
+
+ do_compaction ();
+ /* Compaction may fail to shrink the heap to a reasonable size
+ because it deals in complete chunks: if a very large chunk
+ is at the beginning of the heap, everything gets moved to
+ it and it is not freed.
+
+ In that case, we allocate a new chunk of the desired heap
+ size, chain it at the beginning of the heap (thus pretending
+ its address is smaller), and launch a second compaction.
+ This will move all data to this new chunk and free the
+ very large chunk.
+
+ See PR#5389
+ */
+ /* We compute:
+ freewords = caml_fl_cur_size (exact)
+ heapsize = caml_heap_size (exact)
+ usedwords = heap_size - freewords
+ target_size = usedwords * (1 + caml_percent_free / 100)
+
+ We recompact if target_size < heap_size / 2
+ */
+ target_size = (caml_stat_heap_size - Bsize_wsize (caml_fl_cur_size))
+ * (100 + caml_percent_free) / 100;
+ target_size = caml_round_heap_chunk_size (target_size);
+ if (target_size < caml_stat_heap_size / 2){
+ char *chunk;
+
+ caml_gc_message (0x10, "Recompacting...\n", 0);
+
+ /* round it up to a page size */
+ chunk = caml_alloc_for_heap (target_size);
+ if (chunk == NULL) return;
+ caml_make_free_blocks ((value *) chunk,
+ Wsize_bsize (Chunk_size (chunk)), 0);
+ if (caml_page_table_add (In_heap, chunk, chunk + Chunk_size (chunk)) != 0){
+ caml_free_for_heap (chunk);
+ return;
+ }
+ Chunk_next (chunk) = caml_heap_start;
+ caml_heap_start = chunk;
+ caml_stat_heap_size += Chunk_size (chunk);
+ if (caml_stat_heap_size > caml_stat_top_heap_size){
+ caml_stat_top_heap_size = caml_stat_heap_size;
+ }
+ do_compaction ();
+ Assert (Chunk_next (caml_heap_start) == NULL);
+ }
+}
+
void caml_compact_heap_maybe (void)
{
/* Estimated free words in the heap:
@@ -408,7 +462,7 @@ void caml_compact_heap_maybe (void)
float fw, fp;
Assert (caml_gc_phase == Phase_idle);
if (caml_percent_max >= 1000000) return;
- if (caml_stat_major_collections < 3 || caml_stat_heap_chunks < 3) return;
+ if (caml_stat_major_collections < 3) return;
fw = 3.0 * caml_fl_cur_size - 2.0 * caml_fl_size_at_phase_change;
if (fw < 0) fw = caml_fl_cur_size;
diff --git a/byterun/io.h b/byterun/io.h
index 53d9bb9bf4..89a85380c7 100644
--- a/byterun/io.h
+++ b/byterun/io.h
@@ -22,7 +22,7 @@
#include "mlvalues.h"
#ifndef IO_BUFFER_SIZE
-#define IO_BUFFER_SIZE 4096
+#define IO_BUFFER_SIZE 65536
#endif
#if defined(_WIN32)
diff --git a/byterun/memory.c b/byterun/memory.c
index b0801f130b..b99825d185 100644
--- a/byterun/memory.c
+++ b/byterun/memory.c
@@ -255,6 +255,8 @@ void caml_free_for_heap (char *mem)
caller. All other blocks must have the color [caml_allocation_color(m)].
The caller must update [caml_allocated_words] if applicable.
Return value: 0 if no error; -1 in case of error.
+
+ See also: caml_compact_heap, which duplicates most of this function.
*/
int caml_add_to_heap (char *m)
{
diff --git a/camlp4/Camlp4Parsers/Camlp4OCamlParser.ml b/camlp4/Camlp4Parsers/Camlp4OCamlParser.ml
index 3d841516e4..bbec29b966 100644
--- a/camlp4/Camlp4Parsers/Camlp4OCamlParser.ml
+++ b/camlp4/Camlp4Parsers/Camlp4OCamlParser.ml
@@ -158,6 +158,7 @@ module Make (Syntax : Sig.Camlp4Syntax) = struct
DELETE_RULE Gram expr: SELF; ":="; SELF; dummy END;
DELETE_RULE Gram expr: "~"; a_LIDENT; ":"; SELF END;
DELETE_RULE Gram expr: "?"; a_LIDENT; ":"; SELF END;
+ DELETE_RULE Gram constructor_declarations: a_UIDENT; ":"; ctyp END;
(* Some other DELETE_RULE are after the grammar *)
value clear = Gram.Entry.clear;
@@ -541,6 +542,15 @@ module Make (Syntax : Sig.Camlp4Syntax) = struct
| t = ctyp LEVEL "ctyp1" -> t
] ]
;
+ constructor_declarations:
+ [ [ s = a_UIDENT; ":"; t = constructor_arg_list ; "->" ; ret = ctyp ->
+ <:ctyp< $uid:s$ : ($t$ -> $ret$) >>
+ | s = a_UIDENT; ":"; ret = constructor_arg_list ->
+ match Ast.list_of_ctyp ret [] with
+ [ [c] -> <:ctyp< $uid:s$ : $c$ >>
+ | _ -> raise (Stream.Error "invalid generalized constructor type") ]
+ ] ]
+ ;
semi:
[ [ ";;" -> () | -> () ] ]
;
diff --git a/camlp4/Camlp4Parsers/Camlp4OCamlRevisedParser.ml b/camlp4/Camlp4Parsers/Camlp4OCamlRevisedParser.ml
index c9744140d2..ed6dad0601 100644
--- a/camlp4/Camlp4Parsers/Camlp4OCamlRevisedParser.ml
+++ b/camlp4/Camlp4Parsers/Camlp4OCamlRevisedParser.ml
@@ -303,6 +303,15 @@ New syntax:\
value stopped_at _loc =
Some (Loc.move_line 1 _loc) (* FIXME be more precise *);
+ value rec generalized_type_of_type =
+ fun
+ [ <:ctyp< $t1$ -> $t2$ >> ->
+ let (tl, rt) = generalized_type_of_type t2 in
+ ([t1 :: tl], rt)
+ | t ->
+ ([], t) ]
+ ;
+
value symbolchar =
let list =
['$'; '!'; '%'; '&'; '*'; '+'; '-'; '.'; '/'; ':'; '<'; '='; '>'; '?';
@@ -1135,12 +1144,9 @@ New syntax:\
<:ctyp< $t1$ | $t2$ >>
| s = a_UIDENT; "of"; t = constructor_arg_list ->
<:ctyp< $uid:s$ of $t$ >>
- | s = a_UIDENT; ":"; t = constructor_arg_list ; "->" ; ret = ctyp ->
- <:ctyp< $uid:s$ : ($t$ -> $ret$) >>
- | s = a_UIDENT; ":"; ret = constructor_arg_list ->
- match Ast.list_of_ctyp ret [] with
- [ [c] -> <:ctyp< $uid:s$ : $c$ >>
- | _ -> raise (Stream.Error "invalid generalized constructor type") ]
+ | s = a_UIDENT; ":"; t = ctyp ->
+ let (tl, rt) = generalized_type_of_type t in
+ <:ctyp< $uid:s$ : ($Ast.tyAnd_of_list tl$ -> $rt$) >>
| s = a_UIDENT ->
<:ctyp< $uid:s$ >>
] ]
diff --git a/camlp4/Camlp4Top/Top.ml b/camlp4/Camlp4Top/Top.ml
index 1ff0ef8210..0e07eb21e6 100644
--- a/camlp4/Camlp4Top/Top.ml
+++ b/camlp4/Camlp4Top/Top.ml
@@ -60,45 +60,31 @@ value initialization = lazy begin
else ()
end;
-value lookup x xs = try Some (List.assq x xs) with [ Not_found -> None ];
-
-value wrap parse_fun =
- let token_streams = ref [] in
- let cleanup lb =
- try token_streams.val := List.remove_assq lb token_streams.val
- with [ Not_found -> () ]
- in
- fun lb ->
- let () = Lazy.force initialization in
- let () = Register.iter_and_take_callbacks (fun (_, f) -> f ()) in
- let token_stream =
- match lookup lb token_streams.val with
- [ None ->
- let not_filtered_token_stream = Lexer.from_lexbuf lb in
- let token_stream = Gram.filter (not_filtered not_filtered_token_stream) in
- do { token_streams.val := [ (lb,token_stream) :: token_streams.val ]; token_stream }
- | Some token_stream -> token_stream ]
- in try
- match token_stream with parser
- [ [: `(EOI, _) :] -> raise End_of_file
- | [: :] -> parse_fun token_stream ]
- with
- [ End_of_file | Sys.Break | (Loc.Exc_located _ (End_of_file | Sys.Break))
- as x -> (cleanup lb; raise x)
- | x ->
- let x =
- match x with
- [ Loc.Exc_located loc x -> do {
+value wrap parse_fun lb =
+ let () = Lazy.force initialization in
+ let () = Register.iter_and_take_callbacks (fun (_, f) -> f ()) in
+ let not_filtered_token_stream = Lexer.from_lexbuf lb in
+ let token_stream = Gram.filter (not_filtered not_filtered_token_stream) in
+ try
+ match token_stream with parser
+ [ [: `(EOI, _) :] -> raise End_of_file
+ | [: :] -> parse_fun token_stream ]
+ with
+ [ End_of_file | Sys.Break | (Loc.Exc_located _ (End_of_file | Sys.Break))
+ as x -> raise x
+ | x ->
+ let x =
+ match x with
+ [ Loc.Exc_located loc x -> do {
Toploop.print_location Format.err_formatter
(Loc.to_ocaml_location loc);
x }
- | x -> x ]
- in
- do {
- cleanup lb;
- Format.eprintf "@[<0>%a@]@." Camlp4.ErrorHandler.print x;
- raise Exit
- } ];
+ | x -> x ]
+ in
+ do {
+ Format.eprintf "@[<0>%a@]@." Camlp4.ErrorHandler.print x;
+ raise Exit
+ } ];
value toplevel_phrase token_stream =
match Gram.parse_tokens_after_filter Syntax.top_phrase token_stream with
diff --git a/config/Makefile.mingw b/config/Makefile.mingw
index 29d14f6e6c..ddbc628727 100644
--- a/config/Makefile.mingw
+++ b/config/Makefile.mingw
@@ -19,6 +19,9 @@
PREFIX=C:/ocamlmgw
+### Remove this to disable compiling camlp4
+CAMLP4=camlp4
+
### Where to install the binaries
BINDIR=$(PREFIX)/bin
@@ -78,6 +81,7 @@ EXTRALIBS=
NATDYNLINK=true
CMXS=cmxs
RUNTIMED=noruntimed
+ASM_CFI_SUPPORTED=false
########## Configuration for the bytecode compiler
diff --git a/configure b/configure
index 4937fc9719..4ed6ce1b20 100755
--- a/configure
+++ b/configure
@@ -1116,6 +1116,11 @@ if sh ./hasgot -i sys/types.h -i sys/mman.h && sh ./hasgot mmap munmap; then
echo "#define HAS_MMAP" >> s.h
fi
+if sh ./hasgot pwrite; then
+ echo "pwrite() found"
+ echo "#define HAS_PWRITE" >> s.h
+fi
+
nargs=none
for i in 5 6; do
if sh ./trycompile -DNUM_ARGS=${i} gethostbyname.c; then nargs=$i; break; fi
diff --git a/debugger/program_loading.ml b/debugger/program_loading.ml
index 6ef9d03e7c..bef9f80d17 100644
--- a/debugger/program_loading.ml
+++ b/debugger/program_loading.ml
@@ -50,10 +50,10 @@ let get_environment () =
let env =
Array.fold_right
(fun elem acc ->
- if have_name_in_config_env elem then
- acc
- else
- elem :: acc)
+ if have_name_in_config_env elem then
+ acc
+ else
+ elem :: acc)
env
[] in
Array.of_list (env @ !Debugger_config.environment)
@@ -109,7 +109,7 @@ let generic_exec =
"Win32" -> generic_exec_win
| _ -> generic_exec_unix
-(* Execute the program by calling the runtime explicitely *)
+(* Execute the program by calling the runtime explicitly *)
let exec_with_runtime =
generic_exec
(function () ->
@@ -120,7 +120,7 @@ let exec_with_runtime =
thinks each command line parameter is a file.
So no good solution so far *)
Printf.sprintf "%sset CAML_DEBUG_SOCKET=%s && %s %s %s"
- (get_win32_environment ())
+ (get_win32_environment ())
!socket_name
runtime_program
!program_name
@@ -140,7 +140,7 @@ let exec_direct =
"Win32" ->
(* See the comment above *)
Printf.sprintf "%sset CAML_DEBUG_SOCKET=%s && %s %s"
- (get_win32_environment ())
+ (get_win32_environment ())
!socket_name
!program_name
!arguments
diff --git a/ocamlbuild/command.ml b/ocamlbuild/command.ml
index 131cd8586c..1ce80c9743 100644
--- a/ocamlbuild/command.ml
+++ b/ocamlbuild/command.ml
@@ -91,9 +91,15 @@ let atomize_paths l = S(List.map (fun x -> P x) l)
let env_path = lazy begin
let path_var = Sys.getenv "PATH" in
+ let parse_path =
+ if Sys.os_type = "Win32" then
+ Lexers.parse_environment_path_w
+ else
+ Lexers.parse_environment_path
+ in
let paths =
try
- Lexers.parse_environment_path (Lexing.from_string path_var)
+ parse_path (Lexing.from_string path_var)
with Lexers.Error msg -> raise (Lexers.Error ("$PATH: " ^ msg))
in
let norm_current_dir_name path =
@@ -119,21 +125,33 @@ let virtual_solver virtual_command =
failwith (Printf.sprintf "the solver for the virtual command %S \
has failed finding a valid command" virtual_command)
+(* On Windows, we need to also check for the ".exe" version of the file. *)
+let file_or_exe_exists file =
+ sys_file_exists file || Sys.os_type = "Win32" && sys_file_exists (file ^ ".exe")
-(* FIXME windows *)
let search_in_path cmd =
+ (* Try to find [cmd] in path [path]. *)
+ let try_path path =
+ (* Don't know why we're trying to be subtle here... *)
+ if path = Filename.current_dir_name then file_or_exe_exists cmd
+ else file_or_exe_exists (filename_concat path cmd)
+ in
if Filename.is_implicit cmd then
- let path = List.find begin fun path ->
- if path = Filename.current_dir_name then sys_file_exists cmd
- else sys_file_exists (filename_concat path cmd)
- end !*env_path in
+ let path = List.find try_path !*env_path in
+ (* We're not trying to append ".exe" here because all windows shells are
+ * capable of understanding the command without the ".exe" suffix. *)
filename_concat path cmd
- else cmd
+ else
+ cmd
(*** string_of_command_spec{,_with_calls *)
let rec string_of_command_spec_with_calls call_with_tags call_with_target resolve_virtuals spec =
let self = string_of_command_spec_with_calls call_with_tags call_with_target resolve_virtuals in
let b = Buffer.create 256 in
+ (* The best way to prevent bash from switching to its windows-style
+ * quote-handling is to prepend an empty string before the command name. *)
+ if Sys.os_type = "Win32" then
+ Buffer.add_string b "''";
let first = ref true in
let put_space () =
if !first then
diff --git a/ocamlbuild/command.mli b/ocamlbuild/command.mli
index 0cdc602c8a..f54b8e8ac1 100644
--- a/ocamlbuild/command.mli
+++ b/ocamlbuild/command.mli
@@ -44,3 +44,5 @@ val deps_of_tags : Tags.t -> pathname list
val dep : Tags.elt list -> pathname list -> unit
val pdep : Tags.elt list -> Tags.elt -> (string -> pathname list) -> unit
+
+val file_or_exe_exists: string -> bool
diff --git a/ocamlbuild/lexers.mli b/ocamlbuild/lexers.mli
index 2f37edca64..bc5de4cfb1 100644
--- a/ocamlbuild/lexers.mli
+++ b/ocamlbuild/lexers.mli
@@ -32,6 +32,8 @@ val trim_blanks : Lexing.lexbuf -> string
Example:
":aaa:bbb:::ccc:" -> [""; "aaa"; "bbb"; ""; ""; "ccc"; ""] *)
val parse_environment_path : Lexing.lexbuf -> string list
+(* Same one, for Windows (PATH is ;-separated) *)
+val parse_environment_path_w : Lexing.lexbuf -> string list
val conf_lines : string option -> int -> string -> Lexing.lexbuf -> conf
val path_scheme : bool -> Lexing.lexbuf ->
diff --git a/ocamlbuild/lexers.mll b/ocamlbuild/lexers.mll
index 7b191b0d97..2206f862c0 100644
--- a/ocamlbuild/lexers.mll
+++ b/ocamlbuild/lexers.mll
@@ -81,6 +81,15 @@ and comma_or_blank_sep_strings_aux = parse
| space* eof { [] }
| _ { raise (Error "Expecting (comma|blank)-separated strings (2)") }
+and parse_environment_path_w = parse
+ | ([^ ';']* as word) { word :: parse_environment_path_aux_w lexbuf }
+ | ';' ([^ ';']* as word) { "" :: word :: parse_environment_path_aux_w lexbuf }
+ | eof { [] }
+and parse_environment_path_aux_w = parse
+ | ';' ([^ ';']* as word) { word :: parse_environment_path_aux_w lexbuf }
+ | eof { [] }
+ | _ { raise (Error "Impossible: expecting colon-separated strings") }
+
and parse_environment_path = parse
| ([^ ':']* as word) { word :: parse_environment_path_aux lexbuf }
| ':' ([^ ':']* as word) { "" :: word :: parse_environment_path_aux lexbuf }
diff --git a/ocamlbuild/my_std.ml b/ocamlbuild/my_std.ml
index 78286b53c8..3ba8550242 100644
--- a/ocamlbuild/my_std.ml
+++ b/ocamlbuild/my_std.ml
@@ -249,18 +249,17 @@ let sys_command =
| "Win32" -> fun cmd ->
if cmd = "" then 0 else
let cmd = "bash -c "^Filename.quote cmd in
- (* FIXME fix Filename.quote for windows *)
- let cmd = String.subst "\"&\"\"&\"" "&&" cmd in
Sys.command cmd
| _ -> fun cmd -> if cmd = "" then 0 else Sys.command cmd
(* FIXME warning fix and use Filename.concat *)
let filename_concat x y =
if x = Filename.current_dir_name || x = "" then y else
- if x.[String.length x - 1] = '/' then
+ if Sys.os_type = "Win32" && (x.[String.length x - 1] = '\\') || x.[String.length x - 1] = '/' then
if y = "" then x
else x ^ y
- else x ^ "/" ^ y
+ else
+ x ^ "/" ^ y
(* let reslash =
match Sys.os_type with
diff --git a/ocamlbuild/options.ml b/ocamlbuild/options.ml
index b0ca59d27a..d17e0dc136 100644
--- a/ocamlbuild/options.ml
+++ b/ocamlbuild/options.ml
@@ -50,8 +50,8 @@ let mk_virtual_solvers =
if sys_file_exists !dir then
let long = filename_concat !dir cmd in
let long_opt = long ^ ".opt" in
- if sys_file_exists long_opt then A long_opt
- else if sys_file_exists long then A long
+ if file_or_exe_exists long_opt then A long_opt
+ else if file_or_exe_exists long then A long
else try let _ = search_in_path opt in a_opt
with Not_found -> a_cmd
else
diff --git a/ocamlbuild/shell.ml b/ocamlbuild/shell.ml
index c76d154583..3fbeb81aa7 100644
--- a/ocamlbuild/shell.ml
+++ b/ocamlbuild/shell.ml
@@ -23,7 +23,12 @@ let is_simple_filename s =
| _ -> false in
loop 0
let quote_filename_if_needed s =
- if is_simple_filename s then s else Filename.quote s
+ if is_simple_filename s then s
+ (* We should probably be using [Filename.unix_quote] except that function
+ * isn't exported. Users on Windows will have to live with not being able to
+ * install OCaml into c:\o'caml. Too bad. *)
+ else if Sys.os_type = "Win32" then Printf.sprintf "'%s'" s
+ else Filename.quote s
let chdir dir =
reset_filesys_cache ();
Sys.chdir dir
diff --git a/ocamlbuild/shell.mli b/ocamlbuild/shell.mli
index d393c7b3e7..2d867b032d 100644
--- a/ocamlbuild/shell.mli
+++ b/ocamlbuild/shell.mli
@@ -9,10 +9,14 @@
(* *)
(***********************************************************************)
-
(* Original author: Nicolas Pouillard *)
+
val is_simple_filename : string -> bool
+
val quote_filename_if_needed : string -> string
+(** This will quote using Unix conventions, even on Windows, because commands are
+ * always run through bash -c on Windows. *)
+
val chdir : string -> unit
val rm : string -> unit
val rm_f : string -> unit
diff --git a/otherlibs/bigarray/bigarray.h b/otherlibs/bigarray/bigarray.h
index 8625b0d9fe..f6552107a6 100644
--- a/otherlibs/bigarray/bigarray.h
+++ b/otherlibs/bigarray/bigarray.h
@@ -73,8 +73,8 @@ struct caml_ba_array {
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 / gcc's flexible array types if possible */
-#if (__STDC_VERSION__ >= 199901L) || defined(__GNUC__)
+ /* 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 */
diff --git a/otherlibs/bigarray/bigarray.ml b/otherlibs/bigarray/bigarray.ml
index 1d3dbcf971..b9f22b1828 100644
--- a/otherlibs/bigarray/bigarray.ml
+++ b/otherlibs/bigarray/bigarray.ml
@@ -99,6 +99,8 @@ module Genarray = struct
= "caml_ba_map_file_bytecode" "caml_ba_map_file"
let map_file fd ?(pos = 0L) kind layout shared dims =
map_internal fd kind layout shared dims pos
+ external release: ('a, 'b, 'c) t -> unit
+ = "caml_ba_release"
end
module Array1 = struct
@@ -122,6 +124,8 @@ module Array1 = struct
ba
let map_file fd ?pos kind layout shared dim =
Genarray.map_file fd ?pos kind layout shared [|dim|]
+ external release: ('a, 'b, 'c) t -> unit
+ = "caml_ba_release"
end
module Array2 = struct
@@ -161,6 +165,8 @@ module Array2 = struct
ba
let map_file fd ?pos kind layout shared dim1 dim2 =
Genarray.map_file fd ?pos kind layout shared [|dim1;dim2|]
+ external release: ('a, 'b, 'c) t -> unit
+ = "caml_ba_release"
end
module Array3 = struct
@@ -210,6 +216,8 @@ module Array3 = struct
ba
let map_file fd ?pos kind layout shared dim1 dim2 dim3 =
Genarray.map_file fd ?pos kind layout shared [|dim1;dim2;dim3|]
+ external release: ('a, 'b, 'c) t -> unit
+ = "caml_ba_release"
end
external genarray_of_array1: ('a, 'b, 'c) Array1.t -> ('a, 'b, 'c) Genarray.t
diff --git a/otherlibs/bigarray/bigarray.mli b/otherlibs/bigarray/bigarray.mli
index 8b260bf790..73c27b5750 100644
--- a/otherlibs/bigarray/bigarray.mli
+++ b/otherlibs/bigarray/bigarray.mli
@@ -426,7 +426,27 @@ module Genarray :
or a SIGBUS signal may be raised. This happens, for instance, if the
file is shrinked. *)
- end
+ val release: ('a, 'b, 'c) t -> unit
+ (** Release the resources associated with the given big array,
+ then set all of its dimensions to 0, causing subsequent accesses
+ to the big array to fail. This releasing of resources is performed
+ automatically by the garbage collector when the big array is no longer
+ referenced by the program. However, memory behavior of the program
+ can be improved by releasing the resources explicitly via
+ [Genarray.release] as soon as the big array is no longer useful.
+
+ If the big array was created with [Genarray.create], the memory
+ space occupied by its data is freed. If the big array was
+ created with [Genarray.map_file], updates performed on the array
+ are flushed to the file (if the mapping is shared), then the
+ mapping is removed, freeing the corresponding virtual memory
+ space. If several views on the big array data were created
+ using [Genarray.sub_*] or [Genarray.slice_*], data release occurs
+ when the last not-yet-released view is released. Multiple calls
+ to [Genarray.release] on the same big array are safe: the second
+ and subsequent calls have no effect. *)
+
+end
(** {6 One-dimensional arrays} *)
@@ -496,16 +516,20 @@ module Array1 : sig
(** Memory mapping of a file as a one-dimensional big array.
See {!Bigarray.Genarray.map_file} for more details. *)
+ val release: ('a, 'b, 'c) t -> unit
+ (** Explicit release of the resources associated with the big array.
+ See {!Bigarray.Genarray.release} for more details. *)
+
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.
Use with caution and only when the program logic guarantees that
- the access is within bounds. *)
+ the access is within bounds and the big array has not been released. *)
external unsafe_set: ('a, 'b, 'c) t -> int -> 'a -> unit
= "%caml_ba_unsafe_set_1"
(** Like {!Bigarray.Array1.set}, but bounds checking is not always performed.
Use with caution and only when the program logic guarantees that
- the access is within bounds. *)
+ the access is within bounds and the big array has not been released. *)
end
@@ -601,15 +625,21 @@ module Array2 :
(** Memory mapping of a file as a two-dimensional big array.
See {!Bigarray.Genarray.map_file} for more details. *)
+ val release: ('a, 'b, 'c) t -> unit
+ (** Explicit release of the resources associated with the big array.
+ See {!Bigarray.Genarray.release} for more details. *)
+
external unsafe_get: ('a, 'b, 'c) t -> int -> int -> 'a
= "%caml_ba_unsafe_ref_2"
- (** Like {!Bigarray.Array2.get}, but bounds checking is not always
- performed. *)
+ (** Like {!Bigarray.Array2.get}, but bounds checking is not always performed.
+ Use with caution and only when the program logic guarantees that
+ the access is within bounds and the big array has not been released. *)
external unsafe_set: ('a, 'b, 'c) t -> int -> int -> 'a -> unit
= "%caml_ba_unsafe_set_2"
- (** Like {!Bigarray.Array2.set}, but bounds checking is not always
- performed. *)
+ (** Like {!Bigarray.Array2.set}, but bounds checking is not always performed.
+ Use with caution and only when the program logic guarantees that
+ the access is within bounds and the big array has not been released. *)
end
@@ -729,15 +759,21 @@ module Array3 :
(** Memory mapping of a file as a three-dimensional big array.
See {!Bigarray.Genarray.map_file} for more details. *)
+ val release: ('a, 'b, 'c) t -> unit
+ (** Explicit release of the resources associated with the big array.
+ See {!Bigarray.Genarray.release} for more details. *)
+
external unsafe_get: ('a, 'b, 'c) t -> int -> int -> int -> 'a
= "%caml_ba_unsafe_ref_3"
- (** Like {!Bigarray.Array3.get}, but bounds checking is not always
- performed. *)
+ (** Like {!Bigarray.Array3.get}, but bounds checking is not always performed.
+ Use with caution and only when the program logic guarantees that
+ the access is within bounds and the big array has not been released. *)
external unsafe_set: ('a, 'b, 'c) t -> int -> int -> int -> 'a -> unit
= "%caml_ba_unsafe_set_3"
- (** Like {!Bigarray.Array3.set}, but bounds checking is not always
- performed. *)
+ (** Like {!Bigarray.Array3.set}, but bounds checking is not always performed.
+ Use with caution and only when the program logic guarantees that
+ the access is within bounds and the big array has not been released. *)
end
diff --git a/otherlibs/bigarray/bigarray_stubs.c b/otherlibs/bigarray/bigarray_stubs.c
index 8afdc0df6e..4021b74aee 100644
--- a/otherlibs/bigarray/bigarray_stubs.c
+++ b/otherlibs/bigarray/bigarray_stubs.c
@@ -160,8 +160,8 @@ caml_ba_alloc(int flags, int num_dims, void * data, intnat * dim)
if (data == NULL && size != 0) caml_raise_out_of_memory();
flags |= CAML_BA_MANAGED;
}
- /* PR#5516: use C99's / gcc's flexible array types if possible */
-#if (__STDC_VERSION__ >= 199901L) || defined(__GNUC__)
+ /* PR#5516: use C99's flexible array types if possible */
+#if (__STDC_VERSION__ >= 199901L)
asize = sizeof(struct caml_ba_array) + num_dims * sizeof(intnat);
#else
asize = sizeof(struct caml_ba_array) + (num_dims - 1) * sizeof(intnat);
@@ -496,18 +496,19 @@ CAMLprim value caml_ba_layout(value vb)
return Val_int(Caml_ba_array_val(vb)->flags & CAML_BA_LAYOUT_MASK);
}
-/* Finalization of a big array */
+/* Finalization / release of a big array */
static void caml_ba_finalize(value v)
{
struct caml_ba_array * b = Caml_ba_array_val(v);
+ intnat i;
switch (b->flags & CAML_BA_MANAGED_MASK) {
case CAML_BA_EXTERNAL:
break;
case CAML_BA_MANAGED:
if (b->proxy == NULL) {
- free(b->data);
+ free(b->data); /* no op if b->data = NULL */
} else {
if (-- b->proxy->refcount == 0) {
free(b->proxy->data);
@@ -526,6 +527,17 @@ static void caml_ba_finalize(value v)
}
break;
}
+ /* Make sure that subsequent accesses to the bigarray fail (empty bounds)
+ and that subsequent calls to caml_ba_finalize do nothing. */
+ for (i = 0; i < b->num_dims; i++) b->dim[i] = 0;
+ b->data = NULL;
+ b->proxy = NULL;
+}
+
+CAMLprim value caml_ba_release(value v)
+{
+ caml_ba_finalize(v);
+ return Val_unit;
}
/* Comparison of two big arrays */
diff --git a/otherlibs/bigarray/mmap_unix.c b/otherlibs/bigarray/mmap_unix.c
index 8e71664ab0..30294cc4bb 100644
--- a/otherlibs/bigarray/mmap_unix.c
+++ b/otherlibs/bigarray/mmap_unix.c
@@ -25,12 +25,14 @@
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)
@@ -39,15 +41,61 @@ extern int caml_ba_element_size[]; /* from bigarray_stubs.c */
#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 currpos, startpos, file_size, data_size;
+ file_offset startpos, file_size, data_size;
+ struct stat st;
uintnat array_size, page, delta;
- char c;
void * addr;
fd = Int_val(vfd);
@@ -65,18 +113,15 @@ CAMLprim value caml_ba_map_file(value vfd, value vkind, value vlayout,
if (dim[i] < 0)
caml_invalid_argument("Bigarray.create: negative dimension");
}
- /* Determine file size */
+ /* 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();
- currpos = lseek(fd, 0, SEEK_CUR);
- if (currpos == -1) {
- caml_leave_blocking_section();
- caml_sys_error(NO_ARG);
- }
- file_size = lseek(fd, 0, SEEK_END);
- if (file_size == -1) {
+ 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];
@@ -99,26 +144,22 @@ CAMLprim value caml_ba_map_file(value vfd, value vkind, value vlayout,
} else {
/* Check that file is large enough, and grow it otherwise */
if (file_size < startpos + array_size) {
- if (lseek(fd, startpos + array_size - 1, SEEK_SET) == -1) {
- caml_leave_blocking_section();
- caml_sys_error(NO_ARG);
- }
- c = 0;
- if (write(fd, &c, 1) != 1) {
+ if (caml_grow_file(fd, startpos + array_size) == -1) { /* PR#5543 */
caml_leave_blocking_section();
caml_sys_error(NO_ARG);
}
}
}
- /* Restore original file position */
- lseek(fd, currpos, SEEK_SET);
/* Determine offset so that the mapping starts at the given file pos */
page = getpagesize();
- delta = (uintnat) (startpos % page);
+ delta = (uintnat) startpos % page;
/* Do the mmap */
shared = Bool_val(vshared) ? MAP_SHARED : MAP_PRIVATE;
- addr = mmap(NULL, array_size + delta, PROT_READ | PROT_WRITE,
- shared, fd, startpos - delta);
+ 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);
@@ -128,8 +169,8 @@ CAMLprim value caml_ba_map_file(value vfd, value vkind, value vlayout,
#else
-value caml_ba_map_file(value vfd, value vkind, value vlayout,
- value vshared, value vdim, value vpos)
+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;
@@ -148,6 +189,12 @@ void caml_ba_unmap_file(void * addr, uintnat len)
#if defined(HAS_MMAP)
uintnat page = getpagesize();
uintnat delta = (uintnat) addr % page;
- munmap((void *)((uintnat)addr - delta), len + delta);
+ 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
}
diff --git a/otherlibs/num/ratio.mli b/otherlibs/num/ratio.mli
index 60c0f66dba..408aea9b48 100644
--- a/otherlibs/num/ratio.mli
+++ b/otherlibs/num/ratio.mli
@@ -13,7 +13,10 @@
(* $Id$ *)
-(* Module [Ratio]: operations on rational numbers *)
+(** 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
@@ -25,6 +28,8 @@ open Big_int
type ratio
+(**/**)
+
val null_denominator : ratio -> bool
val numerator_ratio : ratio -> big_int
val denominator_ratio : ratio -> big_int
@@ -32,8 +37,9 @@ 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
+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
diff --git a/otherlibs/systhreads/st_stubs.c b/otherlibs/systhreads/st_stubs.c
index ba10205eb1..9b2493a16e 100644
--- a/otherlibs/systhreads/st_stubs.c
+++ b/otherlibs/systhreads/st_stubs.c
@@ -344,7 +344,10 @@ static value caml_thread_new_descriptor(value clos)
static void caml_thread_remove_info(caml_thread_t th)
{
- if (th->next == th) all_threads = NULL; /* last OCaml thread exiting */
+ if (th->next == th)
+ all_threads = NULL; /* last OCaml thread exiting */
+ else if (all_threads == th)
+ all_threads = th->next; /* PR#5295 */
th->next->prev = th->prev;
th->prev->next = th->next;
#ifndef NATIVE_CODE
diff --git a/parsing/location.ml b/parsing/location.ml
index 02b135fae0..561a9060c4 100644
--- a/parsing/location.ml
+++ b/parsing/location.ml
@@ -223,8 +223,8 @@ let print_filename ppf file =
let reset () =
num_loc_lines := 0
-let (msg_file, msg_line, msg_chars, msg_to, msg_colon, msg_head) =
- ("File \"", "\", line ", ", characters ", "-", ":", "")
+let (msg_file, msg_line, msg_chars, msg_to, msg_colon) =
+ ("File \"", "\", line ", ", characters ", "-", ":")
(* return file, line, char from the given position *)
let get_pos_info pos =
@@ -236,7 +236,7 @@ let print_loc ppf loc =
let endchar = loc.loc_end.pos_cnum - loc.loc_start.pos_cnum + startchar in
if file = "//toplevel//" then begin
if highlight_locations ppf loc none then () else
- fprintf ppf "Characters %i-%i:@."
+ fprintf ppf "Characters %i-%i"
loc.loc_start.pos_cnum loc.loc_end.pos_cnum
end else begin
fprintf ppf "%s%a%s%i" msg_file print_filename file msg_line line;
@@ -248,7 +248,8 @@ let print_loc ppf loc =
let print ppf loc =
if loc.loc_start.pos_fname = "//toplevel//"
&& highlight_locations ppf loc none then ()
- else fprintf ppf "%a%s@.%s" print_loc loc msg_colon msg_head
+ else fprintf ppf "%a%s@." print_loc loc msg_colon
+;;
let print_error ppf loc =
print ppf loc;
diff --git a/parsing/location.mli b/parsing/location.mli
index 1f12366fd0..2b1a5a8fa5 100644
--- a/parsing/location.mli
+++ b/parsing/location.mli
@@ -63,6 +63,6 @@ val print_filename: formatter -> string -> unit
val show_filename: string -> string
(** In -absname mode, return the absolute path for this filename.
Otherwise, returns the filename unchanged. *)
-
+
val absname: bool ref
diff --git a/parsing/parser.mly b/parsing/parser.mly
index cb4d102509..a5065b5cfd 100644
--- a/parsing/parser.mly
+++ b/parsing/parser.mly
@@ -52,7 +52,7 @@ let mkpatvar name pos =
(*
Ghost expressions and patterns:
- expressions and patterns that do not appear explicitely in the
+ expressions and patterns that do not appear explicitly in the
source file they have the loc_ghost flag set to true.
Then the profiler will not try to instrument them and the
-stypes option will not try to display their type.
diff --git a/stdlib/gc.mli b/stdlib/gc.mli
index 71b8ffa783..45d882f25a 100644
--- a/stdlib/gc.mli
+++ b/stdlib/gc.mli
@@ -158,7 +158,7 @@ external quick_stat : unit -> stat = "caml_gc_quick_stat"
external counters : unit -> float * float * float = "caml_gc_counters"
(** Return [(minor_words, promoted_words, major_words)]. This function
- is as fast at [quick_stat]. *)
+ is as fast as [quick_stat]. *)
external get : unit -> control = "caml_gc_get"
(** Return the current values of the GC parameters in a [control] record. *)
diff --git a/stdlib/printf.ml b/stdlib/printf.ml
index c55c64d367..567949064a 100644
--- a/stdlib/printf.ml
+++ b/stdlib/printf.ml
@@ -638,12 +638,19 @@ let mkprintf to_s get_out outc outs flush k fmt =
kapr kpr fmt
;;
+(**************************************************************
+
+ Defining [fprintf] and various flavors of [fprintf].
+
+ **************************************************************)
+
let kfprintf k oc =
mkprintf false (fun _ -> oc) output_char output_string flush k
;;
-let ifprintf _ = kapr (fun _ -> Obj.magic ignore);;
+let ikfprintf k oc = kapr (fun _ _ -> Obj.magic (k oc));;
let fprintf oc = kfprintf ignore oc;;
+let ifprintf oc = ikfprintf ignore oc;;
let printf fmt = fprintf stdout fmt;;
let eprintf fmt = fprintf stderr fmt;;
@@ -671,7 +678,12 @@ let ksprintf k =
let sprintf fmt = ksprintf (fun s -> s) fmt;;
-(* Obsolete and deprecated. *)
+(**************************************************************
+
+ Deprecated stuff.
+
+ **************************************************************)
+
let kprintf = ksprintf;;
(* For OCaml system internal use only: needed to implement modules [Format]
diff --git a/stdlib/printf.mli b/stdlib/printf.mli
index 6fcb45ebac..f7dca62d61 100644
--- a/stdlib/printf.mli
+++ b/stdlib/printf.mli
@@ -82,7 +82,8 @@ val fprintf : out_channel -> ('a, out_channel, unit) format -> 'a
- [!]: take no argument and flush the output.
- [%]: take no argument and output one [%] character.
- [\@]: take no argument and output one [\@] character.
- - [,]: take no argument and do nothing.
+ - [,]: take no argument and output nothing: a no-op delimiter for
+ conversion specifications.
The optional [flags] are:
- [-]: left-justify the output (default is right justification).
@@ -115,12 +116,6 @@ val printf : ('a, out_channel, unit) format -> 'a
val eprintf : ('a, out_channel, unit) format -> 'a
(** Same as {!Printf.fprintf}, but output on [stderr]. *)
-val ifprintf : 'a -> ('b, 'a, unit) format -> 'b
-(** Same as {!Printf.fprintf}, but does not print anything.
- Useful to ignore some material when conditionally printing.
- @since 3.10.0
-*)
-
val sprintf : ('a, unit, string) format -> 'a
(** Same as {!Printf.fprintf}, but instead of printing on an output channel,
return a string containing the result of formatting the arguments. *)
@@ -130,6 +125,12 @@ val bprintf : Buffer.t -> ('a, Buffer.t, unit) format -> 'a
append the formatted arguments to the given extensible buffer
(see module {!Buffer}). *)
+val ifprintf : 'a -> ('b, 'a, unit) format -> 'b
+(** Same as {!Printf.fprintf}, but does not print anything.
+ Useful to ignore some material when conditionally printing.
+ @since 3.10.0
+*)
+
(** Formatted output functions with continuations. *)
val kfprintf : (out_channel -> 'a) -> out_channel ->
@@ -139,6 +140,14 @@ val kfprintf : (out_channel -> 'a) -> out_channel ->
@since 3.09.0
*)
+val ikfprintf : (out_channel -> 'a) -> out_channel ->
+ ('b, out_channel, unit, 'a) format4 -> 'b
+;;
+(** Same as [kfprintf] above, but does not print anything.
+ Useful to ignore some material when conditionally printing.
+ @since 4.0
+*)
+
val ksprintf : (string -> 'a) -> ('b, unit, string, 'a) format4 -> 'b;;
(** Same as [sprintf] above, but instead of returning the string,
passes it to the first argument.
diff --git a/stdlib/random.ml b/stdlib/random.ml
index 50b5708220..800c629706 100644
--- a/stdlib/random.ml
+++ b/stdlib/random.ml
@@ -53,7 +53,7 @@ module State = struct
let j = i mod 55 in
let k = i mod l in
accu := combine !accu seed.(k);
- s.st.(j) <- s.st.(j) lxor extract !accu;
+ s.st.(j) <- (s.st.(j) lxor extract !accu) land 0x3FFFFFFF; (* PR#5575 *)
done;
s.idx <- 0;
;;
@@ -78,8 +78,9 @@ module State = struct
let curval = s.st.(s.idx) in
let newval = s.st.((s.idx + 24) mod 55)
+ (curval lxor ((curval lsr 25) land 0x1F)) in
- s.st.(s.idx) <- newval;
- newval land 0x3FFFFFFF (* land is needed for 64-bit arch *)
+ let newval30 = newval land 0x3FFFFFFF in (* PR#5575 *)
+ s.st.(s.idx) <- newval30;
+ newval30
;;
let rec intaux s n =
diff --git a/stdlib/random.mli b/stdlib/random.mli
index 9c66c3a86e..d8ea01e621 100644
--- a/stdlib/random.mli
+++ b/stdlib/random.mli
@@ -67,7 +67,7 @@ val bool : unit -> bool
(** {6 Advanced functions} *)
(** The functions from module [State] manipulate the current state
- of the random generator explicitely.
+ of the random generator explicitly.
This allows using one or several deterministic PRNGs,
even in a multi-threaded program, without interference from
other parts of the program.
diff --git a/stdlib/scanf.ml b/stdlib/scanf.ml
index 37740765d5..cac4a136a4 100644
--- a/stdlib/scanf.ml
+++ b/stdlib/scanf.ml
@@ -483,7 +483,7 @@ let compatible_format_type fmt1 fmt2 =
Tformat.summarize_format_type (string_to_format fmt2);;
(* Checking that [c] is indeed in the input, then skips it.
- In this case, the character c has been explicitely specified in the
+ In this case, the character c has been explicitly specified in the
format as being mandatory in the input; hence we should fail with
End_of_file in case of end_of_input. (Remember that Scan_failure is raised
only when (we can prove by evidence) that the input does not match the
diff --git a/testsuite/tests/basic-more/testrandom.ml b/testsuite/tests/basic-more/testrandom.ml
index 150d408898..af0e3a2f41 100644
--- a/testsuite/tests/basic-more/testrandom.ml
+++ b/testsuite/tests/basic-more/testrandom.ml
@@ -1,13 +1,12 @@
open Random
-let _ =
+let _ =
for i = 0 to 20 do
- print_float (float 1000.); print_char ' '
+ print_int (int 1000); print_char ' '
done;
print_newline (); print_newline ();
for i = 0 to 20 do
- print_int (int 1000); print_char ' '
+ print_float (float 1000.); print_char ' '
done
let _ = exit 0
-
diff --git a/testsuite/tests/basic-more/testrandom.reference b/testsuite/tests/basic-more/testrandom.reference
index f063674d90..366e682c15 100644
--- a/testsuite/tests/basic-more/testrandom.reference
+++ b/testsuite/tests/basic-more/testrandom.reference
@@ -1,4 +1,4 @@
-270.251355065 597.822945853 287.052171181 625.315015859 241.029649126 559.742196387 932.074421229 756.637587326 360.006556146 987.177314953 190.217751234 758.516786217 59.8488223602 328.350439075 172.627051105 944.543207513 629.424106752 868.196647048 174.382120878 78.1259713643 34.3270777955
+344 685 182 641 439 500 104 20 921 370 217 885 949 678 615 412 401 606 428 869 289
-683 782 740 270 835 136 791 168 324 222 156 835 328 636 233 153 671 69 95 357 92
+122.128067547 461.324792129 360.006556146 768.75882284 396.500946942 190.217751234 567.660068681 403.59226778 59.8488223602 363.816246826 764.705761642 172.627051105 481.861849093 399.173195422 629.424106752 391.547032203 676.701133948 174.382120878 994.425675487 585.00027757 34.3270777955
All tests succeeded.
diff --git a/testsuite/tests/lib-bigarray/bigarrays.ml b/testsuite/tests/lib-bigarray/bigarrays.ml
index 85901400eb..28ed9af6f4 100644
--- a/testsuite/tests/lib-bigarray/bigarrays.ml
+++ b/testsuite/tests/lib-bigarray/bigarrays.ml
@@ -384,6 +384,12 @@ let _ =
test 12 true (test_blit_fill complex64 [Complex.zero; Complex.one; Complex.i]
Complex.i 1 1);
+ testing_function "release";
+ let a = from_list int [1;2;3;4;5] in
+ test 1 (Array1.dim a) 5;
+ Array1.release a;
+ test 2 (Array1.dim a) 0;
+
(* Bi-dimensional arrays *)
print_newline();
@@ -533,6 +539,14 @@ let _ =
test 7 (Array2.slice_right a 2) (from_list_fortran int [1002;2002;3002;4002;5002]);
test 8 (Array2.slice_right a 3) (from_list_fortran int [1003;2003;3003;4003;5003]);
+ testing_function "release";
+ let a = (make_array2 int c_layout 0 4 6 id) in
+ test 1 (Array2.dim1 a) 4;
+ test 2 (Array2.dim2 a) 6;
+ Array2.release a;
+ test 3 (Array2.dim1 a) 0;
+ test 4 (Array2.dim2 a) 0;
+
(* Tri-dimensional arrays *)
print_newline();
@@ -654,6 +668,16 @@ let _ =
test 6 (Array3.slice_right_1 a 1 2) (from_list_fortran int [112;212;312]);
test 7 (Array3.slice_right_1 a 3 1) (from_list_fortran int [131;231;331]);
+ testing_function "release";
+ let a = (make_array3 int c_layout 0 4 5 6 id) in
+ test 1 (Array3.dim1 a) 4;
+ test 2 (Array3.dim2 a) 5;
+ test 3 (Array3.dim3 a) 6;
+ Array3.release a;
+ test 4 (Array3.dim1 a) 0;
+ test 5 (Array3.dim2 a) 0;
+ test 6 (Array3.dim3 a) 0;
+
(* Reshaping *)
print_newline();
testing_function "------ Reshaping --------";
@@ -717,6 +741,7 @@ let _ =
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;
+ Array1.release a;
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;
@@ -727,7 +752,8 @@ let _ =
done
done;
test 1 !ok true;
- b.{50,50} <- (-1.0);
+ b.{50,50} <- (-1.0); (* private mapping -> no effect on file *)
+ Array2.release b;
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;
@@ -738,6 +764,7 @@ let _ =
done
done;
test 2 !ok true;
+ Array2.release c;
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;
@@ -748,6 +775,7 @@ let _ =
done
done;
test 3 !ok true;
+ Array2.release c;
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;
@@ -755,12 +783,13 @@ let _ =
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;
+ Array2.release c;
+ test 5 (Array2.dim1 c) 0;
+ test 5 (Array2.dim2 c) 0
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();
+ (* Win32 doesn't let us erase the file if any mapping on the file is
+ still active. Normally, they have all been released explicitly. *)
Sys.remove mapped_file;
()
diff --git a/testsuite/tests/lib-bigarray/bigarrays.reference b/testsuite/tests/lib-bigarray/bigarrays.reference
index bdc7beae23..def96fe4c5 100644
--- a/testsuite/tests/lib-bigarray/bigarrays.reference
+++ b/testsuite/tests/lib-bigarray/bigarrays.reference
@@ -17,6 +17,8 @@ sub
1... 2... 3... 4... 5... 6... 7... 8... 9...
blit, fill
1... 2... 3... 4... 5... 6... 7... 8... 9... 10... 11... 12...
+release
+ 1... 2...
------ Array2 --------
@@ -32,6 +34,8 @@ sub
1... 2...
slice
1... 2... 3... 4... 5... 6... 7... 8...
+release
+ 1... 2... 3... 4...
------ Array3 --------
@@ -45,6 +49,8 @@ dim
1... 2... 3... 4... 5... 6...
slice1
1... 2... 3... 4... 5... 6... 7...
+release
+ 1... 2... 3... 4... 5... 6...
------ Reshaping --------
@@ -58,4 +64,4 @@ reshape_2
output_value/input_value
1... 2... 3... 4... 5... 6... 7... 8... 9... 10... 11... 12... 13... 14...
map_file
- 1... 2... 3... 4...
+ 1... 2... 3... 4... 5... 5...
diff --git a/testsuite/tests/tool-ocamldoc/odoc_test.ml b/testsuite/tests/tool-ocamldoc/odoc_test.ml
index 1339f10a59..b5cc55626b 100644
--- a/testsuite/tests/tool-ocamldoc/odoc_test.ml
+++ b/testsuite/tests/tool-ocamldoc/odoc_test.ml
@@ -114,4 +114,4 @@ let _ =
method generate = inst#generate
end
end in
- Odoc_args.set_generator (Odoc_gen.Other (module My_generator : Odoc_gen.Base))
+ Odoc_args.set_generator (Odoc_gen.Base (module My_generator : Odoc_gen.Base))
diff --git a/typing/env.ml b/typing/env.ml
index 33a19152f8..53afa5a9e4 100644
--- a/typing/env.ml
+++ b/typing/env.ml
@@ -865,12 +865,13 @@ and store_type id path info env =
if not (Hashtbl.mem used_constructors k) then
let used = ref false in
Hashtbl.add used_constructors k (fun () -> used := true);
- !add_delayed_check_forward
- (fun () ->
- if not !used then
- Location.prerr_warning loc (Warnings.Unused_constructor c)
- )
- )
+ if not (ty = "" || ty.[0] = '_')
+ then !add_delayed_check_forward
+ (fun () ->
+ if not !used then
+ Location.prerr_warning loc (Warnings.Unused_constructor c)
+ )
+ )
constructors
end;
{ env with
diff --git a/typing/includecore.ml b/typing/includecore.ml
index 23c715f4df..972102af88 100644
--- a/typing/includecore.ml
+++ b/typing/includecore.ml
@@ -200,13 +200,12 @@ let rec compare_records env decl1 decl2 n labels1 labels2 =
then compare_records env decl1 decl2 (n+1) rem1 rem2
else [Field_type lab1]
-let type_declarations env id decl1 decl2 =
+let type_declarations env name decl1 id decl2 =
if decl1.type_arity <> decl2.type_arity then [Arity] else
if not (private_flags decl1 decl2) then [Privacy] else
let err = match (decl1.type_kind, decl2.type_kind) with
(_, Type_abstract) -> []
| (Type_variant cstrs1, Type_variant cstrs2) ->
- let name = Ident.name id in
if decl1.type_private = Private || decl2.type_private = Public then
List.iter
(fun (c, _, _) -> Env.mark_constructor_used name decl1 c)
diff --git a/typing/includecore.mli b/typing/includecore.mli
index 66bd04c310..17515a8e20 100644
--- a/typing/includecore.mli
+++ b/typing/includecore.mli
@@ -36,8 +36,8 @@ type type_mismatch =
val value_descriptions:
Env.t -> value_description -> value_description -> module_coercion
val type_declarations:
- Env.t -> Ident.t ->
- type_declaration -> type_declaration -> type_mismatch list
+ Env.t -> string ->
+ type_declaration -> Ident.t -> type_declaration -> type_mismatch list
val exception_declarations:
Env.t -> exception_declaration -> exception_declaration -> bool
(*
diff --git a/typing/includemod.ml b/typing/includemod.ml
index 4cc2904087..f1e87f55ac 100644
--- a/typing/includemod.ml
+++ b/typing/includemod.ml
@@ -63,7 +63,7 @@ let value_descriptions env cxt subst id vd1 vd2 =
let type_declarations env cxt subst id decl1 decl2 =
Env.mark_type_used (Ident.name id) decl1;
let decl2 = Subst.type_declaration subst decl2 in
- let err = Includecore.type_declarations env id decl1 decl2 in
+ let err = Includecore.type_declarations env (Ident.name id) decl1 id decl2 in
if err <> [] then raise(Error[cxt, Type_declarations(id, decl1, decl2, err)])
(* Inclusion between exception declarations *)
diff --git a/typing/typedecl.ml b/typing/typedecl.ml
index 3f483c8df0..307d5041b5 100644
--- a/typing/typedecl.ml
+++ b/typing/typedecl.ml
@@ -359,8 +359,10 @@ let check_abbrev env (_, sdecl) (id, decl) =
else if not (Ctype.equal env false args decl.type_params)
then [Includecore.Constraint]
else
- Includecore.type_declarations env id
+ Includecore.type_declarations env
+ (Path.last path)
decl'
+ id
(Subst.type_declaration
(Subst.add_type id path Subst.identity) decl)
in
diff --git a/utils/warnings.ml b/utils/warnings.ml
index e6ea56e9a8..4745598b07 100644
--- a/utils/warnings.ml
+++ b/utils/warnings.ml
@@ -235,7 +235,7 @@ let message = function
Here is an example of a value that is not matched:\n" ^ s
| Non_closed_record_pattern s ->
"the following labels are not bound in this record pattern:\n" ^ s ^
- "\nEither bind these labels explicitly or add `; _' to the pattern."
+ "\nEither bind these labels explicitly or add '; _' to the pattern."
| Statement_type ->
"this expression should have type unit."
| Unused_match -> "this match case is unused."
@@ -262,8 +262,8 @@ let message = function
"this statement never returns (or has an unsound type.)"
| Camlp4 s -> s
| Useless_record_with ->
- "this record is defined by a `with' expression,\n\
- but no fields are borrowed from the original."
+ "all the fields are explicitly listed in this record:\n\
+ the 'with' clause is useless."
| Bad_module_name (modname) ->
"bad source file name: \"" ^ modname ^ "\" is not a valid module name."
| All_clauses_guarded ->