;;; Copyright (C) 2004, Helmut Eller (in-package :swank-backend) (import-swank-mop-symbols :pcl '(:slot-definition-documentation)) (defun swank-mop:slot-definition-documentation (slot) (documentation slot t)) ;;; missing ANSI stuff (defun readtable-case (&optional x) :upcase) (defun (setf readtable-case) (&optional x y) :upcase) (defun compiler-macro-function (&rest args) nil) (eval-when (compile load eval) (when (and (fboundp 'documentation) (not (typep (symbol-function 'documentation) 'generic-function))) (fmakunbound 'documentation))) (defgeneric documentation (x y) (:method (x y) nil) (:method ((s symbol) (k (eql 'variable))) (get s 'sys::variable-documentation)) (:method ((s symbol) (k (eql 'function))) (get s 'sys::function-documentation)) (:method ((s symbol) (k (eql 'structure))) (get s 'sys::structure-documentation)) (:method ((s symbol) (type (eql 'type))) (get s 'sys::type-documentation)) (:method ((s symbol) (type (eql 'setf))) (get s 'sys::setf-documentation))) ;;; Socket interface (lisp:clines " #include #include #include #include #include static int c_socket (void) { return socket (PF_INET, SOCK_STREAM, 0); } static int c_bind (int socket, int port) { struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons (port); addr.sin_addr.s_addr = htonl (INADDR_ANY); return bind (socket, (struct sockaddr *)&addr, sizeof addr); } static int c_local_port (int socket) { struct sockaddr_in addr; socklen_t len = sizeof addr; int code = getsockname (socket, (struct sockaddr *)&addr, &len); return (code == -1) ? -1 : ntohs (addr.sin_port); } static int c_errno (void) { return errno; } static int c_accept (int socket) { struct sockaddr_in addr; socklen_t len = sizeof addr; return accept (socket, (struct sockaddr *)&addr, &len); } static int c_set_reuse_address (int socket, int value) { return setsockopt (socket, SOL_SOCKET, SO_REUSEADDR, &value, sizeof value); } extern void setup_stream_buffer (object x); static object make_fd_stream (int fd, object name, object output_p) { object stream = (object) alloc_object (t_stream); enum smmode mode = ((output_p == Cnil) ? smm_input : smm_output); char* cmode = ((output_p == Cnil) ? \"r\" : \"w\"); FILE* fp = fdopen (fd, cmode); if (fp == NULL) RETURN1 (Cnil); stream->sm.sm_mode = mode; stream->sm.sm_fp = fp; stream->sm.sm_object0 = Cnil; stream->sm.sm_object1 = name; stream->sm.sm_int0 = fd; stream->sm.sm_int1 = 0; stream->sm.sm_flags = 0; setup_stream_buffer (stream); RETURN1 (stream); } static object compiled_closure_p (object o) { RETURN1 ((type_of (o) == t_cclosure) ? Ct : Cnil); } static object compiled_closure_env (object o) { RETURN1 (o->cc.cc_env); } ") (defmacro defentry (name (&rest atypes) (rtype cname)) (let ((type-map '((:int lisp:int) (:string lisp:string) (:object lisp:object)))) (flet ((long-type (type) (second (assoc type type-map)))) `(lisp:defentry ,name ,(mapcar #'long-type atypes) (,(long-type rtype) ,cname))))) (defentry %errno () (:int c_errno)) (defentry %strerror (:int) (:string strerror)) (defentry %socket () (:int c_socket)) (defentry %set-reuse-address (:int :int) (:int c_set_reuse_address)) (defentry %bind (:int :int) (:int c_bind)) (defentry %listen (:int :int) (:int listen)) (defentry %local-port (:int) (:int c_local_port)) (defentry %accept (:int) (:int c_accept)) (defentry %make-fd-stream (:int :object :object) (:object make_fd_stream)) (defentry %getpid () (:int getpid)) (defentry %compiled-closure-p (:object) (:object compiled_closure_p)) (defentry %compiled-closure-env (:object) (:object compiled_closure_env)) (defmacro icall ((name &rest args) &optional (error-code -1)) `(let* ((args (list ,@args)) (value (apply (function ,name) args))) (when (= value ,error-code) (error "~A ~A failed: ~A" ',name args (%strerror (%errno)))) value)) (defimplementation create-socket (host port) (declare (ignore host)) (let ((socket (icall (%socket)))) (icall (%set-reuse-address socket 1)) (icall (%bind socket port)) (icall (%listen socket 1)) socket)) (defimplementation local-port (socket) (icall (%local-port socket))) (defimplementation close-socket (socket) (warn "close-socket not implemented")) (defimplementation accept-connection (socket &key external-format) (flet ((name (string fd) (format nil "socket-~a: ~d" string fd))) (let* ((client (icall (%accept socket))) (in (%make-fd-stream client (name "input" client) nil)) (out (%make-fd-stream client (name "output" client) t))) (make-two-way-stream in out)))) (defimplementation make-fn-streams (input output) (values *standard-input* *standard-output*)) (defvar *sldb-top-frame*) (defimplementation call-with-debugging-environment (debugger) (let ((*sldb-top-frame* (si:ihs-top))) (funcall debugger))) (defun nth-frame (n) (cond ((>= n *sldb-top-frame*) nil) (t (- *sldb-top-frame* n)))) (defimplementation compute-backtrace (start end) (loop for i from start below end for f = (nth-frame i) while f collect f)) (defimplementation print-frame (frame stream) (format stream "~A" (si::ihs-fname frame))) (defimplementation frame-locals (n) (flet ((gen-local-name (i) (make-symbol (format nil "~A-~D" (string 'local) i)))) (let* ((ihs (nth-frame n)) (fname (si::ihs-fname ihs)) (dvars (get fname 'sys::debug)) (base (si:ihs-vs ihs))) (loop for i from 0 for v in dvars collect (list :name (or v (gen-local-name i)) :id 0 :value (si:vs (+ base i))))))) (defimplementation frame-var-value (frame n) (getf (nth n (frame-locals frame)) :value)) (defimplementation frame-catch-tags (n) ()) (defimplementation getpid () (%getpid)) (defimplementation lisp-implementation-type-name () "gcl") (defimplementation describe-symbol-for-emacs (symbol) (let ((result '())) (flet ((doc (kind &optional (sym symbol)) (or (documentation sym kind) :not-documented)) (maybe-push (property value) (when value (setf result (list* property value result))))) (maybe-push :variable (if (boundp symbol) (doc 'variable))) (maybe-push :function (if (fboundp symbol) (doc 'function))) (maybe-push :class (if (find-class symbol nil) (doc 'class))) (maybe-push :setf (if (pcl::setfboundp symbol) (doc 'setf))) (maybe-push :type (if (sys::known-type-p symbol) (doc 'type))) result))) (defimplementation swank-compile-file (filename load-p) (multiple-value-bind (name warnings failure) (compile-file filename) (when (and load-p name (not failure)) (load name)))) (defimplementation macroexpand-all (form) (walker:macroexpand-all form )) (defclass gcl-inspector (inspector) ()) (defimplementation make-default-inspector () (make-instance 'gcl-inspector)) (defun inspect-structure (struct) (values (format nil "~A is a structure" struct) (let* ((name (type-of struct)) (slots (sys::s-data-slot-descriptions (get name 'si::s-data)))) (loop for (name type _x _y offset) in slots append (label-value-line name (sys:structure-ref1 struct offset)))))) (defun filter-symbols (package status) (let ((accu '())) (do-symbols (sym package) (multiple-value-bind (sym sstatus) (find-symbol (string sym) package) (when (eq status sstatus) (push sym accu)))) accu)) (defun inspect-package (package) (values (format nil "~A is a package" package) (label-value-line* (:nicknames (package-nicknames package)) (:use-list (package-use-list package)) (:used-by-list (package-used-by-list package)) (:shadowing-symbols (package-shadowing-symbols package)) (:external (filter-symbols package :external)) (:internal (filter-symbols package :internal)) (:inherited (filter-symbols package :inherited))))) (defun inspect-compiled-closure (closure) (values (format nil "~A is a compiled closure" closure) (label-value-line* (:name (sys::compiled-function-name closure)) (:env (%compiled-closure-env closure))))) (defimplementation inspect-for-emacs (object (_ gcl-inspector)) (declare (ignore _)) (cond ((sys:structurep object) (inspect-structure object)) ((packagep object) (inspect-package object)) ((%compiled-closure-p object) (inspect-compiled-closure object)) (t (values "~A is an atom" (list "no details available")))))