+;;; Parse a string of the form NAME, PACKAGE:NAME or
+;;; PACKAGE::NAME and return the name. If the string is of the
+;;; form 1) or 3), but the symbol does not exist, it will be created
+;;; and interned in that package.
+(defun read-symbol (string)
+ (let ((size (length string))
+ package name internalp index)
+ (setq index 0)
+ (while (and (< index size)
+ (not (char= (char string index) #\:)))
+ (incf index))
+ (cond
+ ;; No package prefix
+ ((= index size)
+ (setq name string)
+ (setq package *package*)
+ (setq internalp t))
+ (t
+ ;; Package prefix
+ (if (zerop index)
+ (setq package "KEYWORD")
+ (setq package (string-upcase (subseq string 0 index))))
+ (incf index)
+ (when (char= (char string index) #\:)
+ (setq internalp t)
+ (incf index))
+ (setq name (subseq string index))))
+ ;; Canonalize symbol name and package
+ (setq name (string-upcase name))
+ (setq package (find-package package))
+ ;; TODO: PACKAGE:SYMBOL should signal error if SYMBOL is not an
+ ;; external symbol from PACKAGE.
+ (if (or internalp (eq package (find-package "KEYWORD")))
+ (intern name package)
+ (find-symbol name package))))
+
+(defvar *eof* (gensym))