diff --git a/src/CHANGELOG b/src/CHANGELOG index 25074ecb7..619a3f5ea 100644 --- a/src/CHANGELOG +++ b/src/CHANGELOG @@ -11,6 +11,14 @@ ECL 0.9h - New hash routine, similar to SBCL's one, faster and leading to fewer collisions between similar strings. +* Visible changes: + + - The code for handling command line options has been redesigned. Now multiple + -compile options are allowed; the -o/-c/-h/-data options have to come before + the associated -compile; we introduce a new -rc option to force loading + initialization files; errors during initialization are intercepted and cause + ECL to abort. + ;;; Local Variables: *** ;;; mode:text *** ;;; fill-column:79 *** diff --git a/src/lsp/cmdline.lsp b/src/lsp/cmdline.lsp new file mode 100644 index 000000000..4146cfce6 --- /dev/null +++ b/src/lsp/cmdline.lsp @@ -0,0 +1,120 @@ +;;;; command-line.lsp -- command line processing +;;;; +;;;; Copyright (c) 2005, Juan Jose Garcia-Ripoll +;;;; +;;;; This program is free software; you can redistribute it and/or +;;;; modify it under the terms of the GNU Library General Public +;;;; License as published by the Free Software Foundation; either +;;;; version 2 of the License, or (at your option) any later version. +;;;; +;;;; See file '../Copyright' for full details. +;;;; + +(in-package "SYSTEM") + +(export '(*lisp-init-file-list* command-args)) + +(defvar *lisp-init-file-list* '("~/.ecl" "~/.eclrc") + "List of files automatically loaded when ECL is invoked.") + +(defun command-args () + "Returns the command line arguments as list" + (loop for i from 0 below (argc) + collect (argv i))) + +(defun help-message (stream) + "Prints a help message about command line arguments of ECL" + (princ " +Usage: ecl [-? | --help] + [-dir dir] [-load file] [-shell file] [-eval expr] [-rc | -norc] + [[-o ofile] [-c [cfile]] [-h [hfile]] [-data [datafile]] [-s] [-q] + -compile file] + +" + stream)) + +(defun command-arg-error (str &rest fmt-args) + ;; Format an error message and quit + (declare (si::c-local)) + (apply #'format *error-output* str fmt-args) + (help-message *error-output*) + (quit 1)) + +(defconstant +command-arg-rules+ + '(("--help" 0 #0=(progn (help-message *standard-output*) (quit))) + ("-?" 0 #0#) + ("-eval" 1 (eval (read-from-string 1))) + ("-shell" 1 (progn (setq quit 0) (load 1 :verbose nil))) + ("-load" 1 (load 1 :verbose verbose)) + ("-dir" 1 (setf (logical-pathname-translations "SYS") + `(("**;*.*" ,(merge-pathnames "**/*.*" (truename 1)))))) + ("-compile" 1 + (progn + (setq quit + (if (nth-value 3 + (compile-file 1 :output-file output-file :c-file c-file + :h-file h-file :data-file data-file + :verbose verbose :system-p system-p)) + 1 + 0) + output-file t + c-file nil + h-file nil + data-file nil + system-p nil))) + ("-o" 1 (setq output-file 1)) + ("-c" 1 (setq c-file 1)) + ("-h" 1 (setq h-file 1)) + ("-data" 1 (setq data-file 1)) + ("-q" 0 (setq verbose nil)) + ("-s" 1 (setq system-p t)))) + +(defun produce-init-code (option-list) + (declare (si::c-local)) + (do* ((commands '()) + (loadrc t)) + ((null option-list) + (values `(let ((output-file t) + (c-file nil) + (h-file nil) + (data-file nil) + (verbose t) + (system-p nil) + (quit nil)) + ,@(nreverse commands) + (when quit (quit 0))) + loadrc)) + (let* ((option (pop option-list)) + (rule (assoc option +command-arg-rules+ :test #'string=))) + (cond ((string= option "-rc") + (setq loadrc t)) + ((string= option "-norc") + (setq loadrc nil)) + ((string= option "--") + (setf option-list nil)) + ((null rule) + (command-arg-error "Unknown command line option ~A.~%" option)) + (t + (let ((pattern (third rule))) + (unless (zerop (second rule)) + (when (null option-list) + (command-arg-error + "Missing argument after command line option ~A.~%" + option)) + (nsubst (pop option-list) 1 pattern)) + (push pattern commands))))))) + +(defun process-command-args (&optional (args (rest (command-args)))) + (multiple-value-bind (commands loadrc) + (produce-init-code args) + (handler-case + (progn + (when loadrc + (dolist (file *lisp-init-file-list*) + (when (load file :if-does-not-exist nil :search-list nil :verbose nil) + (return)))) + (eval commands)) + (error (c) + (format *error-output* + "An error occurred during initialization:~%~A.~%" c) + (quit 1))))) diff --git a/src/lsp/load.lsp.in b/src/lsp/load.lsp.in index 5907fd3ad..8c88418d1 100644 --- a/src/lsp/load.lsp.in +++ b/src/lsp/load.lsp.in @@ -38,6 +38,7 @@ "src:lsp;tk-init.lsp" "build:lsp;config.lsp" "src:lsp;module.lsp" + "src:lsp;cmdline.lsp" "src:lsp;top.lsp" #+threads "src:lsp;mp.lsp" diff --git a/src/lsp/top.lsp b/src/lsp/top.lsp index 7ca94d8fc..d5687fb01 100644 --- a/src/lsp/top.lsp +++ b/src/lsp/top.lsp @@ -19,10 +19,7 @@ (in-package "SYSTEM") (export '(*break-readtable* *break-on-warnings* *break-enable* - *lisp-init-file-list* *tpl-evalhook*)) - -(defvar *lisp-init-file-list* '("~/.ecl" "~/.eclrc") - "List of files automatically loaded when ECL is invoked.") + *tpl-evalhook*)) (defvar *quit-tag* (cons nil nil)) (defvar *quit-tags* nil) @@ -335,91 +332,6 @@ value of this variable is non-NIL.") ) ) -(eval-when (compile eval) - (defmacro notinline (form) - `(locally (declare (notinline ,(car form))) - ,form))) - -(defun process-command-args (&aux (load-rc t) (commands nil) (quit nil)) - #-ecl-min - (do ((load-rc t) - (commands nil) - (quit nil) - (stop-processing nil) - (i 1 (1+ i)) - (argc (argc))) - ((or (>= i argc) - stop-processing) - (when load-rc - (dolist (file *lisp-init-file-list*) - (when (load file :if-does-not-exist nil :search-list nil :verbose nil) - (return)))) - (eval `(progn ,@(nreverse commands))) - (when quit (quit)) - ) - (labels - ((get-argument (n k default) - (do ((j (1+ n) (1+ j)) - (argc (argc))) - ((>= j argc) default) - (when (string= k (argv j)) - (incf j) - (return - (or (= j argc) - (eql (schar (argv j) 0) #\-) - (let ((arg (argv j))) - (if (string-equal "nil" arg) - NIL - (or (string-equal "t" arg) arg)))))))) - (help-message (stream) - (princ "Usage: ecl [-? | --help] - [-dir dir] [-load file] [-shell file] [-eval expr] [-norc] - [-compile file [-o ofile] [-c [cfile]] [-h [hfile]] - [-data [datafile]] [-s] [-q]] -" - stream)) - (pop-arg (option) - (when (= (incf i) argc) - (format *error-output* "Missing argument to command line option ~A.~%" option) - (help-message *error-output*) - (quit 1)) - (argv i))) - (let ((option (argv i))) - (cond - ((string= "-dir" option) - (setf (logical-pathname-translations "SYS") - `(("**;*.*" ,(merge-pathnames "**/*.*" (truename (pop-arg "-dir"))))))) - ((string= "-compile" option) - (if (nth-value 3 - (compile-file - (pop-arg "-compile") - :output-file (get-argument i "-o" T) - :c-file (get-argument i "-c" NIL) - :h-file (get-argument i "-h" NIL) - :data-file (get-argument i "-data" NIL) - :verbose (not (get-argument i "-q" NIL)) - :system-p (get-argument i "-s" NIL))) - (quit 1) - (quit 0))) - ((string= "-load" option) - (push `(load ,(pop-arg "-load") :verbose t) commands)) - ((string= "-shell" option) - (push `(load ,(pop-arg "-shell") :verbose nil) commands) - (setf quit t load-rc nil)) - ((string= "-eval" option) - (push (read-from-string (pop-arg "-eval")) commands)) - ((string= "-norc" option) - (setf load-rc nil)) - ((or (string= "-?" option) (string= "--help" option)) - (help-message t) - (quit 0)) - ((string= "--" option) - (setq stop-processing t)) - (t - (format *error-output* "Unknown command line option ~A.~%" option) - (help-message *error-output*) - (quit 1))))))) - (defvar *lisp-initialized* nil) (defun top-level () @@ -436,7 +348,7 @@ file. When the saved image is invoked, it will start the redefined top-level." (catch *quit-tag* (let ((*break-enable* nil)) ;; process command arguments - (notinline (process-command-args)))) + (process-command-args))) (format t "ECL (Embeddable Common-Lisp) ~A" (lisp-implementation-version)) (format t "~%Copyright (C) 1984 Taiichi Yuasa and Masami Hagiya~@ @@ -484,7 +396,7 @@ file. When the saved image is invoked, it will start the redefined top-level." (reset-stack-limits)) (when (catch *quit-tag* (tpl-prompt) - (setq - (notinline (tpl-read))) + (setq - (locally (declare (notinline tpl-read)) (tpl-read))) (setq values (multiple-value-list (eval-with-env - *break-env*)))