translator-options.lisp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. (in-package :hurd)
  2. (defclass translator-options ()
  3. ((table :initform nil
  4. :accessor table
  5. :documentation "Alist mapping option names and values."))
  6. (:documentation "Class to manage translator options."))
  7. (defun %get-symbol-name (symbol)
  8. (string-downcase (symbol-name symbol)))
  9. (defun make-translator-options (&optional option-list)
  10. "Create a new translator options object based on an option list.
  11. Example: '(:readonly (:update 30))."
  12. (let ((obj (make-instance 'translator-options)))
  13. (when option-list
  14. (set-translator-options obj option-list nil))
  15. obj))
  16. (defun %obj-to-string (obj)
  17. "Transforms a lisp object into a string."
  18. (cond
  19. ((null obj) "")
  20. ((eq t obj) "yes")
  21. (t (prin1-to-string obj))))
  22. (defun %get-string-keyword (keyword)
  23. "Return an option string. Example: :readonly -> --readonly."
  24. (concatenate-string "--"
  25. (string-downcase (symbol-name keyword))))
  26. (defun %build-option-string (base value)
  27. "Construct an option string."
  28. (if (null value)
  29. base
  30. (concatenate-string base "="
  31. (%obj-to-string value))))
  32. (defmethod get-translator-options ((options translator-options))
  33. "Build a list of string option assignments nearly ready to be passed down a foreign pointer, also good for printing."
  34. (iterate-options
  35. options
  36. (lambda (key value)
  37. (%build-option-string (%get-string-keyword key) value))))
  38. (defmethod set-translator-options ((options translator-options)
  39. option-list &optional (clear-old t))
  40. "Change the current options."
  41. ; Clear old options.
  42. (when clear-old
  43. (setf (table options) nil))
  44. (loop for option in option-list
  45. do (cond
  46. ((listp option)
  47. (push (cons (first option) (second option))
  48. (table options)))
  49. (t
  50. (push (cons option nil) (table options)))))
  51. t)
  52. (defmethod has-translator-option-p ((options translator-options) option)
  53. "Check if 'option' is enabled in this option set."
  54. (if (assoc option (table options) :test #'equal)
  55. t
  56. nil))
  57. (defmethod get-translator-option ((options translator-options) option)
  58. "Returns the value assigned to 'option' if it exists."
  59. (let ((found (assoc option (table options) :test #'equal)))
  60. (when found
  61. (if (cdr found)
  62. (cdr found)
  63. t))))
  64. (defmethod add-option ((options translator-options) option &optional value)
  65. "Add a new option to a set of translator options."
  66. (push (cons option value)
  67. (table options))
  68. options)
  69. (defmethod iterate-options ((options translator-options) (fn function))
  70. "For each option/value in options call 'fn'."
  71. (loop for (key . value) in (table options)
  72. collect (funcall fn key value)))
  73. (defun %get-keyword (str)
  74. "Return the keyword associated with string 'str'."
  75. (intern (string-upcase str) "KEYWORD"))
  76. (defun %split-options (item)
  77. "Split options, examples:
  78. 'readonly' -> :readonly
  79. 'max-files=5' -> (:max-files 5)"
  80. (let ((pos (position #\= item)))
  81. (cond
  82. ((null pos) (%get-keyword item))
  83. (t
  84. (list (%get-keyword (subseq item 0 pos))
  85. (let* ((value (subseq item (1+ pos)))
  86. (converted (read-from-string value)))
  87. (if (symbolp converted)
  88. value
  89. converted)))))))
  90. (defun get-foreign-options (ptr len)
  91. "From a foreign pointer 'ptr' with size 'len', return a translator options object."
  92. (let* ((options-list (foreign-string-zero-separated-to-list
  93. ptr len))
  94. (filtered-list ; Remove options without "--"
  95. (remove-if-not (lambda (item)
  96. (and (> (length item) 2)
  97. (string= "--"
  98. (subseq item 0 2))))
  99. options-list))
  100. (final-list ; Remove initial --
  101. (mapcar (lambda (item)
  102. (%split-options (subseq item 2)))
  103. filtered-list)))
  104. (make-translator-options final-list)))
  105. (defmethod print-object ((options translator-options) stream)
  106. "Print to 'stream' a translator options object."
  107. (format stream "#<translator-options ~a>"
  108. (get-translator-options options)))