diff --git a/collects/compiler/compiler-unit.rkt b/collects/compiler/compiler-unit.rkt
index 43d7c509ba..c6906efd8b 100644
--- a/collects/compiler/compiler-unit.rkt
+++ b/collects/compiler/compiler-unit.rkt
@@ -144,12 +144,12 @@
(let ([zo (append-zo-suffix b)])
(compile-to-zo f zo n prefix verbose? mod?)))))
- (define (compile-directory-visitor dir info worker
- #:verbose [verbose? #t]
- #:skip-path [orig-skip-path #f]
- #:skip-doc-sources? [skip-docs? #f])
+ (define (compile-directory-visitor dir info worker omit-root
+ #:verbose [verbose? #t]
+ #:skip-path [orig-skip-path #f]
+ #:skip-doc-sources? [skip-docs? #f])
(define info* (or info (lambda (key mk-default) (mk-default))))
- (define omit-paths (omitted-paths dir c-get-info/full))
+ (define omit-paths (omitted-paths dir c-get-info/full omit-root))
(define skip-path (and orig-skip-path (path->bytes
(simplify-path (if (string? orig-skip-path)
(string->path orig-skip-path)
@@ -191,10 +191,10 @@
(for/fold ([init init]) ([p (directory-list dir)])
(let ([p* (build-path dir p)])
(if (and (directory-exists? p*) (not (member p omit-paths)))
- (compile-directory-visitor p* (c-get-info/full p*) worker
+ (compile-directory-visitor p* (c-get-info/full p*) worker omit-root
#:verbose verbose?
- #:skip-path skip-path
- #:skip-doc-sources? skip-docs?)
+ #:skip-path skip-path
+ #:skip-doc-sources? skip-docs?)
init))))
init))))
(define (compile-directory dir info
@@ -202,34 +202,43 @@
#:skip-path [orig-skip-path #f]
#:skip-doc-sources? [skip-docs? #f]
#:managed-compile-zo [managed-compile-zo
- (make-caching-managed-compile-zo)])
+ (make-caching-managed-compile-zo)]
+ #:omit-root [omit-root dir])
(define (worker prev sses)
(for-each managed-compile-zo sses))
- (compile-directory-visitor dir info worker
- #:verbose verbose?
- #:skip-path orig-skip-path
- #:skip-doc-sources? skip-docs?))
-
+ (compile-directory-visitor dir info worker omit-root
+ #:verbose verbose?
+ #:skip-path orig-skip-path
+ #:skip-doc-sources? skip-docs?))
+
(define (get-compile-directory-srcs dir info
- #:verbose [verbose? #t]
- #:skip-path [orig-skip-path #f]
- #:skip-doc-sources? [skip-docs? #f]
- #:managed-compile-zo [managed-compile-zo
- (make-caching-managed-compile-zo)])
- (compile-directory-visitor dir info append
- #:verbose verbose?
- #:skip-path orig-skip-path
- #:skip-doc-sources? skip-docs?
- #:managed-compile-zo managed-compile-zo))
+ #:verbose [verbose? #t]
+ #:skip-path [orig-skip-path #f]
+ #:skip-doc-sources? [skip-docs? #f]
+ #:managed-compile-zo [managed-compile-zo
+ (make-caching-managed-compile-zo)]
+ #:omit-root [omit-root dir])
+ (compile-directory-visitor dir info append omit-root
+ #:verbose verbose?
+ #:skip-path orig-skip-path
+ #:skip-doc-sources? skip-docs?
+ #:managed-compile-zo managed-compile-zo))
+
+ (define unspec (gensym))
(define (compile-collection-zos collection
#:skip-path [skip-path #f]
#:skip-doc-sources? [skip-docs? #f]
#:managed-compile-zo [managed-compile-zo
(make-caching-managed-compile-zo)]
+ #:omit-root [omit-root unspec]
. cp)
- (compile-directory (apply collection-path collection cp)
+ (define dir (apply collection-path collection cp))
+ (compile-directory dir
(c-get-info (cons collection cp))
+ #:omit-root (if (eq? omit-root unspec)
+ dir
+ omit-root)
#:verbose #f
#:skip-path skip-path
#:skip-doc-sources? skip-docs?
diff --git a/collects/config/.gitignore b/collects/config/.gitignore
new file mode 100644
index 0000000000..664f8291f2
--- /dev/null
+++ b/collects/config/.gitignore
@@ -0,0 +1 @@
+/links.rktd
diff --git a/collects/racket/sandbox.rkt b/collects/racket/sandbox.rkt
index 766c8623ea..0fb9aa9106 100644
--- a/collects/racket/sandbox.rkt
+++ b/collects/racket/sandbox.rkt
@@ -890,6 +890,7 @@
(current-library-collection-paths))
(read-bytecode ,(PLANET-BASE-DIR))
(exists ,(find-system-path 'addon-dir))
+ (read ,(find-system-path 'links-file))
,@(compute-permissions allow)
,@(sandbox-path-permissions))]
;; general info
diff --git a/collects/scribblings/guide/hash-languages.scrbl b/collects/scribblings/guide/hash-languages.scrbl
index 4cf5b57aee..3ffb116aaa 100644
--- a/collects/scribblings/guide/hash-languages.scrbl
+++ b/collects/scribblings/guide/hash-languages.scrbl
@@ -203,32 +203,50 @@ access languages like @filepath{literal.rkt} and
@filepath{literal.rkt} into a Racket @tech{collection} named
@filepath{literal}.
-To install a collection, you can create a directory either in the main
-Racket installation or in a user-specific directory. Use
-@racket[find-collects-dir] or @racket[find-user-collects-dir] from
-@racketmodname[setup/dirs] to find the directory:
+There are two ways to create the @filepath{literal} collection (see
+also @secref["link-collection"]):
-@interaction[
-(require setup/dirs)
-(eval:alts (find-user-collects-dir)
- (build-path "/home/racketeer/.racket/"
- (version)
- "collects"))
-]
+@itemlist[
-Move @filepath{literal.rkt} to @filepath{literal/lang/reader.rkt}
-within the directory reported by @racket[find-collects-dir] or
-@racket[find-user-collects-dir]. That is, the file
-@filepath{literal.rkt} must be renamed to @filepath{reader.rkt} and
-placed in a @filepath{lang} sub-directory of the @filepath{literal}
-collection.
+ @item{You can create a directory either in the main Racket
+ installation or in a user-specific directory. Use
+ @racket[find-collects-dir] or @racket[find-user-collects-dir]
+ from @racketmodname[setup/dirs] to find the directory:
+
+ @interaction[
+ (require setup/dirs)
+ (eval:alts (find-user-collects-dir)
+ (build-path "/home/racketeer/.racket/"
+ (version)
+ "collects"))
+ ]
+
+ Move @filepath{literal.rkt} to
+ @filepath{literal/lang/reader.rkt} within the directory reported
+ by @racket[find-collects-dir] or
+ @racket[find-user-collects-dir]. That is, the file
+ @filepath{literal.rkt} must be renamed to @filepath{reader.rkt}
+ and placed in a @filepath{lang} sub-directory of the
+ @filepath{literal} collection.
+
+ @racketblock[
+ .... @#,elem{(the main installation or the user's space)}
+ !- @#,filepath{collects}
+ !- @#,filepath{literal}
+ !- @#,filepath{lang}
+ !- @#,filepath{reader.rkt}
+ ]}
+
+ @item{Alternatively, move @filepath{literal.rkt} to
+ @filepath{literal/lang/reader.rkt} for any directory name
+ @filepath{literal}. Then, in the directory that contains
+ @filepath{literal}, use the command line
+
+ @commandline{raco link literal}
+
+ to register the @filepath{literal} directory as the
+ @filepath{literal} collection.}
-@racketblock[
-.... @#,elem{(the main installation or the user's space)}
- !- @#,filepath{collects}
- !- @#,filepath{literal}
- !- @#,filepath{lang}
- !- @#,filepath{reader.rkt}
]
After moving the file, you can use @racket[literal] directly after
@@ -247,17 +265,17 @@ for more information on using @exec{raco}.}
You can also package a collection for others to install by using the
@exec{raco pack} command-line tool:
-@commandline{raco pack --collection literal.plt literal}
+@commandline{raco pack --collect literal.plt literal}
Then, others can install the @filepath{literal} collection using
@exec{raco setup}:
-@commandline{raco setup literal.plt}
+@commandline{raco setup -A literal.plt}
@margin-note{See @other-manual['(lib "planet/planet.scrbl")] for more
information about @|PLaneT| packages.}
-A better approach may be to distribute your language as a @|PLaneT|
+Another approach is to distribute your language as a @|PLaneT|
package. A drawback of using a @|PLaneT| package is that users must
type @racket[@#,hash-lang[] @#,racketmodname[planet]] followed by a
@|PLaneT| path to access the language. The great advantages are that the
diff --git a/collects/scribblings/guide/module-basics.scrbl b/collects/scribblings/guide/module-basics.scrbl
index 666d4cdf29..e475f2851e 100644
--- a/collects/scribblings/guide/module-basics.scrbl
+++ b/collects/scribblings/guide/module-basics.scrbl
@@ -1,38 +1,47 @@
#lang scribble/doc
-@(require scribble/manual scribble/eval "guide-utils.rkt"
- (for-label setup/dirs))
+@(require scribble/manual
+ scribble/eval
+ "guide-utils.rkt"
+ "module-hier.rkt"
+ (for-label setup/dirs
+ setup/link
+ racket/date))
@title[#:tag "module-basics"]{Module Basics}
-The space of module names is distinct from the space of normal Racket
-definitions. Indeed, since modules typically reside in files, the
-space of module names is explicitly tied to the filesystem at run
-time. For example, if the file @filepath{/home/molly/cake.rkt} contains
+Each Racket module typically resides in its own file. For example,
+suppose the file @filepath{cake.rkt} contains the following module:
@racketmod[
+#:file "cake.rkt"
racket
(provide print-cake)
(code:comment @#,t{draws a cake with @racket[n] candles})
(define (print-cake n)
- (printf " ~a \n" (make-string n #\.))
- (printf " .-~a-.\n" (make-string n #\|))
- (printf " | ~a |\n" (make-string n #\space))
- (printf "---~a---\n" (make-string n #\-)))
+ (show " ~a " n #\.)
+ (show " .-~a-. " n #\|)
+ (show " | ~a | " n #\space)
+ (show "---~a---" n #\-))
+
+(define (show fmt n ch)
+ (printf fmt (make-string n ch))
+ (newline))
]
-then it can be used as the source of a module whose full name is based
-on the path @filepath{/home/molly/cake.rkt}. The @racket[provide] line
-exports the definition @racket[print-cake] so that it can be used
-outside the module.
+Then, other modules can import @filepath{cake.rkt} to use the
+@racket[print-cake] function, since the @racket[provide] line in
+@filepath{cake.rkt} explicitly exports the definition
+@racket[print-cake]. The @racket[show] function is private to
+@filepath{cake.rkt} (i.e., it cannot be used from other modules),
+since @racket[show] is not exported.
-Instead of using its full path, a module is more likely to be
-referenced by a relative path. For example, a file
-@filepath{/home/molly/random-cake.rkt} could use the @filepath{cake.rkt} module
-like this:
+The following @filepath{random-cake.rkt} module imports
+@filepath{cake.rkt}:
@racketmod[
+#:file "random-cake.rkt"
racket
(require "cake.rkt")
@@ -41,17 +50,90 @@ racket
]
The relative reference @racket["cake.rkt"] in the import
-@racket[(require "cake.rkt")] works because the @filepath{cake.rkt} module
-source is in the same directory as the @filepath{random-cake.rkt}
-file. (Unix-style relative paths are used for relative module
-references on all platforms, much like relative URLs.)
+@racket[(require "cake.rkt")] works if the @filepath{cake.rkt} and
+@filepath{random-cake.rkt} modules are in the same
+directory. (Unix-style relative paths are used for relative module
+references on all platforms, much like relative URLs in HTML pages.)
-Library modules that are distributed with Racket are usually
-referenced through an unquoted, suffixless path. The path is relative
-to the library installation directory, which contains directories for
-individual library @deftech{collections}. The module below refers to
-the @filepath{date.rkt} library that is part of the @filepath{racket}
-@tech{collection}.
+@; ----------------------------------------
+@section[#:tag "module-org"]{Organizing Modules}
+
+The @filepath{cake.rkt} and @filepath{random-cake.rkt} example
+demonstrates the most common way to organize a program into modules:
+put all module files in a single directory (perhaps with
+subdirectories), and then have the modules reference each other
+through relative paths. A directory of modules can act as a
+project, since it can be moved around on the filesystem or copied to
+other machines, and relative paths preserve the connections among
+modules.
+
+As another example, if you are building a candy-sorting program, you
+might have a main @filepath{sort.rkt} module that uses other modules
+to access a candy database and a control sorting machine. If the
+candy-database module itself is organized into sub-modules that handle
+barcode and manufacturer information, then the database module could
+be @filepath{db/lookup.rkt} that uses helper modules
+@filepath{db/barcodes.rkt} and @filepath{db/makers.rkt}. Similarly,
+the sorting-machine driver @filepath{machine/control.rkt} might use
+helper modules @filepath{machine/sensors.rkt} and
+@filepath{machine/actuators.rkt}.
+
+@centerline[module-hierarchy]
+
+The @filepath{sort.rkt} module uses the relative paths
+@filepath{db/lookup.rkt} and @filepath{machine/control.rkt} to import
+from the database and machine-control libraries:
+
+@racketmod[
+#:file "sort.rkt"
+racket
+(require "db/lookup.rkt" "machine/control.rkt")
+....]
+
+The @filepath{db/lookup.rkt} module similarly uses paths relative to
+its own source to access the @filepath{db/barcodes.rkt} and
+@filepath{db/makers.rkt} modules:
+
+
+@racketmod[
+#:file "db/lookup.rkt"
+racket
+(require "barcode.rkt" "makers.rkt")
+....]
+
+Ditto for @filepath{machine/control.rkt}:
+
+@racketmod[
+#:file "machine/control.rkt"
+racket
+(require "sensors.rkt" "actuators.rkt")
+....]
+
+Racket tools all work automatically with relative paths. For example,
+
+@commandline{racket sort.rkt}
+
+on the comamnd line runs the @filepath{sort.rkt} program and
+automatically loads and compiles required modules. With a large enough
+program, compilation from source can take too long, so use
+
+@commandline{raco make sort.rkt}
+
+to compile @filepath{sort.rkt} and all its dependencies to bytecode
+files. Running @exec{racket sort.rkt} will automatically use bytecode
+files when they are present.
+
+@margin-note{See @secref[#:doc '(lib "scribblings/raco/raco.scrbl")
+"make"] for more information on @exec{raco make}.}
+
+@; ----------------------------------------
+@section{Library Collections}
+
+A @deftech{collection} is a set of installed library modules. A
+module in a @tech{collection} is referenced through an unquoted,
+suffixless path. For example, the following module refers to the
+@filepath{date.rkt} library that is part of the @filepath{racket}
+@tech{collection}:
@racketmod[
racket
@@ -62,12 +144,41 @@ racket
(date->string (seconds->date (current-seconds))))
]
-In addition to the main @tech{collection} directory, which contains
-all collections that are part of the installation, collections can
-also be installed in a user-specific location. Finally, additional
-collection directories can be specified in configuration files or
-through the @envvar{PLTCOLLECTS} search path. Try running the
-following program to find out where your collections are:
+When you search the online Racket documentation, the search results
+indicate the module that provides each binding. Alternatively, if you
+reach a binding's documentation by clicking on hyperlinks, you can
+hover over the binding name to find out which modules provide
+it.
+
+A module reference like @racketmodname[racket/date] looks like an
+identifier, but it is not treated in the same way as @racket[printf]
+or @racket[date->string]. Instead, when @racket[require] sees a module
+reference that is unquoted, it converts the reference to a
+collection-based module path:
+
+@itemlist[
+
+ @item{First, if the unquoted path contains no @litchar{/}, then
+ @racket[require] automatically adds a @filepath{/main} to the
+ reference. For example, @racket[(require
+ @#,racketmodname[slideshow])] is equivalent to @racket[(require
+ slideshow/main)].}
+
+ @item{Second, @racket[require] implicitly adds a @filepath{.rkt}
+ suffix to the path.}
+
+ @item{Finally, @racket[require] treats the path as relative to the
+ installation location of the collection, instead of relative to
+ the enclosing module's path.}
+
+]
+
+The @filepath{racket} collection is located in a directory with the
+Racket installation. A user-specific directory can contain additional
+collections, and even more collection directories can be specified in
+configuration files or through the @envvar{PLTCOLLECTS} search
+path. Try running the following program to find out how your
+collection search path is configured:
@racketmod[
racket
@@ -79,5 +190,84 @@ racket
(get-collects-search-dirs) (code:comment @#,t{complete search path})
]
-We discuss more forms of module reference later in
-@secref["module-paths"].
+@; ----------------------------------------
+@section[#:tag "link-collection"]{Adding Collections}
+
+Looking back at the candy-sorting example of @secref["module-org"],
+suppose that modules in @filepath{db/} and @filepath{machine/} need a
+common set of helper functions. Helper functions could be put in a
+@filepath{utils/} directory, and modules in @filepath{db/} or
+@filepath{machine/} could access utility modules with relative paths
+that start @filepath{../utils/}. As long as a set of modules work
+together in a single project, it's best to stick with relative paths.
+A programmer can follow relative-path references without knowing about
+your Racket configuration.
+
+Some libraries are meant to be used across multiple projects, so that
+keeping the library source in a directory with its uses does not make
+sense. In that case, you have two options:
+
+@itemlist[
+
+ @item{Add the library to a new or existing @tech{collection}. After
+ the library is in a collection, it can be referenced with an
+ unquoted path, just like libraries that are included with the
+ Racket distribution.}
+
+ @item{Add the library a new or existing @|PLaneT| package. Libraries
+ in a @|PLaneT| package are referenced with a path of the form
+ @racket[(planet ....)] path.
+
+ @margin-note{See @other-doc['(lib "planet/planet.scrbl")]
+ for more information on @|PLaneT|.}}
+
+]
+
+The simplest option is to add a new collection. You could add a new
+collection by placing files in the Racket installation or one of the
+directories reported by @racket[(get-collects-search-dirs)]---perhaps
+setting the @envvar{PLTCOLLECTS} environment variable to extend the
+search path---but using @exec{raco link} is usually the best approach.
+
+The @exec{raco link} command-line tool creates a link from a collection
+name to a directory for the collection's modules. For example, suppose
+you have a directory @filepath{/usr/molly/bakery} that contains the
+@filepath{cake.rkt} module (from the
+@seclink["module-basics"]{beginning} of this section) and other
+related modules. To make the modules available as a @filepath{bakery}
+collection, use
+
+@commandline{raco link /usr/molly/bakery}
+
+Afterward, @racket[(require bakery/cake)] from any module will import
+the @racket[print-cake] function from
+@filepath{/usr/molly/bakery/cake.rkt}.
+
+To make a collection name different from the name of the directory
+that contains the collection's modules, use the @DFlag{name} or
+@Flag{n} option for @exec{raco link}. By default, @exec{raco link}
+installs a collection link only for the current user, but you can
+supply the @DFlag{installation} or @Flag{i} flag to install the link
+for all users of your Racket installation.
+
+@margin-note{See @secref[#:doc '(lib "scribblings/raco/raco.scrbl")
+"link"] for more information on @exec{raco link}.}
+
+If you intend to distribute your library collection to others, choose
+the collection name carefully. The collection namespace is
+hierarchical, but (unlike @|PLaneT|) the collection system has no
+built-in feature to avoid conflicts from different producers or
+different versions. Consider putting one-off libraries under some
+top-level name like @filepath{molly} that identifies the producer.
+Use a collection name like @filepath{bakery} when producing the
+definitive collection of baked-goods libraries.
+
+After your libraries are in a @tech{collection}, then you can still
+use @exec{raco make} to compile the library sources, but it's better
+and more convenient to use @exec{raco setup}. The @exec{raco setup}
+command takes a collection name (as opposed to a file name) and
+compiles all libraries within the collection. In addition, it can
+build documentation for the collection and add it to the documentation
+index, as specified by a @filepath{info.rkt} module in the collection.
+See @secref[#:doc '(lib "scribblings/raco/raco.scrbl") "setup"] for
+more information on @exec{raco setup}.
diff --git a/collects/scribblings/guide/module-hier.rkt b/collects/scribblings/guide/module-hier.rkt
new file mode 100644
index 0000000000..ab2196aa54
--- /dev/null
+++ b/collects/scribblings/guide/module-hier.rkt
@@ -0,0 +1,97 @@
+#lang racket/base
+(require slideshow/pict
+ racket/draw
+ racket/class
+ racket/math)
+
+(provide module-hierarchy)
+
+(define GAP 12)
+
+(define file-color (make-object color% #xEC #xF5 #xF5))
+
+(define folder
+ (let ()
+ (define W 200)
+ (define H 144)
+ (define dy (* -8/3 2))
+ (define p (make-object dc-path%))
+ (send p move-to 0 50)
+ (send p arc 0 (+ 22 dy) 8 8 pi (/ pi 2) #f)
+ (send p arc 2 (+ 18 dy) 4 4 (/ pi -2) 0 #t)
+ (send p arc 6 0 20 20 pi (/ pi 2) #f)
+ (send p line-to 60 0)
+ (send p arc 50 0 20 20 (/ pi 2) 0 #f)
+ (send p arc 70 (+ 22 dy) 2 2 pi (* 3/2 pi))
+ (send p arc 180 (+ 24 dy) 20 20 (/ pi 2) 0 #f)
+ (send p arc 180 120 20 20 0 (/ pi -2) #f)
+ (send p arc 0 120 20 20 (/ pi -2) (- pi) #f)
+ (send p close)
+
+ (scale
+ (dc (lambda (dc x y)
+ (define b (send dc get-brush))
+ (send dc set-brush file-color 'solid)
+ (send dc draw-path p x y)
+ (send dc set-brush b))
+ W H)
+ 12/32)))
+
+(define file
+ (file-icon (/ 75 2) 54 file-color))
+
+(define (lbl i t)
+ (vc-append 4 i (text t '(bold . modern) 12)))
+
+(define (listing p)
+ (frame (inset p GAP)
+ #:color "blue"))
+
+(define db-folder (launder folder))
+(define mach-folder (launder folder))
+(define db-listing
+ (listing
+ (vc-append
+ GAP
+ (lbl file "control.rkt")
+ (hc-append (* 2 GAP)
+ (lbl file "sensors.rkt")
+ (lbl file "actuators.rkt")))))
+(define mach-listing
+ (listing
+ (vc-append
+ GAP
+ (lbl file "lookup.rkt")
+ (hc-append (* 2 GAP)
+ (lbl file "barcodes.rkt")
+ (lbl file "makers.rkt")))))
+
+(define (zoom from to p)
+ (pin-line
+ (pin-line p
+ from lb-find
+ to lt-find
+ #:style 'dot)
+ from rb-find
+ to rt-find
+ #:style 'dot))
+
+
+(define module-hierarchy
+ (inset
+ (zoom
+ db-folder db-listing
+ (zoom
+ mach-folder mach-listing
+ (vc-append
+ (* 3 GAP)
+ (listing
+ (hc-append (* 4 GAP)
+ (lbl file "sort.rkt")
+ (lbl db-folder "db")
+ (lbl mach-folder "machine")))
+ (hc-append
+ (* 2 GAP)
+ db-listing
+ mach-listing))))
+ 2))
diff --git a/collects/scribblings/guide/welcome.scrbl b/collects/scribblings/guide/welcome.scrbl
index cad0a39f76..a5fab120c0 100644
--- a/collects/scribblings/guide/welcome.scrbl
+++ b/collects/scribblings/guide/welcome.scrbl
@@ -162,9 +162,14 @@ racket
(extract "the cat out of the bag")
]
-then it is a complete program that prints ``cat'' when run. To
-package this program as an executable, choose one of the following
-options:
+then it is a complete program that prints ``cat'' when run. You can
+run the program within DrRacket or using @racket[enter!] in
+@exec{racket}, but if the program is saved in @nonterm{src-filename},
+you can also run it from a command line with
+
+@commandline{racket @nonterm{src-filename}}
+
+To package the program as an executable, you have a few options:
@itemize[
diff --git a/collects/scribblings/raco/common.rkt b/collects/scribblings/raco/common.rkt
index 378cffeaff..983db069ba 100644
--- a/collects/scribblings/raco/common.rkt
+++ b/collects/scribblings/raco/common.rkt
@@ -1,7 +1,11 @@
#lang scheme/base
(require scribble/manual)
-(provide inside-doc)
+(provide inside-doc
+ reference-doc)
(define inside-doc
'(lib "scribblings/inside/inside.scrbl"))
+
+(define reference-doc
+ '(lib "scribblings/reference/reference.scrbl"))
diff --git a/collects/scribblings/raco/link.scrbl b/collects/scribblings/raco/link.scrbl
new file mode 100644
index 0000000000..452471e6f6
--- /dev/null
+++ b/collects/scribblings/raco/link.scrbl
@@ -0,0 +1,107 @@
+#lang scribble/doc
+@(require scribble/manual
+ scribble/bnf
+ "common.rkt"
+ (for-label racket/base))
+
+@title[#:tag "link"]{@exec{raco link}: Library Collection Links}
+
+The @exec{raco link} command inspects and modifies a @tech[#:doc
+reference-doc]{collection links file} to display, add, or remove
+mappings from collection names to filesystem directories.
+
+For example, the command
+
+@commandline{raco link maze}
+
+installs a user-specific link for the @racket["maze"] collection,
+mapping it to the @filepath{maze} subdirectory of the current
+directory. Supply multiple directory paths to create multiple links at
+once, especially with a command-shell wildcard:
+
+@commandline{raco link *}
+
+By default, the linked collection name is the same as each directory's
+name, but the collection name can be set separately for a single
+directory with the @DFlag{name} flag.
+
+To remove the link created by the first example above, use
+
+@commandline{raco link --remove maze}
+
+or
+
+@commandline{raco link -r maze}
+
+Like link-adding mode, removing mode accepts multiple directory paths to
+remove multiple links, and all links that match any directory are
+removed. If @DFlag{name} is used with @DFlag{remove}, then only
+links matching both the collection name and directory are removed.
+
+Full command-line options:
+
+@itemlist[
+
+ @item{@Flag{s} or @DFlag{show} --- Shows the current link table. If
+ any other command-line arguments are provided that modify the
+ link table, the table is shown after modifications. If no
+ directory arguments are provided, and if none of @Flag{r},
+ @DFlag{remove}, @Flag{i}, @DFlag{installation}, @Flag{f}, or
+ @DFlag{file} are specified, then the link table is shown for
+ both the user-specific and installation-wide @tech[#:doc
+ reference-doc]{collection links files}.}
+
+ @item{@Flag{n} @nonterm{name} or @DFlag{name} @nonterm{name} --- Sets
+ the collection name for adding or removing a single link. By
+ default, the collection name for an added link is derived from
+ the directory name. When the @Flag{r} or @DFlag{remove} flag is
+ also used, only links with a collection name matching
+ @nonterm{name} are removed.}
+
+ @item{@Flag{x} @nonterm{regexp} or @DFlag{version-regexp}
+ @nonterm{regexp} --- Sets a version regexp that limits the link
+ to use only by Racket versions (as reported by
+ @racket[version]) matching @nonterm{regexp}. When the @Flag{r}
+ or @DFlag{remove} flag is also used, only links with a
+ version regexp matching @nonterm{regexp} are removed.}
+
+ @item{@Flag{i} or @DFlag{installation} --- Reads and writes links in
+ installation-wide @tech[#:doc reference-doc]{collection links
+ file} instead of the user-specific @tech[#:doc
+ reference-doc]{collection links file}. This flag is mutally
+ exclusive with @Flag{f} and @DFlag{file}.}
+
+ @item{@Flag{f} @nonterm{file} or @DFlag{file} @nonterm{file} ---
+ Reads and writes links in @nonterm{file} instead of the
+ user-specific @tech[#:doc reference-doc]{collection links
+ file}. This flag is mutally exclusive with @Flag{i} and
+ @DFlag{installation}.}
+
+ @item{@DFlag{repair} --- Enables repairs to the existing file content
+ when the content is erroneous. The file is repaired by deleting
+ individual links when possible.}
+
+]
+
+@; ----------------------------------------
+
+@section{API for Collection Links}
+
+@defmodule[setup/link]
+
+@defproc[(links [dirs (listof path?)]
+ [#:file file path-string? (find-system-path 'links-file)]
+ [#:name name (or/c string? #f) #f]
+ [#:version-regexp version-regexp (or/c regexp? #f) #f]
+ [#:error error-proc (symbol? string? any/c ... . -> . any) error]
+ [#:remove? remove? any/c #f]
+ [#:show? show? any/c #f]
+ [#:repair? repair? any/c #f])
+ (listof string?)]{
+
+A function version of the @exec{raco link} command. The
+@racket[error-proc] argument is called to raise exceptions that would
+be fatal to the @exec{raco link} command.
+
+The result is a list of top-level collections that are mapped by
+@racket[file] and that apply to the running version of Racket.}
diff --git a/collects/scribblings/raco/raco.scrbl b/collects/scribblings/raco/raco.scrbl
index a5585a65b6..e14f55ef57 100644
--- a/collects/scribblings/raco/raco.scrbl
+++ b/collects/scribblings/raco/raco.scrbl
@@ -16,6 +16,7 @@ a typical Racket installation.
@table-of-contents[]
@include-section["make.scrbl"]
+@include-section["link.scrbl"]
@include-section["exe.scrbl"]
@include-section["dist.scrbl"]
@include-section["plt.scrbl"]
diff --git a/collects/scribblings/raco/setup.scrbl b/collects/scribblings/raco/setup.scrbl
index ff878e8e37..367a5d1772 100644
--- a/collects/scribblings/raco/setup.scrbl
+++ b/collects/scribblings/raco/setup.scrbl
@@ -2,6 +2,7 @@
@(require scribble/manual
scribble/bnf
+ "common.rkt"
(for-label racket
racket/future
setup/setup-unit
@@ -1086,16 +1087,13 @@ An @deftech{unpackable} is one of the following:
@defproc[(find-relevant-directories
(syms (listof symbol?))
- (mode (symbols 'preferred 'all-available) 'preferred)) (listof path?)]{
+ (mode (or/c 'preferred 'all-available 'no-planet) 'preferred)) (listof path?)]{
Returns a list of paths identifying installed directories (i.e.,
collections and installed @|PLaneT| packages) whose
@filepath{info.rkt} file defines one or more of the given
symbols. The result is based on a cache that is computed by
- @exec{raco setup} and stored in the @indexed-file{info-domain}
- sub-directory of each collection directory (as determined by the
- @envvar{PLT_COLLECTION_PATHS} environment variable, etc.) and the
- file @filepath{cache.rkt} in the user add-on directory.
+ @exec{raco setup}.
Note that the cache may be out of date by the time you call
@racket[get-info/full], so do not assume that it won't return
@racket[#f].
@@ -1105,20 +1103,27 @@ An @deftech{unpackable} is one of the following:
providing to @racket[get-info/full].
If @racket[mode] is specified, it must be either
- @racket['preferred] (the default) or @racket['all-available]. If
- mode is @racket['all-available], @racket[find-relevant-collections]
+ @racket['preferred] (the default), @racket['all-available], or @racket[no-planet]. If
+ @racket[mode] is @racket['all-available], @racket[find-relevant-collections]
returns all installed directories whose info files contain the
specified symbols---for instance, all installed PLaneT packages
- will be searched if @racket['all-available] is specified. If mode
+ will be searched if @racket['all-available] is specified. If @racket[mode]
is @racket['preferred], then only a subset of ``preferred''
- packages will be searched, and in particular only the directory
+ packages will be searched: only the directory
containing the most recent version of any PLaneT package will be
- returned.
+ returned. If @racket[mode] is @racket['no-planet], then only PLaneT
+ packages are not included in the search.
No matter what @racket[mode] is specified, if more than one
collection has the same name, @racket[find-relevant-directories]
- will only search the one that occurs first in the
- @envvar{PLT_COLLECTION_PATHS} environment variable.}
+ will only search the one that occurs first in a search that through
+ the directories of @racket[current-library-collection-paths].
+ Collection links from the installation-wide @tech[#:doc
+ reference-doc]{collection links file} are cached with the
+ installation's main @filepath{collects} directory, and links from
+ the user-specific @tech[#:doc reference-doc]{collection links file}
+ are cached with the user-specific directory @racket[(build-path
+ (find-system-path 'addon-dir) (version) "collects")].}
@defproc[(find-relevant-directory-records
[syms (listof symbol?)]
diff --git a/collects/scribblings/reference/collects.scrbl b/collects/scribblings/reference/collects.scrbl
index 950be7f835..d26e60ca84 100644
--- a/collects/scribblings/reference/collects.scrbl
+++ b/collects/scribblings/reference/collects.scrbl
@@ -5,10 +5,10 @@
A @deftech{library} is @racket[module] declaration for use by multiple
programs. Racket further groups libraries into @deftech{collections}
-that can be easily distributed and easily added to a local Racket
+that can be easily distributed and added to a local Racket
installation.
-Some collections are distributed via @|PLaneT|. Such collections are
+Some libraries are distributed via @|PLaneT| packages. Such libraries are
referenced through a @racket[planet] module path (see
@racket[require]) and are downloaded by Racket on demand.
@@ -17,9 +17,11 @@ collection is a directory that is located in a @filepath{collects}
directory relative to the Racket executable. A collection can also be
installed in a user-specific directory. More generally, the search
path for installed collections can be configured through the
-@racket[current-library-collection-paths] parameter. In all of these
-cases, the collections are referenced through @racket[lib] paths (see
-@racket[require]).
+@racket[current-library-collection-paths] parameter. Finally, the
+location of collections can be specified through the @tech{collection
+links files}; see @secref["links-file"] for more information. In all
+of these cases, the collections are referenced through @racket[lib]
+paths (see @racket[require]) or symbolic shorthands.
For example, the following module uses the @filepath{getinfo.rkt}
library module from the @filepath{setup} collection, and the
@@ -33,7 +35,8 @@ racket
....
]
-This example is more compactly and more commonly written as
+This example is more compactly and more commonly written using
+symbolic shorthands:
@racketmod[
racket
@@ -60,14 +63,16 @@ resolver}, as specified by the @racket[current-module-name-resolver]
parameter.
For the default @tech{module name resolver}, the search path for
-collections is determined by the
-@racket[current-library-collection-paths] parameter. The list of paths
-in @racket[current-library-collection-paths] is searched from first to
+collections is determined by the content of @racket[(find-system-path
+'links-file)] (if it exists) and the
+@racket[current-library-collection-paths] parameter. The collection
+links and then list of paths in
+@racket[current-library-collection-paths] is searched from first to
last to locate the first that contains @racket[_rel-string]. In other
-words, the filesystem tree for each element in the search path is
-spliced together with the filesystem trees of other path
-elements. Some Racket tools rely on unique resolution of module path
-names, so an installation and
+words, the filesystem tree for each element in the link table and
+search path is spliced together with the filesystem trees of other
+path elements. Some Racket tools rely on unique resolution of module
+path names, so an installation and
@racket[current-library-collection-paths] configuration should not
allow multiple files to match the same collection and file name.
@@ -156,3 +161,46 @@ the directory produced by @racket[(find-system-path 'addon-dir)], are
included in search paths for collections and other files. For example,
@racket[find-library-collection-paths] omits the user-specific
collection directory when this parameter's value is @racket[#f].}
+
+@; ----------------------------------------------------------------------
+
+@section[#:tag "links-file"]{Collection Links}
+
+The @deftech{collection links files} are used by
+@racket[collection-file-path], @racket[collection-path], and the
+default @tech{module name resolver} to locate collections before
+trying the @racket[(current-library-collection-paths)] search
+path. Furthermore, a user-specific @tech{collection links file} takes
+precedence over an installation-wide @tech{collection links file}, but
+the user-specific @tech{collection links file} is used only the
+@racket[use-user-specific-search-paths] parameter is set to
+@racket[#t].
+
+The path of the user-specific @tech{collection links file} is by
+@racket[(find-system-path 'links-file)], while an installation-wide
+@tech{collection links file} is @filepath{links.rktd} in the
+@filepath{config} collection within the installation's main collection
+directory. Each @tech{collection links file} is cached by Racket, but
+the file is re-read if its timestamp changes.
+
+Each @tech{collection links file} is @racket[read] with default reader
+parameter settings to obtain a list. Every element of the list must be
+a link specification with either the form @racket[(_string _path)] or
+the form @racket[(_string _path _regexp)]. In both cases, the
+@racket[_string] names a top-level @tech{collection}, and
+@racket[_path] is a path that can be used as the collection's path
+(directly, as opposed to a subdirectory of @racket[_path] named by
+@racket[_string]). If @racket[_path] is a relative path, it is
+relative to the directory containing the @tech{collection links
+file}. If @racket[_regexp] is specified in a link, then the link is
+used only if @racket[(regexp-match? _regexp (version))] produces a
+true result.
+
+A single top-level collection can have multiple links in a
+@tech{collection links file}. The corresponding paths are effectively
+spliced together, since the paths are tried in order to locate a file
+or sub-collection.
+
+The @exec{raco link} command-link tool can display, install, and
+remove links in the @tech{collection links file}. See @secref[#:doc
+raco-doc "link"] in @other-manual[raco-doc] for more information.
diff --git a/collects/scribblings/reference/filesystem.scrbl b/collects/scribblings/reference/filesystem.scrbl
index 7c6923c6fe..65a4e3accc 100644
--- a/collects/scribblings/reference/filesystem.scrbl
+++ b/collects/scribblings/reference/filesystem.scrbl
@@ -85,8 +85,17 @@ by @racket[kind], which must be one of the following:
]}
+ @item{@indexed-racket['links-file] --- the user-specific
+ @tech{collection links file} for specifying the location of library
+ @tech{collections}. This file is specified by the
+ @indexed-envvar{PLTLINKSFILE} environment variable, and it can be
+ overridden by the @DFlag{links} or @Flag{C} command-line flag. If no
+ environment variable or flag is specified, or if the value is not a
+ legal path name, then this file defaults to @filepath{links.rktd} in
+ the directory reported by @racket[(find-system-path 'addon-dir)].}
+
@item{@indexed-racket['addon-dir] --- a directory for installing
- Racket extensions. This directory is specified by the
+ user-specific Racket extensions. This directory is specified by the
@indexed-envvar{PLTADDONDIR} environment variable, and it can be
overridden by the @DFlag{addon} or @Flag{A} command-line flag. If no
environment variable or flag is specified, or if the value is not a
diff --git a/collects/scribblings/reference/mz.rkt b/collects/scribblings/reference/mz.rkt
index 241cb8afcf..61b42f2d18 100644
--- a/collects/scribblings/reference/mz.rkt
+++ b/collects/scribblings/reference/mz.rkt
@@ -91,7 +91,8 @@
(provide margin-note/ref
refalso moreref Guide guideintro guidealso guidesecref
- HonuManual)
+ HonuManual
+ raco-doc)
(define (margin-note/ref . s)
(apply margin-note
@@ -127,6 +128,9 @@
(define HonuManual
(other-manual '(lib "scribblings/honu/honu.scrbl")))
+
+ (define raco-doc
+ '(lib "scribblings/raco/raco.scrbl"))
(provide speed)
(define-syntax speed
diff --git a/collects/scribblings/reference/startup.scrbl b/collects/scribblings/reference/startup.scrbl
index 228ac08e93..fcca28afc8 100644
--- a/collects/scribblings/reference/startup.scrbl
+++ b/collects/scribblings/reference/startup.scrbl
@@ -250,6 +250,15 @@ flags:
the @Flag{S}/@DFlag{dir} flag is supplied multiple times, the
search order is as supplied.}
+ @item{@FlagFirst{A} @nonterm{dir} or @DFlagFirst{addon}
+ @nonterm{dir} : Sets the directory that is returned by
+ @racket[(find-system-path 'addon-dir)].}
+
+ @item{@FlagFirst{C} @nonterm{file} or @DFlagFirst{links}
+ @nonterm{file} : Sets the user-specific @tech{collection links file} path
+ that is returned by @racket[(find-system-path 'links-file)];
+ see also @secref["links-file"].}
+
@item{@FlagFirst{U} or @DFlagFirst{no-user-path} : Omits
user-specific paths in the search for collections, C
libraries, etc. by initializing the
@@ -405,8 +414,9 @@ language specifies run-time configuration by
A @racket['configure-runtime] query returns a list of vectors, instead
of directly configuring the environment, so that the indicated modules
-to be bundled with a program when creating a stand-alone
-executable; see @secref[#:doc '(lib "scribblings/raco/raco.scrbl") "exe"].
+to be bundled with a program when creating a stand-alone executable;
+see @secref[#:doc raco-doc "exe"] in
+@other-manual[raco-doc].
For information on defining a new @hash-lang[] language, see
@racketmodname[syntax/module-reader].
diff --git a/collects/setup/collects.rkt b/collects/setup/collects.rkt
index e000181383..31c5c7d6fc 100644
--- a/collects/setup/collects.rkt
+++ b/collects/setup/collects.rkt
@@ -3,6 +3,6 @@
(provide (struct-out cc))
(define-struct cc
- (collection path name info root-dir info-path shadowing-policy)
+ (collection path name info omit-root info-root info-path info-path-mode shadowing-policy)
#:inspector #f)
diff --git a/collects/setup/commands/link.rkt b/collects/setup/commands/link.rkt
new file mode 100644
index 0000000000..0fc453197b
--- /dev/null
+++ b/collects/setup/commands/link.rkt
@@ -0,0 +1,74 @@
+#lang scheme/base
+(require racket/cmdline
+ raco/command-name
+ "../link.rkt")
+
+(define link-file (make-parameter #f))
+(define link-name (make-parameter #f))
+(define link-version (make-parameter #f))
+(define remove-mode (make-parameter #f))
+(define repair-mode (make-parameter #f))
+(define show-mode (make-parameter #f))
+(define user-mode (make-parameter #t))
+
+(define link-symbol (string->symbol (short-program+command-name)))
+
+(define dirs
+ (command-line
+ #:program (short-program+command-name)
+ #:once-each
+ [("-s" "--show") "Show the link table (after changes)"
+ (show-mode #t)]
+ [("-n" "--name") name "Set the collection name (for a single directory)"
+ (link-name name)]
+ [("-x" "--version-regexp") regexp "Set the version pregexp"
+ (with-handlers ([exn:fail:contract? (lambda (exn)
+ (raise-user-error link-symbol
+ "bad version regexp: ~a"
+ regexp))])
+ (link-version (pregexp regexp)))]
+ [("-r" "--remove") "Remove links for the specified directories"
+ (remove-mode #t)]
+ #:once-any
+ [("-i" "--installation") "Adjust user-independent links in the installation"
+ (user-mode #f)]
+ [("-f" "--file") file "Select an alternate link file"
+ (link-file (path->complete-path file))]
+ #:once-each
+ [("--repair") "Enable repair mode to fix existing links"
+ (repair-mode #t)]
+ #:args
+ dir dir))
+
+(when (and (link-name)
+ (not (= 1 (length dirs))))
+ (raise-user-error link-symbol
+ "expected a single directory for `--name' mode"))
+
+(define show-both?
+ (and (null? dirs)
+ (show-mode)
+ (user-mode)
+ (not (remove-mode))
+ (not (link-file))))
+
+(when show-both?
+ (printf "User links:\n"))
+
+(void
+ (apply links
+ dirs
+ #:user? (user-mode)
+ #:file (link-file)
+ #:name (link-name)
+ #:version-regexp (link-version)
+ #:error (lambda (who . args)
+ (apply raise-user-error link-symbol args))
+ #:remove? (remove-mode)
+ #:show? (show-mode)
+ #:repair? (repair-mode)))
+
+(when show-both?
+ (printf "Installation links:\n")
+ (void (links #:user? #f #:show? #t)))
+
diff --git a/collects/setup/getinfo.rkt b/collects/setup/getinfo.rkt
index 6b03ae72ec..748a625ee0 100644
--- a/collects/setup/getinfo.rkt
+++ b/collects/setup/getinfo.rkt
@@ -88,6 +88,7 @@
(define preferred-table #f)
(define all-available-table #f)
+(define no-planet-table #f)
;; reset-relevant-directories-state! : -> void
(define (reset-relevant-directories-state!)
@@ -104,7 +105,8 @@
(list i)
l))))
#f #f))
- (set! all-available-table (make-table cons #f #f)))
+ (set! all-available-table (make-table cons #f #f))
+ (set! no-planet-table (make-table cons #f #f)))
(reset-relevant-directories-state!)
@@ -160,20 +162,23 @@
(define t
(cond [(eq? key 'preferred) preferred-table]
[(eq? key 'all-available) all-available-table]
+ [(eq? key 'no-planet) no-planet-table]
[else (error 'find-relevant-directories "Invalid key: ~s" key)]))
;; A list of (cons cache.rktd-path root-dir-path)
;; If root-dir-path is not #f, then paths in the cache.rktd
;; file are relative to it. #f is used for the planet cache.rktd file.
(define search-path
- (cons (cons user-infotable #f)
- (map (lambda (coll)
- (cons (build-path coll "info-domain" "compiled" "cache.rktd")
- coll))
- (current-library-collection-paths))))
- (unless (equal? (table-paths t) search-path)
- (set-table-ht! t (make-hasheq))
- (set-table-paths! t search-path)
- (populate-table! t))
+ ((if (eq? key 'no-planet) (lambda (a l) l) cons)
+ (cons user-infotable #f)
+ (map (lambda (coll)
+ (cons (build-path coll "info-domain" "compiled" "cache.rktd")
+ coll))
+ (current-library-collection-paths))))
+ (when t
+ (unless (equal? (table-paths t) search-path)
+ (set-table-ht! t (make-hasheq))
+ (set-table-paths! t search-path)
+ (populate-table! t)))
(let ([unsorted
(if (= (length syms) 1)
;; Simple case: look up in table
@@ -205,7 +210,7 @@
(get-info/full ((path?) (#:namespace (or/c namespace? #f)) . ->* . (or/c info? boolean?)))
(find-relevant-directories
(->* [(listof symbol?)]
- [(lambda (x) (memq x '(preferred all-available)))]
+ [(lambda (x) (memq x '(preferred all-available no-planet)))]
(listof path?)))
(struct directory-record
([maj integer?]
@@ -215,5 +220,5 @@
[syms (listof symbol?)]))
(find-relevant-directory-records
(->* [(listof symbol?)]
- [(or/c 'preferred 'all-available)]
+ [(or/c 'preferred 'all-available 'no-planet)]
(listof directory-record?))))
diff --git a/collects/setup/info.rkt b/collects/setup/info.rkt
index 3d15e3543c..6af9d1548a 100644
--- a/collects/setup/info.rkt
+++ b/collects/setup/info.rkt
@@ -5,4 +5,5 @@
(define mzscheme-launcher-libraries '("main.rkt"))
(define mzscheme-launcher-names '("Setup PLT"))
-(define raco-commands '(("setup" setup/main "install and build libraries and documentation" 90)))
+(define raco-commands '(("setup" setup/main "install and build libraries and documentation" 90)
+ ("link" setup/commands/link "manage library-collection directories" 80)))
diff --git a/collects/setup/link.rkt b/collects/setup/link.rkt
new file mode 100644
index 0000000000..cd659bf72e
--- /dev/null
+++ b/collects/setup/link.rkt
@@ -0,0 +1,157 @@
+#lang scheme/base
+(require racket/file
+ setup/dirs)
+
+(provide links)
+
+(define (links #:error [error error]
+ #:user? [user? #t]
+ #:file [in-file #f]
+ #:name [name #f]
+ #:version-regexp [version-regexp #f]
+ #:remove? [remove? #f]
+ #:show? [show? #f]
+ #:repair? [repair? #f]
+ . dirs)
+ (define file (or in-file
+ (if user?
+ (find-system-path 'links-file)
+ (let ([d (find-collects-dir)])
+ (if d
+ (build-path d "config" "links.rktd")
+ (error 'links
+ "cannot find installation collections path"))))))
+
+ (define need-repair? #f)
+
+ (define (content-error str v)
+ (if repair?
+ (begin
+ (log-warning (format "~a~e" str v))
+ (set! need-repair? #t)
+ #f)
+ (error 'links "~a~e" str v)))
+
+ (define table
+ (with-handlers ([exn:fail?
+ (lambda (exn)
+ (let ([msg (format
+ "error reading from link file: ~s: ~a"
+ file
+ (exn-message exn))])
+ (if repair?
+ (begin
+ (log-warning msg)
+ (set! need-repair? #t)
+ null)
+ (error 'links "~a" msg))))])
+ (if (file-exists? file)
+ (let ([l (with-input-from-file file read)])
+ (if (list? l)
+ (for/list ([e (in-list l)]
+ #:when
+ (or (and (list? e)
+ (or (= 2 (length e))
+ (= 3 (length e))))
+ (content-error "entry is a not a 2- or 3-element list: " e))
+ #:when
+ (or (string? (car e))
+ (content-error "entry's first element is not a string: " e))
+ #:when
+ (or (path-string? (cadr e))
+ (content-error "entry's second element is not a path string: " e))
+ #:when
+ (or (null? (cddr e))
+ (regexp? (caddr e))
+ (content-error "entry's third element is not a version regexp: " e)))
+ e)
+ (begin
+ (content-error "content is not a list: " l)
+ null)))
+ null)))
+
+ (define mapped (make-hash))
+
+ (define (add-entry! e)
+ (hash-set! mapped
+ (car e)
+ (cons (cdr e) (hash-ref mapped (car e) null))))
+
+
+ (for ([e (in-list table)]) (add-entry! e))
+
+ (define new-table
+ (reverse
+ (for/fold ([table (reverse table)]) ([d (in-list dirs)])
+ (let* ([dp (path->complete-path d)]
+ [a-name (or name
+ (let-values ([(base name dir?) (split-path dp)])
+ (path-element->string name)))]
+ [rx version-regexp]
+ [d (path->string dp)])
+ (unless remove?
+ (unless (directory-exists? dp)
+ (error 'links
+ "no such directory for link: ~a"
+ dp)))
+ (if remove?
+ (filter (lambda (e)
+ (or (not (equal? (cadr e) d))
+ (and name
+ (not (equal? (car e) name)))
+ (and version-regexp
+ (pair? (cddr e))
+ (not (equal? (caddr e) version-regexp)))))
+ table)
+ (let ([l (hash-ref mapped a-name null)]
+ [e (list* a-name
+ d
+ (if rx (list rx) null))])
+ (if (member (cdr e) l)
+ table
+ (let ()
+ (add-entry! e)
+ (cons e table)))))))))
+
+ (unless (and (not need-repair?)
+ (equal? new-table table))
+ (let ([dir (let-values ([(base name dir?) (split-path file)])
+ base)])
+ (make-directory* dir)
+ (let ([tmp (make-temporary-file "links~a.rktd"
+ #f
+ dir)])
+ (with-output-to-file tmp
+ #:exists 'truncate
+ (lambda ()
+ (printf "(")
+ (let loop ([l new-table] [prefix ""])
+ (cond
+ [(null? l) (printf ")\n")]
+ [else
+ (printf "~a~s" prefix (car l))
+ (unless (null? (cdr l)) (newline))
+ (loop (cdr l) " ")]))))
+ (with-handlers ([exn:fail? (lambda (exn)
+ (with-handlers ([exn:fail? void])
+ (delete-file tmp))
+ (raise exn))])
+ (rename-file-or-directory tmp file #t)))))
+
+ (when show?
+ (for ([e (in-list new-table)])
+ (printf " collection: ~s path: ~s~a\n"
+ (car e)
+ (cadr e)
+ (if (null? (cddr e))
+ ""
+ (format " version: ~s"
+ (caddr e))))))
+
+ ;; Return list of collections mapped for this version:
+ (let ([ht (make-hash)])
+ (for ([e (in-list new-table)])
+ (when (or (null? (cddr e))
+ (regexp-match? (caddr e) (version)))
+ (hash-set! ht (car e) #t)))
+ (hash-map ht (lambda (k e) k))))
diff --git a/collects/setup/private/omitted-paths.rkt b/collects/setup/private/omitted-paths.rkt
index cda020a68c..41286b1260 100644
--- a/collects/setup/private/omitted-paths.rkt
+++ b/collects/setup/private/omitted-paths.rkt
@@ -82,7 +82,7 @@
implicit?
get-info/full)))))))
-(define (omitted-paths* dir get-info/full)
+(define (omitted-paths* dir get-info/full root-dir)
(unless (and (path-string? dir) (complete-path? dir) (directory-exists? dir))
(raise-type-error 'omitted-paths
"complete path to an existing directory" dir))
@@ -90,8 +90,13 @@
[r (ormap (lambda (root+table)
(let ([r (relative-from dir* (car root+table))])
(and r (cons (reverse r) root+table))))
- (force roots))]
+ (if root-dir
+ (list (list (explode-path root-dir)
+ (make-hash)
+ #t))
+ (force roots)))]
[r (and r (apply accumulate-omitted get-info/full r))])
+
(unless r
(error 'omitted-paths
"given directory path is not in any collection root: ~e" dir))
@@ -101,5 +106,5 @@
(define omitted-paths-memo (make-hash))
-(define (omitted-paths dir get-info/full)
- (with-memo omitted-paths-memo dir (omitted-paths* dir get-info/full)))
+(define (omitted-paths dir get-info/full [root-dir #f])
+ (with-memo omitted-paths-memo dir (omitted-paths* dir get-info/full root-dir)))
diff --git a/collects/setup/private/path-utils.rkt b/collects/setup/private/path-utils.rkt
index 90bd6de733..558aa76608 100644
--- a/collects/setup/private/path-utils.rkt
+++ b/collects/setup/private/path-utils.rkt
@@ -5,7 +5,7 @@
(provide doc-path)
;; user-doc-mode can be `false-if-missing' or `never'
-(define (doc-path dir name flags [user-doc-mode #f])
+(define (doc-path dir name flags under-main? [user-doc-mode #f])
(define (user-doc [sub #f])
(and (not (eq? 'never user-doc-mode))
(let ([d (find-user-doc-dir)])
@@ -15,6 +15,6 @@
(cond [(memq 'main-doc-root flags) (find-doc-dir)]
[(memq 'user-doc-root flags) (user-doc)]
[(memq 'user-doc flags) (user-doc name)]
- [(or (memq 'main-doc flags) (pair? (path->main-collects-relative dir)))
+ [(or under-main? (memq 'main-doc flags) (pair? (path->main-collects-relative dir)))
(build-path (find-doc-dir) name)]
[else (build-path dir "doc" name)]))
diff --git a/collects/setup/scribble.rkt b/collects/setup/scribble.rkt
index c19124364d..6bb685c592 100644
--- a/collects/setup/scribble.rkt
+++ b/collects/setup/scribble.rkt
@@ -95,7 +95,7 @@
(apply validate i)))
infos)])
(and (not (memq #f infos)) infos))))
- (define (get-docs i rec)
+ (define ((get-docs main-dirs) i rec)
(let ([s (validate-scribblings-infos (i 'scribblings))]
[dir (directory-record-path rec)])
(if s
@@ -106,6 +106,7 @@
(not (memq 'user-doc-root flags))
(not (memq 'user-doc flags))
(or (memq 'main-doc flags)
+ (hash-ref main-dirs dir #f)
(pair? (path->main-collects-relative dir))))])
(make-doc dir
(let ([spec (directory-record-spec rec)])
@@ -117,7 +118,7 @@
(list '= (directory-record-min rec)))))
(cdr spec))))
(build-path dir (car d))
- (doc-path dir (cadddr d) flags)
+ (doc-path dir (cadddr d) flags under-main?)
flags under-main? (caddr d))))
s)
(begin (setup-printf
@@ -126,8 +127,12 @@
null))))
(define docs
(let* ([recs (find-relevant-directory-records '(scribblings) 'all-available)]
+ [main-dirs (parameterize ([current-library-collection-paths
+ (list (find-collects-dir))])
+ (for/hash ([k (in-list (find-relevant-directories '(scribblings) 'no-planet))])
+ (values k #t)))]
[infos (map get-info/full (map directory-record-path recs))])
- (filter-user-docs (append-map get-docs infos recs) make-user?)))
+ (filter-user-docs (append-map (get-docs main-dirs) infos recs) make-user?)))
(define-values (main-docs user-docs) (partition doc-under-main? docs))
(define (can-build*? docs) (can-build? only-dirs docs))
(define auto-main? (and auto-start-doc? (ormap can-build*? main-docs)))
diff --git a/collects/setup/setup-unit.rkt b/collects/setup/setup-unit.rkt
index d494f983bd..6cc099bcf6 100644
--- a/collects/setup/setup-unit.rkt
+++ b/collects/setup/setup-unit.rkt
@@ -1,3 +1,4 @@
+
;; Expects parameters to be set before invocation.
;; Calls `exit' when done.
@@ -27,7 +28,8 @@
"path-to-relative.rkt"
"private/omitted-paths.rkt"
"parallel-build.rkt"
- "collects.rkt")
+ "collects.rkt"
+ "link.rkt")
(define-namespace-anchor anchor)
;; read info files using whatever namespace, .zo-use, and compilation
@@ -168,7 +170,7 @@
;; Find Collections ;;
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- (define (make-cc* collection path root-dir info-path shadowing-policy)
+ (define (make-cc* collection path omit-root info-root info-path info-path-mode shadowing-policy)
(define info
(or (with-handlers ([exn:fail? (warning-handler #f)]) (getinfo path))
(lambda (flag mk-default) (mk-default))))
@@ -186,12 +188,15 @@
"ignoring `compile-subcollections' entry in info ~a"
path-name))
;; this check is also done in compiler/compiler-unit, in compile-directory
- (and (not (eq? 'all (omitted-paths path getinfo)))
+ (and (not (eq? 'all (omitted-paths path getinfo omit-root)))
(make-cc collection path
(if name
(format "~a (~a)" path-name name)
path-name)
- info root-dir info-path shadowing-policy)))
+ info
+ omit-root
+ info-root info-path info-path-mode
+ shadowing-policy)))
(define ((warning-handler v) exn)
(setup-printf "WARNING" "~a" (exn->string exn))
@@ -199,23 +204,39 @@
;; collection->cc : listof path -> cc/#f
(define collection->cc-table (make-hash))
- (define (collection->cc collection-p)
+ (define (collection->cc collection-p
+ #:omit-root [omit-root #f]
+ #:info-root [given-info-root #f]
+ #:info-path [info-path #f]
+ #:info-path-mode [info-path-mode 'relative])
(hash-ref! collection->cc-table collection-p
(lambda ()
- (define root-dir
- (ormap (lambda (p)
- (parameterize ([current-library-collection-paths (list p)])
- (and (with-handlers ([exn:fail? (lambda (x) #f)])
- (apply collection-path collection-p))
- p)))
- (current-library-collection-paths)))
- (make-cc* collection-p
- (apply collection-path collection-p)
- root-dir
- (build-path root-dir "info-domain" "compiled" "cache.rktd")
- ;; by convention, all collections have "version" 1 0. This
- ;; forces them to conflict with each other.
- (list (cons 'lib (map path->string collection-p)) 1 0)))))
+ (define info-root
+ (or given-info-root
+ (ormap (lambda (p)
+ (parameterize ([current-library-collection-paths (list p)]
+ ;; to disable collection links file:
+ [use-user-specific-search-paths #f])
+ (and (with-handlers ([exn:fail? (lambda (x) #f)])
+ (apply collection-path collection-p))
+ p)))
+ (current-library-collection-paths))))
+ (let ([dir (apply collection-path collection-p)])
+ (unless (directory-exists? dir)
+ (error name-sym "directory does not exist for collection: ~s"
+ (string-join (map path->string collection-p) "/")))
+ (make-cc* collection-p
+ dir
+ (if (eq? omit-root 'dir)
+ dir
+ omit-root) ; #f => `omitted-paths' can reconstruct it
+ info-root
+ (or info-path
+ (build-path info-root "info-domain" "compiled" "cache.rktd"))
+ info-path-mode
+ ;; by convention, all collections have "version" 1 0. This
+ ;; forces them to conflict with each other.
+ (list (cons 'lib (map path->string collection-p)) 1 0))))))
;; planet-spec->planet-list : (list string string nat nat) -> (list path string string (listof string) nat nat) | #f
;; converts a planet package spec into the information needed to create a cc structure
@@ -241,8 +262,10 @@
(and (directory-exists? path)
(make-cc* #f
path
- #f ; don't need root-dir; absolute paths in cache.rktd will be ok
+ path
+ #f ; don't need info-root; absolute paths in cache.rktd will be ok
(get-planet-cache-path)
+ 'abs
(list `(planet ,owner ,pkg-file ,@extra-path) maj min))))
;; planet-cc->sub-cc : cc (listof bytes [encoded path]) -> cc
@@ -268,6 +291,23 @@
(lambda ()
(let ([cc (collection->cc (list collection))])
(when cc (hash-set! ht collection cc))))))
+ (let ([main-collects (find-collects-dir)])
+ (for ([c (in-list (links #:user? #f))])
+ (let* ([c (string->path c)]
+ [cc (collection->cc (list c)
+ #:info-root main-collects
+ #:info-path-mode 'abs-in-relative
+ #:omit-root 'dir)])
+ (when cc (hash-set! ht c cc)))))
+ (when (make-user)
+ (let ([user-collects (find-user-collects-dir)])
+ (for ([c (in-list (links))])
+ (let* ([c (string->path c)]
+ [cc (collection->cc (list c)
+ #:info-root user-collects
+ #:info-path-mode 'abs-in-relative
+ #:omit-root 'dir)])
+ (when cc (hash-set! ht c cc))))))
(hash-map ht (lambda (k v) v))))
;; Close over sub-collections
@@ -279,7 +319,7 @@
;; collection should not have been included, but we might
;; jump in if a command-line argument specified a
;; coll/subcoll
- [omit (omitted-paths ccp getinfo)]
+ [omit (omitted-paths ccp getinfo (cc-omit-root cc))]
[subs (if (eq? 'all omit)
'()
(filter (lambda (p)
@@ -292,7 +332,8 @@
(append-map (lambda (cc) (cons cc (loop (get-subs cc)))) l))))
(define (collection-tree-map collections-to-compile
- #:skip-path [orig-skip-path (and (avoid-main-installation) (find-collects-dir))])
+ #:skip-path [orig-skip-path (and (avoid-main-installation)
+ (find-collects-dir))])
(define skip-path (and orig-skip-path (path->bytes
(simplify-path (if (string? orig-skip-path)
(string->path orig-skip-path)
@@ -308,14 +349,18 @@
(define (build-collection-tree cc)
(define (make-child-cc parent-cc name)
- (collection->cc (append (cc-collection parent-cc) (list name))))
+ (collection->cc (append (cc-collection parent-cc) (list name))
+ #:info-root (cc-info-root cc)
+ #:info-path (cc-info-path cc)
+ #:info-path-mode (cc-info-path-mode cc)
+ #:omit-root (cc-omit-root cc)))
(let* ([info (cc-info cc)]
[ccp (cc-path cc)]
;; note: omit can be 'all, if this happens then this
;; collection should not have been included, but we might
;; jump in if a command-line argument specified a
;; coll/subcoll
- [omit (omitted-paths ccp getinfo)])
+ [omit (omitted-paths ccp getinfo (cc-omit-root cc))])
(let-values ([(dirs files)
(if (eq? 'all omit)
(values null null)
@@ -325,7 +370,6 @@
(skip-path? p))))
(directory-list ccp))))])
(let ([children-ccs (map build-collection-tree (filter-map (lambda (x) (make-child-cc cc x)) dirs))]
-
[srcs (append
(filter extract-base-filename/ss files)
(if (make-docs)
@@ -342,7 +386,11 @@
(define (plt-collection-closure collections-to-compile)
(define (make-children-ccs cc children)
(map (lambda (child)
- (collection->cc (append (cc-collection cc) (list child))))
+ (collection->cc (append (cc-collection cc) (list child))
+ #:info-root (cc-info-root cc)
+ #:info-path (cc-info-path cc)
+ #:info-path-mode (cc-info-path-mode cc)
+ #:omit-root (cc-omit-root cc)))
children))
(collection-closure collections-to-compile make-children-ccs))
@@ -668,6 +716,7 @@
[info (cc-info cc)])
(clean-cc dir info)
(compile-directory-zos dir info
+ #:omit-root (cc-omit-root cc)
#:managed-compile-zo caching-managed-compile-zo
#:skip-path (and (avoid-main-installation) (find-collects-dir))
#:skip-doc-sources? (not (make-docs))))))))
@@ -748,7 +797,7 @@
(warning-handler null)])
(with-input-from-file p read))
null))])
- ;; Convert list to hash table. Incluse only well-formed
+ ;; Convert list to hash table. Include only well-formed
;; list elements, and only elements whose corresponding
;; collection exists.
(let ([t (make-hash)]
@@ -757,28 +806,32 @@
(set! all-ok? #t)
(for ([i l])
(match i
- [(list
- (? (lambda (a)
- (and (bytes? a)
- (let ([p (bytes->path a)])
- ;; If we have a root directory,
- ;; then the path must be relative
- ;; to it, otherwise it must be
- ;; absolute:
- (and (if (cc-root-dir cc)
- (relative-path? p)
- (complete-path? p))
- (let ([dir (if (cc-root-dir cc)
- (build-path (cc-root-dir cc) p)
- p)])
- (or (file-exists? (build-path dir "info.rkt"))
- (file-exists? (build-path dir "info.ss"))))))))
- a)
- (list (? symbol? b) ...)
- c
- (? integer? d)
- (? integer? e))
- (hash-set! t a (list b c d e))]
+ [(list (? bytes? a) (list (? symbol? b) ...) c (? integer? d) (? integer? e))
+ (let ([p (bytes->path a)])
+ ;; Check that the path is suitably absolute or relative:
+ (let ([dir (case (cc-info-path-mode cc)
+ [(relative abs-in-relative)
+ (or (and (relative-path? p)
+ (build-path (cc-info-root cc) p))
+ (and (complete-path? p)
+ ;; `c' must be `(lib ...)'
+ (list? c)
+ (pair? c)
+ (eq? 'lib (car c))
+ (pair? (cdr c))
+ (andmap string? (cdr c))
+ ;; Path must match collection resolution:
+ (with-handlers ([exn:fail? (lambda (exn) #f)])
+ (equal? p (apply collection-path (cdr c))))
+ p))]
+ [(abs)
+ (and (complete-path? p)
+ p)])])
+ (if (and dir
+ (or (file-exists? (build-path dir "info.rkt"))
+ (file-exists? (build-path dir "info.ss"))))
+ (hash-set! t a (list b c d e))
+ (set! all-ok? #f))))]
[_ (set! all-ok? #f)])))
;; Record the table loaded for this collection root
;; in the all-roots table:
@@ -792,7 +845,7 @@
;; Add this collection's info to the table, replacing any information
;; already there.
(hash-set! t
- (path->bytes (if (cc-root-dir cc)
+ (path->bytes (if (eq? (cc-info-path-mode cc) 'relative)
;; Use relative path:
(apply build-path (cc-collection cc))
;; Use absolute path:
@@ -802,20 +855,16 @@
(hash-for-each ht
(lambda (info-path ht)
(unless (equal? ht (hash-ref ht-orig info-path))
- (let-values ([(base name must-be-dir?) (split-path info-path)])
- (unless (path? base)
- (error 'make-info-domain
- "Internal error: cc had invalid info-path: ~e"
- info-path))
- (make-directory* base)
- (let ([p info-path])
- (setup-printf "updating" "~a" (path->relative-string/setup p))
- (with-handlers ([exn:fail? (warning-handler (void))])
- (with-output-to-file p
- #:exists 'truncate/replace
- (lambda ()
- (write (hash-map ht cons))
- (newline)))))))))))
+ (define-values (base name dir?) (split-path info-path))
+ (make-directory* base)
+ (let ([p info-path])
+ (setup-printf "updating" "~a" (path->relative-string/setup p))
+ (with-handlers ([exn:fail? (warning-handler (void))])
+ (with-output-to-file p
+ #:exists 'truncate/replace
+ (lambda ()
+ (write (hash-map ht cons))
+ (newline))))))))))
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Docs ;;
diff --git a/collects/setup/xref.rkt b/collects/setup/xref.rkt
index ab67b094ff..13432ec826 100644
--- a/collects/setup/xref.rkt
+++ b/collects/setup/xref.rkt
@@ -3,6 +3,7 @@
(require scribble/xref
scheme/fasl
scheme/path
+ setup/dirs
"getinfo.rkt"
"private/path-utils.rkt")
@@ -11,6 +12,12 @@
(define cached-xref #f)
(define (get-dests)
+ (define main-dirs
+ (parameterize ([current-library-collection-paths
+ (let ([d (find-collects-dir)])
+ (if d (list d) null))])
+ (for/hash ([k (in-list (find-relevant-directories '(scribblings) 'no-planet))])
+ (values k #t))))
(for*/list ([dir (find-relevant-directories '(scribblings) 'all-available)]
[d ((get-info/full dir) 'scribblings)])
(unless (and (list? d) (pair? d))
@@ -23,7 +30,7 @@
(path-replace-suffix (file-name-from-path (car d))
#"")))])
(and (not (and (len . >= . 3) (memq 'omit (caddr d))))
- (let* ([d (doc-path dir name flags 'false-if-missing)]
+ (let* ([d (doc-path dir name flags (hash-ref main-dirs dir #f) 'false-if-missing)]
[p (and d (build-path d "out.sxref"))])
(and p (file-exists? p) p))))))
diff --git a/doc/release-notes/racket/HISTORY.txt b/doc/release-notes/racket/HISTORY.txt
index a025903eb4..5828286a26 100644
--- a/doc/release-notes/racket/HISTORY.txt
+++ b/doc/release-notes/racket/HISTORY.txt
@@ -1,3 +1,7 @@
+Version 5.1.3.4
+Add support for the collection links file, including
+ (find-system-path 'links-file) and the raco link command
+
Version 5.1.3.3
unsafe/ffi: added support for C arrays and unions
diff --git a/src/racket/cmdline.inc b/src/racket/cmdline.inc
index a836aab046..bca89ee316 100644
--- a/src/racket/cmdline.inc
+++ b/src/racket/cmdline.inc
@@ -556,6 +556,7 @@ static int run_from_cmd_line(int argc, char *_argv[],
char *prog, *sprog = NULL;
Scheme_Object *sch_argv;
Scheme_Object *collects_path = NULL, *collects_extra = NULL, *addon_dir = NULL;
+ Scheme_Object *links_file = NULL;
#ifndef NO_FILE_SYSTEM_UTILS
Scheme_Object *collects_paths_l, *collects_paths_r;
#endif
@@ -804,6 +805,8 @@ static int run_from_cmd_line(int argc, char *_argv[],
argv[0] = "-S";
else if (!strcmp("--addon", argv[0]))
argv[0] = "-A";
+ else if (!strcmp("--links", argv[0]))
+ argv[0] = "-C";
# ifdef CMDLINE_STDIO_FLAG
else if (!strcmp("--stdio", argv[0]))
argv[0] = "-z";
@@ -860,6 +863,17 @@ static int run_from_cmd_line(int argc, char *_argv[],
addon_dir = scheme_make_path(argv[0]);
was_config_flag = 1;
break;
+ case 'C':
+ if (argc < 2) {
+ PRINTF("%s: missing path after %s switch\n",
+ prog, real_switch);
+ goto show_need_help;
+ }
+ argv++;
+ --argc;
+ links_file = scheme_make_path(argv[0]);
+ was_config_flag = 1;
+ break;
case 'U':
scheme_set_ignore_user_paths(1);
was_config_flag = 1;
@@ -1204,7 +1218,28 @@ static int run_from_cmd_line(int argc, char *_argv[],
}
}
# endif
- if (addon_dir) scheme_set_addon_dir(addon_dir);
+ if (addon_dir) {
+ addon_dir = scheme_path_to_complete_path(addon_dir, NULL);
+ scheme_set_addon_dir(addon_dir);
+ }
+#endif /* NO_FILE_SYSTEM_UTILS */
+
+#ifndef NO_FILE_SYSTEM_UTILS
+ /* Setup path for "links" file: */
+# ifdef GETENV_FUNCTION
+ if (!links_file) {
+ char *s;
+ s = getenv("PLTLINKSFILE");
+ if (s) {
+ s = scheme_expand_filename(s, -1, NULL, NULL, 0);
+ if (s) links_file = scheme_make_path(s);
+ }
+ }
+# endif
+ if (links_file) {
+ links_file = scheme_path_to_complete_path(links_file, NULL);
+ scheme_set_links_file(links_file);
+ }
#endif /* NO_FILE_SYSTEM_UTILS */
/* Creates the main kernel environment */
@@ -1292,6 +1327,7 @@ static int run_from_cmd_line(int argc, char *_argv[],
" -X
, --collects : Main collects at \n"
" -S , --search : More collects at (after main collects)\n"
" -A , --addon : Addon directory at \n"
+ " -K , --links : Collection links at \n"
" -U, --no-user-path : Ignore user-specific collects, etc.\n"
" -N , --name : Sets `(find-system-path 'run-file)' to \n"
# ifdef MZ_USE_JIT
diff --git a/src/racket/include/scheme.h b/src/racket/include/scheme.h
index 62beb416c0..7e07afc5a0 100644
--- a/src/racket/include/scheme.h
+++ b/src/racket/include/scheme.h
@@ -1801,6 +1801,7 @@ MZ_EXTERN Scheme_Object *scheme_set_run_cmd(char *s);
MZ_EXTERN void scheme_set_collects_path(Scheme_Object *p);
MZ_EXTERN void scheme_set_original_dir(Scheme_Object *d);
MZ_EXTERN void scheme_set_addon_dir(Scheme_Object *p);
+MZ_EXTERN void scheme_set_links_file(Scheme_Object *p);
MZ_EXTERN void scheme_set_command_line_arguments(Scheme_Object *vec);
MZ_EXTERN void scheme_set_compiled_file_paths(Scheme_Object *list);
diff --git a/src/racket/include/schthread.h b/src/racket/include/schthread.h
index 271725e7e4..e4755fbf28 100644
--- a/src/racket/include/schthread.h
+++ b/src/racket/include/schthread.h
@@ -273,6 +273,7 @@ typedef struct Thread_Local_Variables {
int env_uid_counter_;
int scheme_overflow_count_;
struct Scheme_Object *original_pwd_;
+ struct Scheme_Object *inst_links_path_;
void *file_path_wc_buffer_;
intptr_t scheme_hash_request_count_;
intptr_t scheme_hash_iteration_count_;
@@ -605,6 +606,7 @@ XFORM_GC_VARIABLE_STACK_THROUGH_THREAD_LOCAL;
#define env_uid_counter XOA (scheme_get_thread_local_variables()->env_uid_counter_)
#define scheme_overflow_count XOA (scheme_get_thread_local_variables()->scheme_overflow_count_)
#define original_pwd XOA (scheme_get_thread_local_variables()->original_pwd_)
+#define inst_links_path XOA (scheme_get_thread_local_variables()->inst_links_path_)
#define file_path_wc_buffer XOA (scheme_get_thread_local_variables()->file_path_wc_buffer_)
#define scheme_hash_request_count XOA (scheme_get_thread_local_variables()->scheme_hash_request_count_)
#define scheme_hash_iteration_count XOA (scheme_get_thread_local_variables()->scheme_hash_iteration_count_)
diff --git a/src/racket/src/cstartup.inc b/src/racket/src/cstartup.inc
index 3fce116853..7650cfec55 100644
--- a/src/racket/src/cstartup.inc
+++ b/src/racket/src/cstartup.inc
@@ -1,5 +1,5 @@
{
- SHARED_OK static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,53,46,49,46,51,46,50,0,0,0,0,0,0,0,0,0,0,0,
+ SHARED_OK static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,53,46,49,46,51,46,53,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,51,0,0,0,1,0,0,10,0,13,0,22,
0,26,0,31,0,38,0,51,0,58,0,63,0,68,0,72,0,79,0,82,0,
85,0,91,0,105,0,119,0,122,0,128,0,132,0,134,0,145,0,147,0,161,
@@ -15,12 +15,12 @@
116,120,61,115,70,108,101,116,45,118,97,108,117,101,115,61,120,73,108,101,116,
114,101,99,45,118,97,108,117,101,115,66,108,97,109,98,100,97,1,20,112,97,
114,97,109,101,116,101,114,105,122,97,116,105,111,110,45,107,101,121,61,118,73,
-100,101,102,105,110,101,45,118,97,108,117,101,115,97,36,11,8,240,72,76,0,
+100,101,102,105,110,101,45,118,97,108,117,101,115,97,36,11,8,240,112,76,0,
0,95,159,2,17,36,36,159,2,16,36,36,159,2,16,36,36,16,20,2,4,
-2,2,2,6,2,2,2,7,2,2,2,8,2,2,2,9,2,2,2,10,2,
+2,2,2,6,2,2,2,8,2,2,2,7,2,2,2,9,2,2,2,10,2,
2,2,11,2,2,2,5,2,2,2,12,2,2,2,13,2,2,97,37,11,8,
-240,72,76,0,0,93,159,2,16,36,37,16,2,2,3,161,2,2,37,2,3,
-2,2,2,3,96,38,11,8,240,72,76,0,0,16,0,96,11,11,8,240,72,
+240,112,76,0,0,93,159,2,16,36,37,16,2,2,3,161,2,2,37,2,3,
+2,2,2,3,96,11,11,8,240,112,76,0,0,16,0,96,38,11,8,240,112,
76,0,0,16,0,18,98,64,104,101,114,101,13,16,5,36,2,14,2,2,11,
11,8,32,8,31,8,30,8,29,27,248,22,155,4,195,249,22,148,4,80,158,
39,36,251,22,83,2,18,248,22,98,199,12,249,22,73,2,19,248,22,100,201,
@@ -30,14 +30,14 @@
74,193,249,22,148,4,80,158,39,36,251,22,83,2,18,248,22,74,199,249,22,
73,2,11,248,22,75,201,11,18,100,10,13,16,5,36,2,14,2,2,11,11,
8,32,8,31,8,30,8,29,16,4,11,11,2,20,3,1,8,101,110,118,49,
-52,55,51,57,16,4,11,11,2,21,3,1,8,101,110,118,49,52,55,52,48,
+52,55,57,57,16,4,11,11,2,21,3,1,8,101,110,118,49,52,56,48,48,
27,248,22,75,248,22,155,4,196,28,248,22,81,193,20,14,159,37,36,37,28,
248,22,81,248,22,75,194,248,22,74,193,249,22,148,4,80,158,39,36,250,22,
83,2,22,248,22,83,249,22,83,248,22,83,2,23,248,22,74,201,251,22,83,
2,18,2,23,2,23,249,22,73,2,13,248,22,75,204,18,100,11,13,16,5,
36,2,14,2,2,11,11,8,32,8,31,8,30,8,29,16,4,11,11,2,20,
-3,1,8,101,110,118,49,52,55,52,50,16,4,11,11,2,21,3,1,8,101,
-110,118,49,52,55,52,51,248,22,155,4,193,27,248,22,155,4,194,249,22,73,
+3,1,8,101,110,118,49,52,56,48,50,16,4,11,11,2,21,3,1,8,101,
+110,118,49,52,56,48,51,248,22,155,4,193,27,248,22,155,4,194,249,22,73,
248,22,83,248,22,74,196,248,22,75,195,27,248,22,75,248,22,155,4,23,197,
1,249,22,148,4,80,158,39,36,28,248,22,58,248,22,149,4,248,22,74,23,
198,2,27,249,22,2,32,0,88,163,8,36,37,43,11,9,222,33,40,248,22,
@@ -67,8 +67,8 @@
140,9,248,22,149,4,248,22,74,200,64,101,108,115,101,10,248,22,74,197,250,
22,84,2,22,9,248,22,75,200,249,22,73,2,5,248,22,75,202,99,13,16,
5,36,2,14,2,2,11,11,8,32,8,31,8,30,8,29,16,4,11,11,2,
-20,3,1,8,101,110,118,49,52,55,54,53,16,4,11,11,2,21,3,1,8,
-101,110,118,49,52,55,54,54,18,158,94,10,64,118,111,105,100,8,48,27,248,
+20,3,1,8,101,110,118,49,52,56,50,53,16,4,11,11,2,21,3,1,8,
+101,110,118,49,52,56,50,54,18,158,94,10,64,118,111,105,100,8,48,27,248,
22,75,248,22,155,4,196,249,22,148,4,80,158,39,36,28,248,22,58,248,22,
149,4,248,22,74,197,250,22,83,2,28,248,22,83,248,22,74,199,248,22,98,
198,27,248,22,149,4,248,22,74,197,250,22,83,2,28,248,22,83,248,22,74,
@@ -98,410 +98,496 @@
EVAL_ONE_SIZED_STR((char *)expr, 2004);
}
{
- SHARED_OK static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,53,46,49,46,51,46,50,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,82,0,0,0,1,0,0,8,0,21,0,26,
-0,43,0,58,0,76,0,92,0,106,0,128,0,146,0,166,0,182,0,200,0,
-231,0,4,1,26,1,40,1,46,1,60,1,65,1,75,1,83,1,111,1,143,
-1,188,1,194,1,201,1,207,1,252,1,20,2,59,2,73,2,76,2,79,2,
-89,2,100,2,113,2,115,2,117,2,27,3,117,4,231,4,89,5,130,5,203,
-6,33,7,119,7,219,7,47,8,61,8,194,8,168,9,252,9,10,10,31,11,
-235,11,249,11,141,16,156,17,45,18,30,19,12,20,19,20,98,20,179,20,122,
-21,136,21,146,21,187,22,33,23,56,23,73,23,21,25,124,25,138,25,42,26,
-235,27,244,27,253,27,23,28,151,28,0,0,2,32,0,0,67,35,37,117,116,
-105,108,115,72,112,97,116,104,45,115,116,114,105,110,103,63,64,98,115,98,115,
-76,110,111,114,109,97,108,45,99,97,115,101,45,112,97,116,104,74,45,99,104,
-101,99,107,45,114,101,108,112,97,116,104,77,45,99,104,101,99,107,45,99,111,
-108,108,101,99,116,105,111,110,75,99,111,108,108,101,99,116,105,111,110,45,112,
-97,116,104,73,102,105,110,100,45,99,111,108,45,102,105,108,101,1,20,99,111,
-108,108,101,99,116,105,111,110,45,102,105,108,101,45,112,97,116,104,77,99,104,
-101,99,107,45,115,117,102,102,105,120,45,99,97,108,108,79,112,97,116,104,45,
-114,101,112,108,97,99,101,45,115,117,102,102,105,120,75,112,97,116,104,45,97,
-100,100,45,115,117,102,102,105,120,77,108,111,97,100,47,117,115,101,45,99,111,
-109,112,105,108,101,100,1,29,102,105,110,100,45,108,105,98,114,97,114,121,45,
-99,111,108,108,101,99,116,105,111,110,45,112,97,116,104,115,1,27,112,97,116,
-104,45,108,105,115,116,45,115,116,114,105,110,103,45,62,112,97,116,104,45,108,
-105,115,116,1,20,102,105,110,100,45,101,120,101,99,117,116,97,98,108,101,45,
-112,97,116,104,73,101,109,98,101,100,100,101,100,45,108,111,97,100,65,113,117,
-111,116,101,29,94,2,18,68,35,37,112,97,114,97,109,122,11,64,108,111,111,
-112,69,101,120,101,99,45,102,105,108,101,67,119,105,110,100,111,119,115,6,25,
-25,112,97,116,104,32,111,114,32,118,97,108,105,100,45,112,97,116,104,32,115,
-116,114,105,110,103,6,29,29,126,97,58,32,105,110,118,97,108,105,100,32,114,
-101,108,97,116,105,118,101,32,112,97,116,104,58,32,126,115,6,42,42,126,97,
-58,32,99,111,108,108,101,99,116,105,111,110,32,110,111,116,32,102,111,117,110,
-100,58,32,126,115,32,105,110,32,97,110,121,32,111,102,58,32,126,115,65,99,
-108,111,111,112,6,4,4,46,114,107,116,6,3,3,46,115,115,6,42,42,112,
-97,116,104,32,40,102,111,114,32,97,110,121,32,115,121,115,116,101,109,41,32,
-111,114,32,118,97,108,105,100,45,112,97,116,104,32,115,116,114,105,110,103,6,
-21,21,115,116,114,105,110,103,32,111,114,32,98,121,116,101,32,115,116,114,105,
-110,103,6,36,36,99,97,110,110,111,116,32,97,100,100,32,97,32,115,117,102,
-102,105,120,32,116,111,32,97,32,114,111,111,116,32,112,97,116,104,58,32,6,
-11,11,80,76,84,67,79,76,76,69,67,84,83,6,0,0,6,0,0,69,97,
-100,100,111,110,45,100,105,114,6,8,8,99,111,108,108,101,99,116,115,72,99,
-111,108,108,101,99,116,115,45,100,105,114,5,0,5,0,27,20,13,159,80,159,
-37,52,37,250,80,159,40,53,37,249,22,27,11,80,159,42,52,37,22,186,13,
-10,248,22,190,5,23,196,2,28,248,22,189,6,23,194,2,12,86,94,248,22,
-148,9,23,194,1,27,20,13,159,80,159,38,52,37,250,80,159,41,53,37,249,
-22,27,11,80,159,43,52,37,22,186,13,10,248,22,190,5,23,197,2,28,248,
-22,189,6,23,194,2,12,86,94,248,22,148,9,23,194,1,27,20,13,159,80,
-159,39,52,37,250,80,159,42,53,37,249,22,27,11,80,159,44,52,37,22,186,
-13,10,248,22,190,5,23,198,2,28,248,22,189,6,23,194,2,12,86,94,248,
-22,148,9,23,194,1,248,80,159,40,57,39,197,28,248,22,81,23,195,2,9,
-27,248,22,74,23,196,2,27,28,248,22,172,14,23,195,2,23,194,1,28,248,
-22,171,14,23,195,2,249,22,173,14,23,196,1,250,80,158,43,50,248,22,188,
-14,2,21,11,10,250,80,158,41,50,248,22,188,14,2,21,23,197,1,10,28,
-23,193,2,249,22,73,248,22,175,14,249,22,173,14,23,198,1,247,22,189,14,
-27,248,22,75,23,200,1,28,248,22,81,23,194,2,9,27,248,22,74,23,195,
+ SHARED_OK static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,53,46,49,46,51,46,53,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,107,0,0,0,1,0,0,8,0,21,0,26,
+0,43,0,65,0,94,0,109,0,127,0,143,0,157,0,179,0,195,0,212,0,
+234,0,245,0,251,0,4,1,11,1,18,1,30,1,46,1,70,1,102,1,120,
+1,140,1,156,1,174,1,205,1,219,1,224,1,234,1,242,1,251,1,253,1,
+255,1,27,2,59,2,72,2,78,2,117,2,121,2,166,2,190,2,229,2,243,
+2,246,2,249,2,3,3,14,3,181,3,25,5,143,5,5,6,46,6,119,7,
+142,7,159,7,107,9,210,9,224,9,128,10,57,12,66,12,75,12,89,12,99,
+12,140,13,242,13,72,14,158,14,2,15,86,15,100,15,214,15,42,16,56,16,
+9,17,17,17,123,17,172,17,174,17,18,18,78,18,83,18,189,18,10,19,168,
+20,190,20,199,20,192,21,210,21,224,21,183,22,202,22,140,25,4,30,110,30,
+255,30,240,31,222,32,229,32,54,33,137,33,222,33,248,33,121,34,0,0,221,
+38,0,0,67,35,37,117,116,105,108,115,72,112,97,116,104,45,115,116,114,105,
+110,103,63,64,98,115,98,115,76,110,111,114,109,97,108,45,99,97,115,101,45,
+112,97,116,104,1,20,102,105,110,100,45,101,120,101,99,117,116,97,98,108,101,
+45,112,97,116,104,1,27,112,97,116,104,45,108,105,115,116,45,115,116,114,105,
+110,103,45,62,112,97,116,104,45,108,105,115,116,74,45,99,104,101,99,107,45,
+114,101,108,112,97,116,104,77,45,99,104,101,99,107,45,99,111,108,108,101,99,
+116,105,111,110,75,99,111,108,108,101,99,116,105,111,110,45,112,97,116,104,73,
+102,105,110,100,45,99,111,108,45,102,105,108,101,1,20,99,111,108,108,101,99,
+116,105,111,110,45,102,105,108,101,45,112,97,116,104,75,117,115,101,114,45,108,
+105,110,107,115,45,112,97,116,104,76,117,115,101,114,45,108,105,110,107,115,45,
+99,97,99,104,101,1,20,117,115,101,114,45,108,105,110,107,115,45,116,105,109,
+101,115,116,97,109,112,70,108,105,110,107,115,45,112,97,116,104,65,113,117,111,
+116,101,68,35,37,112,97,114,97,109,122,29,94,2,16,2,17,11,29,94,2,
+16,2,17,11,71,108,105,110,107,115,45,99,97,99,104,101,75,108,105,110,107,
+115,45,116,105,109,101,115,116,97,109,112,1,22,103,101,116,45,108,105,110,107,
+101,100,45,99,111,108,108,101,99,116,105,111,110,115,1,30,110,111,114,109,97,
+108,105,122,101,45,99,111,108,108,101,99,116,105,111,110,45,114,101,102,101,114,
+101,110,99,101,77,99,104,101,99,107,45,115,117,102,102,105,120,45,99,97,108,
+108,79,112,97,116,104,45,114,101,112,108,97,99,101,45,115,117,102,102,105,120,
+75,112,97,116,104,45,97,100,100,45,115,117,102,102,105,120,77,108,111,97,100,
+47,117,115,101,45,99,111,109,112,105,108,101,100,1,29,102,105,110,100,45,108,
+105,98,114,97,114,121,45,99,111,108,108,101,99,116,105,111,110,45,112,97,116,
+104,115,73,101,109,98,101,100,100,101,100,45,108,111,97,100,64,108,111,111,112,
+69,101,120,101,99,45,102,105,108,101,67,119,105,110,100,111,119,115,68,114,101,
+108,97,116,105,118,101,5,0,5,0,6,25,25,112,97,116,104,32,111,114,32,
+118,97,108,105,100,45,112,97,116,104,32,115,116,114,105,110,103,6,29,29,126,
+97,58,32,105,110,118,97,108,105,100,32,114,101,108,97,116,105,118,101,32,112,
+97,116,104,58,32,126,115,72,99,111,108,108,101,99,116,115,45,100,105,114,65,
+101,114,114,111,114,6,36,36,101,114,114,111,114,32,114,101,97,100,105,110,103,
+32,108,105,110,107,101,100,32,99,111,108,108,101,99,116,105,111,110,115,58,32,
+126,97,6,1,1,47,6,42,42,112,97,116,104,32,40,102,111,114,32,97,110,
+121,32,115,121,115,116,101,109,41,32,111,114,32,118,97,108,105,100,45,112,97,
+116,104,32,115,116,114,105,110,103,6,21,21,115,116,114,105,110,103,32,111,114,
+32,98,121,116,101,32,115,116,114,105,110,103,6,36,36,99,97,110,110,111,116,
+32,97,100,100,32,97,32,115,117,102,102,105,120,32,116,111,32,97,32,114,111,
+111,116,32,112,97,116,104,58,32,6,11,11,80,76,84,67,79,76,76,69,67,
+84,83,6,0,0,6,0,0,69,97,100,100,111,110,45,100,105,114,6,8,8,
+99,111,108,108,101,99,116,115,27,20,13,159,80,159,37,51,37,250,80,159,40,
+52,37,249,22,27,11,80,159,42,51,37,22,186,13,10,248,22,190,5,23,196,
+2,28,248,22,189,6,23,194,2,12,86,94,248,22,148,9,23,194,1,27,20,
+13,159,80,159,38,51,37,250,80,159,41,52,37,249,22,27,11,80,159,43,51,
+37,22,186,13,10,248,22,190,5,23,197,2,28,248,22,189,6,23,194,2,12,
+86,94,248,22,148,9,23,194,1,27,20,13,159,80,159,39,51,37,250,80,159,
+42,52,37,249,22,27,11,80,159,44,51,37,22,186,13,10,248,22,190,5,23,
+198,2,28,248,22,189,6,23,194,2,12,86,94,248,22,148,9,23,194,1,248,
+80,159,40,8,31,39,197,28,248,22,81,23,195,2,9,27,248,22,74,23,196,
2,27,28,248,22,172,14,23,195,2,23,194,1,28,248,22,171,14,23,195,2,
-249,22,173,14,23,196,1,250,80,158,48,50,248,22,188,14,2,21,11,10,250,
-80,158,46,50,248,22,188,14,2,21,23,197,1,10,28,23,193,2,249,22,73,
-248,22,175,14,249,22,173,14,23,198,1,247,22,189,14,248,80,159,46,56,39,
-248,22,75,23,199,1,86,94,23,193,1,248,80,159,44,56,39,248,22,75,23,
+249,22,173,14,23,196,1,250,80,159,43,39,39,248,22,188,14,2,31,11,10,
+250,80,159,41,39,39,248,22,188,14,2,31,23,197,1,10,28,23,193,2,249,
+22,73,248,22,175,14,249,22,173,14,23,198,1,247,22,189,14,27,248,22,75,
+23,200,1,28,248,22,81,23,194,2,9,27,248,22,74,23,195,2,27,28,248,
+22,172,14,23,195,2,23,194,1,28,248,22,171,14,23,195,2,249,22,173,14,
+23,196,1,250,80,159,48,39,39,248,22,188,14,2,31,11,10,250,80,159,46,
+39,39,248,22,188,14,2,31,23,197,1,10,28,23,193,2,249,22,73,248,22,
+175,14,249,22,173,14,23,198,1,247,22,189,14,248,80,159,46,8,30,39,248,
+22,75,23,199,1,86,94,23,193,1,248,80,159,44,8,30,39,248,22,75,23,
197,1,86,94,23,193,1,27,248,22,75,23,198,1,28,248,22,81,23,194,2,
9,27,248,22,74,23,195,2,27,28,248,22,172,14,23,195,2,23,194,1,28,
-248,22,171,14,23,195,2,249,22,173,14,23,196,1,250,80,158,46,50,248,22,
-188,14,2,21,11,10,250,80,158,44,50,248,22,188,14,2,21,23,197,1,10,
-28,23,193,2,249,22,73,248,22,175,14,249,22,173,14,23,198,1,247,22,189,
-14,248,80,159,44,56,39,248,22,75,23,199,1,248,80,159,42,56,39,248,22,
-75,196,28,248,22,81,23,195,2,9,27,248,22,74,23,196,2,27,28,248,22,
-172,14,23,195,2,23,194,1,28,248,22,171,14,23,195,2,249,22,173,14,23,
-196,1,250,80,158,43,50,248,22,188,14,2,21,11,10,250,80,158,41,50,248,
-22,188,14,2,21,23,197,1,10,28,23,193,2,249,22,73,248,22,175,14,249,
-22,173,14,23,198,1,247,22,189,14,248,80,159,41,55,39,248,22,75,23,200,
-1,248,80,159,39,55,39,248,22,75,197,28,248,22,81,23,195,2,9,27,248,
-22,74,23,196,2,27,28,248,22,172,14,23,195,2,23,194,1,28,248,22,171,
-14,23,195,2,249,22,173,14,23,196,1,250,80,158,43,50,248,22,188,14,2,
-21,11,10,250,80,158,41,50,248,22,188,14,2,21,23,197,1,10,28,23,193,
-2,249,22,73,248,22,175,14,249,22,173,14,23,198,1,247,22,189,14,248,80,
-159,41,54,39,248,22,75,23,200,1,248,80,159,39,54,39,248,22,75,197,27,
-248,22,148,14,23,195,2,28,23,193,2,192,86,94,23,193,1,28,248,22,130,
-7,23,195,2,27,248,22,170,14,195,28,192,192,248,22,171,14,195,11,86,94,
-28,28,248,22,149,14,23,195,2,10,28,248,22,148,14,23,195,2,10,28,248,
-22,130,7,23,195,2,28,248,22,170,14,23,195,2,10,248,22,171,14,23,195,
-2,11,12,250,22,176,9,76,110,111,114,109,97,108,45,112,97,116,104,45,99,
-97,115,101,6,42,42,112,97,116,104,32,40,102,111,114,32,97,110,121,32,115,
-121,115,116,101,109,41,32,111,114,32,118,97,108,105,100,45,112,97,116,104,32,
-115,116,114,105,110,103,23,197,2,28,28,248,22,149,14,23,195,2,249,22,140,
-9,248,22,150,14,23,197,2,2,22,249,22,140,9,247,22,152,8,2,22,27,
-28,248,22,130,7,23,196,2,23,195,2,248,22,142,8,248,22,153,14,23,197,
-2,28,249,22,139,15,0,21,35,114,120,34,94,91,92,92,93,91,92,92,93,
-91,63,93,91,92,92,93,34,23,195,2,28,248,22,130,7,195,248,22,156,14,
-195,194,27,248,22,169,7,23,195,1,249,22,157,14,248,22,145,8,250,22,147,
-15,0,6,35,114,120,34,47,34,28,249,22,139,15,0,22,35,114,120,34,91,
-47,92,92,93,91,46,32,93,43,91,47,92,92,93,42,36,34,23,201,2,23,
-199,1,250,22,147,15,0,19,35,114,120,34,91,32,46,93,43,40,91,47,92,
-92,93,42,41,36,34,23,202,1,6,2,2,92,49,80,159,44,37,38,2,22,
-28,248,22,130,7,194,248,22,156,14,194,193,86,94,28,28,248,22,148,14,23,
-195,2,10,28,248,22,130,7,23,195,2,28,248,22,170,14,23,195,2,10,248,
-22,171,14,23,195,2,11,12,250,22,176,9,23,196,2,2,23,23,197,2,28,
-248,22,170,14,23,195,2,12,248,22,162,12,249,22,168,11,248,22,159,7,250,
-22,178,7,2,24,23,200,1,23,201,1,247,22,23,86,94,28,28,248,22,148,
-14,23,195,2,10,28,248,22,130,7,23,195,2,28,248,22,170,14,23,195,2,
-10,248,22,171,14,23,195,2,11,12,250,22,176,9,23,196,2,2,23,23,197,
-2,28,248,22,170,14,23,195,2,12,248,22,162,12,249,22,168,11,248,22,159,
-7,250,22,178,7,2,24,23,200,1,23,201,1,247,22,23,86,94,86,94,28,
-28,248,22,148,14,23,195,2,10,28,248,22,130,7,23,195,2,28,248,22,170,
-14,23,195,2,10,248,22,171,14,23,195,2,11,12,250,22,176,9,195,2,23,
-23,197,2,28,248,22,170,14,23,195,2,12,248,22,162,12,249,22,168,11,248,
-22,159,7,250,22,178,7,2,24,199,23,201,1,247,22,23,249,22,3,88,163,
-8,36,37,50,11,9,223,2,33,47,196,86,94,28,28,248,22,148,14,23,194,
-2,10,28,248,22,130,7,23,194,2,28,248,22,170,14,23,194,2,10,248,22,
-171,14,23,194,2,11,12,250,22,176,9,2,7,2,23,23,196,2,28,248,22,
-170,14,23,194,2,12,248,22,162,12,249,22,168,11,248,22,159,7,250,22,178,
-7,2,24,2,7,23,200,1,247,22,23,32,50,88,163,8,36,41,56,11,2,
-26,222,33,51,28,248,22,81,23,197,2,86,94,23,196,1,28,23,197,2,196,
-86,94,23,197,1,248,22,162,12,249,22,137,12,251,22,178,7,2,25,2,7,
-28,248,22,81,23,203,2,86,94,23,202,1,23,201,1,250,22,1,22,166,14,
-23,204,1,23,205,1,23,200,1,247,22,23,27,249,22,166,14,248,22,74,23,
-200,2,23,197,2,28,248,22,161,14,23,194,2,27,250,22,1,22,166,14,23,
-197,1,199,28,248,22,161,14,193,192,252,2,50,199,200,201,248,22,75,203,203,
-252,2,50,198,199,200,248,22,75,202,202,86,94,86,94,86,94,28,28,248,22,
+248,22,171,14,23,195,2,249,22,173,14,23,196,1,250,80,159,46,39,39,248,
+22,188,14,2,31,11,10,250,80,159,44,39,39,248,22,188,14,2,31,23,197,
+1,10,28,23,193,2,249,22,73,248,22,175,14,249,22,173,14,23,198,1,247,
+22,189,14,248,80,159,44,8,30,39,248,22,75,23,199,1,248,80,159,42,8,
+30,39,248,22,75,196,28,248,22,81,23,195,2,9,27,248,22,74,23,196,2,
+27,28,248,22,172,14,23,195,2,23,194,1,28,248,22,171,14,23,195,2,249,
+22,173,14,23,196,1,250,80,159,43,39,39,248,22,188,14,2,31,11,10,250,
+80,159,41,39,39,248,22,188,14,2,31,23,197,1,10,28,23,193,2,249,22,
+73,248,22,175,14,249,22,173,14,23,198,1,247,22,189,14,248,80,159,41,8,
+29,39,248,22,75,23,200,1,248,80,159,39,8,29,39,248,22,75,197,28,248,
+22,81,23,195,2,9,27,248,22,74,23,196,2,27,28,248,22,172,14,23,195,
+2,23,194,1,28,248,22,171,14,23,195,2,249,22,173,14,23,196,1,250,80,
+159,43,39,39,248,22,188,14,2,31,11,10,250,80,159,41,39,39,248,22,188,
+14,2,31,23,197,1,10,28,23,193,2,249,22,73,248,22,175,14,249,22,173,
+14,23,198,1,247,22,189,14,248,80,159,41,8,28,39,248,22,75,23,200,1,
+248,80,159,39,8,28,39,248,22,75,197,27,248,22,148,14,23,195,2,28,23,
+193,2,192,86,94,23,193,1,28,248,22,130,7,23,195,2,27,248,22,170,14,
+195,28,192,192,248,22,171,14,195,11,86,94,28,28,248,22,149,14,23,195,2,
+10,28,248,22,148,14,23,195,2,10,28,248,22,130,7,23,195,2,28,248,22,
+170,14,23,195,2,10,248,22,171,14,23,195,2,11,12,250,22,176,9,76,110,
+111,114,109,97,108,45,112,97,116,104,45,99,97,115,101,6,42,42,112,97,116,
+104,32,40,102,111,114,32,97,110,121,32,115,121,115,116,101,109,41,32,111,114,
+32,118,97,108,105,100,45,112,97,116,104,32,115,116,114,105,110,103,23,197,2,
+28,28,248,22,149,14,23,195,2,249,22,140,9,248,22,150,14,23,197,2,2,
+32,249,22,140,9,247,22,152,8,2,32,27,28,248,22,130,7,23,196,2,23,
+195,2,248,22,142,8,248,22,153,14,23,197,2,28,249,22,139,15,0,21,35,
+114,120,34,94,91,92,92,93,91,92,92,93,91,63,93,91,92,92,93,34,23,
+195,2,28,248,22,130,7,195,248,22,156,14,195,194,27,248,22,169,7,23,195,
+1,249,22,157,14,248,22,145,8,250,22,147,15,0,6,35,114,120,34,47,34,
+28,249,22,139,15,0,22,35,114,120,34,91,47,92,92,93,91,46,32,93,43,
+91,47,92,92,93,42,36,34,23,201,2,23,199,1,250,22,147,15,0,19,35,
+114,120,34,91,32,46,93,43,40,91,47,92,92,93,42,41,36,34,23,202,1,
+6,2,2,92,49,80,159,44,37,38,2,32,28,248,22,130,7,194,248,22,156,
+14,194,193,32,56,88,163,8,36,39,53,11,70,102,111,117,110,100,45,101,120,
+101,99,222,33,59,32,57,88,163,8,36,40,58,11,64,110,101,120,116,222,33,
+58,27,248,22,174,14,23,196,2,28,249,22,142,9,23,195,2,23,197,1,11,
+28,248,22,170,14,23,194,2,27,249,22,166,14,23,197,1,23,196,1,28,23,
+197,2,90,159,39,11,89,161,39,36,11,248,22,169,14,23,197,2,86,95,23,
+195,1,23,194,1,27,28,23,202,2,27,248,22,174,14,23,199,2,28,249,22,
+142,9,23,195,2,23,200,2,11,28,248,22,170,14,23,194,2,250,2,56,23,
+205,2,23,206,2,249,22,166,14,23,200,2,23,198,1,250,2,56,23,205,2,
+23,206,2,23,196,1,11,28,23,193,2,192,86,94,23,193,1,27,28,248,22,
+148,14,23,196,2,27,249,22,166,14,23,198,2,23,205,2,28,28,248,22,161,
+14,193,10,248,22,160,14,193,192,11,11,28,23,193,2,192,86,94,23,193,1,
+28,23,203,2,11,27,248,22,174,14,23,200,2,28,249,22,142,9,23,195,2,
+23,201,1,11,28,248,22,170,14,23,194,2,250,2,56,23,206,1,23,207,1,
+249,22,166,14,23,201,1,23,198,1,250,2,56,205,206,195,192,86,94,23,194,
+1,28,23,196,2,90,159,39,11,89,161,39,36,11,248,22,169,14,23,197,2,
+86,95,23,195,1,23,194,1,27,28,23,201,2,27,248,22,174,14,23,199,2,
+28,249,22,142,9,23,195,2,23,200,2,11,28,248,22,170,14,23,194,2,250,
+2,56,23,204,2,23,205,2,249,22,166,14,23,200,2,23,198,1,250,2,56,
+23,204,2,23,205,2,23,196,1,11,28,23,193,2,192,86,94,23,193,1,27,
+28,248,22,148,14,23,196,2,27,249,22,166,14,23,198,2,23,204,2,28,28,
+248,22,161,14,193,10,248,22,160,14,193,192,11,11,28,23,193,2,192,86,94,
+23,193,1,28,23,202,2,11,27,248,22,174,14,23,200,2,28,249,22,142,9,
+23,195,2,23,201,1,11,28,248,22,170,14,23,194,2,250,2,56,23,205,1,
+23,206,1,249,22,166,14,23,201,1,23,198,1,250,2,56,204,205,195,192,28,
+23,193,2,90,159,39,11,89,161,39,36,11,248,22,169,14,23,199,2,86,95,
+23,195,1,23,194,1,27,28,23,198,2,251,2,57,23,198,2,23,203,2,23,
+201,2,23,202,2,11,28,23,193,2,192,86,94,23,193,1,27,28,248,22,148,
+14,195,27,249,22,166,14,197,200,28,28,248,22,161,14,193,10,248,22,160,14,
+193,192,11,11,28,192,192,28,198,11,251,2,57,198,203,201,202,194,32,60,88,
+163,8,36,40,58,11,2,30,222,33,61,28,248,22,81,23,197,2,11,27,248,
+22,173,14,248,22,74,23,199,2,27,249,22,166,14,23,196,1,23,197,2,28,
+248,22,160,14,23,194,2,250,2,56,198,199,195,86,94,23,193,1,27,248,22,
+75,23,200,1,28,248,22,81,23,194,2,11,27,248,22,173,14,248,22,74,23,
+196,2,27,249,22,166,14,23,196,1,23,200,2,28,248,22,160,14,23,194,2,
+250,2,56,201,202,195,86,94,23,193,1,27,248,22,75,23,197,1,28,248,22,
+81,23,194,2,11,27,248,22,173,14,248,22,74,195,27,249,22,166,14,23,196,
+1,202,28,248,22,160,14,193,250,2,56,204,205,195,251,2,60,204,205,206,248,
+22,75,199,86,95,28,28,248,22,148,14,23,195,2,10,28,248,22,130,7,23,
+195,2,28,248,22,170,14,23,195,2,10,248,22,171,14,23,195,2,11,12,250,
+22,176,9,2,5,6,25,25,112,97,116,104,32,111,114,32,115,116,114,105,110,
+103,32,40,115,97,110,115,32,110,117,108,41,23,197,2,28,28,23,195,2,28,
+28,248,22,148,14,23,196,2,10,28,248,22,130,7,23,196,2,28,248,22,170,
+14,23,196,2,10,248,22,171,14,23,196,2,11,248,22,170,14,23,196,2,11,
+10,12,250,22,176,9,2,5,6,29,29,35,102,32,111,114,32,114,101,108,97,
+116,105,118,101,32,112,97,116,104,32,111,114,32,115,116,114,105,110,103,23,198,
+2,28,28,248,22,170,14,23,195,2,90,159,39,11,89,161,39,36,11,248,22,
+169,14,23,198,2,249,22,140,9,194,2,33,11,27,248,22,150,8,6,4,4,
+80,65,84,72,27,28,23,194,2,27,249,80,158,41,40,23,197,1,9,28,249,
+22,140,9,247,22,152,8,2,32,249,22,73,248,22,157,14,5,1,46,194,192,
+86,94,23,194,1,9,28,248,22,81,23,194,2,11,27,248,22,173,14,248,22,
+74,23,196,2,27,249,22,166,14,23,196,1,23,200,2,28,248,22,160,14,23,
+194,2,250,2,56,201,202,195,86,94,23,193,1,27,248,22,75,23,197,1,28,
+248,22,81,23,194,2,11,27,248,22,173,14,248,22,74,23,196,2,27,249,22,
+166,14,23,196,1,23,203,2,28,248,22,160,14,23,194,2,250,2,56,204,205,
+195,86,94,23,193,1,27,248,22,75,23,197,1,28,248,22,81,23,194,2,11,
+27,248,22,173,14,248,22,74,195,27,249,22,166,14,23,196,1,205,28,248,22,
+160,14,193,250,2,56,23,15,23,16,195,251,2,60,23,15,23,16,23,17,248,
+22,75,199,27,248,22,173,14,23,196,1,28,248,22,160,14,193,250,2,56,198,
+199,195,11,250,80,159,39,39,39,196,197,11,250,80,159,39,39,39,196,11,11,
+32,65,88,163,8,36,39,57,11,2,30,222,33,67,0,8,35,114,120,35,34,
+92,34,34,27,249,22,135,15,23,197,2,23,198,2,28,23,193,2,86,94,23,
+196,1,27,248,22,98,23,195,2,27,27,248,22,107,23,197,1,27,249,22,135,
+15,23,201,2,23,196,2,28,23,193,2,86,94,23,194,1,27,248,22,98,23,
+195,2,27,250,2,65,23,203,2,23,204,1,248,22,107,23,199,1,28,249,22,
+191,7,23,196,2,2,34,249,22,87,23,202,2,194,249,22,73,248,22,157,14,
+28,249,22,140,9,247,22,152,8,2,32,250,22,147,15,2,66,23,200,1,2,
+35,23,197,1,194,86,95,23,199,1,23,193,1,28,249,22,191,7,23,196,2,
+2,34,249,22,87,23,200,2,9,249,22,73,248,22,157,14,28,249,22,140,9,
+247,22,152,8,2,32,250,22,147,15,2,66,23,200,1,2,35,23,197,1,9,
+28,249,22,191,7,23,196,2,2,34,249,22,87,197,194,86,94,23,196,1,249,
+22,73,248,22,157,14,28,249,22,140,9,247,22,152,8,2,32,250,22,147,15,
+2,66,23,200,1,2,35,23,197,1,194,86,94,23,193,1,28,249,22,191,7,
+23,198,2,2,34,249,22,87,195,9,86,94,23,194,1,249,22,73,248,22,157,
+14,28,249,22,140,9,247,22,152,8,2,32,250,22,147,15,2,66,23,202,1,
+2,35,23,199,1,9,86,95,28,28,248,22,183,7,194,10,248,22,130,7,194,
+12,250,22,176,9,2,6,6,21,21,98,121,116,101,32,115,116,114,105,110,103,
+32,111,114,32,115,116,114,105,110,103,196,28,28,248,22,82,195,249,22,4,22,
+148,14,196,11,12,250,22,176,9,2,6,6,13,13,108,105,115,116,32,111,102,
+32,112,97,116,104,115,197,250,2,65,197,195,28,248,22,130,7,197,248,22,144,
+8,197,196,86,94,28,28,248,22,148,14,23,195,2,10,28,248,22,130,7,23,
+195,2,28,248,22,170,14,23,195,2,10,248,22,171,14,23,195,2,11,12,250,
+22,176,9,23,196,2,2,36,23,197,2,28,248,22,170,14,23,195,2,12,248,
+22,162,12,249,22,168,11,248,22,159,7,250,22,178,7,2,37,23,200,1,23,
+201,1,247,22,23,86,94,28,28,248,22,148,14,23,195,2,10,28,248,22,130,
+7,23,195,2,28,248,22,170,14,23,195,2,10,248,22,171,14,23,195,2,11,
+12,250,22,176,9,23,196,2,2,36,23,197,2,28,248,22,170,14,23,195,2,
+12,248,22,162,12,249,22,168,11,248,22,159,7,250,22,178,7,2,37,23,200,
+1,23,201,1,247,22,23,86,94,86,94,28,28,248,22,148,14,23,195,2,10,
+28,248,22,130,7,23,195,2,28,248,22,170,14,23,195,2,10,248,22,171,14,
+23,195,2,11,12,250,22,176,9,195,2,36,23,197,2,28,248,22,170,14,23,
+195,2,12,248,22,162,12,249,22,168,11,248,22,159,7,250,22,178,7,2,37,
+199,23,201,1,247,22,23,249,22,3,88,163,8,36,37,50,11,9,223,2,33,
+70,196,86,94,28,28,248,22,148,14,23,194,2,10,28,248,22,130,7,23,194,
+2,28,248,22,170,14,23,194,2,10,248,22,171,14,23,194,2,11,12,250,22,
+176,9,2,9,2,36,23,196,2,28,248,22,170,14,23,194,2,12,248,22,162,
+12,249,22,168,11,248,22,159,7,250,22,178,7,2,37,2,9,23,200,1,247,
+22,23,248,22,162,12,249,22,137,12,23,196,1,247,22,23,86,94,86,94,86,
+94,28,28,248,22,148,14,194,10,28,248,22,130,7,194,28,248,22,170,14,194,
+10,248,22,171,14,194,11,12,250,22,176,9,2,9,2,36,196,28,248,22,170,
+14,194,12,248,22,162,12,249,22,168,11,248,22,159,7,250,22,178,7,2,37,
+2,9,200,247,22,23,249,22,3,32,0,88,163,8,36,37,49,11,9,222,33,
+72,196,252,80,158,41,44,2,9,32,0,88,163,8,36,37,45,11,9,222,33,
+73,198,199,11,86,94,28,28,248,22,148,14,23,194,2,10,28,248,22,130,7,
+23,194,2,28,248,22,170,14,23,194,2,10,248,22,171,14,23,194,2,11,12,
+250,22,176,9,2,11,2,36,23,196,2,28,248,22,170,14,23,194,2,12,248,
+22,162,12,249,22,168,11,248,22,159,7,250,22,178,7,2,37,2,11,23,200,
+1,247,22,23,248,22,162,12,249,22,137,12,23,196,1,247,22,23,86,95,86,
+94,28,28,248,22,148,14,194,10,28,248,22,130,7,194,28,248,22,170,14,194,
+10,248,22,171,14,194,11,12,250,22,176,9,2,11,2,36,196,28,248,22,170,
+14,194,12,248,22,162,12,249,22,168,11,248,22,159,7,250,22,178,7,2,37,
+2,11,200,247,22,23,86,94,86,94,28,28,248,22,148,14,23,196,2,10,28,
+248,22,130,7,23,196,2,28,248,22,170,14,23,196,2,10,248,22,171,14,23,
+196,2,11,12,250,22,176,9,2,11,2,36,23,198,2,28,248,22,170,14,23,
+196,2,12,248,22,162,12,249,22,168,11,248,22,159,7,250,22,178,7,2,37,
+2,11,23,202,2,247,22,23,249,22,3,32,0,88,163,8,36,37,49,11,9,
+222,33,75,23,198,2,249,22,166,14,252,80,158,43,44,2,11,32,0,88,163,
+8,36,37,45,11,9,222,33,76,23,202,1,23,203,1,200,195,0,6,45,105,
+110,102,46,48,27,248,22,188,14,2,38,27,28,248,22,171,14,23,195,2,193,
+20,13,159,80,159,38,51,37,250,80,159,41,52,37,249,22,27,11,80,159,43,
+51,37,22,189,14,248,22,188,14,68,111,114,105,103,45,100,105,114,27,248,22,
+188,14,2,31,250,80,159,42,39,39,23,196,1,23,198,1,11,28,192,250,22,
+166,14,195,6,6,6,99,111,110,102,105,103,6,10,10,108,105,110,107,115,46,
+114,107,116,100,11,86,94,27,247,22,131,10,28,249,22,188,9,23,195,2,2,
+39,251,22,191,9,23,197,1,2,39,249,22,178,7,2,40,248,22,160,11,23,
+202,1,247,22,23,12,248,193,247,22,133,2,2,78,86,95,27,247,22,131,10,
+28,249,22,188,9,23,195,2,2,39,251,22,191,9,23,197,1,2,39,249,22,
+178,7,2,40,248,22,160,11,23,205,1,247,22,23,12,28,192,28,194,86,94,
+20,18,159,11,80,158,39,47,247,22,133,2,20,18,159,11,80,158,39,48,192,
+86,94,20,18,159,11,80,158,39,53,247,22,133,2,20,18,159,11,80,158,39,
+54,192,12,248,194,247,22,133,2,20,20,94,248,22,190,5,23,194,2,28,248,
+22,189,6,248,22,190,5,23,195,1,12,248,22,173,9,6,30,30,101,120,112,
+101,99,116,101,100,32,97,32,115,105,110,103,108,101,32,83,45,101,120,112,114,
+101,115,115,105,111,110,248,22,178,5,193,28,248,22,82,23,194,2,28,28,249,
+22,184,3,38,248,22,86,23,196,2,10,249,22,184,3,39,248,22,86,23,196,
+2,28,248,22,130,7,248,22,74,23,195,2,28,27,248,22,98,194,28,248,22,
148,14,23,194,2,10,28,248,22,130,7,23,194,2,28,248,22,170,14,23,194,
-2,10,248,22,171,14,23,194,2,11,12,250,22,176,9,2,7,2,23,23,196,
-2,28,248,22,170,14,23,194,2,12,248,22,162,12,249,22,168,11,248,22,159,
-7,250,22,178,7,2,24,2,7,23,200,2,247,22,23,249,22,3,32,0,88,
-163,8,36,37,49,11,9,222,33,49,23,196,2,27,247,22,190,14,28,248,22,
-81,23,194,2,248,22,162,12,249,22,137,12,251,22,178,7,2,25,2,7,28,
-248,22,81,23,203,2,86,94,23,202,1,23,201,1,250,22,1,22,166,14,23,
-204,1,23,205,1,23,200,1,247,22,23,27,249,22,166,14,248,22,74,23,197,
-2,23,197,2,28,248,22,161,14,23,194,2,27,250,22,1,22,166,14,23,197,
-1,199,28,248,22,161,14,193,192,252,2,50,199,200,201,248,22,75,200,11,252,
-2,50,198,199,200,248,22,75,199,11,86,94,28,28,248,22,148,14,23,194,2,
-10,28,248,22,130,7,23,194,2,28,248,22,170,14,23,194,2,10,248,22,171,
-14,23,194,2,11,12,250,22,176,9,2,9,2,23,23,196,2,28,248,22,170,
-14,23,194,2,12,248,22,162,12,249,22,168,11,248,22,159,7,250,22,178,7,
-2,24,2,9,23,200,1,247,22,23,32,54,88,163,8,36,42,59,11,2,26,
-222,33,55,28,248,22,81,23,198,2,86,95,23,197,1,23,194,1,28,23,198,
-2,197,86,94,23,198,1,248,22,162,12,249,22,137,12,251,22,178,7,2,25,
-2,9,28,248,22,81,23,204,2,86,94,23,203,1,23,202,1,250,22,1,22,
-166,14,23,205,1,23,206,1,23,200,1,247,22,23,27,249,22,166,14,248,22,
-74,23,201,2,23,198,2,28,248,22,161,14,23,194,2,27,250,22,1,22,166,
-14,23,197,1,23,201,2,28,248,22,161,14,23,194,2,28,23,196,2,28,28,
-248,22,160,14,249,22,166,14,195,198,10,27,28,248,22,148,14,197,248,22,152,
-14,197,196,27,248,22,133,7,23,195,2,27,28,249,22,188,3,23,196,2,40,
-28,249,22,136,7,2,27,249,22,152,7,23,199,2,249,22,176,3,23,200,2,
-40,249,22,153,7,250,22,152,7,23,200,1,36,249,22,176,3,23,201,1,40,
-2,28,86,95,23,195,1,23,194,1,11,11,28,23,193,2,248,22,160,14,249,
-22,166,14,198,23,196,1,11,192,253,2,54,200,201,202,203,248,22,75,205,28,
-205,205,198,192,253,2,54,200,201,202,203,248,22,75,205,205,253,2,54,199,200,
-201,202,248,22,75,204,204,86,95,86,94,28,28,248,22,148,14,193,10,28,248,
-22,130,7,193,28,248,22,170,14,193,10,248,22,171,14,193,11,12,250,22,176,
-9,2,9,2,23,195,28,248,22,170,14,193,12,248,22,162,12,249,22,168,11,
-248,22,159,7,250,22,178,7,2,24,2,9,199,247,22,23,86,94,86,94,28,
-28,248,22,148,14,23,195,2,10,28,248,22,130,7,23,195,2,28,248,22,170,
-14,23,195,2,10,248,22,171,14,23,195,2,11,12,250,22,176,9,2,9,2,
-23,23,197,2,28,248,22,170,14,23,195,2,12,248,22,162,12,249,22,168,11,
-248,22,159,7,250,22,178,7,2,24,2,9,23,201,2,247,22,23,249,22,3,
-32,0,88,163,8,36,37,49,11,9,222,33,53,23,197,2,249,22,166,14,27,
-247,22,190,14,253,2,54,23,199,2,201,23,203,1,23,204,1,23,199,1,11,
-194,32,57,88,163,36,44,8,29,11,2,26,222,33,58,28,248,22,81,23,200,
-2,86,95,23,199,1,23,198,1,28,23,200,2,199,86,94,23,200,1,248,23,
-196,1,251,22,178,7,2,25,23,199,1,28,248,22,81,23,203,2,86,94,23,
-202,1,23,201,1,250,22,1,22,166,14,23,204,1,23,205,1,23,198,1,27,
-249,22,166,14,248,22,74,23,203,2,23,199,2,28,248,22,161,14,23,194,2,
-27,250,22,1,22,166,14,23,197,1,23,202,2,28,248,22,161,14,23,194,2,
-28,23,200,2,28,28,248,22,160,14,249,22,166,14,23,196,2,23,203,2,10,
-27,28,248,22,148,14,23,202,2,248,22,152,14,23,202,2,23,201,2,27,248,
-22,133,7,23,195,2,27,28,249,22,188,3,23,196,2,40,28,249,22,136,7,
-2,27,249,22,152,7,23,199,2,249,22,176,3,23,200,2,40,249,22,153,7,
-250,22,152,7,23,200,1,36,249,22,176,3,23,201,1,40,2,28,86,95,23,
-195,1,23,194,1,11,11,28,23,193,2,248,22,160,14,249,22,166,14,23,199,
-2,23,196,1,11,192,27,248,22,75,23,203,1,27,28,23,204,2,86,94,23,
-195,1,23,204,1,86,94,23,204,1,23,195,1,28,248,22,81,23,195,2,86,
-95,23,202,1,23,194,1,28,23,193,2,192,86,94,23,193,1,248,23,200,1,
-251,22,178,7,2,25,23,203,1,28,248,22,81,23,207,2,86,94,23,206,1,
-23,205,1,250,22,1,22,166,14,23,208,1,23,209,1,23,202,1,27,249,22,
-166,14,248,22,74,23,198,2,23,203,2,28,248,22,161,14,23,194,2,27,250,
-22,1,22,166,14,23,197,1,23,206,2,28,248,22,161,14,23,194,2,28,23,
-204,2,28,28,248,22,160,14,249,22,166,14,195,206,10,27,28,248,22,148,14,
-205,248,22,152,14,205,204,27,248,22,133,7,23,195,2,27,28,249,22,188,3,
-23,196,2,40,28,249,22,136,7,2,27,249,22,152,7,23,199,2,249,22,176,
-3,23,200,2,40,249,22,153,7,250,22,152,7,23,200,1,36,249,22,176,3,
-23,201,1,40,2,28,86,95,23,195,1,23,194,1,11,11,28,23,193,2,248,
-22,160,14,249,22,166,14,198,23,196,1,11,192,26,8,2,57,206,23,15,23,
-16,23,17,23,18,23,19,248,22,75,204,28,202,202,200,192,26,8,2,57,206,
-23,15,23,16,23,17,23,18,23,19,248,22,75,204,202,26,8,2,57,205,206,
-23,15,23,16,23,17,23,18,248,22,75,203,201,192,27,248,22,75,23,203,1,
-28,248,22,81,23,194,2,86,95,23,201,1,23,193,1,28,23,203,2,202,86,
-94,23,203,1,248,23,199,1,251,22,178,7,2,25,23,202,1,28,248,22,81,
-23,206,2,86,94,23,205,1,23,204,1,250,22,1,22,166,14,23,207,1,23,
-208,1,23,201,1,27,249,22,166,14,248,22,74,23,197,2,23,202,2,28,248,
-22,161,14,23,194,2,27,250,22,1,22,166,14,23,197,1,23,205,2,28,248,
-22,161,14,23,194,2,28,23,203,2,28,28,248,22,160,14,249,22,166,14,195,
-205,10,27,28,248,22,148,14,204,248,22,152,14,204,203,27,248,22,133,7,23,
-195,2,27,28,249,22,188,3,23,196,2,40,28,249,22,136,7,2,27,249,22,
-152,7,23,199,2,249,22,176,3,23,200,2,40,249,22,153,7,250,22,152,7,
-23,200,1,36,249,22,176,3,23,201,1,40,2,28,86,95,23,195,1,23,194,
-1,11,11,28,23,193,2,248,22,160,14,249,22,166,14,198,23,196,1,11,192,
-26,8,2,57,205,206,23,15,23,16,23,17,23,18,248,22,75,203,28,23,20,
-23,20,200,192,26,8,2,57,205,206,23,15,23,16,23,17,23,18,248,22,75,
-203,23,20,26,8,2,57,204,205,206,23,15,23,16,23,17,248,22,75,202,23,
-19,86,94,23,193,1,27,248,22,75,23,202,1,28,248,22,81,23,194,2,86,
-95,23,200,1,23,193,1,28,23,202,2,201,86,94,23,202,1,248,23,198,1,
-251,22,178,7,2,25,23,201,1,28,248,22,81,23,205,2,86,94,23,204,1,
-23,203,1,250,22,1,22,166,14,23,206,1,23,207,1,23,200,1,27,249,22,
-166,14,248,22,74,23,197,2,23,201,2,28,248,22,161,14,23,194,2,27,250,
-22,1,22,166,14,23,197,1,23,204,2,28,248,22,161,14,23,194,2,28,23,
-202,2,28,28,248,22,160,14,249,22,166,14,195,204,10,27,28,248,22,148,14,
-203,248,22,152,14,203,202,27,248,22,133,7,23,195,2,27,28,249,22,188,3,
-23,196,2,40,28,249,22,136,7,2,27,249,22,152,7,23,199,2,249,22,176,
-3,23,200,2,40,249,22,153,7,250,22,152,7,23,200,1,36,249,22,176,3,
-23,201,1,40,2,28,86,95,23,195,1,23,194,1,11,11,28,23,193,2,248,
-22,160,14,249,22,166,14,198,23,196,1,11,192,26,8,2,57,204,205,206,23,
-15,23,16,23,17,248,22,75,203,28,23,19,23,19,200,192,26,8,2,57,204,
-205,206,23,15,23,16,23,17,248,22,75,203,23,19,26,8,2,57,203,204,205,
-206,23,15,23,16,248,22,75,202,23,18,27,247,22,190,14,28,248,22,81,23,
-194,2,86,94,23,198,1,248,23,196,1,251,22,178,7,2,25,23,199,1,28,
-248,22,81,23,203,2,86,94,23,202,1,23,201,1,250,22,1,22,166,14,23,
-204,1,23,205,1,23,198,1,27,249,22,166,14,248,22,74,23,197,2,23,199,
-2,28,248,22,161,14,23,194,2,27,250,22,1,22,166,14,23,197,1,23,202,
-2,28,248,22,161,14,23,194,2,28,23,200,2,28,28,248,22,160,14,249,22,
-166,14,195,202,10,27,28,248,22,148,14,201,248,22,152,14,201,200,27,248,22,
-133,7,23,195,2,27,28,249,22,188,3,23,196,2,40,28,249,22,136,7,2,
-27,249,22,152,7,23,199,2,249,22,176,3,23,200,2,40,249,22,153,7,250,
-22,152,7,23,200,1,36,249,22,176,3,23,201,1,40,2,28,86,95,23,195,
+2,10,248,22,171,14,23,194,1,11,27,248,22,81,248,22,100,195,28,192,192,
+248,22,148,15,248,22,107,195,11,11,11,11,28,28,248,22,81,248,22,100,23,
+197,2,10,249,22,139,15,248,22,107,23,198,2,247,22,148,8,27,248,22,61,
+248,22,74,23,198,2,250,22,151,2,23,197,2,23,196,2,249,22,73,248,22,
+125,249,22,173,14,248,22,98,23,205,1,23,203,1,250,22,153,2,23,202,1,
+23,201,1,9,12,20,13,159,80,159,37,56,37,88,163,36,37,51,11,9,223,
+2,33,80,27,250,22,183,14,28,23,197,2,80,159,41,46,38,80,159,41,49,
+38,11,32,0,88,163,8,36,36,41,11,9,222,33,81,28,249,22,186,3,23,
+195,2,28,23,196,2,80,158,40,48,80,158,40,54,20,13,159,80,159,38,56,
+37,20,20,94,88,163,36,37,54,8,240,0,24,6,0,9,226,2,1,3,0,
+33,82,23,196,1,20,13,159,80,159,38,51,37,26,29,80,159,8,31,52,37,
+249,22,27,11,80,159,8,33,51,37,22,182,13,10,22,183,13,10,22,184,13,
+10,22,187,13,10,22,186,13,10,22,188,13,10,22,185,13,10,22,189,13,10,
+22,190,13,10,22,191,13,10,22,128,14,10,22,129,14,10,22,130,14,11,22,
+180,13,11,27,249,22,169,5,28,196,80,159,41,46,38,80,159,41,49,38,66,
+98,105,110,97,114,121,27,250,22,40,22,31,88,163,8,36,36,44,11,9,223,
+4,33,83,20,20,94,88,163,36,36,43,11,9,223,4,33,84,23,197,1,86,
+94,28,28,248,22,82,23,194,2,249,22,4,32,0,88,163,8,36,37,45,11,
+9,222,33,85,23,195,2,11,12,248,22,173,9,6,18,18,105,108,108,45,102,
+111,114,109,101,100,32,99,111,110,116,101,110,116,27,247,22,133,2,27,90,159,
+39,11,89,161,39,36,11,248,22,169,14,28,201,80,159,46,46,38,80,159,46,
+49,38,192,86,95,249,22,3,20,20,94,88,163,8,36,37,54,11,9,224,2,
+3,33,86,23,195,1,23,197,1,28,197,86,94,20,18,159,11,80,158,42,47,
+193,20,18,159,11,80,158,42,48,196,86,94,20,18,159,11,80,158,42,53,193,
+20,18,159,11,80,158,42,54,196,193,28,193,80,158,38,47,80,158,38,53,248,
+22,8,88,163,8,32,37,8,40,8,240,0,188,23,0,9,224,1,2,33,87,
+0,7,35,114,120,34,47,43,34,28,248,22,130,7,23,195,2,27,249,22,137,
+15,2,89,196,28,192,28,249,22,184,3,248,22,97,195,248,22,174,3,248,22,
+133,7,198,249,22,7,250,22,152,7,199,36,248,22,97,198,197,249,22,7,250,
+22,152,7,199,36,248,22,97,198,249,22,73,249,22,152,7,200,248,22,99,199,
+199,249,22,7,196,197,90,159,39,11,89,161,39,36,11,248,22,169,14,23,198,
+1,86,94,23,195,1,28,249,22,140,9,23,195,2,2,33,249,22,7,195,199,
+27,249,22,73,23,197,1,23,201,1,28,248,22,130,7,23,195,2,27,249,22,
+137,15,2,89,196,28,192,28,249,22,184,3,248,22,97,195,248,22,174,3,248,
+22,133,7,198,249,22,7,250,22,152,7,199,36,248,22,97,198,195,249,22,7,
+250,22,152,7,199,36,248,22,97,198,249,22,73,249,22,152,7,200,248,22,99,
+199,197,249,22,7,196,195,90,159,39,11,89,161,39,36,11,248,22,169,14,23,
+198,1,28,249,22,140,9,194,2,33,249,22,7,195,197,249,80,159,45,57,39,
+194,249,22,73,197,199,32,91,88,163,36,44,8,36,11,65,99,108,111,111,112,
+222,33,96,32,92,88,163,8,36,37,55,11,2,30,222,33,93,28,248,22,81,
+248,22,75,23,195,2,248,22,83,27,248,22,74,23,196,1,28,248,22,148,14,
+23,194,2,248,22,152,14,23,194,1,192,250,22,84,27,248,22,74,23,198,2,
+28,248,22,148,14,23,194,2,248,22,152,14,23,194,1,192,2,41,27,248,22,
+75,23,198,1,28,248,22,81,248,22,75,23,195,2,248,22,83,27,248,22,74,
+23,196,1,28,248,22,148,14,23,194,2,248,22,152,14,23,194,1,192,250,22,
+84,27,248,22,74,23,198,2,28,248,22,148,14,23,194,2,248,22,152,14,23,
+194,1,192,2,41,27,248,22,75,23,198,1,28,248,22,81,248,22,75,23,195,
+2,248,22,83,27,248,22,74,23,196,1,28,248,22,148,14,23,194,2,248,22,
+152,14,23,194,1,192,250,22,84,27,248,22,74,23,198,2,28,248,22,148,14,
+23,194,2,248,22,152,14,23,194,1,192,2,41,248,2,92,248,22,75,23,198,
+1,32,94,88,163,8,36,38,57,11,66,102,105,108,116,101,114,222,33,95,28,
+248,22,81,23,195,2,9,28,248,23,194,2,248,22,74,23,196,2,249,22,73,
+248,22,74,23,197,2,27,248,22,75,23,198,1,28,248,22,81,23,194,2,9,
+28,248,23,197,2,248,22,74,23,195,2,249,22,73,248,22,74,23,196,2,27,
+248,22,75,23,197,1,28,248,22,81,23,194,2,9,28,248,23,200,2,248,22,
+74,23,195,2,249,22,73,248,22,74,23,196,2,27,248,22,75,23,197,1,28,
+248,22,81,23,194,2,9,28,248,23,203,2,248,22,74,23,195,2,249,22,73,
+248,22,74,23,196,2,249,2,94,23,206,1,248,22,75,23,198,1,249,2,94,
+23,204,1,248,22,75,23,196,1,27,248,22,75,23,195,1,28,248,22,81,23,
+194,2,9,28,248,23,201,2,248,22,74,23,195,2,249,22,73,248,22,74,23,
+196,2,249,2,94,23,204,1,248,22,75,23,198,1,249,2,94,23,202,1,248,
+22,75,23,196,1,27,248,22,75,23,195,1,28,248,22,81,23,194,2,9,28,
+248,23,198,2,248,22,74,23,195,2,249,22,73,248,22,74,23,196,2,27,248,
+22,75,23,197,1,28,248,22,81,23,194,2,9,28,248,23,201,2,248,22,74,
+23,195,2,249,22,73,248,22,74,23,196,2,249,2,94,23,204,1,248,22,75,
+23,198,1,249,2,94,23,202,1,248,22,75,23,196,1,27,248,22,75,23,195,
+1,28,248,22,81,23,194,2,9,28,248,23,199,2,248,22,74,23,195,2,249,
+22,73,248,22,74,23,196,2,249,2,94,23,202,1,248,22,75,23,198,1,249,
+2,94,23,200,1,248,22,75,23,196,1,27,248,22,75,23,196,1,28,248,22,
+81,23,194,2,9,28,248,23,195,2,248,22,74,23,195,2,249,22,73,248,22,
+74,23,196,2,27,248,22,75,23,197,1,28,248,22,81,23,194,2,9,28,248,
+23,198,2,248,22,74,23,195,2,249,22,73,248,22,74,23,196,2,27,248,22,
+75,23,197,1,28,248,22,81,23,194,2,9,28,248,23,201,2,248,22,74,23,
+195,2,249,22,73,248,22,74,23,196,2,249,2,94,23,204,1,248,22,75,23,
+198,1,249,2,94,23,202,1,248,22,75,23,196,1,27,248,22,75,23,195,1,
+28,248,22,81,23,194,2,9,28,248,23,199,2,248,22,74,23,195,2,249,22,
+73,248,22,74,23,196,2,249,2,94,23,202,1,248,22,75,23,198,1,249,2,
+94,23,200,1,248,22,75,23,196,1,27,248,22,75,23,195,1,28,248,22,81,
+23,194,2,9,28,248,23,196,2,248,22,74,23,195,2,249,22,73,248,22,74,
+23,196,2,27,248,22,75,23,197,1,28,248,22,81,23,194,2,9,28,248,23,
+199,2,248,22,74,23,195,2,249,22,73,248,22,74,23,196,2,249,2,94,23,
+202,1,248,22,75,23,198,1,249,2,94,23,200,1,248,22,75,23,196,1,27,
+248,22,75,23,195,1,28,248,22,81,23,194,2,9,28,248,23,197,2,248,22,
+74,23,195,2,249,22,73,248,22,74,23,196,2,249,2,94,23,200,1,248,22,
+75,23,198,1,249,2,94,197,248,22,75,195,28,248,22,81,23,200,2,86,95,
+23,199,1,23,198,1,28,23,200,2,199,86,94,23,200,1,27,28,248,22,81,
+23,197,2,6,0,0,249,22,1,22,153,7,248,2,92,23,199,2,248,23,199,
+1,252,22,178,7,6,44,44,126,97,58,32,99,111,108,108,101,99,116,105,111,
+110,32,110,111,116,32,102,111,117,110,100,58,32,126,115,32,105,110,32,97,110,
+121,32,111,102,58,32,126,115,126,97,23,203,1,28,248,22,81,23,203,1,28,
+248,22,148,14,23,202,2,248,22,152,14,23,202,1,23,201,1,250,22,153,7,
+28,248,22,148,14,23,205,2,248,22,152,14,23,205,1,23,204,1,6,1,1,
+47,23,202,2,28,248,22,81,23,201,2,9,28,248,22,148,14,248,22,74,23,
+202,2,249,22,73,248,22,74,23,203,2,27,248,22,75,23,204,2,28,248,22,
+81,23,194,2,9,28,248,22,148,14,248,22,74,23,195,2,249,22,73,248,22,
+74,23,196,2,27,248,22,75,23,197,1,28,248,22,81,23,194,2,9,28,248,
+22,148,14,248,22,74,23,195,2,249,22,73,248,22,74,23,196,2,249,2,94,
+22,148,14,248,22,75,23,198,1,249,2,94,22,148,14,248,22,75,23,196,1,
+27,248,22,75,23,195,1,28,248,22,81,23,194,2,9,28,248,22,148,14,248,
+22,74,23,195,2,249,22,73,248,22,74,23,196,2,249,2,94,22,148,14,248,
+22,75,23,198,1,249,2,94,22,148,14,248,22,75,23,196,1,27,248,22,75,
+23,202,2,28,248,22,81,23,194,2,9,28,248,22,148,14,248,22,74,23,195,
+2,249,22,73,248,22,74,23,196,2,27,248,22,75,23,197,1,28,248,22,81,
+23,194,2,9,28,248,22,148,14,248,22,74,23,195,2,249,22,73,248,22,74,
+23,196,2,249,2,94,22,148,14,248,22,75,23,198,1,249,2,94,22,148,14,
+248,22,75,23,196,1,27,248,22,75,23,195,1,28,248,22,81,23,194,2,9,
+28,248,22,148,14,248,22,74,23,195,2,249,22,73,248,22,74,23,196,2,249,
+2,94,22,148,14,248,22,75,23,198,1,249,2,94,22,148,14,248,22,75,23,
+196,1,28,249,22,5,22,127,23,202,2,250,22,178,7,6,21,21,32,111,114,
+58,32,126,115,32,105,110,32,97,110,121,32,111,102,58,32,126,115,23,202,1,
+249,22,2,22,128,2,28,248,22,81,23,206,2,86,94,23,205,1,9,28,248,
+22,127,248,22,74,23,207,2,249,22,73,248,22,74,23,208,2,27,248,22,75,
+23,209,1,28,248,22,81,23,194,2,9,28,248,22,127,248,22,74,23,195,2,
+249,22,73,248,22,74,23,196,2,27,248,22,75,23,197,1,28,248,22,81,23,
+194,2,9,28,248,22,127,248,22,74,23,195,2,249,22,73,248,22,74,23,196,
+2,249,2,94,22,127,248,22,75,23,198,1,249,2,94,22,127,248,22,75,23,
+196,1,27,248,22,75,23,195,1,28,248,22,81,23,194,2,9,28,248,22,127,
+248,22,74,23,195,2,249,22,73,248,22,74,23,196,2,249,2,94,22,127,248,
+22,75,23,198,1,249,2,94,22,127,248,22,75,23,196,1,27,248,22,75,23,
+207,1,28,248,22,81,23,194,2,9,28,248,22,127,248,22,74,23,195,2,249,
+22,73,248,22,74,23,196,2,27,248,22,75,23,197,1,28,248,22,81,23,194,
+2,9,28,248,22,127,248,22,74,23,195,2,249,22,73,248,22,74,23,196,2,
+249,2,94,22,127,248,22,75,23,198,1,249,2,94,22,127,248,22,75,23,196,
+1,27,248,22,75,23,195,1,28,248,22,81,23,194,2,9,28,248,22,127,248,
+22,74,23,195,2,249,22,73,248,22,74,23,196,2,249,2,94,22,127,248,22,
+75,23,198,1,249,2,94,22,127,248,22,75,23,196,1,86,94,23,199,1,6,
+0,0,27,248,22,74,23,201,2,27,28,248,22,148,14,23,195,2,249,22,166,
+14,23,196,1,23,198,2,248,22,128,2,23,195,1,28,28,248,22,148,14,248,
+22,74,23,203,2,248,22,161,14,23,194,2,10,27,250,22,1,22,166,14,23,
+197,1,23,201,2,28,28,248,22,81,23,199,2,10,248,22,161,14,23,194,2,
+28,23,201,2,28,28,248,22,160,14,249,22,166,14,195,203,10,27,28,248,22,
+148,14,202,248,22,152,14,202,201,27,248,22,133,7,23,195,2,27,28,249,22,
+188,3,23,196,2,40,28,249,22,136,7,6,4,4,46,114,107,116,249,22,152,
+7,23,199,2,249,22,176,3,23,200,2,40,249,22,153,7,250,22,152,7,23,
+200,1,36,249,22,176,3,23,201,1,40,6,3,3,46,115,115,86,95,23,195,
1,23,194,1,11,11,28,23,193,2,248,22,160,14,249,22,166,14,198,23,196,
-1,11,192,26,8,2,57,202,203,204,205,206,23,15,248,22,75,203,200,192,26,
-8,2,57,202,203,204,205,206,23,15,248,22,75,203,11,26,8,2,57,201,202,
-203,204,205,206,248,22,75,202,11,86,95,28,28,248,22,149,14,23,194,2,10,
-28,248,22,148,14,23,194,2,10,28,248,22,130,7,23,194,2,28,248,22,170,
-14,23,194,2,10,248,22,171,14,23,194,2,11,12,252,22,176,9,23,200,2,
-2,29,36,23,198,2,23,199,2,28,28,248,22,130,7,23,195,2,10,248,22,
-183,7,23,195,2,86,94,23,194,1,12,252,22,176,9,23,200,2,2,30,37,
-23,198,2,23,199,1,90,159,39,11,89,161,39,36,11,248,22,169,14,23,197,
-2,86,94,23,195,1,86,94,28,192,12,250,22,177,9,23,201,1,2,31,23,
-199,1,249,22,7,194,195,90,159,38,11,89,161,38,36,11,86,95,28,28,248,
-22,149,14,23,196,2,10,28,248,22,148,14,23,196,2,10,28,248,22,130,7,
-23,196,2,28,248,22,170,14,23,196,2,10,248,22,171,14,23,196,2,11,12,
-252,22,176,9,2,11,2,29,36,23,200,2,23,201,2,28,28,248,22,130,7,
-23,197,2,10,248,22,183,7,23,197,2,12,252,22,176,9,2,11,2,30,37,
-23,200,2,23,201,2,90,159,39,11,89,161,39,36,11,248,22,169,14,23,199,
-2,86,94,23,195,1,86,94,28,192,12,250,22,177,9,2,11,2,31,23,201,
-2,249,22,7,194,195,27,249,22,158,14,250,22,146,15,0,20,35,114,120,35,
-34,40,63,58,91,46,93,91,94,46,93,42,124,41,36,34,248,22,154,14,23,
-201,1,28,248,22,130,7,23,203,2,249,22,145,8,23,204,1,8,63,23,202,
+1,11,192,26,8,2,91,203,204,205,206,23,15,23,16,248,22,75,23,18,28,
+23,18,23,18,200,192,26,8,2,91,203,204,205,206,23,15,23,16,248,22,75,
+23,18,23,18,26,8,2,91,202,203,204,205,206,23,15,248,22,75,23,17,23,
+17,90,159,38,11,89,161,38,36,11,249,80,159,40,57,39,23,200,1,23,201,
+1,27,248,22,61,28,248,22,148,14,195,248,22,152,14,195,194,27,250,22,87,
+28,247,22,128,15,250,22,153,2,248,80,159,47,55,39,10,23,200,2,9,9,
+28,80,159,43,49,38,250,22,153,2,248,80,159,47,55,39,11,23,200,1,9,
+86,94,23,197,1,9,247,22,190,14,26,8,2,91,200,202,203,205,206,23,17,
+200,11,86,95,28,28,248,22,149,14,23,194,2,10,28,248,22,148,14,23,194,
+2,10,28,248,22,130,7,23,194,2,28,248,22,170,14,23,194,2,10,248,22,
+171,14,23,194,2,11,12,252,22,176,9,23,200,2,2,42,36,23,198,2,23,
+199,2,28,28,248,22,130,7,23,195,2,10,248,22,183,7,23,195,2,86,94,
+23,194,1,12,252,22,176,9,23,200,2,2,43,37,23,198,2,23,199,1,90,
+159,39,11,89,161,39,36,11,248,22,169,14,23,197,2,86,94,23,195,1,86,
+94,28,192,12,250,22,177,9,23,201,1,2,44,23,199,1,249,22,7,194,195,
+90,159,38,11,89,161,38,36,11,86,95,28,28,248,22,149,14,23,196,2,10,
+28,248,22,148,14,23,196,2,10,28,248,22,130,7,23,196,2,28,248,22,170,
+14,23,196,2,10,248,22,171,14,23,196,2,11,12,252,22,176,9,2,25,2,
+42,36,23,200,2,23,201,2,28,28,248,22,130,7,23,197,2,10,248,22,183,
+7,23,197,2,12,252,22,176,9,2,25,2,43,37,23,200,2,23,201,2,90,
+159,39,11,89,161,39,36,11,248,22,169,14,23,199,2,86,94,23,195,1,86,
+94,28,192,12,250,22,177,9,2,25,2,44,23,201,2,249,22,7,194,195,27,
+249,22,158,14,250,22,146,15,0,20,35,114,120,35,34,40,63,58,91,46,93,
+91,94,46,93,42,124,41,36,34,248,22,154,14,23,201,1,28,248,22,130,7,
+23,203,2,249,22,145,8,23,204,1,8,63,23,202,1,28,248,22,149,14,23,
+199,2,248,22,150,14,23,199,1,86,94,23,198,1,247,22,151,14,28,248,22,
+148,14,194,249,22,166,14,195,194,192,90,159,38,11,89,161,38,36,11,86,95,
+28,28,248,22,149,14,23,196,2,10,28,248,22,148,14,23,196,2,10,28,248,
+22,130,7,23,196,2,28,248,22,170,14,23,196,2,10,248,22,171,14,23,196,
+2,11,12,252,22,176,9,2,26,2,42,36,23,200,2,23,201,2,28,28,248,
+22,130,7,23,197,2,10,248,22,183,7,23,197,2,12,252,22,176,9,2,26,
+2,43,37,23,200,2,23,201,2,90,159,39,11,89,161,39,36,11,248,22,169,
+14,23,199,2,86,94,23,195,1,86,94,28,192,12,250,22,177,9,2,26,2,
+44,23,201,2,249,22,7,194,195,27,249,22,158,14,249,22,131,8,250,22,147,
+15,0,9,35,114,120,35,34,91,46,93,34,248,22,154,14,23,203,1,6,1,
+1,95,28,248,22,130,7,23,202,2,249,22,145,8,23,203,1,8,63,23,201,
1,28,248,22,149,14,23,199,2,248,22,150,14,23,199,1,86,94,23,198,1,
-247,22,151,14,28,248,22,148,14,194,249,22,166,14,195,194,192,90,159,38,11,
-89,161,38,36,11,86,95,28,28,248,22,149,14,23,196,2,10,28,248,22,148,
-14,23,196,2,10,28,248,22,130,7,23,196,2,28,248,22,170,14,23,196,2,
-10,248,22,171,14,23,196,2,11,12,252,22,176,9,2,12,2,29,36,23,200,
-2,23,201,2,28,28,248,22,130,7,23,197,2,10,248,22,183,7,23,197,2,
-12,252,22,176,9,2,12,2,30,37,23,200,2,23,201,2,90,159,39,11,89,
-161,39,36,11,248,22,169,14,23,199,2,86,94,23,195,1,86,94,28,192,12,
-250,22,177,9,2,12,2,31,23,201,2,249,22,7,194,195,27,249,22,158,14,
-249,22,131,8,250,22,147,15,0,9,35,114,120,35,34,91,46,93,34,248,22,
-154,14,23,203,1,6,1,1,95,28,248,22,130,7,23,202,2,249,22,145,8,
-23,203,1,8,63,23,201,1,28,248,22,149,14,23,199,2,248,22,150,14,23,
-199,1,86,94,23,198,1,247,22,151,14,28,248,22,148,14,194,249,22,166,14,
-195,194,192,249,247,22,158,5,194,11,27,247,22,128,15,249,80,158,39,49,28,
-23,195,2,27,248,22,150,8,2,32,28,192,192,2,33,2,34,27,28,23,196,
-1,250,22,166,14,248,22,188,14,2,35,247,22,148,8,2,36,11,27,248,80,
-159,42,54,39,250,22,87,9,248,22,83,248,22,188,14,2,37,9,28,193,249,
-22,73,195,194,192,27,247,22,128,15,249,80,158,39,49,28,23,195,2,27,248,
-22,150,8,2,32,28,192,192,2,33,2,34,27,28,23,196,1,250,22,166,14,
-248,22,188,14,2,35,247,22,148,8,2,36,11,27,248,80,159,42,55,39,250,
-22,87,23,203,1,248,22,83,248,22,188,14,2,37,9,28,193,249,22,73,195,
-194,192,27,247,22,128,15,249,80,158,39,49,28,23,195,2,27,248,22,150,8,
-2,32,28,192,192,2,33,2,34,27,28,23,196,1,250,22,166,14,248,22,188,
-14,2,35,247,22,148,8,2,36,11,27,27,250,22,87,23,203,1,248,22,83,
-248,22,188,14,2,37,23,204,1,28,248,22,81,23,194,2,9,27,248,22,74,
-23,195,2,27,28,248,22,172,14,23,195,2,23,194,1,28,248,22,171,14,23,
-195,2,249,22,173,14,23,196,1,250,80,158,49,50,248,22,188,14,2,21,11,
-10,250,80,158,47,50,248,22,188,14,2,21,23,197,1,10,28,23,193,2,249,
-22,73,248,22,175,14,249,22,173,14,23,198,1,247,22,189,14,248,80,159,47,
-56,39,248,22,75,23,199,1,86,94,23,193,1,248,80,159,45,56,39,248,22,
-75,23,197,1,28,193,249,22,73,195,194,192,32,67,88,163,8,36,39,57,11,
-2,20,222,33,69,0,8,35,114,120,35,34,92,34,34,27,249,22,135,15,23,
-197,2,23,198,2,28,23,193,2,86,94,23,196,1,27,248,22,98,23,195,2,
-27,27,248,22,107,23,197,1,27,249,22,135,15,23,201,2,23,196,2,28,23,
-193,2,86,94,23,194,1,27,248,22,98,23,195,2,27,250,2,67,23,203,2,
-23,204,1,248,22,107,23,199,1,28,249,22,191,7,23,196,2,2,38,249,22,
-87,23,202,2,194,249,22,73,248,22,157,14,28,249,22,140,9,247,22,152,8,
-2,22,250,22,147,15,2,68,23,200,1,2,39,23,197,1,194,86,95,23,199,
-1,23,193,1,28,249,22,191,7,23,196,2,2,38,249,22,87,23,200,2,9,
-249,22,73,248,22,157,14,28,249,22,140,9,247,22,152,8,2,22,250,22,147,
-15,2,68,23,200,1,2,39,23,197,1,9,28,249,22,191,7,23,196,2,2,
-38,249,22,87,197,194,86,94,23,196,1,249,22,73,248,22,157,14,28,249,22,
-140,9,247,22,152,8,2,22,250,22,147,15,2,68,23,200,1,2,39,23,197,
-1,194,86,94,23,193,1,28,249,22,191,7,23,198,2,2,38,249,22,87,195,
-9,86,94,23,194,1,249,22,73,248,22,157,14,28,249,22,140,9,247,22,152,
-8,2,22,250,22,147,15,2,68,23,202,1,2,39,23,199,1,9,86,95,28,
-28,248,22,183,7,194,10,248,22,130,7,194,12,250,22,176,9,2,15,6,21,
-21,98,121,116,101,32,115,116,114,105,110,103,32,111,114,32,115,116,114,105,110,
-103,196,28,28,248,22,82,195,249,22,4,22,148,14,196,11,12,250,22,176,9,
-2,15,6,13,13,108,105,115,116,32,111,102,32,112,97,116,104,115,197,250,2,
-67,197,195,28,248,22,130,7,197,248,22,144,8,197,196,32,71,88,163,8,36,
-39,53,11,70,102,111,117,110,100,45,101,120,101,99,222,33,74,32,72,88,163,
-8,36,40,58,11,64,110,101,120,116,222,33,73,27,248,22,174,14,23,196,2,
-28,249,22,142,9,23,195,2,23,197,1,11,28,248,22,170,14,23,194,2,27,
-249,22,166,14,23,197,1,23,196,1,28,23,197,2,90,159,39,11,89,161,39,
-36,11,248,22,169,14,23,197,2,86,95,23,195,1,23,194,1,27,28,23,202,
-2,27,248,22,174,14,23,199,2,28,249,22,142,9,23,195,2,23,200,2,11,
-28,248,22,170,14,23,194,2,250,2,71,23,205,2,23,206,2,249,22,166,14,
-23,200,2,23,198,1,250,2,71,23,205,2,23,206,2,23,196,1,11,28,23,
-193,2,192,86,94,23,193,1,27,28,248,22,148,14,23,196,2,27,249,22,166,
-14,23,198,2,23,205,2,28,28,248,22,161,14,193,10,248,22,160,14,193,192,
-11,11,28,23,193,2,192,86,94,23,193,1,28,23,203,2,11,27,248,22,174,
-14,23,200,2,28,249,22,142,9,23,195,2,23,201,1,11,28,248,22,170,14,
-23,194,2,250,2,71,23,206,1,23,207,1,249,22,166,14,23,201,1,23,198,
-1,250,2,71,205,206,195,192,86,94,23,194,1,28,23,196,2,90,159,39,11,
-89,161,39,36,11,248,22,169,14,23,197,2,86,95,23,195,1,23,194,1,27,
-28,23,201,2,27,248,22,174,14,23,199,2,28,249,22,142,9,23,195,2,23,
-200,2,11,28,248,22,170,14,23,194,2,250,2,71,23,204,2,23,205,2,249,
-22,166,14,23,200,2,23,198,1,250,2,71,23,204,2,23,205,2,23,196,1,
-11,28,23,193,2,192,86,94,23,193,1,27,28,248,22,148,14,23,196,2,27,
-249,22,166,14,23,198,2,23,204,2,28,28,248,22,161,14,193,10,248,22,160,
-14,193,192,11,11,28,23,193,2,192,86,94,23,193,1,28,23,202,2,11,27,
-248,22,174,14,23,200,2,28,249,22,142,9,23,195,2,23,201,1,11,28,248,
-22,170,14,23,194,2,250,2,71,23,205,1,23,206,1,249,22,166,14,23,201,
-1,23,198,1,250,2,71,204,205,195,192,28,23,193,2,90,159,39,11,89,161,
-39,36,11,248,22,169,14,23,199,2,86,95,23,195,1,23,194,1,27,28,23,
-198,2,251,2,72,23,198,2,23,203,2,23,201,2,23,202,2,11,28,23,193,
-2,192,86,94,23,193,1,27,28,248,22,148,14,195,27,249,22,166,14,197,200,
-28,28,248,22,161,14,193,10,248,22,160,14,193,192,11,11,28,192,192,28,198,
-11,251,2,72,198,203,201,202,194,32,75,88,163,8,36,40,58,11,2,20,222,
-33,76,28,248,22,81,23,197,2,11,27,248,22,173,14,248,22,74,23,199,2,
-27,249,22,166,14,23,196,1,23,197,2,28,248,22,160,14,23,194,2,250,2,
-71,198,199,195,86,94,23,193,1,27,248,22,75,23,200,1,28,248,22,81,23,
-194,2,11,27,248,22,173,14,248,22,74,23,196,2,27,249,22,166,14,23,196,
-1,23,200,2,28,248,22,160,14,23,194,2,250,2,71,201,202,195,86,94,23,
-193,1,27,248,22,75,23,197,1,28,248,22,81,23,194,2,11,27,248,22,173,
-14,248,22,74,195,27,249,22,166,14,23,196,1,202,28,248,22,160,14,193,250,
-2,71,204,205,195,251,2,75,204,205,206,248,22,75,199,86,95,28,28,248,22,
-148,14,23,195,2,10,28,248,22,130,7,23,195,2,28,248,22,170,14,23,195,
-2,10,248,22,171,14,23,195,2,11,12,250,22,176,9,2,16,6,25,25,112,
-97,116,104,32,111,114,32,115,116,114,105,110,103,32,40,115,97,110,115,32,110,
-117,108,41,23,197,2,28,28,23,195,2,28,28,248,22,148,14,23,196,2,10,
-28,248,22,130,7,23,196,2,28,248,22,170,14,23,196,2,10,248,22,171,14,
-23,196,2,11,248,22,170,14,23,196,2,11,10,12,250,22,176,9,2,16,6,
-29,29,35,102,32,111,114,32,114,101,108,97,116,105,118,101,32,112,97,116,104,
-32,111,114,32,115,116,114,105,110,103,23,198,2,28,28,248,22,170,14,23,195,
-2,90,159,39,11,89,161,39,36,11,248,22,169,14,23,198,2,249,22,140,9,
-194,68,114,101,108,97,116,105,118,101,11,27,248,22,150,8,6,4,4,80,65,
-84,72,27,28,23,194,2,27,249,80,159,41,49,38,23,197,1,9,28,249,22,
-140,9,247,22,152,8,2,22,249,22,73,248,22,157,14,5,1,46,194,192,86,
-94,23,194,1,9,28,248,22,81,23,194,2,11,27,248,22,173,14,248,22,74,
-23,196,2,27,249,22,166,14,23,196,1,23,200,2,28,248,22,160,14,23,194,
-2,250,2,71,201,202,195,86,94,23,193,1,27,248,22,75,23,197,1,28,248,
-22,81,23,194,2,11,27,248,22,173,14,248,22,74,23,196,2,27,249,22,166,
-14,23,196,1,23,203,2,28,248,22,160,14,23,194,2,250,2,71,204,205,195,
-86,94,23,193,1,27,248,22,75,23,197,1,28,248,22,81,23,194,2,11,27,
-248,22,173,14,248,22,74,195,27,249,22,166,14,23,196,1,205,28,248,22,160,
-14,193,250,2,71,23,15,23,16,195,251,2,75,23,15,23,16,23,17,248,22,
-75,199,27,248,22,173,14,23,196,1,28,248,22,160,14,193,250,2,71,198,199,
-195,11,250,80,159,39,50,39,196,197,11,250,80,159,39,50,39,196,11,11,86,
-94,249,22,183,6,247,22,154,5,195,248,22,145,6,249,22,128,4,36,249,22,
-176,3,197,198,27,28,23,197,2,86,95,23,196,1,23,195,1,23,197,1,86,
-94,23,197,1,27,248,22,188,14,2,21,27,250,80,159,42,50,39,23,197,1,
-11,11,27,248,22,131,4,23,199,1,27,28,23,194,2,23,194,1,86,94,23,
-194,1,36,27,248,22,131,4,23,202,1,27,28,23,194,2,23,194,1,86,94,
-23,194,1,36,249,22,185,5,23,199,1,20,20,95,88,163,8,36,36,48,11,
-9,224,4,2,33,80,23,195,1,23,197,1,27,248,22,170,5,23,195,1,248,
-80,159,39,57,39,193,159,36,20,112,159,36,16,1,11,16,0,20,26,142,2,
-1,2,1,29,11,11,11,11,11,10,43,80,158,36,36,20,112,159,40,16,18,
-2,2,2,3,2,4,2,5,2,6,2,7,2,8,2,9,2,10,2,11,2,
-12,2,13,2,14,2,15,2,16,2,17,30,2,19,1,20,112,97,114,97,109,
-101,116,101,114,105,122,97,116,105,111,110,45,107,101,121,5,30,2,19,1,23,
-101,120,116,101,110,100,45,112,97,114,97,109,101,116,101,114,105,122,97,116,105,
-111,110,3,16,0,16,0,36,16,0,36,16,4,2,6,2,5,2,3,2,10,
-40,11,11,39,36,11,11,16,12,2,9,2,7,2,17,2,8,2,16,2,14,
-2,13,2,4,2,12,2,15,2,11,2,2,16,12,11,11,11,11,11,11,11,
-11,11,11,11,11,16,12,2,9,2,7,2,17,2,8,2,16,2,14,2,13,
-2,4,2,12,2,15,2,11,2,2,48,48,37,11,11,16,0,16,0,16,0,
-36,36,11,11,11,16,0,16,0,16,0,36,36,16,0,16,20,20,15,16,2,
-88,163,8,36,37,51,8,240,0,0,35,0,2,20,223,0,33,40,80,159,36,
-57,39,20,15,16,2,88,163,8,36,37,56,8,240,0,64,16,0,2,20,223,
-0,33,41,80,159,36,56,39,20,15,16,2,88,163,8,36,37,51,8,240,0,
-64,8,0,2,20,223,0,33,42,80,159,36,55,39,20,15,16,2,88,163,8,
-36,37,51,8,240,0,64,4,0,2,20,223,0,33,43,80,159,36,54,39,20,
-15,16,2,32,0,88,163,36,37,45,11,2,2,222,33,44,80,159,36,36,37,
-20,15,16,2,249,22,132,7,7,92,7,92,80,159,36,37,37,20,15,16,2,
-88,163,36,37,54,38,2,4,223,0,33,45,80,159,36,38,37,20,15,16,2,
-32,0,88,163,8,36,38,50,11,2,5,222,33,46,80,159,36,39,37,20,15,
-16,2,32,0,88,163,8,36,39,51,11,2,6,222,33,48,80,159,36,40,37,
-20,15,16,2,32,0,88,163,8,45,38,54,11,2,7,222,33,52,80,159,36,
-41,37,20,15,16,2,32,0,88,163,45,39,53,11,2,9,222,33,56,80,159,
-36,43,37,20,15,16,2,32,0,88,163,36,41,59,11,2,8,222,33,59,80,
-159,36,42,37,20,15,16,2,32,0,88,163,36,39,50,11,2,10,222,33,60,
-80,159,36,44,37,20,15,16,2,32,0,88,163,36,38,53,11,2,11,222,33,
-61,80,159,36,45,37,20,15,16,2,32,0,88,163,36,38,54,11,2,12,222,
-33,62,80,159,36,46,37,20,15,16,2,32,0,88,163,36,37,44,11,2,13,
-222,33,63,80,159,36,47,37,20,15,16,2,20,25,96,2,14,88,163,36,36,
-53,8,240,0,32,4,0,9,223,0,33,64,88,163,36,37,54,8,240,0,32,
-8,0,9,223,0,33,65,88,163,36,38,58,8,240,0,96,16,0,9,223,0,
-33,66,80,159,36,48,37,20,15,16,2,27,248,22,131,15,248,22,144,8,27,
-28,249,22,140,9,247,22,152,8,2,22,6,1,1,59,6,1,1,58,250,22,
-178,7,6,14,14,40,91,94,126,97,93,42,41,126,97,40,46,42,41,23,196,
-2,23,196,1,88,163,8,36,38,48,11,2,15,223,0,33,70,80,159,36,49,
-37,20,15,16,2,20,25,96,2,16,88,163,8,36,39,8,24,8,128,128,9,
-223,0,33,77,88,163,8,36,38,47,8,240,0,64,0,0,9,223,0,33,78,
-88,163,8,36,37,46,8,240,0,64,0,0,9,223,0,33,79,80,159,36,50,
-37,20,15,16,2,88,163,8,36,39,54,8,240,0,64,32,0,2,17,223,0,
-33,81,80,159,36,51,37,94,29,94,2,18,68,35,37,107,101,114,110,101,108,
-11,29,94,2,18,69,35,37,109,105,110,45,115,116,120,11,9,9,9,36,0};
- EVAL_ONE_SIZED_STR((char *)expr, 8399);
+247,22,151,14,28,248,22,148,14,194,249,22,166,14,195,194,192,249,247,22,158,
+5,194,11,27,247,22,128,15,249,80,159,39,40,38,28,23,195,2,27,248,22,
+150,8,2,45,28,192,192,2,46,2,47,27,28,23,196,1,250,22,166,14,248,
+22,188,14,2,48,247,22,148,8,2,49,11,27,248,80,159,42,8,28,39,250,
+22,87,9,248,22,83,248,22,188,14,2,38,9,28,193,249,22,73,195,194,192,
+27,247,22,128,15,249,80,159,39,40,38,28,23,195,2,27,248,22,150,8,2,
+45,28,192,192,2,46,2,47,27,28,23,196,1,250,22,166,14,248,22,188,14,
+2,48,247,22,148,8,2,49,11,27,248,80,159,42,8,29,39,250,22,87,23,
+203,1,248,22,83,248,22,188,14,2,38,9,28,193,249,22,73,195,194,192,27,
+247,22,128,15,249,80,159,39,40,38,28,23,195,2,27,248,22,150,8,2,45,
+28,192,192,2,46,2,47,27,28,23,196,1,250,22,166,14,248,22,188,14,2,
+48,247,22,148,8,2,49,11,27,248,80,159,42,8,30,39,250,22,87,23,203,
+1,248,22,83,248,22,188,14,2,38,23,204,1,28,193,249,22,73,195,194,192,
+86,94,249,22,183,6,247,22,154,5,195,248,22,145,6,249,22,128,4,36,249,
+22,176,3,197,198,27,28,23,197,2,86,95,23,196,1,23,195,1,23,197,1,
+86,94,23,197,1,27,248,22,188,14,2,31,27,250,80,159,42,39,39,23,197,
+1,11,11,27,248,22,131,4,23,199,1,27,28,23,194,2,23,194,1,86,94,
+23,194,1,36,27,248,22,131,4,23,202,1,27,28,23,194,2,23,194,1,86,
+94,23,194,1,36,249,22,185,5,23,199,1,20,20,95,88,163,8,36,36,48,
+11,9,224,4,2,33,105,23,195,1,23,197,1,27,248,22,170,5,23,195,1,
+248,80,159,39,8,31,39,193,159,36,20,112,159,36,16,1,11,16,0,20,26,
+142,2,1,2,1,29,11,11,11,11,11,10,43,80,158,36,36,20,112,159,40,
+16,28,2,2,2,3,2,4,2,5,2,6,2,7,2,8,2,9,2,10,2,
+11,2,12,2,13,2,14,2,15,30,2,18,76,102,105,110,100,45,108,105,110,
+107,115,45,112,97,116,104,33,4,30,2,19,1,20,112,97,114,97,109,101,116,
+101,114,105,122,97,116,105,111,110,45,107,101,121,6,30,2,19,1,23,101,120,
+116,101,110,100,45,112,97,114,97,109,101,116,101,114,105,122,97,116,105,111,110,
+3,2,20,2,21,2,22,30,2,18,1,21,101,120,99,101,112,116,105,111,110,
+45,104,97,110,100,108,101,114,45,107,101,121,2,2,23,2,24,2,25,2,26,
+2,27,2,28,2,29,16,0,16,0,36,16,0,36,16,12,2,8,2,7,2,
+3,2,24,2,22,2,20,2,15,2,21,2,23,2,13,2,12,2,14,48,11,
+11,39,36,11,11,16,12,2,11,2,9,2,29,2,10,2,5,2,28,2,27,
+2,4,2,26,2,6,2,25,2,2,16,12,11,11,11,11,11,11,11,11,11,
+11,11,11,16,12,2,11,2,9,2,29,2,10,2,5,2,28,2,27,2,4,
+2,26,2,6,2,25,2,2,48,48,37,11,11,16,0,16,0,16,0,36,36,
+11,11,11,16,0,16,0,16,0,36,36,16,0,16,28,20,15,16,2,88,163,
+8,36,37,51,16,2,8,240,0,128,0,0,8,240,1,128,0,0,2,30,223,
+0,33,50,80,159,36,8,31,39,20,15,16,2,88,163,8,36,37,56,16,2,
+44,8,240,0,64,0,0,2,30,223,0,33,51,80,159,36,8,30,39,20,15,
+16,2,88,163,8,36,37,51,16,2,44,8,128,128,2,30,223,0,33,52,80,
+159,36,8,29,39,20,15,16,2,88,163,8,36,37,51,16,2,44,8,128,64,
+2,30,223,0,33,53,80,159,36,8,28,39,20,15,16,2,32,0,88,163,36,
+37,45,11,2,2,222,33,54,80,159,36,36,37,20,15,16,2,249,22,132,7,
+7,92,7,92,80,159,36,37,37,20,15,16,2,88,163,36,37,54,38,2,4,
+223,0,33,55,80,159,36,38,37,20,15,16,2,20,25,96,2,5,88,163,8,
+36,39,8,24,52,9,223,0,33,62,88,163,36,38,47,44,9,223,0,33,63,
+88,163,36,37,46,44,9,223,0,33,64,80,159,36,39,37,20,15,16,2,27,
+248,22,131,15,248,22,144,8,27,28,249,22,140,9,247,22,152,8,2,32,6,
+1,1,59,6,1,1,58,250,22,178,7,6,14,14,40,91,94,126,97,93,42,
+41,126,97,40,46,42,41,23,196,2,23,196,1,88,163,8,36,38,48,11,2,
+6,223,0,33,68,80,159,36,40,37,20,15,16,2,32,0,88,163,8,36,38,
+50,11,2,7,222,33,69,80,159,36,41,37,20,15,16,2,32,0,88,163,8,
+36,39,51,11,2,8,222,33,71,80,159,36,42,37,20,15,16,2,88,163,45,
+38,51,8,128,4,2,9,223,0,33,74,80,159,36,43,37,20,15,16,2,88,
+163,45,39,52,8,128,4,2,11,223,0,33,77,80,159,36,45,37,20,15,16,
+2,248,22,188,14,70,108,105,110,107,115,45,102,105,108,101,80,159,36,46,37,
+20,15,16,2,247,22,133,2,80,158,36,47,20,15,16,2,2,78,80,158,36,
+48,20,15,16,2,248,80,159,37,50,37,88,163,36,36,49,8,240,8,128,1,
+0,9,223,1,33,79,80,159,36,49,37,20,15,16,2,247,22,133,2,80,158,
+36,53,20,15,16,2,2,78,80,158,36,54,20,15,16,2,88,163,36,37,44,
+8,240,0,188,23,0,2,22,223,0,33,88,80,159,36,55,37,20,15,16,2,
+88,163,36,38,56,8,240,0,0,32,0,2,23,223,0,33,90,80,159,36,57,
+37,20,15,16,2,88,163,36,41,59,8,240,0,32,40,0,2,10,223,0,33,
+97,80,159,36,44,37,20,15,16,2,32,0,88,163,36,39,50,11,2,24,222,
+33,98,80,159,36,58,37,20,15,16,2,32,0,88,163,36,38,53,11,2,25,
+222,33,99,80,159,36,59,37,20,15,16,2,32,0,88,163,36,38,54,11,2,
+26,222,33,100,80,159,36,8,24,37,20,15,16,2,32,0,88,163,36,37,44,
+11,2,27,222,33,101,80,159,36,8,25,37,20,15,16,2,20,25,96,2,28,
+88,163,36,36,53,16,2,52,8,128,64,9,223,0,33,102,88,163,36,37,54,
+16,2,52,8,128,128,9,223,0,33,103,88,163,36,38,55,16,2,52,8,240,
+0,64,0,0,9,223,0,33,104,80,159,36,8,26,37,20,15,16,2,88,163,
+8,36,39,54,16,2,44,8,240,0,128,0,0,2,29,223,0,33,106,80,159,
+36,8,27,37,95,29,94,2,16,68,35,37,107,101,114,110,101,108,11,29,94,
+2,16,69,35,37,109,105,110,45,115,116,120,11,2,18,9,9,9,36,0};
+ EVAL_ONE_SIZED_STR((char *)expr, 10204);
}
{
- SHARED_OK static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,53,46,49,46,51,46,50,0,0,0,0,0,0,0,0,0,0,0,
+ SHARED_OK static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,53,46,49,46,51,46,53,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,12,0,0,0,1,0,0,15,0,40,0,57,
0,75,0,97,0,120,0,140,0,162,0,169,0,176,0,183,0,0,0,178,1,
0,0,74,35,37,112,108,97,99,101,45,115,116,114,117,99,116,1,23,115,116,
@@ -528,7 +614,7 @@
EVAL_ONE_SIZED_STR((char *)expr, 499);
}
{
- SHARED_OK static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,53,46,49,46,51,46,50,0,0,0,0,0,0,0,0,0,0,0,
+ SHARED_OK static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,53,46,49,46,51,46,53,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,65,0,0,0,1,0,0,7,0,18,0,45,
0,51,0,64,0,73,0,80,0,102,0,124,0,150,0,158,0,170,0,185,0,
201,0,219,0,239,0,251,0,11,1,34,1,46,1,77,1,84,1,89,1,94,
@@ -788,14 +874,14 @@
142,2,1,2,1,29,11,11,11,11,11,10,38,80,158,36,36,20,112,159,40,
16,26,2,2,2,3,30,2,5,72,112,97,116,104,45,115,116,114,105,110,103,
63,11,30,2,5,75,112,97,116,104,45,97,100,100,45,115,117,102,102,105,120,
-8,30,2,7,2,8,5,30,2,7,1,23,101,120,116,101,110,100,45,112,97,
+8,30,2,7,2,8,6,30,2,7,1,23,101,120,116,101,110,100,45,112,97,
114,97,109,101,116,101,114,105,122,97,116,105,111,110,3,2,9,2,10,2,11,
2,12,2,13,2,14,2,15,2,16,2,17,2,18,2,19,2,20,2,21,30,
-2,22,2,8,5,30,2,5,79,112,97,116,104,45,114,101,112,108,97,99,101,
+2,22,2,8,6,30,2,5,79,112,97,116,104,45,114,101,112,108,97,99,101,
45,115,117,102,102,105,120,10,30,2,5,73,102,105,110,100,45,99,111,108,45,
102,105,108,101,3,30,2,5,76,110,111,114,109,97,108,45,99,97,115,101,45,
112,97,116,104,7,2,23,2,24,30,2,22,74,114,101,112,97,114,97,109,101,
-116,101,114,105,122,101,6,16,0,16,0,36,16,0,36,16,14,2,15,2,16,
+116,101,114,105,122,101,7,16,0,16,0,36,16,0,36,16,14,2,15,2,16,
2,10,2,12,2,17,2,18,2,11,2,3,2,9,2,2,2,13,2,14,2,
19,2,21,50,11,11,39,36,11,11,16,3,2,23,2,20,2,24,16,3,11,
11,11,16,3,2,23,2,20,2,24,39,39,37,11,11,16,0,16,0,16,0,
@@ -829,7 +915,7 @@
EVAL_ONE_SIZED_STR((char *)expr, 6244);
}
{
- SHARED_OK static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,53,46,49,46,51,46,50,0,0,0,0,0,0,0,0,0,0,0,
+ SHARED_OK static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,53,46,49,46,51,46,53,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,11,0,0,0,1,0,0,10,0,16,0,29,
0,44,0,58,0,78,0,90,0,104,0,118,0,170,0,0,0,97,1,0,0,
69,35,37,98,117,105,108,116,105,110,65,113,117,111,116,101,29,94,2,2,67,
@@ -837,7 +923,7 @@
107,11,29,94,2,2,68,35,37,112,97,114,97,109,122,11,29,94,2,2,74,
35,37,112,108,97,99,101,45,115,116,114,117,99,116,11,29,94,2,2,66,35,
37,98,111,111,116,11,29,94,2,2,68,35,37,101,120,112,111,98,115,11,29,
-94,2,2,68,35,37,107,101,114,110,101,108,11,97,36,11,8,240,204,77,0,
+94,2,2,68,35,37,107,101,114,110,101,108,11,97,36,11,8,240,28,78,0,
0,100,159,2,3,36,36,159,2,4,36,36,159,2,5,36,36,159,2,6,36,
36,159,2,7,36,36,159,2,8,36,36,159,2,9,36,36,159,2,9,36,36,
16,0,159,36,20,112,159,36,16,1,11,16,0,20,26,142,2,1,2,1,29,
diff --git a/src/racket/src/file.c b/src/racket/src/file.c
index 1d5aab7208..c3ce91d3ae 100644
--- a/src/racket/src/file.c
+++ b/src/racket/src/file.c
@@ -227,12 +227,15 @@ READ_ONLY static Scheme_Object *doc_dir_symbol, *desk_dir_symbol;
READ_ONLY static Scheme_Object *init_dir_symbol, *init_file_symbol, *sys_dir_symbol;
READ_ONLY static Scheme_Object *exec_file_symbol, *run_file_symbol, *collects_dir_symbol;
READ_ONLY static Scheme_Object *pref_file_symbol, *orig_dir_symbol, *addon_dir_symbol;
+READ_ONLY static Scheme_Object *links_file_symbol;
SHARED_OK static Scheme_Object *exec_cmd;
SHARED_OK static Scheme_Object *run_cmd;
SHARED_OK static Scheme_Object *collects_path;
THREAD_LOCAL_DECL(static Scheme_Object *original_pwd);
SHARED_OK static Scheme_Object *addon_dir;
+SHARED_OK static Scheme_Object *links_file;
+THREAD_LOCAL_DECL(static Scheme_Object *inst_links_path);
#endif
READ_ONLY static Scheme_Object *windows_symbol, *unix_symbol;
@@ -275,6 +278,7 @@ void scheme_init_file(Scheme_Env *env)
REGISTER_SO(collects_dir_symbol);
REGISTER_SO(orig_dir_symbol);
REGISTER_SO(addon_dir_symbol);
+ REGISTER_SO(links_file_symbol);
#endif
REGISTER_SO(windows_symbol);
REGISTER_SO(unix_symbol);
@@ -302,6 +306,7 @@ void scheme_init_file(Scheme_Env *env)
collects_dir_symbol = scheme_intern_symbol("collects-dir");
orig_dir_symbol = scheme_intern_symbol("orig-dir");
addon_dir_symbol = scheme_intern_symbol("addon-dir");
+ links_file_symbol = scheme_intern_symbol("links-file");
#endif
windows_symbol = scheme_intern_symbol("windows");
@@ -5826,7 +5831,8 @@ enum {
id_init_dir,
id_init_file,
id_sys_dir,
- id_addon_dir
+ id_addon_dir,
+ id_links_file
};
Scheme_Object *scheme_get_run_cmd(void)
@@ -5877,6 +5883,15 @@ find_system_path(int argc, Scheme_Object **argv)
} else if (argv[0] == addon_dir_symbol) {
if (addon_dir) return addon_dir;
which = id_addon_dir;
+ } else if (argv[0] == links_file_symbol) {
+ if (links_file) return links_file;
+ if (addon_dir) {
+ Scheme_Object *pa[2];
+ pa[0] = addon_dir;
+ pa[1] = scheme_make_path("links.rktd");
+ return scheme_build_path(2, pa);
+ }
+ which = id_links_file;
} else {
scheme_wrong_type("find-system-path", "system-path-symbol",
0, argc, argv);
@@ -5919,9 +5934,11 @@ find_system_path(int argc, Scheme_Object **argv)
if ((which == id_pref_dir)
|| (which == id_pref_file)
- || (which == id_addon_dir)) {
+ || (which == id_addon_dir)
+ || (which == id_links_file)) {
#if defined(OS_X) && !defined(XONX)
- if (which == id_addon_dir)
+ if ((which == id_addon_dir)
+ || (which == id_links_file))
home_str = "~/Library/Racket/";
else
home_str = "~/Library/Preferences/";
@@ -5968,6 +5985,8 @@ find_system_path(int argc, Scheme_Object **argv)
return append_path(home, scheme_make_path("/racket-prefs.rktd" + ends_in_slash));
#endif
}
+ if (which == id_links_file)
+ return append_path(home, scheme_make_path("/links.rktd" + ends_in_slash));
}
#endif
@@ -6005,7 +6024,8 @@ find_system_path(int argc, Scheme_Object **argv)
if ((which == id_addon_dir)
|| (which == id_pref_dir)
- || (which == id_pref_file))
+ || (which == id_pref_file)
+ || (which == id_links_file))
which_folder = CSIDL_APPDATA;
else if (which == id_doc_dir) {
# ifndef CSIDL_PERSONAL
@@ -6109,6 +6129,8 @@ find_system_path(int argc, Scheme_Object **argv)
return append_path(home, scheme_make_path("\\racketrc.rktl" + ends_in_slash));
if (which == id_pref_file)
return append_path(home, scheme_make_path("\\racket-prefs.rktd" + ends_in_slash));
+ if (which == id_links_file)
+ return append_path(home, scheme_make_path("\\links.rktd" + ends_in_slash));
return home;
}
#endif
@@ -6177,6 +6199,26 @@ void scheme_set_addon_dir(Scheme_Object *p)
addon_dir = p;
}
+/* should only called from main */
+void scheme_set_links_file(Scheme_Object *p)
+{
+ if (!links_file) {
+ REGISTER_SO(links_file);
+ }
+ links_file = p;
+}
+
+Scheme_Object *scheme_find_links_path(int argc, Scheme_Object *argv[])
+{
+ if (inst_links_path)
+ return inst_links_path;
+
+ REGISTER_SO(inst_links_path);
+ inst_links_path = scheme_apply(argv[0], 0, NULL);
+
+ return inst_links_path;
+}
+
/********************************************************************************/
#ifdef DOS_FILE_SYSTEM
diff --git a/src/racket/src/schpriv.h b/src/racket/src/schpriv.h
index b6bd7b94fd..5f8ab1d2ae 100644
--- a/src/racket/src/schpriv.h
+++ b/src/racket/src/schpriv.h
@@ -3358,6 +3358,8 @@ Scheme_Object *scheme_get_fd_identity(Scheme_Object *port, intptr_t fd, char *pa
Scheme_Object *scheme_extract_relative_to(Scheme_Object *obj, Scheme_Object *dir);
+Scheme_Object *scheme_find_links_path(int argc, Scheme_Object *argv[]);
+
#ifdef DOS_FILE_SYSTEM
# define WIDE_PATH(s) scheme_convert_to_wchar(s, 0)
# define WIDE_PATH_COPY(s) scheme_convert_to_wchar(s, 1)
diff --git a/src/racket/src/schvers.h b/src/racket/src/schvers.h
index 6c0e045afb..7640e37ea3 100644
--- a/src/racket/src/schvers.h
+++ b/src/racket/src/schvers.h
@@ -13,12 +13,12 @@
consistently.)
*/
-#define MZSCHEME_VERSION "5.1.3.3"
+#define MZSCHEME_VERSION "5.1.3.5"
#define MZSCHEME_VERSION_X 5
#define MZSCHEME_VERSION_Y 1
#define MZSCHEME_VERSION_Z 3
-#define MZSCHEME_VERSION_W 3
+#define MZSCHEME_VERSION_W 5
#define MZSCHEME_VERSION_MAJOR ((MZSCHEME_VERSION_X * 100) + MZSCHEME_VERSION_Y)
#define MZSCHEME_VERSION_MINOR ((MZSCHEME_VERSION_Z * 1000) + MZSCHEME_VERSION_W)
diff --git a/src/racket/src/startup.inc b/src/racket/src/startup.inc
index b9c500d4ab..ef9b325a41 100644
--- a/src/racket/src/startup.inc
+++ b/src/racket/src/startup.inc
@@ -133,7 +133,7 @@
);
EVAL_ONE_STR(
"(module #%utils '#%kernel"
-"(#%require '#%min-stx)"
+"(#%require '#%min-stx '#%paramz)"
"(#%provide path-string?"
" normal-case-path"
" path-replace-suffix"
@@ -178,6 +178,83 @@
" 'windows)))))"
"((string? s)(string->path s))"
"(else s))))"
+"(define-values(find-executable-path)"
+"(case-lambda "
+"((program libpath reverse?)"
+"(unless(path-string? program) "
+" (raise-type-error 'find-executable-path \"path or string (sans nul)\" program))"
+"(unless(or(not libpath)(and(path-string? libpath) "
+"(relative-path? libpath)))"
+" (raise-type-error 'find-executable-path \"#f or relative path or string\" libpath))"
+"(letrec((found-exec"
+"(lambda(exec-name)"
+"(if libpath"
+"(let-values(((base name isdir?)(split-path exec-name)))"
+"(let((next"
+"(lambda()"
+"(let((resolved(resolve-path exec-name)))"
+"(cond"
+"((equal? resolved exec-name) #f)"
+"((relative-path? resolved)"
+"(found-exec(build-path base resolved)))"
+"(else(found-exec resolved)))))))"
+"(or(and reverse?(next))"
+"(if(path? base)"
+"(let((lib(build-path base libpath)))"
+"(and(or(directory-exists? lib) "
+"(file-exists? lib))"
+" lib))"
+" #f)"
+"(and(not reverse?)(next)))))"
+" exec-name))))"
+"(if(and(relative-path? program)"
+"(let-values(((base name dir?)(split-path program)))"
+"(eq? base 'relative)))"
+" (let ((paths-str (getenv \"PATH\"))"
+"(win-add(lambda(s)(if(eq?(system-type) 'windows) "
+" (cons (bytes->path #\".\") s) "
+" s))))"
+"(let loop((paths(if paths-str "
+"(win-add(path-list-string->path-list paths-str null))"
+" null)))"
+"(if(null? paths)"
+" #f"
+"(let*((base(path->complete-path(car paths)))"
+"(name(build-path base program)))"
+"(if(file-exists? name)"
+"(found-exec name)"
+"(loop(cdr paths)))))))"
+"(let((p(path->complete-path program)))"
+"(and(file-exists? p)(found-exec p))))))"
+"((program libpath)(find-executable-path program libpath #f))"
+"((program)(find-executable-path program #f #f))))"
+"(define-values(path-list-string->path-list)"
+"(let((r(byte-regexp(string->bytes/utf-8"
+"(let((sep(if(eq?(system-type) 'windows)"
+" \";\"\n"
+" \":\")))"
+" (format \"([^~a]*)~a(.*)\" sep sep)))))"
+"(cons-path(lambda(default s l) "
+" (if (bytes=? s #\"\")"
+"(append default l)"
+"(cons(bytes->path(if(eq?(system-type) 'windows)"
+" (regexp-replace* #rx#\"\\\"\" s #\"\")"
+" s))"
+" l)))))"
+"(lambda(s default)"
+"(unless(or(bytes? s)"
+"(string? s))"
+" (raise-type-error 'path-list-string->path-list \"byte string or string\" s))"
+"(unless(and(list? default)"
+"(andmap path? default))"
+" (raise-type-error 'path-list-string->path-list \"list of paths\" default))"
+"(let loop((s(if(string? s)"
+"(string->bytes/utf-8 s)"
+" s)))"
+"(let((m(regexp-match r s)))"
+"(if m"
+"(cons-path default(cadr m)(loop(caddr m)))"
+"(cons-path default s null)))))))"
"(define-values(-check-relpath)"
"(lambda(who s)"
"(unless(path-string? s)"
@@ -210,23 +287,196 @@
" collection collection-path"
" file-name)"
" file-name)))"
+"(define-values(user-links-path)(find-system-path 'links-file))"
+"(define-values(user-links-cache)(make-hasheq))"
+"(define-values(user-links-timestamp) -inf.0)"
+"(define-values(links-path)(find-links-path!"
+"(lambda()"
+"(let((d(let((c(find-system-path 'collects-dir)))"
+"(if(absolute-path? c)"
+" c"
+"(parameterize((current-directory(find-system-path 'orig-dir)))"
+"(find-executable-path(find-system-path 'exec-file) c))))))"
+"(and d"
+" (build-path d \"config\" \"links.rktd\"))))))"
+"(define-values(links-cache)(make-hasheq))"
+"(define-values(links-timestamp) -inf.0)"
+"(define-values(get-linked-collections)"
+"(lambda(user?)"
+"(call/ec(lambda(esc)"
+"(define-values(make-handler)"
+"(lambda(ts)"
+"(lambda(exn)"
+"(let((l(current-logger)))"
+"(when(log-level? l 'error)"
+"(log-message l 'error "
+"(format"
+" \"error reading linked collections: ~a\""
+"(exn-message exn))"
+"(current-continuation-marks))))"
+"(when ts"
+"(if user?"
+"(begin"
+"(set! user-links-cache(make-hasheq))"
+"(set! user-links-timestamp ts))"
+"(begin"
+"(set! links-cache(make-hasheq))"
+"(set! links-timestamp ts))))"
+"(esc(make-hasheq)))))"
+"(with-continuation-mark"
+" exception-handler-key"
+"(make-handler #f)"
+"(let((ts(file-or-directory-modify-seconds(if user?"
+" user-links-path"
+" links-path)"
+" #f "
+"(lambda() -inf.0))))"
+"(if(ts . > .(if user? user-links-timestamp links-timestamp))"
+"(with-continuation-mark"
+" exception-handler-key"
+"(make-handler ts)"
+"(parameterize((read-case-sensitive #t)"
+"(read-square-bracket-as-paren #t)"
+"(read-curly-brace-as-paren #t)"
+"(read-accept-box #t)"
+"(read-accept-compiled #t)"
+"(read-accept-bar-quote #t)"
+"(read-accept-graph #t)"
+"(read-decimal-as-inexact #t)"
+"(read-accept-dot #t)"
+"(read-accept-infix-dot #t)"
+"(read-accept-quasiquote #t)"
+"(read-accept-reader #t)"
+"(read-accept-lang #f)"
+"(current-readtable #f))"
+"(let((v(let((p(open-input-file(if user? user-links-path links-path)"
+" 'binary)))"
+"(dynamic-wind"
+" void"
+"(lambda() "
+"(begin0"
+"(read p)"
+"(unless(eof-object?(read p))"
+" (error \"expected a single S-expression\"))))"
+"(lambda()(close-input-port p))))))"
+"(unless(and(list? v)"
+"(andmap(lambda(p)"
+"(and(list? p)"
+"(or(= 2(length p))"
+"(= 3(length p)))"
+"(string?(car p))"
+"(path-string?(cadr p))"
+"(or(null?(cddr p))"
+"(regexp?(caddr p)))))"
+" v))"
+" (error \"ill-formed content\"))"
+"(let((ht(make-hasheq))"
+"(dir(let-values(((base name dir?)(split-path(if user?"
+" user-links-path"
+" links-path))))"
+" base)))"
+"(for-each"
+"(lambda(p)"
+"(when(or(null?(cddr p))"
+"(regexp-match?(caddr p)(version)))"
+"(let((s(string->symbol(car p))))"
+"(hash-set! ht s(cons(box(path->complete-path(cadr p) dir))"
+"(hash-ref ht s null))))))"
+" v)"
+"(if user?"
+"(begin"
+"(set! user-links-cache ht)"
+"(set! user-links-timestamp ts))"
+"(begin"
+"(set! links-cache ht)"
+"(set! links-timestamp ts)))"
+" ht))))"
+"(if user?"
+" user-links-cache"
+" links-cache))))))))"
+"(define-values(normalize-collection-reference)"
+"(lambda(collection collection-path)"
+"(cond"
+"((string? collection)"
+" (let ((m (regexp-match-positions #rx\"/+\" collection)))"
+"(if m"
+"(cond"
+"((=(caar m)(sub1(string-length collection)))"
+"(values(substring collection 0(caar m)) collection-path))"
+"(else"
+"(values(substring collection 0(caar m))"
+"(cons(substring collection(cdar m))"
+" collection-path))))"
+"(values collection collection-path))))"
+"(else"
+"(let-values(((base name dir?)(split-path collection)))"
+"(if(eq? base 'relative)"
+"(values name collection-path)"
+"(normalize-collection-reference base(cons name collection-path))))))))"
"(define-values(find-col-file)"
"(lambda(who fail collection collection-path file-name)"
-"(let((all-paths(current-library-collection-paths)))"
+"(let-values(((collection collection-path)"
+"(normalize-collection-reference collection collection-path)))"
+"(let((all-paths(let((sym(string->symbol(if(path? collection)"
+"(path->string collection)"
+" collection))))"
+"(append"
+"(if(use-user-specific-search-paths)"
+"(hash-ref(get-linked-collections #t) sym null)"
+" null)"
+"(if links-path"
+"(hash-ref(get-linked-collections #f) sym null)"
+" null)"
+"(current-library-collection-paths)))))"
+"(define-values(*build-path-rep)"
+"(lambda(p c)"
+"(if(path? p)"
+"(build-path p c)"
+"(unbox p))))"
+"(define-values(*directory-exists?)"
+"(lambda(orig p)"
+"(if(path? orig)"
+"(directory-exists? p)"
+" #t)))"
+"(define-values(to-string)(lambda(p)(if(path? p)(path->string p) p)))"
"(let cloop((paths all-paths)(found-col #f))"
"(if(null? paths)"
"(if found-col"
" found-col"
+"(let((rest-coll"
+"(if(null? collection-path)"
+" \"\""
+"(apply"
+" string-append"
+"(let loop((cp collection-path))"
+"(if(null?(cdr cp))"
+"(list(to-string(car cp)))"
+" (list* (to-string (car cp)) \"/\" (loop (cdr cp)))))))))"
+"(define-values(filter)"
+"(lambda(f l)"
+"(if(null? l)"
+" null"
+"(if(f(car l))"
+"(cons(car l)(filter f(cdr l)))"
+"(filter f(cdr l))))))"
"(fail"
-" (format \"~a: collection not found: ~s in any of: ~s\" "
-" who(if(null? collection-path)"
-" collection"
-"(apply build-path collection collection-path))"
-" all-paths)))"
-"(let((dir(build-path(car paths) collection)))"
-"(if(directory-exists? dir)"
+" (format \"~a: collection not found: ~s in any of: ~s~a\" "
+" who"
+"(if(null? collection-path)"
+"(to-string collection)"
+" (string-append (to-string collection) \"/\" rest-coll))"
+"(filter path? all-paths)"
+"(if(ormap box? all-paths)"
+" (format \" or: ~s in any of: ~s\" "
+" rest-coll "
+"(map unbox(filter box? all-paths)))"
+" \"\")))))"
+"(let((dir(*build-path-rep(car paths) collection)))"
+"(if(*directory-exists?(car paths) dir)"
"(let((cpath(apply build-path dir collection-path)))"
-"(if(directory-exists? cpath)"
+"(if(if(null? collection-path)"
+" #t"
+"(directory-exists? cpath))"
"(if file-name"
"(if(or(file-exists?(build-path cpath file-name))"
"(let((alt-file-name"
@@ -243,7 +493,7 @@
"(cloop(cdr paths)(or found-col cpath)))"
" cpath)"
"(cloop(cdr paths) found-col)))"
-"(cloop(cdr paths) found-col))))))))"
+"(cloop(cdr paths) found-col)))))))))"
"(define-values(check-suffix-call)"
"(lambda(s sfx who)"
"(unless(or(path-for-some-system? s)"
@@ -324,83 +574,6 @@
"(cons(simplify-path(path->complete-path v(current-directory)))"
"(loop(cdr l)))"
"(loop(cdr l))))))))))))"
-"(define-values(path-list-string->path-list)"
-"(let((r(byte-regexp(string->bytes/utf-8"
-"(let((sep(if(eq?(system-type) 'windows)"
-" \";\"\n"
-" \":\")))"
-" (format \"([^~a]*)~a(.*)\" sep sep)))))"
-"(cons-path(lambda(default s l) "
-" (if (bytes=? s #\"\")"
-"(append default l)"
-"(cons(bytes->path(if(eq?(system-type) 'windows)"
-" (regexp-replace* #rx#\"\\\"\" s #\"\")"
-" s))"
-" l)))))"
-"(lambda(s default)"
-"(unless(or(bytes? s)"
-"(string? s))"
-" (raise-type-error 'path-list-string->path-list \"byte string or string\" s))"
-"(unless(and(list? default)"
-"(andmap path? default))"
-" (raise-type-error 'path-list-string->path-list \"list of paths\" default))"
-"(let loop((s(if(string? s)"
-"(string->bytes/utf-8 s)"
-" s)))"
-"(let((m(regexp-match r s)))"
-"(if m"
-"(cons-path default(cadr m)(loop(caddr m)))"
-"(cons-path default s null)))))))"
-"(define-values(find-executable-path)"
-"(case-lambda "
-"((program libpath reverse?)"
-"(unless(path-string? program) "
-" (raise-type-error 'find-executable-path \"path or string (sans nul)\" program))"
-"(unless(or(not libpath)(and(path-string? libpath) "
-"(relative-path? libpath)))"
-" (raise-type-error 'find-executable-path \"#f or relative path or string\" libpath))"
-"(letrec((found-exec"
-"(lambda(exec-name)"
-"(if libpath"
-"(let-values(((base name isdir?)(split-path exec-name)))"
-"(let((next"
-"(lambda()"
-"(let((resolved(resolve-path exec-name)))"
-"(cond"
-"((equal? resolved exec-name) #f)"
-"((relative-path? resolved)"
-"(found-exec(build-path base resolved)))"
-"(else(found-exec resolved)))))))"
-"(or(and reverse?(next))"
-"(if(path? base)"
-"(let((lib(build-path base libpath)))"
-"(and(or(directory-exists? lib) "
-"(file-exists? lib))"
-" lib))"
-" #f)"
-"(and(not reverse?)(next)))))"
-" exec-name))))"
-"(if(and(relative-path? program)"
-"(let-values(((base name dir?)(split-path program)))"
-"(eq? base 'relative)))"
-" (let ((paths-str (getenv \"PATH\"))"
-"(win-add(lambda(s)(if(eq?(system-type) 'windows) "
-" (cons (bytes->path #\".\") s) "
-" s))))"
-"(let loop((paths(if paths-str "
-"(win-add(path-list-string->path-list paths-str null))"
-" null)))"
-"(if(null? paths)"
-" #f"
-"(let*((base(path->complete-path(car paths)))"
-"(name(build-path base program)))"
-"(if(file-exists? name)"
-"(found-exec name)"
-"(loop(cdr paths)))))))"
-"(let((p(path->complete-path program)))"
-"(and(file-exists? p)(found-exec p))))))"
-"((program libpath)(find-executable-path program libpath #f))"
-"((program)(find-executable-path program #f #f))))"
"(define(embedded-load start end str)"
"(let*((s(if str"
" str"
diff --git a/src/racket/src/startup.rktl b/src/racket/src/startup.rktl
index e347a6af7a..60796ff4b3 100644
--- a/src/racket/src/startup.rktl
+++ b/src/racket/src/startup.rktl
@@ -179,7 +179,7 @@
;; (along with much of '#%kernel)
(module #%utils '#%kernel
- (#%require '#%min-stx)
+ (#%require '#%min-stx '#%paramz)
(#%provide path-string?
normal-case-path
@@ -230,6 +230,87 @@
[(string? s) (string->path s)]
[else s])))
+ ;; ------------------------------ executable path ------------------------------
+
+ (define-values (find-executable-path)
+ (case-lambda
+ [(program libpath reverse?)
+ (unless (path-string? program)
+ (raise-type-error 'find-executable-path "path or string (sans nul)" program))
+ (unless (or (not libpath) (and (path-string? libpath)
+ (relative-path? libpath)))
+ (raise-type-error 'find-executable-path "#f or relative path or string" libpath))
+ (letrec ([found-exec
+ (lambda (exec-name)
+ (if libpath
+ (let-values ([(base name isdir?) (split-path exec-name)])
+ (let ([next
+ (lambda ()
+ (let ([resolved (resolve-path exec-name)])
+ (cond
+ [(equal? resolved exec-name) #f]
+ [(relative-path? resolved)
+ (found-exec (build-path base resolved))]
+ [else (found-exec resolved)])))])
+ (or (and reverse? (next))
+ (if (path? base)
+ (let ([lib (build-path base libpath)])
+ (and (or (directory-exists? lib)
+ (file-exists? lib))
+ lib))
+ #f)
+ (and (not reverse?) (next)))))
+ exec-name))])
+ (if (and (relative-path? program)
+ (let-values ([(base name dir?) (split-path program)])
+ (eq? base 'relative)))
+ (let ([paths-str (getenv "PATH")]
+ [win-add (lambda (s) (if (eq? (system-type) 'windows)
+ (cons (bytes->path #".") s)
+ s))])
+ (let loop ([paths (if paths-str
+ (win-add (path-list-string->path-list paths-str null))
+ null)])
+ (if (null? paths)
+ #f
+ (let* ([base (path->complete-path (car paths))]
+ [name (build-path base program)])
+ (if (file-exists? name)
+ (found-exec name)
+ (loop (cdr paths)))))))
+ (let ([p (path->complete-path program)])
+ (and (file-exists? p) (found-exec p)))))]
+ [(program libpath) (find-executable-path program libpath #f)]
+ [(program) (find-executable-path program #f #f)]))
+
+ (define-values (path-list-string->path-list)
+ (let ((r (byte-regexp (string->bytes/utf-8
+ (let ((sep (if (eq? (system-type) 'windows)
+ ";"
+ ":")))
+ (format "([^~a]*)~a(.*)" sep sep)))))
+ (cons-path (lambda (default s l)
+ (if (bytes=? s #"")
+ (append default l)
+ (cons (bytes->path (if (eq? (system-type) 'windows)
+ (regexp-replace* #rx#"\"" s #"")
+ s))
+ l)))))
+ (lambda (s default)
+ (unless (or (bytes? s)
+ (string? s))
+ (raise-type-error 'path-list-string->path-list "byte string or string" s))
+ (unless (and (list? default)
+ (andmap path? default))
+ (raise-type-error 'path-list-string->path-list "list of paths" default))
+ (let loop ([s (if (string? s)
+ (string->bytes/utf-8 s)
+ s)])
+ (let ([m (regexp-match r s)])
+ (if m
+ (cons-path default (cadr m) (loop (caddr m)))
+ (cons-path default s null)))))))
+
;; ------------------------------ Collections ------------------------------
(define-values (-check-relpath)
@@ -268,45 +349,232 @@
file-name)
file-name)))
+ (define-values (user-links-path) (find-system-path 'links-file))
+ (define-values (user-links-cache) (make-hasheq))
+ (define-values (user-links-timestamp) -inf.0)
+
+ (define-values (links-path) (find-links-path!
+ ;; This thunk is called once per place, and the result
+ ;; is remembered for later invocations. Otherwise, the
+ ;; search for the config file can trip over filesystem
+ ;; restrictions imposed by security guards.
+ (lambda ()
+ (let ([d (let ([c (find-system-path 'collects-dir)])
+ (if (absolute-path? c)
+ c
+ (parameterize ([current-directory (find-system-path 'orig-dir)])
+ (find-executable-path (find-system-path 'exec-file) c))))])
+ (and d
+ (build-path d "config" "links.rktd"))))))
+ (define-values (links-cache) (make-hasheq))
+ (define-values (links-timestamp) -inf.0)
+
+ (define-values (get-linked-collections)
+ (lambda (user?)
+ (call/ec (lambda (esc)
+ (define-values (make-handler)
+ (lambda (ts)
+ (lambda (exn)
+ (let ([l (current-logger)])
+ (when (log-level? l 'error)
+ (log-message l 'error
+ (format
+ "error reading linked collections: ~a"
+ (exn-message exn))
+ (current-continuation-marks))))
+ (when ts
+ (if user?
+ (begin
+ (set! user-links-cache (make-hasheq))
+ (set! user-links-timestamp ts))
+ (begin
+ (set! links-cache (make-hasheq))
+ (set! links-timestamp ts))))
+ (esc (make-hasheq)))))
+ (with-continuation-mark
+ exception-handler-key
+ (make-handler #f)
+ (let ([ts (file-or-directory-modify-seconds (if user?
+ user-links-path
+ links-path)
+ #f
+ (lambda () -inf.0))])
+ (if (ts . > . (if user? user-links-timestamp links-timestamp))
+ (with-continuation-mark
+ exception-handler-key
+ (make-handler ts)
+ (parameterize ([read-case-sensitive #t]
+ [read-square-bracket-as-paren #t]
+ [read-curly-brace-as-paren #t]
+ [read-accept-box #t]
+ [read-accept-compiled #t]
+ [read-accept-bar-quote #t]
+ [read-accept-graph #t]
+ [read-decimal-as-inexact #t]
+ [read-accept-dot #t]
+ [read-accept-infix-dot #t]
+ [read-accept-quasiquote #t]
+ [read-accept-reader #t]
+ [read-accept-lang #f]
+ [current-readtable #f])
+ (let ([v (let ([p (open-input-file (if user? user-links-path links-path)
+ 'binary)])
+ (dynamic-wind
+ void
+ (lambda ()
+ (begin0
+ (read p)
+ (unless (eof-object? (read p))
+ (error "expected a single S-expression"))))
+ (lambda () (close-input-port p))))])
+ (unless (and (list? v)
+ (andmap (lambda (p)
+ (and (list? p)
+ (or (= 2 (length p))
+ (= 3 (length p)))
+ (string? (car p))
+ (path-string? (cadr p))
+ (or (null? (cddr p))
+ (regexp? (caddr p)))))
+ v))
+ (error "ill-formed content"))
+ (let ([ht (make-hasheq)]
+ [dir (let-values ([(base name dir?) (split-path (if user?
+ user-links-path
+ links-path))])
+ base)])
+ (for-each
+ (lambda (p)
+ (when (or (null? (cddr p))
+ (regexp-match? (caddr p) (version)))
+ (let ([s (string->symbol (car p))])
+ (hash-set! ht s (cons (box (path->complete-path (cadr p) dir))
+ (hash-ref ht s null))))))
+ v)
+ (if user?
+ (begin
+ (set! user-links-cache ht)
+ (set! user-links-timestamp ts))
+ (begin
+ (set! links-cache ht)
+ (set! links-timestamp ts)))
+ ht))))
+ (if user?
+ user-links-cache
+ links-cache))))))))
+
+ (define-values (normalize-collection-reference)
+ (lambda (collection collection-path)
+ ;; make sure that `collection' is a top-level collection name,
+ (cond
+ [(string? collection)
+ (let ([m (regexp-match-positions #rx"/+" collection)])
+ (if m
+ (cond
+ [(= (caar m) (sub1 (string-length collection)))
+ (values (substring collection 0 (caar m)) collection-path)]
+ [else
+ (values (substring collection 0 (caar m))
+ (cons (substring collection (cdar m))
+ collection-path))])
+ (values collection collection-path)))]
+ [else
+ (let-values ([(base name dir?) (split-path collection)])
+ (if (eq? base 'relative)
+ (values name collection-path)
+ (normalize-collection-reference base (cons name collection-path))))])))
+
(define-values (find-col-file)
(lambda (who fail collection collection-path file-name)
- (let ([all-paths (current-library-collection-paths)])
- (let cloop ([paths all-paths][found-col #f])
- (if (null? paths)
- (if found-col
- found-col
- (fail
- (format "~a: collection not found: ~s in any of: ~s"
- who (if (null? collection-path)
- collection
- (apply build-path collection collection-path))
- all-paths)))
- (let ([dir (build-path (car paths) collection)])
- (if (directory-exists? dir)
- (let ([cpath (apply build-path dir collection-path)])
- (if (directory-exists? cpath)
- (if file-name
- (if (or (file-exists? (build-path cpath file-name))
- (let ([alt-file-name
- (let* ([file-name (if (path? file-name)
- (path->string file-name)
- file-name)]
- [len (string-length file-name)])
- (and (len . >= . 4)
- (string=? ".rkt" (substring file-name (- len 4)))
- (string-append (substring file-name 0 (- len 4)) ".ss")))])
- (and alt-file-name
- (file-exists? (build-path cpath alt-file-name)))))
- cpath
- ;; Look further for specific file, but remember
- ;; first found directory
- (cloop (cdr paths) (or found-col cpath)))
- ;; Just looking for dir; found it:
- cpath)
- ;; sub-collection not here; try next instance
- ;; of the top-level collection
- (cloop (cdr paths) found-col)))
- (cloop (cdr paths) found-col))))))))
+ (let-values ([(collection collection-path)
+ (normalize-collection-reference collection collection-path)])
+ (let ([all-paths (let ([sym (string->symbol (if (path? collection)
+ (path->string collection)
+ collection))])
+ (append
+ ;; list of (box path)s:
+ (if (use-user-specific-search-paths)
+ (hash-ref (get-linked-collections #t) sym null)
+ null)
+ ;; list of (box path)s:
+ (if links-path
+ (hash-ref (get-linked-collections #f) sym null)
+ null)
+ ;; list of paths:
+ (current-library-collection-paths)))])
+ (define-values (*build-path-rep)
+ (lambda (p c)
+ (if (path? p)
+ (build-path p c)
+ ;; box => from links table for c
+ (unbox p))))
+ (define-values (*directory-exists?)
+ (lambda (orig p)
+ (if (path? orig)
+ (directory-exists? p)
+ ;; orig is box => from links table
+ #t)))
+ (define-values (to-string) (lambda (p) (if (path? p) (path->string p) p)))
+ (let cloop ([paths all-paths] [found-col #f])
+ (if (null? paths)
+ (if found-col
+ found-col
+ (let ([rest-coll
+ (if (null? collection-path)
+ ""
+ (apply
+ string-append
+ (let loop ([cp collection-path])
+ (if (null? (cdr cp))
+ (list (to-string (car cp)))
+ (list* (to-string (car cp)) "/" (loop (cdr cp)))))))])
+ (define-values (filter)
+ (lambda (f l)
+ (if (null? l)
+ null
+ (if (f (car l))
+ (cons (car l) (filter f (cdr l)))
+ (filter f (cdr l))))))
+ (fail
+ (format "~a: collection not found: ~s in any of: ~s~a"
+ who
+ (if (null? collection-path)
+ (to-string collection)
+ (string-append (to-string collection) "/" rest-coll))
+ (filter path? all-paths)
+ (if (ormap box? all-paths)
+ (format " or: ~s in any of: ~s"
+ rest-coll
+ (map unbox (filter box? all-paths)))
+ "")))))
+ (let ([dir (*build-path-rep (car paths) collection)])
+ (if (*directory-exists? (car paths) dir)
+ (let ([cpath (apply build-path dir collection-path)])
+ (if (if (null? collection-path)
+ #t
+ (directory-exists? cpath))
+ (if file-name
+ (if (or (file-exists? (build-path cpath file-name))
+ (let ([alt-file-name
+ (let* ([file-name (if (path? file-name)
+ (path->string file-name)
+ file-name)]
+ [len (string-length file-name)])
+ (and (len . >= . 4)
+ (string=? ".rkt" (substring file-name (- len 4)))
+ (string-append (substring file-name 0 (- len 4)) ".ss")))])
+ (and alt-file-name
+ (file-exists? (build-path cpath alt-file-name)))))
+ cpath
+ ;; Look further for specific file, but remember
+ ;; first found directory
+ (cloop (cdr paths) (or found-col cpath)))
+ ;; Just looking for dir; found it:
+ cpath)
+ ;; sub-collection not here; try next instance
+ ;; of the top-level collection
+ (cloop (cdr paths) found-col)))
+ (cloop (cdr paths) found-col)))))))))
(define-values (check-suffix-call)
(lambda (s sfx who)
@@ -393,85 +661,6 @@
(cons (simplify-path (path->complete-path v (current-directory)))
(loop (cdr l)))
(loop (cdr l)))))))))]))
-
- (define-values (path-list-string->path-list)
- (let ((r (byte-regexp (string->bytes/utf-8
- (let ((sep (if (eq? (system-type) 'windows)
- ";"
- ":")))
- (format "([^~a]*)~a(.*)" sep sep)))))
- (cons-path (lambda (default s l)
- (if (bytes=? s #"")
- (append default l)
- (cons (bytes->path (if (eq? (system-type) 'windows)
- (regexp-replace* #rx#"\"" s #"")
- s))
- l)))))
- (lambda (s default)
- (unless (or (bytes? s)
- (string? s))
- (raise-type-error 'path-list-string->path-list "byte string or string" s))
- (unless (and (list? default)
- (andmap path? default))
- (raise-type-error 'path-list-string->path-list "list of paths" default))
- (let loop ([s (if (string? s)
- (string->bytes/utf-8 s)
- s)])
- (let ([m (regexp-match r s)])
- (if m
- (cons-path default (cadr m) (loop (caddr m)))
- (cons-path default s null)))))))
-
- (define-values (find-executable-path)
- (case-lambda
- [(program libpath reverse?)
- (unless (path-string? program)
- (raise-type-error 'find-executable-path "path or string (sans nul)" program))
- (unless (or (not libpath) (and (path-string? libpath)
- (relative-path? libpath)))
- (raise-type-error 'find-executable-path "#f or relative path or string" libpath))
- (letrec ([found-exec
- (lambda (exec-name)
- (if libpath
- (let-values ([(base name isdir?) (split-path exec-name)])
- (let ([next
- (lambda ()
- (let ([resolved (resolve-path exec-name)])
- (cond
- [(equal? resolved exec-name) #f]
- [(relative-path? resolved)
- (found-exec (build-path base resolved))]
- [else (found-exec resolved)])))])
- (or (and reverse? (next))
- (if (path? base)
- (let ([lib (build-path base libpath)])
- (and (or (directory-exists? lib)
- (file-exists? lib))
- lib))
- #f)
- (and (not reverse?) (next)))))
- exec-name))])
- (if (and (relative-path? program)
- (let-values ([(base name dir?) (split-path program)])
- (eq? base 'relative)))
- (let ([paths-str (getenv "PATH")]
- [win-add (lambda (s) (if (eq? (system-type) 'windows)
- (cons (bytes->path #".") s)
- s))])
- (let loop ([paths (if paths-str
- (win-add (path-list-string->path-list paths-str null))
- null)])
- (if (null? paths)
- #f
- (let* ([base (path->complete-path (car paths))]
- [name (build-path base program)])
- (if (file-exists? name)
- (found-exec name)
- (loop (cdr paths)))))))
- (let ([p (path->complete-path program)])
- (and (file-exists? p) (found-exec p)))))]
- [(program libpath) (find-executable-path program libpath #f)]
- [(program) (find-executable-path program #f #f)]))
;; used for the -k command-line argument:
(define (embedded-load start end str)
diff --git a/src/racket/src/thread.c b/src/racket/src/thread.c
index a8ee52fabe..fe26d20705 100644
--- a/src/racket/src/thread.c
+++ b/src/racket/src/thread.c
@@ -636,6 +636,7 @@ void scheme_init_paramz(Scheme_Env *env)
GLOBAL_PRIM_W_ARITY("check-for-break" , check_break_now , 0, 0, newenv);
GLOBAL_PRIM_W_ARITY("reparameterize" , reparameterize , 1, 1, newenv);
GLOBAL_PRIM_W_ARITY("make-custodian-from-main", make_custodian_from_main, 0, 0, newenv);
+ GLOBAL_PRIM_W_ARITY("find-links-path!" , scheme_find_links_path , 1, 1, newenv);
scheme_finish_primitive_module(newenv);
scheme_protect_primitive_provide(newenv, NULL);