X-Git-Url: https://git.distorted.org.uk/~mdw/sod/blobdiff_plain/e0808c472145fc81e52898bc9ac289e10c4f4f41..12949379840101e2d65883f29c5e8f0f6de49e9c:/src/pset-impl.lisp diff --git a/src/pset-impl.lisp b/src/pset-impl.lisp index e3e505f..42049db 100644 --- a/src/pset-impl.lisp +++ b/src/pset-impl.lisp @@ -26,11 +26,81 @@ (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 ((truth-map (make-hash-table :test #'equalp))) + (dolist (string '("true" "t" "yes" "on" "yup" "verily")) + (setf (gethash string truth-map) t)) + (dolist (string '("false" "nil" "no" "off" "nope" "nowise")) + (setf (gethash string truth-map) nil)) + (defun truishp (string) + "Convert STRING to a boolean." + (multiple-value-bind (val foundp) (gethash string truth-map) + (if foundp val + (error "Unrecognized boolean value `~A'" string))))) + +;;;-------------------------------------------------------------------------- ;;; Property representation. (defmethod file-location ((prop property)) (file-location (p-location prop))) +;;; Input conversions. + +(defmethod decode-property ((raw symbol)) (values :symbol raw)) +(defmethod decode-property ((raw integer)) (values :int raw)) +(defmethod decode-property ((raw string)) (values :string raw)) +(defmethod decode-property ((raw character)) (values :char raw)) +(defmethod decode-property ((raw function)) (values :func raw)) +(defmethod decode-property ((raw c-type)) (values :type raw)) +(defmethod decode-property ((raw c-fragment)) (values :c-fragment raw)) + ;;; Keywords. (defmethod coerce-property-value @@ -65,6 +135,29 @@ ((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 (and (boundp '*module-type-map*) + (gethash value *module-type-map*)) + (find-simple-c-type value) + (error "Unknown type `~A'" value))) + ;;;-------------------------------------------------------------------------- ;;; Property sets.