utils.lisp 3.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. ;;; -*- Mode: Lisp; show-trailing-whitespace: t; Base: 10; indent-tabs: nil; Syntax: ANSI-Common-Lisp; Package: UTILS; -*-
  2. ;;; Copyright (c) 2013, Mark VandenBrink. All rights reserved.
  3. (in-package #:utils)
  4. (defparameter *break-on-warn-user* nil "set to T if you'd like to stop in warn user")
  5. ;;; COMPLETELY UNPORTABLE!!!
  6. (defun warn-user (format-string &rest args)
  7. "print a warning error to *ERROR-OUTPUT* and continue"
  8. (when *break-on-warn-user* (break "Breaking in WARN-USER"))
  9. (format *error-output* "~&********************************************************************************~%")
  10. (format *error-output* "~&WARNING in ~a:: " (ccl::%last-fn-on-stack 1))
  11. (apply #'format *error-output* format-string args)
  12. (format *error-output* "~&**********************************************************************************~%"))
  13. (defparameter *max-raw-bytes-print-len* 10 "Max number of octets to print from an array")
  14. (defun printable-array (array &optional (max-len *max-raw-bytes-print-len*))
  15. "Given an array, return a string of the first *MAX-RAW-BYTES-PRINT-LEN* bytes"
  16. (let* ((len (length array))
  17. (print-len (min len max-len))
  18. (printable-array (make-array print-len :displaced-to array)))
  19. (format nil "[~:d of ~:d bytes] <~x>" print-len len printable-array)))
  20. (defun upto-null (string)
  21. "Trim STRING to end at first NULL found"
  22. (subseq string 0 (position #\Null string)))
  23. (defun dump-data (file-name data)
  24. (with-open-file (f file-name :direction :output :if-exists :supersede :element-type '(unsigned-byte 8))
  25. (write-sequence data f)))
  26. (defmethod has-extension ((n string) ext)
  27. "Probably should use CL's PATHNAME methods, but simply looking at the .XXX portion of a filename
  28. to see if it matches. This is the string version that makes a PATHNAME and calls the PATHNAME version."
  29. (has-extension (parse-namestring n) ext))
  30. (defmethod has-extension ((p pathname) ext)
  31. "Probably should use CL's PATHNAME methods , but simply looking at the .XXX portion of a filename
  32. to see if it matches. PATHNAME version."
  33. (let ((e (pathname-type p)))
  34. (if e
  35. (string= (string-downcase e) (string-downcase ext))
  36. nil)))
  37. (defmacro redirect (filename &rest body)
  38. "Temporarily set *STANDARD-OUTPUT* to FILENAME and execute BODY."
  39. `(let ((*standard-output* (open ,filename :direction :output :if-does-not-exist :create :if-exists :supersede)))
  40. ,@body
  41. (finish-output *standard-output*)))
  42. (defun get-bitmask(start width)
  43. "Create a bit mask that begins at bit START (31 is MSB) and is WIDTH bits wide.
  44. Example: (get-bitmask 31 11) -->> #xffe00000"
  45. (ash (- (ash 1 width) 1) (- (1+ start) width)))
  46. (defmacro get-bitfield (int start width)
  47. "Extract WIDTH bits from INT starting at START
  48. Example: (get-bitfield #xFFFBB240 31 11) -->> #x7ff.
  49. The above will expand to (ash (logand #xFFFBB240 #xFFE00000) -21) at COMPILE time."
  50. `(ash (logand ,int ,(utils::get-bitmask start width)) ,(- ( - start width -1))))
  51. ;;;;;;;;;;;;;;;;;;;; convenience macros ;;;;;;;;;;;;;;;;;;;;
  52. (defmacro with-gensyms (syms &body body)
  53. `(let ,(mapcar #'(lambda (s)
  54. `(,s (gensym)))
  55. syms)
  56. ,@body))
  57. (defun make-keyword (name)
  58. (intern (string name) :keyword))
  59. (defmacro while (test &body body)
  60. `(do ()
  61. ((not ,test))
  62. ,@body))
  63. (defmacro aif (test-form then-form &optional else-form)
  64. `(let ((it ,test-form))
  65. (if it ,then-form ,else-form)))
  66. (defmacro awhen (test-form &body body)
  67. `(aif ,test-form
  68. (progn ,@body)))
  69. (defmacro fastest (&body body)
  70. `(locally (declare (optimize (speed 3) (safety 0) (debug 0)))
  71. ,@body))