;;;; libgpg-error.lisp ;;; Copyright (C) 2006 g10 Code GmbH ;;; ;;; This file is part of libgpg-error. ;;; ;;; libgpg-error is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU Lesser General Public License ;;; as published by the Free Software Foundation; either version 2.1 of ;;; the License, or (at your option) any later version. ;;; ;;; libgpg-error is distributed in the hope that it will be useful, but ;;; WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;; Lesser General Public License for more details. ;;; ;;; You should have received a copy of the GNU Lesser General Public ;;; License along with libgpg-error; if not, write to the Free ;;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA ;;; 02111-1307, USA. ;;; Set up the library. (in-package :gpg-error) (define-foreign-library libgpg-error (:unix "libgpg-error.so") (t (:default "libgpg-error"))) (use-foreign-library libgpg-error) ;;; System dependencies. (defctype size-t :unsigned-int "The system size_t type.") ;;; Error sources. (defcenum gpg-err-source-t "The GPG error source type." (:gpg-err-source-unknown 0) (:gpg-err-source-gcrypt 1) (:gpg-err-source-gpg 2) (:gpg-err-source-gpgsm 3) (:gpg-err-source-gpgagent 4) (:gpg-err-source-pinentry 5) (:gpg-err-source-scd 6) (:gpg-err-source-gpgme 7) (:gpg-err-source-keybox 8) (:gpg-err-source-ksba 9) (:gpg-err-source-dirmngr 10) (:gpg-err-source-gsti 11) (:gpg-err-source-any 31) (:gpg-err-source-user-1 32) (:gpg-err-source-user-2 33) (:gpg-err-source-user-3 34) (:gpg-err-source-user-4 35)) (defconstant +gpg-err-source-dim+ 256) ;;; The error code type gpg-err-code-t. ;;; libgpg-error-codes.lisp is loaded by ASDF. (defctype gpg-error-t :unsigned-int "The GPG error code type.") ;;; Bit mask manipulation constants. (defconstant +gpg-err-code-mask+ (- +gpg-err-code-dim+ 1)) (defconstant +gpg-err-source-mask+ (- +gpg-err-source-dim+ 1)) (defconstant +gpg-err-source-shift+ 24) ;;; Constructor and accessor functions. ;;; If we had in-library versions of our static inlines, we wouldn't ;;; need to replicate them here. Oh well. (defun c-gpg-err-make (source code) "Construct an error value from an error code and source. Within a subsystem, use gpg-error instead." (logior (ash (logand source +gpg-err-source-mask+) +gpg-err-source-shift+) (logand code +gpg-err-code-mask+))) (defun c-gpg-err-code (err) "retrieve the error code from an error value." (logand err +gpg-err-code-mask+)) (defun c-gpg-err-source (err) "retrieve the error source from an error value." (logand (ash err (- +gpg-err-source-shift+)) +gpg-err-source-mask+)) ;;; String functions. (defcfun ("gpg_strerror" c-gpg-strerror) :string (err gpg-error-t)) (defcfun ("gpg_strsource" c-gpg-strsource) :string (err gpg-error-t)) ;;; Mapping of system errors (errno). (defcfun ("gpg_err_code_from_errno" c-gpg-err-code-from-errno) gpg-err-code-t (err :int)) (defcfun ("gpg_err_code_to_errno" c-gpg-err-code-to-errno) :int (code gpg-err-code-t)) (defcfun ("gpg_err_code_from_syserror" c-gpg-err-code-from-syserror) gpg-err-code-t) ;;; Self-documenting convenience functions. ;;; See below. ;;; ;;; ;;; Lispy interface. ;;; ;;; ;;; Low-level support functions. (defun gpg-err-code-as-value (code-key) (foreign-enum-value 'gpg-err-code-t code-key)) (defun gpg-err-code-as-key (code) (foreign-enum-keyword 'gpg-err-code-t code)) (defun gpg-err-source-as-value (source-key) (foreign-enum-value 'gpg-err-source-t source-key)) (defun gpg-err-source-as-key (source) (foreign-enum-keyword 'gpg-err-source-t source)) (defun gpg-err-canonicalize (err) "Canonicalize the error value err." (gpg-err-make (gpg-err-source err) (gpg-err-code err))) (defun gpg-err-as-value (err) "Get the integer representation of the error value ERR." (let ((error (gpg-err-canonicalize err))) (c-gpg-err-make (gpg-err-source-as-value (gpg-err-source error)) (gpg-err-code-as-value (gpg-err-code error))))) ;;; Constructor and accessor functions. (defun gpg-err-make (source code) "Construct an error value from an error code and source. Within a subsystem, use gpg-error instead." ;; As an exception to the rule, the function gpg-err-make will use ;; the error source value as is when provided as integer, instead of ;; parsing it as an error value. (list (if (integerp source) (gpg-err-source-as-key source) (gpg-err-source source)) (gpg-err-code code))) (defvar *gpg-err-source-default* :gpg-err-source-unknown "define this to specify a default source for gpg-error.") (defun gpg-error (code) "Construct an error value from an error code, using the default source." (gpg-err-make *gpg-err-source-default* code)) (defun gpg-err-code (err) "Retrieve an error code from the error value ERR." (cond ((listp err) (second err)) ((keywordp err) err) ; FIXME (t (gpg-err-code-as-key (c-gpg-err-code err))))) (defun gpg-err-source (err) "Retrieve an error source from the error value ERR." (cond ((listp err) (first err)) ((keywordp err) err) ; FIXME (t (gpg-err-source-as-key (c-gpg-err-source err))))) ;;; String functions. (defun gpg-strerror (err) "Return a string containig a description of the error code." (c-gpg-strerror (gpg-err-as-value err))) ;;; FIXME: maybe we should use this as the actual implementation for ;;; gpg-strerror. ;; (defcfun ("gpg_strerror_r" c-gpg-strerror-r) :int ;; (err gpg-error-t) ;; (buf :string) ;; (buflen size-t)) ;; (defun gpg-strerror-r (err) ;; "Return a string containig a description of the error code." ;; (with-foreign-pointer-as-string (errmsg 256 errmsg-size) ;; (c-gpg-strerror-r (gpg-err-code-as-value (gpg-err-code err)) ;; errmsg errmsg-size))) (defun gpg-strsource (err) "Return a string containig a description of the error source." (c-gpg-strsource (gpg-err-as-value err))) ;;; Mapping of system errors (errno). (defun gpg-err-code-from-errno (err) "Retrieve the error code for the system error. If the system error is not mapped, :gpg-err-unknown-errno is returned." (gpg-err-code-as-key (c-gpg-err-code-from-errno err))) (defun gpg-err-code-to-errno (code) "Retrieve the system error for the error code. If this is not a system error, 0 is returned." (c-gpg-err-code-to-errno (gpg-err-code code))) (defun gpg-err-code-from-syserror () "Retrieve the error code directly from the system ERRNO. If the system error is not mapped, :gpg-err-unknown-errno is returned and :gpg-err-missing-errno if ERRNO has the value 0." (gpg-err-code-as-key (c-gpg-err-code-from-syserror))) ;;; Self-documenting convenience functions. (defun gpg-err-make-from-errno (source err) (gpg-err-make source (gpg-err-code-from-errno err))) (defun gpg-error-from-errno (err) (gpg-error (gpg-err-code-from-errno err))) (defun gpg-error-from-syserror () (gpg-error (gpg-err-code-from-syserror)))