;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;                                                          ;;;;;;;;
;;;;;;  All files in this directory or any subdirectories are   ;;;;;;;;
;;;;;;  copyright 1997, 1998, 1999, 2000, 2002, 2003.           ;;;;;;;;
;;;;;;  by Rafael D. Sorkin.  All rights reserved.              ;;;;;;;;
;;;;;;                                                          ;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; preparations.el        Time-stamp:<2003-Dec-06 23:15:54 16338.43386> 

;=========================================================================
;                  General Preparations for elisp 
;=========================================================================
; Flagship version at suhep
;
; (Hay tambien counterparts like `preparations.cmucl' for use with dialects
;  of TrueCommonLisp) 
;
; "User options" are flagged { ;! }
;=========================================================================

;: By default, we won't recompile the biblioteks

(defvar recompile nil)
;(setq recompile  t)

(message "\
===================================================================
Loading the file preparations.el")

;: Table of Contents 
 ;  
 ;  Define some global constants
 ;  Declare and initialize some global variables     
 ;  Adjust various limits   
 ;  Kwa ajili ya TCL
 ;  Try to define Infinity% and NaN%
 ;  Adjust Load Path
 ;  Load various libraries (with recompilation if requested)
 ;  Other 
;-------------------------------
;: Define some global constants
;-------------------------------
(progn

  (defconst *lisp-type* 'elisp	        "elisp with CL extensions")
  (defconst *elisp* t)
  (defconst *cmucl* nil)		; cmucl = CMU Common Lisp
  (defconst *CMUCL* nil)
  (defconst *TCL* nil)			; TCL = True Common Lisp
  (defconst *tcl* nil)
  (defconst *gcl* nil)			; gcl = Gnu  Common Lisp
  (defconst *GCL* nil)
  (defconst *clisp* nil)		; CLISP
  (defconst *sun-lisp* nil)		; Sun version of Lucid Lisp 

  (defconst otherwise t "for use in ``otherwise'' clause of `cond' etc.")
  (defconst else t      "for use in ``otherwise'' clause of `cond' etc.")

  "some constants defined") 



;-----------------------------------------------
;: Declare and initialize some global variables
;----------------------------------------------- 
(defvar *carefully* t 
  "\
 When true, makes various functions operate with more checking:
 a function that produces a causet by sprinkling may check that the result
 really is transitive, a function to multiply matrices may check that
 the dimensions of the factors match, etc." )
 ; 
 ; Note: the default value of `t' takes effect only if *carefully* is void.

(defvar *mrv* nil " Place to deposit multiple return values") 

;; All of the following junk is just to avoid trouble for outside users

 ; The variable `*user=rds*' is kwa ajili ya elisp code which is trying to
 ; avoid causing trouble for outside users (eg those who download the poset
 ; package from my web site).  See the file bibliotek.elisp.coda.el for an
 ; example of its use.  

 ; Ordinarily it would be set in the file `.emacs'.  If it hasn't been bound,
 ; we define it but issue a warning if it was already in use by the outside
 ; user.  (Recall that `defvar' will not change the value if it has one
 ; already.)  The only reason we bother to define it for the outside user is to
 ; avoid error messages from the compiler when it's referred to.

(setq *mrv* (intern-soft "*user=rds*"))

(unless (boundp '*user=rds*) 
  (defvar *user=rds* nil "To help avoid causing trouble for outside users")
  (message "WARNING  The variable `*user=rds*' has been set to nil *******"))

(cond
 (*user=rds* (message "I'm assuming that the user is Rafael D. Sorkin"))
 (*mrv* (message "WARNING The symbol `*user=rds*' was already in use! ")))

; (defvar *user=rds* nil)

; This did not work:
;
; (unless (boundp '*user=rds*) 
;   (defvar *user=rds* nil)
;   (makunbound '*user=rds*)
;   (message "WARNING  The variable `*user=rds*' has NOT been set *******"))

;-----------------------------------------------
;: Adjust various limits, printing options, etc 
;----------------------------------------------- 
(setq 
 max-lisp-eval-depth (expt 2 14)   ; recursion depth 
 max-specpdl-size    (expt 2 16)   ; number of variable bindings 
 gc-cons-threshold   (expt 2 24)   ; frequency of garbage collection (in bytes)
 print-length nil		   ; nil means no limit on sequence length
 print-level  nil		   ; nil means no limit on nesting depth
 print-gensym (list t))		   ; affects how uninterned symbols print

 ;; some of these are also set in .emacs

(message "Various limits increased governing recursion depth, etc.")  

 ; Reduced limits of 2^13 were the best possible for umoja-suhep as of
 ; Dec 25 1997 but doing { ulimit -s 32000 } seemed to cure the problem.
 ;
 ; Newer emacs versions guarantee integers up to at least 2^27-1.
 ; (Some older implementations were limited to 2^23-1.)
 ;
 ; Reducing the frequency of garbage collection gains perhaps 
 ; a factor of 2 to 3 in speed. 

;-----------------------------
;: Kwa ajili ya TCL 
;----------------------------- 
; More things related to TCL compatibility are in `bibliotek.elisp.el'

(defmacro in-package (&optional $) 
  "A dummy macro as far as elisp is concerned" nil)

(defconst *float* 'float 
 " This is a variable whose VALUE is supposed to be the default float type.  
 We seem to need it for elisp - TCL compatiblity.  (See the comments in the
 file `preparations.el')")
 ;
 ; It would be better if we could eliminate this stupid global vble in favor of
 ; references to the type `realfloat' defined below, but it doesn't seem to be
 ; possible for now (see ~/lisp/3:COMMENTS).

;-------------------------------------------------
;: Try to define Infinity% and NaN% 
;-------------------------------------------------
(condition-case 
 error-message
 (progn
 ;-----------------------------------------
 ;/produce numbers we hope are Inf and NaN
 ;-----------------------------------------
  (defconst Infinity% 1e5000    "The ``infinite number''")
  (defconst Infinity  Infinity% "The ``infinite number''")
  (defconst -Infinity%  (- Infinity%) "The negatively ``infinite number''")
  (defconst NaN% (- Infinity% Infinity%) "``Not a Number''")
  (defconst NaN NaN%)
 ;--------------------------------------------------
 ;/Now test for them really being +Infinity and NaN
 ;--------------------------------------------------
  (unless 
    (and
      (numberp NaN)
      (numberp Infinity)
      (not(or
	(> NaN 0)
	(< NaN 0)
	(= NaN 0)))
      (= Infinity (+ Infinity Infinity))
      (/= Infinity 0)
      (> Infinity 0))
   ;-------------------------------------
   ;/take remedial action if they weren't
   ;-------------------------------------
    (message
     "Infinity and NaN came out WRONG:\n   Infinity => %s and NaN => %s." 
     Infinity% NaN%)
    (setq 
     Infinity% 'Inf
     -Infinity% '-Inf     
     NaN%      'NaN
     Infinity   Infinity%
     NaN        NaN%)
    (message "   Both have been made symbols (rather than IEEE floats)")))
;--------------------------
;/do this if error occurred
;--------------------------
 (error
  (message 
   "  Failed to define Infinity%% or NaN%%, error message was:\n  %s." 
   error-message)))
  ;  
  ; Notes
  ;
  ; Except for Infinity% and NaN%, all other numerical constants are loaded
  ; from the file "bibliotek.constants" 
  ; (Infinity and NaN% are lisp "numbers" (numberp=t))
  ;
  ; Apparently, one NaN need not be equal (or = or eql or equalp) to another!
  ;
  ; We trap errors here because the attempt to define Infinity sometimes
  ; produces arithmetic errors.  The checks are done to make sure that Infinity
  ; did not come out to be just a very big, but ordinary number (in which case
  ; NaN should come out to be zero).  One implementation that has this last
  ; problem is DEC emacs.
 
;--------------------------
;: Adjust Load Path 
;--------------------------

(defconst *lisp-home* nil " The home directory for the bibliotek files")

(setq *lisp-home* "~/lisp/")		;!

; NOTICE THE TRAILING SLASH, it is essential.
;
; (In elisp this is the supposed to be the proper form of a filename, and it
;  seems more compatible with TCL as well)

(unless (member *lisp-home* load-path)
  (setq load-path (append load-path (list *lisp-home*))))

 ; This ensures that our lisp base directory is in the load path.
 ; Any other directories we might need could also be added here
 ; (e.g. "lisp/cl-source.files", if we need to maintain cl locally).
 ;
 ; Often, the load path will already have been taken care of in the .emacs
 ; file.  However, when emacs is invoked using `emacs -q' (or in batch mode?)
 ; then the file .emacs doesn't get loaded, and the above is needed.
 ;
 ; In the load-path `nil' represents the current directory.  We do NOT include
 ; it because it leads to trouble when there is a local file sharing a name
 ; with one the system is looking for (e.g. "outline" which can be confused
 ; with the system's "outline.elc").  Of course this entails the opposite
 ; danger of a system file pre-empting a local one.  To avoid that, either use
 ; more complete pathnames for local files, or give them names the system
 ; wouldn't be likely to employ.
 ;
 ; There are many ways to find out which machine you are on without executing a
 ; a shell command, or using `getenv', eg the variable `system-name' has it.  
 ;
 ; The vble `emacs-version' holds the version number of emacs as a string.

   ; (cond
   ;  ((and
   ;    (equal system-name  "umoja.syr.edu")
   ;    (equal user-login-name "rdsorkin"))
   ;   "/home1/sorkin/")
   ;  (otherwise "~/")))

;------------------------------------------------------------
;: Load various libraries (with recompilation if requested) 
;------------------------------------------------------------
; Notes
;
;   Obviously the order of loading can be important.
;
;   The second argument to `load' is optional.  Keeping it nil means that we
;   will get an error if the requested file is not found.  The third argument,
;   `no-msg' turns off routine messages about loading (but shouldn't interfere
;   with warnings about the source file being newer.)
;
;   Here, we could use `byte-force-recompile' to recompile all the .elc files,
;   but it acts on all SUBDIRECTORIES, which we might not want.  Also it seems
;   better to control the order of compilation.

;--------------------------------------------
;:: Load the CL package that comes with emacs
;--------------------------------------------

(fset 'Macroexpand (symbol-function 'macroexpand))
 ; 
 ; Loading `cl' redefines `macroexpand' for some reason, so we preserve the
 ; true elisp function in `Macroexpand'.  (Actually it's not clear how much the
 ; two macros differ, since their documentation strings are isomorphic!)

(progn
  (load "cl"       nil 'no-msg)		; master file (calls others if needed)
  (load "cl-macs"  nil 'no-msg)		; macros
  (load "cl-seq"   nil 'no-msg)		; sequence functions, etc. 
  (load "cl-extra" nil 'no-msg)		; larger, more complex functions
  (require 'cl)
 (message "CL package loaded"))
 ; 
 ; It is better to make sure all of the CL files are loaded at this stage, so
 ; we don't just content ourselves with `(require 'cl)'.

;; (if recompile (declaim (optimize (speed 3) (safety 0))))
 ;
 ; maybe loading cl package undid this

;-------------------------------------------------
;:: Load any patches for elisp and its cl package
;-------------------------------------------------

; This file WILL NOT be compiled below. COMPILE IT BY HAND WHEN IT IS CHANGED!

(message "Loading patches for elisp...")

(load "bibliotek.elisp.patch" nil 'no-msg)

;-------------------------------------------------------
;:: Load my biblioteks (with recompilation if requested)
;-------------------------------------------------------
(when recompile

  (load-file  "bibliotek.elisp.el")
  (load-file  "bibliotek.macros.l")
  (load-file  "bibliotek.elisp.coda.el")
  (load-file  "bibliotek.constants.l")
  (load-file  "bibliotek.general.l")
  (load-file  "bibliotek.poset.l")
  (load-file  "bibliotek.float.l")
  (load-file  "bibliotek.extras.l")

  (byte-compile-file (concat *lisp-home* "bibliotek.elisp.el")        'load) 
  (byte-compile-file (concat *lisp-home* "bibliotek.macros.el")       'load)
  (byte-compile-file (concat *lisp-home* "bibliotek.elisp.coda.el")   'load)
  (byte-compile-file (concat *lisp-home* "bibliotek.constants.el")    'load)
  (byte-compile-file (concat *lisp-home* "bibliotek.general.el")      'load)
  (byte-compile-file (concat *lisp-home* "bibliotek.poset.el")        'load)
  (byte-compile-file (concat *lisp-home* "bibliotek.float.el")        'load)
  (byte-compile-file (concat *lisp-home* "bibliotek.extras.el")       'load)

  (message "Eight bibliotek's recompiled and loaded"))

 ; ADVERTENCIA It's important that the source files all end with {.el}, since
 ; if they end with only {.l} then the compiled file will end with {.l.elc}, as
 ; opposed to just plain {.elc}, and then `load' won't find it (unless we give
 ; it the extended name).  For this reason a source file like float.l should be
 ; linked to float.el for the sake of elisp.
 ;
 ; To avoid any mistaken identity, we load the source files with `load-file'
 ; rather than `load', since it takes the name exactly as given, without trying
 ; to add suffixes.  (Here we use the true filename, not the link name)
 ;
 ; We give `byte-compile-file' the full pathname because (unlike `load') it
 ; doesn't search `load-path' for a suitable prefix.
 ;
 ; The final argument `load' says to load after compiling.


(when (not recompile)

  (load  "bibliotek.elisp"        nil 'no-msg)  
  (load  "bibliotek.macros"       nil 'no-msg)
  (load  "bibliotek.elisp.coda"   nil 'no-msg)
  (load  "bibliotek.constants"    nil 'no-msg)
  (load  "bibliotek.general"      nil 'no-msg)
  (load  "bibliotek.poset"        nil 'no-msg)
  (load  "bibliotek.float"        nil 'no-msg)
  (load  "bibliotek.extras"       nil 'no-msg)

  (message "Eight bibliotek's loaded without recompilation"))

;--------------------------------------------------------
;: Initialize the random state / seed to "random" values
;--------------------------------------------------------

(setq *random-state* (make-random-state t))

(el:random t)

(message "Random number generators initialized from time of day or similar.")

;--------------------
;: Other 
;--------------------

(defconst *hostname* (subseq system-name 0 (search "." system-name)))

(assert (and (eq 0 0) (eq 1 1) (eq 2 2) (eq 3 3)))
 ; 
 ; In some places we assume that this is true, but unfortunately, the above
 ; doesn't really prove it.

(deftype realfloat () 'float)
 ;
 ; This works only partly in elisp, see remarks above with `*float*'
 ; (and it won't work at all before the cl package is loaded)


;; (setq  *gensym-counter* 0)  
;;   
;;  Uncomment this if you want to make cl-19 behavior repeatable for debugging
;;  purposes. (It's not good to do otherwise, since it carries a risk of name
;;  collisions.)

(setq recompile nil)

(provide 'preparations)	    ; which really means "I have provided"

(message "===================================================================")

;: End
