Removed :colors initarg from initialize-instance for the COLOR class
[clg] / glib / gforeign.lisp
1 ;; Common Lisp bindings for GTK+ v2.0
2 ;; Copyright (C) 1999-2000 Espen S. Johnsen <espejohn@online.no>
3 ;;
4 ;; This library is free software; you can redistribute it and/or
5 ;; modify it under the terms of the GNU Lesser General Public
6 ;; License as published by the Free Software Foundation; either
7 ;; version 2 of the License, or (at your option) any later version.
8 ;;
9 ;; This library is distributed in the hope that it will be useful,
10 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 ;; Lesser General Public License for more details.
13 ;;
14 ;; You should have received a copy of the GNU Lesser General Public
15 ;; License along with this library; if not, write to the Free Software
16 ;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
18 ;; $Id: gforeign.lisp,v 1.5 2000-10-01 17:19:11 espen Exp $
19
20 (in-package "GLIB")
21
22 ;;;; Type methods
23
24 (defvar *type-methods* (make-hash-table))
25
26 (defun ensure-type-method-fun (fname)
27 (unless (fboundp fname)
28 (setf
29 (symbol-function fname)
30 #'(lambda (type-spec &rest args)
31 (apply
32 (find-applicable-type-method type-spec fname) type-spec args)))))
33
34 (defmacro define-type-method-fun (fname lambda-list)
35 (declare (ignore lambda-list))
36 `(defun ,fname (type-spec &rest args)
37 (apply
38 (find-applicable-type-method type-spec ',fname) type-spec args)))
39
40
41 (defun ensure-type-name (type)
42 (etypecase type
43 (symbol type)
44 (pcl::class (class-name type))))
45
46 (defun add-type-method (type fname function)
47 (push
48 (cons fname function)
49 (gethash (ensure-type-name type) *type-methods*)))
50
51 (defun find-type-method (type fname)
52 (cdr (assoc fname (gethash (ensure-type-name type) *type-methods*))))
53
54 (defun find-applicable-type-method (type-spec fname &optional (error t))
55 (flet ((find-superclass-method (class)
56 (when class
57 (dolist (super (cdr (pcl::class-precedence-list class)))
58 (return-if (find-type-method super fname)))))
59 (find-expanded-type-method (type-spec)
60 (multiple-value-bind (expanded-type-spec expanded-p)
61 (type-expand-1 type-spec)
62 (cond
63 (expanded-p
64 (find-applicable-type-method expanded-type-spec fname nil))
65 ((neq type-spec t)
66 (find-applicable-type-method t fname nil))))))
67
68 (or
69 (typecase type-spec
70 (pcl::class
71 (or
72 (find-type-method type-spec fname)
73 (find-superclass-method type-spec)))
74 (symbol
75 (or
76 (find-type-method type-spec fname)
77 (find-expanded-type-method type-spec)
78 (find-superclass-method (find-class type-spec nil))))
79 (cons
80 (or
81 (find-type-method (first type-spec) fname)
82 (find-expanded-type-method type-spec)))
83 (t
84 (error "Invalid type specifier ~A" type-spec)))
85 (and
86 error
87 (error
88 "No applicable method for ~A when called with type specifier ~A"
89 fname type-spec)))))
90
91 (defmacro deftype-method (fname type lambda-list &body body)
92 `(progn
93 (ensure-type-method-fun ',fname)
94 (add-type-method ',type ',fname #'(lambda ,lambda-list ,@body))
95 ',fname))
96
97 (defmacro deftype (name parameters &body body)
98 (destructuring-bind (lisp-name &optional alien-name) (mklist name)
99 `(progn
100 ,(when alien-name
101 `(setf (alien-type-name ',lisp-name) ,alien-name))
102 (lisp:deftype ,lisp-name ,parameters ,@body))))
103
104 ;; To make the compiler shut up
105 (eval-when (:compile-toplevel :load-toplevel :execute)
106 (define-type-method-fun translate-type-spec (type-spec))
107 (define-type-method-fun size-of (type-spec))
108 (define-type-method-fun translate-to-alien (type-spec expr &optional copy))
109 (define-type-method-fun translate-from-alien (type-spec expr &optional alloc))
110 (define-type-method-fun cleanup-alien (type-spec alien &optional copied)))
111
112
113 ;;;;
114
115 (defvar *type-function-cache* (make-hash-table :test #'equal))
116
117 (defun get-cached-function (type-spec fname)
118 (cdr (assoc fname (gethash type-spec *type-function-cache*))))
119
120 (defun set-cached-function (type-spec fname function)
121 (push (cons fname function) (gethash type-spec *type-function-cache*))
122 function)
123
124
125 ;; Creates a function to translate an object of the specified type
126 ;; from lisp to alien representation.
127 (defun get-to-alien-function (type-spec)
128 (or
129 (get-cached-function type-spec 'to-alien-function)
130 (set-cached-function type-spec 'to-alien-function
131 (compile
132 nil
133 `(lambda (object)
134 (declare (ignorable object))
135 ,(translate-to-alien type-spec 'object))))))
136
137 ;; and the opposite
138 (defun get-from-alien-function (type-spec)
139 (or
140 (get-cached-function type-spec 'from-alien-function)
141 (set-cached-function type-spec 'from-alien-function
142 (compile
143 nil
144 `(lambda (alien)
145 (declare (ignorable alien))
146 ,(translate-from-alien type-spec 'alien))))))
147
148 ;; and for cleaning up
149 (defun get-cleanup-function (type-spec)
150 (or
151 (get-cached-function type-spec 'cleanup-function)
152 (set-cached-function type-spec 'cleanup-function
153 (compile
154 nil
155 `(lambda (alien)
156 (declare (ignorable alien))
157 ,(cleanup-alien type-spec 'alien))))))
158
159
160
161 ;; Creates a function to write an object of the specified type
162 ;; to the given memory location
163 (defun get-writer-function (type-spec)
164 (or
165 (get-cached-function type-spec 'writer-function)
166 (set-cached-function type-spec 'writer-function
167 (compile
168 nil
169 `(lambda (value sap offset)
170 (declare (ignorable value sap offset))
171 (setf
172 (,(sap-ref-fname type-spec) sap offset)
173 ,(translate-to-alien type-spec 'value :copy)))))))
174
175 ;; Creates a function to read an object of the specified type
176 ;; from the given memory location
177 (defun get-reader-function (type-spec)
178 (or
179 (get-cached-function type-spec 'reader-function)
180 (set-cached-function type-spec 'reader-function
181 (compile
182 nil
183 `(lambda (sap offset)
184 (declare (ignorable sap offset))
185 ,(translate-from-alien
186 type-spec `(,(sap-ref-fname type-spec) sap offset) :reference))))))
187
188
189 (defun get-destroy-function (type-spec)
190 (or
191 (get-cached-function type-spec 'destroy-function)
192 (set-cached-function type-spec 'destroy-function
193 (compile
194 nil
195 `(lambda (sap offset)
196 (declare (ignorable sap offset))
197 ,(cleanup-alien
198 type-spec `(,(sap-ref-fname type-spec) sap offset) :copied))))))
199
200
201
202 ;;;;
203
204 (defconstant +bits-per-unit+ 8
205 "Number of bits in an addressable unit (byte)")
206
207 ;; Sizes of fundamental C types in addressable units
208 (defconstant +size-of-short+ 2)
209 (defconstant +size-of-int+ 4)
210 (defconstant +size-of-long+ 4)
211 (defconstant +size-of-sap+ 4)
212 (defconstant +size-of-float+ 4)
213 (defconstant +size-of-double+ 8)
214
215 (defun sap-ref-unsigned (sap offset)
216 (sap-ref-32 sap offset))
217
218 (defun sap-ref-signed (sap offset)
219 (signed-sap-ref-32 sap offset))
220
221 (defun sap-ref-fname (type-spec)
222 (let ((alien-type-spec (mklist (translate-type-spec type-spec))))
223 (ecase (first alien-type-spec)
224 (unsigned
225 (ecase (second alien-type-spec)
226 (8 'sap-ref-8)
227 (16 'sap-ref-16)
228 (32 'sap-ref-32)
229 (64 'sap-ref-64)))
230 (signed
231 (ecase (second alien-type-spec)
232 (8 'signed-sap-ref-8)
233 (16 'signed-sap-ref-16)
234 (32 'signed-sap-ref-32)
235 (64 'signed-sap-ref-64)))
236 (system-area-pointer 'sap-ref-sap)
237 (single-float 'sap-ref-single)
238 (double-float 'sap-ref-double))))
239
240
241 ;;;; Foreign function call interface
242
243 (defvar *package-prefix* nil)
244
245 (defun set-package-prefix (prefix &optional (package *package*))
246 (let ((package (find-package package)))
247 (delete-if #'(lambda (assoc) (eq (car assoc) package)) *package-prefix*)
248 (push (cons package prefix) *package-prefix*))
249 prefix)
250
251 (defun package-prefix (&optional (package *package*))
252 (let ((package (find-package package)))
253 (or
254 (cdr (assoc package *package-prefix*))
255 (substitute #\_ #\- (string-downcase (package-name package))))))
256
257 (defmacro use-prefix (prefix &optional (package *package*))
258 `(eval-when (:compile-toplevel :load-toplevel :execute)
259 (set-package-prefix ,prefix ,package)))
260
261
262 (defun default-alien-func-name (lisp-name)
263 (let* ((lisp-name-string
264 (if (char= (char (the simple-string (string lisp-name)) 0) #\%)
265 (subseq (the simple-string (string lisp-name)) 1)
266 (string lisp-name)))
267 (prefix (package-prefix *package*))
268 (name (substitute #\_ #\- (string-downcase lisp-name-string))))
269 (if (or (not prefix) (string= prefix ""))
270 name
271 (format nil "~A_~A" prefix name))))
272
273
274 (defmacro define-foreign (name lambda-list return-type-spec &rest docs/args)
275 (multiple-value-bind (c-name lisp-name)
276 (if (atom name)
277 (values (default-alien-func-name name) name)
278 (values-list name))
279 (let ((supplied-lambda-list lambda-list)
280 (docs nil)
281 (args nil))
282 (dolist (doc/arg docs/args)
283 (if (stringp doc/arg)
284 (push doc/arg docs)
285 (progn
286 (destructuring-bind (expr type &optional (style :in)) doc/arg
287 (unless (member style '(:in :out :in-out))
288 (error "Bogus argument style ~S in ~S." style doc/arg))
289 (when (and
290 (not supplied-lambda-list)
291 (namep expr) (member style '(:in :in-out)))
292 (push expr lambda-list))
293 (push
294 (list (if (namep expr) expr (gensym)) expr type style) args)))))
295
296 (%define-foreign
297 c-name lisp-name (or supplied-lambda-list (nreverse lambda-list))
298 return-type-spec (reverse docs) (reverse args)))))
299
300
301 #+cmu
302 (defun %define-foreign (foreign-name lisp-name lambda-list
303 return-type-spec docs args)
304 (ext:collect ((alien-types) (alien-bindings) (alien-parameters)
305 (alien-values) (alien-deallocators))
306 (dolist (arg args)
307 (destructuring-bind (var expr type-spec style) arg
308 (let ((declaration (translate-type-spec type-spec))
309 (deallocation (cleanup-alien type-spec expr)))
310 (cond
311 ((member style '(:out :in-out))
312 (alien-types `(* ,declaration))
313 (alien-parameters `(addr ,var))
314 (alien-bindings
315 `(,var ,declaration
316 ,@(when (eq style :in-out)
317 (list (translate-to-alien type-spec expr)))))
318 (alien-values (translate-from-alien type-spec var)))
319 (deallocation
320 (alien-types declaration)
321 (alien-bindings
322 `(,var ,declaration ,(translate-to-alien type-spec expr)))
323 (alien-parameters var)
324 (alien-deallocators deallocation))
325 (t
326 (alien-types declaration)
327 (alien-parameters (translate-to-alien type-spec expr)))))))
328
329 (let ((alien-funcall `(alien-funcall ,lisp-name ,@(alien-parameters))))
330 `(defun ,lisp-name ,lambda-list
331 ,@docs
332 (with-alien ((,lisp-name
333 (function
334 ,(translate-type-spec return-type-spec)
335 ,@(alien-types))
336 :extern ,foreign-name)
337 ,@(alien-bindings))
338 ,(if return-type-spec
339 `(let ((result
340 ,(translate-from-alien return-type-spec alien-funcall)))
341 ,@(alien-deallocators)
342 (values result ,@(alien-values)))
343 `(progn
344 ,alien-funcall
345 ,@(alien-deallocators)
346 (values ,@(alien-values)))))))))
347
348
349
350
351 ;;;; Definitons and translations of fundamental types
352
353 (lisp:deftype long (&optional (min '*) (max '*)) `(integer ,min ,max))
354 (lisp:deftype unsigned-long (&optional (min '*) (max '*)) `(integer ,min ,max))
355 (lisp:deftype int (&optional (min '*) (max '*)) `(long ,min ,max))
356 (lisp:deftype unsigned-int (&optional (min '*) (max '*)) `(unsigned-long ,min ,max))
357 (lisp:deftype short (&optional (min '*) (max '*)) `(int ,min ,max))
358 (lisp:deftype unsigned-short (&optional (min '*) (max '*)) `(unsigned-int ,min ,max))
359 (lisp:deftype signed (&optional (size '*)) `(signed-byte ,size))
360 (lisp:deftype unsigned (&optional (size '*)) `(signed-byte ,size))
361 (lisp:deftype char () 'base-char)
362 (lisp:deftype pointer () 'system-area-pointer)
363 (lisp:deftype boolean (&optional (size '*))
364 (declare (ignore size))
365 `(member t nil))
366 (lisp:deftype static (type) type)
367 (lisp:deftype invalid () nil)
368
369
370
371 (deftype-method cleanup-alien t (type-spec alien &optional copied)
372 (declare (ignore type-spec alien copied))
373 nil)
374
375
376 (deftype-method translate-to-alien integer (type-spec number &optional copy)
377 (declare (ignore type-spec copy))
378 number)
379
380 (deftype-method translate-from-alien integer (type-spec number &optional alloc)
381 (declare (ignore type-spec alloc))
382 number)
383
384
385 (deftype-method translate-type-spec fixnum (type-spec)
386 (declare (ignore type-spec))
387 (translate-type-spec 'signed))
388
389 (deftype-method size-of fixnum (type-spec)
390 (declare (ignore type-spec))
391 (size-of 'signed))
392
393 (deftype-method translate-to-alien fixnum (type-spec number &optional copy)
394 (declare (ignore type-spec copy))
395 number)
396
397 (deftype-method translate-from-alien fixnum (type-spec number &optional alloc)
398 (declare (ignore type-spec alloc))
399 number)
400
401
402 (deftype-method translate-type-spec long (type-spec)
403 (declare (ignore type-spec))
404 `(signed ,(* +bits-per-unit+ +size-of-long+)))
405
406 (deftype-method size-of long (type-spec)
407 (declare (ignore type-spec))
408 +size-of-long+)
409
410
411 (deftype-method translate-type-spec unsigned-long (type-spec)
412 (declare (ignore type-spec))
413 `(unsigned ,(* +bits-per-unit+ +size-of-long+)))
414
415 (deftype-method size-of unsigned-long (type-spec)
416 (declare (ignore type-spec))
417 +size-of-long+)
418
419
420 (deftype-method translate-type-spec int (type-spec)
421 (declare (ignore type-spec))
422 `(signed ,(* +bits-per-unit+ +size-of-int+)))
423
424 (deftype-method size-of int (type-spec)
425 (declare (ignore type-spec))
426 +size-of-int+)
427
428
429 (deftype-method translate-type-spec unsigned-int (type-spec)
430 (declare (ignore type-spec))
431 `(signed ,(* +bits-per-unit+ +size-of-int+)))
432
433 (deftype-method size-of unsigned-int (type-spec)
434 (declare (ignore type-spec))
435 +size-of-int+)
436
437
438 (deftype-method translate-type-spec short (type-spec)
439 (declare (ignore type-spec))
440 `(signed ,(* +bits-per-unit+ +size-of-short+)))
441
442 (deftype-method size-of short (type-spec)
443 (declare (ignore type-spec))
444 +size-of-short+)
445
446
447 (deftype-method translate-type-spec unsigned-short (type-spec)
448 (declare (ignore type-spec))
449 `(unsigned ,(* +bits-per-unit+ +size-of-short+)))
450
451 (deftype-method size-of unsigned-short (type-spec)
452 (declare (ignore type-spec))
453 +size-of-short+)
454
455
456 (deftype-method translate-type-spec signed-byte (type-spec)
457 (let ((size (second (mklist (type-expand-to 'signed-byte type-spec)))))
458 `(signed
459 ,(cond
460 ((member size '(nil *)) (* +bits-per-unit+ +size-of-int+))
461 (t size)))))
462
463 (deftype-method size-of signed-byte (type-spec)
464 (let ((size (second (mklist (type-expand-to 'signed-byte type-spec)))))
465 (cond
466 ((member size '(nil *)) +size-of-int+)
467 (t (/ size +bits-per-unit+)))))
468
469 (deftype-method translate-to-alien signed-byte (type-spec number &optional copy)
470 (declare (ignore type-spec copy))
471 number)
472
473 (deftype-method translate-from-alien signed-byte
474 (type-spec number &optional alloc)
475 (declare (ignore type-spec alloc))
476 number)
477
478
479 (deftype-method translate-type-spec unsigned-byte (type-spec)
480 (let ((size (second (mklist (type-expand-to 'unsigned-byte type-spec)))))
481 `(signed
482 ,(cond
483 ((member size '(nil *)) (* +bits-per-unit+ +size-of-int+))
484 (t size)))))
485
486 (deftype-method size-of unsigned-byte (type-spec)
487 (let ((size (second (mklist (type-expand-to 'unsigned-byte type-spec)))))
488 (cond
489 ((member size '(nil *)) +size-of-int+)
490 (t (/ size +bits-per-unit+)))))
491
492 (deftype-method translate-to-alien unsigned-byte
493 (type-spec number &optional copy)
494 (declare (ignore type-spec copy))
495 number)
496
497 (deftype-method translate-from-alien unsigned-byte
498 (type-spec number &optional alloc)
499 (declare (ignore type-spec alloc))
500 number)
501
502
503 (deftype-method translate-type-spec single-float (type-spec)
504 (declare (ignore type-spec))
505 'single-float)
506
507 (deftype-method size-of single-float (type-spec)
508 (declare (ignore type-spec))
509 +size-of-float+)
510
511 (deftype-method translate-to-alien single-float
512 (type-spec number &optional copy)
513 (declare (ignore type-spec copy))
514 number)
515
516 (deftype-method translate-from-alien single-float
517 (type-spec number &optional alloc)
518 (declare (ignore type-spec alloc))
519 number)
520
521
522 (deftype-method translate-type-spec double-float (type-spec)
523 (declare (ignore type-spec))
524 'double-float)
525
526 (deftype-method size-of double-float (type-spec)
527 (declare (ignore type-spec))
528 +size-of-double+)
529
530 (deftype-method translate-to-alien double-float
531 (type-spec number &optional copy)
532 (declare (ignore type-spec copy))
533 number)
534
535 (deftype-method translate-from-alien double-float
536 (type-spec number &optional alloc)
537 (declare (ignore type-spec alloc))
538 number)
539
540
541 (deftype-method translate-type-spec base-char (type-spec)
542 (declare (ignore type-spec))
543 '(unsigned +bits-per-unit+))
544
545 (deftype-method size-of base-char (type-spec)
546 (declare (ignore type-spec))
547 1)
548
549 (deftype-method translate-to-alien base-char (type-spec char &optional copy)
550 (declare (ignore type-spec copy))
551 `(char-code ,char))
552
553 (deftype-method translate-from-alien base-char (type-spec code &optional alloc)
554 (declare (ignore type-spec alloc))
555 `(code-char ,code))
556
557
558 (deftype-method translate-type-spec string (type-spec)
559 (declare (ignore type-spec))
560 'system-area-pointer)
561
562 (deftype-method size-of string (type-spec)
563 (declare (ignore type-spec))
564 +size-of-sap+)
565
566 (deftype-method translate-to-alien string (type-spec string &optional copy)
567 (declare (ignore type-spec))
568 (if copy
569 `(let ((string ,string))
570 (copy-memory
571 (make-pointer (1+ (kernel:get-lisp-obj-address string)))
572 (1+ (length string))))
573 `(make-pointer (1+ (kernel:get-lisp-obj-address ,string)))))
574
575 (deftype-method translate-from-alien string
576 (type-spec sap &optional (alloc :copy))
577 (declare (ignore type-spec))
578 `(let ((sap ,sap))
579 (unless (null-pointer-p sap)
580 (prog1
581 (c-call::%naturalize-c-string sap)
582 ;,(when (eq alloc :copy) `(deallocate-memory ,sap))
583 ))))
584
585 (deftype-method cleanup-alien string (type-spec sap &optional copied)
586 (declare (ignore type-spec))
587 (when copied
588 `(let ((sap ,sap))
589 (unless (null-pointer-p sap)
590 (deallocate-memory sap)))))
591
592
593 (deftype-method translate-type-spec boolean (type-spec)
594 (translate-type-spec
595 (cons 'unsigned (cdr (mklist (type-expand-to 'boolean type-spec))))))
596
597 (deftype-method size-of boolean (type-spec)
598 (size-of
599 (cons 'unsigned (cdr (mklist (type-expand-to 'boolean type-spec))))))
600
601 (deftype-method translate-to-alien boolean (type-spec boolean &optional copy)
602 (declare (ignore type-spec copy))
603 `(if ,boolean 1 0))
604
605 (deftype-method translate-from-alien boolean (type-spec int &optional alloc)
606 (declare (ignore type-spec alloc))
607 `(not (zerop ,int)))
608
609
610 (deftype-method translate-type-spec or (union-type)
611 (let* ((member-types (cdr (type-expand-to 'or union-type)))
612 (alien-type (translate-type-spec (first member-types))))
613 (dolist (type (cdr member-types))
614 (unless (eq alien-type (translate-type-spec type))
615 (error "No common alien type specifier for union type: ~A" union-type)))
616 alien-type))
617
618 (deftype-method size-of or (union-type)
619 (size-of (first (cdr (type-expand-to 'or union-type)))))
620
621 (deftype-method translate-to-alien or (union-type-spec expr &optional copy)
622 (destructuring-bind (name &rest type-specs)
623 (type-expand-to 'or union-type-spec)
624 (declare (ignore name))
625 `(let ((value ,expr))
626 (etypecase value
627 ,@(map
628 'list
629 #'(lambda (type-spec)
630 (list type-spec (translate-to-alien type-spec 'value copy)))
631 type-specs)))))
632
633
634 (deftype-method translate-type-spec system-area-pointer (type-spec)
635 (declare (ignore type-spec))
636 'system-area-pointer)
637
638 (deftype-method size-of system-area-pointer (type-spec)
639 (declare (ignore type-spec))
640 +size-of-sap+)
641
642 (deftype-method translate-to-alien system-area-pointer
643 (type-spec sap &optional copy)
644 (declare (ignore type-spec copy))
645 sap)
646
647 (deftype-method translate-from-alien system-area-pointer
648 (type-spec sap &optional alloc)
649 (declare (ignore type-spec alloc))
650 sap)
651
652
653 (deftype-method translate-type-spec null (type-spec)
654 (declare (ignore type-spec))
655 'system-area-pointer)
656
657 (deftype-method translate-to-alien null (type-spec expr &optional copy)
658 (declare (ignore type-spec expr copy))
659 `(make-pointer 0))
660
661
662 (deftype-method translate-type-spec nil (type-spec)
663 (declare (ignore type-spec))
664 'void)
665
666
667 (deftype-method transalte-type-spec static (type-spec)
668 (translate-type-spec (second type-spec)))
669
670 (deftype-method size-of static (type-spec)
671 (size-of type-spec))
672
673 (deftype-method translate-to-alien static (type-spec expr &optional copy)
674 (declare (ignore copy))
675 (translate-to-alien (second type-spec) expr nil))
676
677 (deftype-method translate-from-alien static (type-spec alien &optional alloc)
678 (declare (ignore alloc))
679 (translate-from-alien (second type-spec) alien nil))
680
681 (deftype-method cleanup-alien static (type-spec alien &optional copied)
682 (declare (ignore copied))
683 (cleanup-alien type-spec alien nil))
684
685
686
687 ;;;; Enum and flags type
688
689 (defun map-mappings (args op)
690 (let ((current-value 0))
691 (map
692 'list
693 #'(lambda (mapping)
694 (destructuring-bind (symbol &optional (value current-value))
695 (mklist mapping)
696 (setf current-value (1+ value))
697 (case op
698 (:enum-int (list symbol value))
699 (:flags-int (list symbol (ash 1 value)))
700 (:int-enum (list value symbol))
701 (:int-flags (list (ash 1 value) symbol))
702 (:symbols symbol))))
703 (if (integerp (first args))
704 (rest args)
705 args))))
706
707
708 (lisp:deftype enum (&rest args)
709 `(member ,@(map-mappings args :symbols)))
710
711 (deftype-method translate-type-spec enum (type-spec)
712 (let ((args (cdr (type-expand-to 'enum type-spec))))
713 (if (integerp (first args))
714 (translate-type-spec `(signed ,(first args)))
715 (translate-type-spec 'signed))))
716
717 (deftype-method size-of enum (type-spec)
718 (let ((args (cdr (type-expand-to 'enum type-spec))))
719 (if (integerp (first args))
720 (size-of `(signed ,(first args)))
721 (size-of 'signed))))
722
723 (deftype-method translate-to-alien enum (type-spec expr &optional copy)
724 (declare (ignore copy))
725 (let ((args (cdr (type-expand-to 'enum type-spec))))
726 `(ecase ,expr
727 ,@(map-mappings args :enum-int))))
728
729 (deftype-method translate-from-alien enum (type-spec expr &optional alloc)
730 (declare (ignore alloc))
731 (destructuring-bind (name &rest args) (type-expand-to 'enum type-spec)
732 (declare (ignore name))
733 `(ecase ,expr
734 ,@(map-mappings args :int-enum))))
735
736
737 (lisp:deftype flags (&rest args)
738 `(or
739 null
740 (cons
741 (member ,@(map-mappings args :symbols))
742 list)))
743
744 (deftype-method translate-type-spec flags (type-spec)
745 (let ((args (cdr (type-expand-to 'flags type-spec))))
746 (if (integerp (first args))
747 (translate-type-spec `(signed ,(first args)))
748 (translate-type-spec 'signed))))
749
750 (deftype-method size-of flags (type-spec)
751 (let ((args (cdr (type-expand-to 'flags type-spec))))
752 (if (integerp (first args))
753 (size-of `(signed ,(first args)))
754 (size-of 'signed))))
755
756 (deftype-method translate-to-alien flags (type-spec expr &optional copy)
757 (declare (ignore copy))
758 (destructuring-bind (name &rest args) (type-expand-to 'flags type-spec)
759 (declare (ignore name))
760 (let ((mappings (map-mappings args :flags-int))
761 (value (make-symbol "VALUE")))
762 `(let ((,value 0))
763 (dolist (flag ,expr ,value)
764 (setq ,value (logior ,value (second (assoc flag ',mappings)))))))))
765
766 (deftype-method translate-from-alien flags (type-spec expr &optional alloc)
767 (declare (ignore alloc))
768 (destructuring-bind (name &rest args) (type-expand-to 'flags type-spec)
769 (declare (ignore name))
770 (let ((mappings (map-mappings args :int-flags))
771 (result (make-symbol "RESULT")))
772 `(let ((,result nil))
773 (dolist (mapping ',mappings ,result)
774 (unless (zerop (logand ,expr (first mapping)))
775 (push (second mapping) ,result)))))))