; This is an XLISP-PLUS glossary lookup package.
; It requires the package facility to work, and uses a file called
; glos.txt which is the glossary portion of the XLISP documentation file
; When loaded for the first time, it adds a *glossary* property to all
; functions which are defined in glos.txt and are in the XLISP package.
; This property is the displacement into the file. When a glossary lookup
; occurs the file itself is referenced. By operating this way, very little
; space is taken for this feature.

; There are two user-accessable symbols. tools:*glospaging* is a variable
; which causes the output to "page" (pause for user response) at every
; screenful. Set it to NIL to defeat this feature or to the number of lines
; per page to enable.

; The main entry point is the function tools:glos. When given an argument that
; is a function symbol, it will look up the glossary definition. If the
; symbol is not in the XLISP package, or if a second non-nil argument is
; supplied, the name will be passed to APROPOS, and the glossary definitions
; for all matching symbols will be displayed

; For instance (glos :car) or (glos 'car) or (glos "car") will show the
; definition for the CAR function, while (glos 'car t) will show that of
; MAPCAR as well. (glos "X") will give the glossary listing of all functions
; with names containing an X character, since there is no external symbol
; named X in the XLISP package.

; It would not be that difficult to modifify this program for environments
; where packages are not compiled in, however operation would not be quite
; as sophisticated.

;Tom Almy
;10/93

; Revised 2/94, improving operation and clarifying some loading messages

; Revised 10/14/96 to create file useable with function DOCUMENTATION


#-:packages
(error "This utility was written asuming the package facility is in use")
#-:common
(load "common")

(unless (find-package "TOOLS")
	(make-package "TOOLS" :use '("XLISP")))

(in-package "TOOLS")

(export '(glos *glospaging*))

(defvar *glosfilename*)

; We will look things up while loading
; so we can toss all the code when done

(unless *glosfilename*
	(format t "~&Building glossary references---")
	(let ((lpar #\()
	      (rpar #\))
	      (dot #\.)
	      (*pos* 0)
	      symbol)
	     (labels (
	      

(xposition (chr str &aux (pos (position chr str)))
       (if pos pos (length str)))

(seek-next-fcn (strm)
       (do ((thispos *pos* (file-position strm))
	    (text (read-line strm nil) (read-line strm nil)))
	   ((null text) nil)
	   (when (and (> (length text) 3)
		      (or (char= lpar (char text 0))
			  (char= dot (char text 0))))
		 (setf *pos* thispos)
		 (return-from seek-next-fcn
			      (subseq text 1 (min (xposition rpar text)
						  (xposition #\space text))))))))

;; The body of the code that does the work:		   
		   (unless (open "glos.txt" :direction :probe)
			   (error "Could not find glossary file glos.txt"))
		   (with-open-file
		    (strm "glos.txt")
		    (setq *glosfilename* (truename strm))
		    (do ((name (seek-next-fcn strm) (seek-next-fcn strm)))
			((null name) nil)
			(setq symbol (find-symbol (string-upcase name) :xlisp))
			(unless symbol
				(if (string-equal name "nil")
				    (setf (get nil '*glossary*) *pos*)
				    (format t
					    "~&Documented symbol ~s not found in XLISP.~%"
					    name)))
			(when symbol
;			      (format t "~s " symbol)
			      (setf (get symbol '*glossary*) *pos*))))
;; Check for functions & vars in package XLISP that aren't documented
		   (format t "~&Not documented, but found in XLISP:")
		   (do-external-symbols
		    (x :xlisp)
		    (when (and (or (fboundp x) (specialp x))
			       (not (get x '*glossary*)))
			  (format t "~s " x)))
		   (format t "~&")

))) ;; Ends the Flet, let, and unless

(defvar *linecount*)
(defvar *glospaging* 23)

(defun linechk ()
       (when (and *glospaging*
		  (> (incf *linecount*) *glospaging*))
	     (setq *linecount* 0)
	     (if (y-or-n-p "--PAUSED--  Continue?")
		 (fresh-line)
		 (throw 'getoutahere))))
       
(defun glos2 (val)
       (with-open-file
	(strm *glosfilename*)
	(file-position strm val)
	(do ((line (read-line strm nil) (read-line strm nil)))
	    ((zerop (length line))
	     (linechk)
	     (format t "~%"))
	    (linechk)
	    (format t "~a~%" line))))


(defun glos (symbol &optional matchall &aux val (sym (string symbol)))
       (catch
	'getoutahere
	(setq *linecount* 0)
	(if (and (null matchall) (setq val (find-symbol sym)))
	    (if (setq val (get val '*glossary*))
		(glos2 val)
		(format t"No information on ~a~%" sym))
	    (progn
	     (setq val
		   (do ((list (apropos-list sym :xlisp) (cdr list))
			(result nil result))
		       ((null list) result)
		       (when (setq val (get (car list) '*glossary*))
			     (pushnew val result))))
	     (if (zerop (length val))
		 (format t "No matches for ~a~%" symbol)
		 (map nil #'glos2 val)))))
#+:mulvals (values)
#-:mulvals nil
)


syntax highlighted by Code2HTML, v. 0.9.1