1 | ;;; -*- package: asdf-install; -*- |
---|
2 | ;;; |
---|
3 | ;;; Digitool-specific bootstrapping |
---|
4 | ;;; |
---|
5 | ;;; 2004-01-18 james.anderson@setf.de additions for MCL |
---|
6 | ;;; 2008-01-22 added exit-code checks to call-system |
---|
7 | |
---|
8 | (in-package #:asdf-install) |
---|
9 | |
---|
10 | #+:digitool |
---|
11 | (let ((getenv-fn 0) |
---|
12 | (setenv-fn 0) |
---|
13 | (unsetenv-fn 0) |
---|
14 | (popen-fn 0) |
---|
15 | (pclose-fn 0) |
---|
16 | (fread-fn 0) |
---|
17 | (feof-fn 0)) |
---|
18 | (ccl::with-cfstrs ((framework "System.framework")) |
---|
19 | (let ((err 0) |
---|
20 | (baseURL nil) |
---|
21 | (bundleURL nil) |
---|
22 | (bundle nil)) |
---|
23 | (ccl::rlet ((folder :fsref)) |
---|
24 | ;; Find the folder holding the bundle |
---|
25 | (setf err (ccl::require-trap traps::_FSFindFolder |
---|
26 | (ccl::require-trap-constant traps::$kOnAppropriateDisk) |
---|
27 | (ccl::require-trap-constant traps::$kFrameworksFolderType) |
---|
28 | t folder)) |
---|
29 | ;; if everything's cool, make a URL for it |
---|
30 | (when (zerop err) |
---|
31 | (setf baseURL (ccl::require-trap traps::_CFURLCreateFromFSRef (ccl::%null-ptr) folder))) |
---|
32 | (if (ccl::%null-ptr-p baseURL) |
---|
33 | (setf err (ccl::require-trap-constant traps::$coreFoundationUnknownErr)))) |
---|
34 | ;; if everything's cool, make a URL for the bundle |
---|
35 | (when (zerop err) |
---|
36 | (setf bundleURL (ccl::require-trap traps::_CFURLCreateCopyAppendingPathComponent (ccl::%null-ptr) baseURL framework nil)) |
---|
37 | (if (ccl::%null-ptr-p bundleURL) |
---|
38 | (setf err (ccl::require-trap-constant traps::$coreFoundationUnknownErr)))) |
---|
39 | ;; if everything's cool, create it |
---|
40 | (when (zerop err) |
---|
41 | (setf bundle (ccl::require-trap traps::_CFBundleCreate (ccl::%null-ptr) bundleURL)) |
---|
42 | (if (ccl::%null-ptr-p bundle) |
---|
43 | (setf err (ccl::require-trap-constant traps::$coreFoundationUnknownErr)))) |
---|
44 | ;; if everything's cool, load it |
---|
45 | (when (zerop err) |
---|
46 | (if (not (ccl::require-trap traps::_CFBundleLoadExecutable bundle)) |
---|
47 | (setf err (ccl::require-trap-constant traps::$coreFoundationUnknownErr)))) |
---|
48 | ;; if there's an error, but we've got a pointer, free it and clear result |
---|
49 | (when (and (not (zerop err)) (not (ccl::%null-ptr-p bundle))) |
---|
50 | (ccl::require-trap traps::_CFRelease bundle) |
---|
51 | (setf bundle nil)) |
---|
52 | ;; free the URLs if here non-null |
---|
53 | (when (not (ccl::%null-ptr-p bundleURL)) |
---|
54 | (ccl::require-trap traps::_CFRelease bundleURL)) |
---|
55 | (when (not (ccl::%null-ptr-p baseURL)) |
---|
56 | (ccl::require-trap traps::_CFRelease baseURL)) |
---|
57 | (cond (bundle |
---|
58 | ;; extract the necessary function id's |
---|
59 | (flet ((get-addr (name) |
---|
60 | (ccl::with-cfstrs ((c-name name)) |
---|
61 | (let* ((addr (ccl::require-trap traps::_CFBundleGetFunctionPointerForName bundle c-name))) |
---|
62 | (when (ccl::%null-ptr-p addr) |
---|
63 | (error "Couldn't resolve address of foreign function ~s" name)) |
---|
64 | (ccl::rlet ((buf :long)) |
---|
65 | (setf (ccl::%get-ptr buf) addr) |
---|
66 | (ash (ccl::%get-signed-long buf) -2)))))) |
---|
67 | (setf getenv-fn (get-addr "getenv")) |
---|
68 | (setf setenv-fn (get-addr "setenv")) |
---|
69 | (setf unsetenv-fn (get-addr "unsetenv")) |
---|
70 | (setf popen-fn (get-addr "popen")) |
---|
71 | (setf pclose-fn (get-addr "pclose")) |
---|
72 | (setf fread-fn (get-addr "fread")) |
---|
73 | (setf feof-fn (get-addr "feof"))) |
---|
74 | (ccl::require-trap traps::_CFRelease bundle) |
---|
75 | (setf bundle nil)) |
---|
76 | (t |
---|
77 | (error "can't resolve core framework entry points."))))) |
---|
78 | |
---|
79 | (defun ccl::getenv (variable-name) |
---|
80 | (ccl::with-cstrs ((c-variable-name variable-name)) |
---|
81 | (let* ((env-ptr (ccl::%null-ptr))) |
---|
82 | (declare (dynamic-extent env-ptr)) |
---|
83 | (ccl::%setf-macptr env-ptr (ccl::ppc-ff-call getenv-fn |
---|
84 | :address c-variable-name |
---|
85 | :address)) |
---|
86 | (unless (ccl::%null-ptr-p env-ptr) |
---|
87 | (ccl::%get-cstring env-ptr))))) |
---|
88 | |
---|
89 | (defun ccl::setenv (variable-name variable-value) |
---|
90 | (ccl::with-cstrs ((c-variable-name variable-name) |
---|
91 | (c-variable-value variable-value)) |
---|
92 | (ccl::ppc-ff-call setenv-fn |
---|
93 | :address c-variable-name |
---|
94 | :address c-variable-value |
---|
95 | :signed-fullword 1 |
---|
96 | :signed-fullword))) |
---|
97 | |
---|
98 | (defun ccl::unsetenv (variable-name) |
---|
99 | (ccl::with-cstrs ((c-variable-name variable-name)) |
---|
100 | (ccl::ppc-ff-call unsetenv-fn |
---|
101 | :address c-variable-name |
---|
102 | :void))) |
---|
103 | |
---|
104 | (labels ((fread (fp buffer length) |
---|
105 | (ccl::ppc-ff-call fread-fn |
---|
106 | :address buffer |
---|
107 | :unsigned-fullword 1 |
---|
108 | :unsigned-fullword length |
---|
109 | :address fp |
---|
110 | :signed-fullword)) |
---|
111 | (feof-p (fp) |
---|
112 | (not (zerop (ccl::ppc-ff-call feof-fn |
---|
113 | :address fp |
---|
114 | :signed-fullword)))) |
---|
115 | (popen (command) |
---|
116 | (ccl::with-cstrs ((read "r") |
---|
117 | (cmd command)) |
---|
118 | (ccl::ppc-ff-call popen-fn |
---|
119 | :address cmd |
---|
120 | :address read |
---|
121 | :address))) |
---|
122 | (pclose (fp) |
---|
123 | (ccl::ppc-ff-call pclose-fn |
---|
124 | :address fp |
---|
125 | :signed-fullword)) |
---|
126 | |
---|
127 | (fread-decoded (fp io-buffer io-buffer-length string-buffer script) |
---|
128 | (cond ((feof-p fp) |
---|
129 | (values nil string-buffer)) |
---|
130 | (t |
---|
131 | (let ((io-count (fread fp io-buffer io-buffer-length))) |
---|
132 | (cond ((and io-count (plusp io-count)) |
---|
133 | (if script |
---|
134 | (multiple-value-bind (chars fatp) (ccl::pointer-char-length io-buffer io-count script) |
---|
135 | (cond ((not fatp) |
---|
136 | (ccl::%copy-ptr-to-ivector io-buffer 0 string-buffer 0 io-count)) |
---|
137 | (t |
---|
138 | (unless (>= (length string-buffer) chars) |
---|
139 | (setf string-buffer (make-string chars :element-type 'base-character))) |
---|
140 | (ccl::pointer-to-string-in-script io-buffer string-buffer io-count script) |
---|
141 | (setf io-count chars)))) |
---|
142 | (ccl::%copy-ptr-to-ivector io-buffer 0 string-buffer 0 io-count)) |
---|
143 | (values io-count string-buffer)) |
---|
144 | (t |
---|
145 | (values 0 string-buffer)))))))) |
---|
146 | |
---|
147 | (defun ccl::call-system (command) |
---|
148 | (let* ((script (ccl::default-script nil)) |
---|
149 | (table (ccl::get-char-byte-table script)) |
---|
150 | (result (make-array 128 :element-type 'character :adjustable t :fill-pointer 0)) |
---|
151 | (string-buffer (unless table (make-string 512 :element-type 'base-character))) |
---|
152 | (io-count 0) |
---|
153 | (fp (popen command)) |
---|
154 | (exit-code 0)) |
---|
155 | (unless (ccl::%null-ptr-p fp) |
---|
156 | (unwind-protect |
---|
157 | (ccl::%stack-block ((io-buffer 512)) |
---|
158 | (loop (multiple-value-setq (io-count string-buffer) |
---|
159 | (fread-decoded fp io-buffer 512 string-buffer (when table script))) |
---|
160 | (unless io-count (return)) |
---|
161 | (let ((char #\null)) |
---|
162 | (dotimes (i io-count) |
---|
163 | (case (setf char (schar string-buffer i)) |
---|
164 | ((#\return #\linefeed) (setf char #\newline))) |
---|
165 | (vector-push-extend char result))))) |
---|
166 | (setf exit-code (pclose fp)) |
---|
167 | (setf fp nil)) |
---|
168 | (if (zerop exit-code) |
---|
169 | (values result 0) |
---|
170 | (values nil exit-code result))))) |
---|
171 | |
---|
172 | ;; need a function to avoid both the reader macro and the compiler |
---|
173 | (setf (symbol-function '%new-ptr) #'ccl::%new-ptr) |
---|
174 | |
---|
175 | (defclass popen-input-stream (ccl::input-stream) |
---|
176 | ((io-buffer :initform nil) |
---|
177 | (fp :initform nil ) |
---|
178 | (string-buffer :initform nil) |
---|
179 | (length :initform 0) |
---|
180 | (index :initform 0) |
---|
181 | (script :initarg :script :initform (ccl::default-script nil))) |
---|
182 | (:default-initargs :direction :input)) |
---|
183 | |
---|
184 | (defmethod initialize-instance :after ((instance popen-input-stream) &key command) |
---|
185 | (with-slots (io-buffer string-buffer fp script) instance |
---|
186 | (setf fp (popen command) |
---|
187 | io-buffer (%new-ptr 512 nil) |
---|
188 | string-buffer (make-string 512 :element-type 'base-character)) |
---|
189 | (when script (unless (ccl::get-char-byte-table script) (setf script nil))))) |
---|
190 | |
---|
191 | (defmethod ccl::stream-close ((stream popen-input-stream)) |
---|
192 | (declare (ignore abort)) |
---|
193 | (with-slots (io-buffer string-buffer fp ccl::direction) stream |
---|
194 | (when (and fp (not (ccl::%null-ptr-p fp))) |
---|
195 | (pclose fp) |
---|
196 | (setf fp nil) |
---|
197 | (setf ccl::direction :closed) |
---|
198 | (ccl::disposeptr io-buffer) |
---|
199 | (setf io-buffer nil)))) |
---|
200 | |
---|
201 | (defmethod stream-element-type ((stream popen-input-stream)) |
---|
202 | 'character) |
---|
203 | |
---|
204 | (defmethod ccl::stream-tyi ((stream popen-input-stream)) |
---|
205 | ;; despite the decoding provisions, unix input comes with linefeeds |
---|
206 | ;; and i don't know what decoding one would need. |
---|
207 | (with-slots (io-buffer fp string-buffer length index script) stream |
---|
208 | (when fp |
---|
209 | (when (>= index length) |
---|
210 | (multiple-value-setq (length string-buffer) |
---|
211 | (fread-decoded fp io-buffer 512 string-buffer script)) |
---|
212 | (unless (and length (plusp length)) |
---|
213 | (setf length -1) |
---|
214 | (return-from ccl::stream-tyi nil)) |
---|
215 | (setf index 0)) |
---|
216 | (let ((char (schar string-buffer index))) |
---|
217 | (incf index) |
---|
218 | (case char |
---|
219 | ((#\return #\linefeed) #\newline) |
---|
220 | (t char)))))) |
---|
221 | |
---|
222 | (defmethod ccl::stream-untyi ((stream popen-input-stream) char) |
---|
223 | (with-slots (string-buffer length index) stream |
---|
224 | (unless (and (plusp index) (eql char (schar (decf index) string-buffer))) |
---|
225 | (error "invalid tyi character: ~s." char)) |
---|
226 | char)) |
---|
227 | |
---|
228 | (defmethod ccl::stream-eofp ((stream popen-input-stream)) |
---|
229 | (with-slots (length) stream |
---|
230 | (minusp length))))) |
---|