utils.lisp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  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. #+CCL (eval-when (:compile-toplevel :load-toplevel :exec)
  5. (defvar *standard-optimize-settings* '(optimize (speed 3) (safety 0) (space 0) (debug 0))))
  6. ;; #+SBCL (eval-when (:compile-toplevel :load-toplevel :execute)
  7. ;; (defvar *standard-optimize-settings* '(optimize (speed 3) (safety 0) (space 0) (debug 0))))
  8. (defparameter *break-on-warn-user* nil "set to T if you'd like to stop in warn-user")
  9. (defun warn-user (format-string &rest args)
  10. "Print a warning error to *ERROR-OUTPUT* and continue"
  11. (when *break-on-warn-user* (break "Breaking in WARN-USER"))
  12. (format *error-output* "~&********************************************************************************~%")
  13. #+CCL (format *error-output* "~&WARNING in ~a:: " (ccl::%last-fn-on-stack 1))
  14. (apply #'format *error-output* format-string args)
  15. (format *error-output* "~&**********************************************************************************~%"))
  16. (defparameter *max-raw-bytes-print-len* 10 "Max number of octets to print from an array")
  17. (defun printable-array (array &optional (max-len *max-raw-bytes-print-len*))
  18. "Given an array, return a string of the first *MAX-RAW-BYTES-PRINT-LEN* bytes"
  19. (declare #.utils:*standard-optimize-settings*)
  20. (let* ((len (length array))
  21. (print-len (min len max-len))
  22. (printable-array (make-array print-len :displaced-to array)))
  23. (format nil "[~:d of ~:d bytes] <~x>" print-len len printable-array)))
  24. (defun upto-null (string)
  25. "Trim STRING to end at first NULL found"
  26. (declare #.utils:*standard-optimize-settings*)
  27. (subseq string 0 (position #\Null string)))
  28. (defun dump-data (file-name data)
  29. (with-open-file (f file-name :direction :output :if-exists :supersede :element-type '(unsigned-byte 8))
  30. (write-sequence data f)))
  31. (defmacro redirect (filename &rest body)
  32. "Temporarily set *STANDARD-OUTPUT* to FILENAME and execute BODY."
  33. `(let ((*standard-output* (open ,filename :direction :output :if-does-not-exist :create :if-exists :supersede)))
  34. ,@body
  35. (finish-output *standard-output*)))
  36. (defun get-bitmask(start width)
  37. "Create a bit mask that begins at bit START (31 is MSB) and is WIDTH bits wide.
  38. Example: (get-bitmask 31 11) -->> #xffe00000"
  39. (declare #.utils:*standard-optimize-settings*)
  40. (ash (- (ash 1 width) 1) (- (1+ start) width)))
  41. (defmacro get-bitfield (int start width)
  42. "Extract WIDTH bits from INT starting at START
  43. Example: (get-bitfield #xFFFBB240 31 11) -->> #x7ff.
  44. The above will expand to (ash (logand #xFFFBB240 #xFFE00000) -21) at COMPILE time."
  45. `(ash (logand ,int ,(utils::get-bitmask start width)) ,(- ( - start width -1))))
  46. ;;;;;;;;;;;;;;;;;;;; convenience macros ;;;;;;;;;;;;;;;;;;;;
  47. (defmacro with-gensyms (syms &body body)
  48. `(let ,(mapcar #'(lambda (s)
  49. `(,s (gensym)))
  50. syms)
  51. ,@body))
  52. (defun make-keyword (name)
  53. (intern (string name) :keyword))
  54. (defmacro while (test &body body)
  55. `(do ()
  56. ((not ,test))
  57. ,@body))
  58. (defmacro aif (test-form then-form &optional else-form)
  59. `(let ((it ,test-form))
  60. (if it ,then-form ,else-form)))
  61. (defmacro awhen (test-form &body body)
  62. `(aif ,test-form
  63. (progn ,@body)))
  64. (defun mk-memoize (func)
  65. "Takes a normal function object and returns a memoized one"
  66. (let* (;(count 0)
  67. (hash-table (make-hash-table :test 'equal)))
  68. #'(lambda (arg)
  69. ;;(format t "Looking for <~a>~%" arg)
  70. (multiple-value-bind (value foundp) (gethash arg hash-table)
  71. ;;(incf count)
  72. ;; (when (> count 20)
  73. ;; (break "Breaking as requested")
  74. ;; (setf count 0))
  75. (if foundp
  76. (progn
  77. ;;(format t "Already seen <~a>~%" arg)
  78. value)
  79. (progn
  80. ;;(format t "First time seen <~a>~%" arg)
  81. (setf (gethash arg hash-table) (funcall func arg))))))))
  82. (defmacro memoize (func-name)
  83. "Memoize function associated with Function-Name. Simplified version"
  84. `(setf (symbol-function ,func-name) (utils::mk-memoize (symbol-function ,func-name))))