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
			       (not (eq (char-after) ?{))
			       (or
				(consp (setq decl-or-cast
					     (c-forward-decl-or-cast-1
					      after-prec-token
					      nil ; Or 'arglist ???
					      nil)))
				(throw 'knr 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)))))))))