Function: unsafep
unsafep is an autoloaded and byte-compiled function defined in
unsafep.el.gz.
Signature
(unsafep FORM &optional VARS)
Documentation
Return nil if evaluating FORM couldn't possibly do any harm.
Otherwise result is a reason why FORM is unsafe.
VARS is a list of symbols with local bindings like unsafep-vars.
Probably introduced at or before Emacs version 22.1.
Source Code
;; Defined in /usr/src/emacs/lisp/emacs-lisp/unsafep.el.gz
;;;###autoload
(defun unsafep (form &optional vars)
"Return nil if evaluating FORM couldn't possibly do any harm.
Otherwise result is a reason why FORM is unsafe.
VARS is a list of symbols with local bindings like `unsafep-vars'."
(catch 'unsafep
(if (or (eq safe-functions t) ;User turned off safety-checking
(atom form)) ;Atoms are never unsafe
(throw 'unsafep nil))
(let* ((unsafep-vars vars)
(fun (car form))
(reason (unsafep-function fun))
arg)
(cond
((not reason)
;;It's a normal function - unsafe if any arg is
(unsafep-progn (cdr form)))
((eq fun 'quote)
;;Never unsafe
nil)
((memq fun '(apply mapc mapcar mapconcat))
;;Unsafe if 1st arg isn't a quoted lambda
(setq arg (cadr form))
(cond
((memq (car-safe arg) '(quote function))
(setq reason (unsafep-function (cadr arg))))
((eq (car-safe arg) 'lambda)
;;Self-quoting lambda
(setq reason (unsafep arg unsafep-vars)))
(t
(setq reason `(unquoted ,arg))))
(or reason (unsafep-progn (cddr form))))
((eq fun 'lambda)
;;First arg is temporary bindings
(mapc #'(lambda (x)
(or (memq x '(&optional &rest))
(let ((y (unsafep-variable x t)))
(if y (throw 'unsafep y))
(push x unsafep-vars))))
(cadr form))
(unsafep-progn (cddr form)))
((eq fun 'let)
;;Creates temporary bindings in one step
(setq unsafep-vars (nconc (mapcar #'unsafep-let (cadr form))
unsafep-vars))
(unsafep-progn (cddr form)))
((eq fun 'let*)
;;Creates temporary bindings iteratively
(dolist (x (cadr form))
(push (unsafep-let x) unsafep-vars))
(unsafep-progn (cddr form)))
((eq fun 'setq)
;;Safe if odd arguments are local-var syms, evens are safe exprs
(setq arg (cdr form))
(while arg
(setq reason (or (unsafep-variable (car arg) nil)
(unsafep (cadr arg) unsafep-vars)))
(if reason (throw 'unsafep reason))
(setq arg (cddr arg))))
((eq fun 'pop)
;;safe if arg is local-var sym
(unsafep-variable (cadr form) nil))
((eq fun 'push)
;;Safe if 2nd arg is a local-var sym
(or (unsafep (cadr form) unsafep-vars)
(unsafep-variable (nth 2 form) nil)))
((eq fun 'add-to-list)
;;Safe if first arg is a quoted local-var sym
(setq arg (cadr form))
(if (not (eq (car-safe arg) 'quote))
`(unquoted ,arg)
(or (unsafep-variable (cadr arg) nil)
(unsafep-progn (cddr form)))))
((eq fun 'cond)
;;Special form with unusual syntax - safe if all args are
(dolist (x (cdr form))
(setq reason (unsafep-progn x))
(if reason (throw 'unsafep reason))))
((memq fun '(dolist dotimes))
;;Safe if COUNT and RESULT are safe. VAR is bound while checking BODY.
(setq arg (cadr form))
(or (unsafep-progn (cdr arg))
(let ((unsafep-vars (cons (car arg) unsafep-vars)))
(unsafep-progn (cddr form)))))
((eq fun 'condition-case)
;;Special form with unusual syntax - safe if all args are
(or (unsafep-variable (cadr form) t)
(unsafep (nth 2 form) unsafep-vars)
(let ((unsafep-vars (cons (cadr form) unsafep-vars)))
;;var is bound only during handlers
(dolist (x (nthcdr 3 form))
(setq reason (unsafep-progn (cdr x)))
(if reason (throw 'unsafep reason))))))
((eq fun '\`)
;; Backquoted form - safe if its expansion is.
(unsafep (cdr (backquote-process (cadr form)))))
(t
;;First unsafep-function call above wasn't nil, no special case applies
reason)))))