Function: c-in-knr-argdecl
c-in-knr-argdecl is a byte-compiled function defined in
cc-engine.el.gz.
Signature
(c-in-knr-argdecl &optional LIM)
Source Code
;; Defined in /usr/src/emacs/lisp/progmodes/cc-engine.el.gz
(defun c-in-knr-argdecl (&optional lim)
;; Return the position of the first argument declaration if point is
;; inside a K&R style argument declaration list, nil otherwise.
;; `c-recognize-knr-p' is not checked. If LIM is non-nil, it's a
;; position that bounds the backward search for the argument list. This
;; function doesn't move point.
;;
;; Point must be within a possible K&R region, e.g. just before a top-level
;; "{". It must be outside of parens and brackets. The test can return
;; false positives otherwise.
;;
;; This function might do hidden buffer changes.
(save-excursion
(save-restriction
;; If we're in a macro, our search range is restricted to it. Narrow to
;; the searchable range.
(let* ((macro-start (save-excursion (and (c-beginning-of-macro) (point))))
(macro-end (save-excursion (and macro-start (c-end-of-macro) (point))))
(low-lim (max (or lim (point-min)) (or macro-start (point-min))))
before-lparen after-rparen
(here (point))
(pp-count-out 20) ; Max number of paren/brace constructs before
; we give up
ids ; List of identifiers in the parenthesized list.
id-start after-prec-token decl-or-cast
c-last-identifier-range semi-position+1)
(narrow-to-region low-lim (or macro-end (point-max)))
;; Search backwards for the defun's argument list. We give up if we
;; encounter a "}" (end of a previous defun) an "=" (which can't be in
;; a knr region) or BOB.
;;
;; The criterion for a paren structure being the arg list is:
;; o - there is non-WS stuff after it but before any "{"; AND
;; o - the token after it isn't a ";" AND
;; o - it is preceded by either an identifier (the function name) or
;; a macro expansion like "DEFUN (...)"; AND
;; o - its content is a non-empty comma-separated list of identifiers
;; (an empty arg list won't have a knr region).
;;
;; The following snippet illustrates these rules:
;; int foo (bar, baz, yuk)
;; int bar [] ;
;; int (*baz) (my_type) ;
;; int (*(* yuk) (void)) (void) ;
;; {
;;
;; Additionally, for a knr list to be recognized:
;; o - The identifier of each declarator up to and including the
;; one "near" point must be contained in the arg list.
(catch 'knr
(while (> pp-count-out 0) ; go back one paren/bracket pair each time.
(setq pp-count-out (1- pp-count-out))
(c-syntactic-skip-backward "^)]}=")
(cond ((eq (char-before) ?\))
(setq after-rparen (point)))
((eq (char-before) ?\])
(setq after-rparen nil))
(t ; either } (hit previous defun) or = or no more
; parens/brackets.
(throw 'knr nil)))
(if after-rparen
;; We're inside a paren. Could it be our argument list....?
(if
(and
(progn
(goto-char after-rparen)
(unless (c-go-list-backward) (throw 'knr nil)) ;
;; FIXME!!! What about macros between the parens? 2007/01/20
(setq before-lparen (point)))
;; It can't be the arg list if next token is ; or {
(progn (goto-char after-rparen)
(c-forward-syntactic-ws)
(not (memq (char-after) '(?\; ?\{ ?\=))))
;; Is the thing preceding the list an identifier (the
;; function name), or a macro expansion?
(progn
(goto-char before-lparen)
(eq (c-backward-token-2) 0)
(or (eq (c-on-identifier) (point))
(and (eq (char-after) ?\))
(c-go-up-list-backward)
(eq (c-backward-token-2) 0)
(eq (c-on-identifier) (point)))))
;; Have we got a non-empty list of comma-separated
;; identifiers?
(progn
(goto-char before-lparen)
(and
(c-forward-over-token-and-ws) ; to first token inside parens
(setq id-start (c-on-identifier)) ; Must be at least one.
(catch 'id-list
(while
(progn
(forward-char)
(c-end-of-current-token)
(push (buffer-substring-no-properties id-start
(point))
ids)
(c-forward-syntactic-ws)
(eq (char-after) ?\,))
(c-forward-over-token-and-ws)
(unless (setq id-start (c-on-identifier))
(throw 'id-list nil)))
(eq (char-after) ?\)))))
;; Are all the identifiers in the k&r list up to the
;; current one also in the argument list?
(progn
(forward-char) ; over the )
(setq after-prec-token after-rparen)
(c-forward-syntactic-ws)
;; Each time around the following checks one
;; declaration (which may contain several identifiers).
(while (and
(consp (setq decl-or-cast
(c-forward-decl-or-cast-1
after-prec-token
nil ; Or 'arglist ???
nil)))
(memq (char-after) '(?\; ?\,))
(goto-char (car decl-or-cast))
(save-excursion
(setq semi-position+1
(c-syntactic-re-search-forward
";" (+ (point) 1000) t)))
(c-do-declarators
semi-position+1 t nil nil
(lambda (id-start id-end _next _not-top
_func _init)
(if (not (member
(buffer-substring-no-properties
id-start id-end)
ids))
(throw 'knr nil))))
(progn (forward-char)
(<= (point) here))
(progn (c-forward-syntactic-ws)
t)))
t))
;; ...Yes. We've identified the function's argument list.
(throw 'knr
(progn (goto-char after-rparen)
(c-forward-syntactic-ws)
(point)))
;; ...No. The current parens aren't the function's arg list.
(goto-char before-lparen))
(or (c-go-list-backward) ; backwards over [ .... ]
(throw 'knr nil)))))))))