Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

add `raco link'

includes a rewrite the "Module Basics" section of the Guide
  • Loading branch information...
commit a7855e20a8b1b8e35bd7dac0718e2fd76d3b09c0 1 parent b7bad5c
@mflatt mflatt authored
Showing with 2,181 additions and 833 deletions.
  1. +34 −25 collects/compiler/compiler-unit.rkt
  2. +1 −0  collects/config/.gitignore
  3. +1 −0  collects/racket/sandbox.rkt
  4. +44 −26 collects/scribblings/guide/hash-languages.scrbl
  5. +227 −37 collects/scribblings/guide/module-basics.scrbl
  6. +97 −0 collects/scribblings/guide/module-hier.rkt
  7. +8 −3 collects/scribblings/guide/welcome.scrbl
  8. +5 −1 collects/scribblings/raco/common.rkt
  9. +107 −0 collects/scribblings/raco/link.scrbl
  10. +1 −0  collects/scribblings/raco/raco.scrbl
  11. +17 −12 collects/scribblings/raco/setup.scrbl
  12. +61 −13 collects/scribblings/reference/collects.scrbl
  13. +10 −1 collects/scribblings/reference/filesystem.scrbl
  14. +5 −1 collects/scribblings/reference/mz.rkt
  15. +12 −2 collects/scribblings/reference/startup.scrbl
  16. +1 −1  collects/setup/collects.rkt
  17. +74 −0 collects/setup/commands/link.rkt
  18. +17 −12 collects/setup/getinfo.rkt
  19. +2 −1  collects/setup/info.rkt
  20. +157 −0 collects/setup/link.rkt
  21. +9 −4 collects/setup/private/omitted-paths.rkt
  22. +2 −2 collects/setup/private/path-utils.rkt
  23. +8 −3 collects/setup/scribble.rkt
  24. +113 −64 collects/setup/setup-unit.rkt
  25. +8 −1 collects/setup/xref.rkt
  26. +4 −0 doc/release-notes/racket/HISTORY.txt
  27. +37 −1 src/racket/cmdline.inc
  28. +1 −0  src/racket/include/scheme.h
  29. +2 −0  src/racket/include/schthread.h
  30. +498 −412 src/racket/src/cstartup.inc
  31. +46 −4 src/racket/src/file.c
  32. +2 −0  src/racket/src/schpriv.h
  33. +2 −2 src/racket/src/schvers.h
  34. +261 −88 src/racket/src/startup.inc
  35. +306 −117 src/racket/src/startup.rktl
  36. +1 −0  src/racket/src/thread.c
View
59 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?
View
1  collects/config/.gitignore
@@ -0,0 +1 @@
+/links.rktd
View
1  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
View
70 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
View
264 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.)
-
-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}.
+@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.)
+
+@; ----------------------------------------
+@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}.
View
97 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))
View
11 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[
View
6 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"))
View
107 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.}
View
1  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"]
View
29 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?)]
View
74 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.
View
11 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
View
6 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
View
14 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].
View
2  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)
View
74 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)))
+
View
29 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?))))
View
3  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)))
View
157 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))))
View
13 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)))
View
4 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)]))
View
11 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)))
View
177 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 ;;
View
9 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))))))
View
4 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
View
38 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 <dir>, --collects <dir> : Main collects at <dir>\n"
" -S <dir>, --search <dir> : More collects at <dir> (after main collects)\n"
" -A <dir>, --addon <dir> : Addon directory at <dir>\n"
+ " -K <file>, --links <file> : Collection links at <file>\n"
" -U, --no-user-path : Ignore user-specific collects, etc.\n"
" -N <file>, --name <file> : Sets `(find-system-path 'run-file)' to <file>\n"
# ifdef MZ_USE_JIT
View
1  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);
View
2  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_)
View
910 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,