scsh-install-lib-1.3.0/0000755000076500000240000000000010301650404015217 5ustar michelschinzstaffscsh-install-lib-1.3.0/bin/0000755000076500000240000000000010301650404015767 5ustar michelschinzstaffscsh-install-lib-1.3.0/bin/scsh-test-pkg0000755000076500000240000003370610145664134020435 0ustar michelschinzstaff#!/bin/sh exec scsh -o let-opt -o sort -o srfi-26 -o thread-fluids -e main -s "$0" "$@" !# ;; Test a scsh package (either stand-alone or composed of two ;; archives) by checking that is conforms to the rules given in the ;; proposal. ;; $Id: scsh-test-pkg,v 1.1 2004/11/14 14:14:52 michel-schinz Exp $ ; TODO have a way to give a log file (define valid-extensions '(".tar" ".tar.gz" ".tar.bz2")) ;;; Utilities ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (define (string->version str) (map string->number ((infix-splitter ".") str))) (define (version->string v) (string-join (map number->string v) ".")) (define (permissions->string perms) (let ((decode (lambda (mask str) (if (zero? (bitwise-and perms mask)) "-" str)))) (string-append (decode #o400 "r") (decode #o200 "w") (decode #o100 "x") (decode #o040 "r") (decode #o020 "w") (decode #o010 "x") (decode #o004 "r") (decode #o002 "w") (decode #o001 "x")))) (define (paths->file-name . paths) (path-list->file-name paths)) (define (delete-directory-and-contents dir) (run (rm -rf ,(directory-as-file-name dir)))) (define (create-temp-directory) (temp-file-iterate (lambda (dir) (create-directory dir) dir) "/var/tmp/tmp.~a")) (define (call-with-temp-directory proc) (let ((temp-dir (create-temp-directory))) (proc temp-dir) (delete-directory-and-contents temp-dir))) (define (with-temp-directory* thunk) (call-with-temp-directory (lambda (dir) (with-cwd dir (thunk))))) (define-syntax with-temp-directory (syntax-rules () ((with-temp-directory body ...) (with-temp-directory* (lambda () body ...))))) (define-syntax let-temp-directories (syntax-rules () ((let-temp-directories () body ...) (begin body ...)) ((let-temp-directories (i1 i2 ...) body ...) (call-with-temp-directory (lambda (i1) (let-temp-directories (i2 ...) body ...)))))) (define-syntax when (syntax-rules () ((when cond body1 ...) (if cond (begin body1 ...))))) (define-syntax unless (syntax-rules () ((unless cond body1 ...) (if (not cond) (begin body1 ...))))) (define (dir-for-each f dir) (for-each (lambda (thing) (f thing) (if (file-directory? thing #f) (dir-for-each f (absolute-file-name thing dir)))) (directory-files dir))) (define (directory-contents dir) (with-cwd dir (append-map (lambda (path) (if (file-directory? path #f) (cons path (map (cut absolute-file-name <> path) (directory-contents path))) (list path))) (directory-files)))) (define (take-max lst len ellipsis) (if (zero? len) (if (null? lst) lst (list ellipsis)) (cons (car lst) (take-max (cdr lst) (- len 1) ellipsis)))) ;; Package name parsing (define pkg-name-rx (rx (w/nocase alphabetic (* (| "-" alphanumeric))))) (define pkg-version-rx (rx (+ digit) (* "." (+ digit)))) (define pkg-full-name-rx (rx (submatch ,pkg-name-rx) "-" (submatch ,pkg-version-rx))) (define (parse-pkg-full-name full-name) (let-match (regexp-search pkg-full-name-rx full-name) (#f pkg-name pkg-vers) (list pkg-name pkg-vers))) ;; Interface with TAR (define (tar-decompress-option archive) (let ((archive-ext (string-downcase (file-name-extension archive)))) (cond ((string=? archive-ext ".gz") '(--gzip)) ((string=? archive-ext ".bz2") '(--bzip2)) (else '())))) (define (tar-unpack! archive) (run (tar --extract ,@(tar-decompress-option archive) --file ,archive))) (define (tar-file-list archive) (run/strings (tar --list ,@(tar-decompress-option archive) --file ,archive))) ;; Directory comparison (define (sorted-directory-files dir) (sort-list (map (cut absolute-file-name <> dir) (directory-files dir)) string /dev/null)))) (mismatch-handler f1 f2 'contents))) (define (compare-directories dir1 dir2 mismatch-handler) (for-each (lambda (f1 f2) (unless (string=? (file-name-nondirectory f1) (file-name-nondirectory f2)) (mismatch-handler f1 f2 'name)) (let ((i1 (file-info f1 #f)) (i2 (file-info f2 #f))) (compare-file-kind f1 i1 f2 i2 mismatch-handler) (cond ((file-info-regular? i1) (compare-file-mode f1 i1 f2 i2 mismatch-handler) (compare-file-contents f1 i1 f2 i2 mismatch-handler)) ((file-info-directory? i1) (compare-file-mode f1 i1 f2 i2 mismatch-handler) (compare-directories f1 f2 mismatch-handler)) ((file-info-symlink? i1) ) (else (mismatch-handler f1 f2 'unknown))))) (sorted-directory-files dir1) (sorted-directory-files dir2))) (define (get-characteristic file characteristic) (case characteristic ((name) (string-append "name = " file)) ((mode) (string-append "mode = " (permissions->string (file-mode file)))) ((type) (string-append "type = " (file-type file))) ((contents) "contents") (else "unknown characteristic"))) ;;; Logging ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (define (display* . args) (for-each (cut display <> (current-output-port)) args)) (define (log . args) (apply display* args) (newline)) (define log-info log) (define error-count 0) (define (log-error . args) (apply log "Error: " args) (set! error-count (+ 1 error-count))) (define (log-check . args) (apply log "Checking " args)) ;;; Tests ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (define (pkg-full-name name version) (string-append name "-" (version->string version))) (define test-layout '(lambda (pkg) (let ((pkg-full-name (package-full-name pkg))) `((base . ,pkg-full-name) (misc-shared . ,pkg-full-name) (scheme . ,(paths->file-name pkg-full-name "scheme")) (lib . ,(paths->file-name pkg-full-name "lib")) (doc . ,(paths->file-name pkg-full-name "doc")) (active . "."))))) (define (base-location pkg-dir) pkg-dir) (define (doc-location pkg-dir) (absolute-file-name "doc" pkg-dir)) (define (layout->string layout) (call-with-string-output-port (lambda (port) (write layout port)))) (define (valid-archive-names base-name) (map (cut string-append base-name <>) valid-extensions)) (define (check-archive-name base-name archive-name) (let ((valid-names (valid-archive-names base-name))) (unless (member archive-name valid-names) (log-error "invalid archive name "archive-name"\n" " should be one of: "(string-join valid-names ", "))))) (define (check-archive-contents name version archive) (let ((top-dir-name (pkg-full-name name version)) (archive-files (map simplify-file-name (tar-file-list archive)))) (for-each (lambda (req-file) (unless (member req-file archive-files) (log-error "required file "req-file" not found " "in archive"))) (map (cut absolute-file-name <> top-dir-name) '("pkg-def.scm" "README" "COPYING"))) (for-each (lambda (name) (let ((dir-name (first (split-file-name name)))) (unless (string=? dir-name top-dir-name) (log-error "archive file "name" not in correct directory" "\n(should be: "top-dir-name")")))) archive-files))) (define (check-dir-file dir sub-dir file) (let ((abs-sub-dir (absolute-file-name sub-dir dir))) (when (and (file-exists? abs-sub-dir) (file-not-exists? (absolute-file-name file abs-sub-dir))) (log-error "directory "abs-sub-dir" exists, but it doesn't contain\n" "required file "file)))) ;; Check that the installed files have the appropriate names. (define (check-installation-names pkg-name pkg-root) (check-dir-file (base-location pkg-root) "." "load.scm") (let ((doc (doc-location pkg-root))) (check-dir-file doc "html" "index.html") (check-dir-file doc "pdf" (string-append pkg-name ".pdf")) (check-dir-file doc "ps" (string-append pkg-name ".ps")))) (define (for-all-contents f dir) (for-each (lambda (thing) (f thing) (if (file-directory? thing) (for-all-contents f thing))) (map (cut absolute-file-name <> dir) (directory-files dir)))) (define (check-installation-protections pkg-root) (for-all-contents (lambda (file) (let* ((info (file-info file)) (fnd-perms (file-info:mode info)) (req-perms (cond ((file-info-regular? info) #o444) ((file-info-directory? info) #o555) (else 0)))) (unless (= req-perms (bitwise-and req-perms fnd-perms)) (log-error "insufficient permissions for file "file"\n" " required: "(permissions->string req-perms)"\n" " found: "(permissions->string fnd-perms))))) pkg-root)) (define (check-installation main-pkg-full-name prefix-dir) (with-cwd prefix-dir (let ((all-dirs (filter (cut file-directory? <> #f) (directory-files)))) (unless (member main-pkg-full-name all-dirs) (log-error "expected at least one directory called " main-pkg-full-name" to be installed\n" " only found: "(string-join all-dirs ", "))) (for-each (lambda (pkg-dir) (let ((abs-pkg-dir (absolute-file-name pkg-dir)) (pkg-name (first (parse-pkg-full-name pkg-dir)))) (check-installation-names pkg-name abs-pkg-dir) (check-installation-protections abs-pkg-dir))) all-dirs)))) (define (install-pkg installer pkg-full-name archives prefix options) (with-temp-directory (for-each tar-unpack! archives) (with-cwd pkg-full-name (unless (zero? (run (,installer --no-user-defaults --layout ,(layout->string test-layout) --prefix ,prefix ,@options) (> /dev/null))) (log-error "unsuccessful installation"))))) (define (log-dest-dir-mismatch file-normal file-dest-dir characteristic) (log-error "difference between file installed with and without --dest-dir\n" " file: ~a\n" " without --dest-dir: ~a\n" " with --dest-dir: ~a\n" file-normal (get-characteristic file-normal characteristic) (get-characteristic file-dest-dir characteristic))) (define (test-pkg name version main-archive pkg-archive) (let ((full-name (pkg-full-name name version)) (all-archives (delete #f (list main-archive pkg-archive))) (sip (exec-path-search "scsh-install-pkg" (thread-fluid exec-path-list)))) (unless (zero? (run (,sip --version) (> /dev/null))) (error "need at least install-lib 1.2.0")) (log-info "Using scsh-install-pkg executable: "sip"\n" " ("(string-trim-right (run/string (,sip --version)))")") (log-check "archive name") (check-archive-name full-name (file-name-nondirectory main-archive)) (if pkg-archive (check-archive-name (string-append "pkg_" full-name) (file-name-nondirectory pkg-archive))) (log-check "archive contents") (for-each (cut check-archive-contents name version <>) all-archives) (let-temp-directories (ref-dir tst-dir) (log-check "basic installation") (install-pkg sip full-name all-archives ref-dir '()) (check-installation full-name ref-dir) (log-check "installation with --dest-dir") (install-pkg sip full-name all-archives ref-dir `(--dest-dir ,tst-dir)) (compare-directories ref-dir tst-dir log-dest-dir-mismatch)) (log-check "installation with --dry-run") (let-temp-directories (empty-dir) (install-pkg sip full-name all-archives empty-dir `(--dry-run)) (let ((contents (directory-contents empty-dir))) (unless (null? contents) (log-error "no files should have been installed, but the " "following were:\n " (string-join (take-max contents 3 "...") ", "))))))) ; (log-check "installation with --non-shared-only") ; (do-test check-non-shared-installation main-archive pkg-archive)) (define (display-usage-then-exit prog) (format #t "Usage: ~a []\n" prog) (exit 1)) (define (main cmd-line) (let ((prog (car cmd-line)) (args (cdr cmd-line))) (if (<= 3 (length args) 4) (test-pkg (first args) (string->version (second args)) (absolute-file-name (third args)) (and (> (length args) 3) (absolute-file-name (fourth args)))) (display-usage-then-exit (file-name-nondirectory prog))) (if (zero? error-count) (display "Test passed.\n") (begin (display* "Test failed " "("error-count" error"(if (= 1 error-count) "" "s")")\n") (exit 1))))) ;;; Local Variables: ;;; mode:scheme ;;; End: scsh-install-lib-1.3.0/COPYING0000644000076500000240000000271010031613322016250 0ustar michelschinzstaffCopyright (c) 2004, Michel Schinz All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. scsh-install-lib-1.3.0/doc/0000755000076500000240000000000010301650404015764 5ustar michelschinzstaffscsh-install-lib-1.3.0/doc/install-lib.pdf0000644000076500000240000041067610301650347020715 0ustar michelschinzstaff%PDF-1.4 5 0 obj << /S /GoTo /D (section.1) >> endobj 8 0 obj (Introduction) endobj 9 0 obj << /S /GoTo /D (subsection.1.1) >> endobj 12 0 obj (Package identification and naming) endobj 13 0 obj << /S /GoTo /D (section.2) >> endobj 16 0 obj (Distributing packages) endobj 17 0 obj << /S /GoTo /D (subsection.2.1) >> endobj 20 0 obj (Stand-alone packages) endobj 21 0 obj << /S /GoTo /D (subsection.2.2) >> endobj 24 0 obj (Split packages) endobj 25 0 obj << /S /GoTo /D (section.3) >> endobj 28 0 obj (Downloading and installing packages) endobj 29 0 obj << /S /GoTo /D (subsection.3.1) >> endobj 32 0 obj (Layouts) endobj 33 0 obj << /S /GoTo /D (subsubsection.3.1.1) >> endobj 36 0 obj (Predefined layouts) endobj 37 0 obj << /S /GoTo /D (subsection.3.2) >> endobj 40 0 obj (Installation procedure) endobj 41 0 obj << /S /GoTo /D (subsubsection.3.2.1) >> endobj 44 0 obj (User preferences) endobj 45 0 obj << /S /GoTo /D (section.4) >> endobj 48 0 obj (Using packages) endobj 49 0 obj << /S /GoTo /D (section.5) >> endobj 52 0 obj (Authoring packages) endobj 53 0 obj << /S /GoTo /D (subsection.5.1) >> endobj 56 0 obj (Installation library) endobj 57 0 obj << /S /GoTo /D (subsubsection.5.1.1) >> endobj 60 0 obj (Package definition) endobj 61 0 obj << /S /GoTo /D (subsubsection.5.1.2) >> endobj 64 0 obj (Content installation) endobj 65 0 obj << /S /GoTo /D (subsubsection.5.1.3) >> endobj 68 0 obj (Queries) endobj 69 0 obj << /S /GoTo /D (subsubsection.5.1.4) >> endobj 72 0 obj (Load script generation) endobj 73 0 obj << /S /GoTo /D (subsubsection.5.1.5) >> endobj 76 0 obj (Miscellaneous) endobj 77 0 obj << /S /GoTo /D (subsection.5.2) >> endobj 80 0 obj (Packages containing C code \(for shared libraries\)) endobj 81 0 obj << /S /GoTo /D (section.6) >> endobj 84 0 obj (Packaging packages) endobj 85 0 obj << /S /GoTo /D (section.7) >> endobj 88 0 obj (Acknowledgments) endobj 89 0 obj << /S /GoTo /D [90 0 R /Fit ] >> endobj 92 0 obj << /Length 1620 /Filter /FlateDecode >> stream xڍXK6WV-bE=($h(t(-6YT؍; %yW$rH |3?$|GLd?(Xcgbޅq]Njtf JP g$/򤆻9EYrեiAyT=fZsGEo@_Hb%; EΫ#, BȬ?$҈l ,q.OavB  Dt6GꊣJ)XSӓ& MT!rv1{AAЩnH":xpGBǃt" H;sЇ pف , - qI-X{Ҡ8JZE|R [uN`Ժ;y9lnT0k)n8zbu @(8zX24p 3SK.-x) F\Y8X^k$й#e%+̥3-lpq>k3Pg*r,Tڭs;rOΩ1h X!pqa}$#&s ]zR97'%mq|wO4!=>W M ar u+/k愙]wp/ݭYAEǍӔzpc틾(/4)wrjGgYKE\pɂ4MuN \clqdhG3{+GeoQFԟmY!,nD~3ǩiVee'!C7 N_RӡT~! gȡ:%,7܅Qxw%{9/[fI4nr?l"^e~C "JV@*ʛ_oendstream endobj 90 0 obj << /Type /Page /Contents 92 0 R /Resources 91 0 R /MediaBox [0 0 595.276 841.89] /Parent 109 0 R >> endobj 93 0 obj << /D [90 0 R /XYZ 72 757.935 null] >> endobj 94 0 obj << /D [90 0 R /XYZ 72 733.028 null] >> endobj 6 0 obj << /D [90 0 R /XYZ 72 564.859 null] >> endobj 10 0 obj << /D [90 0 R /XYZ 72 425.953 null] >> endobj 91 0 obj << /Font << /F31 97 0 R /F33 100 0 R /F35 103 0 R /F37 105 0 R /F30 108 0 R >> /ProcSet [ /PDF /Text ] >> endobj 112 0 obj << /Length 1792 /Filter /FlateDecode >> stream xڝ˲6tܙX.m6iitl3{sͽIɏϾYzu[*]R0ݿA0ޭɩn&'\ێXw-u;\l?-sVklBzR"y8#v]ts1GbXNS Oev% unPr$%.V;e$@֋+9gR w4sճ9Aa'ݹ!UoHUc;x}IV"gRxjWhwye=} vOFFΆ 3 M\,MJt8i>6@dv.sTա@NnEFq6i ^<8PUx뺵n|8;94 '%.=8Fr!WF8'j&(*=.O,Yk`s4!qyiN CHMӹ.j8.ntX#6њ8SCx-GFZNR$)J S]iSvwnómm_`/zӗ}|qg!gJ"BLP<1$ѹt1_SP)_{'!236!3R*$t{˙LKCbRJڝDg4FQ[Uw b%diU#}B>J̄, X2"Al\B)燂 hfq\<?l@KHq^*-tf̚ iDAVdap xm +=ˣP~@fKoP[㨬uL7sbOE>&{^:%83s' ߆ci^o5Tlr8 ;~`)EGqSa \^k?y "Pz5(:7W?&6 ɃX1B3<`N(JmD0 7C٫gendstream endobj 111 0 obj << /Type /Page /Contents 112 0 R /Resources 110 0 R /MediaBox [0 0 595.276 841.89] /Parent 109 0 R /Annots [ 116 0 R ] >> endobj 116 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [108.571 275.439 116.541 288.711] /Subtype /Link /A << /S /GoTo /D (section.5) >> >> endobj 113 0 obj << /D [111 0 R /XYZ 72 757.935 null] >> endobj 14 0 obj << /D [111 0 R /XYZ 72 660.549 null] >> endobj 18 0 obj << /D [111 0 R /XYZ 72 535.493 null] >> endobj 22 0 obj << /D [111 0 R /XYZ 72 209.549 null] >> endobj 110 0 obj << /Font << /F30 108 0 R /F31 97 0 R /F35 103 0 R /F33 100 0 R /F37 105 0 R /F47 115 0 R >> /ProcSet [ /PDF /Text ] >> endobj 119 0 obj << /Length 1979 /Filter /FlateDecode >> stream xڭXK6W620bfwsrYo %v[hbS*ʒN`n,zG~{>R{Dǧ}O FT02i{>,w4= kA,4ퟘĄrD ˷R*Tu;4oc`d{z=CH<_}0&q ]uubx/c'%ҜHnXז>^L㩿4ռz/5i*;K:: ˰8{C `1O}"^j-tlWXdRª<碄A6qc!;"TL'G[*MC]\0FZH9-e`:.\eyre1њe.6O]ಛY v:շg;DN<&#/Lwu?(2> Qw G$]L Iy.&6c8HT*mg+h &v}+t̅U RuKX9fUla8˸-k/zؒ#1OhERڬʣ8~[*#`Nch8ƛ@EO:'a箟N.JNHB&c#,^/v€A.^aaVOꦢbT2 `P;R7vÂie+&A&TIeaL MQZ#\q,Tդ[9gBg7oy73}:jAu5\07+7t]RQ` `rqY3t@xL6W:CSp(ʗ=h~d~a8A r 4V39whĢW 4=^B+ QBk夊p/t "h4󇥊71[TDFII?w-I'e~&˳h`F]6.DV.7 1P8qlhRF&XgJrdta22uq`854Ƕdh>fnv܂ |} mC0(lYݭF¤ [FQ1q#NY^Z>"pİ.a܈4s*{Ey\|؊ZO<ȗe;.Ỵ7$6a\@M)=qapgT3uڏ/Nl$jEvq$Z6jueGe\qXF&#l ȅK9$o_h#E9rKmFkk{|%C\Jp:[V% F~#|읗@zNBAJ 'DsA;&vxPb؄"ru}4Y1?m endstream endobj 118 0 obj << /Type /Page /Contents 119 0 R /Resources 117 0 R /MediaBox [0 0 595.276 841.89] /Parent 109 0 R >> endobj 120 0 obj << /D [118 0 R /XYZ 72 757.935 null] >> endobj 121 0 obj << /D [118 0 R /XYZ 72 686.784 null] >> endobj 122 0 obj << /D [118 0 R /XYZ 72 485.51 null] >> endobj 26 0 obj << /D [118 0 R /XYZ 72 395.475 null] >> endobj 30 0 obj << /D [118 0 R /XYZ 72 313.868 null] >> endobj 117 0 obj << /Font << /F31 97 0 R /F30 108 0 R /F37 105 0 R /F33 100 0 R /F35 103 0 R /F47 115 0 R >> /ProcSet [ /PDF /Text ] >> endobj 125 0 obj << /Length 2330 /Filter /FlateDecode >> stream xڽY i>%2 !MMpiR$Ar-y}ᐲd=p8뻛[O`ΘjK'nY|=:murջzQeIM-mHbδvV4ծڮXZ|7cٮiԉ*63o2e2fZgA]{rf]?ӲyL4[ozZ-qlY墭qnQa}*"j k6L+meCTΰ<7kVQ Zb2z }y?r̙M甆]lw~[wӟ8p+Ԩp̯u@}/}zz *07b55֓4 #~\u$%5.<{98 }d-L>`|ƿ&z 6bhp!t~CErRT;VcjyGitS'֝ ΒpC0 ҢQ&`n =T<eUW]<\ Ϣ[ȿ#RmP`dlaǀ|cmM"xriiC ~ѩH!0H 馟#_~19>ۺT#hehfO27Ȟ M QKZl}#Y,!ur3 jI㢥oz(t46ڃ"U.-ni2fbv,SNqm J@mh]]v/J1 QCF pz)|l`?o^t`>qʸLlMʔY&fDgviƸ LF $MRT9sy2d/b㿂1e*J1!l143S9ZN9v!|9B9AnQE)rPL q3VHsl la}ݴrS$;˸F )5P#rB L&Ԉ`С7]DFċS5Zq h4j?51㰁x3PT#q}s+cBbV l3,a;oe5DjX *>4D,ڂFe24u﫚(.p!iWSډ{Lug1, l;x.&/XLx©MKTH H׵hաDsL&98lBթfz:=ENFʇk@TmKcqlG!Yď{tfG1<]H&ʼn(w7Pw:v,~ 2˜-23~UIq(+v'E'@YeL9b2:RáϡGe88R?=PIw }f)>!c:-bٰ)jY ߳Vš roNZfNtĞ*x1L$|2äV=͢YB0=)2 :TUW2qi:5/?q,<2At,ZYݙ^"(<^.7eI C#0y樐yR6T_[Y$oQH^p(^SBY˧K㉜9(3C#*$)x^N}pP/.|{w⁑Ýrm'Sb͏?O [d'7Y<ޓE8EϿOe\1>H5/V|mlA3rK#J8desBЏKtO5?}. .kP =@u(X)r*sT_4~31}bʛckT]R^PEtMEz:n s9]pθr/'c ɸpA>*\ҳo0Gά{sFF ~_[!IP_&yaʌP5.yzҍ^8LR)ҙK-㉊&QS{qzO0ITZ $mPz2gnarE& %endstream endobj 124 0 obj << /Type /Page /Contents 125 0 R /Resources 123 0 R /MediaBox [0 0 595.276 841.89] /Parent 109 0 R /Annots [ 127 0 R 128 0 R ] >> endobj 127 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [372.904 305.248 389.841 319.321] /Subtype /Link /A << /S /GoTo /D (subsection.3.2) >> >> endobj 128 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [236.969 220.068 262.872 234.141] /Subtype /Link /A << /S /GoTo /D (section*.1) >> >> endobj 126 0 obj << /D [124 0 R /XYZ 72 757.935 null] >> endobj 123 0 obj << /Font << /F47 115 0 R /F31 97 0 R /F37 105 0 R /F35 103 0 R /F33 100 0 R /F30 108 0 R /F1 131 0 R /F40 134 0 R >> /ProcSet [ /PDF /Text ] >> endobj 138 0 obj << /Length 2514 /Filter /FlateDecode >> stream xڵZo_%@0av=܋ӷmP1cgӞ%i[]@dJH(Jd'BDnIGjqc`blɹ,j-5_:߀ድ,֡cV?Je^6) U`٤u~l7YC䧼ѸqTpW"^e^/1dcFmÙ-*"lC`}L@ %x[lzDĴNθ %CXXmUVU zi7W>UjmծJjͣi4b\[a#ҦiI HOug.KL Me]U`;HnѤ_Cj$޸wUnnGP#q,\\3f ?ց8a̒8qDCeA:/[@q >\7TQ7cR! CV9!ǟ\=@3νM8 G !E, >4 L"yBhŤ8~}c X2pXK<`/< ӑ }rEr/ZKByy@M70ڮUD¯dx}6x_n߿OYuh̼_s:u+@ {:K/aGKDrV +B0/wh\/MFc߇1+/ :ҚM}r`ӂ312=}_|n8xmN5 uྋ/7혭!Zn V(X A,An?]\< j)LRU at/g6-#t?s' uf^QRpV͢ "kz.9KMx@k&Ulm1MvOJn3 {fޣ!\t Bg6QJ_èg7FSy]GјCBCýPW!SpYciѳ)<޴cn\9 f E^Uz^s5%k QCj>) )^AJF<*Tk$H {;R#*tH͡!^ڝA<9Mn b=9#6]W9$?''ÚAFsVIlQ%*rYJ.QRZ-=)))55“6ȿ݌cVCrզRH5M2ͨ^^-6e Q^rׇ]^,Vk.j{*KFsh!uBdt006(Nxzf3`7%Y@UP6֊P49QPfjJhfE94FrGPB$ᵊ4Sbu 5!F9tظbaĎk ZhԦPŢ]B l>2,&  ?"O7':.?gܔ5S^~ϛؽ#F5l^ ofhmkQqoGt/-*!VX_C?8+noh qlJ ge%zSuz`wũ0T*iojW!ɡ͠t|Ͷ#Op 227T/!lD*US޽* *z]M>*g!'dmm!?q2 y! c/q$endstream endobj 137 0 obj << /Type /Page /Contents 138 0 R /Resources 136 0 R /MediaBox [0 0 595.276 841.89] /Parent 109 0 R /Annots [ 141 0 R 142 0 R 143 0 R ] >> endobj 141 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[0 1 1] /Rect [151.426 297.623 333.748 311.696] /Subtype/Link/A<> >> endobj 142 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[0 1 1] /Rect [381.538 153.318 421.536 167.391] /Subtype/Link/A<> >> endobj 143 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[0 1 1] /Rect [434.629 153.318 460.352 167.391] /Subtype/Link/A<> >> endobj 139 0 obj << /D [137 0 R /XYZ 72 757.935 null] >> endobj 34 0 obj << /D [137 0 R /XYZ 72 733.028 null] >> endobj 135 0 obj << /D [137 0 R /XYZ 72 590.553 null] >> endobj 140 0 obj << /D [137 0 R /XYZ 72 327.511 null] >> endobj 136 0 obj << /Font << /F33 100 0 R /F31 97 0 R /F37 105 0 R /F35 103 0 R /F47 115 0 R >> /ProcSet [ /PDF /Text ] >> endobj 146 0 obj << /Length 1894 /Filter /FlateDecode >> stream xڥXKo6 z"!i@{i뱧d}I=@^EQ?w?JD蛻M2o?XDPI):;m[M(y+SOu3Q7J"MQ HvZ~-O影v a`# Rkjlݓ8lXeZRV$z *D!th+㱩l[y.zb.DpBLf7!/IW^Q6.;T p}qH+6&&}`XnƣHQgy +A8m?]$ #`Ӝ-lK?j),ᓐXෳyn NyO~?k9=KܛuߙM>v%S=He.Itg3d]HN bDgX;||]/8zӡowuʑÊmh:|3u}c9:򦍿l@:(t񱅏5g ʫ= xƎ_iXJQ_G>S `v17Te)b#:j6݆E3`ʼ;m DXH*Z T"*ss>2]ާvCU1/ PC<\j:A skhKHDYֿ4Lqf0`}*XIP v\ M#j`\&e7RT]E#=<={Hp!F~|qnh0D.rn" REC׼$%}E~]RF^yY&i(K*J<ʗ>5X)^Vy[DDvQ~.Ԑo >Qvqm[W}Hߗ}*5~u8گuPYb-n';ܶ=[oѸS_ORYJ 8[\FzUi[X .>h-i& MZ$~sD?Vkb=/ȟg<Yvy2)KzoATm7oZ{q*. %,*ffki.g"҂L$,!"Ș[S%6O23ͲƄ*tUW]lLVQ&402V#:7 '9 ew?K@iD76A&^AG)^2wq ř4<6y_n=ѹLyNƑw?ܽERendstream endobj 145 0 obj << /Type /Page /Contents 146 0 R /Resources 144 0 R /MediaBox [0 0 595.276 841.89] /Parent 109 0 R /Annots [ 148 0 R 149 0 R 150 0 R ] >> endobj 148 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [404.826 641.637 430.729 656.672] /Subtype /Link /A << /S /GoTo /D (subsubsection.3.1.1) >> >> endobj 149 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [426.925 526.07 452.828 541.106] /Subtype /Link /A << /S /GoTo /D (subsubsection.3.2.1) >> >> endobj 150 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [427.73 505.115 435.701 519.188] /Subtype /Link /A << /S /GoTo /D (section.6) >> >> endobj 147 0 obj << /D [145 0 R /XYZ 72 757.935 null] >> endobj 38 0 obj << /D [145 0 R /XYZ 72 733.028 null] >> endobj 42 0 obj << /D [145 0 R /XYZ 72 488.28 null] >> endobj 46 0 obj << /D [145 0 R /XYZ 72 192.308 null] >> endobj 144 0 obj << /Font << /F33 100 0 R /F31 97 0 R /F37 105 0 R /F30 108 0 R /F35 103 0 R >> /ProcSet [ /PDF /Text ] >> endobj 153 0 obj << /Length 2593 /Filter /FlateDecode >> stream xڭYo6_aK`M"u{=Ew[1$'f8CYrM.`jDoOWۿkRJ֮n,QBfzu[.u{Il]pzH#fi}웧\}3k\?rw5l$s_@\O]= mWTk L_Ҍw^]Cc*ްnVfv4`ҁT2lz *]9" QVc,KbT̗ni#f51Y.Ft}K4WՓg#I0RS} FWO>)lapdkz6SakYDd ]۠OCtb֮;k%p"oAeqpǂw]U>_økp.3?^"Sѕ`c2t\ռfBV[ :%oM(kXBۙbnoJրq.Զ3 ֊s<ғԾni}nXϐR(ˆ2, SI[a`@$9(`k=U R [;>֋ZTF=DuutUHSI\dG;@NAYZ&x׿ZIH#eLR^ )D?4"1ZkҞZ:0"X(v`_4^հme{-bȔtTZ0z h|m0#U`$e#'6'8l23:}E,VZ I*,u~ޘd-E= Y< >RջQBc+ 2wc^䀀u+ M,Sa7lG);1O_0.,bM:ƙf(റDSBS2KaFϭ?.ľBᫎGy>iS`f&7hlN}B!Xd'>> \ƄOf O>aM"Kއ@hfYb_xq )I )/A*z܎DW9%~C'3{s Inl6|<%<-tVFr3SE܌T[xe2\+ ,pȚTJxd] *i/{!~, E\& eY.bvņPCd:+MZkm&-] MjЂ]aob273nRo?A>?,u $; KOU?+ẖq <-2y 1\iZ'&p%+B2 \#\XU) #*4= d_H6Ñ#v)Qke.gm;׽ʨy*P9P} )KYu(Vd?w;Uc2_Y9VdhL`KX 4|*}&/sXo-'갘}6ū#~m [ 1 #~w$nlmVdpE 1 JaT pю :qm50c% ț4,n->q|23F]5 &IkBF>R2&zf*8Pl˙1;Cp%fPioتS <9 ;W.hR9aL aH&Z'G_.uf|}YMEgLo&u.Q]M;aMJߺȀ䓞b?/6FȤ?I܀[T%ڝ-ltMfxe죫XU)׳(^rHNwḼ/ | u4 <<3vfXendstream endobj 152 0 obj << /Type /Page /Contents 153 0 R /Resources 151 0 R /MediaBox [0 0 595.276 841.89] /Parent 157 0 R /Annots [ 155 0 R 156 0 R ] >> endobj 155 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [415.963 488.871 441.866 502.944] /Subtype /Link /A << /S /GoTo /D (section*.2) >> >> endobj 156 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [350.907 416.642 376.81 430.715] /Subtype /Link /A << /S /GoTo /D (section*.1) >> >> endobj 154 0 obj << /D [152 0 R /XYZ 72 757.935 null] >> endobj 50 0 obj << /D [152 0 R /XYZ 72 249.326 null] >> endobj 151 0 obj << /Font << /F31 97 0 R /F37 105 0 R /F35 103 0 R /F33 100 0 R >> /ProcSet [ /PDF /Text ] >> endobj 160 0 obj << /Length 2488 /Filter /FlateDecode >> stream xڥˎ>_G b(*@.8H\>3vK=bjz $z?/4j(|t9+ ,sc2T?:?|#-epu}T.y};(stbvά02pm^Ta9V SD2] ;DݥFZa KƑ eh 5"LAç?JI6KTtxT%pĥsiqCJ_>=@['R^袺g +tQR"v\ڣ}JK+g# /ݕIv궧U1:޿kpAt.傽gt~P{$Sœ SxQ/m{vM_GEL)ĉk!SLXn_[sV1xn;theIzx-VcOqq>SEC$РFΘp4:cT Cwh%9Ua QTM2 sOKpJ-.HtBքFbl*b!TBq$1J]/C]Jֱh9P:7:0ȡ!b.))ea{ku}h\ ˋHc)ȥ'5@n>Q:-m+mf*12z.@qFB- RX[2P7."3ل$7_fsiJpNSǔUK"sYn9wk[,NDM5qφB+89(C2f,R TaL8Q➋d=Sj5D3ff >c:47YcS8EetEW1i3R#8MzOXiYVBh\iPv+Lk(U@r*e{(neeUsuCUSl~|ɖvM~-Lw!1"(cv m:{^7%ugYCEd}i.8!-;~f;D"7 gbփ&g "-,U:pSnC(\/ zy5|Oo)(h[fBWթk@=+CsM3ضtu6@VrɇPw`L%.l4yHf>o4VVoWBmSJ%L:%8@ezx=ׯt8hN! R^LB/ZEv1^ͬb<]GG3U!y!5NG7rY)\BVs-"'><XGڨx%'f̺4 \-tkv,RՁzz8=|"%D\2kH+RPk# s[{T20yYSL%㷢WV6~`f~O4 ,.$]Cx[s9:t4 eI 4p?~=L'Xbv^} hD00I9B>7VηG$4 OLJN l!kӚ.cM Mр;}'q:-/n -w m%ݭRB1@[ߨ1GU (@i6:kWҔH ȃxc﩮dq"'iG ̆aÿРKᧇt"<˹y0B1^Қ8+}H; t^b ;E>VyV nzj.&`XḨ PM(AEq s"YyvUV 'ދ .8ky+!͎H1F lN b.ʟetuI4ҵ ,n;=ӧ o qNua)Tt-6/ƾ`c+`z TUL7D iˉnd݅;q /Ȕw8ӽ镂a7CQo\6bm)}t8]2X,</ ;_G˳w?s[X)endstream endobj 159 0 obj << /Type /Page /Contents 160 0 R /Resources 158 0 R /MediaBox [0 0 595.276 841.89] /Parent 157 0 R /Annots [ 165 0 R ] >> endobj 165 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [236.929 236.645 243.405 251.911] /Subtype /Link /A << /S /GoTo /D (Hfootnote.1) >> >> endobj 161 0 obj << /D [159 0 R /XYZ 72 757.935 null] >> endobj 162 0 obj << /D [159 0 R /XYZ 72 733.028 null] >> endobj 163 0 obj << /D [159 0 R /XYZ 72 713.233 null] >> endobj 164 0 obj << /D [159 0 R /XYZ 72 662.489 null] >> endobj 54 0 obj << /D [159 0 R /XYZ 72 519.572 null] >> endobj 58 0 obj << /D [159 0 R /XYZ 72 489.604 null] >> endobj 166 0 obj << /D [159 0 R /XYZ 89.933 150.214 null] >> endobj 158 0 obj << /Font << /F31 97 0 R /F37 105 0 R /F33 100 0 R /F35 103 0 R /F8 169 0 R /F11 172 0 R /F7 175 0 R /F30 108 0 R >> /ProcSet [ /PDF /Text ] >> endobj 178 0 obj << /Length 2049 /Filter /FlateDecode >> stream xڭYKo6ȭ !ҩ@آ)٦cbɵd;ЛlӓI⼾f(tӯ0Fj)o72•ќϢkw}U[EIJVP/*isTöoa;p„Ɏ2Ύiq/6<8>CNNU%T7U$TU#nZxiSrN4i*u7M{ڌ9U R30mw|vg5Nh_p|ϫouYdU SM-ͷ4֒(nAt##!<ӼgjeX7A93a\4siYy< 6)i!Zi]sF4Ǽ%(iilW) m')mS" &Vk;o;ڄ8=>@7D 鸁+!<\1KXDuoͥAtOQjc^5EJʱ N<5g [Dp F͋åนwm357f6X"0TZb-hrV;xrC\!| H73mrq̹=_ޓi=7)yEz! 4x+R*Mz-=;lAoxn u Cq?llx v3-pCWg|q:No޲dJ ֥>h>>Q"c <%#!g\o2f|p(D/ *#8_bE7\*"DtjPK `Ǡ| 댔"IMd V(Z%XqRY)*4WT ;9 īzQ'3, Ʒ0̮|eT !#Rl. >;i߅x;"!b!?GKQJ{Xm7M"f%~֖U$p`[IU6XC͸߹fq"e-`YWK{,xSRrg4αL`dty[3vh𞘼:{l??猤:s9IҖ%pFnJ0^p:<ZE'j ¦?p|cJ&vBD+@Q,Dąw5@*qfRzrIVBW<^[b5Z/g_rY$.b U=f7ZWmq{cߛ80_0 Jذޡjk"}vAMɕF 6n ( NM$1pog 6bYWRYZiJx#y2Uјch{x-"ͰП:CY0{UrN$ϩj S]0BcώܪiMtd8uM83Xcjh^dAu׿ixho5T*jR K^ e-->AsW.ʝ^ݤ J|Ygțfe rӧ&xcIn &]ICT)MF6 F*Zmp!_Kxkq9adl/?x-Px4g' IK͓< mǎ=tK',c1I$k]qh(隟| j"f~pe5_E]QP*)H%0.P)x =ɢZVݙMgUVЦVo"l;(aH#/,`ķ_QբՆˬ/}c `~xů+wt!~1ԪfPУ%1 _|ÿ=endstream endobj 177 0 obj << /Type /Page /Contents 178 0 R /Resources 176 0 R /MediaBox [0 0 595.276 841.89] /Parent 157 0 R >> endobj 179 0 obj << /D [177 0 R /XYZ 72 757.935 null] >> endobj 62 0 obj << /D [177 0 R /XYZ 72 439.188 null] >> endobj 176 0 obj << /Font << /F61 182 0 R /F31 97 0 R /F37 105 0 R /F35 103 0 R /F33 100 0 R >> /ProcSet [ /PDF /Text ] >> endobj 185 0 obj << /Length 1791 /Filter /FlateDecode >> stream xڽXK6W[D,D E"Ei4YmaeI:mc8~ҏ/!Hrݭr ?pV07o|FŐd-I表d[1)fP͠A>;HD(!b$uݖP} KWs LR3qIL"2kT,׶TI0;8g8EXUB1Jijs ; rIi;kw'^51d1)\4C7I3ɨ+ARO jDDf(+I qO *a"E+DŘd  b{(#e<5A2Dtu!(QcE)APN (2a 9$c}T}t7S$x 57`T)kc1r_'=WA1.6A8^ffnP;XǢ'A/!bx.BϮLl. BT.K `6 9]Xꕙ 﫰|`i:hsT, fw[Ü'[Z 6*_Xi !Z0ĂA nPVWh1,=Ts¶+ʻbt&ں@ 9Uٌz{X`e/ݹlP}fG 601ԨRi]#ּ yumM y]1bcOjS7~ۛ<_HM0k;k0xQEJrB#F<')'Hj{MX؎ʭ٢K‚+l`mRWMLiPJ3$Li\8ikL$ؕh!SE[_IOT{Wo9jG-[U!WUwئ * b Y_]Dt@ ŧ(5,ciN}P4Ű˞"ʦ> =ՠ)pN' $1dv6ݑaxL:h m/e&CPrL>qk͌O8E({yέ:J/ !(g dE%76b2wASqX M8 y Ǯ*LSgv|1^iͼƕp{ڥ`^m j./a9о0 ̧oT\`MWoi7j6VD a19VJ&2(^/А7gƸwo{/޾Qyendstream endobj 184 0 obj << /Type /Page /Contents 185 0 R /Resources 183 0 R /MediaBox [0 0 595.276 841.89] /Parent 157 0 R /Annots [ 187 0 R ] >> endobj 187 0 obj << /Type /Annot /Border[0 0 1]/H/I/C[1 0 0] /Rect [389.152 378.74 397.122 392.813] /Subtype /Link /A << /S /GoTo /D (section.6) >> >> endobj 186 0 obj << /D [184 0 R /XYZ 72 757.935 null] >> endobj 66 0 obj << /D [184 0 R /XYZ 72 632.231 null] >> endobj 70 0 obj << /D [184 0 R /XYZ 72 361.514 null] >> endobj 183 0 obj << /Font << /F31 97 0 R /F37 105 0 R /F35 103 0 R /F33 100 0 R >> /ProcSet [ /PDF /Text ] >> endobj 190 0 obj << /Length 1750 /Filter /FlateDecode >> stream xڥXK6W,@D-i-ڴh(4L%גCڒͣ{Ef曡yx#+H VhƮrmjle34릫7 e7\ѫI";S];v胼^+,r׿wd~ӵ ]kSIQ F * ^_sfvX3VYêS>޶wx`X\#+w2wv;@{ R ٲEUH؞ ( ζ9+fOS˄3 }B:Tn?z7nꚦ{WrƬ V>Y!<+乗 $ st)@荏u aD_W;~t}c.E񔳺 ,A\5` 'HhS5 `pC_ ^ӒٱBFhJ1(6[w[U >@@J 9@_6<RaxT-[} [z`6&?D=B##4=ʻK}vIr6MQ +(k Y!YȈp|R{T5Z5fi1hLN dEq"qxڞ-,Fc_ :F7xU(Z)b9BE=zMu{<EqJ8Qfzg:0,NYKc9?/ GKiJ42: !T:({_'e>TSQBI4>dRl͵m /xV`?>ԉB箻as5Ʒƶ GC(At?9SbD)D ҶplKc4#J0qĴSEd@Ra~}m`hMOg8'ѹA}p >[ڍ =bs_*݀~kj:ă lG8̍9rq>Z=B!9$9øm`7[}oVk?l ?,?ziI{ja53/y`3/e94,bn!4jR9U$XW *hUgc<,qLοn&~$as e>ۀU;s*I"ᢆ~@׻TvM4 Z+4*`ao~l0jCЍ6;h5mrB 8Vٸ;F h` m9t6E)?F0#=LTuNԓQcQIAUӦ+aS*޹yT1a ʁ#xz2ڑ^; @k2S~CySfTM&K 9&{'uD6cp; 'ʧ }O˃'W\{ uI̡C2cȇ<b@{?޶Hgq48эE91Qs6;Kƒ՗녝ˉ iͬ}3;z ]"w\>!~~BR(S~!9dIؘBYG(;45PiLB(5"66'<=xETVjd,k7!^.7pOn+thaK=vW<!vC}:jZ~+DHc<(0 ^>un&2V>Ai)UX>yrendstream endobj 189 0 obj << /Type /Page /Contents 190 0 R /Resources 188 0 R /MediaBox [0 0 595.276 841.89] /Parent 157 0 R >> endobj 191 0 obj << /D [189 0 R /XYZ 72 757.935 null] >> endobj 192 0 obj << /D [189 0 R /XYZ 72 633.019 null] >> endobj 193 0 obj << /D [189 0 R /XYZ 72 599.146 null] >> endobj 194 0 obj << /D [189 0 R /XYZ 72 552.358 null] >> endobj 195 0 obj << /D [189 0 R /XYZ 72 519.369 null] >> endobj 196 0 obj << /D [189 0 R /XYZ 72 484.612 null] >> endobj 74 0 obj << /D [189 0 R /XYZ 72 433.477 null] >> endobj 188 0 obj << /Font << /F37 105 0 R /F31 97 0 R /F33 100 0 R /F35 103 0 R >> /ProcSet [ /PDF /Text ] >> endobj 199 0 obj << /Length 2239 /Filter /FlateDecode >> stream xڕXK ϯ[UkHzmԤ*V-mȢGx}%=rA>ӻIi?< ?'E'R|܉$I_uY?q'UծlL1$jG==X3 D\)$;)R~ˮiVmvMiWR㮨ã(#C[ZhQi2tO:^;@.h]j[wz۷4Z@YFvzJ]VD&ԣ; S'{w6fz5~/W]/`7lHͷf NIYu]C@C U8"I0Ovx'sbٞ$ҟ&lt!Փ&&ux0iA>=OG7۹c=y%UI2d2Ѿ38d!X瑁bQ0,b) 2LE -fGQ~?܈~S"cy7*}،Ԙ\$RXR!~y1n=m)Imr/1h#FDQUqX>\G]>I jW R7SU!Qk{8lC"nZH-B; hGs=Kj b7A<6e"L#j6 aJMRlSYDA-8t |~77!|<:EOũHIM4' R ?jAIrK` }ʓˌP2>\/sT ||\: yoԟAx6lx7B JjjU(ݸ"j/Fz1^G)xH dWxJlKM{'>z#N*dm)q!7%VVr}咀W;uKҀ^j44hZ("2_+O.*Ӕ+T*v՛.Rzܠ|ѧ~QXn4(0/|~*oɃſgFONb޷X^H= eY`ebϟ܄߬X8c .([4nVr\.N6/<ؽᱨ͗Ĵ8<,)&jU3vZ1mb*VMf[4$ ҎM>s8JuˡA2s>Ğw??P$Nendstream endobj 198 0 obj << /Type /Page /Contents 199 0 R /Resources 197 0 R /MediaBox [0 0 595.276 841.89] /Parent 157 0 R >> endobj 200 0 obj << /D [198 0 R /XYZ 72 757.935 null] >> endobj 78 0 obj << /D [198 0 R /XYZ 72 733.028 null] >> endobj 82 0 obj << /D [198 0 R /XYZ 72 617.438 null] >> endobj 201 0 obj << /D [198 0 R /XYZ 72 133.184 null] >> endobj 197 0 obj << /Font << /F33 100 0 R /F31 97 0 R /F35 103 0 R /F37 105 0 R >> /ProcSet [ /PDF /Text ] >> endobj 204 0 obj << /Length 692 /Filter /FlateDecode >> stream xmTr0,Ҏ8qeuq ((C@v9<(*{{w7dFlq^f%W,v?rVopʬ Z]ϭ~nD\ l]D[yR1'Gck CiYi#\ƾ]HbLg:5}a Z5EtAuՀ1RmpC`:7F%0wV"ވ <,΃{6% ԔUb. խUZ]7hGuޝde@(@iX@3:azoz<ϗq(}ƌmgWm5cJt_Qi&v4"uZXF*DI g'HpVь2֚KڶgkS-ftQK0C5yV7`CyJ4_XDRi3k45Z]Wwe INH,g_;( AX)F!,0Rxѳ> endobj 205 0 obj << /D [203 0 R /XYZ 72 757.935 null] >> endobj 206 0 obj << /D [203 0 R /XYZ 72 733.028 null] >> endobj 86 0 obj << /D [203 0 R /XYZ 72 659.223 null] >> endobj 202 0 obj << /Font << /F31 97 0 R /F35 103 0 R /F37 105 0 R /F33 100 0 R >> /ProcSet [ /PDF /Text ] >> endobj 208 0 obj << /Type /Encoding /Differences [ 0 /.notdef 1/dotaccent/fi/fl/fraction/hungarumlaut/Lslash/lslash/ogonek/ring 10/.notdef 11/breve/minus 13/.notdef 14/Zcaron/zcaron/caron/dotlessi/dotlessj/ff/ffi/ffl 22/.notdef 30/grave/quotesingle/space/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/asciicircum/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/asciitilde 127/.notdef 128/Euro 129/.notdef 130/quotesinglbase/florin/quotedblbase/ellipsis/dagger/daggerdbl/circumflex/perthousand/Scaron/guilsinglleft/OE 141/.notdef 147/quotedblleft/quotedblright/bullet/endash/emdash/tilde/trademark/scaron/guilsinglright/oe 157/.notdef 159/Ydieresis 160/.notdef 161/exclamdown/cent/sterling/currency/yen/brokenbar/section/dieresis/copyright/ordfeminine/guillemotleft/logicalnot/hyphen/registered/macron/degree/plusminus/twosuperior/threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior/ordmasculine/guillemotright/onequarter/onehalf/threequarters/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis] >> endobj 181 0 obj << /Length1 1652 /Length2 10152 /Length3 532 /Length 11034 /Filter /FlateDecode >> stream xxeT\ݖ-!)%;!x];}jqZs=)jrUuf1 $ 0 4?hښ`[Fp@&@Hv~~~j{šgddOLg+ {+`BA 0$TTuet2ʚ= US[+3D0;l^@?9b9L 34Ꮛ rrv~X9,L!3Vf.?^98_#^}``gZUURoKȟVn56s_WW/C2V&_leoOL' g:_7qp+Wr8lYP9^kA^k[X٣.r`;v?| Dgп0m=@9 2Z@?S'AywF& -bklb+ ss4VfWڠWb0mrrU fsie״lA5P3;ۿ4,lo_9,  VsI\bfe0sagsr7UbZdgcaccϕHٛ:srtIvU΄qc׭Pfi!x_G$;aCiW;W?Vԍ <wxڔgĵHPw[ie d5,FK?Ў:T\aZQ`X@2trCOMu,6 :&q暶@_|&cv,2+Mc6fTy2t|%,"] x6Z(qJ0Mvݗyhm%Z6cUd49.HH8LdؔY/4ܻWXKa[6kpN|ZNϘ$GRy7ֹ[[d[EkpJ23e^;!p\2Jm8qHXC$~G(Eq-.{uDVО5qcraԀUq<%6w֓8H-RѧkVC_Q8wi0=W"O: SJ fMRdv!}]4rE'#0u%B쮢0&𵮁l_ȹ'Ο{0lh#WԟI^:aX ~A b wr©Eqoih؛Z kODG؝p+| ߒO>~5 >J%'|=/jId\-kgYJ8XH%1/:֛8!M̶K¢2R#ap}YM^󼑒=\ M<)$~m73d/o+Xnl>.|~Ȇ s=Mclll$^ד@2\^v[ w FU3{pB~\Uܰ)7}È}a`jWE_V82NWWدlYTN&N3x5`^dZ[vAB)кXB0o#7t r qLqᷪ>XQ$[Rt7D(eLcIR߈(oFSt56vd 7}o(g| gS۹+o. rwGF T۰3DZ8494ڊ7q?((c{5|gƽ'zK+'ʨN<)2FUb6Jt>/P(w`a'Sb1՗wP5xEy:OK2m@iW>G5UDCpB2`&8:fh`reܒޅ9s֠puttwĕSג'SW>'H; Y^dd֬Ѕ-~BMxއj1%bZ\ܯEƫvҟ?uml`Oe@ib!˂DcJO x27I1*TC&6o;[X4Xl`qCĵa]mt%0ri Y i3nod4./={6!AtGڕAB⠑mU~zN+;S_(. UH $W×^z`A94Џ*A[OA.\[/9O=FV\RZ6 RSbzѧ@3-綪]3yMfq^mj`ƌYRy81 7,zt魤֔_pW<=E,d.\9דL.WB5ϩ0˖zgR]5'aJ ' h[eM8 CUYz7i(aPlHF8+d}H`|wEW<u7,#0=Z׸vBc:fɩ6G Њ#]HF:n!"Sc*~quˡ}0b{v-g=P}äw&zl{ŏ+5 OzTmvwH =QcN5zPڍ$y98<#~а߂u9.fh'q2O d *Hq[ #Mdo^JC8YkFy0K4LHxX klg9Qf9bntޭZv[a)IO(=㏑$eM7S.#4Lpb9h#yDz?FnlUWBm̊=9rL DٻHg&TS=]%kNt7]ޘi籌ΕΣ;nH2@-%&v*]˨ve&~AXq\Xr' Ϣw{IPMێ˧US9lnptk{z`-Ie,'vԲSôl3{?T;bZ~'C6ih<S.W=7BO.# ᓸ eܦf'wfdҎ$ nR^+o؜[O\5eχq#ưŤ̹cCo߲AԱ~Uu7xB/!t 7hImC*;ziŞ26J%po|ۄTu[t c;# 'DM}.u%#"25(=/%G^V^wįReI`H.E4B.۞M1kf": ]׊0Ed#ߖԧo1;") ̈T;}!#Ra2&]h.1kmw~MFz0>B8¡{빲-ҕy&}6 7kVb>]ev۽1L]`1L\lMThx=f pB\! TR~$:5zԡ:!34oEWb5%jiQaҮF17i,p) R8#HGٖ};?ym֔.Jޠ8p0c~ k)@|H7A S$1Ҥr[30~0=tDx GbW` qW*_ Ó wҐ`[G4S#S!8]UyK1f^~N/qTc^Q;w5Kok21J'hkr*ګwGUi$c[\0ܿb͢,nVRՈvJ-<(ʾ@zM9F+GA+,XKoJX*s+{!Y xekĎ#6p\AfhAIsgz\Ā@F7q ))+ef֪c:E wZ{>mnf`JoQQsPظ?НA= xA١V\kO8+ \|s*Hq o|]=Φ*oٹQF2W~ 87dpʴ* /2P 7OFP皹fiy?t~I|ݥ~ƃ!m[/t(c~}qﵽl0ͦ|QpE&4ݩ^;~)(?GU |B&>#ULx1ףR Ȥ_,z.ssoxƛ"D4@:2„XS]9n9d/$0 Rr:|:&Ժp<O + Օ->~:nPʛu6k,P`Vqb~ڍ8AMrR7O,NO,VqשBLqvO&l12/ɭ\Ý7HC$yr͒cLʛ[?ݲZQ}zSHsR/1+sI)k2{.4f5,z> ltu-|*.̂ u .=jJC!bW*͎N~Bn{~d=Dfh\u@EC&9 35.MDܘa)Ɏ _w c~ NK_vVyOWok$u;^6ԁJp ;J^7k1{)HqZ*q5ԥV3M3ye*M O4t.^T5H4 HcLgRol,D?@+vڈ4Ks˒)1Y8*9mFN%#Jf"#)~KQ>X5:;M rgT(⩢7@٭em6LUМ|59Yh*>&[VtיV }v-!/JzMHmZc=k[EsicS*xK·mrzU8 %mXE%(IQ]"L s0Ĕ|ns>Z|ԍ4؜|iW'd߈ITozDzP^/'T'㉍E,S?_p $fnxK0Φ;Q͋m}(pDXbi~.ēeqq}ZkJW}o(W>tB?*{ w/]p_>~@=#Wfi"W WqA.݌_5}cXX,vVyb 4uݟ Om^4l:!faL| #7>9EmV&gm~<ЉRVb9Fצ"ѯ0|f{zɲb)֑Io[3]Ԍivug$w xbV~0sZ!Pv;x<~M, נU?0ŗ250rRY}HJĀ=6YҖQa-cD%yNbyew"r`w6wQ_$X&1%hoО&e,U%$P/[gCWȁw^^\,[!-\&<QI~f-x0}Yr36q?^XdQ~tZ"Be4baܥ:b.f`9|"R!kUD@| "{e4wm dq՝լm|bĠ=eu:&?rcT+aU.2HZDZBF~+u*Y~FNgkA&8i#ʐpF}l<]ol[*I A4a[}j+3KhsUcv|}[=NmirYp47T鴨Pa$\j{ Ĝ` ;C4zhIKP/#? ZGbG-JN:iWWu|Z.Iًl4 !̭Db!X}ܠ%W*Rlr%)|+y$9h{\ַM% gk<F:n?c[ߦٗ5Pߕ>Vx<9tg4(_2_$e}Qi7 LJ7QGx'!+~r`K|˜rGM=w%ȇ3&v16paRh|RGU4 Y/֨rR&E褱ۗH bnxe6ck 9ϧ-[lƫjlo1o #W8vX0]DVghtD%[:/f+)<;`Z n&D>\K{S0'l*-LYVJ |htZ[ cU[CPṀȳYM|0G>V7W #îW>1kDDMDZ7p btxf%xi/ B`Iq%͓_]QapֵHD])h ]͚~f_X:S<)b+v釨n_Zm镌c' Iec=@3ABU2vBfTT#Ym@ݭTҧC=]M,]<%a=һK= )Sо B\/=۬urVNr9j$UmsBY$BF+|H_PMFpƉ5vKT"ɡI%f"‘I}λ ppEڳg8dxMåy_O1cTNOz%\*r4DjڰB}ϟC8-lj9Gw?_s{$l"w/0;w9)@?y7R Uk& 0 LIiy9 iNE`[+sȠcv;%b%,"3GϤ؜@8KrV+|\qzg7>lSb=|Ѽ,?JX!JZk"/e7VDCHN‰MPloF}HЭߜt0Mg)WVDCQoi %Tr%,ZzP,5hg0aiy7 !m̯ []]w*  D#Б[Wx!@VfWP) ^# ۧ!_ʨNV\l 6B0̹ d8*:pNupfӂ%`U2zB~3P "Ԉh]*H2r`lC"ojX#hɹ؂WKO=`#0 ;Y5@ '>Dan?ϜGQJLxˈfh7\g8vYa%myU tƓq[I.y'rjӾ6LI;Ӻ _e(C]8UB ״T+Ш gVRd&"akCBT\v8 Ϣdl{"(]i$a=}%dE$DE~i|Q Mf0e89墅k&XyI42Sp EƂ.&v_#Nh+F7(?+pkݴ%"+'2:?bӶvmŚ J0;NXgJ"j;qP=+[dR^77t&)O\`%rR ib`1Uu7o&olIvU(ULq> endobj 180 0 obj << /Ascent 728 /CapHeight 669 /Descent -256 /FontName /VCUZYH+URWPalladioL-BoldItal /ItalicAngle -9 /StemV 114 /XHeight 469 /FontBBox [-170 -300 1073 935] /Flags 4 /CharSet (/hyphen/question/a/d/e/f/g/h/i/l/m/n/o/p/q/r/s/t/u/x) /FontFile 181 0 R >> endobj 209 0 obj [389 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 444 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 556 0 0 556 444 333 500 556 333 0 0 333 833 556 556 556 537 389 444 389 556 0 0 500 ] endobj 210 0 obj << /Type /Encoding /Differences [ 0 /Gamma/Delta/Theta/Lambda/Xi/Pi/Sigma/Upsilon/Phi/Psi/Omega/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/acute/caron/breve/macron/ring/cedilla/germandbls/ae/oe/oslash/AE/OE/Oslash/suppress/exclam/quotedblright/numbersign/dollar/percent/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/exclamdown/equal/questiondown/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/quotedblleft/bracketright/circumflex/dotaccent/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/endash/emdash/hungarumlaut/tilde/dieresis/suppress 129/.notdef 160/space/Gamma/Delta/Theta/Lambda/Xi/Pi/Sigma/Upsilon/Phi/Psi 171/.notdef 173/Omega/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/acute/caron/breve/macron/ring/cedilla/germandbls/ae/oe/oslash/AE/OE/Oslash/suppress/dieresis 197/.notdef] >> endobj 174 0 obj << /Length1 773 /Length2 1203 /Length3 532 /Length 1774 /Filter /FlateDecode >> stream xRkXWU#r_€"W$$DJ DZ)&&3& 4 Aj\T"e[ƊPH;`>K9=-xh"D}hEQdՕxc2\ήt2` xRv$)D0,\؆raOݑ@(  $ i֏e8c+ %[ܤ[䡈@ N3G8+g.G QaD/ʃD|j/ă]#H%8 K Ƹq@ G!7ۜs9bs` .:˝ä`<,D$D|}rQ ` 8R>8;I IpND-I*IqP-a*8a㝼P5dI$2Q&!pـk 5bB!c`<]@\(M?8qdWw~U:K2{4gooN *U /H^ʮ Ǻg)/WJ[Md_(Uӿ8?ˆl OԨݞT]{BB e*AY_Uv 08PMM6?53szEl4uF7n_.ԍ=+'SFfR}Tz8x8|KO|Oo<<ǡDſoxeT[~V+[K3}A9YGբvi)6ϽVQw{Z{˰^4?}*c 9p'Wק|Lfl'ۨU F^Y+uT#J*;JV#꒴ZwX,0U8T*/-uOfB7/7EiHsqݭWƠ8xHZn7G ~;ISE.--ty*^.9LgrRg+7-y:xx~RIowSW ?LWri՗&(ǶFFk"׹H~J(Ivr1v2ewEhC;semv)-hmI?d)alwk|}[ͩ蕜*_gurM3~Kw#%5U&sW?K8DFnJ„ OD<\<9 eEtD?ZKe2-C!>Qpp4jsz鄼0EKl-ü_,.Ҍ6;`ee%ǣ8vO W[ahqq\?Ӽ9^+}k S\[c!%cJv :I[?ӻ֏כ(ׅ&5FlzjmA (eOY3.\JM6wPy0rVbpݡ!O/?WqD*v~Nendstream endobj 175 0 obj << /Type /Font /Subtype /Type1 /Encoding 210 0 R /FirstChar 49 /LastChar 50 /Widths 211 0 R /BaseFont /TTHJPO+CMR7 /FontDescriptor 173 0 R >> endobj 173 0 obj << /Ascent 694 /CapHeight 683 /Descent -194 /FontName /TTHJPO+CMR7 /ItalicAngle 0 /StemV 79 /XHeight 431 /FontBBox [-27 -250 1122 750] /Flags 4 /CharSet (/one/two) /FontFile 174 0 R >> endobj 211 0 obj [569 569 ] endobj 212 0 obj << /Type /Encoding /Differences [ 0 /Gamma/Delta/Theta/Lambda/Xi/Pi/Sigma/Upsilon/Phi/Psi/Omega/alpha/beta/gamma/delta/epsilon1/zeta/eta/theta/iota/kappa/lambda/mu/nu/xi/pi/rho/sigma/tau/upsilon/phi/chi/psi/omega/epsilon/theta1/pi1/rho1/sigma1/phi1/arrowlefttophalf/arrowleftbothalf/arrowrighttophalf/arrowrightbothalf/arrowhookleft/arrowhookright/triangleright/triangleleft/zerooldstyle/oneoldstyle/twooldstyle/threeoldstyle/fouroldstyle/fiveoldstyle/sixoldstyle/sevenoldstyle/eightoldstyle/nineoldstyle/period/comma/less/slash/greater/star/partialdiff/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/flat/natural/sharp/slurbelow/slurabove/lscript/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/dotlessi/dotlessj/weierstrass/vector/tie/psi 129/.notdef 160/space/Gamma/Delta/Theta/Lambda/Xi/Pi/Sigma/Upsilon/Phi/Psi 171/.notdef 173/Omega/alpha/beta/gamma/delta/epsilon1/zeta/eta/theta/iota/kappa/lambda/mu/nu/xi/pi/rho/sigma/tau/upsilon/phi/chi/psi/tie 197/.notdef] >> endobj 171 0 obj << /Length1 786 /Length2 1293 /Length3 532 /Length 1867 /Filter /FlateDecode >> stream xR{<'ژ,r0(d1иL %fofW;" )SjCklʼnvR 2E*rIvh?||},L>bH%Q]æRzO/ J`J @e0TBspq&$c0NllItC"ÕAb+($$@D%BX'Ty<P@PK> ,Qm ,شj|%>$P4Hak8K*p Iâ8A*0A,Aq >,/%\c"BTGCNd2Kxq@%B u/vo)`.40" INw!a DRH UMTE|ʇ!9.qqGF4B0‡dI*QdvJ2<_-?'*K!:=M= 4'"N)43PI1 B$ IG,C T(5kG4*eRDsk w%={jp ;w3ZRNh[2_@{?LmO &o_ih[qgWQ\DFr}k*dV~#1\/r ڽ_D{}AH Ea?M7VOFeY ޘ͒=SU6ط'Kd l>+Z"7M=Unv{9-M_1{y3\k,2Y4^̋huI0YwFI-}7L b ngiwkYNK#Y?9|tGmExڲm+ nkM~*u.DK#IRNuC8 7^N"݅2 Lg0/A#k*Fǯ}$G.kz~;hNƬkGwShj6s9Q)cnT3o"Mi;k;SgCLm7nixcL~ngUOeylm6q:O |(`3wEffMhW:-AX)o}=޲b}N=4*4|걥ŦeWnPĆZ{B13}L+!d$ZԀ?ƒQ/Q bTq"_@endstream endobj 172 0 obj << /Type /Font /Subtype /Type1 /Encoding 212 0 R /FirstChar 105 /LastChar 114 /Widths 213 0 R /BaseFont /AHNFSN+CMMI10 /FontDescriptor 170 0 R >> endobj 170 0 obj << /Ascent 694 /CapHeight 683 /Descent -194 /FontName /AHNFSN+CMMI10 /ItalicAngle -14 /StemV 72 /XHeight 431 /FontBBox [-32 -250 1048 750] /Flags 4 /CharSet (/i/r) /FontFile 171 0 R >> endobj 213 0 obj [345 0 0 0 0 0 0 0 0 451 ] endobj 168 0 obj << /Length1 812 /Length2 1310 /Length3 532 /Length 1899 /Filter /FlateDecode >> stream xRiTSgNDeKYdVV$@B($7@F "" T@p(KJQP: R -GR ԙ3̯9s=}}~=l^Dq=$+pID@")Xcc7D`ם@ND&*nk xqbS7U#p04& Ţ5XL`[WWOBxm%f! XUI^Hp\٢xH DE5fq9b"־<joX*p|WC sĿxq" Gum4 b7f&fr8 C 'BlaEH&GQܚkîAt09,gUZLW#KBac(`cSEoكdl(@`k+.AԓT`WjGqL@jj%_Nl?S(=6$. " grarD"ёlDvPC?đ0j?%B,393Xu9ͣseJԭ3wۚ1̩曏-^j+(>NX6hI9:?SE iRARU'2&pͲ'|0َ S*C6F|C[icU Ė@Ǘ/K첇{2bUo[㵈4T{c[\>2yB6w} *@[һ2ʵj˒=ŸYt@Z#?c(fi~[q_7nw䊭jG5hOi7kk6F/~ sLK^>kKE9ie*OrsAǏ{l/_ȑnO5*]:q{ﮃ }³>GvplO}By|䒄~2ϛ|Z/fU =mԬg Ӻcy)sR; ЫvhwAGt `Gɻ\b9tW7yru"\P-(c^8aќHV)M ]ktLÖ.?Ňv$H[͘~͌ ou{L!rc!݉zW7=HYqiQZO>u#`Ҹ 8+c(>5V ekv}ys\_^@vveÊbfݻ;_I1͇fWb<|E.U].,n$ $s?H*]ūundhz7Vv?]1쨟=d!_D{ELm_S*g[.X)@xLxdVendstream endobj 169 0 obj << /Type /Font /Subtype /Type1 /Encoding 210 0 R /FirstChar 40 /LastChar 61 /Widths 214 0 R /BaseFont /LSTAXR+CMR10 /FontDescriptor 167 0 R >> endobj 167 0 obj << /Ascent 694 /CapHeight 683 /Descent -194 /FontName /LSTAXR+CMR10 /ItalicAngle 0 /StemV 69 /XHeight 431 /FontBBox [-251 -250 1009 969] /Flags 4 /CharSet (/parenleft/parenright/equal) /FontFile 168 0 R >> endobj 214 0 obj [389 389 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 778 ] endobj 133 0 obj << /Length1 791 /Length2 1391 /Length3 532 /Length 1970 /Filter /FlateDecode >> stream xRk|=Ex? Kp.pdDPa%`G<(A iN . cc> .3xJ& 05LTD; @G;\B-+BQƖgy`%"\#镧 %]EF̀\׈]\'h5_|Y]iD~D/Wu^%e,\>Vks@9+J섅އCmsꊫQWYV,˂q ̈n*AgCUR;GL#u"y) ޳cwyifX=}^9\/Ar!|I6ygYAR,ݞ±:sț9ѤSmWBMkuQqIڸ T -ڡ!:IPKlyW0;MACǘ'x)f+gog G}zk:"AG(wn̈Zkdo[D"ZRG(V6-wh}="j}o7kzk/16u0>I|/)۞4iV*ԕ3?M{{T|e!=8U)˯HȁZm&w;:6.Xkk򘬧h'KJj:Rl{mZlTbݝ^`3|5QVЭ{]u˃eɍҳ#u__n(O`ՈNsPqV&"%Sjy,s" Dzߑ]CcηKRB]<&FWw)$ l+qt莹&տ.eVM6T4}y[\G 9ԯb`OhJR/g FVXB&V߽Uk]šW)ѺTh4O\>άupI9tJiG xFz0&4rZW{c 5~.`Y nمlr!])WnP><*jZ-]ǘwsTfMԳpxuņS'yMk=qA^Ms͊ۮLi¹Ϲc /?!C(7\Oendstream endobj 134 0 obj << /Type /Font /Subtype /Type1 /Encoding 210 0 R /FirstChar 49 /LastChar 51 /Widths 215 0 R /BaseFont /IBBXZX+CMR8 /FontDescriptor 132 0 R >> endobj 132 0 obj << /Ascent 694 /CapHeight 683 /Descent -194 /FontName /IBBXZX+CMR8 /ItalicAngle 0 /StemV 76 /XHeight 431 /FontBBox [-36 -250 1070 750] /Flags 4 /CharSet (/one/two/three) /FontFile 133 0 R >> endobj 215 0 obj [531 531 531 ] endobj 130 0 obj << /Length1 872 /Length2 1324 /Length3 532 /Length 1927 /Filter /FlateDecode >> stream xR{*ND 4HD H`AnL d `2DB_Q` 0&>AA )0h x$aZ(@)(}g0P`j8E9Wr Nht2':dsN bG" "Y~4@hAL] D(D\0y Ark{8lvB`PhdWk5s-ȇhAQ~:0kD'CDA1 8׃`rՍbX@ߗA$T ӃaHAV9au~q ~k^p].P8<02ž30 @;+Fpk]ad @Ձ`HB >ƜL-IrjI"z YV3\4sj"BinlT`RxxfmENc;_GOIݩ8:7KIgYsS.V&RC#B&pJM5-%8~~Ot8ݏož֢[ܝAcy,e .r*4E}'>R%W_]t=aDFuZoӪPy8Zcp(]RBS{Dע\wmy4ǘ cMj^Llyb}ftqܙ}Nqvl oϺTʎ✦|ZL.n6Q ^\h} FזS?ΙT;x s.z s _'9:ڤbbrEf<1;ļTl, D _&ö*Vqhge.Ȍo˗ꯘUio,Ϥi+ۧ_̰5%-Z?-!ãSrڍKTl;zX_1Vq).y4V)IxKA3#M/~̼(b@}9#qLe>M ߩӓUmJ +Ql*{kUs[v}+*`%] joA֭t`{#,[6_r#prFVr{'v ^ݾӽwOz߰N~- ^ٙΣoCe)^%x9JVܩ<ၥ܋i<_*YRi|8:,UܝB O}pew?49~ֈ\f(Jv>o-> endobj 129 0 obj << /Ascent 40 /CapHeight 0 /Descent -600 /FontName /UXMFKG+CMEX10 /ItalicAngle 0 /StemV 47 /XHeight 431 /FontBBox [-24 -2960 1454 772] /Flags 4 /CharSet (/bracehtipdownleft/bracehtipdownright/bracehtipupleft/bracehtipupright) /FontFile 130 0 R >> endobj 217 0 obj [450 450 450 450 ] endobj 216 0 obj << /Type /Encoding /Differences [ 0 /.notdef 122/bracehtipdownleft/bracehtipdownright/bracehtipupleft/bracehtipupright 126/.notdef] >> endobj 115 0 obj << /Type /Font /Subtype /Type1 /Encoding 208 0 R /BaseFont /Courier-Bold >> endobj 218 0 obj << /Type /Encoding /Differences [ 0 /minus/periodcentered/multiply/asteriskmath/divide/diamondmath/plusminus/minusplus/circleplus/circleminus/circlemultiply/circledivide/circledot/circlecopyrt/openbullet/bullet/equivasymptotic/equivalence/reflexsubset/reflexsuperset/lessequal/greaterequal/precedesequal/followsequal/similar/approxequal/propersubset/propersuperset/lessmuch/greatermuch/precedes/follows/arrowleft/arrowright/arrowup/arrowdown/arrowboth/arrownortheast/arrowsoutheast/similarequal/arrowdblleft/arrowdblright/arrowdblup/arrowdbldown/arrowdblboth/arrownorthwest/arrowsouthwest/proportional/prime/infinity/element/owner/triangle/triangleinv/negationslash/mapsto/universal/existential/logicalnot/emptyset/Rfractur/Ifractur/latticetop/perpendicular/aleph/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/union/intersection/unionmulti/logicaland/logicalor/turnstileleft/turnstileright/floorleft/floorright/ceilingleft/ceilingright/braceleft/braceright/angbracketleft/angbracketright/bar/bardbl/arrowbothv/arrowdblbothv/backslash/wreathproduct/radical/coproduct/nabla/integral/unionsq/intersectionsq/subsetsqequal/supersetsqequal/section/dagger/daggerdbl/paragraph/club/diamond/heart/spade/arrowleft 129/.notdef 161/minus/periodcentered/multiply/asteriskmath/divide/diamondmath/plusminus/minusplus/circleplus/circleminus 171/.notdef 173/circlemultiply/circledivide/circledot/circlecopyrt/openbullet/bullet/equivasymptotic/equivalence/reflexsubset/reflexsuperset/lessequal/greaterequal/precedesequal/followsequal/similar/approxequal/propersubset/propersuperset/lessmuch/greatermuch/precedes/follows/arrowleft/spade 197/.notdef] >> endobj 107 0 obj << /Length1 818 /Length2 946 /Length3 532 /Length 1539 /Filter /FlateDecode >> stream xRiTWU+FTd)=,H2A&,6hA퐼$*V mrrE TT\@EʢUz:gwߝ}6G tD3pI6@l+Qn( F.`9lg.n\hSu*H`RT D( UU . |0QPƤ#aR@ r>eOP$")S29 PeZ dPNgq.H97L(bT5$?8”*\CBp$#+s"(4DV(!pD2s,B7FJCUF>TFZ6 sQLM.=\#k*%ӂ@6F("~ qZ0pJh4 `jj*X XubPBr? Z>H 5OaV$mppm# 8:ͣl RPk|rE9o⬩ v˜1?WLOǐOhfq Ѱnk#N/3Ie.-xyt턦7]3/K4'*B;X&Ͻ԰Ѓxը *y>jI G֖ynv}`*ݗ+>n)Vi&k=S_W19*u;~9y_yݗ'۷uww≝c=V|[⪡S;5Ǖ )z-G^8/*V|?{1w\ ݮ˼ssa#(ɈaE 0n{v > endobj 106 0 obj << /Ascent 750 /CapHeight 683 /Descent -194 /FontName /NIAMTY+CMSY10 /ItalicAngle -14 /StemV 85 /XHeight 431 /FontBBox [-29 -960 1116 775] /Flags 4 /CharSet (/bullet/greaterequal/section) /FontFile 107 0 R >> endobj 219 0 obj [500 0 0 0 0 0 778 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 444 ] endobj 105 0 obj << /Type /Font /Subtype /Type1 /Encoding 208 0 R /BaseFont /Courier >> endobj 102 0 obj << /Length1 1642 /Length2 12445 /Length3 532 /Length 13321 /Filter /FlateDecode >> stream xveP\&wwwwwi<N\Cp;s:{Mͮ]],y޵4ŭ@Mf`n+1Cobn$jjIW9v2@+`GH]A6=##ӿ$,yt8h><`gG Q@lk /" UoE[8,J K` v8;Y*͍ K `psZ܀^@TLg#rظ;Az@NV%&+MvY!jR2bk+M [YZ-*ơbrr@^bYV 7gso`ήpw9+&+WwU'ooVtfAbxi ymrBb;Yl[;StAt$̭N+5 @2?B<;#o'?w @ גY'ssGdqw0ww?ŝlag&Z ks^-v:oN3;ۿlAN5*տFɳh(1-og U[/  6vo_D_ges+ `x{H;Y1s'K;P^rvv.οo ZCz-vi_!xكcR찃a +]iefUa,Z珜_vvqhRg~=yk4m&Q)mS0)zF ht}~GHMuo6Cu1M-m@%|cV"*ͧ@,"QR1a,-@gVGUӾe"؉_>=$X%I[=qs(uX`=aCntaۣwdשŔmܽfCy&6:ڀ~yOwYPgZ(| >O)UkuD Z*i "HЅFɮi}tkJ-KU~TP;OΨ@6à/wINN YogH$(bU+իC]53>mǍJfꂐx;yo0RxM~v.4=ѧFmi1.t/o77mרOAe;v'awy37!0tAn-Oa-z%^C[ls}t< kZD甭tH Cƽdhg$6ePiGe:혞ur9pcjڥ[X֎ҔIeI'_n8RATu xnTo1$hC%hs-<)*rO`\TS:1};uXGvJđG q}|dsR(7Dnq[)90"iܖ#Ө2}D^%ZCW~z:#j-*LTDpn1f ~B7\У7&ֵKIО?|kBn?4e.='7 1Tk&L;+0l;z'`.5;0MNfN7fQN? nY,D $8qH{x(?e&]ƜiH#7Vh0 (Ҭ^r;G)b>A2_٭Åe>yy/gZ)SB7C {^JUC!c lRQY= ʾ}IM0c|kQRB7t?o-Z ΀etm'N#w/-9#Z=WZ_ר /1h:$QbdKpdތk|`;J,8yI͏C#h+*c2 Rvow7o&v>LewQJOd .0h z>qܱD[qn{LKf' Sv4q6bWȖ:pcgOm=wzΩb۝8?e2a}ԢqMۈ">=75PLfo]NT<=z@R$!ݺp;֛OFhI[Ƒ}fȲb݌aE;ڿM08V{ ]Dc  FXHRaO@x`΋D09rN-)[)싌YRt)&sK#Lq>${.$p@z~fAI`,!f+J2Շ^ƋyOݍڏJgyCوK>TWcr7Xd,Y\ו >׶Ɋ~R@_g -11|HXIƿi) ER-*&Mx.K3ZuU+5X1[ wzijl<_oZtdlUķ${ķP~V7"ZN)|R8Jy8ٳ\D xkFU*v9Avmj^/4G Bn>#U?ѱDF8ētQY>'oc F{ӏt?Z~J@Ыo(ٔpI&F\&$HO; wvwy tGhx<{pv,i;zlwA[ ߙ!~m[>@!&Q~|*L:_moG~KiT4JFo ƢIi{xeOaϕ0Zܰj/s#: ʁ+5 N)7@ 2P6}nɬKh>{mfRrQ׋ >|d0%qHjS1:pfVxBwOf@<ϑ{TY5i?tû NOPk^2\pDM]yBnÊ$I6F0S0Somt*sk4+BӄNt9>mJ0Zr^Jpy 3cMhG\L]/0Ha-(ӿF7`/A#Э2NgOR_܆ް0@^mEoDa7V>vSy!SMe{r9x0YSHWNT< F2Us~.{o& |@IXA{(0Jt2yU}Է )ΛYaƂ wH="JNK՗ zhɇ. K뺒,| =:l0Ivi+NcE8.BSMzg9o39JvMw^_]*oufwW*LŤ"ᆴHf,-wW+R Hyɰ('pˌ'fѿH.ComJ~KQmV^3?< 6(g 5JzRPi7RA"Wpl&M>m1|D6"IjqJM5_YFrwh c[@/YIygwD6W0'KS&5Fzʅ<o~ݫpl krp[ypM#HCC` 391%cVroE2n4)P>n{DF֮_ځoMSD}j?.ϖ :R1/zJ?uO֯j6d]ں9lz4v _h2L…#P릿qjo <d.5pSͷ7` ,| t>ӡAEr6,R[8&Vm[b j4Vh5VJ.U[a WUhD=4=~!,b%[,lS<@UhiHoK!{sNN.65SÆ#7w1ج =\,%rJ+# o/|{~"΂({e/=VQ1kTgO4]J0Rpl tvVƟEspdoRJ]e#SZlU;h$2cFB5TA:_]&~c^[q6ڌ gD{r(f5*Uui>ős-|aGug-Y.z^JsI􇓼~]7c!4ͧ?0ě9, a[J( AL) _9]gϬ\_˙"֐DؐW1/TzrT_# ca [M(mDux6myS _leYE׳G¦üdJ`zF✯gE_pXLe+dYLvh+xo, |V咽ߗz1D%?+͑)6Vf* \Vqj9UxYcd$_n`3h^aqQe:XN^^[ԝu1佧ACx*oBA6r/]t*QkZQ]#!`'ƭgp.+A/d%ŇR3Š!4'*|N.y0cm>QO3a̴G={dF}fՂwJaZH 'wɛ"LW7 uX.|)m$NL&>;$e$Y_Iqm-LHm'})(&MÍH^׾jȸ ._Bղ&6$;QL#?dJNn2eF~}xqm1mlzRTygTD T:íQ(+z5wş7" ^fJ‡BBOұKa[m,fP9܃3Vo^ø۽PjOgS"ٝn[k⌅*.Z՚+r)Ph*U2ʑD+7waoJȚp,/Ww@_^S찆b)ٵ(^v LKͧ WF@WΤ3JHe=jt /}1w(Oe~Wb2dŘKT(t@Tn6Vz;;h(Pz;bV (djo-O z 0z g(0@V)`!*˅:n_a013_BRάM22~'MQo$ [8fIOG*ru7P:L;RĖr+$oa6w[i}ƪx}l3{??^#>xה.҈a?;̂Y6xӮ*Fkice ޟd: @N GtʼnvGZIn;w+(>Lrr]V0E"յe/"D j=d!KKI~IvO\4PV"v%.ш]-GppܾŔ7&eu\t)*$_ۤrXZKkn9l "T?4R|5136P" U䌋yRBԈiG҂tcq`\9< Wus|mr*X0mftc6cc;wS@ *DE!KDΨE}ZG%ؓR$˼J|C|58S_șRL`Yh0wПˣW屢MCC93 hHUM\+*=xNV(-Mc=tA34龱 U@Gי=ɚĒO9B.:ut0ۍ- ᕹŞ=G٭YN< WК`Q"M Ɏ>Njt8s9"W_yƬ˲#x{s)juR"錸ZA6ru]uF5epm%f(Q!ڷGU}X-6aJ*Ck@ ^ #NozĘ`0JZC2n*ϱԏ1WLp/+t >?ߓ( xBo7su[?eԭ_y!'Sb8rZ.̾R.w8Z1du w%o'ǠbLi'8 Q:_@WCk qmSKY+O4_˧%],{A]X8^l@|AY>᫗EP{X3LCi!O5ct_Y.,j}Sg;ONO'c(2 &<+dc9]h=:_(%VHkѶTLi$w=^L+FcG1B.RMC?a\1,BQT(?؜ Ky8K&urdZY莪Zިkh=0,oABy~dJW/ F=%aF`Aծպk嶯o ʑY@$PȔd8tT}|tk`>v'|X;#p;#O]ǎa(Hl~Zb[M9܏wdצQ9׭K@':D}"+NSmVo!9o9{WTVL."V>X!+ ŗ?)Ѱ%3G&`39nnI~Vy*D0T GirF{rCu|/4Nm8gncH[qk8#ᾴv k`펥^mu`7@%L@{o6 ZfM\A.'J->۴jTXJ /4MQbe߹qhnb=?$HkѨ#9:d3|<G|Uºbz_UU`]ĊL.eȇ#ܪG<ѵ.4/a‘tN"=BROZU"FM8 qA.Ld;=dɁ]{1'پ/ij:ρ8w]3 kQʛ՚>"hOv!.bt[ )Yikb6#uf.C _a%e d^X¢7Wl/X>-{堢?ثc' 3U`SGQMay,fՔtSvwsT;d䶢ZjmE >/v 'b( ѝ~6Lr(NþYf)n+IMKEt ȪV9g4OKùV'U.Qqz*EFP'ǣo:z^}./2q"6j G3t_U|CC7'9 {(R$hlSG-/JjVoAU@(yo( V֩x)RE[BciVԡ͜$Z !/Ͳ>˓X'fdE&g{64=jJ4_0jrU,/rLO&دC5,^aԢ8x1E?  hYg +3 5`hrŭ<&Iэ,8 >}y=>p` 0K'>HՖG!$ZWScM|箘ڣ21Tcq}=e͆. DP. &?G]-90Edb(Yߔ7;!T+ mc}M?V$fV`2=h>rIq2$? q^Q뮠u_or"tԬܧJiQ{s1}) JAK+k1]F&Me-8^me鄨wu Y++`m P]0t#7"0 Q?M바F /Y8TRjzHn0C3h2I[0g7; 7{l.ʔHd DSzm5-nLGW!/_ihNhb_ þ">{,Qqۈu ,ROPAuln ؚ?\1HjjboOj| BD^Dy;hۯ#7S>^Q^b JwS{XyZW趴rzSYP>$$:h*+Al I$}'oOSCHQɗ-|FV0uBP>`N%upϵ|0?=0DN`P'Xzn{HgBñt{=-0rXV f%ؑ/CHQ#OW%߯0 N}1Nhp=v`%ϴ=qDFd׼^yyxm -'{oIm>,Bus&b6~r9<{Cjl'5~G{QH_Ҵ½ nD#k #V.aXr9L=ENa'4rc?9禙T(N mVɶ=o%V'Gk;I =)#PI+y Sr8]FL 3}O20*Q&[А&P7Qv/,C59P8n[Le\gcyԯys%ܵ~+闅,obٽ؆;qzhK\`} L=hT51wv ꛔêS<[<. R\LV<t+MxfuT`L_]xr%״c| M.V>EO_EY^5viB;lCECGQKX>ux2f]JKw!ke 3-T&- &oi1zL- sdNƑޥ,Pr?׀|-yEӗ.8NB?!X CBZyiSre#Uϧ_*k5$5 (MɭR(nހm}q.5_;UvI*Jї%kec8s [>.UyA2HQz>Z ,3r"YI5(AMŻrp5zP 5VN}׀i{A|eQmjG1=IWhU5R2sJ'j #HZtXݛ͗8!Ӷ:{#C+-km N\4y)i[}̱ )g_Y>ۏBfkkAߔ3~= 5~蒊EHW]9!.Jd ۶i_\Y H/d[GHO-&29];Xxd)`,gO5ϗGc]~)i2 rG~?9<{|Z]2oo2qRL|,i\4*R !L wY(Vdm?mG^wL?CaAZ530X1s`I9Hk .Cʈbt+ϖ&KMYCO/%w#G<`l5!WŢ)䴣V/ k٧㫑Fy-7!(n{Lkv4{MzEdF#b@<:Ķ.[Ď36cLdLxטF ?tBH wendstream endobj 103 0 obj << /Type /Font /Subtype /Type1 /Encoding 208 0 R /FirstChar 2 /LastChar 121 /Widths 220 0 R /BaseFont /OFSVNL+URWPalladioL-Ital /FontDescriptor 101 0 R >> endobj 101 0 obj << /Ascent 723 /CapHeight 694 /Descent -261 /FontName /OFSVNL+URWPalladioL-Ital /ItalicAngle -9 /StemV 78 /XHeight 482 /FontBBox [-170 -305 1010 941] /Flags 4 /CharSet (/fi/parenleft/parenright/hyphen/period/question/E/N/P/T/bracketleft/bracketright/a/b/c/d/e/f/g/h/i/k/l/m/n/o/p/r/s/t/u/v/w/x/y) /FontFile 102 0 R >> endobj 220 0 obj [528 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 333 333 0 0 0 333 250 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 500 0 0 0 0 0 611 0 0 0 0 0 0 0 0 778 0 611 0 0 0 611 0 0 0 0 0 0 333 0 333 0 0 0 444 463 407 500 389 278 500 500 278 0 444 278 778 556 444 500 0 389 389 333 556 500 722 500 500 ] endobj 99 0 obj << /Length1 1636 /Length2 17691 /Length3 532 /Length 18604 /Filter /FlateDecode >> stream xڬct$\&c;6*IFض::msκ3Vg?{?U?TIQ(io PWT2161ۘ9()Ŝ. {;qc /@h<<<1{O' /-==Y xo3@h:QX  @LQI[ZA @#mJ&6 Sh ;l03Ӛ3_,g1h 0:b8lA@ 'c;3pLm\!nn/!'}]M@.U%?A{f/_1p `rv1[/_ ;bpZ;g:'l'3Ɯ oMS-@v=?fs:; v/ c3{;OYoILD Or-jc`l 7 o @#ۂl9moUW@fR3(y-(.qe7vv'GZrLd_ԺX03}XxJ>7($H! Зf{sJٵ'`M!lΊ].c'ӭ4ΪUF u&/ .-q[(cɎ"n&Є\'2h&52x-SE5-p h`(wg,Y_[U12mw+.ScU:F, m&9K\v=.b3j˱ժjXUL6r!}<%DKºg~䳸I{0VW0h6PL>ݬ O'czE2 ?ᄪ'ace)RuM6GlÞ#+3xM.![)cPo$ŧ'_ʷK2Q,v}SԬfڢvDLolSbf/fΰFyYk.NG_k1g7IEpM˯b&L5Bc#4LM[ %.bFJlRHK:aiXfy#{$wHsAVكZn_c;e]UoKmyca" tN,N)(B (6n2s>7:Go}Tt6qu`kjTIpf)Y'fu}RQ"qJYѡɀ.5L,"!4+9dRsrpɰjiM2)])xbb6W+kVgQ#IG2QC}S}9 9:՜G XFr8Ct aV@Z'u9PN j@.PGs]?p6 DpDVtt q})I"b4q3}8WP5. B?@Ef!4*#2i$49e`Vtў/5:[K?Ξx]AX.Cfa Q-ё'CgQ u1p*kQ(<3eAP ;*]rQ, ra(m&L9>^#1J2iIQBӎE)[h]ѠTh_0C^޾fܷ8ԭdpvgXH\-x:7?gzIkQّ{t Ei(g>;TԖJvVrrkh *Agv*n-4>߃m`/k۞vWf^*P5< XI{-[:/t׭rѳsJcu'| QNnTs2$,{؜9G Tap|QH(gT\<25vP֟,^4%A!$`[DZ9b>gj(Ub̾ \.Tjqw%I cDQp-^̞n]VUc}Hv/,9"ٟ,56{ 2?TīYߣE.0xdj-AC\)}ryu, 'D&*09#֖4QK.o?BڇV>&$\/lC6גp#&]5qRqV8B/ϘrZ 'hzFʤ0{ lNqQ!1wީF6J"ۜDoPC}_/ K(s^XGiܵCh QEH7JG,΅%_ll#0HiY2l-'\ lD&B(w\K';˙V=EcBMm(ه/mF[SPPoل}oAFM)R%6PѲNDc˜hR^o#XtM^B&MS$%0 G!,7SWkWs]$QFȄNIG2i62p̹?`Shd|^>hj).n4y+I Qye:Lhv, F_~w|(3W.( kG7nvY:?qπ, aRmi&-yavi)%%jhkY€[u͙z7ɦ9*XF6rB pUu@[c85Wz~Ip Q#W93//L+Z*~zL7vtR膠Rd%fc2_،=;~lRzXG6.6T,9۵BEGcIMdc cʔ F0߬u&gQ5!^Ӥy+vFxrn*(Q5@!|.a9]BPiRaxRgI/\6HJY5ɛ ݦ ̓ 9EM2zP4jP^mȚ؛QLY6TLg="Hkpn T#q*D2;%.yp==ŕ\BwoXC#fe#J~5^` 2VcR7ub5 r?!-pȎS<@ߖjGos VG^SV]NBYpz'%?n7U!d۹-/s}tlkDhl[@=/<VJW81Hu\ 8t~~МYeH>HOݣ G ߭0SAS׺==tf}Fs&Ԗ|[ė?K:,<)o&S2DTƒi\TGu\-2B?7l*Q%-yV,y$L92yuNr@9@{ 76^p&Y@"e] ֕PLBxwX;[rҌc h d&|K%:Ut8|Vitޮ ML|5!OLnttg;0Z pX=Z(mjȵ]J!iP2:8iKf-B,rlVm H<{종a~Eb!iY-4RG8tK%Z~wۈ x2{'!W7^D =&oم6*1(pW(茑v4沌qp*=2ͅFGmM$ke+#nB(w1g/vx[Sc5e#|Q9ɡ{bpӧp'>wcՑ"KT~'gu]]fhٳ;WX$@W\[um-xZkoQ9J#<3"nQ\Ź"4Y[-AbgbǢ{퍼^X {˼%B $JT55+4Rk4@? јԂ޾H0%qQ wAnЅ-EzA%"ܥ?w2IJy&nr64LHWQ&FM-Z% 'p5;/09_IZb(oD 3j cNMk::aPFY;UaejX¼rjޤD{kxo6ȼ@HHxL[2o?8rsTWއpWlǑ+z0y@[y_w`پum=+tU7v>Za[\)~f~:yc Ii DxF쉛Cd*:YJ-[[ay۶ڽK֏up>W0U,Dn$A^"t{*tOKs,N9J^M黚/ߐ>-K . i2)t|Ug\RSa1A9NTL}'DOwQG&N}vp=>+sA8ubkxHePC;Mgۿxb)Lj~I0aܜNmY <s _oGossדțr«cX\X6EO()XjO~5Sg@Ё굯 t@`d>)2Sh~ebQX["pqBrX.Y\)MYphya\_>T+M Nn4 VhKq$l|kM?8aŬ>INcFC kY栖OBEs H/ulҠHoFyŇ"QcfLƩhm;J&5FyS5P;Vv<rƠp I_=z _oݾ=ks*-q{ uƢ:zy@0Y:&ĀL>&+ _jGSU'V'#"?mGsDԚMP! lOT>5BKD]̸zi…RGѓ}A!vǯ6mNnrk-UgJW;po3#I۔Oʠql}wL8g9fKWzy>5# ?f]]']#Xw1ꔥ#J~ߞQ&Y]#+! S(֔M{h˃-fu-Ǜ`zHDy:z"yqKi!F}AI=ޜ3z`Ֆ$}?B3b x؛+KQq "&X1&*`Atם qD>I] :23/^ܺQCP (.sfb-^Qb0O\.><B, @/Ne|܂ Sg'D )e_ E{Cu$񥯬e,\&oJdžuXCbMt$LۀЌpc2Ԙ #wsBhpIrK{ߩؼtJ[f˞J neYX8A'Q`P'CKQ7 fnL#tS+mOFng" K?]XEL6>};i3m3gfu1B,*YƏ fJ!\D.]}Fd}DT|`m{ a8KU60cڵטNqtmLzSldMe?np?D/7}?GF%yjqF13.V,wF}uιI |+*F}`|n魢į鈂[T p4h-9c/q'{z` 6W) N!#sP%4X;|k[JLUL|/xU:[,{p%@z3X➵혩y4.Da0WŔ|tS"r3#t:5ImY63EZ yww2RߘvġGHXѠ9~[ŷ~oU_˒2_:AYj51#oEM\ns j"1I~B¬37?~Ե~3~ܪc$+J{qcGJzBjsyD([WD"LrnhfT~q2n`&`lM[Qnidm(V+9n'JwUOwןe9<9:30(A5)豗obj,2aRTS8[DÒ[TK zKp*vS̾w{t7BrA46~Ce\eviM&M6um"=I 2WBsvn;V8-` bWuP/ WLBod3tQWXoSVyvM `1~)9=m(/#2[qq: D6{LFD7E5~`0# 2j:)NW#Kx>y2Awe^Y,1B53wsodkېmne~϶$Ye.^?a5dmO!&e&E{ܔ$qI!LboӮ,AFsHwa#"Fl?X )D ͇tܡJekJq˖U rPIYZܣAQ9u[hJ~K:rKXsy~1)|I6/x, xR4K{u`»H|-;GXKT^d+)oj|UE}WGlJ}\DI/GeEb׽q]bģ0D @]R!m˜-OpR'&Aᅵ067]ikXY~Cvn6q4_@GBɩY*ΐ7WwRޤP$d lU4Opf)ܸE a4pL~bPhwi,&>Nvhu7f%fꥀf!iaEBrxOƽBGvňi~ӝ@͆dk.hLE p)3̊Z?m9IosB9- -T6Vߩy _,bƢʆ`" `H:w{Y3kr#eԏ5B#h2AZIU1vT:T»X.?/UB"*!$;,Vw-3a,tk?.Z^F؝ЊG8~O*B\\ۏ>-{(҄]v-ewISO-I߶'/Y2V446Cؑ%q臮bز Wv8Õ Jl/挨dhUfIű.|}Eo$t=s@Rԟߤ-ϮZ(D\&sqĚH3OHml#C}#khLg{b,R<5}o`Qʢ  ]aOV*6ajxwj%J3r G "b_&߮o<x<]-iíQK*cM?~(u$cj1}3|PG*iijAGťg:-ωr:>2-)q('@YkftqnFNa0 M4<3ğca/#&8G(a˗W]@Dӟ^͘;b=hm71ˠWƻ_|\؆R 7d<s h\ѻf/ώ(^/mGrk7>Q>51aH\;+,)T?nLNB<pmCOw٬ -a<و1ozȊG"yr(5Oˈ5A> :ʝœue'>B0N[:n&rkgAiC/)WA=UKs q6l: T1ܓmѧљuR$:<` tCo=G䟋'\{$KK-2RbXMYY[0B:2XlXy$,%9 Sѵm?UգZ ߭R1eb,kPkǬ'ni}~>MGRARphEy kNJl _π2tq]1rg {τӄ.MkcWr Lۼt%u 2./7 qfV:G)^qMhu Ms^_Nݒ ﳠlv]Yh:CtÐ*Sj@1 QQӆ7l / Eb$2vqG7.p'J8de::VJbp؂nlh8@罪ıU5#Uw"<ȹ'E%H Ȧ{<9Ӛp(Hx+8Z929/Bt <_y9d9E6k(-_SNG^+P {t ;fyT*Fa&\FdJbzUdB'L$ReTڷ5ǻ ]vEid奫m^qh^,90ؤu AKWz&ܐX+;D%=E^3& 1Jn2m!ΐ/saYFzqiԤZiŎ95Qʨ>V.۝~$zn9JH;:ceqT6=XmrvaUa?E[޴WrT Xc%mZ;IRJV挊Q2tL+/ɍȇVA̛s pW&$gwQ6B{}H ̅)O'Xlh1sO纳{FN9,c'x0 Tʎ'T 9cYXl k|(༹߱%MWYލ+:RP,]\ U%y,U-Q+߫(MWW(#Jd\ǹ^\"kU9e͈paGfD^]NΡ'sIuCzV!m"jŊ{_p=;>r/][DGq_$qHг~(Hތ<[>Kr5:0.9L24kWv8wbeϢG"FW# Y #vL\)(agZZ?P.ݝI֩sJq>eנ?|'씏2U# xi-h_5Ӯ~*I7z5.׸ۋK}i 4VMo8:8ckŎ?Q|&ˆf zLЫv輐O'3NڕW?[pqpD,+ӎd>Nmӎpo&j>L1BjCsnjƬT.iq\Nvr~eMSp> JGt/~)L 5n._`\?9 1'TlU~&t]*eI9+\í𶭘U GJ֩-mI5%0X!攊])u:SWR? 6irE-?`Wf˜D4 hd(mѲ̀(Fw)' lK$es];{*;(5vmiik)m9>y k! vJP_mګg7OWP:rtۣ&cq.~ZyM= '&%g@p&4N7v|0}t,;;3\s|eŲO8@{&~lX$wiO!;/K( aZA)LY_J>Oi.$҉yɝ@|yil4& "X[n$l%A|~7iR;Dz`S(1>XA Q2R%?y9v]:Et/02ʊ2jm{sT +uT3_ l2@gOAe$@Zqa1TCĹM;Gc]{C.֕ew^L-=ƣ 3^VH C8$NF&Om39GD[~'0>h*"&Dk~xR[4L)Бk!ûZ1T ڻ@o4^1C4Xx@K9:w .wߛ5c>u#cIхu w+J>`% "t"9@dbu28P[QYg~ .$pfL#Q:īy] ]1!201TO3Q˦%E_je;fA*klԄ OxEy-0t3 nxS1dĎdth$=#!*|is'2~j+!_/DSlMe=畸a;Kd[I4Go]#-_(lI婊WSc * U {%rr]B*B0K*D qꧪcms(&[KxLeQ;ЮĪt/K-x-Z̚Ouʓ+<ې6-He3/7]bs%ֽ4%Y(<..쉸vԥ~t?0_v~wВ9\mg#6jb}inW^N*甯Wbq8 [l(}iV$'JY'Su2|I?`.vFa&M_ ݏi?ewސjS8?[gSs~bځj!- gC+ ˫T9rƠv`  --q? JQMe]PݿӬy$}Ch2ɇV+lX\.@;an;Q6nW_]`v_؛`G`گ(JmL}%~ը>ɗiHt|/[z)~ iwŸmvENdhrͿM^ff1au}ՆvrY5%aR]߼aP_cC t ^!x|I΄Lu,:@YSJ0!*I"Am7oҚCU{4;fR'hS$BdZ϶ܖ5P Q..֖4#*Mf:V ?Qďơ6jhPUs=Gn*8Q>E%0ߛ;z> B 6|۴z\ll|S|ךO oܵ.dlܛlkYMe7GO K7ULώM,כS ]౫e&]J8,-0VpfϊҬ-Bk$N‡A`ۋ/_Vy?\٧ і$y p3+'z'ExAKcendstream endobj 100 0 obj << /Type /Font /Subtype /Type1 /Encoding 208 0 R /FirstChar 2 /LastChar 121 /Widths 221 0 R /BaseFont /PGTWSU+URWPalladioL-Bold /FontDescriptor 98 0 R >> endobj 98 0 obj << /Ascent 708 /CapHeight 672 /Descent -266 /FontName /PGTWSU+URWPalladioL-Bold /ItalicAngle 0 /StemV 123 /XHeight 471 /FontBBox [-152 -301 1000 935] /Flags 4 /CharSet (/fi/parenleft/parenright/hyphen/period/one/two/three/four/five/six/seven/A/C/D/E/I/L/M/P/Q/R/S/T/U/a/b/c/d/e/f/g/h/i/k/l/m/n/o/p/r/s/t/u/v/w/x/y) /FontFile 99 0 R >> endobj 221 0 obj [611 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 333 333 0 0 0 333 250 0 0 500 500 500 500 500 500 500 0 0 0 0 0 0 0 0 0 778 0 722 833 611 0 0 0 389 0 0 611 1000 0 0 611 833 722 611 667 778 0 0 0 0 0 0 0 0 0 0 0 500 611 444 611 500 389 556 611 333 0 611 333 889 611 556 611 0 389 444 333 611 556 833 500 556 ] endobj 96 0 obj << /Length1 1638 /Length2 21999 /Length3 532 /Length 22918 /Filter /FlateDecode >> stream xڬweT]Ͷ%Npw;Cpww rK@pw ;twu{]Kkͪ{S*1ٛ%\YXZ66f {yFU{[c_3'<%do'nh@S ftŠgO˿B& P}q;\B?'K d))(Jh5R@; @d 휁s{'ͿS{;3пZsf% 08;MAӀ@@'[w`dlw.ٿCo__0e{ggS' oUeqt4vWmg_7oZd pz `rv1[/ ;dpZ;tOֽ?D/ g9<+ߚ.k[Ud,: πhgh06]'-';BK(I뒱?mA67+QYF$h r1?v ;3 WF `dea/>uKݿor+?̙tu5%;8ڻ{:?[Q7_{Yl<+R \+8<zfaHؙڛkۙ`?grtʈ휍ߵL]Mw@S%{SY.8yCz}=C% #y+Մ25N}y.:`Pw/ }i{ 6ڹ K2δb䷠tX4v&TT `ٝ\=`R<8 cu6<=J>~|쾆'ύwBp%(ll6.aez-b53QC %$=G MGJ1R?EzAt"QI|oY9?wZAtp4&9S!o+; lק=7XsVJovW91 H5DRWy}A\y92##mH7Eʓۇ|3m:Mg#ɹJQ3:O7J1Su$1Rqf hql>gE'L ]h_2f/I6 ] D'5PԛERh^4;c#<JSieW̒%C'A%>^__ŗrJLCDT}}kf۽;W wEǁl1͜ RUoD҆O93%[GHi& 1'c `Bvн-HQ6Kq4@z0=Kh6,=C_%` %n cc}2~P6AuHoL1C^59;s1u8w8Q)%q%l2$m_?ftTy&T.ۣqpGwt#rMDPex2d¾6ȿ лNVP !sPi&ǭڝԂbZTtڶZO)͚'SI ;UB{F$*GWf 55[V𸳦;JYJ0"$kҫ>2%I&SZ U^T,j׳:EVh?Fs|{Xc<,ʢKٿa5E튧u`F6A$eҤ;t1l:DVx%7^7ؾ ڤ–C9T<uxs7)"~V5֏c`H)ԂDܗoyItuG ]F/Bw4"qk1xx>c*hx:Cx3 9kE*Ɋ+E#5L09/4ၖidRzoq? *|Tk Aγj8 {gԐrǞ ^A$31\u!B.oCXJMN4 BJl~Ujɕ!QBOJaTEgH9&ζrY0ȮAK!UA @GPbUe"\c+ACͤ!h&tB2IԡDCFg)z]SvݺNM.̺u3) e-mh%ɣ UOR\!UWUuN1!_O9OUZw0*j w?aɆyXSИYᅝ\74K5.oV8% ?oc H$c1xw#TE:6Rp_^_%>ȕxSz [#Gwxי`OpL<@w[нN \J~;{54%Jm wka0.Awh^؆ݶeqS m)Le"ͧJ1%s!pկ9sg*1rM&6$"R3+tZEǢM/khnl:ij=EF=6(c9]n}#0)lcD|QX<5YywF+MUTdq `yJ8_l,Z<9?dά{'( z.X|Б:q6s)P+߶+ٯ bq/Rs} c1x E7eg Z4LU HQֈ6(\.[o҉!ctK:XGE Wg+P3d1/" ,E1]G&>Ў eK ~DQGq7YH>E+ٰ=<% ^k=`۵WAG}pn? 1žzʈ?CTeMv7 }O}6o/&f)dO\9ђPZ[iW཈Hx#~c~HؘaQ|TZau/f`-=1xyِ d#jS2/ԅv\LpȪ:b6 )D8J,T\W[kNpcTgt:%Hį xPet~XQIn0O_K"HZp6Vf1'%]aS38#7pᏮ 5B7˚N 9;"";^8x+~SEՑ7 Cˈ"4 0,Dzkr4asI ' ƻo/aUkǪrH>7?56!u%ZY%FE,ߟ񼠓[:ӻؼ} LV%d /;z+_x;[6L^l䋞o ҅rWvEo.@.G3εa8ǿ9 rn"J=00cb0b_hCψ5}s.uy'MGF%>M1_. dD5O(?HYj˷2Bԡ"S?E$E\l!{aGU I4 jSegұ垩Q?׆-JJԖcJQaLP~I?GU^a?jPE~n\f$WLG CAV| f{4 ?O # 3bָ)~:qq:MsGޯ5 -B$%e忋5iRedA}am4DB>A@}w9tzFx\;ZɒX+~6 0V")ZJŧpzpbDHlߪ5G}1#@j[Y_s]-E?@q̜W~`~U~ZO4Y~K_j'KȃPV.2X}/;$5Y'd X3"NvYWΔ0 }U ՆRQ62ȐݰXSw  v*+硍w&ƪT?Ϻ5LwقhBgJƱp>vb,ZC5)L5]ViKj6q̎{i+!Rogat28>I5T8N.-c͈XFOrt1:f!d5.fX"%CD;8@LA;kZ p~X(c9mC % "~ oG6VijI61uO;!|XZџA9-|b8Qdȇ=ߍ]sܭyFept 1D10U*A9saUzW 7Z7JL}UE1bYG-^V>M;'66Gc Ӄ6.o{xb4ڼEvJ6<|Si1I^q&(㵔tv?VFZc ۵f;Ϭ{L5uO6%{~;J,14Lp`܍Di&8 Hj$;>֠XshfjЈuђBLo)㦨}tn線_kn)Ļϩ~ LZ<)E@Uo=))1M tMBOCD( G{~;w%3 ./5*O:,@6pt3Dv#3BZSc]t;'~/;" ! i ]< [,).hoqB?*ܾwg5k YAB0k fyeݷwzSG4k5%V#Mb:3| Kiq5kzJ2#l ֠]HzEtmmN×cW/#)+l-xjա ,ZX s4VX&ǎX2' ֦:T:iֺv ab󵻯Nb0|;,d@;G0ta}:5ij #MX*<~>omq|aRn;ctU`櫹dW B_g#(4^& UAhRh&&HYF{ODZPlpӈ>H#VՁMD +9mM㫀M1] ?$WgZ$"j?gybA4L;MFHQiF>Vs3Rά"v5,*?w\TTh.ƕ5!Burn[ކ]/MxQ aW;+1M`+mp&R zz!$ 6xoP 2Lr4]YVGf9ƗZR9}Z}lNQnh(K_ {O7#RXԼ gQh[x? [y(Eg[a+Q!߬Q|`9@U;܉ {|P`/}~zNAYi I9): 4MROcEqsF0^oE'zA|5(l|BA)H{^C4TADl`6 aXg]&I^ F 5*n8G4#Czcp9(DSoDO$Ә Q+rhӂࠔ HͰڋPPXv"<F9WV ^?>U[_M~2r+Fo5NB 8lXj;Wr_|{UmM`dMfR`pz];l$|jdݬ@"*_I"Mu8Dk'޴{ް`:;4 5̜w2Tf*6H31gDPRLQ^\]Y _Z]D#52;GTS39.C6 PDC'j^j؁{k<򕹚SG$g}q9$QyODrPVĠ` J}E.uIBi=t J?-ec-k4ªl?*u4& qvN qu^P ;q?sU4YMחV6beh{UrQ`LzC\ A{j F]l'ijp Eo#bl1`m)G˓=[;?Y})ነ}m2%PoH@}"_⚣hNEIhYF0 \xJ%v`vVxES 600\M.QK@9ִ3'<(| K5j3/Fī c97\0l|e]4܃Ysis!isyNBx%{?41rkT糔^, ,-|dC7VՓ(|0ؒJ39v-gQCq6=u=-ɒ9;lXu.gSXp,-@@FaNU8,"цvUmv`r4m$rT:@&czṭr㈨(t^t)OA2#E H+1K[nAbII[vqd#a_aT^4s%Ȇ4 .T,.棕#]t9}]kPU>fvk;kFR:] 8ARc"gE,)+,]'i9eS&ٝ~wB3SIg9 2HᬈTЉD< n,XFؾf,3K~O5#M1!˥^h T@EPylj6^Q^kB̓v {.*(MawJ- y}Zizن_)R9YMIlm&,k(-Qĥ!|Fc*ur Khc Qc?tuLvCѮ9d2LʣZߊ`QD̪Ԛ1bs>h*A^\WuuMj3~PӧQhC- v͡6~O!Ԇ!e]nTy~K%7G(gN0uA 9Ԭm4O}V@ˇd4U ߍd`ۑp0sDpl>`S2CTNDQoF;2\CLhxۑ*"o \,N#Ӱ}[!- L!; ,]$8Ì_ <"] ػTP*yG:?x#$]\XUO,ƼhPˡ]DYn'bHpkYM?C֣B"}>SBR_L#cM\D^ TԝM y4|J4WGڹ0R22}1ʹEaA:^:~9n!"IFoHXPՆ 7q 1^ qo?af8ؖ%| u:#DQEEOJrLGD v<ލB+։,XsëDTkV:~`O#*)v+jugEYqX:Qǀ(DU ^CߘBig!W5O#܂Ӯihv4V lx5x gcذFetvwwz)z6C630dlZqXM[k{d|L' t+0ޓ B`K{L s0Mrg~%_s϶la=!MHE^iH7R vh]z+:WW}3/5nXlfBb pI@Bi c*cxУ<0M#Sqwz90ZeN,l}H34զbǔ!Wc$9Y2oUZioK~9TFA 2&ᳮQ7?-bun3x4^;-]}! '\m9(+C @A/f$ìD#rCAOI46N<`Q7aSŽOlgMB'~c4W|C^n{c^qAdAiB|n4=%jDЈ3'#N{#M>1_BV KD5!zzfM$:K\ :#,!TQ6 #k"דFmZS2Jp UxJ^Ea6"0FVrE[?e&EUlIq$B>͘awiQex&ME%vSe 'T">1Qn,x70@DqCL瓼(َñ.@[~I!&ى\s kܫ e e@gxq⠨dz=9 l^K~~x6b$sb!KGv7a7(6jEDz 89,#eP<{iiƒ9|][1GmO^Y+ZGtނۮipl hAGY2hQvS8 Υ|k:bpzt Igԥ31%@*Z ֘RvlHCdK~:>ͬ!S`b(J6?ا/ )U}.Q~捞TWjWmw`|[R&!E2ju~I&RK'4f bEcגc,278H6SYѮIceEM?6k?!@%_6 bоaNSC^̰zڔ0GSGrj3lOD3)Cւ}[/ RTOCp vo丛X̑'c,B}S>Y PWՓٽu]P5Nd)$ӅAqBkc7+rpY|B*)4E][QR^蕤s19DlSgYCL˖6HIURCc&i}tmCKƒI:"#/%k8}-7RW` ̺ ͢Ah7ec؃PNL1HwL\ڈ,?*$4Ktv '׃!mJz+} ;4d/@!eL[xA_h\zuX(Q|y:69&dI^.ݗ~p+|05,=nvVD2%%8EcL5Un?%f=_N:9ͩ&w)4ꨁڰ5[TnJw&R˸uV R6Aה:y@КVm<,LVx'_e9h;s)t躦lYQ]P (R}s =?ZӝLCnELgv`u͍b7Mr6!uAg&o,~e;r4o37ٯƋVۆԖ!͚6Wg6w>o&uh1"$X3m1JΝ\CZP\cmЪ C_J K'˲)A(Sz;l'R dC?d0ebbT&UB@+뾜[gO~wOrɗL[jڔPoE+0imZwVO7\Nbxn?Yfڡi4R_Bgt8}=d-ŷ~g>gI.+xnJc1РD?t4К[gG6e6:;!m V9D\41SC\}ԨvJZB=#yU\>iY Յ$ NiE_6zX.^LJ q 2簌G!hEm9+ZtMQ )"|kRfЩ+Rc w쬣ޖrG= 2IWlCZ ̦c1Dk 0$#/ӰOrjo/2gm߼Z+G6gƓ EB9 o.iplE2)r򏪍e9_]]Q<'z1; _v ?5턔އWwKDw!i:GB'X3φ!JCc'c^[]\w1CQ/[1?|G;(l8'Nksmf1dm6ۮMm7\u;s ӌu&ɟp1c3>Ӏ`82,|G&@riAu)CkWE69KLexU6miu;LT\S;&[ɕ$qfK^ݾBg]6rb#v-}۪\&Y.זa}'cݶA]/wZwsyz68c8q關o )^[?5RIH $a}@!>K7mۇ`Ço:fz4(ƈ c>_vD/;u zi&d=Cݶ?u=>2&:9qP[>XzR'rcvECZZ(6UG$7͔̤Pjmkb6r#B֝f3ZǼhө0'AZ[y@)h[CsiYC]@G ͟N)yϫ*MQppw?ӜGTr5tG>"$GPK,e0xS7MHg/ ˫>JY?-9O\ em^%a'^,Ⴞ˲AqNĂe,Lٯ(2(VOiLsv@9ڪ9Hu2b́?5Ms+.AbZKc0}h w=0$^:a4ry0'8@1mN $k1CE2g(rgT= Q]/Ѻ;Y,4 ꥳ44! Eq=iOD[ 9AC6 _g?#>x>?7P~%QEm=hⳜT|,/?.OJA:ı G( 9%vnwGc{_<Ӎ}eړL8.G$/0ܩ3==Gڴ(+s4L.0`U|oR%[oTPϤ3KBqÐS7 yuBau/ [_۲6?kH`ʔX4ZxDݞ^47h0*0MRԱ4үc8)=T&#|Ueb%%&YH{m`X~0,RKɏ@4E)t,7( 6Yu("IL6@y6PbE]:>I˒&wBy)Ud^IB9-dqɳizFP#i*ڎDu9)I7%\DpvGhz1G| 3 (QƐVY2j1g]R3tӽ`S$*,=Wً0݇W'?QY?ȍh|Z :))6 e =GBi-DۥFm:"_Ok6®G҅I[|L/XNq??S?êo; s^ecN~}33f^8wY~*bVi= amW67$vQ9)vB]K2L))]G>¢La!XFfmU .D-}\9gSg_ Wu/48pg[n:/]kq2v} 6z .EN܇Ee|~8k;ݷ0f*6{-|lF cxI8>fa'%9/% ~Er <s6*묟=a DUoPynb@\A}XAq׷čp֬kWR駛sEԎw`)A3Z+>GaNk!_?tei E B]  XїnW*]z@+~E@0Esع"IE&֠aƂD8,CFiE櫦H/؍IZ17#J?Q::5kYT&1!4viBA=YsQnO8sBɸ0p8@&,tD֙` e5Z9Y5)lP5ѕncY<_VG*dDpiE=_Lҝ\^x(kGﭗHW' q0TDtlJDAZY>nHcZL/ -7$1v,KF/"R7z򕸺??1 Lyu)=+wYCjN:\!<[\8M '*m >5֠ΧZ\n[X.ڞ.L00i%8Ma`=,d(Hu*sEYXSX9-'h=?TXrʷuM%SYDMZGύ 3Z럓= }*iH986{Uzfﺿ%cA ǖ 3Ǭ:;;n^ :E%OQa |[~a7=+4l%\7ES(^6q .5ǾBG@O) H@>- G#>%k/;=tCxU>igOxj6A72iKfL܊H;Tt_,.*#vCDDOby'#Fw$A9[n&vsw( nvzIFP}+rʭ8Ny% vEkshi2&؏V[տɞw Y~>Z>r0w3qUM#2Pr΀K9(gDޟlC/jU20D(S84sZH9 b )~d1F#Elz" Q :… ləc#Z>CΏRL{ں`"|09̅@"S;"#kiĸHI lg_ &dT$VVUsMTW"71 EkOԩNH䷉z2 U8j~h4M+! V4-̡P#xÁiTsX'Z"8w1k/AVv <=~]M3pݼz3zF!w1䏕j/^| ɵNGY&)]Սcto`h_5 ,亇;cR*ܶʕ*y uMO( ̶ &Bjvw4Q,Wc$ ejyN|r}ke֯d=?tҾpvn yfϫEAFd/S R,մ_ήDޖX|<>1K !tnLG/8z},4NE2MLCOw?ii 9y 1|u =Gܾc\+SC6wl\I˪8 MN.YYܚTRʵa9>cӟ~ZT5`G*bl ]j({<9cr~doľ+ko#j^H \j1\#0~8%\C4@/*2NCK@9eudKDuFΉ3TB艬_whcNӴ).1!BF;XLLR,b5.Ȱbj*j_O?tzMf*SuޛG+*;1j~'1ejw1='>in/еdq cmvTfh] W>Ը zK3>9pYDz}GDury`#_==ȁjS){u9^+fɌܧ /"9Q,>P)ԁmS\Ty&C|_Oޛ@ YsP7!ueJhDLեSﴡsMiG OWmV $;A";o"Imjq=c~EԑCNl1Ŕ#'d:&> endobj 95 0 obj << /Ascent 715 /CapHeight 680 /Descent -282 /FontName /KSZZVF+URWPalladioL-Roma /ItalicAngle 0 /StemV 84 /XHeight 469 /FontBBox [-166 -283 1021 943] /Flags 4 /CharSet (/fi/quoteright/parenleft/parenright/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/R/S/T/U/V/W/Z/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/quotedblleft/quotedblright/emdash/dieresis) /FontFile 96 0 R >> endobj 222 0 obj [605 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 278 333 333 0 0 250 333 250 606 500 500 500 500 500 500 500 500 500 500 250 250 0 0 0 0 0 778 611 709 774 611 556 763 832 337 333 726 611 946 831 786 604 0 668 525 613 778 722 1000 0 0 667 0 0 0 0 0 278 500 553 444 611 479 333 556 582 291 234 556 291 883 582 546 601 560 395 424 326 603 565 834 516 556 500 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 500 500 0 0 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 333 ] endobj 109 0 obj << /Type /Pages /Count 6 /Parent 223 0 R /Kids [90 0 R 111 0 R 118 0 R 124 0 R 137 0 R 145 0 R] >> endobj 157 0 obj << /Type /Pages /Count 6 /Parent 223 0 R /Kids [152 0 R 159 0 R 177 0 R 184 0 R 189 0 R 198 0 R] >> endobj 207 0 obj << /Type /Pages /Count 1 /Parent 223 0 R /Kids [203 0 R] >> endobj 223 0 obj << /Type /Pages /Count 13 /Kids [109 0 R 157 0 R 207 0 R] >> endobj 224 0 obj << /Type /Outlines /First 7 0 R /Last 87 0 R /Count 7 >> endobj 87 0 obj << /Title 88 0 R /A 85 0 R /Parent 224 0 R /Prev 83 0 R >> endobj 83 0 obj << /Title 84 0 R /A 81 0 R /Parent 224 0 R /Prev 51 0 R /Next 87 0 R >> endobj 79 0 obj << /Title 80 0 R /A 77 0 R /Parent 51 0 R /Prev 55 0 R >> endobj 75 0 obj << /Title 76 0 R /A 73 0 R /Parent 55 0 R /Prev 71 0 R >> endobj 71 0 obj << /Title 72 0 R /A 69 0 R /Parent 55 0 R /Prev 67 0 R /Next 75 0 R >> endobj 67 0 obj << /Title 68 0 R /A 65 0 R /Parent 55 0 R /Prev 63 0 R /Next 71 0 R >> endobj 63 0 obj << /Title 64 0 R /A 61 0 R /Parent 55 0 R /Prev 59 0 R /Next 67 0 R >> endobj 59 0 obj << /Title 60 0 R /A 57 0 R /Parent 55 0 R /Next 63 0 R >> endobj 55 0 obj << /Title 56 0 R /A 53 0 R /Parent 51 0 R /Next 79 0 R /First 59 0 R /Last 75 0 R /Count -5 >> endobj 51 0 obj << /Title 52 0 R /A 49 0 R /Parent 224 0 R /Prev 47 0 R /Next 83 0 R /First 55 0 R /Last 79 0 R /Count -2 >> endobj 47 0 obj << /Title 48 0 R /A 45 0 R /Parent 224 0 R /Prev 27 0 R /Next 51 0 R >> endobj 43 0 obj << /Title 44 0 R /A 41 0 R /Parent 39 0 R >> endobj 39 0 obj << /Title 40 0 R /A 37 0 R /Parent 27 0 R /Prev 31 0 R /First 43 0 R /Last 43 0 R /Count -1 >> endobj 35 0 obj << /Title 36 0 R /A 33 0 R /Parent 31 0 R >> endobj 31 0 obj << /Title 32 0 R /A 29 0 R /Parent 27 0 R /Next 39 0 R /First 35 0 R /Last 35 0 R /Count -1 >> endobj 27 0 obj << /Title 28 0 R /A 25 0 R /Parent 224 0 R /Prev 15 0 R /Next 47 0 R /First 31 0 R /Last 39 0 R /Count -2 >> endobj 23 0 obj << /Title 24 0 R /A 21 0 R /Parent 15 0 R /Prev 19 0 R >> endobj 19 0 obj << /Title 20 0 R /A 17 0 R /Parent 15 0 R /Next 23 0 R >> endobj 15 0 obj << /Title 16 0 R /A 13 0 R /Parent 224 0 R /Prev 7 0 R /Next 27 0 R /First 19 0 R /Last 23 0 R /Count -2 >> endobj 11 0 obj << /Title 12 0 R /A 9 0 R /Parent 7 0 R >> endobj 7 0 obj << /Title 8 0 R /A 5 0 R /Parent 224 0 R /Next 15 0 R /First 11 0 R /Last 11 0 R /Count -1 >> endobj 225 0 obj << /Names [(Doc-Start) 94 0 R (Hfootnote.1) 166 0 R (Item.1) 121 0 R (Item.10) 196 0 R (Item.11) 201 0 R (Item.12) 206 0 R (Item.2) 122 0 R (Item.3) 162 0 R (Item.4) 163 0 R (Item.5) 164 0 R (Item.6) 192 0 R (Item.7) 193 0 R (Item.8) 194 0 R (Item.9) 195 0 R (page.1) 93 0 R (page.10) 186 0 R (page.11) 191 0 R (page.12) 200 0 R (page.13) 205 0 R (page.2) 113 0 R (page.3) 120 0 R (page.4) 126 0 R (page.5) 139 0 R (page.6) 147 0 R (page.7) 154 0 R (page.8) 161 0 R (page.9) 179 0 R (section*.1) 135 0 R (section*.2) 140 0 R (section.1) 6 0 R (section.2) 14 0 R (section.3) 26 0 R (section.4) 46 0 R (section.5) 50 0 R (section.6) 82 0 R (section.7) 86 0 R (subsection.1.1) 10 0 R (subsection.2.1) 18 0 R (subsection.2.2) 22 0 R (subsection.3.1) 30 0 R (subsection.3.2) 38 0 R (subsection.5.1) 54 0 R (subsection.5.2) 78 0 R (subsubsection.3.1.1) 34 0 R (subsubsection.3.2.1) 42 0 R (subsubsection.5.1.1) 58 0 R (subsubsection.5.1.2) 62 0 R (subsubsection.5.1.3) 66 0 R (subsubsection.5.1.4) 70 0 R (subsubsection.5.1.5) 74 0 R] /Limits [(Doc-Start) (subsubsection.5.1.5)] >> endobj 226 0 obj << /Kids [225 0 R] >> endobj 227 0 obj << /Dests 226 0 R >> endobj 228 0 obj << /Type /Catalog /Pages 223 0 R /Outlines 224 0 R /Names 227 0 R /PageMode /UseOutlines /URI<> /ViewerPreferences<<>> /OpenAction 89 0 R /PTEX.Fullbanner (This is pdfTeX, Version 3.14159-1.10b) >> endobj 229 0 obj << /Author()/Title()/Subject()/Creator(LaTeX with hyperref package)/Producer(pdfTeX-1.10b)/Keywords() /CreationDate (D:20050820174800) >> endobj xref 0 230 0000000001 65535 f 0000000002 00000 f 0000000003 00000 f 0000000004 00000 f 0000000104 00000 f 0000000009 00000 n 0000003865 00000 n 0000129268 00000 n 0000000054 00000 n 0000000084 00000 n 0000003919 00000 n 0000129209 00000 n 0000000134 00000 n 0000000186 00000 n 0000006316 00000 n 0000129085 00000 n 0000000232 00000 n 0000000272 00000 n 0000006372 00000 n 0000129011 00000 n 0000000323 00000 n 0000000362 00000 n 0000006428 00000 n 0000128937 00000 n 0000000413 00000 n 0000000446 00000 n 0000008968 00000 n 0000128812 00000 n 0000000492 00000 n 0000000546 00000 n 0000009024 00000 n 0000128701 00000 n 0000000597 00000 n 0000000623 00000 n 0000015629 00000 n 0000128640 00000 n 0000000679 00000 n 0000000716 00000 n 0000018582 00000 n 0000128529 00000 n 0000000767 00000 n 0000000808 00000 n 0000018638 00000 n 0000128468 00000 n 0000000864 00000 n 0000000899 00000 n 0000018693 00000 n 0000128380 00000 n 0000000945 00000 n 0000000978 00000 n 0000022054 00000 n 0000128255 00000 n 0000001024 00000 n 0000001061 00000 n 0000025309 00000 n 0000128144 00000 n 0000001112 00000 n 0000001151 00000 n 0000025365 00000 n 0000128070 00000 n 0000001207 00000 n 0000001244 00000 n 0000027947 00000 n 0000127983 00000 n 0000001300 00000 n 0000001339 00000 n 0000030344 00000 n 0000127896 00000 n 0000001395 00000 n 0000001421 00000 n 0000030400 00000 n 0000127809 00000 n 0000001477 00000 n 0000001518 00000 n 0000032857 00000 n 0000127735 00000 n 0000001574 00000 n 0000001606 00000 n 0000035518 00000 n 0000127661 00000 n 0000001657 00000 n 0000001727 00000 n 0000035574 00000 n 0000127573 00000 n 0000001773 00000 n 0000001810 00000 n 0000036802 00000 n 0000127498 00000 n 0000001856 00000 n 0000001890 00000 n 0000003639 00000 n 0000003974 00000 n 0000001940 00000 n 0000003755 00000 n 0000003810 00000 n 0000126048 00000 n 0000102839 00000 n 0000125878 00000 n 0000102131 00000 n 0000083235 00000 n 0000101960 00000 n 0000082570 00000 n 0000068955 00000 n 0000082398 00000 n 0000000114 00000 f 0000068867 00000 n 0000068403 00000 n 0000066583 00000 n 0000068241 00000 n 0000127036 00000 n 0000006484 00000 n 0000005968 00000 n 0000004096 00000 n 0000006259 00000 n 0000000000 00000 f 0000064833 00000 n 0000006107 00000 n 0000009080 00000 n 0000008679 00000 n 0000006620 00000 n 0000008798 00000 n 0000008855 00000 n 0000008912 00000 n 0000012140 00000 n 0000011626 00000 n 0000009216 00000 n 0000012083 00000 n 0000011773 00000 n 0000011930 00000 n 0000064381 00000 n 0000062171 00000 n 0000064218 00000 n 0000061931 00000 n 0000059682 00000 n 0000061772 00000 n 0000015685 00000 n 0000015799 00000 n 0000014895 00000 n 0000012301 00000 n 0000015572 00000 n 0000015742 00000 n 0000015050 00000 n 0000015226 00000 n 0000015396 00000 n 0000018749 00000 n 0000017896 00000 n 0000015922 00000 n 0000018525 00000 n 0000018051 00000 n 0000018213 00000 n 0000018374 00000 n 0000022110 00000 n 0000021545 00000 n 0000018872 00000 n 0000021997 00000 n 0000021692 00000 n 0000021845 00000 n 0000127152 00000 n 0000025482 00000 n 0000024788 00000 n 0000022220 00000 n 0000025081 00000 n 0000025138 00000 n 0000025195 00000 n 0000025252 00000 n 0000024927 00000 n 0000025421 00000 n 0000059389 00000 n 0000057210 00000 n 0000059229 00000 n 0000056964 00000 n 0000054814 00000 n 0000056801 00000 n 0000053589 00000 n 0000051536 00000 n 0000053430 00000 n 0000028003 00000 n 0000027771 00000 n 0000025642 00000 n 0000027890 00000 n 0000050112 00000 n 0000038779 00000 n 0000049935 00000 n 0000030456 00000 n 0000029997 00000 n 0000028126 00000 n 0000030287 00000 n 0000030136 00000 n 0000032913 00000 n 0000032396 00000 n 0000030566 00000 n 0000032515 00000 n 0000032572 00000 n 0000032629 00000 n 0000032686 00000 n 0000032743 00000 n 0000032800 00000 n 0000035687 00000 n 0000035342 00000 n 0000033023 00000 n 0000035461 00000 n 0000035630 00000 n 0000036858 00000 n 0000036569 00000 n 0000035797 00000 n 0000036688 00000 n 0000036745 00000 n 0000127269 00000 n 0000036968 00000 n 0000050378 00000 n 0000050590 00000 n 0000053791 00000 n 0000053819 00000 n 0000057166 00000 n 0000059612 00000 n 0000062139 00000 n 0000064681 00000 n 0000064645 00000 n 0000064926 00000 n 0000068629 00000 n 0000082905 00000 n 0000102482 00000 n 0000126532 00000 n 0000127346 00000 n 0000127424 00000 n 0000129377 00000 n 0000130470 00000 n 0000130509 00000 n 0000130547 00000 n 0000130773 00000 n trailer << /Size 230 /Root 228 0 R /Info 229 0 R >> startxref 130928 %%EOF scsh-install-lib-1.3.0/doc/install-lib.tex0000644000076500000240000010201610301650125020720 0ustar michelschinzstaff%% $Id: install-lib.tex,v 1.5 2005/08/20 15:46:29 michel-schinz Exp $ \documentclass[a4paper,12pt]{article} \usepackage[latin1]{inputenc} \usepackage{a4wide, palatino, url, hyperref} \newcommand{\file}{\begingroup \urlstyle{tt}\Url} \newcommand{\envvar}[1]{\texttt{#1}} \newcommand{\cloption}[1]{\texttt{#1}} \newcommand{\package}[1]{\texttt{#1}} \newcommand{\layout}[1]{\texttt{#1}} \newcommand{\location}[1]{\texttt{#1}} \newcommand{\ident}[1]{\texttt{#1}} \newcommand{\phase}[1]{\texttt{#1}} \newcommand{\define}[3]{% \noindent% (\texttt{#1} \textit{#2})\hfill\textit{(#3)}\\[0.5em]% } \newcommand{\definep}[2]{\define{#1}{#2}{procedure}} \newcommand{\defines}[2]{\define{#1}{#2}{syntax}} \newcommand{\param}[1]{\emph{#1}} \newenvironment{rationale}% {\begin{quotation}\noindent\textbf{Rationale}}% {\end{quotation}} \newenvironment{example}% {\begin{quotation}\noindent\textbf{Example}}% {\end{quotation}} \begin{document} \title{A proposal for scsh packages} \author{Michel Schinz} \maketitle \section{Introduction} \label{sec:introduction} The aim of the following proposal is to define a standard for the packaging, distribution, installation, use and removal of libraries for scsh. Such packaged libraries are called \emph{scsh packages} or simply \emph{packages} below. This proposal attempts to cover both libraries containing only Scheme code and libraries containing additional C code. It does not try to cover applications written in scsh, which are currently considered to be outside of its scope. \subsection{Package identification and naming} Packages are identified by a globally-unique name. This name should start with an ASCII letter (a-z or A-Z) and should consist only of ASCII letters, digits or hyphens `\verb|-|'. Package names are case-sensitive, but there should not be two packages with names which differ only by their capitalisation. \begin{rationale} This restriction on package names ensures that they can be used to name directories on current operating systems. \end{rationale} Several versions of a given package can exist. A version is identified by a sequence of non-negative integers. Versions are ordered lexicographically. A version has a printed representation which is obtained by separating (the printed representation of) its components by dots. For example, the printed representation of a version composed of the integer 1 followed by the integer 2 is the string \texttt{1.2}. Below, versions are usually represented using their printed representation for simplicity, but it is important to keep in mind that versions are sequences of integers, not strings. A specific version of a package is therefore identified by a name and a version. The \emph{full name} of a version of a package is obtained by concatenating: \begin{itemize} \item the name of the package, \item a hyphen `\texttt{-}', \item the printed representation of the version. \end{itemize} In what follows, the term \emph{package} is often used to designate a specific version of a package, but this should be clear from the context. \section{Distributing packages} Packages are usually distributed as a stand-alone archive containing the code and documentation to install, as well as a file describing the installation procedure. However, it is also possible to distribute the scsh-specific installation procedure separately from the main code and documentation. This is typically useful to turn general Scheme libraries into scsh packages. \subsection{Stand-alone packages} \label{sec:stand-alone-packages} Stand-alone packages are distributed in a single \texttt{tar} archive, which can optionally be compressed by \texttt{gzip} or \texttt{bzip2}. The name of the archive is composed by appending: \begin{itemize} \item the full name of the package, \item the string \texttt{.tar} indicating that it's a \texttt{tar} archive, \item either the string \texttt{.gz} if the archive is compressed using \texttt{gzip}, or the string \texttt{.bz2} if the archive is compressed using \texttt{bzip2}, or nothing if the archive is not compressed. \end{itemize} The archive of a stand-alone package is organised so that it contains one top-level directory whose name is the full name of the package. This directory is called the \emph{package unpacking directory}. All the files belonging to the package are stored below it. The unpacking directory contains at least the following files: \begin{description} \item[\file{pkg-def.scm}] a Scheme file containing the installation procedure for the package (see ~\ref{sec:authoring-packages}), \item[\file{README}] a textual file containing a short description of the package, \item[\file{COPYING}] a textual file containing the license of the package. \end{description} \subsection{Split packages} \label{sec:split-packages} Split packages are distributed as two separate archives. The first one, called the \emph{upstream archive}, contains the code and documentation of the package. The second one, called the \emph{downstream archive}, contains the scsh-specific installation procedure for the package. Ideally, the upstream archive should follow the rules laid out in the previous section for stand-alone archives. Most of the time, however, the author of the upstream package has no reason to be aware of the current policy, or simply to adhere to it. The name and layout of the downstream archive should therefore mirror the one of the upstream archive, as follows: \begin{enumerate} \item the name of the downstream archive is composed by appending: \begin{itemize} \item the string \texttt{pkg\_} (the three letters `p', `k' and `g' followed by an underscore character), \item the name of the upstream archive, including its version but excluding extensions indicating the archive type and/or compression method, \item an underscore character, \item a single number indicating the version of the downstream archive, \item the string \texttt{.tar} indicating that it's a \texttt{tar} archive, \item either the string \texttt{.gz} if the archive is compressed using \texttt{gzip}, or the string \texttt{.bz2} if the archive is compressed using \texttt{bzip2}, or nothing if the archive is not compressed. \end{itemize} \item the downstream archive should contain at least the file \file{pkg-def.scm} placed in a directory with the same name as the ``main'' directory of the upstream archive. \end{enumerate} These conventions ensure that split packages behave almost like stand-alone packages after the two archives have been unpacked at the same location. % TODO give an example of a split package \section{Downloading and installing packages} A package can be installed on a target machine by downloading its archive, expanding it and finally running the installation script located in the unpacking directory. \subsection{Layouts} The installation script installs files according to some given \emph{layout}. A layout maps abstract \emph{locations} to concrete directories on the target machine. For example, a layout could map the abstract location \location{doc}, where documentation is stored, to the directory \file{/usr/local/share/doc/my_package}. Currently, the following abstract locations are defined: \begin{description} \item[\location{base}] The ``base'' location of a package, where the package loading script \file{load.scm} resides. \item[\location{active}] Location containing a symbolic link, with the same name as the package (excluding the version), pointing to the base location of the package. This link is used to designate the \emph{active} version of a package\,---\,the one to load when a package is requested by giving only its name, without an explicit version. \item[\location{scheme}] Location containing all Scheme code. If the package comes with some examples showing its usage, they are put in a sub-directory called \file{examples} of this location. \item[\location{lib}] Location containing platform-dependent files, like shared libraries. This location contains one sub-directory per platform for which packages have been installed, and nothing else. \item[\location{doc}] Location containing all the package documentation. This location contains one or more sub-directories, one per format in which the documentation is available. The contents of these sub-directories is standardised as follows, to make it easy for users to find the document they need: \begin{description} \item[\file{html}] Directory containing the HTML documentation of the package, if any; this directory should at least contain one file called \file{index.html} serving as an entry point to the documentation. \item[\file{pdf}] Directory containing the PDF documentation of the package, if any; this directory should contain at least one file called \file{.pdf} where \file{} is the name of the package. \item[\file{ps}] Directory containing the PostScript documentation of the package, if any; this directory should contain at least one file called \file{.ps} where \file{} is the name of the package. \item[\file{text}] Directory containing the raw textual documentation of the package, if any. \end{description} \item[\location{misc-shared}] Location containing miscellaneous data which does not belong to any directory above, and which is platform-independent. \end{description} The directories to which a layout maps these abstract locations are not absolute directories, but rather relative ones. They are relative to a \emph{prefix}, specified at installation time using the \cloption{--prefix} option, as explained in section \ref{sec:inst-proc}. \begin{example} Let's imagine that a user is installing version 1.2 of a package called \package{foo}. This package contains a file called \file{COPYING} which has to be installed in sub-directory \file{license} of the \location{doc} location. If the user chooses to use the default layout, which maps \location{doc} to directory \file{//doc} (see ~\ref{sec:scsh-layout}), and specifies \file{/usr/local/share/scsh/modules} as a prefix, then the \file{COPYING} file will end up in: \[ \begin{small} \underbrace{\mbox{\texttt{/usr/local/share/scsh/modules/}}}_{1}% \underbrace{\mbox{\texttt{0.6/foo-1.2/doc/}}}_{2}% \underbrace{\mbox{\texttt{license/COPYING}}}_{3} \end{small} \] (provided the user is running scsh v0.6.x) Part 1 is the prefix, part 2 is the layout's mapping for the \location{doc} location, and part 3 is the file name relative to the location. \end{example} \subsubsection{Predefined layouts} \label{sec:predefined-layouts} Every installation script comes with a set of predefined layouts which serve different aims. They are described below The directories to which these layouts map locations often have a name which includes the current version of scsh and/or the full name of the package. In what follows, the notation \file{} represents the printed representation of the first two components of scsh's version (e.g. \file{0.6} for scsh v0.6.x). The notation \file{} represents the \emph{full} name of the package being installed. \paragraph{The \layout{scsh} layout} \label{sec:scsh-layout} The \layout{scsh} layout is the default layout. It maps all locations to sub-directories of a single directory, called the package installation directory, which contains nothing but the files of the package being installed. Its name is simply the full name of the package in question, and it resides in the \file{prefix} directory. The \layout{scsh} layout maps locations as given in the following table: \begin{center} \begin{tabular}{|l|l|} \hline \textbf{Location} & \textbf{Directory (relative to prefix)} \\ \hline \location{base} & \file{/} \\ \location{active} & \file{} \\ \location{scheme} & \file{//scheme} \\ \location{lib} & \file{//lib} \\ \location{doc} & \file{//doc} \\ \location{misc-shared} & \file{/} \\ \hline \end{tabular} \end{center} This layout is well suited for installations performed without the assistance of an additional package manager, because it makes many common operations easy. For example, finding to which package a file belongs is trivial, as is the removal of an installed package. \paragraph{The \layout{fhs} layout} \label{sec:fhs-layout} The \layout{fhs} layout maps locations according to the File Hierarchy Standard (FHS, see \href{http://www.pathname.com/fhs/}% {http://www.pathname.com/fhs/}), as follows: \begin{center} \begin{tabular}{|l|l|} \hline \textbf{Location} & \textbf{Directory (relative to prefix)} \\ \hline \layout{base} & \file{share/scsh-/modules/} \\ \layout{active} & \file{share/scsh-/modules} \\ \layout{scheme} & \file{share/scsh-/modules//scheme} \\ \layout{lib} & \file{lib/scsh-/modules/} \\ \layout{doc} & \file{share/doc/scsh-/} \\ \layout{misc-shared} & \file{share/scsh-/modules/} \\ \hline \end{tabular} \end{center} The main advantage of this layout is that it adheres to the FHS standard, and is therefore compatible with several packaging policies, like \href{http://www.debian.org/}{Debian}'s, \href{http://fink.sourceforge.net/}{Fink}'s and others. Its main drawback is that files belonging to a given package are scattered, and therefore hard to find when removing or upgrading a package. Its use should therefore be considered only if third-party tools are available to track files belonging to a package. %% TODO \subsection{File permissions} \subsection{Installation procedure} \label{sec:inst-proc} Packages are installed using the \file{scsh-install-pkg} script, which is part of the installation library. This script must be given the name of the prefix using the \cloption{--prefix} option. It also accepts the following options: \begin{center} \begin{tabular}{lp{.6\textwidth}} \cloption{--layout} name & Specifies the layout to use (see ~\ref{sec:predefined-layouts}). \\ \cloption{--verbose} & Print messages about what is being done. \\ \cloption{--dry-run} & Print what actions would be performed to install the package, but do not perform them. \\ \cloption{--inactive} & Do not activate package after installing it. \\ \cloption{--non-shared-only} & Only install platform-dependent files, if any. \\ \cloption{--force} & Overwrite existing files during installation. \\ \cloption{--no-user-defaults} & Don't read user defaults in \file{.scsh-pkg-defaults.scm} (see ~\ref{sec:user-preferences}). \\ \end{tabular} \end{center} A few, more advanced options exist and are documented in section \ref{sec:packaging-packages}. \subsubsection{User preferences} \label{sec:user-preferences} Users can store default values for the options passed to the installation script by storing them in a file called \file{.scsh-pkg-defaults.scm} residing in their home directory. This file must contain exactly one Scheme expression whose value is an association list. The keys of this list, which must be symbols, identify options and the values specify the default value for these options. The contents of this file is implicitly quasi-quoted. The values stored in this file override the default values of the options, but they are in turn overridden by the values specified on the command line of the installation script. Furthermore, it is possible to ask for this file to be completely ignored by passing the \cloption{--no-user-defaults} option to the installation script. \begin{example} A \file{.scsh-pkg-defaults.scm} file containing the following: \begin{verbatim} ;; Default values for scsh packages installation ((layout . "fhs") (prefix . "/usr/local/share/scsh/modules") (verbose . #t)) \end{verbatim} specifies default values for the \cloption{--layout}, \cloption{--prefix} and \cloption{--verbose} options. \end{example} \section{Using packages} To use a package, its \emph{loading script} must be loaded in Scheme~48's exec package. The loading script for a package is a file written in the Scheme 48 exec language, whose name is \file{load.scm} and which resides in the \location{base} location. To load this file, one typically uses scsh's \cloption{-lel} option along with a properly defined \envvar{SCSH\_LIB\_DIRS} environment variable. Scsh has a list of directories, called the library directories, in which it looks for files to load when the options \cloption{-ll} or \cloption{-lel} are used. This list can be given a default value during scsh's configuration, and this value can be overridden by setting the environment variable \envvar{SCSH\_LIB\_DIRS} before running scsh. In order for scsh to find the package loading scripts, one must make sure that scsh's library search path contains the names of all \location{active} locations which containing packages. The names of these directories should not end with a slash `\verb|/|', as this forces scsh to search them recursively. This could \emph{drastically} slow down scsh when looking for packages. \begin{example} Let's imagine a machine on which the system administrator installs scsh packages according to the \layout{fhs} layout in prefix directory \file{/usr/local}. The \location{active} location for these packages corresponds to the directory \file{/usr/local/share/scsh-0.6/modules}, according to section \ref{sec:fhs-layout}. Let's also imagine that there is a user called \texttt{john} on this machine, who installs additional scsh packages for himself in his home directory, using \file{/home/john/scsh} as a prefix. To ease their management, he uses the \layout{scsh} layout. The \location{active} location for these packages corresponds to the directory \file{/home/john/scsh/0.6}, according to section \ref{sec:scsh-layout}. In order to be able to use scsh packages installed both by the administrator and by himself, user \texttt{john} needs to put both active directories in his \envvar{SCSH\_LIB\_DIRS} environment variable. The value of this variable will therefore be: \begin{small} \begin{verbatim} "/usr/local/share/scsh-0.6/modules" "/home/john/scsh/0.6" \end{verbatim} \end{small} Now, in order to use packages \package{foo} and \package{bar} in one of his script, user \texttt{john} just needs to load their loading script using the \cloption{-lel} option when invoking scsh, as follows: \begin{verbatim} -lel foo/load.scm -lel bar/load.scm \end{verbatim} \end{example} \section{Authoring packages} \label{sec:authoring-packages} Once the Scheme and/or C code for a package has been written, the last step in turning it into a standard package as defined by this proposal is to write the installation script. This script could be written fully by the package author, but in order to simplify this task a small scsh installation framework is provided. This framework must be present on the host system before a scsh package can be installed. As explained above, when the \file{scsh-install-pkg} script is invoked, it launches scsh on the main function of the installation library, which does the following: \begin{enumerate} \item parse the command line arguments (e.g the \cloption{--prefix} option), \item load the package definition file, a (Scheme) file called \file{pkg-def.scm}, which is supplied by the package author and which contains one or several package definition statements, and \item install the packages which were defined in the previous step. \end{enumerate} Most package definition files should contain a single package definition, but the ability to define several packages in one file can sometimes be useful. The main job of the package author is therefore to write the package definition file, \file{pkg-def.scm}. This file is mostly composed of a package definition statement, which specifies the name, version and installation code for the package. The package definition statement is expressed using the \ident{define-package} form, documented in the next section. \subsection{Installation library} \label{sec:install-library} \subsubsection{Package definition} \defines{define-package}{name version extension body ...}% Define a package to be installed. \param{Name} (a string) is the package name, \param{version} (a list of integers) is its version, \param{extensions} is a list of extensions (see below), and \param{body} is the list of statements to be evaluated in order to install the package. The installation statements typically use functions of the installation library in order to install files in their target location. The available functions are presented below. \param{Extensions} consists in a list of lists, each one starting with a symbol identifying the extension, possibly followed by extension-specific parameters. It is used to specify various parameters, which are usually optional. Currently, the following extensions are defined: \begin{description} \item[install-lib-version] specifies the version of the installation library that this package definition requires. The version is specified as a list composed of \emph{exactly two} integers, giving the major and minor version number of the library. Before installing a package, this version requirement is checked and installation aborts if the installation library does not satisfy it.% \footnote{Version $(i_1\,i_2)$ of the installation library satisfies a requirement $(r_1\,r_2)$ if and only if both major numbers are equal, and the minor number of the installation library is greater or equal to the minor requirement. In other words, iff $i_1 = r_1$ and $i_2 \ge r_2$.}% It is strongly recommended that package authors provide this information, as it makes it possible to provide helpful error messages to users. \item[options] enables the script to define additional command-line options. It accepts nine parameters in total, with the last three being optional. The description of these parameters follows, in the order in which they should appear: \begin{description} \item[\param{name}] (a symbol) is the name of the option, without the initial double hyphen (\verb|--|), \item[\param{help-text}] (a string) describes the option for the user, \item[\param{arg-help-text}] (a string) describes the option's argument (if any) for the user, \item[\param{required-arg?}] (a boolean) says whether this option requires an argument or not, \item[\param{optional-arg?}] (a boolean) says whether this option's argument can be omitted or not, \item[\param{default}] (anything) is the default value for the option, \item[\param{parser}] (a function from string to anything) parses the option, i.e. turns its string representation into its internal value, \item[\param{unparser}] (a function from anything to string) turns the internal representation of the option into a string, \item[\param{transformer}] is a function taking the current value of the option, the value given by the user and returning its new value. \end{description} By default, \param{parser} and \param{unparser} are the identity function, and \param{transformer} is a function which takes two arguments and returns the second (i.e. the current value of the option is simply replaced by the one given). \end{description} \subsubsection{Content installation} \definep{install-file}{file location [target-dir]}% Install the given \param{file} in the sub-directory \param{target-dir} (which must be a relative directory) of the given \param{location}. \param{Target-dir} is \file{.} by default. If the directory in which the file is about to be installed does not exist, it is created along with all its parents, as needed. If \param{file} is a string, then the installed file will have the same name as the original one. If \param{file} is a pair, then its first element specifies the name of the source file, and its second element the name it will have once installed. The second element must be a simple file name, without any directory part. \vspace{1em} \definep{install-files}{file-list location [target-dir]}% Like \ident{install-file} but for several files, which are specified as a list. Each element in the list can be either a simple string or a pair, as explained above. \vspace{1em} \definep{install-directory}{directory location [target-dir]}% Install the given \param{directory} and all its contents, including sub-directories, in sub-directory \param{target-dir} of \param{location}. This is similar to what \param{install-file} does, but for complete hierarchies. Notice that \param{directory} will be installed as a sub-directory of \param{target-dir}. \vspace{1em} \definep{install-directories}{dir-list location [target-dir]}% Install several directories in one go. \vspace{1em} \definep{install-directory-contents}{directory location [target-dir]}% Install the contents of the given \param{directory} in sub-directory \param{target} of \param{location}. \vspace{1em} \definep{install-string}{string location [target-dir]}% Install the contents of \param{string} in sub-directory \param{target-dir} of \param{location}. \subsubsection{Queries} \definep{get-directory}{location install?}% Get the absolute name of the directory to which the current layout maps the abstract \param{location}. If \param{install?} is true, the directory is the one valid during installation; If it is false, the directory is the one valid after installation, that is when the package is later used. The distinction between installation-time and usage-time directories is necessary to support staged installation, as performed by package managers like Debian's APT. \vspace{1em} \definep{get-option-value}{option}% Return the value of the given command-line \param{option} (a symbol). This can be used to get the value of predefined options (like \cloption{--dry-run}) or package-specific options. \vspace{1em} \definep{phase-active?}{phase}% Return true iff the given \param{phase} is active, that is if the steps associated with it should be performed. \param{Phase} should be one of the following symbols: \texttt{build}, \texttt{build-clean} or \texttt{install}, designating the corresponding phase (see section \ref{sec:packaging-packages}). \subsubsection{Load script generation} \definep{with-output-to-load-script*}{thunk}% Evaluate \param{thunk} with the current output opened on the loading script of the current package. If this script was already existing, its previous contents is deleted. \vspace{1em} \defines{with-output-to-load-script}{body ...}% Syntactic sugar for \ident{with-output-to-load-script*}. \vspace{1em} \definep{write-to-load-script}{s-expression}% Pretty-print the \param{s-expression} to the loading script of the current package. If this script was already existing, its previous contents is deleted. \begin{example} A typical package definition file for a simple package called \package{pkg} whose version is 1.2 could look like this: \begin{verbatim} (define-package "pkg" (1 2) () (install-file "load.scm" 'base) (install-directory-contents "scheme" 'scheme) (install-file ("LICENSE" . "COPYING") 'doc) (install-directory-contents "doc" 'doc)) \end{verbatim} With such a definition, invoking the installation script with \file{/usr/local/} as prefix and \layout{fhs} as layout has the following effects: \begin{enumerate} \item The base directory \file{/usr/local/share/scsh/modules/pkg-1.2} is created and file \file{load.scm} is copied to it. \item All the contents of the directory called \file{scheme} is copied to directory \file{/usr/local/share/scsh/modules/pkg-1.2/scheme} which is created before, if needed. \item File \file{LICENSE} is copied to directory \file{/usr/local/share/doc/pkg-1.2/} with name \file{COPYING}. \item All the contents of the directory called \file{doc} is copied to directory \file{/usr/local/share/doc/pkg-1.2/} \item The package is activated by creating a symbolic link with name \file{/usr/local/share/scsh/modules/pkg} pointing to \file{./pkg-1.2} \end{enumerate} \end{example} \subsubsection{Miscellaneous} \label{sec:misc} A few functions which are not specifically related to installation are provided, as they can sometimes be useful when writing installation scripts. They are documented below. \vspace{1em} \definep{parent-directory}{dir}% Returns the parent directory of \param{dir}. Notice that a trailing slash is always ignored by this function, so that the parent directory of both \file{/tmp/dir} and \file{/tmp/dir/} is \file{/tmp/}. \vspace{1em} \definep{create-directory\&parents}{dir}% Similar to scsh's \ident{create-directory}, but also create all parent directories which do not exist yet. \vspace{1em} \definep{relative-file-name}{fname [dir]}% Return the name of file \param{fname} relative to \param{dir}, which defaults to the current directory. \vspace{1em} \definep{paths->file-name}{path ...}% Similar to scsh's \ident{path-list->file-name} except that all arguments are taken to form the final path. This function has no equivalent for \ident{path-list->file-name}'s optional argument. \subsection{Packages containing C code (for shared libraries)} Packages containing C code are more challenging to write, since all the problems related to C's portability and incompatibilities between the APIs of the various platforms have to be accounted for. Fortunately, the GNU Autoconf system simplifies the management of these problems, and authors of scsh packages containing C code are strongly encouraged to use it. %% Integrating Autoconf into the installation procedure should not be a %% major problem thanks to scsh's ability to run separate programs. \section{Packaging packages} \label{sec:packaging-packages} Most important Unix systems today have one (or several) package management systems which ease the installation of packages on a system. In order to avoid confusion between these packages and the scsh packages discussed above, they will be called \emph{system packages} in what follows. It makes perfect sense to provide system packages for scsh packages. System packages should as much as possible try to use the standard installation script described above to install scsh packages. In order to make this as easy as possible, the installation script recognizes the following additional options: \begin{center} \begin{tabular}{lp{.6\textwidth}} \cloption{--dest-dir} dir & Specify a prefix for all installed files\\ \cloption{--phases} phases & Only perform some phases of installation.\\ \end{tabular} \end{center} The \cloption{--dest-dir} option plays the same role as the \envvar{DESTDIR} variable which is typically given to \texttt{make install}. Its value, which is the empty string by default, is prepended to all installation paths. This is used to perform staged installations, during which the package is first installed into a temporary directory and then moved to its final location by some external tool. The \cloption{--phases} option is used to perform only some steps of the whole installation process. Currently, three phases are defined: \phase{build}, \phase{build-clean} and \phase{install}. The \phase{build} phase is the one during which the operations required to build the package are performed. For scsh packages containing only Scheme code, this phase usually does nothing. For scsh packages containing some C code, this phase is the one during which the C code is compiled. The \phase{build-clean} phase is the one during which all the files created during the \phase{build} phase are removed. The \phase{install} phase is the one during which the files are copied to their final location. Using the \cloption{--phases} option, each phase can happen during a separate run of the installation script. This makes it possible, for example, to perform the build phase as one user, and the install phase as another one (e.g. root). In order for this to work, the installation script must be invoked as follows: \begin{enumerate} \item first with the \cloption{--phases build} option and maybe other options, \item then with the \emph{exact same options} as in the first step, except that \phase{install} has to be given to \cloption{--phases} instead of \phase{build}. \end{enumerate} The behaviour of the installation script is not defined if these conditions are violated. %% \section{Glossary} %% TODO define the following terms %% Version %% Target machine %% Package %% (Package) unpacking directory %% Layout %% (Abstract) location %% Package loading script \section{Acknowledgments} \label{sec:acknowledgments} Discussions with Andreas Bernauer, Anthony Carrico, David Frese, Friedrich Delgado Friedrichs, Martin Gasbichler, Eric Knauel, Daniel Kobras, Lionel Elie Mamane, and Jorgen Schfer greatly helped the design of this proposal. Mark Sapa started everything by asking for a Fink package for sunet and sunterlib. \end{document}scsh-install-lib-1.3.0/install.scm0000755000076500000240000000015310053621211017371 0ustar michelschinzstaff#!/bin/sh exec scsh -lm scheme/install-lib-module.scm -o install-lib -e install-main-quiet -s "$0" "$@" !# scsh-install-lib-1.3.0/NEWS0000644000076500000240000000576710301647241015742 0ustar michelschinzstaffRecent changes to install-lib -*- outline -*- * Changes in version 1.3.0 (released 2005-08-20) Added phase "build-clean", during which all the files created during phase "build" should be removed. Fixed a bug in the package definition of the library itself. Added the source of the documentation to the distribution, to make sure this library is considered as free software by Debian. * Changes in version 1.2.0 (released 2004-11-14) Added option --phases to perform only parts of the installation procedure (either the "build" phase or the "install" phase). Added a script called scsh-test-pkg (in bin/) which can be used to test if a package satisfies (some of) the conventions laid out in the documentation. While far from being perfect, and slightly pedantic on naming issues, this script can be very useful for package authors. Currently, it isn't installed automatically. Fixed the test to check if a package is installed when --non-shared-only is specified: in that case, consider the package as already installed iff a directory in the "lib" location corresponding to the current platform exists. Added naming conventions and some documentation for "split packages" (scsh packages composed of a main archive which is not scsh-aware, and another archive providing scsh-related files, e.g. the package definition). Removed previously undocumented --layout-to option. Changed (undocumented) behaviour of --layout and --layout-from options: layouts must now be specified as a single s-expression evaluating to a function mapping a package to a layout. Note: this doesn't affect the documented behaviour of --layout which still accepts names to designate predefined layouts. * Changes in version 1.1.2 (released 2004-07-08) By default, skip installation of all packages which are already installed (and report these packages in the final message). The "--force" option must be used to force their re-installation. * Changes in version 1.1.1 (released 2004-06-13) Changed the way "--destdir" is interpreted: now, it is a prefix for the installation prefix, whereas before it was the root of the installation prefix. In some cases, this implies a slightly different behaviour, which corresponds more to the de facto standard. * Changes in version 1.1 (released 2004-05-22) The installation library itself is now installed as a scsh package called "install-lib". The "scsh-install-pkg" script is just a wrapper around this library. As a consequence, the meaning of the "--prefix" option passed to the installation script changed: it is now the prefix to use to install the "install-lib" package. All the files but the wrapper script are installed below this prefix, according to the chosen layout. The wrapper script itself is put in the directory specified by the "--bindir" option. To comply with the packaging policy, some files were also renamed. Most importantly, the name of the documentation changed from "proposal.pdf" to "install-lib.pdf". * Version 1.0 (released 2004-04-01) First public release. scsh-install-lib-1.3.0/pkg-def.scm0000644000076500000240000000373210301645444017255 0ustar michelschinzstaff;; Package definition for the installation library itself. ;; Template for scsh-install-pkg script, must be plugged with the ;; directory containing the Scheme code. (define scsh-install-pkg-template #<" #t #f ,(bin-dir) ,identity ,identity))) ;; Install "package" part (doc & Scheme code) (install-file "doc/install-lib.pdf" 'doc "pdf") (install-files '("scheme/install-lib.scm" "scheme/install-lib-version.scm" "scheme/install-lib-module.scm") 'scheme) (write-to-load-script `((config) (load ,(absolute-file-name "install-lib-module.scm" (get-directory 'scheme #f))) (user))) ;; Install "program" part (scsh-install-pkg script). (if (phase-active? 'install) (let ((bindir (string-append (get-option-value 'dest-dir) (get-option-value 'bindir)))) (if (or (get-option-value 'dry-run) (get-option-value 'verbose)) (format #t "creating scsh-install-pkg script in ~a\n" bindir)) (if (not (get-option-value 'dry-run)) (let ((wrapper-name (absolute-file-name "scsh-install-pkg" bindir))) (with-errno-handler ((errno packet) (else ((display-error-and-exit "cannot create wrapper script " wrapper-name ":\n " (first packet))))) (create-directory&parents bindir #o755) (call-with-output-file wrapper-name (lambda (port) (format port scsh-install-pkg-template (get-directory 'base #f)) (set-file-mode port #o755))))))))) scsh-install-lib-1.3.0/README0000644000076500000240000000541710063060071016106 0ustar michelschinzstaff scsh installation library Introduction ------------ This is the scsh installation library, which aims at making it easy to install extension libraries for scsh. The complete documentation for this library can be found in doc/install-lib.pdf. Apart from describing the library itself, this document also explains how to install and use scsh packages in general. At least Sections 3 and 4 of this document should be read before proceeding further. Notice that this library needs scsh v0.6.6 or newer, and will not work at all with older versions. Installation ------------ This library must be installed before any attempt at installing scsh packages is made. Since version 1.1, this library installs itself as a scsh package called "install-lib", and additonally installs a small wrapper script called "scsh-install-pkg", to install other packages later. Installation is performed by running the "install.scm" script found in the same directory as the present file. This script must at least be provided with the following parameter: --prefix The prefix directory in which the "install-lib" package is to be installed. Please notice that this is *NOT* exactly the same as configure's prefix. Ideally, you should choose one prefix now and then stick to it when installing further packages, as this will greatly simplify their use. Optionally, the directory in which to install the wrapper script ("scsh-install-pkg") can be specified using the "--bindir" option. By default, the directory in which scsh itself is installed will be used. Other parameters can also be supplied (--help, --layout, --verbose, --dest-dir, etc.), as explained in the documentation. As an example, to install everything in /usr/local one could invoke the installation script as follows: ./install.scm --bindir /usr/local/bin --prefix /usr/local/share/scsh This would install the following files (where stands for the current version of the installation library, e.g. 1.0.0): /usr/local/bin/scsh-install-pkg The script to run in order to install scsh packages. Its use is explained in the documentation. /usr/local/share/scsh/0.6/install-lib-/scheme/install-lib-module.scm /usr/local/share/scsh/0.6/install-lib-/scheme/install-lib-version.scm /usr/local/share/scsh/0.6/install-lib-/scheme/install-lib.scm /usr/local/share/scsh/0.6/install-lib-/load.scm The Scheme code for the installation library. /usr/local/share/scsh/0.6/install-lib A link pointing to /usr/local/share/scsh/0.6/install-lib-, used to designate the current version of this package. /usr/local/share/scsh/0.6/install-lib-/doc/pdf/install-lib.pdf The documentation describing the installation library, and how to manage scsh packages in general. scsh-install-lib-1.3.0/scheme/0000755000076500000240000000000010301650404016463 5ustar michelschinzstaffscsh-install-lib-1.3.0/scheme/install-lib-module.scm0000644000076500000240000000456210143747333022707 0ustar michelschinzstaff;;; Installation library for scsh modules. ;;; $Id: install-lib-module.scm,v 1.14 2004/11/08 19:54:03 michel-schinz Exp $ ;;; Interfaces (define-interface install-lib-version-interface (export install-lib-version)) ;; List utilities (extensions to SRFI-1) (define-interface list-utils-interface (export common-prefix-length alist-replace alist-combine alist-get)) ;; String utilities (extensions to SRFI-13) (define-interface string-utils-interface (export as-string spaces)) ;; File utilities (extensions to scsh) (define-interface file-utils-interface (export parent-directory create-directory&parents relative-file-name paths->file-name)) ;; Installation library (define-interface install-interface (export tmpl-libtool-la-reader version->string string->version version-compare version? version=? phase-active? package-name package-full-name package-version ((define-package define-program) :syntax) load-package-in install-file install-files install-directory install-directories install-directory-contents install-string install-sub-package identity parse-boolean show-boolean get-directory get-option-value with-output-to-load-script* (with-output-to-load-script :syntax) write-to-load-script display-error-and-exit install-main install-main-quiet install-program-main)) (define-interface install-full-interface (compound-interface install-interface list-utils-interface string-utils-interface file-utils-interface)) ;;; Structures (define-structure install-lib-version install-lib-version-interface (open scheme) (files install-lib-version)) (define-structures ((install-lib install-full-interface) (install install-full-interface)) ;deprecated name (open scheme-with-scsh cells fluids let-opt srfi-1 srfi-2 srfi-9 srfi-13 srfi-37 configure scsh-version pp install-lib-version) (files install-lib)) scsh-install-lib-1.3.0/scheme/install-lib-version.scm0000644000076500000240000000205610301645427023100 0ustar michelschinzstaff;; ;; Version of the installation library ;; ;; The versioning scheme is as follows: a version is composed of three ;; integers called (from left to right) "major", "minor" and ;; "revision". ;; ;; Two versions which share a "major" and "minor" number must be fully ;; compatible in that one should be exchangeable for the other without ;; (important) change in behaviour. ;; ;; Two versions which share a "major" number must be compatible in an ;; ascendent fashion: the features offered by the version with the ;; greatest "minor" number must be a superset of those offered by the ;; other. ;; ;; Two versions which do not even share a "major" number can be ;; mutually incompatible. ;; ;; Clients using the installation library must specify which "major" ;; and "minor" number they need --- if the above scheme is respected, ;; the "revision" should not matter. This need is satisfied if the ;; requested "major" number matches the one of the library, and the ;; requested "minor" is smaller or equal to the one of the library. (define install-lib-version '(1 3 0)) scsh-install-lib-1.3.0/scheme/install-lib.scm0000755000076500000240000013244710301647776021441 0ustar michelschinzstaff;;; Installation library for scsh modules. ;;; $Id: install-lib.scm,v 1.25 2005/08/20 15:45:02 michel-schinz Exp $ ;; TODO ;; - think about --build: does it make sense? ;; - get-directory should get 'install or 'final instead of #f #t ;; - add a "--debug" option ;; - add support for communication between configure and pkg-def.scm ;; - add support for image creation ;; - add support to maintain a documentation index ;; ;; Support code templates ;; ;; These templates are meant to be inserted in package-loading ;; scripts. ;; Template to parse libtool's ".la" files. (define tmpl-libtool-la-reader '((define (normalize-la-entry key val) (let ((left-quotes-rx (rx (: bos #\'))) (right-quotes-rx (rx (: #\' eos))) (kill-matches (lambda (rx str) (regexp-substitute/global #f rx str 'pre 'post)))) (cons (string->symbol key) (kill-matches left-quotes-rx (kill-matches right-quotes-rx val))))) (define add-la-entry (let ((splitter (infix-splitter (rx #\=))) (comment-rx (rx (: bos #\#)))) (lambda (line alist) (cond ((and (not (regexp-search? comment-rx line)) (string-index line #\=)) (let ((lst (splitter line))) (if (= 2 (length lst)) (cons (apply normalize-la-entry lst) alist) (error "Could not read la entry" line list)))) (else alist))))) (define (read-libtool-la file-name) (call-with-input-file file-name (lambda (port) (let lp ((line (read-line port)) (alist '())) (if (eof-object? line) alist (lp (read-line port) (add-la-entry line alist))))))))) ;; ;; Utilities ;; (define default-perms #o755) ;; Function composition (for functions with one argument) (define (compose f g) (lambda (x) (f (g x)))) ;; Fail if CONDITION is not true, displaying ERROR-MSG with ARGUMENTS. (define (assert condition error-msg . arguments) (if (not condition) (apply error error-msg arguments))) ;; True iff LIST has more than one element. (define (many? list) (> (length list) 1)) ;; Return the name of the parent directory of FNAME. (define (parent-directory fname) (file-name-directory (directory-as-file-name fname))) (define (get-perms integer/fun fname) (cond ((procedure? integer/fun) (integer/fun fname)) ((integer? integer/fun) integer/fun) (else (error "invalid permission specification" integer/fun)))) ;; Create directory FNAME and all its parents, as needed. (define (create-directory&parents fname . rest) (let-optionals rest ((perms default-perms)) (let ((parent (parent-directory fname))) (if (file-not-exists? parent) (apply create-directory&parents parent rest)) (if (file-not-exists? fname) (create-directory fname (get-perms perms (absolute-file-name fname))))))) ;; Return the length of the longest prefix common to lists L1 and L2, ;; by comparing elements using PRED (defaults to EQUAL?). (define (common-prefix-length l1 l2 . rest) (let-optionals rest ((pred equal?)) (if (or (null? l1) (null? l2) (not (pred (first l1) (first l2)))) 0 (+ 1 (apply common-prefix-length (cdr l1) (cdr l2) rest))))) ;; Return the name of file NAME relative to DIR (defaults to current ;; directory). (define (relative-file-name name . rest) (let-optionals rest ((dir (cwd))) (let* ((abs-pl (split-file-name (absolute-file-name name))) (dir-pl (split-file-name (directory-as-file-name dir))) (cp-len (common-prefix-length abs-pl dir-pl))) (path-list->file-name (append (make-list (- (length dir-pl) cp-len) "..") (drop abs-pl cp-len)))))) ;; Similar to path-list->file-name, but take all arguments as ;; components of the path. (define (paths->file-name . paths) (path-list->file-name paths)) ;; If FILE exists, fail if --force was not given, delete it otherwise. (define (delete-file-or-fail file) (if (file-exists? file) (if (get-option-value 'force) (-delete-file file) (display-error-and-exit "target file already exists: " file)))) ;; Copy file/symlink SOURCE to TARGET. TARGET must be the name of a ;; non-existing file (i.e. it cannot be the name of a directory). (define (copy-file source target) (delete-file-or-fail target) (if (file-symlink? source) (create-symlink (read-symlink source) target) (begin (run (cp ,source ,target)) (set-file-mode target (file-mode source))))) ;; Like "load" but without printing anything. (define load-quietly (let ((eval (lambda (expr t) (eval expr (interaction-environment))))) (lambda (file-name) (call-with-input-file file-name (lambda (port) (port-fold port read eval #f)))))) ;; Load the contents of FILE-NAME which should contain exactly one ;; s-expression. Complain if it is not the case. (define (load-single-sexp file-name) (if (file-not-exists? file-name) (display-error-and-exit "file "file-name" doesn't exist") (call-with-input-file file-name (lambda (port) (read-single-sexp port (string-append "file "file-name)))))) ;; Read the contents of PORT which should contain exactly one ;; s-expression. Complain if it is not the case, using SOURCE to ;; identify the source of data. (define (read-single-sexp port source) (let ((sexp (read port))) (if (eof-object? sexp) (display-error-and-exit source" is empty")) (if (not (eof-object? (read port))) (display-error-and-exit "more than one s-expression found in "source)) sexp)) (define (permissions->string perms) (let ((decode (lambda (mask str) (if (zero? (bitwise-and perms mask)) "-" str)))) (string-append (decode #o400 "r") (decode #o200 "w") (decode #o100 "x") (decode #o040 "r") (decode #o020 "w") (decode #o010 "x") (decode #o004 "r") (decode #o002 "w") (decode #o001 "x")))) ;; Replace all bindings of KEY in ALIST with one binding KEY to DATUM. (define (alist-replace key datum alist) (alist-cons key datum (alist-delete key alist))) ;; Add all mappings from ALIST-2 to ALIST-1. If a key is mapped in ;; both lists, the mapping in the first list takes precedence. (define (alist-combine alist-1 alist-2) (fold (lambda (key/value result) (if (assoc (car key/value) result) result (cons key/value result))) alist-1 alist-2)) ;; Return the value associated with KEY in ALIST. If none exists, ;; return DEFAULT, or signal an error if no DEFAULT was given. (define (alist-get key alist . rest) (cond ((assoc key alist) => cdr) ((not (null? rest)) (first rest)) (else (error "cannot find key in alist" key alist)))) ;; Display all arguments on the current output port. (define (display-all . args) (for-each display args)) ;; Convert all arguments to strings using DISPLAY and concatenate the ;; result in a single string which is returned. (define (as-string . args) (call-with-string-output-port (lambda (port) (with-current-output-port port (apply display-all args))))) ;; Return a string of N white spaces. (define (spaces n) (make-string n #\space)) ;; ;; Support for dry runs / verbose operation. ;; (define (wrap real-fn info-fn) (lambda args (if (or (get-option-value 'verbose) (get-option-value 'dry-run)) (begin (display (apply info-fn args)) (newline))) (if (not (get-option-value 'dry-run)) (apply real-fn args)))) (define -create-directory (wrap create-directory (lambda (fname . rest) (let-optionals rest ((perms #o777)) (as-string "creating directory " fname " (perms: " (permissions->string perms) ")"))))) (define -create-directory&parents (wrap create-directory&parents (lambda (fname . rest) (as-string "creating directory " fname " (and its parents)")))) (define -create-symlink (wrap create-symlink (lambda (old-name new-name) (as-string "creating symbolic link " new-name " pointing to " old-name)))) (define -copy-file (wrap copy-file (lambda (source target) (as-string "copying file " source " to " target)))) (define -delete-file (wrap delete-file (lambda (fname) (as-string "deleting file " fname)))) (define -call-with-output-file (wrap call-with-output-file (lambda (fname port-function) (let ((string-out (make-string-output-port))) (port-function string-out) (as-string "writing>>\n" (string-output-port-output string-out) "<string mode))))) ;; ;; Versions ;; ;; Versions are represented as lists of integers, the most significant ;; being at the head. ;; Return major/minor parts of a version. (define version-major first) (define version-minor second) ;; Return true iff OBJECT can be interpreted as a version. (define (version? object) (and (list? object) (every integer? object))) ;; Return the printed representation of VERSION. (define (version->string version) (string-join (map number->string version) ".")) ;; Convert the printed representation of a version found in ;; VERSION-STRING to the version it represents. (define string->version (let ((split-version (infix-splitter "."))) (lambda (version-string) (map string->number (split-version version-string))))) ;; Compare two versions lexicographically and return the symbol ;; 'smaller if the first is strictly smaller than the second, 'equal ;; if both are equal, and 'greater otherwise. (define (version-compare v1 v2) (cond ((and (null? v1) (null? v2)) 'equal) ((null? v1) 'smaller) ((null? v2) 'greater) (else (let ((v1h (car v1)) (v2h (car v2))) (cond ((< v1h v2h) 'smaller) ((> v1h v2h) 'greater) (else (version-compare (cdr v1) (cdr v2)))))))) (define (version? v1 v2) (eq? (version-compare v1 v2) 'greater)) (define (version=? v1 v2) (eq? (version-compare v1 v2) 'equal)) ;; ;; Phases ;; (define all-phases '(build build-clean install)) (define all-phases-str (string-join (map symbol->string all-phases) ", ")) (define (valid-phase? thing) (member thing all-phases)) (define (phase-active? phase) (assert (valid-phase? phase) "invalid phase" phase) (member phase (get-option-value 'phases))) (define (parse-phase str) (let ((phase (string->symbol str))) (if (valid-phase? phase) phase (display-error-and-exit "invalid phase "str" " "(valid ones are: "all-phases-str")")))) (define (parse-phases str) (map parse-phase ((infix-splitter ",") str))) ;; ;; Layouts ;; ;; Names of all shared locations (i.e. the ones which do not depend on ;; the platform). (define shared-locations '(active base misc-shared scheme doc)) ;; Names of all non-shared (i.e. platform-dependent) locations. (define non-shared-locations '(lib bin)) ;; All locations defined for a layout. (define all-locations (append shared-locations non-shared-locations)) ;; Return true iff LOCATION is valid. (define (valid-location? location) (member location all-locations)) ;; Return true iff LOCATION is "active", that is if files should be ;; installed in it. (define (active-location? location) (assert (valid-location? location) "invalid location" location) (and (phase-active? 'install) (or (not (get-option-value 'non-shared-only)) (member location non-shared-locations)))) ;; Parse a layout given as an s-expression evaluating to a procedure. (define (parse-layout str) (let ((layout (eval (read-single-sexp (make-string-input-port str) "--layout argument") (interaction-environment)))) (if (procedure? layout) layout (display-error-and-exit "--layout argument doesn't specify a valid layout" layout)))) ;; Load layout from FILE-NAME, which must contain exactly one ;; s-expression evaluating to a procedure. (define (load-layout file-name) (let ((layout (eval (load-single-sexp file-name) (interaction-environment)))) (if (procedure? layout) layout (display-error-and-exit "file "file-name" doesn't contain a valid layout")))) ;; Return an absolute version of LAYOUT by prepending PREFIX to all ;; its components (which must be relative). (define (absolute-layout layout prefix) (map (lambda (key/value) (cons (car key/value) (absolute-file-name (cdr key/value) prefix))) layout)) ;; Return the directory associated with the LOCATION in LAYOUT. (define (layout-dir layout location) (assert (valid-location? location) "invalid location" location) (or (alist-get location layout #f) (display-error-and-exit "cannot find the directory for location '" location "' in active layout."))) ;; Predefined layouts ;; Directory corresponding to the current major and minor version of ;; scsh. (define scsh-version-string (version->string (list scsh-major-version scsh-minor-version))) (define (scsh-layout base) `((base . ,base) (misc-shared . ,base) (scheme . ,(absolute-file-name "scheme" base)) (lib . ,(absolute-file-name "lib" base)) (doc . ,(absolute-file-name "doc" base)))) (define (scsh-layout-1 pkg) (alist-combine `((active . ,scsh-version-string)) (scsh-layout (paths->file-name scsh-version-string (package-full-name pkg))))) (define (scsh-layout-2 pkg) (alist-combine `((active . ,(paths->file-name scsh-version-string "active"))) (scsh-layout (paths->file-name scsh-version-string "installed" (package-name pkg) (version->string (package-version pkg)))))) (define (fhs-layout pkg) (let* ((scsh-version-dir (string-append "scsh-" scsh-version-string)) (base (paths->file-name "share" scsh-version-dir "modules" (package-full-name pkg)))) `((base . ,base) (misc-shared . ,base) (scheme . ,(absolute-file-name "scheme" base)) (lib . ,(paths->file-name "lib" scsh-version-dir "modules" (package-full-name pkg))) (doc . ,(paths->file-name "share" "doc" scsh-version-dir (package-full-name pkg))) (active . ,(paths->file-name "share" scsh-version-dir "modules"))))) (define (fhs-program-layout pkg) (let* ((pkg-share (paths->file-name "share" (package-full-name pkg)))) `((bin . "bin") (scheme . ,(paths->file-name pkg-share "scheme")) (doc . ,(paths->file-name "share" "doc" (package-full-name pkg)))))) (define predefined-layouts `(("scsh" . ,scsh-layout-1) ("scsh-alt" . ,scsh-layout-2) ("fhs" . ,fhs-layout) ("fhs-program" . ,fhs-program-layout))) ;; If LAYOUT-SPEC is a procedure, return it as-is. If it's a string ;; and refers to a predefined layout, this layout is returned. If it's ;; a string and a valid layout definition, parse and return it. ;; Otherwise, return false. (define (resolve-layout layout-spec) (or (and (procedure? layout-spec) layout-spec) (alist-get layout-spec predefined-layouts #f) (parse-layout layout-spec))) ;; ;; Packages ;; (define-record-type package (make-package name version extensions directory install-thunk) package? (name package-name) (version package-version) (extensions package-extensions) (directory package-directory) (install-thunk package-install-thunk)) ;; Return the full name of PKG. (define (package-full-name pkg) (string-append (package-name pkg) "-" (version->string (package-version pkg)))) ;; Return the value of extension called EXT for PKG. If such an ;; extension doesn't exist, return #f. (define (package-extension pkg ext) (alist-get ext (package-extensions pkg) #f)) ;; List of all defined packages (define *packages* (make-fluid (make-cell '()))) ;; Add PKG to the above list of all defined packages. (define (add-package pkg) (cell-set! (fluid *packages*) (cons pkg (cell-ref (fluid *packages*))))) (define-syntax define-package (syntax-rules () ((define-package name version extensions body ...) (add-package (make-package name (quasiquote version) (quasiquote extensions) (cwd) (lambda () body ...)))))) (define-syntax define-program (syntax-rules () ((define-program name version extensions body ...) (define-package name version extensions body ...)))) (define (package-version-requirement pkg) (and-let* ((req-lst (package-extension pkg 'install-lib-version))) (first req-lst))) ;; Load (and evaluate the contents of) the file "pkg-def.scm" in the ;; current directory and return the packages it defines. (define (load-packages) (let-fluid *packages* (make-cell '()) (lambda () (if (file-exists? package-definition-file) (load-quietly package-definition-file)) (cell-ref (fluid *packages*))))) ;; Check that the given package does not require a more recent version ;; of the installation library, and fail if it is the case. (define (check-package pkg) (and-let* ((req (package-version-requirement pkg)) ((or (not (= (version-major req) (version-major install-lib-version))) (> (version-minor req) (version-minor install-lib-version))))) (display-error-and-exit "package "(package-name pkg)" needs a newer " "version of install-lib: "(version->string req)"\n" "(installed: " (version->string install-lib-version) ")"))) ;; Like load-package but additionally check loaded packages. (define (load&check-packages) (and-let* ((pkgs (load-packages)) ((for-each check-package pkgs))) pkgs)) (define (load-package-in dir) (with-cwd dir (load-quietly package-definition-file))) ;; ;; Package options ;; (define-record-type pkg-opt (really-make-pkg-opt key help arg-help required-arg? optional-arg? default parse show transform) pkg-opt? (key pkg-opt-key) (help pkg-opt-help) (arg-help pkg-opt-arg-help) (required-arg? pkg-opt-required-arg?) (optional-arg? pkg-opt-optional-arg?) (default pkg-opt-default) (parse pkg-opt-parse) (show pkg-opt-show) (transform pkg-opt-transform)) (define (make-pkg-opt key help arg-help req-arg? opt-arg? default . rest) (let-optionals rest ((parse identity) (show identity) (transform (lambda (old new) new))) (really-make-pkg-opt key help arg-help req-arg? opt-arg? default parse show transform))) ;; Return the name of PKG-OPT (define (pkg-opt-name pkg-opt) (symbol->string (pkg-opt-key pkg-opt))) ;; Convert PKG-OPT into an SRFI-37 option. (define (pkg-opt->option pkg-opt) (let ((key (pkg-opt-key pkg-opt)) (transform (pkg-opt-transform pkg-opt)) (parse (pkg-opt-parse pkg-opt))) (option (list (pkg-opt-name pkg-opt)) (pkg-opt-required-arg? pkg-opt) (pkg-opt-optional-arg? pkg-opt) (lambda (opt name arg alist) (alist-replace key (transform (alist-get key alist) (parse arg)) alist))))) ;; Return a pair (key, default) which associates the default value of ;; PKG-OPT to its key. (define (pkg-opt-key&default pkg-opt) (cons (pkg-opt-key pkg-opt) (pkg-opt-default pkg-opt))) ;; Return the list of all package options of the PACKAGES. (define (all-package-options packages) (append-map (lambda (pkg) (cond ((package-extension pkg 'options) => (lambda (opts) (map (lambda (args) (apply make-pkg-opt args)) opts))) (else '()))) packages)) ;; ;; Load script handling ;; (define load-script-name "load.scm") ;; Evaluate THUNK with CURRENT-OUTPUT-PORT opened on the current ;; package's loading script (in the install directory). During a dry ;; run, or when only non-shared data has to be installed, do nothing. (define (with-output-to-load-script* thunk) (if (and (not (get-option-value 'dry-run)) (active-location? 'base)) (let* ((dir (get-directory 'base #t)) (file (absolute-file-name load-script-name dir))) (-create-directory&parents dir) (delete-file-or-fail file) (with-output-to-file file thunk)))) ;; Sugar for with-output-to-load-script*. (define-syntax with-output-to-load-script (syntax-rules () ((with-output-to-load-script body ...) (with-output-to-load-script* (lambda () body ...))))) ;; Pretty-print all the elements of s-exps, one after the other, to ;; the current package's loading script (in the install directory). (define (write-to-load-script s-exps) (with-output-to-load-script (for-each p s-exps))) ;; ;; Actions ;; ;; Perform all actions required to make the given version of the ;; package active (i.e. the default version for that package). (define (activate-package layout pkg) (if (active-location? 'active) (let ((lnk-name (absolute-file-name (package-name pkg) (layout-dir layout 'active)))) (if (and (file-exists? lnk-name) (file-symlink? lnk-name)) (-delete-file lnk-name)) (-create-symlink (relative-file-name (layout-dir layout 'base) (file-name-directory lnk-name)) lnk-name)))) (define (install-thing% layout name-or-pair location target-rel-dir perms) (let* ((target-dir (absolute-file-name target-rel-dir (layout-dir layout location))) (source (if (pair? name-or-pair) (car name-or-pair) name-or-pair)) (target-name (file-name-nondirectory (if (pair? name-or-pair) (cdr name-or-pair) name-or-pair))) (target (absolute-file-name target-name target-dir))) (if (not ((get-option-value 'exclude) source)) (begin (-create-directory&parents target-dir perms) (cond ((or (file-regular? source) (file-symlink? source)) (-copy-file source target)) ((file-directory? source) (if (file-exists? target) (if (file-directory? target) (if (get-option-value 'force) (-set-file-mode target (file-mode source)) (display-error-and-exit "target directory already exists: " target)) (begin (delete-file-or-fail target) (-create-directory target (file-mode source)))) (-create-directory target (file-mode source))) (install-directory-contents% layout source location (absolute-file-name target-name target-rel-dir) perms)) (else (display-error-and-exit "cannot install file-system object: " source))))))) (define (install-directory-contents% layout name location target-rel-dir perms) (for-each (lambda (thing) (install-thing% layout thing location target-rel-dir perms)) (map (lambda (f) (absolute-file-name f name)) (directory-files name #t)))) (define (install-thing name-or-pair location . rest) (if (active-location? location) (let-optionals rest ((target-rel-dir ".") (perms default-perms)) (install-thing% (fluid *install-layout*) name-or-pair location target-rel-dir perms)))) (define (install-things names-or-pairs . rest) (for-each (lambda (name-or-pair) (apply install-thing name-or-pair rest)) names-or-pairs)) (define install-file install-thing) (define install-files install-things) (define install-directory install-thing) (define install-directories install-things) (define (install-directory-contents name location . rest) (if (active-location? location) (let-optionals rest ((target-rel-dir ".") (perms default-perms)) (install-directory-contents% (fluid *install-layout*) name location target-rel-dir perms)))) (define (install-string% layout str target-name location target-rel-dir perms) (let* ((target-dir (absolute-file-name target-rel-dir (layout-dir layout location))) (target-full-name (absolute-file-name target-name target-dir))) (-create-directory&parents target-dir) (delete-file-or-fail target-full-name) (-call-with-output-file target-full-name (lambda (port) (write-string str port))) (-set-file-mode target-full-name (get-perms perms target-full-name)))) (define (install-string str target-name location . rest) (let-optionals rest ((target-rel-dir ".") (perms default-perms)) (if (active-location? location) (install-string% (fluid *install-layout*) str target-name location target-rel-dir perms)))) (define *layout* (make-fluid #f)) (define *install-layout* (make-fluid #f)) ;; Return the directory identified by LOCATION in the current layout. ;; If INSTALL? is true, return the directory valid during the ;; installation of the package, otherwise return the directory valid ;; after installation (i.e. during package use). (define (get-directory location install?) (layout-dir (fluid (if install? *install-layout* *layout*)) location)) ;; Perform all actions to install PKG in INSTALL-LAYOUT. If LAYOUT is ;; not the same as INSTALL-LAYOUT, assume that some external tool will ;; move the installed files so that they are laid out according to ;; LAYOUT. (define (install-package layout install-layout pkg) (with-cwd (package-directory pkg) (let-fluids *layout* layout *install-layout* install-layout (package-install-thunk pkg)))) ;; Install all PACKAGES with the given OPTIONS-VALUES. (define (install-packages packages options-values) (let* ((prefix (alist-get 'prefix options-values)) (dest-dir (alist-get 'dest-dir options-values)) (dest-prefix (and prefix (string-append dest-dir prefix))) (layout-fn (resolve-layout (alist-get 'layout options-values))) (activate? (not (alist-get 'inactive options-values)))) (let-fluids *options-values* options-values (lambda () (for-each (lambda (pkg) (let* ((rel-layout (layout-fn pkg)) (layout (absolute-layout rel-layout prefix)) (i-layout (absolute-layout rel-layout dest-prefix))) (install-package layout i-layout pkg) (if activate? (activate-package i-layout pkg)))) packages))))) (define (install-sub-package dir . rest) (let-optionals rest ((options-diff '())) (with-cwd dir (install-packages (load&check-packages) (fold (lambda (diff options) (cond ((pair? diff) (cons diff (alist-delete (car diff) options))) ((symbol? diff) (alist-delete diff options)) (else (error "invalid option difference" diff)))) (fluid *options-values*) options-diff))))) ;; ;; Error handling ;; ;; Display all the MSGS, then exit with an error code of 1. (define (display-error-and-exit . msgs) (for-each display (cons "Error: " msgs)) (newline) (exit 1)) ;; Usage for all options. This also defines an order on options, and ;; this order is used when displaying available options to the user. (define options-usage `(("help" #f "display this help message, then exit") ("version" #f "display version of install-lib, then exit") ("prefix" "dir" "specify directory where files are installed") ("layout" "layout" ("specify layout of installation directory" ,(string-append "(predefined: " (string-join (map car predefined-layouts) ", ") ")"))) ("dry-run" #f "don't do anything, print what would have been done") ("verbose" #f "print messages about what is being done") ("inactive" #f "don't activate package after installing it") ("non-shared-only" #f "only build/install platform-dependent files") ("force" #f "overwrite existing files during installation") ("no-user-defaults" #f "don't read defaults from ~/.scsh-pkg-defaults.scm") ;; advanced ("phases" "phases" ("perform only the given phase(s) " ,(string-append "("all-phases-str")"))) ("build" "name" "name of platform for which to build") ("layout-from" "file" "load layout of installation directory from file") ("dest-dir" "dir" ("specify prefix to use during installation" "(use only for staged installations!)")))) (define (sort-options options) (filter-map (lambda (name) (find (lambda (opt) (string=? (option-long-name opt) name)) options)) (map first options-usage))) ;; Return the long name of the given OPTION. It is an error if that ;; option doesn't have a long name. (define (option-long-name option) (first (filter string? (option-names option)))) ;; Return the usage string for an option with OPT-NAME as long name, ;; and OPT-ARG as argument template. If OPT-ARG is #f, the option ;; doesn't take an argument. (define (option/arg-usage opt-name opt-arg) (string-append "--" opt-name (if opt-arg (string-append " <" opt-arg ">") ""))) ;; Return the usage list for the given SRFI-37 OPTION. (define (srfi-37-opt-usage option) (let ((raw-usage (assoc (option-long-name option) options-usage))) (cons (option/arg-usage (first raw-usage) (second raw-usage)) (third raw-usage)))) ;; Return the usage list for the given package OPTION. (define (pkg-opt-usage option) (cons (option/arg-usage (pkg-opt-name option) (pkg-opt-arg-help option)) (string-append (pkg-opt-help option) " [" ((pkg-opt-show option) (pkg-opt-default option)) "]"))) ;; Return a complete usage string, considering the fact that the ;; script is called PROG-NAME and takes options BASE-OPTS (a list of ;; SRFI-37 options), and the package takes options PKG-OPTS (a list of ;; pkg-option records). (define (build-usage-string prog-name base-opts pkg-opts) (let* ((base-usages (map srfi-37-opt-usage (sort-options base-opts))) (pkg-usages (map pkg-opt-usage pkg-opts)) (max-arg-len (apply max (map (compose string-length car) (append base-usages pkg-usages))))) (with-current-output-port (make-string-output-port) (display-all "Usage: "prog-name" [options]\n\n" "options:\n") (let ((format-usage (lambda (usage-pair) (let ((arg (car usage-pair)) (msg (cdr usage-pair))) (display-all " " arg (spaces (+ 1 (- max-arg-len (string-length arg)))) (if (list? msg) (first msg) msg) #\newline) (if (list? msg) (for-each (lambda (line) (display-all (spaces (+ 3 max-arg-len)) line #\newline)) (cdr msg))))))) (for-each format-usage base-usages) (if (not (null? pkg-usages)) (begin (display "\npackage-specific options:\n") (for-each format-usage pkg-usages))) (string-output-port-output (current-output-port)))))) (define usage-string #f) ;; Display the usage string, then exit successfully. (define (display-usage-and-exit) (display usage-string) (newline) (exit)) (define (display-version-and-exit) (display-all "scsh-install-lib version " (version->string install-lib-version) "\n") (exit)) ;; Display a hint about how to use the just-installed PACKAGES, ;; assuming they were laid out according to LAYOUT and PREFIX. (define (display-use-hint prefix layout packages skipped-pkgs) (let* ((active-locations (delete-duplicates (map (lambda (pkg) (string-append "\"" (layout-dir (absolute-layout (layout pkg) prefix) 'active) "\"")) packages) string=?)) (load-scripts (map (lambda (pkg) (absolute-file-name load-script-name (package-name pkg))) packages)) (scsh-options (map (lambda (load-script) (string-append "-lel " load-script)) load-scripts))) (if (not (null? packages)) (begin (display (as-string "The following scsh package" (if (many? packages) "s were" " was") " installed successfully:\n" " "(string-join (map package-full-name packages) ", ")"\n")) (if (not (every (lambda (script) (find-library-file script (lib-dirs) "")) load-scripts)) (display (as-string "To make sure scsh finds "(if (many? packages) "them" "it")", " "please add the following value" (if (many? active-locations) "s" "")"\n" "to the environment variable SCSH_LIB_DIRS (quotes included):" "\n " (string-join active-locations " ") "\n"))) (display (as-string "To use " (if (many? packages) "these packages" "this package") " in a script, invoke scsh with the following option" (if (many? scsh-options) "s" "")":\n" " "(string-join scsh-options " ")"\n")))) (if (not (null? skipped-pkgs)) (display (as-string "The following scsh package" (if (many? skipped-pkgs) "s were" " was") " *not* installed, because " (if (many? skipped-pkgs) "they were" "it was") "\n" "already present (use --force option to force" " reinstallation):\n" " "(string-join (map package-full-name skipped-pkgs) ", ") "\n"))))) ;; ;; Command line parsing ;; ;; Predefined parsers/unparsers (define (parse-boolean s) (cond ((string=? s "yes") #t) ((string=? s "no") #f) (else (display-error-and-exit "unknown boolean value '"s"'. Use 'yes' or 'no'.")))) (define (show-boolean b) (if b "yes" "no")) ;; The identity function, sometimes useful for parsers/unparsers. (define (identity x) x) ;; Fluid containing the value of all options. (define *options-values* (make-fluid #f)) (define package-definition-file "pkg-def.scm") (define (get-option-value key) (alist-get key (fluid *options-values*))) (define (alist-updater key parser) (lambda (opt name arg alist) (alist-replace key (parser arg) alist))) (define (alist-arg-updater key) (alist-updater key identity)) (define (alist-boolean-updater key) (alist-updater key (lambda (arg) (or (not arg) (parse-boolean arg))))) (define common-options (list (option '(#\h "help") #f #f (lambda args (display-usage-and-exit))) (option '(#\v "version") #f #f (lambda args (display-version-and-exit))) (option '("prefix") #t #f (alist-arg-updater 'prefix)) (option '("dest-dir") #t #f (alist-arg-updater 'dest-dir)) (option '("layout") #t #f (alist-arg-updater 'layout)) (option '("layout-from") #t #f (alist-updater 'layout load-layout)) (option '("dry-run") #f #t (alist-boolean-updater 'dry-run)) (option '("verbose") #f #t (alist-boolean-updater 'verbose)) (option '("force") #f #t (alist-boolean-updater 'force)) (option '("no-user-defaults") #f #f (lambda (opt name arg alist) alist)) (option '("phases") #t #f (alist-updater 'phases parse-phases)))) (define lib-options (list (option '("build") #t #f (alist-arg-updater 'build)) (option '("non-shared-only") #f #t (alist-boolean-updater 'non-shared-only)) (option '("inactive") #f #t (alist-boolean-updater 'inactive)))) (define no-user-defaults-option "--no-user-defaults") (define (options pkg-kind) (append (if (kind-lib? pkg-kind) lib-options '()) common-options)) (define (parse-options args options defaults) (args-fold args options (lambda (option name . rest) (display-error-and-exit "Unknown option "name"\n" "(use --help to get a list of " "valid options)")) (lambda (operand . rest) (display-error-and-exit "Don't know what to do with "operand"\n" "(use --help to get a list of " "valid options)")) defaults)) ;; Return user-specific defaults. (define (read-user-defaults) (let ((file (expand-file-name "~/.scsh-pkg-defaults.scm"))) (if (file-exists? file) (let ((defaults (load-single-sexp file))) (eval (list 'quasiquote defaults) (interaction-environment))) '()))) (define (kind-lib? pkg-kind) (cond ((eq? pkg-kind 'library) #t) ((eq? pkg-kind 'program) #f) (else (error "invalid package kind" pkg-kind)))) (define (options-defaults pkg-kind) `((prefix . ,(if (kind-lib? pkg-kind) #f "/usr/local")) (dest-dir . "") (layout . ,(if (kind-lib? pkg-kind) "scsh" "fhs-program")) (build . ,(host)) (non-shared-only . #f) (inactive . ,(not (kind-lib? pkg-kind))) (dry-run . #f) (verbose . #f) (force . #f) (phases . ,all-phases) (exclude . ,(lambda args #f)))) ;; Partition PACKAGES in two sets: the ones which are not installed ;; yet, and the ones which are already. If FORCE? is true, pretend ;; that all packages are not installed yet. (define (partition-packages prefix layout packages force? non-shared-only?) (partition (lambda (pkg) (or force? (let ((abs-layout (absolute-layout (layout pkg) prefix))) (file-not-exists? (if non-shared-only? (paths->file-name (layout-dir abs-layout 'lib) (host)) (layout-dir abs-layout 'base)))))) packages)) (define (install-main-internal cmd-line display-hint?) (let* ((prog (file-name-nondirectory (car cmd-line))) (args (cdr cmd-line)) (packages (load&check-packages)) (all-pkg-opts (all-package-options packages))) (set! usage-string (build-usage-string prog (options 'library) all-pkg-opts)) (let* ((all-opts (append (options 'library) (map pkg-opt->option all-pkg-opts))) (all-dfts (append (alist-combine (if (member no-user-defaults-option args) '() (read-user-defaults)) (options-defaults 'library)) (map pkg-opt-key&default all-pkg-opts))) (options-values (parse-options args all-opts all-dfts)) (phases (alist-get 'phases options-values)) (prefix (alist-get 'prefix options-values)) (layout (alist-get 'layout options-values)) (force? (alist-get 'force options-values)) (non-shared-only? (alist-get 'non-shared-only options-values))) (if (null? packages) (display-error-and-exit "no package to install" (if (file-not-exists? package-definition-file) (as-string "\n(cannot find file called \"" package-definition-file "\" in current directory)") ""))) (if (not prefix) (display-error-and-exit "no prefix specified (use --prefix option)")) (if (not (file-name-absolute? prefix)) (display-error-and-exit "prefix must be an absolute path")) (let ((resolved-layout (resolve-layout layout))) (if (not resolved-layout) (display-error-and-exit "invalid layout "layout)) (if (and (not (lset= eq? phases all-phases)) (any (lambda (req) (versionoption all-pkg-opts))) (all-dfts (append (alist-combine (if (member no-user-defaults-option args) '() (read-user-defaults)) (options-defaults 'program)) (map pkg-opt-key&default all-pkg-opts))) (options-values (parse-options args all-opts all-dfts)) (prefix (alist-get 'prefix options-values)) (layout (alist-get 'layout options-values)) (force? (alist-get 'force options-values))) (if (null? packages) (display-error-and-exit "no package to install")) (if (not (file-name-absolute? prefix)) (display-error-and-exit "prefix must be an absolute path")) (let ((resolved-layout (resolve-layout layout))) (if (not resolved-layout) (display-error-and-exit "invalid layout "layout)) (install-packages packages options-values)))))