src/{module-impl,utilities}.lisp: Make `#line' work when pretty-printing.
[sod] / src / c-types-impl.lisp
CommitLineData
abdf50aa
MW
1;;; -*-lisp-*-
2;;;
dea4d055 3;;; C type representation implementation
abdf50aa 4;;;
dea4d055 5;;; (c) 2009 Straylight/Edgeware
abdf50aa
MW
6;;;
7
8;;;----- Licensing notice ---------------------------------------------------
9;;;
e0808c47 10;;; This file is part of the Sensible Object Design, an object system for C.
abdf50aa
MW
11;;;
12;;; SOD is free software; you can redistribute it and/or modify
13;;; it under the terms of the GNU General Public License as published by
14;;; the Free Software Foundation; either version 2 of the License, or
15;;; (at your option) any later version.
16;;;
17;;; SOD is distributed in the hope that it will be useful,
18;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;;; GNU General Public License for more details.
21;;;
22;;; You should have received a copy of the GNU General Public License
23;;; along with SOD; if not, write to the Free Software Foundation,
24;;; Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25
26(cl:in-package #:sod)
27
28;;;--------------------------------------------------------------------------
dea4d055
MW
29;;; Interning types.
30
31(defparameter *c-type-intern-map* (make-hash-table :test #'equal)
32 "Hash table mapping lists describing types to their distinguished
33 representations.")
34
35(defun intern-c-type (class &rest initargs)
36 "If the CLASS and INITARGS have already been interned, then return the
37 existing object; otherwise make a new one."
38 (let ((list (cons class initargs)))
39 (or (gethash list *c-type-intern-map*)
40 (let ((new (apply #'make-instance class initargs)))
41 (setf (gethash new *c-type-intern-map*) t
42 (gethash list *c-type-intern-map*) new)))))
43
44#+test
45(defun check-type-intern-map ()
46 "Sanity check for the type-intern map."
47 (let ((map (make-hash-table)))
48
49 ;; Pass 1: check that interned types are consistent with their keys.
50 ;; Remember interned types.
51 (maphash (lambda (k v)
52 (when (listp k)
53 (let ((ty (apply #'make-instance k)))
54 (assert (c-type-equal-p ty v)))
55 (setf (gethash v map) t)))
56 *c-type-intern-map*)
57
58 ;; Pass 2: check that the interned type indicators are correct.
59 (maphash (lambda (k v)
60 (declare (ignore v))
61 (assert (gethash k *c-type-intern-map*)))
62 map)
63 (maphash (lambda (k v)
64 (declare (ignore v))
65 (when (typep k 'c-type)
66 (assert (gethash k map))))
67 *c-type-intern-map*)))
abdf50aa 68
bf090e02
MW
69(defmethod qualify-c-type ((type qualifiable-c-type) qualifiers)
70 (let ((initargs (instance-initargs type)))
71 (remf initargs :qualifiers)
72 (apply (if (gethash type *c-type-intern-map*)
73 #'intern-c-type #'make-instance)
74 (class-of type)
75 :qualifiers (canonify-qualifiers
76 (append qualifiers (c-type-qualifiers type)))
77 initargs)))
78
abdf50aa 79;;;--------------------------------------------------------------------------
dea4d055 80;;; Simple C types.
abdf50aa 81
dea4d055 82;; Class definition.
abdf50aa 83
dea4d055
MW
84(export '(simple-c-type c-type-name))
85(defclass simple-c-type (qualifiable-c-type)
86 ((name :initarg :name :type string :reader c-type-name))
abdf50aa 87 (:documentation
dea4d055 88 "C types with simple forms."))
abdf50aa 89
dea4d055 90;; Constructor function and interning.
abdf50aa 91
dea4d055
MW
92(export 'make-simple-type)
93(defun make-simple-type (name &optional qualifiers)
94 "Make a distinguished object for the simple type called NAME."
95 (intern-c-type 'simple-c-type
96 :name name
97 :qualifiers (canonify-qualifiers qualifiers)))
abdf50aa 98
dea4d055 99;; Comparison protocol.
abdf50aa 100
dea4d055
MW
101(defmethod c-type-equal-p and
102 ((type-a simple-c-type) (type-b simple-c-type))
103 (string= (c-type-name type-a) (c-type-name type-b)))
abdf50aa 104
dea4d055 105;; C syntax output protocol.
1f1d88f5
MW
106
107(defmethod pprint-c-type ((type simple-c-type) stream kernel)
108 (pprint-logical-block (stream nil)
109 (format stream "~{~(~A~) ~@_~}~A"
110 (c-type-qualifiers type)
111 (c-type-name type))
112 (funcall kernel stream 0 t)))
abdf50aa 113
dea4d055
MW
114;; S-expression notation protocol.
115
116(defparameter *simple-type-map* (make-hash-table)
117 "Hash table mapping strings of C syntax to symbolic names.")
abdf50aa
MW
118
119(defmethod print-c-type (stream (type simple-c-type) &optional colon atsign)
120 (declare (ignore colon atsign))
121 (let* ((name (c-type-name type))
122 (symbol (gethash name *simple-type-map*)))
1f1d88f5
MW
123 (format stream "~:[~S~;~:@<~S~0@*~{ ~_~S~}~:>~]"
124 (c-type-qualifiers type) (or symbol name))))
abdf50aa 125
1f1d88f5
MW
126(eval-when (:compile-toplevel :load-toplevel :execute)
127 (defmethod expand-c-type-spec ((spec string))
128 `(make-simple-type ,spec))
129 (defmethod expand-c-type-form ((head string) tail)
dea4d055 130 `(make-simple-type ,head (list ,@tail))))
abdf50aa 131
dea4d055 132(export 'define-simple-c-type)
abdf50aa
MW
133(defmacro define-simple-c-type (names type)
134 "Define each of NAMES to be a simple type called TYPE."
1f1d88f5
MW
135 (let ((names (if (listp names) names (list names))))
136 `(progn
137 (setf (gethash ,type *simple-type-map*) ',(car names))
138 (defctype ,names ,type)
139 (define-c-type-syntax ,(car names) (&rest quals)
140 `(make-simple-type ,',type (list ,@quals))))))
abdf50aa 141
dea4d055
MW
142;; Built-in C types.
143
0e7cdea0
MW
144(export '(void
145 float double long-double
146 float-complex double-complex long-double-complex
147 float-imaginary double-imaginary long-double-imaginary
148 va-list size-t ptrdiff-t wchar-t
dea4d055
MW
149 char unsigned-char uchar signed-char schar
150 int signed signed-int sint unsigned unsigned-int uint
151 short signed-short short-int signed-short-int sshort
152 unsigned-short unsigned-short-int ushort
153 long signed-long long-int signed-long-int slong
154 unsigned-long unsigned-long-int ulong
155 long-long signed-long-long long-long-int signed-long-long-int
156 unsigned-long-long unsigned-long-long-int llong sllong ullong))
157
abdf50aa
MW
158(define-simple-c-type void "void")
159
160(define-simple-c-type char "char")
161(define-simple-c-type (unsigned-char uchar) "unsigned char")
162(define-simple-c-type (signed-char schar) "signed char")
0e7cdea0 163(define-simple-c-type wchar-t "wchar-t")
abdf50aa
MW
164
165(define-simple-c-type (int signed signed-int sint) "int")
166(define-simple-c-type (unsigned unsigned-int uint) "unsigned")
167
168(define-simple-c-type (short signed-short short-int signed-short-int sshort)
169 "short")
170(define-simple-c-type (unsigned-short unsigned-short-int ushort)
171 "unsigned short")
172
173(define-simple-c-type (long signed-long long-int signed-long-int slong)
174 "long")
175(define-simple-c-type (unsigned-long unsigned-long-int ulong)
176 "unsigned long")
177
178(define-simple-c-type (long-long signed-long-long long-long-int
179 signed-long-long-int llong sllong)
180 "long long")
181(define-simple-c-type (unsigned-long-long unsigned-long-long-int ullong)
182 "unsigned long long")
183
184(define-simple-c-type float "float")
185(define-simple-c-type double "double")
186(define-simple-c-type long-double "long double")
187
0e7cdea0
MW
188(define-simple-c-type bool "_Bool")
189
190(define-simple-c-type float-complex "float _Complex")
191(define-simple-c-type double-complex "double _Complex")
192(define-simple-c-type long-double-complex "long double _Complex")
193
194(define-simple-c-type float-imaginary "float _Imaginary")
195(define-simple-c-type double-imaginary "double _Imaginary")
196(define-simple-c-type long-double-imaginary "long double _Imaginary")
197
abdf50aa
MW
198(define-simple-c-type va-list "va_list")
199(define-simple-c-type size-t "size_t")
200(define-simple-c-type ptrdiff-t "ptrdiff_t")
201
202;;;--------------------------------------------------------------------------
dea4d055 203;;; Tagged types (enums, structs and unions).
abdf50aa 204
dea4d055 205;; Class definition.
abdf50aa 206
dea4d055 207(export '(tagged-c-type c-type-tag))
abdf50aa 208(defclass tagged-c-type (qualifiable-c-type)
77027cca 209 ((tag :initarg :tag :type string :reader c-type-tag))
abdf50aa
MW
210 (:documentation
211 "C types with tags."))
212
dea4d055
MW
213;; Subclass definitions.
214
215(export 'c-tagged-type-kind)
abdf50aa
MW
216(defgeneric c-tagged-type-kind (type)
217 (:documentation
218 "Return the kind of tagged type that TYPE is, as a keyword."))
219
dea4d055
MW
220(export 'kind-c-tagged-type)
221(defgeneric kind-c-tagged-type (kind)
222 (:documentation
223 "Given a keyword KIND, return the appropriate class name."))
224
225(export 'make-c-tagged-type)
226(defun make-c-tagged-type (kind tag &optional qualifiers)
227 "Return a tagged type with the given KIND (keyword) and TAG (string)."
228 (intern-c-type (kind-c-tagged-type kind)
229 :tag tag
230 :qualifiers (canonify-qualifiers qualifiers)))
231
abdf50aa 232(macrolet ((define-tagged-type (kind what)
dea4d055
MW
233 (let* ((type (symbolicate 'c- kind '-type))
234 (keyword (intern (symbol-name kind) :keyword))
235 (constructor (symbolicate 'make- kind '-type)))
abdf50aa 236 `(progn
bf090e02 237 (export '(,type ,kind ,constructor))
abdf50aa
MW
238 (defclass ,type (tagged-c-type) ()
239 (:documentation ,(format nil "C ~a types." what)))
240 (defmethod c-tagged-type-kind ((type ,type))
dea4d055
MW
241 ',keyword)
242 (defmethod kind-c-tagged-type ((kind (eql ',keyword)))
243 ',type)
244 (defun ,constructor (tag &optional qualifiers)
245 (intern-c-type ',type :tag tag
246 :qualifiers (canonify-qualifiers
247 qualifiers)))
1f1d88f5
MW
248 (define-c-type-syntax ,kind (tag &rest quals)
249 ,(format nil "Construct ~A type named TAG" what)
250 `(,',constructor ,tag (list ,@quals)))))))
251 (define-tagged-type enum "enumerated")
252 (define-tagged-type struct "structure")
253 (define-tagged-type union "union"))
254
dea4d055
MW
255;; Comparison protocol.
256
257(defmethod c-type-equal-p and ((type-a tagged-c-type) (type-b tagged-c-type))
258 (string= (c-type-tag type-a) (c-type-tag type-b)))
259
260;; C syntax output protocol.
261
1f1d88f5
MW
262(defmethod pprint-c-type ((type tagged-c-type) stream kernel)
263 (pprint-logical-block (stream nil)
264 (format stream "~{~(~A~) ~@_~}~(~A~) ~A"
265 (c-type-qualifiers type)
266 (c-tagged-type-kind type)
267 (c-type-tag type))
268 (funcall kernel stream 0 t)))
abdf50aa 269
dea4d055 270;; S-expression notation protocol.
abdf50aa
MW
271
272(defmethod print-c-type (stream (type tagged-c-type) &optional colon atsign)
273 (declare (ignore colon atsign))
1f1d88f5 274 (format stream "~:@<~S ~@_~S~{ ~_~S~}~:>"
abdf50aa 275 (c-tagged-type-kind type)
1f1d88f5
MW
276 (c-type-tag type)
277 (c-type-qualifiers type)))
abdf50aa
MW
278
279;;;--------------------------------------------------------------------------
280;;; Pointer types.
281
dea4d055 282;; Class definition.
abdf50aa 283
dea4d055 284(export 'c-pointer-type)
abdf50aa 285(defclass c-pointer-type (qualifiable-c-type)
77027cca 286 ((subtype :initarg :subtype :type c-type :reader c-type-subtype))
dea4d055 287 (:documentation "C pointer types."))
abdf50aa 288
dea4d055
MW
289;; Constructor function.
290
291(export 'make-pointer-type)
292(defun make-pointer-type (subtype &optional qualifiers)
293 "Return a (maybe distinguished) pointer type."
294 (let ((canonical (canonify-qualifiers qualifiers)))
295 (funcall (if (gethash subtype *c-type-intern-map*)
296 #'intern-c-type #'make-instance)
297 'c-pointer-type
298 :subtype subtype
299 :qualifiers canonical)))
300
301;; Comparison protocol.
302
303(defmethod c-type-equal-p and ((type-a c-pointer-type)
304 (type-b c-pointer-type))
305 (c-type-equal-p (c-type-subtype type-a) (c-type-subtype type-b)))
306
307;; C syntax output protocol.
1f1d88f5
MW
308
309(defmethod pprint-c-type ((type c-pointer-type) stream kernel)
310 (pprint-c-type (c-type-subtype type) stream
311 (lambda (stream prio spacep)
312 (when spacep (c-type-space stream))
313 (maybe-in-parens (stream (> prio 1))
314 (format stream "*~{~(~A~)~^ ~@_~}"
315 (c-type-qualifiers type))
316 (funcall kernel stream 1 (c-type-qualifiers type))))))
abdf50aa 317
dea4d055 318;; S-expression notation protocol.
abdf50aa
MW
319
320(defmethod print-c-type (stream (type c-pointer-type) &optional colon atsign)
321 (declare (ignore colon atsign))
dea4d055 322 (format stream "~:@<* ~@_~/sod:print-c-type/~{ ~_~S~}~:>"
1f1d88f5
MW
323 (c-type-subtype type)
324 (c-type-qualifiers type)))
abdf50aa 325
dea4d055 326(export '(* pointer ptr))
1f1d88f5 327(define-c-type-syntax * (sub &rest quals)
abdf50aa 328 "Return the type of pointer-to-SUB."
1f1d88f5
MW
329 `(make-pointer-type ,(expand-c-type-spec sub) (list ,@quals)))
330(c-type-alias * pointer ptr)
abdf50aa 331
dea4d055
MW
332;; Built-in C types.
333
334(export '(string const-string))
abdf50aa 335(defctype string (* char))
1f1d88f5 336(defctype const-string (* (char :const)))
abdf50aa
MW
337
338;;;--------------------------------------------------------------------------
339;;; Array types.
340
dea4d055 341;; Class definition.
abdf50aa 342
dea4d055 343(export '(c-array-type c-array-dimensions))
abdf50aa 344(defclass c-array-type (c-type)
77027cca
MW
345 ((subtype :initarg :subtype :type c-type :reader c-type-subtype)
346 (dimensions :initarg :dimensions :type list :reader c-array-dimensions))
abdf50aa
MW
347 (:documentation
348 "C array types."))
349
dea4d055
MW
350;; Constructor function.
351
352(export 'make-array-type)
1f1d88f5
MW
353(defun make-array-type (subtype dimensions)
354 "Return a new array of SUBTYPE with given DIMENSIONS."
355 (make-instance 'c-array-type :subtype subtype
356 :dimensions (or dimensions '(nil))))
abdf50aa 357
dea4d055
MW
358;; Comparison protocol.
359
360(defmethod c-type-equal-p and ((type-a c-array-type) (type-b c-array-type))
361
362 ;; Messy. C doesn't have multidimensional arrays, but we fake them for
363 ;; convenience's sake. But it means that we have to arrange for
364 ;; multidimensional arrays to equal vectors of vectors -- and in general
365 ;; for multidimensional arrays of multidimensional arrays to match each
366 ;; other properly, even when their dimensions don't align precisely.
367 (labels ((check (sub-a dim-a sub-b dim-b)
368 (cond ((endp dim-a)
369 (cond ((endp dim-b)
370 (c-type-equal-p sub-a sub-b))
371 ((typep sub-a 'c-array-type)
372 (check (c-type-subtype sub-a)
373 (c-array-dimensions sub-a)
374 sub-b dim-b))
375 (t
376 nil)))
377 ((endp dim-b)
378 (check sub-b dim-b sub-a dim-a))
379 ((equal (car dim-a) (car dim-b))
380 (check sub-a (cdr dim-a) sub-b (cdr dim-b)))
381 (t
382 nil))))
383 (check (c-type-subtype type-a) (c-array-dimensions type-a)
384 (c-type-subtype type-b) (c-array-dimensions type-b))))
385
386;; C syntax output protocol.
387
1f1d88f5
MW
388(defmethod pprint-c-type ((type c-array-type) stream kernel)
389 (pprint-c-type (c-type-subtype type) stream
390 (lambda (stream prio spacep)
391 (maybe-in-parens (stream (> prio 2))
392 (funcall kernel stream 2 spacep)
393 (format stream "~@<~{[~@[~A~]]~^~_~}~:>"
394 (c-array-dimensions type))))))
abdf50aa 395
dea4d055 396;; S-expression notation protocol.
abdf50aa
MW
397
398(defmethod print-c-type (stream (type c-array-type) &optional colon atsign)
399 (declare (ignore colon atsign))
dea4d055 400 (format stream "~:@<[] ~@_~:I~/sod:print-c-type/~{ ~_~S~}~:>"
abdf50aa
MW
401 (c-type-subtype type)
402 (c-array-dimensions type)))
403
dea4d055 404(export '([] array vec))
1f1d88f5 405(define-c-type-syntax [] (sub &rest dims)
abdf50aa
MW
406 "Return the type of arrays of SUB with the dimensions DIMS.
407
408 If the DIMS are omitted, a single unknown-length dimension is added."
1f1d88f5
MW
409 `(make-array-type ,(expand-c-type-spec sub)
410 (list ,@(or dims '(nil)))))
411(c-type-alias [] array vec)
abdf50aa
MW
412
413;;;--------------------------------------------------------------------------
414;;; Function types.
415
dea4d055 416;; Function arguments.
abdf50aa 417
933bbda6 418(defun argument-lists-equal-p (list-a list-b)
1f1d88f5
MW
419 "Return whether LIST-A and LIST-B match.
420
421 They must have the same number of arguments, and each argument must have
3109662a 422 the same type, or be `:ellipsis'. The argument names are not inspected."
abdf50aa
MW
423 (and (= (length list-a) (length list-b))
424 (every (lambda (arg-a arg-b)
425 (if (eq arg-a :ellipsis)
426 (eq arg-b :ellipsis)
b4aab8d4
MW
427 (and (argumentp arg-a) (argumentp arg-b)
428 (c-type-equal-p (argument-type arg-a)
429 (argument-type arg-b)))))
abdf50aa
MW
430 list-a list-b)))
431
dea4d055 432;; Class definition.
1f1d88f5 433
dea4d055 434(export '(c-function-type c-function-arguments))
1f1d88f5 435(defclass c-function-type (c-type)
77027cca 436 ((subtype :initarg :subtype :type c-type :reader c-type-subtype)
8e36de0e 437 (arguments :type list :reader c-function-arguments))
1f1d88f5
MW
438 (:documentation
439 "C function types. The subtype is the return type, as implied by the C
440 syntax for function declarations."))
441
8e36de0e
MW
442(defmethod shared-initialize :after
443 ((type c-function-type) slot-names &key (arguments nil argsp))
444 (declare (ignore slot-names))
445 (when argsp
446 (setf (slot-value type 'arguments)
447 (if (and arguments
448 (null (cdr arguments))
449 (not (eq (car arguments) :ellipsis))
450 (eq (argument-type (car arguments)) c-type-void))
451 nil
452 arguments))))
453
dea4d055
MW
454;; Constructor function.
455
456(export 'make-function-type)
1f1d88f5
MW
457(defun make-function-type (subtype arguments)
458 "Return a new function type, returning SUBTYPE and accepting ARGUMENTS."
4d89d941 459 (make-instance 'c-function-type :subtype subtype
8e36de0e 460 :arguments arguments))
1f1d88f5 461
dea4d055
MW
462;; Comparison protocol.
463
464(defmethod c-type-equal-p and
465 ((type-a c-function-type) (type-b c-function-type))
466 (and (c-type-equal-p (c-type-subtype type-a) (c-type-subtype type-b))
933bbda6
MW
467 (argument-lists-equal-p (c-function-arguments type-a)
468 (c-function-arguments type-b))))
abdf50aa 469
dea4d055 470;; C syntax output protocol.
abdf50aa 471
4d89d941
MW
472(let ((void-arglist (list (make-argument nil c-type-void))))
473 (defmethod pprint-c-type ((type c-function-type) stream kernel)
474 (pprint-c-type (c-type-subtype type) stream
475 (lambda (stream prio spacep)
476 (maybe-in-parens (stream (> prio 2))
477 (when spacep (c-type-space stream))
478 (funcall kernel stream 2 nil)
479 (pprint-indent :block 4 stream)
480 (pprint-logical-block
481 (stream nil :prefix "(" :suffix ")")
482 (let ((firstp t))
483 (dolist (arg (or (c-function-arguments type)
484 void-arglist))
485 (if firstp
486 (setf firstp nil)
487 (format stream ", ~_"))
488 (if (eq arg :ellipsis)
489 (write-string "..." stream)
490 (pprint-c-type (argument-type arg)
491 stream
492 (argument-name arg)))))))))))
1f1d88f5 493
dea4d055
MW
494;; S-expression notation protocol.
495
496(defmethod print-c-type
497 (stream (type c-function-type) &optional colon atsign)
498 (declare (ignore colon atsign))
499 (format stream "~:@<~
500 FUN ~@_~:I~/sod:print-c-type/~
501 ~{ ~_~:<~S ~@_~/sod:print-c-type/~:>~}~
502 ~:>"
503 (c-type-subtype type)
504 (mapcar (lambda (arg)
1224dfb0 505 (if (eq arg :ellipsis) arg
dea4d055
MW
506 (list (argument-name arg) (argument-type arg))))
507 (c-function-arguments type))))
abdf50aa 508
93348ae9 509(export '(fun function () func fn))
1f1d88f5 510(define-c-type-syntax fun (ret &rest args)
abdf50aa
MW
511 "Return the type of functions which returns RET and has arguments ARGS.
512
1f1d88f5
MW
513 The ARGS are a list of arguments of the form (NAME TYPE). The NAME can be
514 NIL to indicate that no name was given.
515
516 If an entry isn't a list, it's assumed to be the start of a Lisp
517 expression to compute the tail of the list; similarly, if the list is
518 improper, then it's considered to be a complete expression. The upshot of
519 this apparently bizarre rule is that you can say
520
521 (c-type (fun int (\"foo\" int) . arg-tail))
522
523 where ARG-TAIL is (almost) any old Lisp expression and have it tack the
524 arguments onto the end. Of course, there don't have to be any explicit
525 arguments at all. The only restriction is that the head of the Lisp form
526 can't be a list -- so ((lambda (...) ...) ...) is out, but you probably
527 wouldn't type that anyway."
528
529 `(make-function-type ,(expand-c-type-spec ret)
530 ,(do ((args args (cdr args))
531 (list nil
532 (cons `(make-argument ,(caar args)
533 ,(expand-c-type-spec
534 (cadar args)))
535 list)))
536 ((or (atom args) (atom (car args)))
537 (cond ((and (null args) (null list)) `nil)
538 ((null args) `(list ,@(nreverse list)))
dea4d055
MW
539 ((and (consp args)
540 (eq (car args) :ellipsis))
541 `(list ,@(nreverse list) :ellipsis))
1f1d88f5
MW
542 ((null list) `,args)
543 (t `(list* ,@(nreverse list) ,args)))))))
544(c-type-alias fun function () func fn)
abdf50aa 545
dea4d055
MW
546;; Additional utilities for dealing with functions.
547
548(export 'commentify-argument-names)
549(defun commentify-argument-names (arguments)
550 "Return an argument list with the arguments commentified.
551
3109662a
MW
552 That is, with each argument name passed through
553 `commentify-argument-name'."
dea4d055 554 (mapcar (lambda (arg)
1224dfb0 555 (if (eq arg :ellipsis) arg
dea4d055
MW
556 (make-argument (commentify-argument-name (argument-name arg))
557 (argument-type arg))))
558 arguments))
559
560(export 'commentify-function-type)
561(defun commentify-function-type (type)
562 "Return a type like TYPE, but with arguments commentified.
563
564 This doesn't recurse into the return type or argument types."
565 (make-function-type (c-type-subtype type)
566 (commentify-argument-names
567 (c-function-arguments type))))
568
abdf50aa 569;;;----- That's all, folks --------------------------------------------------