build: Clearly mark Nixpkgs as optional.
[jackhill/guix/guix.git] / guix / utils.scm
CommitLineData
e3deeebb
LC
1;;; Guix --- Nix package management from Guile. -*- coding: utf-8 -*-
2;;; Copyright (C) 2012 Ludovic Courtès <ludo@gnu.org>
3;;;
4;;; This file is part of Guix.
5;;;
6;;; Guix is free software; you can redistribute it and/or modify it
7;;; under the terms of the GNU General Public License as published by
8;;; the Free Software Foundation; either version 3 of the License, or (at
9;;; your option) any later version.
10;;;
11;;; Guix is distributed in the hope that it will be useful, but
12;;; WITHOUT ANY WARRANTY; without even the implied warranty of
13;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14;;; GNU General Public License for more details.
15;;;
16;;; You should have received a copy of the GNU General Public License
17;;; along with Guix. If not, see <http://www.gnu.org/licenses/>.
18
19(define-module (guix utils)
38b3122a 20 #:use-module (srfi srfi-1)
72d86963 21 #:use-module (srfi srfi-9)
38b3122a 22 #:use-module (srfi srfi-26)
de4c3f26 23 #:use-module (srfi srfi-39)
e3deeebb
LC
24 #:use-module (srfi srfi-60)
25 #:use-module (rnrs bytevectors)
dba6b34b 26 #:use-module ((rnrs io ports) #:select (put-bytevector))
c8369cac 27 #:use-module (ice-9 vlist)
38b3122a 28 #:use-module (ice-9 format)
de4c3f26
LC
29 #:autoload (ice-9 popen) (open-pipe*)
30 #:autoload (ice-9 rdelim) (read-line)
98090557 31 #:use-module (ice-9 regex)
72d86963 32 #:use-module (ice-9 match)
8ef3401f 33 #:use-module (ice-9 format)
39b9372c 34 #:autoload (system foreign) (pointer->procedure)
e3deeebb
LC
35 #:export (bytevector-quintet-length
36 bytevector->base32-string
d0a92b75 37 bytevector->nix-base32-string
38b3122a 38 bytevector->base16-string
c8369cac
LC
39 base32-string->bytevector
40 nix-base32-string->bytevector
6d800a80 41 base16-string->bytevector
de4c3f26
LC
42 sha256
43
44 %nixpkgs-directory
45 nixpkgs-derivation
ce5d658c 46 nixpkgs-derivation*
de4c3f26 47
72d86963 48 define-record-type*
900f7267 49 compile-time-value
98090557 50 memoize
ff352cfb
LC
51
52 location
53 location?
54 location-file
55 location-line
56 location-column
57 source-properties->location
58
98090557
LC
59 gnu-triplet->nix-system
60 %current-system))
e3deeebb 61
38b3122a 62\f
dba6b34b
LC
63;;;
64;;; Compile-time computations.
65;;;
66
67(define-syntax compile-time-value
68 (syntax-rules ()
69 "Evaluate the given expression at compile time. The expression must
70evaluate to a simple datum."
71 ((_ exp)
72 (let-syntax ((v (lambda (s)
73 (let ((val exp))
74 (syntax-case s ()
75 (_ #`'#,(datum->syntax s val)))))))
76 v))))
77
78\f
38b3122a
LC
79;;;
80;;; Base 32.
81;;;
82
e3deeebb
LC
83(define bytevector-quintet-ref
84 (let* ((ref bytevector-u8-ref)
85 (ref+ (lambda (bv offset)
86 (let ((o (+ 1 offset)))
87 (if (>= o (bytevector-length bv))
88 0
89 (bytevector-u8-ref bv o)))))
90 (ref0 (lambda (bv offset)
91 (bit-field (ref bv offset) 3 8)))
92 (ref1 (lambda (bv offset)
93 (logior (ash (bit-field (ref bv offset) 0 3) 2)
94 (bit-field (ref+ bv offset) 6 8))))
95 (ref2 (lambda (bv offset)
96 (bit-field (ref bv offset) 1 6)))
97 (ref3 (lambda (bv offset)
98 (logior (ash (bit-field (ref bv offset) 0 1) 4)
99 (bit-field (ref+ bv offset) 4 8))))
100 (ref4 (lambda (bv offset)
101 (logior (ash (bit-field (ref bv offset) 0 4) 1)
102 (bit-field (ref+ bv offset) 7 8))))
103 (ref5 (lambda (bv offset)
104 (bit-field (ref bv offset) 2 7)))
105 (ref6 (lambda (bv offset)
106 (logior (ash (bit-field (ref bv offset) 0 2) 3)
107 (bit-field (ref+ bv offset) 5 8))))
108 (ref7 (lambda (bv offset)
109 (bit-field (ref bv offset) 0 5)))
110 (refs (vector ref0 ref1 ref2 ref3 ref4 ref5 ref6 ref7)))
111 (lambda (bv index)
112 "Return the INDEXth quintet of BV."
113 (let ((p (vector-ref refs (modulo index 8))))
114 (p bv (quotient (* index 5) 8))))))
115
f9c7080a
LC
116(define bytevector-quintet-ref-right
117 (let* ((ref bytevector-u8-ref)
118 (ref+ (lambda (bv offset)
119 (let ((o (+ 1 offset)))
120 (if (>= o (bytevector-length bv))
121 0
122 (bytevector-u8-ref bv o)))))
123 (ref0 (lambda (bv offset)
124 (bit-field (ref bv offset) 0 5)))
125 (ref1 (lambda (bv offset)
126 (logior (bit-field (ref bv offset) 5 8)
127 (ash (bit-field (ref+ bv offset) 0 2) 3))))
128 (ref2 (lambda (bv offset)
129 (bit-field (ref bv offset) 2 7)))
130 (ref3 (lambda (bv offset)
131 (logior (bit-field (ref bv offset) 7 8)
132 (ash (bit-field (ref+ bv offset) 0 4) 1))))
133 (ref4 (lambda (bv offset)
134 (logior (bit-field (ref bv offset) 4 8)
135 (ash (bit-field (ref+ bv offset) 0 1) 4))))
136 (ref5 (lambda (bv offset)
137 (bit-field (ref bv offset) 1 6)))
138 (ref6 (lambda (bv offset)
139 (logior (bit-field (ref bv offset) 6 8)
140 (ash (bit-field (ref+ bv offset) 0 3) 2))))
141 (ref7 (lambda (bv offset)
142 (bit-field (ref bv offset) 3 8)))
143 (refs (vector ref0 ref1 ref2 ref3 ref4 ref5 ref6 ref7)))
144 (lambda (bv index)
145 "Return the INDEXth quintet of BV, assuming quintets start from the
146least-significant bits, contrary to what RFC 4648 describes."
147 (let ((p (vector-ref refs (modulo index 8))))
148 (p bv (quotient (* index 5) 8))))))
149
e3deeebb
LC
150(define (bytevector-quintet-length bv)
151 "Return the number of quintets (including truncated ones) available in BV."
152 (ceiling (/ (* (bytevector-length bv) 8) 5)))
153
154(define (bytevector-quintet-fold proc init bv)
155 "Return the result of applying PROC to each quintet of BV and the result of
156the previous application or INIT."
157 (define len
158 (bytevector-quintet-length bv))
159
160 (let loop ((i 0)
161 (r init))
162 (if (= i len)
163 r
164 (loop (1+ i) (proc (bytevector-quintet-ref bv i) r)))))
165
f9c7080a
LC
166(define (bytevector-quintet-fold-right proc init bv)
167 "Return the result of applying PROC to each quintet of BV and the result of
168the previous application or INIT."
169 (define len
170 (bytevector-quintet-length bv))
171
172 (let loop ((i len)
173 (r init))
174 (if (zero? i)
175 r
176 (let ((j (- i 1)))
177 (loop j (proc (bytevector-quintet-ref-right bv j) r))))))
178
179(define (make-bytevector->base32-string quintet-fold base32-chars)
e3deeebb
LC
180 (lambda (bv)
181 "Return a base32 encoding of BV using BASE32-CHARS as the alphabet."
f9c7080a
LC
182 (let ((chars (quintet-fold (lambda (q r)
183 (cons (vector-ref base32-chars q)
184 r))
185 '()
186 bv)))
e3deeebb
LC
187 (list->string (reverse chars)))))
188
189(define %nix-base32-chars
190 ;; See `libutil/hash.cc'.
191 #(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9
192 #\a #\b #\c #\d #\f #\g #\h #\i #\j #\k #\l #\m #\n
193 #\p #\q #\r #\s #\v #\w #\x #\y #\z))
194
195(define %rfc4648-base32-chars
196 #(#\a #\b #\c #\d #\e #\f #\g #\h #\i #\j #\k #\l #\m
197 #\n #\o #\p #\q #\r #\s #\t #\u #\v #\w #\x #\y #\z
198 #\2 #\3 #\4 #\5 #\6 #\7))
199
200(define bytevector->base32-string
f9c7080a
LC
201 (make-bytevector->base32-string bytevector-quintet-fold
202 %rfc4648-base32-chars))
e3deeebb
LC
203
204(define bytevector->nix-base32-string
f9c7080a
LC
205 (make-bytevector->base32-string bytevector-quintet-fold-right
206 %nix-base32-chars))
38b3122a 207
c8369cac
LC
208
209(define bytevector-quintet-set!
210 (let* ((setq! (lambda (bv offset start stop value)
211 (let ((v (bytevector-u8-ref bv offset))
212 (w (arithmetic-shift value start))
213 (m (bitwise-xor (1- (expt 2 stop))
214 (1- (expt 2 start)))))
215 (bytevector-u8-set! bv offset
216 (bitwise-merge m w v)))))
217 (set0! (lambda (bv offset value)
218 (setq! bv offset 3 8 value)))
219 (set1! (lambda (bv offset value)
220 (setq! bv offset 0 3 (bit-field value 2 5))
221 (or (= (+ 1 offset) (bytevector-length bv))
222 (setq! bv (+ 1 offset) 6 8 (bit-field value 0 2)))))
223 (set2! (lambda (bv offset value)
224 (setq! bv offset 1 6 value)))
225 (set3! (lambda (bv offset value)
226 (setq! bv offset 0 1 (bit-field value 4 5))
227 (or (= (+ 1 offset) (bytevector-length bv))
228 (setq! bv (+ 1 offset) 4 8 (bit-field value 0 4)))))
229 (set4! (lambda (bv offset value)
230 (setq! bv offset 0 4 (bit-field value 1 5))
231 (or (= (+ 1 offset) (bytevector-length bv))
232 (setq! bv (+ 1 offset) 7 8 (bit-field value 0 1)))))
233 (set5! (lambda (bv offset value)
234 (setq! bv offset 2 7 value)))
235 (set6! (lambda (bv offset value)
236 (setq! bv offset 0 2 (bit-field value 3 5))
237 (or (= (+ 1 offset) (bytevector-length bv))
238 (setq! bv (+ 1 offset) 5 8 (bit-field value 0 3)))))
239 (set7! (lambda (bv offset value)
240 (setq! bv offset 0 5 value)))
241 (sets (vector set0! set1! set2! set3! set4! set5! set6! set7!)))
242 (lambda (bv index value)
243 "Set the INDEXth quintet of BV to VALUE."
244 (let ((p (vector-ref sets (modulo index 8))))
245 (p bv (quotient (* index 5) 8) (logand value #x1f))))))
246
247(define bytevector-quintet-set-right!
248 (let* ((setq! (lambda (bv offset start stop value)
249 (let ((v (bytevector-u8-ref bv offset))
250 (w (arithmetic-shift value start))
251 (m (bitwise-xor (1- (expt 2 stop))
252 (1- (expt 2 start)))))
253 (bytevector-u8-set! bv offset
254 (bitwise-merge m w v)))))
255 (set0! (lambda (bv offset value)
256 (setq! bv offset 0 5 value)))
257 (set1! (lambda (bv offset value)
258 (setq! bv offset 5 8 (bit-field value 0 3))
259 (or (= (+ 1 offset) (bytevector-length bv))
260 (setq! bv (+ 1 offset) 0 2 (bit-field value 3 5)))))
261 (set2! (lambda (bv offset value)
262 (setq! bv offset 2 7 value)))
263 (set3! (lambda (bv offset value)
264 (setq! bv offset 7 8 (bit-field value 0 1))
265 (or (= (+ 1 offset) (bytevector-length bv))
266 (setq! bv (+ 1 offset) 0 4 (bit-field value 1 5)))))
267 (set4! (lambda (bv offset value)
268 (setq! bv offset 4 8 (bit-field value 0 4))
269 (or (= (+ 1 offset) (bytevector-length bv))
270 (setq! bv (+ 1 offset) 0 1 (bit-field value 4 5)))))
271 (set5! (lambda (bv offset value)
272 (setq! bv offset 1 6 value)))
273 (set6! (lambda (bv offset value)
274 (setq! bv offset 6 8 (bit-field value 0 2))
275 (or (= (+ 1 offset) (bytevector-length bv))
276 (setq! bv (+ 1 offset) 0 3 (bit-field value 2 5)))))
277 (set7! (lambda (bv offset value)
278 (setq! bv offset 3 8 value)))
279 (sets (vector set0! set1! set2! set3! set4! set5! set6! set7!)))
280 (lambda (bv index value)
281 "Set the INDEXth quintet of BV to VALUE, assuming quintets start from
282the least-significant bits."
283 (let ((p (vector-ref sets (modulo index 8))))
284 (p bv (quotient (* index 5) 8) (logand value #x1f))))))
285
286(define (base32-string-unfold f s)
287 "Given procedure F which, when applied to a character, returns the
288corresponding quintet, return the bytevector corresponding to string S."
289 (define len (string-length s))
290
291 (let ((bv (make-bytevector (quotient (* len 5) 8))))
292 (string-fold (lambda (chr index)
293 (bytevector-quintet-set! bv index (f chr))
294 (+ 1 index))
295 0
296 s)
297 bv))
298
299(define (base32-string-unfold-right f s)
300 "Given procedure F which, when applied to a character, returns the
301corresponding quintet, return the bytevector corresponding to string S,
302starting from the right of S."
303 (define len (string-length s))
304
305 (let ((bv (make-bytevector (quotient (* len 5) 8))))
306 (string-fold-right (lambda (chr index)
307 (bytevector-quintet-set-right! bv index (f chr))
308 (+ 1 index))
309 0
310 s)
311 bv))
312
313(define (make-base32-string->bytevector base32-string-unfold base32-chars)
314 (let ((char->value (let loop ((i 0)
315 (v vlist-null))
316 (if (= i (vector-length base32-chars))
317 v
318 (loop (+ 1 i)
319 (vhash-consv (vector-ref base32-chars i)
320 i v))))))
321 (lambda (s)
322 "Return the binary representation of base32 string S as a bytevector."
323 (base32-string-unfold (lambda (chr)
324 (or (and=> (vhash-assv chr char->value) cdr)
325 (error "invalid base32 character" chr)))
326 s))))
327
328(define base32-string->bytevector
329 (make-base32-string->bytevector base32-string-unfold %rfc4648-base32-chars))
330
331(define nix-base32-string->bytevector
332 (make-base32-string->bytevector base32-string-unfold-right %nix-base32-chars))
333
334
38b3122a
LC
335\f
336;;;
337;;; Base 16.
338;;;
339
340(define (bytevector->base16-string bv)
341 "Return the hexadecimal representation of BV's contents."
342 (define len
343 (bytevector-length bv))
344
345 (let-syntax ((base16-chars (lambda (s)
346 (syntax-case s ()
347 (_
348 (let ((v (list->vector
349 (unfold (cut > <> 255)
350 (lambda (n)
351 (format #f "~2,'0x" n))
352 1+
353 0))))
354 v))))))
355 (define chars base16-chars)
356 (let loop ((i 0)
357 (r '()))
358 (if (= i len)
359 (string-concatenate-reverse r)
360 (loop (+ 1 i)
361 (cons (vector-ref chars (bytevector-u8-ref bv i)) r))))))
362
6d800a80
LC
363(define base16-string->bytevector
364 (let ((chars->value (fold (lambda (i r)
365 (vhash-consv (string-ref (number->string i 16)
366 0)
367 i r))
368 vlist-null
369 (iota 16))))
370 (lambda (s)
371 "Return the bytevector whose hexadecimal representation is string S."
372 (define bv
373 (make-bytevector (quotient (string-length s) 2) 0))
374
375 (string-fold (lambda (chr i)
376 (let ((j (quotient i 2))
377 (v (and=> (vhash-assv chr chars->value) cdr)))
378 (if v
379 (if (zero? (logand i 1))
380 (bytevector-u8-set! bv j
381 (arithmetic-shift v 4))
382 (let ((w (bytevector-u8-ref bv j)))
383 (bytevector-u8-set! bv j (logior v w))))
384 (error "invalid hexadecimal character" chr)))
385 (+ i 1))
386 0
387 s)
388 bv)))
389
d0a92b75
LC
390\f
391;;;
392;;; Hash.
393;;;
394
3a310cc0
LC
395(define %libgcrypt
396 ;; Name of the libgcrypt shared library.
397 (compile-time-value (or (getenv "LIBGCRYPT") "libgcrypt")))
398
39b9372c
LC
399(define sha256
400 (cond
401 ((compile-time-value
3a310cc0 402 (false-if-exception (dynamic-link %libgcrypt)))
39b9372c
LC
403 ;; Using libgcrypt.
404 (let ((hash (pointer->procedure void
405 (dynamic-func "gcry_md_hash_buffer"
3a310cc0 406 (dynamic-link %libgcrypt))
39b9372c
LC
407 `(,int * * ,size_t)))
408 (sha256 8)) ; GCRY_MD_SHA256, as of 1.5.0
409 (lambda (bv)
410 "Return the SHA256 of BV as a bytevector."
411 (let ((digest (make-bytevector (/ 256 8))))
412 (hash sha256 (bytevector->pointer digest)
413 (bytevector->pointer bv) (bytevector-length bv))
414 digest))))
415
416 ((compile-time-value
417 (false-if-exception (resolve-interface '(chop hash))))
418 ;; Using libchop.
419 (let ((bytevector-hash (@ (chop hash) bytevector-hash))
420 (hash-method/sha256 (@ (chop hash) hash-method/sha256)))
421 (lambda (bv)
422 "Return the SHA256 of BV as a bytevector."
423 (bytevector-hash hash-method/sha256 bv))))
424
425 (else
426 ;; Slow, poor programmer's implementation that uses Coreutils.
427 (lambda (bv)
428 "Return the SHA256 of BV as a bytevector."
dba6b34b
LC
429 (let ((in (pipe))
430 (out (pipe))
431 (pid (primitive-fork)))
432 (if (= 0 pid)
39b9372c 433 (begin ; child
dba6b34b
LC
434 (close (cdr in))
435 (close (car out))
436 (close 0)
437 (close 1)
438 (dup2 (fileno (car in)) 0)
439 (dup2 (fileno (cdr out)) 1)
440 (execlp "sha256sum" "sha256sum"))
39b9372c 441 (begin ; parent
dba6b34b
LC
442 (close (car in))
443 (close (cdr out))
444 (put-bytevector (cdr in) bv)
39b9372c 445 (close (cdr in)) ; EOF
dba6b34b
LC
446 (let ((line (car (string-tokenize (read-line (car out))))))
447 (close (car out))
448 (and (and=> (status:exit-val (cdr (waitpid pid)))
449 zero?)
39b9372c 450 (base16-string->bytevector line))))))))))
d0a92b75 451
de4c3f26
LC
452
453\f
454;;;
455;;; Nixpkgs.
456;;;
457
458(define %nixpkgs-directory
900f7267
LC
459 (make-parameter
460 ;; Capture the build-time value of $NIXPKGS.
e76bdf8b
LC
461 (or (compile-time-value (getenv "NIXPKGS"))
462 (getenv "NIXPKGS"))))
de4c3f26 463
fbc93bed 464(define* (nixpkgs-derivation attribute #:optional (system (%current-system)))
de4c3f26 465 "Return the derivation path of ATTRIBUTE in Nixpkgs."
b86b0056
LC
466 (let* ((p (open-pipe* OPEN_READ (or (getenv "NIX_INSTANTIATE")
467 "nix-instantiate")
fbc93bed
LC
468 "-A" attribute (%nixpkgs-directory)
469 "--argstr" "system" system))
de4c3f26
LC
470 (l (read-line p))
471 (s (close-pipe p)))
472 (and (zero? (status:exit-val s))
473 (not (eof-object? l))
474 l)))
475
ce5d658c
LC
476(define-syntax-rule (nixpkgs-derivation* attribute)
477 "Evaluate the given Nixpkgs derivation at compile-time."
478 (compile-time-value (nixpkgs-derivation attribute)))
479
de4c3f26
LC
480\f
481;;;
482;;; Miscellaneous.
483;;;
484
72d86963
LC
485(define-syntax define-record-type*
486 (lambda (s)
487 "Define the given record type such that an additional \"syntactic
488constructor\" is defined, which allows instances to be constructed with named
489field initializers, à la SRFI-35, as well as default values."
dcd60f43
LC
490 (define (make-syntactic-constructor type name ctor fields defaults)
491 "Make the syntactic constructor NAME for TYPE, that calls CTOR, and
492expects all of FIELDS to be initialized. DEFAULTS is the list of
493FIELD/DEFAULT-VALUE tuples."
494 (with-syntax ((type type)
495 (name name)
72d86963
LC
496 (ctor ctor)
497 (expected fields)
498 (defaults defaults))
dcd60f43 499 #`(define-syntax name
72d86963 500 (lambda (s)
dcd60f43
LC
501 (define (record-inheritance orig-record field+value)
502 ;; Produce code that returns a record identical to
503 ;; ORIG-RECORD, except that values for the FIELD+VALUE alist
504 ;; prevail.
505 (define (field-inherited-value f)
506 (and=> (find (lambda (x)
507 (eq? f (car (syntax->datum x))))
508 field+value)
509 car))
510
511 #`(make-struct type 0
512 #,@(map (lambda (field index)
513 (or (field-inherited-value field)
514 #`(struct-ref #,orig-record
515 #,index)))
516 'expected
517 (iota (length 'expected)))))
518
519
520 (syntax-case s (inherit #,@fields)
521 ((_ (inherit orig-record) (field value) (... ...))
522 #`(letrec* ((field value) (... ...))
523 #,(record-inheritance #'orig-record
524 #'((field value) (... ...)))))
72d86963 525 ((_ (field value) (... ...))
8fd5bd2b
LC
526 (let ((fields (map syntax->datum #'(field (... ...))))
527 (dflt (map (match-lambda
528 ((f v)
529 (list (syntax->datum f) v)))
530 #'defaults)))
531
dcd60f43
LC
532 (define (field-value f)
533 (or (and=> (find (lambda (x)
534 (eq? f (car (syntax->datum x))))
535 #'((field value) (... ...)))
536 car)
537 (car (assoc-ref dflt (syntax->datum f)))))
72d86963 538
8ef3401f
LC
539 (let-syntax ((error*
540 (syntax-rules ()
541 ((_ fmt args (... ...))
542 (syntax-violation 'name
543 (format #f fmt args
544 (... ...))
545 s)))))
546 (let ((fields (append fields (map car dflt))))
547 (cond ((lset= eq? fields 'expected)
8fd5bd2b
LC
548 #`(letrec* ((field value) (... ...))
549 (ctor #,@(map field-value 'expected))))
8ef3401f
LC
550 ((pair? (lset-difference eq? fields 'expected))
551 (error* "extraneous field initializers ~a"
552 (lset-difference eq? fields 'expected)))
553 (else
554 (error* "missing field initializers ~a"
555 (lset-difference eq? 'expected
556 fields)))))))))))))
72d86963
LC
557
558 (define (field-default-value s)
559 (syntax-case s (default)
560 ((field (default val) _ ...)
561 (list #'field #'val))
562 ((field _ options ...)
563 (field-default-value #'(field options ...)))
564 (_ #f)))
565
566 (syntax-case s ()
567 ((_ type syntactic-ctor ctor pred
568 (field get options ...) ...)
569 #`(begin
570 (define-record-type type
571 (ctor field ...)
572 pred
573 (field get) ...)
dcd60f43 574 #,(make-syntactic-constructor #'type #'syntactic-ctor #'ctor
72d86963
LC
575 #'(field ...)
576 (filter-map field-default-value
577 #'((field options ...)
578 ...))))))))
579
de4c3f26
LC
580(define (memoize proc)
581 "Return a memoizing version of PROC."
582 (let ((cache (make-hash-table)))
583 (lambda args
584 (let ((results (hash-ref cache args)))
585 (if results
586 (apply values results)
587 (let ((results (call-with-values (lambda ()
588 (apply proc args))
589 list)))
590 (hash-set! cache args results)
591 (apply values results)))))))
98090557
LC
592
593(define (gnu-triplet->nix-system triplet)
594 "Return the Nix system type corresponding to TRIPLET, a GNU triplet as
595returned by `config.guess'."
596 (let ((triplet (cond ((string-match "^i[345]86-(.*)$" triplet)
597 =>
598 (lambda (m)
599 (string-append "i686-" (match:substring m 1))))
600 (else triplet))))
601 (cond ((string-match "^([^-]+)-([^-]+-)?linux-gnu.*" triplet)
602 =>
603 (lambda (m)
604 ;; Nix omits `-gnu' for GNU/Linux.
605 (string-append (match:substring m 1) "-linux")))
606 ((string-match "^([^-]+)-([^-]+-)?([[:alpha:]]+)([0-9]+\\.?)*$" triplet)
607 =>
608 (lambda (m)
609 ;; Nix strip the version number from names such as `gnu0.3',
610 ;; `darwin10.2.0', etc., and always strips the vendor part.
611 (string-append (match:substring m 1) "-"
612 (match:substring m 3))))
613 (else triplet))))
614
615(define %current-system
616 ;; System type as expected by Nix, usually ARCHITECTURE-KERNEL.
617 (make-parameter (gnu-triplet->nix-system %host-type)))
ff352cfb
LC
618
619\f
620;;;
621;;; Source location.
622;;;
623
624;; A source location.
625(define-record-type <location>
626 (make-location file line column)
627 location?
628 (file location-file) ; file name
629 (line location-line) ; 1-indexed line
630 (column location-column)) ; 0-indexed column
631
632(define location
633 (memoize
634 (lambda (file line column)
635 "Return the <location> object for the given FILE, LINE, and COLUMN."
636 (and line column file
637 (make-location file line column)))))
638
639(define (source-properties->location loc)
640 "Return a location object based on the info in LOC, an alist as returned
641by Guile's `source-properties', `frame-source', `current-source-location',
642etc."
643 (let ((file (assq-ref loc 'filename))
644 (line (assq-ref loc 'line))
645 (col (assq-ref loc 'column)))
5e6c9012
LC
646 ;; In accordance with the GCS, start line and column numbers at 1.
647 (location file (and line (+ line 1)) (and col (+ col 1)))))