>>>>> "Raymond" == Raymond Toy <[EMAIL PROTECTED]> writes:

>>>>> "Nicolas" == Nicolas Neuss <[EMAIL PROTECTED]> writes:

    Raymond> FWIW, here is a simpler example that demonstrates the bug:

    Raymond> (use-package "ALIEN")
    Raymond> (use-package "C-CALL")

    Raymond> (def-alien-type yes_no_t (enum yes_no_t :NO :YES))
    Raymond> (def-alien-type nil
    Raymond>     (struct foo
    Raymond>        (arg1 yes_no_t)
    Raymond>        (arg2 yes_no_t)))

    Raymond> (def-alien-routine "set_default_options" void
    Raymond>   (options (* (struct foo))))

I've finally gotten around to looking at this again.  I confess that I
know very little about how alien stuff works, but the culprit appears
to be in the def-alien-type-translator for enum in
src/code/alieneval.lisp:

(def-alien-type-translator enum (&whole type name &rest mappings)
  (cond (mappings
         (let ((result (parse-enum name mappings)))
           (when name
             (multiple-value-bind
                 (old old-p)
                 (auxiliary-alien-type :enum name)
               (when old-p
                 (unless (alien-type-= result old)
                   (warn "Redefining alien enum ~S" name))))
             (setf (auxiliary-alien-type :enum name) result))
           result))
        ...))

That (setf (auxiliary-alien-type ...)) is always done, whether the
type already exists or not.  Compare this to parse-alien-record-type:

(defun parse-alien-record-type (kind name fields)
  (if fields
      (let* ((old (and name (auxiliary-alien-type kind name)))
             (result (if (or (null old)
                             (alien-record-type-fields old))
                         (make-alien-record-type :name name :kind kind)
                         old)))
        (when (and name (not (eq old result)))
          (setf (auxiliary-alien-type kind name) result))
        (parse-alien-record-fields result fields)
        result)
     ...))

In this case, the setf auxiliary-alien-type is done only if the old
type and the result type are not eq.  

I suspect we can should do the same for enum---if the old type is
equivalent to the result, we can skip the setf.  This seems to work
with the sample (giving an error about set_default_options being an
undefined foreign symbol, of course).  Something like:

(def-alien-type-translator enum (&whole type name &rest mappings)
  (cond (mappings
         (let ((result (parse-enum name mappings)))
           (when name
             (multiple-value-bind (old old-p)
                 (auxiliary-alien-type :enum name)
               (when old-p
                 (unless (alien-type-= result old)
                   (warn "Redefining alien enum ~S" name)))
               (when (or (not old-p)
                         (not (alien-type-= result old)))
                 (setf (auxiliary-alien-type :enum name) result))))
           result))
    ...))

I know this is very likely too late to help, but if you have time, I'd
like to see if this solves the problem for you.

Ray



Reply via email to