implemented -C option
[rrq/newlisp/packnl.git] / packnl.lsp
1 ;; Utility to "compile" a list of lsp files into a self-contained
2 ;; binary, which is an embedded newlisp binary with the same embedding
3 ;; script as binnl itself.
4 ;;
5 ;; Usage: [ -r ] binary ( member | -a archive | -C dir )*
6 ;;
7 ;; The script processes the arguments from left to right to form then
8 ;; named binary with the named members appended.
9 ;;
10 ;; Use '-a archive' to make the nominated ar style archive members
11 ;; available subsequently for embedding.
12 ;;
13 ;; Use '-A archive' to embed all members of the nominated ar style
14 ;; archive.
15 ;;
16 ;; Use '-C dir' to change source directory
17 ;;
18 ;; Use '-r' to overwrite an existing binary
19
20 ;; The first embedded member will be the "main script".
21 ;;
22
23 (constant
24  'OPTIONS
25  '(("-w" ?) ; write new file
26    ("-u" ? ?) ; unpack members to given directory
27    ("-t" ?) ; merely list packed members of
28    ))
29
30 (load "main-args.lsp")
31
32 (define (compile-file M (D (read-file M)))
33   (unless D
34     (write-line 2 (format "*** Mising %s .. aborting" M))
35     (exit 1))
36   (append-file BINARY (format "%s\n%d\n" M (length D)))
37   (append-file BINARY D))
38
39 (define (compile-ar A M)
40   (let ((MEMBERS (archive M)))
41     (if (= A "-A") (dolist (M MEMBERS) (compile-file M)))))
42
43 (define (compile BINARY MEMBERS)
44   (unless (starts-with BINARY "/")
45     (setf BINARY (format "%s/%s" (real-path) BINARY)))
46   (write-file BINARY (0 archive:incore core)) ; includes the marker
47   (exec (format "chmod a+x %s" BINARY))
48   (let ((A nil) (C nil))
49     (dolist (M MEMBERS)
50       ;;(write-line 1 (string "[" M "]" (archives)))
51       (case M
52         ("-a" (setf A "-a"))
53         ("-A" (setf A "-A"))
54         ("-C" (setf C "-C"))
55         (true (if A (compile-ar A M)
56                 C (unless (change-dir M)
57                     (write-line 2 (string "** directory is " (real-path)))
58                     (write-line 2 (string "Cannot change to " M))
59                     (exit 1))
60                 (compile-file M))
61               (setf A nil)
62               (setf C nil)
63               )))
64     ))
65
66 (define (decompile BINARY DIR)
67   (let ((D (read-file BINARY)))
68     (when D
69       (let ((P (find (dup "x" 40) D)))
70         (when P
71           (inc P 41)
72           (while (regex "([^\n]+)\n([^\n]+)\n" D 0 P)
73             (let ((N $1) (S (int $2)) (L (length $0)))
74               (inc P L)
75               (if DIR (write-file (string DIR "/" N) (P S D)) (println N))
76               (inc P S))))))))
77
78 ;; clear the compiler archive index, to be used for source archives
79 (dolist (M (map first (archives))) (archives M nil))
80
81 (when (or (!= 1 (length (clean null? OPTIONS)))
82           (!= 2 (length ((clean null? OPTIONS) 0))))
83   (write-line 2 "Please use one of -w -u or -t")
84   (exit 1))
85
86 (cond
87  ((OPTIONS 0) (compile (OPTIONS 0 1 0) ARGS))
88  ((OPTIONS 1) (decompile (OPTIONS 1 1 0) (OPTIONS 1 1 1)))
89  ((OPTIONS 2) (decompile (OPTIONS 2 1 0) nil)))
90
91 (exit 0)