1 1.9 christos ;; Copyright (C) 2008-2024 Free Software Foundation, Inc. 2 1.1 christos ;; 3 1.1 christos ;; This program is free software; you can redistribute it and/or modify 4 1.1 christos ;; it under the terms of the GNU General Public License as published by 5 1.1 christos ;; the Free Software Foundation; either version 3 of the License, or 6 1.1 christos ;; (at your option) any later version. 7 1.1 christos ;; 8 1.1 christos ;; This program is distributed in the hope that it will be useful, 9 1.1 christos ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 10 1.1 christos ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 1.1 christos ;; GNU General Public License for more details. 12 1.1 christos ;; 13 1.1 christos ;; You should have received a copy of the GNU General Public License 14 1.1 christos ;; along with this program. If not, see <http://www.gnu.org/licenses/>. 15 1.1 christos 16 1.1 christos ;; This file is part of the GDB testsuite. 17 1.1 christos ;; It tests Scheme pretty printers. 18 1.1 christos 19 1.1 christos (use-modules (gdb) (gdb printing)) 20 1.1 christos 21 1.1 christos (define (make-pointer-iterator pointer len) 22 1.1 christos (let ((next! (lambda (iter) 23 1.1 christos (let* ((start (iterator-object iter)) 24 1.1 christos (progress (iterator-progress iter)) 25 1.1 christos (current (car progress)) 26 1.1 christos (len (cdr progress))) 27 1.1 christos (if (= current len) 28 1.1 christos (end-of-iteration) 29 1.1 christos (let ((pointer (value-add start current))) 30 1.1 christos (set-car! progress (+ current 1)) 31 1.1 christos (cons (format #f "[~A]" current) 32 1.1 christos (value-dereference pointer)))))))) 33 1.1 christos (make-iterator pointer (cons 0 len) next!))) 34 1.1 christos 35 1.1 christos (define (make-pointer-iterator-except pointer len) 36 1.1 christos (let ((next! (lambda (iter) 37 1.1 christos (if *exception-flag* 38 1.1 christos (throw 'gdb:memory-error "hi bob")) 39 1.1 christos (let* ((start (iterator-object iter)) 40 1.1 christos (progress (iterator-progress iter)) 41 1.1 christos (current (car progress)) 42 1.1 christos (len (cdr progress))) 43 1.1 christos (if (= current len) 44 1.1 christos (end-of-iteration) 45 1.1 christos (let ((pointer (value-add start current))) 46 1.1 christos (set-car! progress (+ current 1)) 47 1.1 christos (cons (format #f "[~A]" current) 48 1.1 christos (value-dereference pointer)))))))) 49 1.1 christos (make-iterator pointer (cons 0 len) next!))) 50 1.1 christos 51 1.1 christos ;; Test returning a <gdb:value> from a printer. 52 1.1 christos 53 1.1 christos (define (make-string-printer val) 54 1.1 christos (make-pretty-printer-worker 55 1.1 christos #f 56 1.1 christos (lambda (printer) 57 1.1 christos (value-field (value-field val "whybother") 58 1.1 christos "contents")) 59 1.1 christos #f)) 60 1.1 christos 61 1.1 christos ;; Test a printer with children. 62 1.1 christos 63 1.1 christos (define (make-container-printer val) 64 1.1 christos ;; This is a little different than the Python version in that if there's 65 1.1 christos ;; an error accessing these fields we'll throw it at matcher time instead 66 1.1 christos ;; of at printer time. Done this way to explore the possibilities. 67 1.1 christos (let ((name (value-field val "name")) 68 1.1 christos (len (value-field val "len")) 69 1.1 christos (elements (value-field val "elements"))) 70 1.1 christos (make-pretty-printer-worker 71 1.1 christos #f 72 1.1 christos (lambda (printer) 73 1.1 christos (format #f "container ~A with ~A elements" 74 1.1 christos name len)) 75 1.1 christos (lambda (printer) 76 1.1 christos (make-pointer-iterator elements (value->integer len)))))) 77 1.1 christos 78 1.1 christos ;; Test "array" display hint. 79 1.1 christos 80 1.1 christos (define (make-array-printer val) 81 1.1 christos (let ((name (value-field val "name")) 82 1.1 christos (len (value-field val "len")) 83 1.1 christos (elements (value-field val "elements"))) 84 1.1 christos (make-pretty-printer-worker 85 1.1 christos "array" 86 1.1 christos (lambda (printer) 87 1.1 christos (format #f "array ~A with ~A elements" 88 1.1 christos name len)) 89 1.1 christos (lambda (printer) 90 1.1 christos (make-pointer-iterator elements (value->integer len)))))) 91 1.1 christos 92 1.1 christos ;; Flag to make no-string-container printer throw an exception. 93 1.1 christos 94 1.1 christos (define *exception-flag* #f) 95 1.1 christos 96 1.1 christos ;; Test a printer where to_string returns #f. 97 1.1 christos 98 1.1 christos (define (make-no-string-container-printer val) 99 1.1 christos (let ((len (value-field val "len")) 100 1.1 christos (elements (value-field val "elements"))) 101 1.1 christos (make-pretty-printer-worker 102 1.1 christos #f 103 1.1 christos (lambda (printer) #f) 104 1.1 christos (lambda (printer) 105 1.1 christos (make-pointer-iterator-except elements (value->integer len)))))) 106 1.1 christos 107 1.1 christos ;; The actual pretty-printer for pp_s is split out so that we can pass 108 1.1 christos ;; in a prefix to distinguish objfile/progspace/global. 109 1.1 christos 110 1.1 christos (define (pp_s-printer prefix val) 111 1.1 christos (let ((a (value-field val "a")) 112 1.1 christos (b (value-field val "b"))) 113 1.1 christos (if (not (value=? (value-address a) b)) 114 1.1 christos (error (format #f "&a(~A) != b(~A)" 115 1.1 christos (value-address a) b))) 116 1.1 christos (format #f "~aa=<~A> b=<~A>" prefix a b))) 117 1.1 christos 118 1.1 christos (define (make-pp_s-printer val) 119 1.1 christos (make-pretty-printer-worker 120 1.1 christos #f 121 1.1 christos (lambda (printer) 122 1.1 christos (pp_s-printer "" val)) 123 1.1 christos #f)) 124 1.1 christos 125 1.1 christos (define (make-pp_ss-printer val) 126 1.1 christos (make-pretty-printer-worker 127 1.1 christos #f 128 1.1 christos (lambda (printer) 129 1.1 christos (let ((a (value-field val "a")) 130 1.1 christos (b (value-field val "b"))) 131 1.1 christos (format #f "a=<~A> b=<~A>" a b))) 132 1.1 christos #f)) 133 1.1 christos 134 1.1 christos (define (make-pp_sss-printer val) 135 1.1 christos (make-pretty-printer-worker 136 1.1 christos #f 137 1.1 christos (lambda (printer) 138 1.1 christos (let ((a (value-field val "a")) 139 1.1 christos (b (value-field val "b"))) 140 1.1 christos (format #f "a=<~A> b=<~A>" a b))) 141 1.1 christos #f)) 142 1.1 christos 143 1.1 christos (define (make-pp_multiple_virtual-printer val) 144 1.1 christos (make-pretty-printer-worker 145 1.1 christos #f 146 1.1 christos (lambda (printer) 147 1.1 christos (format #f "pp value variable is: ~A" (value-field val "value"))) 148 1.1 christos #f)) 149 1.1 christos 150 1.1 christos (define (make-pp_vbase1-printer val) 151 1.1 christos (make-pretty-printer-worker 152 1.1 christos #f 153 1.1 christos (lambda (printer) 154 1.1 christos (format #f "pp class name: ~A" (type-tag (value-type val)))) 155 1.1 christos #f)) 156 1.1 christos 157 1.1 christos (define (make-pp_nullstr-printer val) 158 1.1 christos (make-pretty-printer-worker 159 1.1 christos #f 160 1.1 christos (lambda (printer) 161 1.1 christos (value->string (value-field val "s") 162 1.1 christos #:encoding (arch-charset (current-arch)))) 163 1.1 christos #f)) 164 1.1 christos 165 1.1 christos (define (make-pp_ns-printer val) 166 1.1 christos (make-pretty-printer-worker 167 1.1 christos "string" 168 1.1 christos (lambda (printer) 169 1.1 christos (let ((len (value-field val "length"))) 170 1.1 christos (value->string (value-field val "null_str") 171 1.1 christos #:encoding (arch-charset (current-arch)) 172 1.1 christos #:length (value->integer len)))) 173 1.1 christos #f)) 174 1.1 christos 175 1.1 christos (define *pp-ls-encoding* #f) 176 1.1 christos 177 1.1 christos (define (make-pp_ls-printer val) 178 1.1 christos (make-pretty-printer-worker 179 1.1 christos "string" 180 1.1 christos (lambda (printer) 181 1.1 christos (if *pp-ls-encoding* 182 1.1 christos (value->lazy-string (value-field val "lazy_str") 183 1.1 christos #:encoding *pp-ls-encoding*) 184 1.1 christos (value->lazy-string (value-field val "lazy_str")))) 185 1.1 christos #f)) 186 1.1 christos 187 1.1 christos (define (make-pp_hint_error-printer val) 188 1.1 christos "Use an invalid value for the display hint." 189 1.1 christos (make-pretty-printer-worker 190 1.1 christos 42 191 1.1 christos (lambda (printer) "hint_error_val") 192 1.1 christos #f)) 193 1.1 christos 194 1.1 christos (define (make-pp_children_as_list-printer val) 195 1.1 christos (make-pretty-printer-worker 196 1.1 christos #f 197 1.1 christos (lambda (printer) "children_as_list_val") 198 1.1 christos (lambda (printer) (make-list-iterator (list (cons "one" 1)))))) 199 1.1 christos 200 1.1 christos (define (make-pp_outer-printer val) 201 1.1 christos (make-pretty-printer-worker 202 1.1 christos #f 203 1.1 christos (lambda (printer) 204 1.1 christos (format #f "x = ~A" (value-field val "x"))) 205 1.1 christos (lambda (printer) 206 1.1 christos (make-list-iterator (list (cons "s" (value-field val "s")) 207 1.1 christos (cons "x" (value-field val "x"))))))) 208 1.1 christos 209 1.1 christos (define (make-memory-error-string-printer val) 210 1.1 christos (make-pretty-printer-worker 211 1.1 christos "string" 212 1.1 christos (lambda (printer) 213 1.1 christos (scm-error 'gdb:memory-error "memory-error-printer" 214 1.1 christos "Cannot access memory." '() '())) 215 1.1 christos #f)) 216 1.1 christos 217 1.1 christos (define (make-pp_eval_type-printer val) 218 1.1 christos (make-pretty-printer-worker 219 1.1 christos #f 220 1.1 christos (lambda (printer) 221 1.1 christos (execute "bt" #:to-string #t) 222 1.1 christos (format #f "eval=<~A>" 223 1.1 christos (value-print 224 1.1 christos (parse-and-eval 225 1.1 christos "eval_func (123456789, 2, 3, 4, 5, 6, 7, 8)")))) 226 1.1 christos #f)) 227 1.1 christos 228 1.1 christos (define (get-type-for-printing val) 229 1.1 christos "Return type of val, stripping away typedefs, etc." 230 1.1 christos (let ((type (value-type val))) 231 1.1 christos (if (= (type-code type) TYPE_CODE_REF) 232 1.1 christos (set! type (type-target type))) 233 1.1 christos (type-strip-typedefs (type-unqualified type)))) 234 1.1 christos 235 1.1 christos (define (disable-matcher!) 236 1.1 christos (set-pretty-printer-enabled! *pretty-printer* #f)) 237 1.1 christos 238 1.1 christos (define (enable-matcher!) 239 1.1 christos (set-pretty-printer-enabled! *pretty-printer* #t)) 240 1.1 christos 241 1.1 christos (define (make-pretty-printer-dict) 242 1.1 christos (let ((dict (make-hash-table))) 243 1.1 christos (hash-set! dict "struct s" make-pp_s-printer) 244 1.1 christos (hash-set! dict "s" make-pp_s-printer) 245 1.1 christos (hash-set! dict "S" make-pp_s-printer) 246 1.1 christos 247 1.1 christos (hash-set! dict "struct ss" make-pp_ss-printer) 248 1.1 christos (hash-set! dict "ss" make-pp_ss-printer) 249 1.1 christos (hash-set! dict "const S &" make-pp_s-printer) 250 1.1 christos (hash-set! dict "SSS" make-pp_sss-printer) 251 1.1 christos 252 1.1 christos (hash-set! dict "VirtualTest" make-pp_multiple_virtual-printer) 253 1.1 christos (hash-set! dict "Vbase1" make-pp_vbase1-printer) 254 1.1 christos 255 1.1 christos (hash-set! dict "struct nullstr" make-pp_nullstr-printer) 256 1.1 christos (hash-set! dict "nullstr" make-pp_nullstr-printer) 257 1.1 christos 258 1.1 christos ;; Note that we purposely omit the typedef names here. 259 1.1 christos ;; Printer lookup is based on canonical name. 260 1.1 christos ;; However, we do need both tagged and untagged variants, to handle 261 1.1 christos ;; both the C and C++ cases. 262 1.1 christos (hash-set! dict "struct string_repr" make-string-printer) 263 1.1 christos (hash-set! dict "struct container" make-container-printer) 264 1.1 christos (hash-set! dict "struct justchildren" make-no-string-container-printer) 265 1.1 christos (hash-set! dict "string_repr" make-string-printer) 266 1.1 christos (hash-set! dict "container" make-container-printer) 267 1.1 christos (hash-set! dict "justchildren" make-no-string-container-printer) 268 1.1 christos 269 1.1 christos (hash-set! dict "struct ns" make-pp_ns-printer) 270 1.1 christos (hash-set! dict "ns" make-pp_ns-printer) 271 1.1 christos 272 1.1 christos (hash-set! dict "struct lazystring" make-pp_ls-printer) 273 1.1 christos (hash-set! dict "lazystring" make-pp_ls-printer) 274 1.1 christos 275 1.1 christos (hash-set! dict "struct outerstruct" make-pp_outer-printer) 276 1.1 christos (hash-set! dict "outerstruct" make-pp_outer-printer) 277 1.1 christos 278 1.1 christos (hash-set! dict "struct hint_error" make-pp_hint_error-printer) 279 1.1 christos (hash-set! dict "hint_error" make-pp_hint_error-printer) 280 1.1 christos 281 1.1 christos (hash-set! dict "struct children_as_list" 282 1.1 christos make-pp_children_as_list-printer) 283 1.1 christos (hash-set! dict "children_as_list" make-pp_children_as_list-printer) 284 1.1 christos 285 1.1 christos (hash-set! dict "memory_error" make-memory-error-string-printer) 286 1.1 christos 287 1.1 christos (hash-set! dict "eval_type_s" make-pp_eval_type-printer) 288 1.1 christos 289 1.1 christos dict)) 290 1.1 christos 291 1.1 christos ;; This is one way to register a printer that is composed of several 292 1.1 christos ;; subprinters, but there's no way to disable or list individual subprinters. 293 1.1 christos 294 1.1 christos (define (make-pretty-printer-from-dict name dict lookup-maker) 295 1.1 christos (make-pretty-printer 296 1.1 christos name 297 1.1 christos (lambda (matcher val) 298 1.1 christos (let ((printer-maker (lookup-maker dict val))) 299 1.1 christos (and printer-maker (printer-maker val)))))) 300 1.1 christos 301 1.1 christos (define (lookup-pretty-printer-maker-from-dict dict val) 302 1.1 christos (let ((type-name (type-tag (get-type-for-printing val)))) 303 1.1 christos (and type-name 304 1.1 christos (hash-ref dict type-name)))) 305 1.1 christos 306 1.1 christos (define *pretty-printer* 307 1.1 christos (make-pretty-printer-from-dict "pretty-printer-test" 308 1.1 christos (make-pretty-printer-dict) 309 1.1 christos lookup-pretty-printer-maker-from-dict)) 310 1.1 christos 311 1.1 christos (append-pretty-printer! #f *pretty-printer*) 312 1.1 christos 313 1.1 christos ;; Different versions of a simple pretty-printer for use in testing 314 1.1 christos ;; objfile/progspace lookup. 315 1.1 christos 316 1.1 christos (define (make-objfile-pp_s-printer val) 317 1.1 christos (make-pretty-printer-worker 318 1.1 christos #f 319 1.1 christos (lambda (printer) 320 1.1 christos (pp_s-printer "objfile " val)) 321 1.1 christos #f)) 322 1.1 christos 323 1.1 christos (define (install-objfile-pretty-printers! pspace objfile-name) 324 1.1 christos (let ((objfiles (filter (lambda (objfile) 325 1.1 christos (string-contains (objfile-filename objfile) 326 1.1 christos objfile-name)) 327 1.1 christos (progspace-objfiles pspace))) 328 1.1 christos (dict (make-hash-table))) 329 1.1 christos (if (not (= (length objfiles) 1)) 330 1.1 christos (error "objfile not found or ambiguous: " objfile-name)) 331 1.1 christos (hash-set! dict "s" make-objfile-pp_s-printer) 332 1.1 christos (let ((pp (make-pretty-printer-from-dict 333 1.1 christos "objfile-pretty-printer-test" 334 1.1 christos dict lookup-pretty-printer-maker-from-dict))) 335 1.1 christos (append-pretty-printer! (car objfiles) pp)))) 336 1.1 christos 337 1.1 christos (define (make-progspace-pp_s-printer val) 338 1.1 christos (make-pretty-printer-worker 339 1.1 christos #f 340 1.1 christos (lambda (printer) 341 1.1 christos (pp_s-printer "progspace " val)) 342 1.1 christos #f)) 343 1.1 christos 344 1.1 christos (define (install-progspace-pretty-printers! pspace) 345 1.1 christos (let ((dict (make-hash-table))) 346 1.1 christos (hash-set! dict "s" make-progspace-pp_s-printer) 347 1.1 christos (let ((pp (make-pretty-printer-from-dict 348 1.1 christos "progspace-pretty-printer-test" 349 1.1 christos dict lookup-pretty-printer-maker-from-dict))) 350 1.1 christos (append-pretty-printer! pspace pp)))) 351