src/module-{proto,impl}.lisp: Publish fragments properly.
[sod] / src / pset-impl.lisp
index 14cb43b..e6986a5 100644 (file)
 (cl:in-package #:sod)
 
 ;;;--------------------------------------------------------------------------
+;;; Conversion utilities.
+
+(defun string-to-symbol
+    (string &key (package *package*) (swap-case t) (swap-hyphen t))
+  "Convert STRING to a symbol in PACKAGE.
+
+   Parse off a `PACKAGE:' prefix from STRING if necessary, to identify the
+   package; PACKAGE is used if there isn't a prefix.  A doubled colon allows
+   access to internal symbols, and will intern if necessary.  Note that
+   escape characters are /not/ processed; don't put colons in package names
+   if you want to use them from SOD property sets.
+
+   The portions of the string are modified by `frob-identifier'; the
+   arguments SWAP-CASE and SWAP-HYPHEN are passed to `frob-identifier' to
+   control this process."
+
+  (let* ((length (length string))
+        (colon (position #\: string)))
+    (multiple-value-bind (start internalp)
+       (cond ((not colon) (values 0 t))
+             ((and (< (1+ colon) length)
+                   (char= (char string (1+ colon)) #\:))
+              (values (+ colon 2) t))
+             (t
+              (values (1+ colon) nil)))
+      (when colon
+       (let* ((package-name (if (zerop colon) "KEYWORD"
+                                (frob-identifier (subseq string 0 colon)
+                                                 :swap-case swap-case
+                                                 :swap-hyphen swap-hyphen)))
+              (found (find-package package-name)))
+         (unless found
+           (error "Unknown package `~A'" package-name))
+         (setf package found)))
+      (let ((name (frob-identifier (subseq string start)
+                                  :swap-case swap-case
+                                  :swap-hyphen swap-hyphen)))
+       (multiple-value-bind (symbol status)
+           (funcall (if internalp #'intern #'find-symbol) name package)
+         (cond ((or internalp (eq status :external))
+                symbol)
+               ((not status)
+                (error "Symbol `~A' not found in package `~A'"
+                       name (package-name package)))
+               (t
+                (error "Symbol `~A' not external in package `~A'"
+                       name (package-name package)))))))))
+
+(let ((truish '("true" "t" "yes" "verily"))
+      (falsish '("false" "nil" "no" "nowise")))
+  (defun truishp (string)
+    "Convert STRING to a boolean."
+    (cond ((member string truish :test #'string=) t)
+         ((member string falsish :test #'string=) nil)
+         (t (error "Unrecognized boolean value `~A'" string)))))
+
+;;;--------------------------------------------------------------------------
 ;;; Property representation.
 
 (defmethod file-location ((prop property))
     ((value symbol) (type (eql :symbol)) (wanted (eql :id)))
   (frob-identifier (symbol-name value)))
 
+;;; Boolean.
+
+(defmethod coerce-property-value
+    ((value symbol) (type (eql :symbol)) (wanted (eql :boolean)))
+  value)
+
+(defmethod coerce-property-value
+    ((value string) (type (eql :id)) (wanted (eql :boolean)))
+  (truishp value))
+
+(defmethod coerce-property-value
+    ((value integer) (type (eql :int)) (wanted (eql :boolean)))
+  (not (zerop value)))
+
 ;;; Types.
 
 (defmethod coerce-property-value
     ((value string) (type (eql :id)) (wanted (eql :type)))
-  (or (gethash value *module-type-map*)
-      (gethash value *declspec-map*)
-      (error "Unknown type `~A'." value)))
+  (or (and (boundp '*module-type-map*)
+          (gethash value *module-type-map*))
+      (find-simple-c-type value)
+      (error "Unknown type `~A'" value)))
 
 ;;;--------------------------------------------------------------------------
 ;;; Property sets.