[comp.sys.att] KCL on a unix-pc

alex@umbc3.UMD.EDU (Alex S. Crain) (10/11/88)

	I recently redid my port of KCL to the 3b1, and will happily mail
it to anyone interested.

	KCL (Koyto Common Lisp) is a full implementation of Steel's 
_Common Lisp the Language_, and includes a compliler. It is reletively small
for a CL system, but is still huge for a unixpc program, occupying some
4.5meg of disk space for the execuable images. (this will go down to ~3meg
as soon as I can fix undump). I have been using the system for about a year
and it works well enough.

	You will need to get a copy of the kcl distribution, about 1.3meg
compressed, which is available from a variety of archive sites.

-- 
					:alex.
					Systems Programmer
nerwin!alex@umbc3.umd.edu		UMBC
alex@umbc3.umd.edu

baur@spp2.UUCP (Steven L. Baur) (10/12/88)

in article <1246@umbc3.UMD.EDU>, alex@umbc3.UMD.EDU (Alex S. Crain) says:
> 	I recently redid my port of KCL to the 3b1 ...

I managed to port KCL to UNIXPC too, but ...

> as soon as I can fix undump). ...

failed on trying to make undump work.  The technique I used for debugging
GNU EMACS 18.51 unexec (analyze the binary on a SUN) was no help with KCL.
I tried several techniques, the hardest being converting all .BSS global
variables to .DATA.  (Compiling KCL on a UNIXPC tends to be rather hateful).

I would dearly like to know just what undump in KCL is trying to do (and how to
make it work on a UNIXPC).


> 					:alex.

steve (ucbvax!trwrb!trwspp!spp2!baur)

alex@umbc3.UMD.EDU (Alex S. Crain) (10/14/88)

In article <1470@spp2.UUCP> baur@spp2.UUCP (Steven L. Baur) writes:
>in article <1246@umbc3.UMD.EDU>, alex@umbc3.UMD.EDU (Alex S. Crain) says:
>> 	I recently redid my port of KCL to the 3b1 ...
>
>I managed to port KCL to UNIXPC too, but ...
>
>> as soon as I can fix undump). ...
>
>failed on trying to make undump work.  The technique I used for debugging

	In the spirit of unix philosophy, I decided that one undump is
enough. Emacs unexec() works but requires special linking orders and other
wonders, and the kcl undump isn't very system 5ish. TeX, however, got it
right. TeX comes with an undump program that works like this:

	1) get your target program to the state you want (loaded, or whatever)
	2) Inspire it to dump core, say with ^\
	3) % undump new_a.out old_a.out corefile
	4) THe result is a binary generated from the dumped image.

This requires no special anything on the part of the target program, and works
fine on just about anything. (I undumped less once, and the file buffers still
had stuff un them :-)).

	Undump doesn't work out of the box, but its been ported to the 3b1,
and knows about shlib, etc. I believe that Brant Cheikes did the port, but I
don't remember off hand. The only fault is that undump can't restore the symbol
table, so if you need that, you have to save the old image for reading. (Thats
the problem with KCL). I've been meaning to fix that, but I havn't had time. I
would send sources to anyone who asked.

-- 
					:alex.
					Systems Programmer
nerwin!alex@umbc3.umd.edu		UMBC
alex@umbc3.umd.edu

dave@arnold.UUCP (Dave Arnold) (10/16/88)

Does anybody know how I can format the KCL docs?  I don't have the
Kroff program.
-- 
Dave Arnold (dave@arnold.UUCP)
Work: Volt Delta Resources     Phone: (714) 921-7635
Home: 26561 Fresno street,  Mission Viejo, Ca  92691

alex@umbc3.UMD.EDU (Alex S. Crain) (10/16/88)

In article <217@arnold.UUCP> dave@arnold.UUCP (Dave Arnold) writes:
>Does anybody know how I can format the KCL docs?  I don't have the
>Kroff program.

	A TeX version of the kcl doc exists, kclreport.tex or something
close to that. Anonymous ftp from rascal.ics.utexas.edu, and probably
uunet. Note that this only covers the internals, for the fuction defs, get
_Common Lisp the Language_ by Guy Steel. This is the definition of CL, and
the model for the KCL system.

	As a side note, here is the kcl-mode that I wrote. I think that its
pretty portable, moderatly well documented, and not too discustingly coded.
It provides on line help for CL through \C-h\C-l, automatic size limits on
the interpretur buffer, and a few other funzies. Comments and critisizms are
most welcome. to use it, just load the file. I have 

(autoload 'run-kcl "kcl-mode" "" t nil)

in my startup file, so the interactive command run-kcl does it all.

------------------- cut here --------------------
;; KCL (Koyto Common Lisp) mode/environment for emacs
;; Written By Alex Crain -- alex@umbc3.umd.edu

;; Start
;;
;;

(defvar *buff-max-size* 100 
   "The maximum size that a shell buffer is allowed to become before
it is truncated from the top by (check-buffer-size).")

(defvar *buff-decrement* 10
   "The stepping value for truncating a limited buffer")

(defun check-buffer-size ()
   (interactive)
   (progn
      (save-excursion
	 (beginning-of-line)
	 (if (> (count-lines 1 (point)) *buff-max-size*)
	       (let ((save-kill kill-ring))
		  (goto-char 1)
		  (kill-line *buff-decrement*)
		  (setq kill-ring save-kill))))
      (shell-send-input)))

(defvar shell-mode-map nil)

(setq shell-mode-map (make-sparse-keymap))
                       ;;;
                       ;;; We do all this for this line...
                       ;;;
(define-key shell-mode-map "\C-m" 'check-buffer-size)

(define-key shell-mode-map "\C-c\C-d" 'shell-send-eof)
(define-key shell-mode-map "\C-c\C-u" 'kill-shell-input)
(define-key shell-mode-map "\C-c\C-w" 'backward-kill-word)
(define-key shell-mode-map "\C-c\C-c" 'interrupt-shell-subjob)
(define-key shell-mode-map "\C-c\C-z" 'stop-shell-subjob)
(define-key shell-mode-map "\C-c\C-\\" 'quit-shell-subjob)
(define-key shell-mode-map "\C-c\C-o" 'kill-output-from-shell)
(define-key shell-mode-map "\C-c\C-r" 'show-output-from-shell)
(define-key shell-mode-map "\C-c\C-y" 'copy-last-shell-input)

(load "shell")

;;
;; Redefine this here so that we can fix the documentation.
;;


(defun inferior-lisp-mode ()
""  (interactive)
  (kill-all-local-variables)
  (setq major-mode 'inferior-kcl-mode)
  (setq mode-name "Inferior KCL")
  (setq mode-line-process '(": %s"))
  (lisp-mode-variables t)
  (use-local-map inferior-lisp-mode-map)
  (make-local-variable 'last-input-start)
  (setq last-input-start (make-marker))
  (make-local-variable 'last-input-end)
  (setq last-input-end (make-marker))
  (run-hooks 'shell-mode-hook 'lisp-mode-hook))

(defun inferior-kcl-mode nil 
   "Major mode for interacting with an inferior KCL process.
A modification of inferior-lisp-mode, and is a superset of
that mode plus KCL specific extensions. Runs a KCL interpreter
as a subprocess of Emacs, with Lisp I/O through an Emacs buffer.

The lisp buffer is named 'Kcl <run>'. In addition, a shell buffer is
opened in the current directory, this buffer is called *unix*.
Emacs will recognise certain lisp expressions and respond to them. 
Currently these are:

(cd <directory>)	directory is a string or symbol refering
 			to a subdirectory. symbols are converted to 
			uppercase automatically. Emacs will respond
			by attempting to cd the buffer to the new 
			directory.

(bye)			Emacs changes the buffer name to reflect an
			inactive process, and cd's the buffer to the
			users home directory. in addition, the 'r' key
			will automatically restart the KCL process.

(exit)			emacs will query-save all the buffers and exit.

In addition, this mode knows about many of the standard CL forms for
indenting purposes.

Buffer size restrictions:
Emacs will restrict the lisp buffer to a size stored in *buffer-max-size*,
by periodically deleting the topmost lines of the buffer. This is done to
avoid extreamly large buffers generated by extended interactive lisp sessions.
The buffer is decremented whenever the buffer length (in lines) exceedes
*buffer-max-size* + *buff-decrement*, when *buff-decrement* lines will be 
deleted. The default sizes for *buff-max-size* and *buff-decrement* are
100 and 10, respectively.

Commands:
DELETE converts tabs to spaces as it moves back.
TAB indents for Lisp; with argument, shifts rest
 of expression rigidly with the current line.
Meta-Control-Q does TAB on each line starting within following expression.
Paragraphs are separated only by blank lines.  Semicolons start comments.

Return at end of buffer sends line as input.
Return not at end copies rest of line to end and sends it.

Help for common lisp is implemented in a manner simular to elisp
help. C-hC-l involks help which propts for a lisp symbol, the symbol
at the current cursor position is offered as a default.

The following commands imitate the usual Unix interrupt and
editing control characters:
\\{shell-mode-map}

Entry to this mode calls the value of lisp-mode-hook with no arguments,
if that value is non-nil.  Likewise with the value of shell-mode-hook.
lisp-mode-hook is called after shell-mode-hook.

You can send text to the inferior Lisp from other buffers
using the commands process-send-region, process-send-string
and \\[lisp-send-defun]."
(interactive)
(inferior-lisp-mode))

(shell)

(save-excursion
(set-buffer "*shell*")
(rename-buffer "*unix*"))

;(setq inferior-lisp-program "kcl")

(defvar *kcl-program-name* "kcl"
   "The name of the Koyto Common Lisp executable.")

(defun run-kcl nil 
   "The autoload tag for the kcl-mode file."
   (interactive)
   (atom t))

(defun start-kcl ()
   (interactive)
   (progn
      (define-key inferior-lisp-mode-map "r" 'self-insert-command)
      (apply 'start-process
	     "lisp"
	     (current-buffer)
	     (concat exec-directory "env")
	     (format "TERMCAP=emacs:co#%d:tc=unknown:" (screen-width))
	     "TERM=emacs"
	     "EMACS=t"
	     "-"
	     (list *kcl-program-name*))
      (rename-buffer "KCL: <Run>")))

(switch-to-buffer (get-buffer-create "KCL: <No Process>"))
(start-kcl)
(inferior-lisp-mode)
(setq mode-line-format 
      '( "                                                       %20b" ))


;;;
;;; CL forms
;;;
(put 'block 'lisp-indent-hook 0)
(put 'tagbody 'lisp-indent-hook 0)

(put 'do 'lisp-indent-hook 0)
(put 'do* 'lisp-indent-hook 0)

(put 'let 'lisp-indent-hook 1)
(put 'flet 'lisp-indent-hook 1)
(put 'macrolet 'lisp-indent-hook 1)
(put 'labels 'lisp-indent-hook 1)

(put 'loop 'lisp-indent-hook 0)

(put 'prog 'lisp-indent-hook 1)
(put 'progn 'lisp-indent-hook 0)
(put 'prog1 'lisp-indent-hook 0)
(put 'prog2 'lisp-indent-hook 0)
(put 'progv 'lisp-indent-hook 0)

(put 'if 'lisp-indent-hook 2)
(put 'when 'lisp-indent-hook 1)
(put 'unless 'lisp-indent-hook 1)
(put 'cond 'lisp-indent-hook 0)
(put 'typecase 'lisp-indent-hook 1)

(put 'dolist 'lisp-indent-hook 1)
(put 'dotimes 'lisp-indent-hook 1)

;;;
;;; indenting characteristics
;;;
   
(setq lisp-body-indent 3)
   
   
;;
;; Interactive emacs help for kcl bound to C-hC-l
;;

(defvar *help-file* "/usr/local/doc/prindoc.out")

(defun kcl-help (s &optional no-error)
   (interactive
    (let* ((sname (symbol-at-point))
	   (val (read-from-minibuffer 
		 (if (equal sname "")
		       "KCL Symbol> "
		    (format "KCL Symbol (default: %s) " (upcase sname))))))
       (list 
	(if (equal val "")
	      sname
	   val))))
   (let ((buff (or
		(get-buffer "*KCL: <Help>*")
		(gen-help-buff))))
      (save-excursion
	 (set-buffer buff)
	 (or no-error (goto-char 1))
	 (or
	  (search-forward (concat "------------------
" s " ") 512000 t)
	  (search-forward (concat "------------------
si:" s " ") 512000 t)
	  (if no-error (throw 'help-exit nil)
	     (error "No documentation on KCL Symbol %s." (upcase s)))
	  )
	 (beginning-of-line)
	 (save-excursion
	    (previous-line 1)
	    (condition-case ()
		  (split-window
		   (selected-window)
		   (min
		    (count-lines (point)
				 (progn
				    (forward-line)
				    (search-forward "------------------------")
				    (beginning-of-line)
				    (point)))
		    10))
	       (error 
		(message "base window too small to split for help screen")))))
      (switch-to-buffer buff)
      (set-window-start (selected-window) (point))
      (other-window 1)
      (catch 'help-exit (kcl-help s t))
      (bury-buffer "*KCL: <Help>*")
      ))

(defun gen-help-buff ()
   (save-excursion
      (set-buffer (find-file-noselect *help-file*))
      (rename-buffer "*KCL: <Help>*")
      (setq mode-line-format 
 '( "                                                       KCL: <Help>" ))
      (get-buffer (current-buffer))))
	      
(global-set-key "\C-h\C-l" 'kcl-help)

(defun help-for-help ()
  "You have typed C-h, the help character.  Type a Help option:

A  command-apropos.   Give a substring, and see a list of commands
              (functions interactively callable) that contain
	      that substring.  See also the  apropos  command.
B  describe-bindings.  Display table of all key bindings.
C  describe-key-briefly.  Type a command key sequence;
	      it prints the function name that sequence runs.
F  describe-function.  Type a function name and get documentation of it.
I  info. The  info  documentation reader.
K  describe-key.  Type a command key sequence;
	      it displays the full documentation.
L  view-lossage.  Shows last 100 characters you typed.
M  describe-mode.  Print documentation of current major mode,
	      which describes the commands peculiar to it.
N  view-emacs-news.  Shows emacs news file.
S  describe-syntax.  Display contents of syntax table, plus explanations
T  help-with-tutorial.  Select the Emacs learn-by-doing tutorial.
V  describe-variable.  Type name of a variable;
	      it displays the variable's documentation and value.
W  where-is.  Type command name; it prints which keystrokes
	      invoke that command.
C-c print Emacs copying permission (General Public License).
C-d print Emacs ordering information.
C-l Help for Koyto Common Lisp. Type a CL symbol name;
              it displayes all references to that symbol from the KCL 
              documentation.
C-n print news of recent Emacs changes.
C-w print information on absence of warranty for GNU Emacs."
  (interactive)
  (message
"A B C F I K L M N S T V W C-c C-d C-l C-n C-w.  Type C-h again for more help:")
  (let ((char (read-char)))
    (if (or (= char ?\C-h) (= char ??))
	(save-window-excursion
	  (switch-to-buffer "*Help*")
	  (erase-buffer)
	  (insert (documentation 'help-for-help))
	  (goto-char (point-min))
	  (while (memq char '(?\C-h ?? ?\C-v ?\ ?\177 ?\M-v))
	    (if (memq char '(?\C-v ?\ ))
		(scroll-up))
	    (if (memq char '(?\177 ?\M-v))
		(scroll-down))
	    (message "A B C F I K L M N S T V W C-c C-d C-l C-n C-w%s: "
		     (if (pos-visible-in-window-p (point-max))
			 "" " or Space to scroll"))
	    (let ((cursor-in-echo-area t))
	      (setq char (read-char))))))
    (let ((defn (cdr (assq (downcase char) (cdr help-map)))))
      (if defn (call-interactively defn) (ding)))))

(defun symbol-at-point ()
  (condition-case ()
	(save-excursion
	   (forward-sexp -1)
	   (skip-chars-forward "'(#?\ 	")
	   (buffer-substring (point)
			     (progn
				(skip-chars-forward "a-zA-Z0-9\-*$_")
				(point))))
     (error nil)))

;;;;;;;;
;;;
;;;  From kcl-shell.el
;;;
;;;;;;;;

(defun shell-set-directory ()
   (cond
      ;;;
      ;;; (bye) Must return us to the $HOME directory, or init.kcl won't
      ;;;    get loaded on restart.
      ;;;
      ((looking-at "([ \n\t]*bye[ \n\t]*)")
       (progn
	  (define-key inferior-lisp-mode-map "r" 'start-kcl)
	  (rename-buffer "KCL: <No Process>")
	  (cd (getenv "HOME"))))
      ;;;
      ;;; (exit) is a fatal command. Query to save buffers and exit emacs.
      ;;;
      ((looking-at "([ \n\t]*exit[ \n\t]*)")
       (progn
	  (rename-buffer "KCL: <Exiting>")
	  (kill-process "shell")
	  (kill-process "lisp")
	  (save-buffers-kill-emacs)))
      ;;;
      ;;; This bit is for keeping emacs in the smae dir as kcl.
      ;;;
      ((looking-at "(cd[ \n\t)]") 
       (let (dir)
	  (forward-char 3)
	  (skip-chars-forward " \t\n\"")
	  (if (eq (char-after (point)) 41)
		(cd (getenv "HOME"))
	     (if (file-directory-p
		  (setq dir
			(expand-file-name
			 (substitute-in-file-name
			  (upcase
			   (let ((ts (buffer-substring
				      (point)
				      (progn
					 (skip-chars-forward "^\n \t\")")
					 (point)))))
			      (if (string-equal "^" ts)
				    ".."
				 ts)))))))
		   (cd dir)))))))

;;
;;
;; end
-- 
					:alex.
					Systems Programmer
nerwin!alex@umbc3.umd.edu		UMBC
alex@umbc3.umd.edu