~ chicken-core (chicken-5) 11014f17d16e50f99d4a54cb7c4927228269c5c7


commit 11014f17d16e50f99d4a54cb7c4927228269c5c7
Author:     felix <felix@call-with-current-continuation.org>
AuthorDate: Wed Sep 15 08:50:29 2010 -0400
Commit:     felix <felix@call-with-current-continuation.org>
CommitDate: Wed Sep 15 08:50:29 2010 -0400

    first implementation of pointer vectors

diff --git a/c-backend.scm b/c-backend.scm
index fac2058a..2a33a9b6 100644
--- a/c-backend.scm
+++ b/c-backend.scm
@@ -1178,6 +1178,7 @@
       [(s32vector nonnull-s32vector) (str "int *")]
       [(f32vector nonnull-f32vector) (str "float *")]
       [(f64vector nonnull-f64vector) (str "double *")]
+      ((pointer-vector nonnull-pointer-vector) (str "void **"))
       [(nonnull-c-string c-string nonnull-c-string* c-string* symbol) 
        (str "char *")]
       [(nonnull-unsigned-c-string nonnull-unsigned-c-string* unsigned-c-string unsigned-c-string*)
@@ -1284,6 +1285,8 @@
       ((nonnull-f32vector) "C_c_f32vector(")
       ((f64vector) "C_c_f64vector_or_null(")
       ((nonnull-f64vector) "C_c_f64vector(")
+      ((pointer-vector) "C_c_pointer_vector_or_null(")
+      ((nonnull-pointer-vector) "C_c_pointer_vector(")
       ((c-string c-string* unsigned-c-string unsigned-c-string*) "C_string_or_null(")
       ((nonnull-c-string nonnull-c-string* nonnull-unsigned-c-string 
 			 nonnull-unsigned-c-string* symbol) "C_c_string(")
diff --git a/chicken.h b/chicken.h
index 5830ae3d..dde32f07 100644
--- a/chicken.h
+++ b/chicken.h
@@ -986,6 +986,7 @@ extern double trunc(double);
 #define C_c_f32vector_or_null(x)   ((float *)C_srfi_4_vector_or_null(x))
 #define C_c_f64vector(x)           ((double *)C_data_pointer(C_u_i_cdr(x)))
 #define C_c_f64vector_or_null(x)   ((double *)C_srfi_4_vector_or_null(x))
+#define C_c_pointer_vector(x)      ((void **)C_data_pointer(C_block_item((x), 2)))
 
 #define C_isnan(f)                 (!((f) == (f)))
 #define C_isinf(f)                 ((f) == (f) + (f) && (f) != 0.0)
@@ -2033,6 +2034,12 @@ C_inline void *C_srfi_4_vector_or_null(C_word x)
 }
 
 
+C_inline void *C_c_pointer_vector_or_null(C_word x) 
+{
+  return C_truep(x) ? C_data_pointer(C_block_item(x, 1)) : NULL;
+}
+
+
 C_inline void *C_c_pointer_or_null(C_word x) 
 {
   return C_truep(x) ? (void *)C_block_item(x, 0) : NULL;
diff --git a/library.scm b/library.scm
index bb738448..d0bb6dd5 100644
--- a/library.scm
+++ b/library.scm
@@ -3910,6 +3910,10 @@ EOF
 (define (##sys#foreign-integer-argument x) (##core#inline "C_i_foreign_integer_argumentp" x))
 (define (##sys#foreign-unsigned-integer-argument x) (##core#inline "C_i_foreign_unsigned_integer_argumentp" x))
 
+(define (##sys#foreign-pointer-vector-argument x) ; not optimized yet
+  (##sys#check-structure x 'pointer-vector)
+  x)
+
 
 ;;; Low-level threading interface:
 
@@ -4362,6 +4366,7 @@ EOF
 	    (let ([v (##sys#slot obj 1)])
 	      (##sys#check-range index 0 (##sys#size v) loc)
 	      (##core#inline_allocate ("C_a_i_make_locative" 5) 9 v index weak?) ) ]
+	   ;;XXX pointer-vector currently not supported
 	   [else 
 	    (##sys#check-range index 0 (fx- (##sys#size obj) 1) loc)
 	    (##core#inline_allocate ("C_a_i_make_locative" 5) 0 obj (fx+ index 1) weak?) ] ) ]
diff --git a/lolevel.scm b/lolevel.scm
index a5f20737..acff3cd3 100644
--- a/lolevel.scm
+++ b/lolevel.scm
@@ -32,7 +32,8 @@
    ##sys#check-block
    ##sys#check-become-alist
    ##sys#check-generic-structure
-   ##sys#check-generic-vector )
+   ##sys#check-generic-vector
+   pv-buf-ref pv-buf-set!)
   (not inline ipc-hook-0 ##sys#invalid-procedure-call-hook)
   (foreign-declare #<<EOF
 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
@@ -647,3 +648,67 @@ EOF
   (##sys#check-symbol sym 'global-make-unbound!)
   (##sys#setslot sym 0 (##sys#slot '##sys#arbitrary-unbound-symbol 0))
   sym )
+
+
+;;; pointer vectors
+
+(define make-pointer-vector
+  (let ((unset (list 'unset)))
+    (lambda (n #!optional (init unset))
+      (##sys#check-exact n 'make-pointer-vector)
+      (let* ((mul (if (##sys#fudge 3) 8 4)) ; 64-bit?
+	     (size (fx* n mul))
+	     (buf (##sys#make-blob size)))
+	(unless (eq? init unset)
+	  (when init
+	    (##sys#check-pointer init 'make-pointer-vector)
+	    (do ((i 0 (fx+ i 1)))
+		((fx>= i n))
+	      (pv-buf-set! buf i init))))
+	(##sys#make-structure 'pointer-vector n buf)))))
+
+(define (pointer-vector? x) 
+  (##sys#structure? x 'pointer-vector))
+
+(define (pointer-vector . ptrs)
+  (let* ((n (length ptrs))
+	 (pv (make-pointer-vector n))
+	 (buf (##sys#slot pv 2)))	; buf
+    (do ((ptrs ptrs (cdr ptrs))
+	 (i 0 (fx+ i 1)))
+	((null? ptrs) pv)
+      (pv-buf-set! buf i (car ptrs)))))
+
+(define (pointer-vector-fill! pv ptr)
+  (##sys#check-structure pv 'pointer-vector 'pointer-vector-fill!)
+  (when ptr (##sys#check-pointer ptr 'pointer-vector-fill!))
+  (let ((buf (##sys#slot pv 2))		; buf
+	(n (##sys#slot pv 1)))		; n
+    (do ((i 0 (fx+ i 1)))
+	((fx>= i n))
+      (pv-buf-set! buf i ptr))))
+
+(define pv-buf-ref
+  (foreign-lambda* c-pointer ((scheme-object buf) (unsigned-int i))
+    "C_return(*(C_data_pointer(buf) + i));"))
+
+(define pv-buf-set!
+  (foreign-lambda* void ((scheme-object buf) (unsigned-int i) (c-pointer ptr))
+    "*(C_data_pointer(buf) + i) = ptr;"))
+
+(define (pointer-vector-set! pv i ptr)
+  (##sys#check-structure pv 'pointer-vector 'pointer-vector-ref)
+  (##sys#check-exact i 'pointer-vector-ref)
+  (##sys#check-range i 0 (##sys#slot pv 1)) ; len
+  (when ptr (##sys#check-pointer ptr 'pointer-vector-set!))
+  (pv-buf-set! (##sys#slot pv 2) i ptr))
+
+(define pointer-vector-ref
+  (getter-with-setter
+   (lambda (pv i)
+     (##sys#check-structure pv 'pointer-vector 'pointer-vector-ref)
+     (##sys#check-exact i 'pointer-vector-ref)
+     (##sys#check-range i 0 (##sys#slot pv 1)) ; len
+     (pv-buf-ref (##sys#slot pv 2) i))	; buf
+   pointer-vector-set!
+   "(pointer-vector-ref pv i)"))
diff --git a/manual/Foreign type specifiers b/manual/Foreign type specifiers
index c0ff376b..dd98b573 100644
--- a/manual/Foreign type specifiers	
+++ b/manual/Foreign type specifiers	
@@ -85,6 +85,15 @@ a return value, a {{NULL}} pointer will be returned as {{#f}}.
 
 As {{c-pointer}}, but guaranteed not to be {{#f/NULL}}.
 
+=== pointer-vector
+
+A vector of foreign pointer objects. {{#f}} is allowed and passed as a
+{{NULL}} pointer.
+
+=== nonnull-pointer-vector
+
+As {{pointer-vector}}, but guaranteed not to be {{#f/NULL}}.
+
 === blob
 
 A blob object, passed as a pointer to its contents. Arguments of type {{blob}}
@@ -253,6 +262,8 @@ double
 double
 </td></tr><tr><td>[nonnull-]c-pointer</td><td>
 void *
+</td></tr><tr><td>[nonnull-]pointer-vector</td><td>
+void **
 </td></tr><tr><td>[nonnull-]blob</td><td>
 unsigned char *
 </td></tr><tr><td>[nonnull-]u8vector</td><td>
diff --git a/manual/Unit lolevel b/manual/Unit lolevel
index 49cbd051..078ee79c 100644
--- a/manual/Unit lolevel	
+++ b/manual/Unit lolevel	
@@ -307,6 +307,51 @@ is any other kind of pointer-like object {{#f}} is returned. Otherwise an
 error is signalled.
 
 
+=== Pointer vectors
+
+/Pointer-vectors/ are specialized and space-efficient vectors or
+foreign pointer objects. All procedures defined below that accept
+a pointer object allow {{#f}} as an alternative representation of
+the {{NULL}}-pointer.
+
+==== make-pointer-vector 
+
+<procedure>(make-pointer-vector LENGTH [INIT])</procedure>
+
+Creates a pointer-vector of the given length and optionally initializes each
+element to {{INIT}}, which should be a pointer or {{#f}, which represents the
+{{NULL}} pointer.
+
+==== pointer-vector?
+
+<procedure>(pointer-vector? X)</procedure>
+
+Returns {{#t}} if {{X}} is a pointer-vector or {{#f}} otherwise.
+
+==== pointer-vector
+
+<procedure>(pointer-vector POINTER ...)</procedure>
+
+Returns a pointer-vector from the given pointer arguments.
+
+==== pointer-vector-ref
+
+<procedure>(pointer-vector-ref POINTERVECTOR INDEX)</procedure>
+
+Returns the pointer at {{INDEX}} in the given pointer-vector or
+{{#f}} if the element is a {{NULL}}- pointer.
+
+==== pointer-vector-set!
+
+<procedure>(pointer-vector-set! POINTERVECTOR INDEX POINTER)</procedure>
+
+Sets the element at the position {{INDEX}} in the given pointer-vector to
+{{POINTER}}. The alternative syntax
+
+  (set! (pointer-vector-ref POINTERVECTOR INDEX) POINTER)
+
+is also allowed.
+
 
 === Locatives
 
diff --git a/scrutinizer.scm b/scrutinizer.scm
index d3105b7a..a18634f7 100644
--- a/scrutinizer.scm
+++ b/scrutinizer.scm
@@ -50,7 +50,8 @@
 ;       | deprecated
 ;   BASIC = * | string | symbol | char | number | boolean | list | pair | 
 ;           procedure | vector | null | eof | undefined | port | 
-;           blob | noreturn | pointer | locative | fixnum | float
+;           blob | noreturn | pointer | locative | fixnum | float |
+;           pointer-vector
 ;   RESULTS = * 
 ;           | (VAL1 ...)
 
diff --git a/support.scm b/support.scm
index 143ef741..a52fefea 100644
--- a/support.scm
+++ b/support.scm
@@ -900,10 +900,10 @@
 ;;; Create foreign type checking expression:
 
 (define foreign-type-check
-  (let ([tmap '((nonnull-u8vector . u8vector) (nonnull-u16vector . u16vector)
+  (let ((tmap '((nonnull-u8vector . u8vector) (nonnull-u16vector . u16vector)
 		(nonnull-s8vector . s8vector) (nonnull-s16vector . s16vector)
 		(nonnull-u32vector . u32vector) (nonnull-s32vector . s32vector)
-		(nonnull-f32vector . f32vector) (nonnull-f64vector . f64vector) ) ] )
+		(nonnull-f32vector . f32vector) (nonnull-f64vector . f64vector))))
     (lambda (param type)
       (follow-without-loop
        type
@@ -926,6 +926,18 @@
 	      (if unsafe
 		  param
 		  `(##sys#foreign-block-argument ,param) ) ]
+	     ((pointer-vector)
+	      (let ([tmp (gensym)])
+		`(let ([,tmp ,param])
+		   (if ,tmp
+		       ,(if unsafe
+			    tmp
+			    `(##sys#foreign-pointer-vector-argument ,tmp) )
+		       '#f) ) ) )
+	     ((nonnull-pointer-vector)
+	      (if unsafe
+		  param
+		  `(##sys#foreign-pointer-vector-argument ,param) ) ]
 	     [(u8vector u16vector s8vector s16vector u32vector s32vector f32vector f64vector)
 	      (let ([tmp (gensym)])
 		`(let ([,tmp ,param])
diff --git a/types.db b/types.db
index 1200d696..459a111f 100644
--- a/types.db
+++ b/types.db
@@ -584,6 +584,7 @@
 (locative-set! (procedure locative-set! (locative *) *))
 (locative? (procedure locative? (*) boolean))
 (make-locative (procedure make-locative (* #!optional fixnum) locative))
+(make-pointer-vector (procedure make-pointer-vector (fixnum #!optional pointer) pointer-vector))
 (make-record-instance (procedure make-record-instance (* #!rest) *))
 (make-weak-locative (procedure make-weak-locative (* #!optional fixnum) locative))
 (move-memory! (procedure move-memory! (* * #!optional fixnum fixnum fixnum) *))
@@ -601,15 +602,20 @@
 (object-release (procedure object-release (* #!optional (procedure (pointer) *)) *))
 (object-size (procedure object-size (*) fixnum))
 (object-unevict (procedure object-unevict (* #!optional *) *))
+(pointer+ (procedure pointer+ (pointer fixnum) pointer))
 (pointer->address (procedure pointer->address (pointer) number))
-(pointer-like? (procedure pointer-like? (*) boolean))
 (pointer->object (procedure pointer->object (pointer) *))
+(pointer-offset deprecated)
+(pointer-like? (procedure pointer-like? (*) boolean))
 (pointer-f32-ref (procedure pointer-f32-ref (pointer) number))
 (pointer-f32-set! (procedure pointer-f32-set! (pointer number) undefined))
 (pointer-f64-ref (procedure pointer-f64-ref (pointer) number))
 (pointer-f64-set! (procedure pointer-f64-set! (pointer number) undefined))
-(pointer-offset deprecated)
-(pointer+ (procedure pointer+ (pointer fixnum) pointer))
+(pointer-vector (procedure pointer-vector (#!rest pointer-vector) boolean))
+(pointer-vector? (procedure pointer-vector? (*) boolean))
+(pointer-vector-fill! (procedure pointer-vector-fill! (pointer-vector pointer) undefined))
+(pointer-vector-ref (procedure pointer-vector-ref (pointer-vector fixnum) pointer))
+(pointer-vector-set! (procedure pointer-vector-set! (pointer-vector fixnum pointer) pointer))
 (pointer-s16-ref (procedure pointer-s16-ref (pointer) fixnum))
 (pointer-s16-set! (procedure pointer-s16-set! (pointer fixnum) undefined))
 (pointer-s32-ref (procedure pointer-s32-ref (pointer) number))
Trap