Initial revision
authorChris Hanson <org/chris-hanson/cph>
Tue, 21 Feb 1995 23:00:42 +0000 (23:00 +0000)
committerChris Hanson <org/chris-hanson/cph>
Tue, 21 Feb 1995 23:00:42 +0000 (23:00 +0000)
v7/src/runtime/os2ctype.scm [new file with mode: 0644]

diff --git a/v7/src/runtime/os2ctype.scm b/v7/src/runtime/os2ctype.scm
new file mode 100644 (file)
index 0000000..732f9a2
--- /dev/null
@@ -0,0 +1,322 @@
+#| -*-Scheme-*-
+
+$Id: os2ctype.scm,v 1.1 1995/02/21 23:00:42 cph Exp $
+
+Copyright (c) 1995 Massachusetts Institute of Technology
+
+This material was developed by the Scheme project at the Massachusetts
+Institute of Technology, Department of Electrical Engineering and
+Computer Science.  Permission to copy this software, to redistribute
+it, and to use it for any purpose is granted, subject to the following
+restrictions and understandings.
+
+1. Any copy made of this software must include this copyright notice
+in full.
+
+2. Users of this software agree to make their best efforts (a) to
+return to the MIT Scheme project any improvements or extensions that
+they make, so that these may be included in future releases; and (b)
+to inform MIT of noteworthy uses of this software.
+
+3. All materials developed as a consequence of the use of this
+software shall duly acknowledge such use, in accordance with the usual
+standards of acknowledging credit in academic research.
+
+4. MIT has made no warrantee or representation that the operation of
+this software will be error-free, and MIT is under no obligation to
+provide any services, by way of maintenance, update, or otherwise.
+
+5. In conjunction with products arising from the use of this material,
+there shall be no use of the name of the Massachusetts Institute of
+Technology nor of any adaptation thereof in any advertising,
+promotional, or sales literature without prior written consent from
+MIT in each case. |#
+
+;;;; OS/2 C Type Model
+;;; package: (runtime os2-graphics)
+
+(declare (usual-integrations))
+\f
+;;;; Generic Type Modelling
+
+(define-structure (c-type (conc-name c-type/) (constructor #f) (predicate #f))
+  (size #f read-only #t)
+  (alignment #f read-only #t))
+
+(define-structure (c-number-type (conc-name c-number-type/))
+  (size #f read-only #t)
+  (alignment #f read-only #t)
+  (reader #f read-only #t)
+  (writer #f read-only #t))
+
+(define-structure (c-pointer-type
+                  (conc-name c-pointer-type/)
+                  (constructor %make-c-pointer-type))
+  (size #f read-only #t)
+  (alignment #f read-only #t)
+  (element-type #f read-only #t))
+
+(define-structure (c-array-type
+                  (conc-name c-array-type/)
+                  (constructor %make-c-array-type))
+  (size #f read-only #t)
+  (alignment #f read-only #t)
+  (element-type #f read-only #t)
+  (n-elements #f read-only #t)
+  (element-spacing #f read-only #t))
+
+(define-structure (c-struct-type
+                  (conc-name c-struct-type/)
+                  (constructor %make-c-struct-type))
+  (size #f read-only #t)
+  (alignment #f read-only #t)
+  (elements #f read-only #t))
+
+(define-structure (c-struct-element (conc-name c-struct-element/))
+  (name #f read-only #t)
+  (type #f read-only #t)
+  (offset #f read-only #t))
+\f
+(define (define-c-type name type)
+  (hash-table/put! c-type-names name (canonicalize-c-type type)))
+
+(define (lookup-c-type name)
+  (let ((type (hash-table/get c-type-names name #f)))
+    (if (not type)
+       (error "Unknown C type name:" name))
+    type))
+
+(define c-type-names)
+
+(define (canonicalize-c-type type)
+  (cond ((string? type)
+        (lookup-c-type type))
+       ((and (pair? type)
+             (eq? 'ARRAY (car type))
+             (pair? (cdr type))
+             (pair? (cddr type))
+             (exact-nonnegative-integer? (caddr type))
+             (null? (cdddr type)))
+        (make-c-array-type (canonicalize-c-type (cadr type)) (caddr type)))
+       ((and (pair? type)
+             (eq? 'POINTER (car type))
+             (pair? (cdr type))
+             (null? (cddr type)))
+        (make-c-pointer-type (canonicalize-c-type (cadr type))))
+       ((and (pair? type)
+             (eq? 'STRUCT (car type))
+             (list? (cdr type))
+             (for-all? (cdr type)
+               (lambda (element)
+                 (and (pair? element)
+                      (pair? (cdr element))
+                      (string? (cadr element))
+                      (null? (cddr element))))))
+        (make-c-struct-type (map (lambda (element)
+                                   (cons (cadr element)
+                                         (canonicalize-c-type (car element))))
+                                 (cdr type))))
+       (else
+        (error "Malformed C type expression:" type))))
+\f
+(define (define-c-integer-type name signed? size)
+  (define-c-type name
+    (if signed?
+       (make-c-number-type size size
+                           (signed-integer-reader size)
+                           (signed-integer-writer size))
+       (make-c-number-type size size
+                           (unsigned-integer-reader size)
+                           (unsigned-integer-writer size)))))
+
+(define (unsigned-integer-reader n-bytes)
+  (lambda (bytes start)
+    (let ((end (+ start n-bytes)))
+      (let loop ((index start) (accum 0) (factor 1))
+       (if (< index end)
+           (loop (+ index 1)
+                 (+ accum (* (vector-8b-ref bytes index) factor))
+                 (* factor 256))
+           accum)))))
+
+(define (signed-integer-reader n-bytes)
+  (let ((read-raw (unsigned-integer-reader n-bytes))
+       (split (expt 2 (- (* n-bytes 8) 1))))
+    (let ((radix (* split 2)))
+      (lambda (bytes start)
+       (let ((raw (read-raw bytes start)))
+         (if (< raw split)
+             raw
+             (- raw radix)))))))
+
+(define (unsigned-integer-writer n-bytes)
+  (lambda (bytes start value)
+    (let ((end (+ start n-bytes)))
+      (let loop ((index start) (value value))
+       (if (< index end)
+           (let ((q.r (integer-divide value 256)))
+             (vector-8b-set! bytes index (integer-divide-remainder q.r))
+             (loop (+ index 1) (integer-divide-quotient q.r))))))))
+
+(define (signed-integer-writer n-bytes)
+  (let ((write-raw (unsigned-integer-writer n-bytes))
+       (radix (expt 2 (* n-bytes 8))))
+    (lambda (bytes start value)
+      (write-raw bytes start (if (< value 0) (+ value radix) value)))))
+\f
+(define (make-c-pointer-type element-type)
+  (%make-c-pointer-type (implementation/pointer-size element-type)
+                       (implementation/pointer-alignment element-type)
+                       element-type))
+
+(define (make-c-array-type element-type n-elements)
+  (let ((element-spacing (implementation/array-element-spacing element-type)))
+    (let ((size (* element-spacing n-elements)))
+      (%make-c-array-type size
+                         (implementation/array-alignment element-type size)
+                         element-type
+                         n-elements
+                         element-spacing))))
+
+(define (make-c-struct-type element-alist)
+  (let loop ((offset 0) (alist element-alist) (elements '()))
+    (if (null? alist)
+       (let ((elements (reverse elements)))
+         (%make-c-struct-type offset
+                              (implementation/struct-alignment elements
+                                                               offset)
+                              elements))
+       (let ((offset
+              (implementation/struct-element-offset (cdar alist) offset)))
+         (loop (+ offset (c-type/size (cdar alist)))
+               (cdr alist)
+               (cons (make-c-struct-element (caar alist) (cdar alist) offset)
+                     elements))))))
+\f
+(define (c-number-reader type offset . selectors)
+  (call-with-values (lambda () (select-c-type type offset selectors))
+    (lambda (type offset)
+      (guarantee-number-type type)
+      (let ((reader (c-number-type/reader type)))
+       (lambda (bytes)
+         (reader bytes offset))))))
+
+(define (c-number-writer type offset . selectors)
+  (call-with-values (lambda () (select-c-type type offset selectors))
+    (lambda (type offset)
+      (guarantee-number-type type)
+      (let ((writer (c-number-type/writer type)))
+       (lambda (bytes value)
+         (writer bytes offset value))))))
+
+(define (c-element-type type offset . selectors)
+  (call-with-values (lambda () (select-c-type type offset selectors))
+    (lambda (type offset)
+      offset
+      type)))
+
+(define (c-element-offset type offset . selectors)
+  (call-with-values (lambda () (select-c-type type offset selectors))
+    (lambda (type offset)
+      type
+      offset)))
+
+(define (c-array-reader type offset . selectors)
+  (call-with-values (lambda () (select-c-type type offset selectors))
+    (lambda (type offset)
+      (let ((element-type (c-array-type/element-type type))
+           (element-spacing (c-array-type/element-spacing type)))
+       (guarantee-number-type element-type)
+       (let ((reader (c-number-type/reader element-type)))
+         (lambda (bytes index)
+           (reader bytes (+ offset (* element-spacing index)))))))))
+
+(define (c-array-writer type offset . selectors)
+  (call-with-values (lambda () (select-c-type type offset selectors))
+    (lambda (type offset)
+      (let ((element-type (c-array-type/element-type type))
+           (element-spacing (c-array-type/element-spacing type)))
+       (guarantee-number-type element-type)
+       (let ((writer (c-number-type/writer element-type)))
+         (lambda (bytes index value)
+           (writer bytes (+ offset (* element-spacing index)) value)))))))
+
+(define (guarantee-number-type type)
+  (if (not (c-number-type? type))
+      (error "Selected type is not a number type:" type)))
+
+(define (select-c-type type offset selectors)
+  (if (null? selectors)
+      (values type offset)
+      (call-with-values
+         (lambda () (select-c-type-1 type offset (car selectors)))
+       (lambda (type offset)
+         (select-c-type type offset (cdr selectors))))))
+
+(define (select-c-type-1 type offset selector)
+  (cond ((c-array-type? type)
+        (if (not (exact-nonnegative-integer? selector))
+            (error "Illegal selector for C array:" selector))
+        (values (c-array-type/element-type type)
+                (+ offset (* (c-array-type/element-spacing type) selector))))
+       ((c-struct-type? type)
+        (if (not (string? selector))
+            (error "Illegal selector for C struct:" selector))
+        (let loop ((elements (c-struct-type/elements type)))
+          (if (null? elements)
+              (error "No element with this name:" selector))
+          (if (string=? selector (c-struct-element/name (car elements)))
+              (values (c-struct-element/type (car elements))
+                      (+ offset (c-struct-element/offset (car elements))))
+              (loop (cdr elements)))))
+       (else
+        (error "Can't select this type:" type))))
+\f
+;;;; OS/2 Type Specification
+
+(define (initialize-c-types!)
+  (load-option 'hash-table)
+  (set! c-type-names (make-equal-hash-table))
+
+  (define-c-integer-type "signed char"  #t 1)
+  (define-c-integer-type "signed short" #t 2)
+  (define-c-integer-type "signed int"   #t 4)
+  (define-c-integer-type "signed long"  #t 4)
+
+  (define-c-integer-type "unsigned char"  #f 1)
+  (define-c-integer-type "unsigned short" #f 2)
+  (define-c-integer-type "unsigned int"   #f 4)
+  (define-c-integer-type "unsigned long"  #f 4)
+
+  (define-c-type "char"  "signed char")
+  (define-c-type "short" "signed short")
+  (define-c-type "int"   "signed int")
+  (define-c-type "long"  "signed long"))
+
+(define (implementation/pointer-size element-type) element-type 4)
+(define (implementation/pointer-alignment element-type) element-type 4)
+
+(define (implementation/array-element-spacing element-type)
+  (let ((size (c-type/size element-type))
+       (alignment (c-type/alignment element-type)))
+    (let ((delta (remainder size alignment)))
+      (if (= 0 delta)
+         size
+         (+ size (- alignment delta))))))
+
+(define (implementation/array-alignment element-type array-size)
+  (if (< array-size 4)
+      (c-type/alignment element-type)
+      4))
+
+(define (implementation/struct-element-offset element-type prev-end)
+  (let ((a (c-type/alignment element-type)))
+    (let ((r (remainder prev-end a)))
+      (if (= 0 r)
+         prev-end
+         (+ prev-end (- a r))))))
+
+(define (implementation/struct-alignment elements struct-size)
+  (if (< struct-size 4)
+      (apply max (map c-type/alignment (map c-struct-element/type elements)))
+      4))
\ No newline at end of file