X-Git-Url: http://git.kpe.io/?a=blobdiff_plain;f=base%2Futils.lisp;h=0221ac4eb7b1837d4e51b526ffe17ce68792ee21;hb=e5744a78271044484b3399d4fc1d55b3e8808784;hp=3f9ad8a6348862c3dce8723b4cd5dee1d80db835;hpb=67e6b9eaab9c9bcf8b57cbd476581437e4876b26;p=clsql.git diff --git a/base/utils.lisp b/base/utils.lisp index 3f9ad8a..0221ac4 100644 --- a/base/utils.lisp +++ b/base/utils.lisp @@ -81,6 +81,15 @@ procstr))) +(defun position-char (char string start max) + "From KMRCL." + (declare (optimize (speed 3) (safety 0) (space 0)) + (fixnum start max) (simple-string string)) + (do* ((i start (1+ i))) + ((= i max) nil) + (declare (fixnum i)) + (when (char= char (schar string i)) (return i)))) + (defun delimited-string-to-list (string &optional (separator #\space) skip-terminal) "Split a string with delimiter, from KMRCL." @@ -104,11 +113,92 @@ (setq pos (1+ end)))) (defun string-to-list-connection-spec (str) - (let ((at-pos (position #\@ str))) + (let ((at-pos (position-char #\@ str 0 (length str)))) (cond ((and at-pos (> (length str) at-pos)) ;; Connection spec is SQL*NET format - (append (delimited-string-to-list (subseq str 0 at-pos) #\/) - (list (subseq str (1+ at-pos))))) + (cons (subseq str (1+ at-pos)) + (delimited-string-to-list (subseq str 0 at-pos) #\/))) (t (delimited-string-to-list str #\/))))) + +#+allegro +(eval-when (:compile-toplevel :load-toplevel :execute) + (unless (find-package '#:excl.osi) + (require 'osi))) + +(defun command-output (control-string &rest args) + ;; Concatenates output and error since Lispworks combines + ;; these, thus CLSQL can't depend upon separate results + (multiple-value-bind (output error status) + (apply #'%command-output control-string args) + (values + (concatenate 'string (if output output "") + (if error error "")) + status))) + +;; From KMRCL +(defun %command-output (control-string &rest args) + "Interpolate ARGS into CONTROL-STRING as if by FORMAT, and +synchronously execute the result using a Bourne-compatible shell, +returns (VALUES string-output error-output exit-status)" + (let ((command (apply #'format nil control-string args))) + #+sbcl + (let ((process (sb-ext:run-program + "/bin/sh" + (list "-c" command) + :input nil :output :stream :error :stream))) + (values + (sb-impl::process-output process) + (sb-impl::process-error process) + (sb-impl::process-exit-code process))) + + #+(or cmu scl) + (let ((process (ext:run-program + "/bin/sh" + (list "-c" command) + :input nil :output :stream :error :stream))) + (values + (ext::process-output process) + (ext::process-error process) + (ext::process-exit-code process))) + + #+allegro + (multiple-value-bind (output error status) + (excl.osi:command-output command :whole t) + (values output error status)) + + #+lispworks + ;; BUG: Lispworks combines output and error streams + (let ((output (make-output-string-stream))) + (unwind-protect + (let ((status + (system:call-system-showing-output + command + :shell-type "/bin/sh" + :output-stream output))) + (values (get-output-string output) nil status)) + (close output))) + + #+clisp + ;; BUG: CLisp doesn't allow output to user-specified stream + (values + nil + nil + (ext:run-shell-command command :output :terminal :wait t)) + + #+openmcl + (let ((process (ccl:run-program + "/bin/sh" + (list "-c" command) + :input nil :output :stream :error :stream + :wait t))) + (values + (get-output-stream-string (ccl::external-process-output-stream process)) + (get-output-stream-string (ccl::external-process-error-stream process)) + (nth-value 1 (ccl::external-process-status process)))) + + #-(or openmcl clisp lispworks allegro scl cmu sbcl) + (error "COMMAND-OUTPUT not implemented for this Lisp") + + ))