[Unison-hackers] [unison-svn] r400 - in trunk/src: . system system/win ubase uimacnew uimacnew09

vouillon@seas.upenn.edu vouillon at seas.upenn.edu
Sun Jan 10 17:53:01 EST 2010


Author: vouillon
Date: 2010-01-10 17:52:59 -0500 (Sun, 10 Jan 2010)
New Revision: 400

Modified:
   trunk/src/RECENTNEWS
   trunk/src/fpcache.ml
   trunk/src/mkProjectInfo.ml
   trunk/src/os.ml
   trunk/src/osx.ml
   trunk/src/props.ml
   trunk/src/remote.ml
   trunk/src/system/system_win.ml
   trunk/src/system/win/system_impl.ml
   trunk/src/ubase/util.ml
   trunk/src/uimacbridgenew.ml
   trunk/src/uimacnew/Bridge.h
   trunk/src/uimacnew/Bridge.m
   trunk/src/uimacnew/ImageAndTextCell.m
   trunk/src/uimacnew/MyController.m
   trunk/src/uimacnew/ProfileController.m
   trunk/src/uimacnew/ReconItem.h
   trunk/src/uimacnew/ReconItem.m
   trunk/src/uimacnew/ReconTableView.m
   trunk/src/uimacnew/UnisonToolbar.h
   trunk/src/uimacnew/main.m
   trunk/src/uimacnew09/Bridge.h
   trunk/src/uimacnew09/Bridge.m
   trunk/src/uimacnew09/ImageAndTextCell.m
   trunk/src/uimacnew09/MyController.m
   trunk/src/uimacnew09/ProfileController.m
   trunk/src/uimacnew09/ReconItem.h
   trunk/src/uimacnew09/ReconItem.m
   trunk/src/uimacnew09/main.m
Log:
* Mac GUIs (NEED TESTING):
  - use doubles rather than ints for file sizes to prevent overflows
  - should now be 64 bit clean (the Growl framework is not up to date,
    though)
  - fixes from uimacnew09 copied back to uimacnew
  - made the bridge between Objective C and Ocaml code GC friendly
    (it was allocating ML values and putting them in an array which
    was not registered with the GC)
* Windows: only use long UNC path for accessing replicas (as '..' is
  not handled with this format of paths, but can be useful)
* Bumped fingerprint cache magic number (the format was changed in
  revision 398)


Modified: trunk/src/RECENTNEWS
===================================================================
--- trunk/src/RECENTNEWS	2010-01-10 15:30:18 UTC (rev 399)
+++ trunk/src/RECENTNEWS	2010-01-10 22:52:59 UTC (rev 400)
@@ -1,5 +1,21 @@
 CHANGES FROM VERSION 2.39.0
 
+* Mac GUIs (NEED TESTING):
+  - use doubles rather than ints for file sizes to prevent overflows
+  - should now be 64 bit clean (the Growl framework is not up to date,
+    though)
+  - fixes from uimacnew09 copied back to uimacnew
+  - made the bridge between Objective C and Ocaml code GC friendly
+    (it was allocating ML values and putting them in an array which
+    was not registered with the GC)
+* Windows: only use long UNC path for accessing replicas (as '..' is
+  not handled with this format of paths, but can be useful)
+* Bumped fingerprint cache magic number (the format was changed in
+  revision 398)
+
+-------------------------------
+CHANGES FROM VERSION 2.39.0
+
 * Back out some minimal support we'd added for checking out Unison sources via Bazaar.
 
 * Small fix for OSX GUI

Modified: trunk/src/fpcache.ml
===================================================================
--- trunk/src/fpcache.ml	2010-01-10 15:30:18 UTC (rev 399)
+++ trunk/src/fpcache.ml	2010-01-10 22:52:59 UTC (rev 400)
@@ -59,7 +59,7 @@
 let compress state path =
   let s = state.last in
   let p = Path.toString path in
-  let l = String.length s in
+  let l = min (String.length p) (String.length s) in
   let i = ref 0 in
   while !i < l && p.[!i] = s.[!i] do incr i done;
   state.last <- p;
@@ -126,7 +126,7 @@
                closeOut st
   | None    -> ()
 
-let magic = "Unison fingerprint cache format 1"
+let magic = "Unison fingerprint cache format 2"
 
 let init fastCheck fspath =
   finish ();

Modified: trunk/src/mkProjectInfo.ml
===================================================================
--- trunk/src/mkProjectInfo.ml	2010-01-10 15:30:18 UTC (rev 399)
+++ trunk/src/mkProjectInfo.ml	2010-01-10 22:52:59 UTC (rev 400)
@@ -100,3 +100,4 @@
 
 
 
+

Modified: trunk/src/os.ml
===================================================================
--- trunk/src/os.ml	2010-01-10 15:30:18 UTC (rev 399)
+++ trunk/src/os.ml	2010-01-10 22:52:59 UTC (rev 400)
@@ -292,14 +292,7 @@
       genericName
 
 (* build a fspath representing an archive child path whose name is given     *)
-let fileInUnisonDir str =
-  begin try
-    ignore (Name.fromString str)
-  with Invalid_argument _ ->
-    raise (Util.Transient
-             ("Ill-formed name of file in UNISON directory: "^str))
-  end;
-  System.fspathConcat unisonDir str
+let fileInUnisonDir str = System.fspathConcat unisonDir str
 
 (* Make sure archive directory exists                                        *)
 let createUnisonDir() =
@@ -316,9 +309,9 @@
 (*****************************************************************************)
 
 (* Truncate a filename to at most [l] bytes, making sure of not
-   truncating an UTF-8 character *)
+   truncating an UTF-8 character.  Assumption: [String.length s > l] *)
 let rec truncate_filename s l =
-  if l >= 0 && Char.code s.[l] land 0xC0 = 0x80 then
+  if l > 0 && Char.code s.[l] land 0xC0 = 0x80 then
     truncate_filename s (l - 1)
   else
     String.sub s 0 l

Modified: trunk/src/osx.ml
===================================================================
--- trunk/src/osx.ml	2010-01-10 15:30:18 UTC (rev 399)
+++ trunk/src/osx.ml	2010-01-10 22:52:59 UTC (rev 400)
@@ -206,7 +206,7 @@
 (* Remove trailing zeroes *)
 let trim s =
   let rec trim_rec s pos =
-    if s.[pos - 1] = '\000' then
+    if pos > 0 && s.[pos - 1] = '\000' then
       trim_rec s (pos - 1)
     else
       String.sub s 0 pos

Modified: trunk/src/props.ml
===================================================================
--- trunk/src/props.ml	2010-01-10 15:30:18 UTC (rev 399)
+++ trunk/src/props.ml	2010-01-10 22:52:59 UTC (rev 400)
@@ -614,7 +614,8 @@
 
 let toString t =
   match t with
-    Some s when s.[0] = 'F' && String.sub (s ^ zeroes) 1 8 <> zeroes ->
+    Some s when String.length s > 0 && s.[0] = 'F' &&
+                String.sub (s ^ zeroes) 1 8 <> zeroes ->
       let s = s ^ zeroes in
       " " ^ String.escaped (String.sub s 1 4) ^
       " " ^ String.escaped (String.sub s 5 4)

Modified: trunk/src/remote.ml
===================================================================
--- trunk/src/remote.ml	2010-01-10 15:30:18 UTC (rev 399)
+++ trunk/src/remote.ml	2010-01-10 22:52:59 UTC (rev 400)
@@ -987,10 +987,6 @@
   negociateFlowControl conn;
   Lwt.return conn)
 
-let inetAddr host =
-  let targetHostEntry = Unix.gethostbyname host in
-  targetHostEntry.Unix.h_addr_list.(0)
-
 let rec findFirst f l =
   match l with
     []     -> None

Modified: trunk/src/system/system_win.ml
===================================================================
--- trunk/src/system/system_win.ml	2010-01-10 15:30:18 UTC (rev 399)
+++ trunk/src/system/system_win.ml	2010-01-10 22:52:59 UTC (rev 400)
@@ -22,6 +22,8 @@
 
 *)
 
+module M (P : sig val useLongUNCPaths : bool end) = struct
+
 type fspath = string
 
 let fspathFromString f = f
@@ -43,7 +45,9 @@
 let winRootRx = Rx.rx "[a-zA-Z]:[/\\].*"
 let winUncRx = Rx.rx "[/\\][/\\][^/\\]+[/\\][^/\\]+[/\\].*"
 let extendedPath f =
-  if Rx.match_string winRootRx f then
+  if not P.useLongUNCPaths then
+    f
+  else if Rx.match_string winRootRx f then
     fixPath ("\\\\?\\" ^ f)
   else if Rx.match_string winUncRx f then
     fixPath ("\\\\?\\UNC" ^ String.sub f 1 (String.length f - 1))
@@ -318,3 +322,5 @@
     rawTerminal = (fun () -> setConsoleMode 0x19; setConsoleOutputCP 65001);
     startReading = (fun () -> setConsoleMode 0x18);
     stopReading = (fun () -> setConsoleMode 0x19) }
+
+end

Modified: trunk/src/system/win/system_impl.ml
===================================================================
--- trunk/src/system/win/system_impl.ml	2010-01-10 15:30:18 UTC (rev 399)
+++ trunk/src/system/win/system_impl.ml	2010-01-10 22:52:59 UTC (rev 400)
@@ -15,7 +15,7 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *)
 
-module System = System_win
+module System = System_win.M (struct let useLongUNCPaths = false end)
 
 module Fs = struct
 
@@ -28,7 +28,7 @@
   let c3 f1 f2 v1 v2 v3 = if !unicode then f1 v1 v2 v3 else f2 v1 v2 v3
 
   module G = System_generic
-  module W = System_win
+  module W = System_win.M (struct let useLongUNCPaths = true end)
 
   type fspath = string
 

Modified: trunk/src/ubase/util.ml
===================================================================
--- trunk/src/ubase/util.ml	2010-01-10 15:30:18 UTC (rev 399)
+++ trunk/src/ubase/util.ml	2010-01-10 22:52:59 UTC (rev 400)
@@ -383,6 +383,7 @@
   if l = 0 || s.[l - 1] <> '\r' then s else
   String.sub s 0 (l - 1)
 
+(* FIX: quadratic! *)
 let rec trimWhitespace s =
   let l = String.length s in
   if l=0 then s

Modified: trunk/src/uimacbridgenew.ml
===================================================================
--- trunk/src/uimacbridgenew.ml	2010-01-10 15:30:18 UTC (rev 399)
+++ trunk/src/uimacbridgenew.ml	2010-01-10 22:52:59 UTC (rev 400)
@@ -392,9 +392,7 @@
 Callback.register "unisonRiToRight" unisonRiToRight;;
 
 let unisonRiToFileSize ri =
-  (*FIX: will not work with files and directories larger than 1 GiB on
-    32bit machines! *)
-  Uutil.Filesize.toInt (riLength ri.ri);;
+  Uutil.Filesize.toFloat (riLength ri.ri);;
 Callback.register "unisonRiToFileSize" unisonRiToFileSize;;
 
 let unisonRiToFileType ri =
@@ -450,9 +448,7 @@
 Callback.register "unisonRiToProgress" unisonRiToProgress;;
 
 let unisonRiToBytesTransferred ri =
-  (*FIX: will not work when transferring more than 1 GiB on 32bit
-    machines! *)
-  Uutil.Filesize.toInt ri.bytesTransferred;;
+  Uutil.Filesize.toFloat ri.bytesTransferred;;
 Callback.register "unisonRiToBytesTransferred" unisonRiToBytesTransferred;;
 
 (* --------------------------------------------------- *)

Modified: trunk/src/uimacnew/Bridge.h
===================================================================
--- trunk/src/uimacnew/Bridge.h	2010-01-10 15:30:18 UTC (rev 399)
+++ trunk/src/uimacnew/Bridge.h	2010-01-10 22:52:59 UTC (rev 400)
@@ -24,14 +24,14 @@
 	Args/return values are converted to/from C/OCaml according to the
 	supplied type signture string.  Type codes are:
 		x	- void (for return type)
-		i	- int
+		i	- long
 		s	- char *
 		S	- NSString *
+                N       - NSNumber *
 		@	- OCamlValue (see below)
-		v	- unwrapped OCaml value (deprecated -- unsafe!)
 		
 	Examples:
-		int count = (int)ocamlCall("iS", "lengthOfString", @"Some String");
+		long count = (long)ocamlCall("iS", "lengthOfString", @"Some String");
 		
 		(void)ocamlCall("x", "someVoidOCamlFunction");
 		
@@ -42,17 +42,17 @@
 
 // Wrapper/proxy for unconverted OCaml values
 @interface OCamlValue : NSObject {
-	int _v;
+	long _v;
 }
-- initWithValue:(int)v;
+- initWithValue:(long)v;
 
-- (void *)getField:(int)i withType:(char)t;
+- (void *)getField:(long)i withType:(char)t;
 	// get value by position.  See ocamlCall for list of type conversion codes
 	
-- (int)count;
+- (long)count;
 	// count of items in array
 	
-- (int)value;
+- (long)value;
 	// returns Ocaml value directly -- not safe to use except in direct callback from OCaml
 	// (i.e. in the OCaml thread)
 @end

Modified: trunk/src/uimacnew/Bridge.m
===================================================================
--- trunk/src/uimacnew/Bridge.m	2010-01-10 15:30:18 UTC (rev 399)
+++ trunk/src/uimacnew/Bridge.m	2010-01-10 22:52:59 UTC (rev 400)
@@ -95,7 +95,10 @@
 	// NSLog(@"*** caml_init complete!");
 }
 
-- (BOOL)exceptionHandler:(NSExceptionHandler *)sender shouldLogException:(NSException *)exception mask:(unsigned int)aMask
+#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
+typedef unsigned int NSUInteger;
+#endif
+- (BOOL)exceptionHandler:(NSExceptionHandler *)sender shouldLogException:(NSException *)exception mask:(NSUInteger)aMask
 {
 	// if (![[exception name] isEqual:@"OCamlException"]) return YES;
 	
@@ -121,7 +124,7 @@
 
 	// Field access
 	value *valueP;
-	int fieldIndex;
+	long fieldIndex;
 	char fieldType;
 	
 	// Return values
@@ -139,9 +142,11 @@
 
 // Our OCaml callback server thread -- waits for call then makes them
 // Called from thread spawned from OCaml
-CAMLprim value bridgeThreadWait(int ignore)
+CAMLprim value bridgeThreadWait(value ignore)
 {
-	value args[10];
+        CAMLparam0();
+        CAMLlocal1 (args);
+        args = caml_alloc_tuple(3);
 	
 	// NSLog(@"*** bridgeThreadWait init!  (%d) Taking lock...", pthread_self());
 	while (TRUE) {
@@ -168,6 +173,7 @@
 		char retType = 'v';
 		value e = Val_unit;
 		if (cs->opCode == SafeCall) {
+                        int i;
 			char *fname = va_arg(cs->args, char *);
 			value *f = caml_named_value(fname);
 			// varargs with C-based args -- convert them to OCaml values based on type code string
@@ -179,33 +185,31 @@
 				switch (*p) {
 					case 's':
 						str = va_arg(cs->args, const char *);
-						args[argCount] = caml_copy_string(str);
+						Store_field (args, argCount, caml_copy_string(str));
 						break;
 					case 'S':
 						str = [va_arg(cs->args, NSString *) UTF8String];
-						args[argCount] = caml_copy_string(str);
+						Store_field (args, argCount, caml_copy_string(str));
 						break;
-					case 'n':
-						// leak?
-						args[argCount] = *caml_named_value(va_arg(cs->args, char *));
-						break;
 					case 'i':
-						args[argCount] = Val_int(va_arg(cs->args, int));
+                                                Store_field (args, argCount, Val_long(va_arg(cs->args, long)));
 						break;
-					case 'v':
-						args[argCount] = va_arg(cs->args, value);
-						break;
 					case '@':
-						args[argCount] = [va_arg(cs->args, OCamlValue *) value];
+                                                Store_field (args, argCount, [va_arg(cs->args, OCamlValue *) value]);
 						break;
+                                        default:
+                                                NSCAssert1(0, @"Unknown input type '%c'", *p);
+						break;
 				}
 				argCount++;
+                                NSCAssert(argCount <= 3, @"More than 3 arguments");
 			}
 			// Call OCaml -- TODO: add support for > 3 args
-			if (argCount == 3) e = caml_callback3_exn(*f,args[0],args[1],args[2]);
-			else if (argCount == 2) e = caml_callback2_exn(*f,args[0],args[1]);
-			else if (argCount == 1) e = caml_callback_exn(*f,args[0]);
+			if (argCount == 3) e = caml_callback3_exn(*f,Field(args,0),Field(args,1),Field(args,2));
+			else if (argCount == 2) e = caml_callback2_exn(*f,Field(args,0),Field(args,1));
+			else if (argCount == 1) e = caml_callback_exn(*f,Field(args,0));
 			else e = caml_callback_exn(*f,Val_unit);			
+                        for (i = 0; i < argCount; i++) Store_field (args, i, Val_unit);
 		} else if (cs->opCode == OldCall) {
 			// old style (unsafe) version where OCaml values were passed directly from C thread
 			if (cs->argCount == 3) e = caml_callback3_exn(cs->call,cs->a1,cs->a2,cs->a3);
@@ -213,8 +217,8 @@
 			else e = caml_callback_exn(cs->call,cs->a1);
 			retType = 'v';
 		} else if (cs->opCode == FieldAccess) {
-			int index = cs->fieldIndex;
-			e = (index == -1) ? Val_int(Wosize_val(*cs->valueP)) : Field(*cs->valueP, cs->fieldIndex);
+			long index = cs->fieldIndex;
+			e = (index == -1) ? Val_long(Wosize_val(*cs->valueP)) : Field(*cs->valueP, index);
 			retType = cs->fieldType;
 		}
 		
@@ -223,30 +227,38 @@
 		cs->ret = e; // OCaml return type -- unsafe...
 		if (!Is_exception_result(e)) {
 			switch (retType) {
-				case 's':
-					*((char **)&cs->retV) = (e == Val_unit) ? NULL : String_val(e);
-					break;
 				case 'S':
 					*((NSString **)&cs->retV) = (e == Val_unit) ? NULL : [[NSString alloc] initWithUTF8String:String_val(e)];
 					cs->_autorelease = TRUE;
 					break;
+				case 'N':
+                                        if (Is_long (e)) {
+					        *((NSNumber **)&cs->retV) = [[NSNumber alloc] initWithLong:Long_val(e)];
+                                        } else {
+					        *((NSNumber **)&cs->retV) = [[NSNumber alloc] initWithDouble:Double_val(e)];
+                                        }
+					cs->_autorelease = TRUE;
+					break;
 				case '@':
 					*((NSObject **)&cs->retV) = (e == Val_unit) ? NULL : [[OCamlValue alloc] initWithValue:e];
 					cs->_autorelease = TRUE;
 					break;
-				case 'v':
-					*((value *)&cs->retV) = e;
-					break;
 				case 'i':
-					*((int *)&cs->retV) = Int_val(e);
+					*((long *)&cs->retV) = Long_val(e);
 					break;
+				case 'x':
+                                        break;
+                                default:
+                                        NSCAssert1(0, @"Unknown return type '%c'", retType);
+                                        break;
 			}
 		}
 
 		if (Is_exception_result(e)) {
 			// get exception string -- it will get thrown back in the calling thread
 		    value *f = caml_named_value("unisonExnInfo");
-			cs->exception = String_val(caml_callback(*f,Extract_exception(e)));
+                    // We leak memory here...
+                    cs->exception = strdup(String_val(caml_callback(*f,Extract_exception(e))));
 		}
 		
  	    [pool release];
@@ -260,7 +272,7 @@
 		pthread_mutex_unlock(&global_res_lock);
 	}
 	// Never get here...
-    return Val_unit;
+        CAMLreturn (Val_unit);
 }
 
 void *_passCall(CallState *cs)
@@ -292,20 +304,18 @@
 
 void *ocamlCall(const char *argTypes, ...)
 {
-	va_list ap;
-	va_start(ap, argTypes);
 	CallState cs;
 	cs.opCode = SafeCall;
 	cs.exception = NULL;
 	cs.argTypes = argTypes;
-	cs.args = ap;
+	va_start(cs.args, argTypes);
 	void * res = _passCall(&cs);
 	
-	va_end(ap);
+	va_end(cs.args);
 	return res;
 }
 
-void *getField(value *vP, int index, char type)
+void *getField(value *vP, long index, char type)
 {
 	CallState cs;
 	cs.opCode = FieldAccess;
@@ -318,7 +328,7 @@
 
 @implementation OCamlValue
 
-- initWithValue:(int)v
+- initWithValue:(long)v
 {
 	[super init];
 	_v = v;
@@ -326,17 +336,17 @@
 	return self;
 }
 
-- (int)count
+- (long)count
 {
-	return (int)getField((value *)&_v, -1, 'i');
+        return (long)getField((value *) &_v, -1, 'i');
 }
 
-- (void *)getField:(int)i withType:(char)t
+- (void *)getField:(long)i withType:(char)t
 {
-	return getField((value *)&_v, i, t);
+        return getField((value *)&_v, i, t);
 }
 
-- (int)value 
+- (long)value
 {
 	// Unsafe to use!
 	return _v;

Modified: trunk/src/uimacnew/ImageAndTextCell.m
===================================================================
--- trunk/src/uimacnew/ImageAndTextCell.m	2010-01-10 15:30:18 UTC (rev 399)
+++ trunk/src/uimacnew/ImageAndTextCell.m	2010-01-10 22:52:59 UTC (rev 400)
@@ -88,7 +88,10 @@
     [super editWithFrame: textFrame inView: controlView editor:textObj delegate:anObject event: theEvent];
 }
 
-- (void)selectWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)anObject start:(int)selStart length:(int)selLength {
+#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
+typedef int NSInteger;
+#endif
+- (void)selectWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)anObject start:(NSInteger)selStart length:(NSInteger)selLength {
     NSRect textFrame, imageFrame;
     NSDivideRect (aRect, &imageFrame, &textFrame, 3 + [image size].width, NSMinXEdge);
     [super selectWithFrame: textFrame inView: controlView editor:textObj delegate:anObject start:selStart length:selLength];

Modified: trunk/src/uimacnew/MyController.m
===================================================================
--- trunk/src/uimacnew/MyController.m	2010-01-10 15:30:18 UTC (rev 399)
+++ trunk/src/uimacnew/MyController.m	2010-01-10 22:52:59 UTC (rev 400)
@@ -31,7 +31,9 @@
 
 // BCP (11/09): Added per Onne Gorter:
 // if user closes main window, terminate app, instead of keeping an empty app around with no window
-- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication { return YES; }
+- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication {
+  return YES;
+}
 
 - (id)init
 {
@@ -166,8 +168,7 @@
 }
 
 /* Only valid once a profile has been selected */
-- (NSString *)profile
-{
+- (NSString *)profile {
     return myProfile;
 }
 
@@ -176,8 +177,7 @@
     [aProfile retain];
     [myProfile release];
     myProfile = aProfile;
-    [mainWindow setTitle:
-        [NSString stringWithFormat:@"Unison: %@", myProfile]];
+    [mainWindow setTitle: [NSString stringWithFormat:@"Unison: %@", myProfile]];
 }
 
 - (IBAction)restartButton:(id)sender
@@ -217,7 +217,7 @@
 {
 	[tableView reloadData]; 
 	if (shouldResetSelection) {
-		[tableView selectRow:0 byExtendingSelection:NO];
+		[tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:0] byExtendingSelection:NO];
 		shouldResetSelection = NO;
 	}
 	[updatesView setNeedsDisplay:YES];	    
@@ -268,6 +268,7 @@
 
 CAMLprim value unisonInit1Complete(value v)
 {
+  id pool = [[NSAutoreleasePool alloc] init];
     if (v == Val_unit) {
         NSLog(@"Connected.");
 		[me->preconn release];
@@ -278,7 +279,7 @@
 		me->preconn = [[OCamlValue alloc] initWithValue:Field(v,0)]; // value of Some
 		[me performSelectorOnMainThread:@selector(unisonInit1Complete:) withObject:nil waitUntilDone:FALSE]; 
 	}
-
+  [pool release];
     return Val_unit;
 }
 
@@ -310,7 +311,7 @@
 {
     // FIX: some prompts don't ask for password, need to look at it
     NSLog(@"Got the prompt: '%@'",prompt);
-    if ((int)ocamlCall("iS", "unisonPasswordMsg", prompt)) {
+    if ((long)ocamlCall("iS", "unisonPasswordMsg", prompt)) {
         [passwordPrompt setStringValue:@"Please enter your password"];
         [NSApp beginSheet:passwordWindow
             modalForWindow:mainWindow
@@ -319,7 +320,7 @@
             contextInfo:nil];
         return;
     }
-    if ((int)ocamlCall("iS", "unisonPassphraseMsg", prompt)) {
+    if ((long)ocamlCall("iS", "unisonPassphraseMsg", prompt)) {
         [passwordPrompt setStringValue:@"Please enter your passphrase"];
         [NSApp beginSheet:passwordWindow
             modalForWindow:mainWindow
@@ -328,7 +329,7 @@
             contextInfo:nil];
         return;
     }
-    if ((int)ocamlCall("iS", "unisonAuthenticityMsg", prompt)) {
+    if ((long)ocamlCall("iS", "unisonAuthenticityMsg", prompt)) {
         int i = NSRunAlertPanel(@"New host",prompt,@"Yes",@"No",nil);
         if (i == NSAlertDefaultReturn) {
 			ocamlCall("x at s", "openConnectionReply", preconn, "yes");
@@ -466,7 +467,9 @@
 
 CAMLprim value unisonInit2Complete(value v)
 {
+  id pool = [[NSAutoreleasePool alloc] init];
     [me performSelectorOnMainThread:@selector(afterUpdate:) withObject:[[OCamlValue alloc] initWithValue:v] waitUntilDone:FALSE]; 
+  [pool release];
     return Val_unit;
 }
 
@@ -502,7 +505,9 @@
 
 CAMLprim value syncComplete()
 {
+  id pool = [[NSAutoreleasePool alloc] init];
     [me performSelectorOnMainThread:@selector(afterSync:) withObject:nil waitUntilDone:FALSE]; 
+  [pool release];
     return Val_unit;
 }
 
@@ -517,10 +522,12 @@
 
 CAMLprim value reloadTable(value row)
 {
+  id pool = [[NSAutoreleasePool alloc] init];
 	// NSLog(@"OCaml says... ReloadTable: %i", Int_val(row));
 	NSNumber *num = [[NSNumber alloc] initWithInt:Int_val(row)];
     [me performSelectorOnMainThread:@selector(reloadTable:) withObject:num waitUntilDone:FALSE]; 
 	[num release];
+  [pool release];
     return Val_unit;
 }
 
@@ -556,9 +563,9 @@
 		[(ImageAndTextCell*)cell setImage:[item fileIcon]];
 		
 		// For parents, format the file count into the text
-		int fileCount = [item fileCount];
+		long fileCount = [item fileCount];
 		if (fileCount > 1) {
-			NSString *countString = [NSString stringWithFormat:@"  (%i files)", fileCount];
+			NSString *countString = [NSString stringWithFormat:@"  (%ld files)", fileCount];
 			NSString *fullString = [(NSString *)[cell objectValue] stringByAppendingString:countString];
 			NSMutableAttributedString *as = [[NSMutableAttributedString alloc] initWithString:fullString];
 
@@ -623,7 +630,7 @@
 {
     [reconItems release];
     reconItems = [[NSMutableArray alloc] init];
-	int i, n =[caml_reconItems count];
+	long i, n =[caml_reconItems count];
     for (i=0; i<n; i++) {
 		LeafReconItem *item = [[LeafReconItem alloc] initWithRiAndIndex:(id)[caml_reconItems getField:i withType:'@'] index:i];
         [reconItems addObject:item];
@@ -712,7 +719,7 @@
 
 - (id)updateForIgnore:(id)item
 {
-    int j = (int)ocamlCall("ii", "unisonUpdateForIgnore", [reconItems indexOfObjectIdenticalTo:item]);
+    long j = (long)ocamlCall("ii", "unisonUpdateForIgnore", [reconItems indexOfObjectIdenticalTo:item]);
 	NSLog(@"Updating for ignore...");
     [self updateReconItems:(OCamlValue *)ocamlCall("@", "unisonState")];
     return [reconItems objectAtIndex:j];
@@ -721,10 +728,12 @@
 // A function called from ocaml
 CAMLprim value displayStatus(value s)
 {
+  id pool = [[NSAutoreleasePool alloc] init];
 	NSString *str = [[NSString alloc] initWithUTF8String:String_val(s)];
     // NSLog(@"displayStatus: %@", str);
     [me performSelectorOnMainThread:@selector(statusTextSet:) withObject:str waitUntilDone:FALSE];
 	[str release];
+  [pool release];
     return Val_unit;
 }
 
@@ -738,31 +747,36 @@
 // Called from ocaml to dislpay progress bar
 CAMLprim value displayGlobalProgress(value p)
 {
+  id pool = [[NSAutoreleasePool alloc] init];
 	NSNumber *num = [[NSNumber alloc] initWithDouble:Double_val(p)];
     [me performSelectorOnMainThread:@selector(updateProgressBar:) 
 		withObject:num waitUntilDone:FALSE]; 
 	[num release];
+  [pool release];
     return Val_unit;
 }
 
 // Called from ocaml to display diff
 CAMLprim value displayDiff(value s, value s2)
 {
+  id pool = [[NSAutoreleasePool alloc] init];
     [me performSelectorOnMainThread:@selector(diffViewTextSet:) 
 						withObject:[NSArray arrayWithObjects:[NSString stringWithUTF8String:String_val(s)],
 											[NSString stringWithUTF8String:String_val(s2)], nil]
 						waitUntilDone:FALSE]; 
+  [pool release];
     return Val_unit;
 }
 
 // Called from ocaml to display diff error messages
 CAMLprim value displayDiffErr(value s)
 {
+  id pool = [[NSAutoreleasePool alloc] init];
     NSString * str = [NSString stringWithUTF8String:String_val(s)];
-    str = [[str componentsSeparatedByString:@"\n"] 
-        componentsJoinedByString:@" "];
+  str = [[str componentsSeparatedByString:@"\n"] componentsJoinedByString:@" "];
 	[me->statusText performSelectorOnMainThread:@selector(setStringValue:) 
 				withObject:str waitUntilDone:FALSE]; 
+  [pool release];
     return Val_unit;
 }
 

Modified: trunk/src/uimacnew/ProfileController.m
===================================================================
--- trunk/src/uimacnew/ProfileController.m	2010-01-10 15:30:18 UTC (rev 399)
+++ trunk/src/uimacnew/ProfileController.m	2010-01-10 22:52:59 UTC (rev 400)
@@ -13,7 +13,11 @@
 - (void)initProfiles
 {
     NSString *directory = unisonDirectory();
+#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
     NSArray *files = [[NSFileManager defaultManager] directoryContentsAtPath:directory];
+#else
+    NSArray *files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:directory error:nil];
+#endif
     unsigned int count = [files count];
     unsigned int i,j;
     
@@ -31,7 +35,7 @@
         }
     }
     if (j > 0)
-        [tableView selectRow:0 byExtendingSelection:NO];
+        [tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:0] byExtendingSelection:NO];
 }
 
 - (void)awakeFromNib
@@ -39,7 +43,7 @@
     // start with the default profile selected
     [self initProfiles];
     if (defaultIndex >= 0)
-        [tableView selectRow:defaultIndex byExtendingSelection:NO];
+        [tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:defaultIndex] byExtendingSelection:NO];
     // on awake the scroll bar is inactive, but after adding profiles we might need it;
     // reloadData makes it happen.  Q: is setNeedsDisplay more efficient?
     [tableView reloadData];

Modified: trunk/src/uimacnew/ReconItem.h
===================================================================
--- trunk/src/uimacnew/ReconItem.h	2010-01-10 15:30:18 UTC (rev 399)
+++ trunk/src/uimacnew/ReconItem.h	2010-01-10 22:52:59 UTC (rev 400)
@@ -12,8 +12,8 @@
     BOOL selected;
     NSImage *direction;
     NSString *directionSortString;
-	int fileSize;
-	int bytesTransferred;
+    double fileSize;
+    double bytesTransferred;
     BOOL resolved;
 }
 - (BOOL)selected;
@@ -24,10 +24,10 @@
 - (NSString *)right;
 - (NSImage *)direction;
 - (NSImage *)fileIcon;
-- (int)fileCount;
-- (int)fileSize;
+- (long)fileCount;
+- (double)fileSize;
 - (NSString *)fileSizeString;
-- (int)bytesTransferred;
+- (double)bytesTransferred;
 - (NSString *)bytesTransferredString;
 - (void)setDirection:(char *)d;
 - (void) doAction:(unichar)action;
@@ -64,15 +64,15 @@
     NSString *progress;
     NSString *details;
     OCamlValue *ri; // an ocaml Common.reconItem
-    int index; // index in Ri list
+    long index; // index in Ri list
 }
-- initWithRiAndIndex:(OCamlValue *)v index:(int)i;
+- initWithRiAndIndex:(OCamlValue *)v index:(long)i;
 @end
 
 @interface ParentReconItem : ReconItem
 {
 	NSMutableArray *_children;
-	int fileCount;
+	long fileCount;
 }
 - (void)addChild:(ReconItem *)item nested:(BOOL)useNesting;
 - (void)sortUsingDescriptors:(NSArray *)sortDescriptors;

Modified: trunk/src/uimacnew/ReconItem.m
===================================================================
--- trunk/src/uimacnew/ReconItem.m	2010-01-10 15:30:18 UTC (rev 399)
+++ trunk/src/uimacnew/ReconItem.m	2010-01-10 22:52:59 UTC (rev 400)
@@ -9,8 +9,8 @@
 	[super init];
 	selected = NO; // NB only used/updated during sorts. Not a 
 				   // reliable indicator of whether item is selected
-	fileSize = -1;
-	bytesTransferred = -1;
+	fileSize = -1.;
+	bytesTransferred = -1.;
 	return self;
 }
 
@@ -129,30 +129,29 @@
 }
 
 
-- (int)computeFileSize
+- (double)computeFileSize
 {
-	return 0;
+	return 0.;
 }
 
-- (int)bytesTransferred
+- (double)bytesTransferred
 {
-	return 0;
+	return 0.;
 }
 
-- (int)fileCount
+- (long)fileCount
 {
 	return 1;
 }
 
-- (int)fileSize
+- (double)fileSize
 {
-	if (fileSize == -1) fileSize = [self computeFileSize];
+	if (fileSize == -1.) fileSize = [self computeFileSize];
 	return fileSize;
 }
 
-- (NSString *)formatFileSize:(int)intSize
+- (NSString *)formatFileSize:(double)size
 {
-	float size = (float)intSize;
 	if (size == 0) return @"--";
 	if (size < 1024) return @"< 1KB"; // return [NSString stringWithFormat:@"%i bytes", size];
 	size /= 1024;
@@ -175,8 +174,8 @@
 
 - (NSNumber *)percentTransferred
 {
-	int size = [self computeFileSize];
-	return (size > 0) ? [NSNumber numberWithFloat:(((float)[self bytesTransferred]) / (float)size) * 100.0]
+	double size = [self computeFileSize];
+	return (size > 0) ? [NSNumber numberWithDouble:([self bytesTransferred] / (size) * 100.0)]
 					  : nil;
 }
 
@@ -379,8 +378,8 @@
 
 - (BOOL)transferInProgress
 {
-	int soFar = [self bytesTransferred];
-	return (soFar > 0) && (soFar != [self fileSize]);
+	double soFar = [self bytesTransferred];
+	return (soFar > 0) && (soFar < [self fileSize]);
 }
 
 - (void)resetProgress
@@ -390,7 +389,7 @@
 - (NSString *)progressString
 {
 	NSString *progress = [self progress];
-	if ([progress length] == 0 || [progress hasSuffix:@"%"])
+	if ([progress length] == 0. || [progress hasSuffix:@"%"])
 		progress = [self transferInProgress] ? [self bytesTransferredString] : @"";
 	else if ([progress isEqual:@"done"]) progress = @"";
 	return progress;
@@ -443,7 +442,7 @@
 // --- Leaf items -- actually corresponding to ReconItems in OCaml
 @implementation LeafReconItem
 
-- initWithRiAndIndex:(OCamlValue *)v index:(int)i
+- initWithRiAndIndex:(OCamlValue *)v index:(long)i
 {
     [super init];
     ri = [v retain];
@@ -482,17 +481,17 @@
 	return right;
 }
 
-- (int)computeFileSize
+- (double)computeFileSize
 {
-	return (int)ocamlCall("i@", "unisonRiToFileSize", ri);
+  return [(NSNumber *)ocamlCall("N@", "unisonRiToFileSize", ri) doubleValue];
 }
 
-- (int)bytesTransferred
+- (double)bytesTransferred
 {
-	if (bytesTransferred == -1) {
+	if (bytesTransferred == -1.) {
 		// need to force to fileSize if done, otherwise may not match up to 100%
 		bytesTransferred = ([[self progress] isEqual:@"done"]) ? [self fileSize]
-			: (int)ocamlCall("i@", "unisonRiToBytesTransferred", ri);
+                  : [(NSNumber*)ocamlCall("N@", "unisonRiToBytesTransferred", ri) doubleValue];
 	}
 	return bytesTransferred;
 }
@@ -535,7 +534,7 @@
 {
     // Get rid of the memoized progress because we expect it to change
 	[self willChange];
-	bytesTransferred = -1;
+	bytesTransferred = -1.;
     [progress release];
 	
 	// Force update now so we get the result while the OCaml thread is available
@@ -559,12 +558,12 @@
 
 - (BOOL)isConflict
 {
-	return ((int)ocamlCall("i@", "unisonRiIsConflict", ri) ? YES : NO);
+	return ((long)ocamlCall("i@", "unisonRiIsConflict", ri) ? YES : NO);
 }
 
 - (BOOL)changedFromDefault
 {
-	return ((int)ocamlCall("i@", "changedFromDefault", ri) ? YES : NO);
+	return ((long)ocamlCall("i@", "changedFromDefault", ri) ? YES : NO);
 }
 
 - (void)revertDirection
@@ -575,7 +574,7 @@
 
 - (BOOL)canDiff
 {
-	return ((int)ocamlCall("i@", "canDiff", ri) ? YES : NO);
+	return ((long)ocamlCall("i@", "canDiff", ri) ? YES : NO);
 }
 
 - (void)showDiffs
@@ -715,7 +714,7 @@
 	// [directionSortString autorelease]; 
 	direction = nil;
 	directionSortString = nil;
-	bytesTransferred = -1;
+	bytesTransferred = -1.;
 	// fileSize = -1;
     // resolved = NO;
 
@@ -748,7 +747,7 @@
 }
 
 // Rollup methods
-- (int)fileCount
+- (long)fileCount
 {
 	if (fileCount == 0) {
 		int i = [_children count];
@@ -760,9 +759,9 @@
 	return fileCount;
 }
 
-- (int)computeFileSize
+- (double)computeFileSize
 {
-	int size = 0;
+	double size = 0;
 	int i = [_children count];
 	while (i--) {
 		ReconItem *child = [_children objectAtIndex:i];
@@ -771,10 +770,10 @@
 	return size;
 }
 
-- (int)bytesTransferred
+- (double)bytesTransferred
 {
-	if (bytesTransferred == -1) {
-		bytesTransferred = 0;
+	if (bytesTransferred == -1.) {
+		bytesTransferred = 0.;
 		int i = [_children count];
 		while (i--) {
 			ReconItem *child = [_children objectAtIndex:i];

Modified: trunk/src/uimacnew/ReconTableView.m
===================================================================
--- trunk/src/uimacnew/ReconTableView.m	2010-01-10 15:30:18 UTC (rev 399)
+++ trunk/src/uimacnew/ReconTableView.m	2010-01-10 22:52:59 UTC (rev 400)
@@ -11,12 +11,16 @@
 #import "MyController.h"
 
 @implementation NSOutlineView (_UnisonExtras)
+
 - (NSArray *)selectedObjects
 {
 	NSMutableArray *result = [NSMutableArray array];
-	NSEnumerator *e = [self selectedRowEnumerator];
-    NSNumber *n;
-    while (n = [e nextObject]) [result addObject:[self itemAtRow:[n intValue]]]; 
+  NSIndexSet *set = [self selectedRowIndexes];
+  NSUInteger index = [set firstIndex];
+  while (index != NSNotFound) {
+    [result addObject:[self itemAtRow:index]];
+    index = [set indexGreaterThanIndex: index];
+  }
 	return result;
 }
 
@@ -136,8 +140,9 @@
 		last = item;
     }
     if (last) { // something was selected
-        last = [[self dataSource] updateForIgnore:last];
-        [self selectRow:[self rowForItem:last] byExtendingSelection:NO];
+        MyController* controller = (MyController*) [self dataSource];
+        last = [controller updateForIgnore:last];
+        [self selectRowIndexes:[NSIndexSet indexSetWithIndex:[self rowForItem:last]] byExtendingSelection:NO];
         [self reloadData];
     }
 }
@@ -171,7 +176,7 @@
 		int nextRow = [self rowForItem:last] + 1;
         if (numSelected == 1 && [self numberOfRows] > nextRow && c!='d') {
             // Move to next row, unless already at last row, or if more than one row selected
-            [self selectRow:nextRow byExtendingSelection:NO];
+            [self selectRowIndexes:[NSIndexSet indexSetWithIndex:nextRow] byExtendingSelection:NO];
             [self scrollRowToVisible:nextRow];
         }
         [self reloadData];
@@ -206,12 +211,13 @@
 - (IBAction)selectConflicts:(id)sender
 {
     [self deselectAll:self];
-    NSMutableArray *reconItems = [[self dataSource] reconItems];
+    MyController* controller = (MyController*) [self dataSource];
+    NSMutableArray *reconItems = [controller reconItems];
     int i = 0;
     for (; i < [reconItems count]; i++) {
 		ReconItem *item = [reconItems objectAtIndex:i]; 
         if ([item isConflict])
-            [self selectRow:[self rowForItem:item] byExtendingSelection:YES];
+            [self selectRowIndexes:[NSIndexSet indexSetWithIndex:[self rowForItem:item]] byExtendingSelection:YES];
     }
 }
 

Modified: trunk/src/uimacnew/UnisonToolbar.h
===================================================================
--- trunk/src/uimacnew/UnisonToolbar.h	2010-01-10 15:30:18 UTC (rev 399)
+++ trunk/src/uimacnew/UnisonToolbar.h	2010-01-10 22:52:59 UTC (rev 400)
@@ -12,6 +12,9 @@
 @class ReconTableView, MyController;
 
 @interface UnisonToolbar : NSToolbar
+#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060)
+  <NSToolbarDelegate>
+#endif
 {
 	ReconTableView*  tableView;
 	MyController*    myController;

Modified: trunk/src/uimacnew/main.m
===================================================================
--- trunk/src/uimacnew/main.m	2010-01-10 15:30:18 UTC (rev 399)
+++ trunk/src/uimacnew/main.m	2010-01-10 22:52:59 UTC (rev 400)
@@ -11,6 +11,7 @@
 
 int main(int argc, const char *argv[])
 {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
     int i;
     
     /* When you click-start or use the open command, the program is invoked with
@@ -34,22 +35,19 @@
             !strcmp(argv[i],"-server") ||
             !strcmp(argv[i],"-socket") ||
             !strcmp(argv[i],"-ui")) {
-            /* We install an autorelease pool here because there might be callbacks
-               from ocaml to objc code */
 			NSLog(@"Calling nonGuiStartup");
-            NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 			@try {
 				ocamlCall("x", "unisonNonGuiStartup");
 			} @catch (NSException *ex) {
 				NSLog(@"Uncaught exception: %@", [ex reason]);
 				exit(1);
 			}
-            [pool release];
             /* If we get here without exiting first, the non GUI startup detected a
                -ui graphic or command-line profile, and we should in fact start the GUI. */
         }
     }
 	
 	/* go! */
+    [pool release];
     return NSApplicationMain(argc, argv);
 }

Modified: trunk/src/uimacnew09/Bridge.h
===================================================================
--- trunk/src/uimacnew09/Bridge.h	2010-01-10 15:30:18 UTC (rev 399)
+++ trunk/src/uimacnew09/Bridge.h	2010-01-10 22:52:59 UTC (rev 400)
@@ -24,14 +24,14 @@
 	Args/return values are converted to/from C/OCaml according to the
 	supplied type signture string.  Type codes are:
 		x	- void (for return type)
-		i	- int
+		i	- long
 		s	- char *
 		S	- NSString *
+                N       - NSNumber *
 		@	- OCamlValue (see below)
-		v	- unwrapped OCaml value (deprecated -- unsafe!)
 		
 	Examples:
-		int count = (int)ocamlCall("iS", "lengthOfString", @"Some String");
+		long count = (long)ocamlCall("iS", "lengthOfString", @"Some String");
 		
 		(void)ocamlCall("x", "someVoidOCamlFunction");
 		
@@ -42,17 +42,17 @@
 
 // Wrapper/proxy for unconverted OCaml values
 @interface OCamlValue : NSObject {
-	int _v;
+	long _v;
 }
-- initWithValue:(int)v;
+- initWithValue:(long)v;
 
-- (void *)getField:(int)i withType:(char)t;
+- (void *)getField:(long)i withType:(char)t;
 	// get value by position.  See ocamlCall for list of type conversion codes
 	
-- (int)count;
+- (long)count;
 	// count of items in array
 	
-- (int)value;
+- (long)value;
 	// returns Ocaml value directly -- not safe to use except in direct callback from OCaml
 	// (i.e. in the OCaml thread)
 @end

Modified: trunk/src/uimacnew09/Bridge.m
===================================================================
--- trunk/src/uimacnew09/Bridge.m	2010-01-10 15:30:18 UTC (rev 399)
+++ trunk/src/uimacnew09/Bridge.m	2010-01-10 22:52:59 UTC (rev 400)
@@ -95,7 +95,10 @@
 	// NSLog(@"*** caml_init complete!");
 }
 
-- (BOOL)exceptionHandler:(NSExceptionHandler *)sender shouldLogException:(NSException *)exception mask:(unsigned int)aMask
+#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
+typedef unsigned int NSUInteger;
+#endif
+- (BOOL)exceptionHandler:(NSExceptionHandler *)sender shouldLogException:(NSException *)exception mask:(NSUInteger)aMask
 {
 	// if (![[exception name] isEqual:@"OCamlException"]) return YES;
 	
@@ -121,7 +124,7 @@
 
 	// Field access
 	value *valueP;
-	int fieldIndex;
+	long fieldIndex;
 	char fieldType;
 	
 	// Return values
@@ -139,9 +142,11 @@
 
 // Our OCaml callback server thread -- waits for call then makes them
 // Called from thread spawned from OCaml
-CAMLprim value bridgeThreadWait(int ignore)
+CAMLprim value bridgeThreadWait(value ignore)
 {
-	value args[10];
+        CAMLparam0();
+        CAMLlocal1 (args);
+        args = caml_alloc_tuple(3);
 	
 	// NSLog(@"*** bridgeThreadWait init!  (%d) Taking lock...", pthread_self());
 	while (TRUE) {
@@ -168,6 +173,7 @@
 		char retType = 'v';
 		value e = Val_unit;
 		if (cs->opCode == SafeCall) {
+                        int i;
 			char *fname = va_arg(cs->args, char *);
 			value *f = caml_named_value(fname);
 			// varargs with C-based args -- convert them to OCaml values based on type code string
@@ -179,33 +185,31 @@
 				switch (*p) {
 					case 's':
 						str = va_arg(cs->args, const char *);
-						args[argCount] = caml_copy_string(str);
+						Store_field (args, argCount, caml_copy_string(str));
 						break;
 					case 'S':
 						str = [va_arg(cs->args, NSString *) UTF8String];
-						args[argCount] = caml_copy_string(str);
+						Store_field (args, argCount, caml_copy_string(str));
 						break;
-					case 'n':
-						// leak?
-						args[argCount] = *caml_named_value(va_arg(cs->args, char *));
-						break;
 					case 'i':
-						args[argCount] = Val_int(va_arg(cs->args, int));
+                                                Store_field (args, argCount, Val_long(va_arg(cs->args, long)));
 						break;
-					case 'v':
-						args[argCount] = va_arg(cs->args, value);
-						break;
 					case '@':
-						args[argCount] = [va_arg(cs->args, OCamlValue *) value];
+                                                Store_field (args, argCount, [va_arg(cs->args, OCamlValue *) value]);
 						break;
+                                        default:
+                                                NSCAssert1(0, @"Unknown input type '%c'", *p);
+						break;
 				}
 				argCount++;
+                                NSCAssert(argCount <= 3, @"More than 3 arguments");
 			}
 			// Call OCaml -- TODO: add support for > 3 args
-			if (argCount == 3) e = caml_callback3_exn(*f,args[0],args[1],args[2]);
-			else if (argCount == 2) e = caml_callback2_exn(*f,args[0],args[1]);
-			else if (argCount == 1) e = caml_callback_exn(*f,args[0]);
+			if (argCount == 3) e = caml_callback3_exn(*f,Field(args,0),Field(args,1),Field(args,2));
+			else if (argCount == 2) e = caml_callback2_exn(*f,Field(args,0),Field(args,1));
+			else if (argCount == 1) e = caml_callback_exn(*f,Field(args,0));
 			else e = caml_callback_exn(*f,Val_unit);			
+                        for (i = 0; i < argCount; i++) Store_field (args, i, Val_unit);
 		} else if (cs->opCode == OldCall) {
 			// old style (unsafe) version where OCaml values were passed directly from C thread
 			if (cs->argCount == 3) e = caml_callback3_exn(cs->call,cs->a1,cs->a2,cs->a3);
@@ -213,8 +217,8 @@
 			else e = caml_callback_exn(cs->call,cs->a1);
 			retType = 'v';
 		} else if (cs->opCode == FieldAccess) {
-			int index = cs->fieldIndex;
-			e = (index == -1) ? Val_int(Wosize_val(*cs->valueP)) : Field(*cs->valueP, cs->fieldIndex);
+			long index = cs->fieldIndex;
+			e = (index == -1) ? Val_long(Wosize_val(*cs->valueP)) : Field(*cs->valueP, index);
 			retType = cs->fieldType;
 		}
 		
@@ -223,30 +227,38 @@
 		cs->ret = e; // OCaml return type -- unsafe...
 		if (!Is_exception_result(e)) {
 			switch (retType) {
-				case 's':
-					*((char **)&cs->retV) = (e == Val_unit) ? NULL : String_val(e);
-					break;
 				case 'S':
 					*((NSString **)&cs->retV) = (e == Val_unit) ? NULL : [[NSString alloc] initWithUTF8String:String_val(e)];
 					cs->_autorelease = TRUE;
 					break;
+				case 'N':
+                                        if (Is_long (e)) {
+					        *((NSNumber **)&cs->retV) = [[NSNumber alloc] initWithLong:Long_val(e)];
+                                        } else {
+					        *((NSNumber **)&cs->retV) = [[NSNumber alloc] initWithDouble:Double_val(e)];
+                                        }
+					cs->_autorelease = TRUE;
+					break;
 				case '@':
 					*((NSObject **)&cs->retV) = (e == Val_unit) ? NULL : [[OCamlValue alloc] initWithValue:e];
 					cs->_autorelease = TRUE;
 					break;
-				case 'v':
-					*((value *)&cs->retV) = e;
-					break;
 				case 'i':
-					*((int *)&cs->retV) = Int_val(e);
+					*((long *)&cs->retV) = Long_val(e);
 					break;
+				case 'x':
+                                        break;
+                                default:
+                                        NSCAssert1(0, @"Unknown return type '%c'", retType);
+                                        break;
 			}
 		}
 
 		if (Is_exception_result(e)) {
 			// get exception string -- it will get thrown back in the calling thread
 		    value *f = caml_named_value("unisonExnInfo");
-			cs->exception = String_val(caml_callback(*f,Extract_exception(e)));
+                    // We leak memory here...
+                    cs->exception = strdup(String_val(caml_callback(*f,Extract_exception(e))));
 		}
 		
  	    [pool release];
@@ -260,7 +272,7 @@
 		pthread_mutex_unlock(&global_res_lock);
 	}
 	// Never get here...
-    return Val_unit;
+        CAMLreturn (Val_unit);
 }
 
 void *_passCall(CallState *cs)
@@ -292,20 +304,18 @@
 
 void *ocamlCall(const char *argTypes, ...)
 {
-	va_list ap;
-	va_start(ap, argTypes);
 	CallState cs;
 	cs.opCode = SafeCall;
 	cs.exception = NULL;
 	cs.argTypes = argTypes;
-	cs.args = ap;
+	va_start(cs.args, argTypes);
 	void * res = _passCall(&cs);
 	
-	va_end(ap);
+	va_end(cs.args);
 	return res;
 }
 
-void *getField(value *vP, int index, char type)
+void *getField(value *vP, long index, char type)
 {
 	CallState cs;
 	cs.opCode = FieldAccess;
@@ -318,7 +328,7 @@
 
 @implementation OCamlValue
 
-- initWithValue:(int)v
+- initWithValue:(long)v
 {
 	[super init];
 	_v = v;
@@ -326,17 +336,17 @@
 	return self;
 }
 
-- (int)count
+- (long)count
 {
-	return (int)getField((value *)&_v, -1, 'i');
+        return (long)getField((value *) &_v, -1, 'i');
 }
 
-- (void *)getField:(int)i withType:(char)t
+- (void *)getField:(long)i withType:(char)t
 {
-	return getField((value *)&_v, i, t);
+        return getField((value *)&_v, i, t);
 }
 
-- (int)value 
+- (long)value
 {
 	// Unsafe to use!
 	return _v;

Modified: trunk/src/uimacnew09/ImageAndTextCell.m
===================================================================
--- trunk/src/uimacnew09/ImageAndTextCell.m	2010-01-10 15:30:18 UTC (rev 399)
+++ trunk/src/uimacnew09/ImageAndTextCell.m	2010-01-10 22:52:59 UTC (rev 400)
@@ -88,7 +88,10 @@
     [super editWithFrame: textFrame inView: controlView editor:textObj delegate:anObject event: theEvent];
 }
 
-- (void)selectWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)anObject start:(int)selStart length:(int)selLength {
+#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
+typedef int NSInteger;
+#endif
+- (void)selectWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)anObject start:(NSInteger)selStart length:(NSInteger)selLength {
     NSRect textFrame, imageFrame;
     NSDivideRect (aRect, &imageFrame, &textFrame, 3 + [image size].width, NSMinXEdge);
     [super selectWithFrame: textFrame inView: controlView editor:textObj delegate:anObject start:selStart length:selLength];

Modified: trunk/src/uimacnew09/MyController.m
===================================================================
--- trunk/src/uimacnew09/MyController.m	2010-01-10 15:30:18 UTC (rev 399)
+++ trunk/src/uimacnew09/MyController.m	2010-01-10 22:52:59 UTC (rev 400)
@@ -395,7 +395,7 @@
 {
     // FIX: some prompts don't ask for password, need to look at it
     NSLog(@"Got the prompt: '%@'",prompt);
-    if ((int)ocamlCall("iS", "unisonPasswordMsg", prompt)) {
+    if ((long)ocamlCall("iS", "unisonPasswordMsg", prompt)) {
         [passwordPrompt setStringValue:@"Please enter your password"];
         [NSApp beginSheet:passwordWindow
             modalForWindow:mainWindow
@@ -404,7 +404,7 @@
             contextInfo:nil];
         return;
     }
-    if ((int)ocamlCall("iS", "unisonPassphraseMsg", prompt)) {
+    if ((long)ocamlCall("iS", "unisonPassphraseMsg", prompt)) {
         [passwordPrompt setStringValue:@"Please enter your passphrase"];
         [NSApp beginSheet:passwordWindow
             modalForWindow:mainWindow
@@ -413,7 +413,7 @@
             contextInfo:nil];
         return;
     }
-    if ((int)ocamlCall("iS", "unisonAuthenticityMsg", prompt)) {
+    if ((long)ocamlCall("iS", "unisonAuthenticityMsg", prompt)) {
         int i = NSRunAlertPanel(@"New host",prompt,@"Yes",@"No",nil);
         if (i == NSAlertDefaultReturn) {
 			ocamlCall("x at s", "openConnectionReply", preconn, "yes");
@@ -649,9 +649,9 @@
 		[(ImageAndTextCell*)cell setImage:[item fileIcon]];
 		
 		// For parents, format the file count into the text
-		int fileCount = [item fileCount];
+		long fileCount = [item fileCount];
 		if (fileCount > 1) {
-			NSString *countString = [NSString stringWithFormat:@"  (%i files)", fileCount];
+			NSString *countString = [NSString stringWithFormat:@"  (%ld files)", fileCount];
 			NSString *fullString = [(NSString *)[cell objectValue] stringByAppendingString:countString];
 			NSMutableAttributedString *as = [[NSMutableAttributedString alloc] initWithString:fullString];
 
@@ -716,7 +716,7 @@
 {
     [reconItems release];
     reconItems = [[NSMutableArray alloc] init];
-	int i, n =[caml_reconItems count];
+	long i, n =[caml_reconItems count];
     for (i=0; i<n; i++) {
 		LeafReconItem *item = [[LeafReconItem alloc] initWithRiAndIndex:(id)[caml_reconItems getField:i withType:'@'] index:i];
         [reconItems addObject:item];
@@ -805,7 +805,7 @@
 
 - (id)updateForIgnore:(id)item
 {
-    int j = (int)ocamlCall("ii", "unisonUpdateForIgnore", [reconItems indexOfObjectIdenticalTo:item]);
+    long j = (long)ocamlCall("ii", "unisonUpdateForIgnore", [reconItems indexOfObjectIdenticalTo:item]);
 	NSLog(@"Updating for ignore...");
     [self updateReconItems:(OCamlValue *)ocamlCall("@", "unisonState")];
     return [reconItems objectAtIndex:j];

Modified: trunk/src/uimacnew09/ProfileController.m
===================================================================
--- trunk/src/uimacnew09/ProfileController.m	2010-01-10 15:30:18 UTC (rev 399)
+++ trunk/src/uimacnew09/ProfileController.m	2010-01-10 22:52:59 UTC (rev 400)
@@ -13,7 +13,11 @@
 - (void)initProfiles
 {
     NSString *directory = unisonDirectory();
+#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
+    NSArray *files = [[NSFileManager defaultManager] directoryContentsAtPath:directory];
+#else
     NSArray *files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:directory error:nil];
+#endif
     unsigned int count = [files count];
     unsigned int i,j;
     

Modified: trunk/src/uimacnew09/ReconItem.h
===================================================================
--- trunk/src/uimacnew09/ReconItem.h	2010-01-10 15:30:18 UTC (rev 399)
+++ trunk/src/uimacnew09/ReconItem.h	2010-01-10 22:52:59 UTC (rev 400)
@@ -12,8 +12,8 @@
     BOOL selected;
     NSImage *direction;
     NSString *directionSortString;
-	int fileSize;
-	int bytesTransferred;
+    double fileSize;
+    double bytesTransferred;
     BOOL resolved;
 }
 - (BOOL)selected;
@@ -24,10 +24,10 @@
 - (NSString *)right;
 - (NSImage *)direction;
 - (NSImage *)fileIcon;
-- (int)fileCount;
-- (int)fileSize;
+- (long)fileCount;
+- (double)fileSize;
 - (NSString *)fileSizeString;
-- (int)bytesTransferred;
+- (double)bytesTransferred;
 - (NSString *)bytesTransferredString;
 - (void)setDirection:(char *)d;
 - (void) doAction:(unichar)action;
@@ -64,15 +64,15 @@
     NSString *progress;
     NSString *details;
     OCamlValue *ri; // an ocaml Common.reconItem
-    int index; // index in Ri list
+    long index; // index in Ri list
 }
-- initWithRiAndIndex:(OCamlValue *)v index:(int)i;
+- initWithRiAndIndex:(OCamlValue *)v index:(long)i;
 @end
 
 @interface ParentReconItem : ReconItem
 {
 	NSMutableArray *_children;
-	int fileCount;
+	long fileCount;
 }
 - (void)addChild:(ReconItem *)item nested:(BOOL)useNesting;
 - (void)sortUsingDescriptors:(NSArray *)sortDescriptors;

Modified: trunk/src/uimacnew09/ReconItem.m
===================================================================
--- trunk/src/uimacnew09/ReconItem.m	2010-01-10 15:30:18 UTC (rev 399)
+++ trunk/src/uimacnew09/ReconItem.m	2010-01-10 22:52:59 UTC (rev 400)
@@ -9,8 +9,8 @@
 	[super init];
 	selected = NO; // NB only used/updated during sorts. Not a 
 				   // reliable indicator of whether item is selected
-	fileSize = -1;
-	bytesTransferred = -1;
+	fileSize = -1.;
+	bytesTransferred = -1.;
 	return self;
 }
 
@@ -129,30 +129,29 @@
 }
 
 
-- (int)computeFileSize
+- (double)computeFileSize
 {
-	return 0;
+	return 0.;
 }
 
-- (int)bytesTransferred
+- (double)bytesTransferred
 {
-	return 0;
+	return 0.;
 }
 
-- (int)fileCount
+- (long)fileCount
 {
 	return 1;
 }
 
-- (int)fileSize
+- (double)fileSize
 {
-	if (fileSize == -1) fileSize = [self computeFileSize];
+	if (fileSize == -1.) fileSize = [self computeFileSize];
 	return fileSize;
 }
 
-- (NSString *)formatFileSize:(int)intSize
+- (NSString *)formatFileSize:(double)size
 {
-	float size = (float)intSize;
 	if (size == 0) return @"--";
 	if (size < 1024) return @"< 1KB"; // return [NSString stringWithFormat:@"%i bytes", size];
 	size /= 1024;
@@ -175,8 +174,8 @@
 
 - (NSNumber *)percentTransferred
 {
-	int size = [self computeFileSize];
-	return (size > 0) ? [NSNumber numberWithFloat:(((float)[self bytesTransferred]) / (float)size) * 100.0]
+	double size = [self computeFileSize];
+	return (size > 0) ? [NSNumber numberWithDouble:([self bytesTransferred] / (size) * 100.0)]
 					  : nil;
 }
 
@@ -379,8 +378,8 @@
 
 - (BOOL)transferInProgress
 {
-	int soFar = [self bytesTransferred];
-	return (soFar > 0) && (soFar != [self fileSize]);
+	double soFar = [self bytesTransferred];
+	return (soFar > 0) && (soFar < [self fileSize]);
 }
 
 - (void)resetProgress
@@ -390,7 +389,7 @@
 - (NSString *)progressString
 {
 	NSString *progress = [self progress];
-	if ([progress length] == 0 || [progress hasSuffix:@"%"])
+	if ([progress length] == 0. || [progress hasSuffix:@"%"])
 		progress = [self transferInProgress] ? [self bytesTransferredString] : @"";
 	else if ([progress isEqual:@"done"]) progress = @"";
 	return progress;
@@ -443,7 +442,7 @@
 // --- Leaf items -- actually corresponding to ReconItems in OCaml
 @implementation LeafReconItem
 
-- initWithRiAndIndex:(OCamlValue *)v index:(int)i
+- initWithRiAndIndex:(OCamlValue *)v index:(long)i
 {
     [super init];
     ri = [v retain];
@@ -482,17 +481,17 @@
 	return right;
 }
 
-- (int)computeFileSize
+- (double)computeFileSize
 {
-	return (int)ocamlCall("i@", "unisonRiToFileSize", ri);
+  return [(NSNumber *)ocamlCall("N@", "unisonRiToFileSize", ri) doubleValue];
 }
 
-- (int)bytesTransferred
+- (double)bytesTransferred
 {
-	if (bytesTransferred == -1) {
+	if (bytesTransferred == -1.) {
 		// need to force to fileSize if done, otherwise may not match up to 100%
 		bytesTransferred = ([[self progress] isEqual:@"done"]) ? [self fileSize]
-			: (int)ocamlCall("i@", "unisonRiToBytesTransferred", ri);
+                  : [(NSNumber*)ocamlCall("N@", "unisonRiToBytesTransferred", ri) doubleValue];
 	}
 	return bytesTransferred;
 }
@@ -535,7 +534,7 @@
 {
     // Get rid of the memoized progress because we expect it to change
 	[self willChange];
-	bytesTransferred = -1;
+	bytesTransferred = -1.;
     [progress release];
 	
 	// Force update now so we get the result while the OCaml thread is available
@@ -559,12 +558,12 @@
 
 - (BOOL)isConflict
 {
-	return ((int)ocamlCall("i@", "unisonRiIsConflict", ri) ? YES : NO);
+	return ((long)ocamlCall("i@", "unisonRiIsConflict", ri) ? YES : NO);
 }
 
 - (BOOL)changedFromDefault
 {
-	return ((int)ocamlCall("i@", "changedFromDefault", ri) ? YES : NO);
+	return ((long)ocamlCall("i@", "changedFromDefault", ri) ? YES : NO);
 }
 
 - (void)revertDirection
@@ -575,7 +574,7 @@
 
 - (BOOL)canDiff
 {
-	return ((int)ocamlCall("i@", "canDiff", ri) ? YES : NO);
+	return ((long)ocamlCall("i@", "canDiff", ri) ? YES : NO);
 }
 
 - (void)showDiffs
@@ -715,7 +714,7 @@
 	// [directionSortString autorelease]; 
 	direction = nil;
 	directionSortString = nil;
-	bytesTransferred = -1;
+	bytesTransferred = -1.;
 	// fileSize = -1;
     // resolved = NO;
 
@@ -748,7 +747,7 @@
 }
 
 // Rollup methods
-- (int)fileCount
+- (long)fileCount
 {
 	if (fileCount == 0) {
 		int i = [_children count];
@@ -760,9 +759,9 @@
 	return fileCount;
 }
 
-- (int)computeFileSize
+- (double)computeFileSize
 {
-	int size = 0;
+	double size = 0;
 	int i = [_children count];
 	while (i--) {
 		ReconItem *child = [_children objectAtIndex:i];
@@ -771,10 +770,10 @@
 	return size;
 }
 
-- (int)bytesTransferred
+- (double)bytesTransferred
 {
-	if (bytesTransferred == -1) {
-		bytesTransferred = 0;
+	if (bytesTransferred == -1.) {
+		bytesTransferred = 0.;
 		int i = [_children count];
 		while (i--) {
 			ReconItem *child = [_children objectAtIndex:i];

Modified: trunk/src/uimacnew09/main.m
===================================================================
--- trunk/src/uimacnew09/main.m	2010-01-10 15:30:18 UTC (rev 399)
+++ trunk/src/uimacnew09/main.m	2010-01-10 22:52:59 UTC (rev 400)
@@ -11,7 +11,7 @@
 
 int main(int argc, const char *argv[])
 {
-  id pool = [[NSAutoreleasePool alloc] init];
+  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
   int i;
     
   /* When you click-start or use the open command, the program is invoked with
@@ -35,17 +35,13 @@
         !strcmp(argv[i],"-server") ||
         !strcmp(argv[i],"-socket") ||
         !strcmp(argv[i],"-ui")) {
-      /* We install an autorelease pool here because there might be callbacks
-       from ocaml to objc code */
 			NSLog(@"Calling nonGuiStartup");
-      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 			@try {
 				ocamlCall("x", "unisonNonGuiStartup");
 			} @catch (NSException *ex) {
 				NSLog(@"Uncaught exception: %@", [ex reason]);
 				exit(1);
 			}
-      [pool release];
       /* If we get here without exiting first, the non GUI startup detected a
        -ui graphic or command-line profile, and we should in fact start the GUI. */
     }



More information about the Unison-hackers mailing list