Changeset 687
- Timestamp:
- Mar 22, 2004, 9:29:03 AM (21 years ago)
- File:
-
- 1 edited
-
trunk/ccl/level-1/l1-readloop.lisp (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/ccl/level-1/l1-readloop.lisp
r604 r687 38 38 (defvar *continuablep* nil) 39 39 (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 45 43 (defvar *did-startup* nil) 46 44 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))))54 45 55 46 … … 63 54 (throw :toplevel nil)) 64 55 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 (progn70 (process-interrupt *initial-process*71 #'(lambda (p)72 (let ((function.args (process.initial-form p)))73 (apply #'process-preset74 p75 (car function.args)76 (cdr function.args))))77 p)78 (loop79 (suspend-current-process))))))80 |#81 56 82 57 (defun cancel () 83 58 (throw :cancel :cancel)) 84 59 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. 87 62 (defun interactive-abort () 88 63 (interactive-abort-in-process *current-process*)) … … 99 74 100 75 101 ; What process-to-abort does now (5/5/95):102 ; - all processes idling: cmd-. & opt-cmd-. abort event-processor103 ; - one process busy: cmd-. aborts the busy process; opt-cmd-. gives dialog104 ; - two or more processes busy: cmd-. & opt-cmd-. gives dialog105 ; (a busy process is a non-idling listener, or any other that's not event-processor)106 107 #+notyet108 (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 (cond120 ((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-cancel125 (select-item-from-list l126 :window-title what127 :help-spec 15010128 :list-spec 15011129 :button-spec 15013))))130 (if (neq p :cancel) (car p)))))))131 132 76 (defun abort (&optional condition) 133 77 (invoke-restart-no-return (find-restart 'abort condition))) … … 142 86 (defun abort-break () 143 87 (invoke-restart-no-return 'abort-break)) 144 145 #| Doing it this way prevents abort from clearing input in the listener146 (defun abort-break ()147 (let ((res (find-restart-2 'abort)))148 (if res (invoke-restart-no-return res) (abort))))149 150 ; find second restart151 (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 |#157 88 158 89 … … 172 103 173 104 174 175 176 105 (defglobal *quitting* nil) 177 178 179 106 180 107 … … 211 138 )) 212 139 213 214 215 216 217 218 219 ;; Application classes220 221 (defstruct command-line-argument222 keyword223 help-string224 option-char225 long-name226 may-take-operand227 allow-multiple ; option can appear multiple times228 )229 230 (defvar *standard-help-argument*231 (make-command-line-argument232 :keyword :help233 :help-string "this text"234 :option-char #\h235 :long-name "help"))236 237 (defvar *standard-version-argument*238 (make-command-line-argument239 :keyword :version240 :help-string "print (LISP-APPLICATION-VERSION) and exit"241 :option-char #\V242 :long-name "version"))243 244 (defclass application ()245 ((command-line-arguments246 :initform247 (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 banner263 :signed-fullword exit-status264 :address other-args265 :void)))266 267 ;;; Returns three values: error-flag, options-alist, non-option-arguments268 (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 (option280 (if (and (>= val-len 2)281 (eql (schar val 0) #\-))282 (if (eql (schar val 1) #\-)283 (find val cla284 :key #'command-line-argument-long-name285 :test #'(lambda (k v) (string= k v :start1 2)))286 (progn287 (setq short-p t)288 (find (schar val 1) cla289 :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 argument295 ;; We recognized the option. Is it a duplicate of296 ;; 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 vals308 (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-option319 (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 (progn330 (format t "~&~a~&" (application-version-string a))331 (force-output t)332 (#_exit 0))))333 (%usage-exit334 (format nil335 (case error-flag336 (: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_USAGE342 (summarize-option-syntax a))))343 344 345 ;;; an example method to base a specialization on346 (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-object365 (apply #'ui-object-do-operation ui-object operation args))))366 367 368 369 370 371 (defun find-restart-in-process (name p)372 (without-interrupts373 (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 application382 (defmethod open-application ((self application) startup)383 (declare (ignore startup))384 nil)385 386 ; specialize this for your application387 (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-arguments396 :initform397 (list *standard-help-argument*398 *standard-version-argument*399 (make-command-line-argument400 :option-char #\n401 :long-name "no-init"402 :keyword :noinit403 :help-string "suppress loading of init file")404 (make-command-line-argument405 :option-char #\e406 :long-name "eval"407 :keyword :eval408 :help-string "evaluate <form> (may need to quote <form> in shell)"409 :may-take-operand t410 :allow-multiple t)411 (make-command-line-argument412 :option-char #\l413 :long-name "load"414 :keyword :load415 :help-string "load <file>"416 :may-take-operand t417 :allow-multiple t)418 (make-command-line-argument419 :option-char #\T420 :long-name "set-lisp-heap-gc-threshold"421 :help-string "set lisp-heap-gc-threshold to <n>"422 :keyword :gc-threshold423 :may-take-operand t424 :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, errors436 (if args437 (%usage-exit (format nil "Unrecognized non-option arguments: ~a" args)438 #$EX_USAGE439 (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-process451 "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 nil463 (loop464 (%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-support475 (defmethod application-error ((a application) condition error-pointer)476 (declare (ignore condition error-pointer))477 (quit))478 140 479 141 (defun error-header (kind)
Note:
See TracChangeset
for help on using the changeset viewer.
