Changeset 687


Ignore:
Timestamp:
Mar 22, 2004, 9:29:03 AM (21 years ago)
Author:
Gary Byers
Message:

Move application stuff to l1-application.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/ccl/level-1/l1-readloop.lisp

    r604 r687  
    3838(defvar *continuablep* nil)
    3939(defvar *in-read-loop* nil
    40  "Not CL. Is T if waiting for input in the read loop")
    41 (defvar *listener-p* nil
    42   "Bound true by READ-LOOP. This is how we tell if a process is a Listener")
    43 
    44 (defparameter *inhibit-error* nil "If non-nil, ERROR just throws")
     40 "Is T if waiting for input in the read loop")
     41
     42
    4543(defvar *did-startup* nil)
    4644
    47 
    48 (defun process-is-listener-p (process)
    49   (symbol-value-in-process '*listener-p* process))
    50 
    51 (defun process-is-toplevel-listener-p (process)
    52   (and (symbol-value-in-process '*in-read-loop* process)
    53        (eql 0 (symbol-value-in-process '*break-level* process))))
    5445
    5546
     
    6354  (throw :toplevel nil))
    6455
    65 ; This is the old way we did this.
    66 ; It has the drawback that it doesn't throw out,
    67 ; just restarts the process without cleaning up.
    68 #|
    69       (progn
    70         (process-interrupt *initial-process*
    71                            #'(lambda (p)
    72                                (let ((function.args (process.initial-form p)))
    73                                  (apply #'process-preset
    74                                         p
    75                                         (car function.args)
    76                                         (cdr function.args))))
    77                            p)
    78         (loop
    79           (suspend-current-process))))))
    80 |#
    8156
    8257(defun cancel ()
    8358 (throw :cancel :cancel))
    8459
    85 ; It's not clear that this is the right behavior, but aborting CURRENT-PROCESS -
    86 ; when no one's sure just what CURRENT-PROCESS is - doesn't seem right either.
     60;;; It's not clear that this is the right behavior, but aborting CURRENT-PROCESS -
     61;;; when no one's sure just what CURRENT-PROCESS is - doesn't seem right either.
    8762(defun interactive-abort ()
    8863  (interactive-abort-in-process *current-process*))
     
    9974
    10075
    101 ; What process-to-abort does now (5/5/95):
    102 ; - all processes idling: cmd-. & opt-cmd-. abort event-processor
    103 ; - one process busy: cmd-. aborts the busy process; opt-cmd-. gives dialog
    104 ; - two or more processes busy: cmd-. & opt-cmd-. gives dialog
    105 ; (a busy process is a non-idling listener, or any other that's not event-processor)
    106 
    107 #+notyet
    108 (defun process-to-abort (what)
    109   (let ((l (mapcan #'(lambda (x)
    110                        (unless (or (process-exhausted-p x)
    111                                    (not (find-restart-in-process 'abort x))
    112                                    ; idling listeners:
    113                                    #|
    114                                    (and (symbol-value-in-process '*in-read-loop* x)
    115                                         (eq 0 (symbol-value-in-process '*break-level* x)))|#
    116                                    )
    117                          (list x)))
    118                    (reverse *active-processes*))))
    119     (cond
    120       ((null (cdr l)) (car l)) ; *current-process*
    121       ((and (null (cddr l))
    122             (not (option-key-p)))
    123        (if (eq (car l) *event-processor*) (cadr l) (car l)))
    124       (t (let ((p (catch-cancel
    125                     (select-item-from-list l
    126                                            :window-title what
    127                                            :help-spec 15010
    128                                            :list-spec 15011
    129                                            :button-spec 15013))))
    130            (if (neq p :cancel) (car p)))))))
    131 
    13276(defun abort (&optional condition)
    13377  (invoke-restart-no-return (find-restart 'abort condition)))
     
    14286(defun abort-break ()
    14387  (invoke-restart-no-return 'abort-break))
    144 
    145 #| Doing it this way prevents abort from clearing input in the listener
    146 (defun abort-break ()
    147   (let ((res (find-restart-2 'abort)))
    148     (if  res (invoke-restart-no-return res) (abort))))
    149 
    150 ; find second restart
    151 (defun find-restart-2 (name &aux res)
    152   (dolist (cluster %restarts% res)
    153     (dolist (restart cluster)
    154       (when (eq (restart-name restart) name)                 
    155         (if res (return-from find-restart-2 restart)(setq res restart))))))
    156 |#
    15788
    15889
     
    172103
    173104
    174 
    175 
    176105(defglobal *quitting* nil)
    177 
    178 
    179106
    180107
     
    211138    ))
    212139
    213 
    214 
    215 
    216 
    217 
    218 
    219 ;; Application classes
    220 
    221 (defstruct command-line-argument
    222   keyword
    223   help-string
    224   option-char
    225   long-name
    226   may-take-operand
    227   allow-multiple                        ; option can appear multiple times
    228 )
    229 
    230 (defvar *standard-help-argument*
    231   (make-command-line-argument
    232    :keyword :help
    233    :help-string "this text"
    234    :option-char #\h
    235    :long-name "help"))
    236 
    237 (defvar *standard-version-argument*
    238   (make-command-line-argument
    239    :keyword :version
    240    :help-string "print (LISP-APPLICATION-VERSION) and exit"
    241    :option-char #\V
    242    :long-name "version"))
    243 
    244 (defclass application ()
    245     ((command-line-arguments
    246       :initform
    247       (list *standard-help-argument* *standard-version-argument*))
    248      (ui-object :initform nil :initarg :ui-object :accessor application-ui-object)))
    249        
    250 (defclass ui-object ()
    251     ())
    252 
    253 ;;; It's intended that this be specialized ...
    254 (defmethod ui-object-do-operation ((u ui-object) operation &rest args)
    255   (declare (ignore operation args)))
    256 
    257 
    258 (defun %usage-exit (banner exit-status other-args)
    259   (with-cstrs ((banner banner)
    260                (other-args other-args))
    261     (ff-call (%kernel-import ppc32::kernel-import-usage-exit)
    262              :address banner
    263              :signed-fullword exit-status
    264              :address other-args
    265              :void)))
    266 
    267 ;;; Returns three values: error-flag, options-alist, non-option-arguments
    268 (defmethod parse-application-arguments ((a application))
    269   (let* ((cla (slot-value a 'command-line-arguments))
    270          (vals (cdr *command-line-argument-list*))
    271          (options ())
    272          (non-options ()))
    273     (do* ()
    274          ((null vals)
    275           (values nil (nreverse options) (nreverse non-options)))
    276       (let* ((val (pop vals))
    277              (val-len (length val))
    278              (short-p nil)
    279              (option
    280               (if (and (>= val-len 2)
    281                        (eql (schar val 0) #\-))
    282                 (if (eql (schar val 1) #\-)
    283                   (find val cla
    284                         :key #'command-line-argument-long-name
    285                         :test #'(lambda (k v) (string= k v :start1 2)))
    286                   (progn
    287                     (setq short-p t)
    288                     (find (schar val 1) cla
    289                           :key #'command-line-argument-option-char))))))
    290         (if (null option)
    291           (if (and (>= val-len 1)
    292                    (eql (schar val 0) #\-))
    293             (return (values :unknown-option val nil))
    294             (push val non-options))     ;non-option argument
    295           ;; We recognized the option.  Is it a duplicate of
    296           ;; something already seen?
    297           (let* ((key (command-line-argument-keyword option))
    298                  (operand nil))
    299             (when (and (assoc key options)
    300                        (not (command-line-argument-allow-multiple option)))
    301               (return (values :duplicate-option val nil)))
    302             (when (command-line-argument-may-take-operand option)
    303               ;; A short option name can be followed by the operand,
    304               ;; without intervening whitespace.
    305               (if (and short-p (> val-len 2))
    306                 (setq operand (subseq val 2))
    307                 (if vals
    308                   (setq operand (pop vals))
    309                   (return (values :missing-operand val nil)))))
    310             (push (cons key operand) options)))))))
    311 
    312 (defmethod summarize-option-syntax ((a application))
    313   (flet ((summarize-option (o)
    314            (format nil "~8t-~a, --~a : ~a~%"
    315                    (command-line-argument-option-char o)
    316                    (command-line-argument-long-name o)
    317                    (command-line-argument-help-string o))))
    318     (format nil "~{~a~}" (mapcar #'summarize-option
    319                                  (slot-value a 'command-line-arguments)))))
    320 
    321  
    322 ;;; Process the "help" and "version" options, report parsing errors.
    323 (defmethod process-application-arguments ((a application) error-flag opts args)
    324   (declare (ignore args))
    325   (if (null error-flag)
    326     (if (assoc :help opts)
    327       (%usage-exit "" 0 (summarize-option-syntax a))
    328       (if (assoc :version opts)
    329         (progn
    330           (format t "~&~a~&" (application-version-string a))
    331           (force-output t)
    332           (#_exit 0))))
    333     (%usage-exit
    334      (format nil
    335              (case error-flag
    336                (:missing-argument "Missing argument to ~a option")
    337                (:duplicate-argument "Duplicate ~a option")
    338                (:unknown-option "Unknown option: ~a")
    339                (t "~a"))
    340              opts)
    341      #$EX_USAGE
    342      (summarize-option-syntax a))))
    343                
    344 
    345 ;;; an example method to base a specialization on
    346 (defmethod toplevel-function ((a application) init-file)
    347   (declare (ignore init-file))
    348   (multiple-value-bind (error-flag options args)
    349       (parse-application-arguments a)
    350     (process-application-arguments a error-flag options args)))
    351 
    352 (defmethod application-version-string ((a application))
    353   "Return a string which (arbitrarily) represents the application version.
    354 Default version returns OpenMCL version info."
    355   (format nil "~&~d.~d~@[.~d~]~@[-~a~]~&"
    356           *openmcl-major-version*
    357           *openmcl-minor-version*
    358           (unless (zerop *openmcl-revision*)
    359             *openmcl-revision*)
    360           *openmcl-suffix*))
    361 
    362 (defmethod application-ui-operation ((a application) operation &rest args)
    363   (let* ((ui-object (application-ui-object a)))
    364     (when ui-object
    365       (apply #'ui-object-do-operation ui-object operation args))))
    366 
    367 
    368 
    369 
    370 
    371 (defun find-restart-in-process (name p)
    372   (without-interrupts
    373    (let ((restarts (symbol-value-in-process '%restarts% p)))
    374      (dolist (cluster restarts)
    375        (dolist (restart cluster)
    376          (when (and (or (eq restart name) (eq (restart-name restart) name)))
    377            (return-from find-restart-in-process restart)))))))
    378 
    379 
    380 
    381 ; specialize this for your application
    382 (defmethod open-application ((self application) startup)
    383   (declare (ignore startup))
    384   nil)
    385  
    386 ; specialize this for your application
    387 (defmethod open-application-document ((a application) path &optional startup)
    388   (declare (ignore path startup)))
    389 
    390 (defmethod application-name          ((app application)) nil)
    391 (defmethod application-init-file     ((app application)) nil)
    392 
    393 
    394 (defclass lisp-development-system (application)
    395   ((command-line-arguments
    396     :initform
    397     (list *standard-help-argument*
    398           *standard-version-argument*
    399           (make-command-line-argument
    400            :option-char #\n
    401            :long-name "no-init"
    402            :keyword :noinit
    403            :help-string "suppress loading of init file")
    404           (make-command-line-argument
    405            :option-char #\e
    406            :long-name "eval"
    407            :keyword :eval
    408            :help-string "evaluate <form> (may need to quote <form> in shell)"
    409            :may-take-operand t
    410            :allow-multiple t)
    411           (make-command-line-argument
    412            :option-char #\l
    413            :long-name "load"
    414            :keyword :load
    415            :help-string "load <file>"
    416            :may-take-operand t
    417            :allow-multiple t)
    418           (make-command-line-argument
    419            :option-char #\T
    420            :long-name "set-lisp-heap-gc-threshold"
    421            :help-string "set lisp-heap-gc-threshold to <n>"
    422            :keyword :gc-threshold
    423            :may-take-operand t
    424            :allow-multiple nil)))))
    425 
    426 (defparameter *application*
    427   (make-instance 'lisp-development-system))
    428 
    429 (defvar *load-lisp-init-file* t)
    430 (defvar *lisp-startup-parameters* ())
    431 
    432 (defmethod process-application-arguments ((a lisp-development-system)
    433                                           error-flag options args)
    434   (declare (ignorable error-flag))
    435   (call-next-method)                    ; handle help, errors
    436   (if args
    437     (%usage-exit (format nil "Unrecognized non-option arguments: ~a" args)
    438                  #$EX_USAGE
    439                  (summarize-option-syntax a))
    440     (setq *load-lisp-init-file* (not (assoc :noinit options))
    441           *lisp-startup-parameters*
    442           (mapcan #'(lambda (x)
    443                       (and (member (car x) '(:load :eval :gc-threshold)) (list x)))
    444                   options))))
    445        
    446 
    447 (defmethod toplevel-function ((a lisp-development-system) init-file)
    448   (call-next-method)
    449   (let* ((sr (input-stream-shared-resource *terminal-input*)))
    450     (make-mcl-listener-process
    451      "listener"
    452      *terminal-input*
    453      *terminal-output*
    454      #'(lambda () (when sr (setf (shared-resource-primary-owner sr)
    455                                  *initial-process*)))
    456      #'(lambda ()
    457          (startup-ccl (and *load-lisp-init-file* init-file))
    458          (listener-function)
    459          nil)
    460      nil))
    461   (%set-toplevel #'(lambda ()
    462                      (with-standard-abort-handling nil
    463                        (loop
    464                          (%nanosleep *periodic-task-seconds* *periodic-task-nanoseconds*)
    465                          (housekeeping)))))
    466   (toplevel))
    467 
    468 
    469 
    470 (defmethod application-init-file ((app lisp-development-system))
    471   "home:openmcl-init")
    472 
    473 
    474 ; redefined by hide-listener-support
    475 (defmethod application-error ((a application) condition error-pointer)
    476   (declare (ignore condition error-pointer))
    477   (quit))
    478140
    479141(defun error-header (kind)
Note: See TracChangeset for help on using the changeset viewer.