New routines for processing command line options

This commit is contained in:
jjgarcia 2005-08-31 10:20:12 +00:00
parent bd6e9940f2
commit c3f436f2e3
4 changed files with 132 additions and 91 deletions

View file

@ -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 ***

120
src/lsp/cmdline.lsp Normal file
View file

@ -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)))))

View file

@ -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"

View file

@ -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*)))