internal.scm 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. ;;; guile-gcrypt --- crypto tooling for guile
  2. ;;; Copyright © 2019 Ludovic Courtès <ludo@gnu.org>
  3. ;;;
  4. ;;; This file is part of guile-gcrypt.
  5. ;;;
  6. ;;; guile-gcrypt is free software; you can redistribute it and/or modify it
  7. ;;; under the terms of the GNU General Public License as published by
  8. ;;; the Free Software Foundation; either version 3 of the License, or
  9. ;;; (at your option) any later version.
  10. ;;;
  11. ;;; guile-gcrypt is distributed in the hope that it will be useful, but
  12. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. ;;; General Public License for more details.
  15. ;;;
  16. ;;; You should have received a copy of the GNU General Public License
  17. ;;; along with guile-gcrypt. If not, see <http://www.gnu.org/licenses/>.
  18. (define-module (gcrypt internal)
  19. #:use-module (gcrypt package-config)
  20. #:use-module (system foreign)
  21. #:export (libgcrypt->pointer
  22. libgcrypt->procedure
  23. define-enumerate-type
  24. define-lookup-procedure
  25. gcrypt-version))
  26. ;;; Code:
  27. ;;;
  28. ;;; This module provides tools for internal use. The API of this module may
  29. ;;; change anytime; you should not rely on it. Loading this module
  30. ;;; initializes Libgcrypt as a side effect.
  31. ;;;
  32. ;;; Comment:
  33. (define (libgcrypt->pointer name)
  34. "Return a pointer to symbol FUNC in libgcrypt."
  35. (catch #t
  36. (lambda ()
  37. (dynamic-func name (dynamic-link %libgcrypt)))
  38. (lambda args
  39. (lambda _
  40. (throw 'system-error name "~A" (list (strerror ENOSYS))
  41. (list ENOSYS))))))
  42. (define (libgcrypt->procedure return name params)
  43. "Return a pointer to symbol FUNC in libgcrypt."
  44. (catch #t
  45. (lambda ()
  46. (let ((ptr (dynamic-func name (dynamic-link %libgcrypt))))
  47. ;; The #:return-errno? facility was introduced in Guile 2.0.12.
  48. (pointer->procedure return ptr params
  49. #:return-errno? #t)))
  50. (lambda args
  51. (lambda _
  52. (throw 'system-error name "~A" (list (strerror ENOSYS))
  53. (list ENOSYS))))))
  54. (define-syntax-rule (define-enumerate-type name->integer symbol->integer
  55. (name id) ...)
  56. (begin
  57. (define-syntax name->integer
  58. (syntax-rules (name ...)
  59. "Return hash algorithm NAME."
  60. ((_ name) id) ...))
  61. (define symbol->integer
  62. (let ((alist '((name . id) ...)))
  63. (lambda (symbol)
  64. "Look up SYMBOL and return the corresponding integer or #f if it
  65. could not be found."
  66. (assq-ref alist symbol))))))
  67. (define-syntax define-lookup-procedure
  68. (lambda (s)
  69. "Define LOOKUP as a procedure that maps an integer to its corresponding
  70. value in O(1)."
  71. (syntax-case s ()
  72. ((_ lookup docstring (index value) ...)
  73. (let* ((values (syntax->datum #'((index . value) ...)))
  74. (min (apply min (syntax->datum #'(index ...))))
  75. (max (apply max (syntax->datum #'(index ...))))
  76. (array (let loop ((i max)
  77. (result '()))
  78. (if (< i min)
  79. result
  80. (loop (- i 1)
  81. (cons (or (assv-ref values i) -1)
  82. result))))))
  83. #`(define lookup
  84. ;; Allocate a big sparse vector.
  85. (let ((values '#(#,@array)))
  86. (lambda (integer)
  87. docstring
  88. (and (<= integer #,max) (>= integer #,min)
  89. (let ((result (vector-ref values (- integer #,min))))
  90. (and (> result 0) result)))))))))))
  91. (define gcrypt-version
  92. ;; According to the manual, this function must be called before any other,
  93. ;; and it's not clear whether it can be called more than once. So call it
  94. ;; right here from the top level. During cross-compilation, the call to
  95. ;; PROC fails with a 'system-error exception; catch it.
  96. (let* ((proc (libgcrypt->procedure '* "gcry_check_version" '(*)))
  97. (version (catch 'system-error
  98. (lambda ()
  99. (pointer->string (proc %null-pointer)))
  100. (const ""))))
  101. (lambda ()
  102. "Return the version number of libgcrypt as a string."
  103. version)))