ref: 70f57939ef437a822bfacde3a6e487633b6ba706
parent: 42d448ae565b8114797afce598ddc34b8ed97e7d
author: henesy <devnull@localhost>
date: Sat Nov 3 21:28:43 EST 2018
init 2
--- /dev/null
+++ b/INSTALL
@@ -1,0 +1,86 @@
+Installing hosted Inferno from source
+
+Overview
+
+ Like the native kernels emu relies on several auxil-
+iary libraries (the source of which it often shares with the
+native kernels). Emu itself is built by the mkfile in the
+emu subdirectory containing the platform-specific source for
+the host platform. Each library has its own mkfile; the
+various components are made in the right order by the
+mkfile at the root of the Inferno tree. The mkfile for
+each platform will also invoke mk recursively to make the
+appropriate libraries for a given configuration.
+
+ The Unix emu variant generally is covered by `POSIX'
+(with common extensions) but each Unix port has one file
+that differs considerably for each port, namely
+emu/platform/os.c, the differences corresponding to the dif-
+ferent ways under Unix of implementing kernel-scheduled
+threads efficiently.
+
+ There are working emu versions for FreeBSD/386,
+Irix/mips, Linux/386, NetBSD/386, MacOSX/386, MacOSX/power,
+Plan 9, Solaris/sparc, and Windows (NT, 2000 and Explorer
+plug-in). Each platform typically uses mechanisms specific
+to the host operating system to implement Inferno's internal
+thread/process structure. POSIX threads have often been
+found to be insufficient (poorly implemented) on some plat-
+forms, and if so are avoided. See kproc in emu/*/os.c.
+
+ Source is included for ports to HP/UX (S800 architec-
+ture), Solaris/386, and Unixware, in case someone wishes to
+take them up now, but we have not determined their fitness.
+
+ The Plan 9 hosted implementation is unusual in that it
+supports several processor types: 386, mips, power (Power
+PC) and sparc. Furthermore, all versions of emu can be
+built on any processor type, in the usual way for Plan 9.
+
+ Otherwise, as distributed, emu for a platform can only
+be built when running on that platform.
+
+ One unusual variant makes the whole of Inferno a plug-
+in for Microsoft's Internet Explorer, giving the same envi-
+ronment for Inferno applications running in an HTML page as
+is provided by hosted or native Inferno. That is, there is
+not a distinct `applet' environment with special programming
+interfaces. The source for the various plug-in components
+is found in /tools/plugin and /usr/internet within the
+Inferno tree; they use the version of emu defined by the
+configuration file /emu/Nt/ie.
+
+Build steps
+
+ All the libraries and executables can be built in a
+tree containing only the source code. To do that for a sup-
+ported variant of hosted Inferno, on Unix or Plan 9, do the
+following in the root of the Inferno tree:
+
+1 Edit mkconfig to reflect your host environment,
+ specifically ROOT (which must be an absolute path
+ name), SYSHOST and OBJTYPE. The comments in the file
+ should help you choose.
+
+2 Run makemk.sh to rebuild the mk command, which is
+ used to build everything else.
+
+3 Set PATH (or path on Plan 9) to include the bin
+ directory for the platform, which will now contain the
+ mk binary just built. On Unix, export PATH.
+
+4 Then mk nuke to remove any extraneous object files.
+
+5 Finally, mk install to create and install the
+ libraries, limbo compiler, emu for hosted Inferno,
+ and auxiliary commands. The rules do that in an order
+ that ensures that the commands or libraries needed by a
+ later stage are built and installed first. (Note that
+ a plain mk will not suffice, because it does not put
+ the results in the search path.)
+
+Doing something similar on Windows or Plan 9 currently
+requires the executable for mk to be available in the
+search path, since there is no equivalent of makemk.sh.
+Otherwise the procedure is the same. On Plan 9, of course,
+the host system's normal version of mk should be adequate.
--- /dev/null
+++ b/README.md
@@ -1,0 +1,9 @@
+Inferno® is a distributed operating system, originally developed at Bell Labs, but now developed and maintained by Vita Nuova® as Free Software. Applications written in Inferno's concurrent programming language, Limbo, are compiled to its portable virtual machine code (Dis), to run anywhere on a network in the portable environment that Inferno provides. Unusually, that environment looks and acts like a complete operating system.
+
+The use of a high-level language and virtual machine is sensible but mundane. The interesting thing is the system's representation of services and resources. They are represented in a file-like name hiearchy. Programs access them using only the file operations open, read/write, and close. The 'files' may of course represent stored data, but may also be devices, network and protocol interfaces, dynamic data sources, and services. The approach unifies and provides basic naming, structuring, and access control mechanisms for all system resources. A single file-service protocol (the same as Plan 9's 9P) makes all those resources available for import or export throughout the network in a uniform way, independent of location. An application simply attaches the resources it needs to its own per-process name hierarchy ('name space').
+
+The system can be used to build portable client and server applications. It makes it straightforward to build lean applications that share all manner of resources over a network, without the cruft of much of the 'Grid' software one sees.
+
+Inferno can run 'native' on various ARM, PowerPC, SPARC and x86 platforms but also 'hosted', under an existing operating system (including FreeBSD, Irix, Linux, MacOS X, Plan 9, and Solaris), again on various processor types.
+
+This Bitbucket project includes source for the basic applications, Inferno itself (hosted and native), all supporting software, including the native compiler suite, essential executables and supporting files.
--- /dev/null
+++ b/doc/20010618.ms
@@ -1,0 +1,941 @@
+.TL
+Inferno 3rd Edition \- June 2001 Revision
+.br
+Release Notes and Errata
+.AI
+Vita Nuova
+support@vitanuova.com
+.br
+18 June 2001
+.SP 4
+.NH 1
+Installation
+.LP
+If you have a previous version of Inferno installed, this one must not
+be installed over it.
+If you have a Lucent Inferno 2.3 release from 1999 or earlier, you
+should make a completely new installation from this CD.
+If you have installed the Vita Nuova `Binary and Limited Source' CD you
+should also make a new installation from this CD.
+If you have previously installed the Vita Nuova Full Source CD from July 2000,
+see the section `Updating the July 2000 release' at the end of this document.
+(You could also make a fresh installation in a new directory, or remove the old
+release and install this one if there are no files you wish to keep.)
+.LP
+Follow the installation instructions in ``Installation of the Inferno Software''
+at the end of Volume 2.
+The printed copy has several mistakes:
+.IP \(bu
+Page 327 notes that on Unix
+if the installation is done as user
+.CW root
+but a user
+.CW inferno
+exists the files will be owned by
+.CW inferno .
+They are not.
+Indeed, on Unix there is no reason to install the package as
+the super-user
+.CW root .
+Do the installation as the user, perhaps
+.CW inferno ,
+that is to own the files.
+.IP \(bu
+It refers on page 327
+to the Windows installation program as
+.CW Nt-386.exe .
+The correct name is used on the next
+page in the actual instructions, namely
+.CW \einstall\esetup.exe .
+.IP \(bu
+The Windows
+.CW setup.exe
+will offer to create the target installation directory if it does not exist.
+On all other systems, you must first create the directory yourself.
+.IP \(bu
+Solaris and some other commercial Unix systems
+do not read the `Joliet' format section of the CD,
+which uses Unicode names, and
+they
+force the names in the non-Joliet portion on the CD to lower case, sometimes
+with hyphens converted to underscores.
+The installation script on Solaris is therefore
+.CW install/solaris_sparc.sh .
+The installation script itself works despite this.
+Alternatively, if the CD is mounted with the option
+.CW nomaplcase
+the system will not force the names to lower case
+and all names will appear as we intended
+(see the Solaris manual entry for
+.I mount_hsfs ).
+Future CDs will use Rock Ridge format as well as Joliet to avoid the problem.
+(We attempted that this time
+but ran into trouble on Windows systems because of an error in the CD writing program.)
+Linux and FreeBSD show the names we intended.
+.LP
+When installing on Windows NT or Windows 2000, the installation program determines
+if the current user belongs to the
+.CW Administrators
+group.
+If so, the Start Menu entry is created in the
+.CW "All Users"
+profile, otherwise it is created in the user's private profile.
+On Windows 95 and Windows 98, if the user has a private profile the
+Start Menu entry is created there,
+otherwise it is created in the main system Start Menu.
+Furthermore,
+.CW setup.exe
+looks for
+.CW "Start Menu"
+to install the shortcut, but that name is locale-dependent,
+and thus the shortcut will not be installed correctly in non-English locales,
+although Inferno itself will be installed successfully.
+.LP
+When the installation completes normally,
+it prints ``installation complete'', but on some platforms it can then print
+``Killed: ...'' followed by the command line used in the installation shell script.
+Provided it has said ``installation complete'' and there were no errors noted
+prior to that, the installation has succeeded.
+The ``Killed'' message results from the installation software
+running inside the Inferno environment having shut down that environment.
+It does not mean that installation failed.
+.LP
+If an installation does fail, for instance by running out of space,
+delete everything in the target directory before retrying the installation.
+Also see the ``Known Problems'' section below.
+.NH 1
+CD Number
+.LP
+There is a set of six unique numbers on the back of the CD case.
+You should keep the case or record the numbers:
+they identify your subscription, and you will need them
+to gain access to subscriber's services we provide electronically.
+(They are randomly generated and usable in a 6/49 lottery!)
+.NH 1
+Hosted Operating System versions
+.LP
+The software was compiled on the operating system versions listed below.
+UNIX systems show the output from
+.CW "uname -a"
+and the version of the C compiler,
+if known.
+See the section
+.I "Known problems"
+below for a list of known problems for any given release.
+.TS
+center;
+lf(B) lf(R)w(4i) .
+Windows Nt Windows NT4.0 SP4
+Linux T{
+Linux vespa 2.2.9-19mdk #1 Wed May 19 19:53:00 GMT 1999 i586 ...
+.br
+(gcc-2.91.66)
+T}
+Solaris T{
+SunOS pazzo 5.6 Generic_105181-03 sun4u sparc SUNW,Ultra-5_10
+.br
+(gcc 2.95)
+T}
+FreeBSD 4.x T{
+FreeBSD outside 4.0-RELEASE FreeBSD 4.0-RELEASE #0: ... i386
+.br
+(gcc 2.95.2)
+T}
+HP/UX T{
+HP-UX hpserv1 B.10.20 A 9000/715 2013314861 ...
+.br
+(c89)
+T}
+IRIX 5.3 T{
+IRIX invece 5.3 11091812 IP22 mips
+.br
+(MIPS cc)
+T}
+Plan9/x86 Third Edition, updates to 5th June 2001
+.TE
+.LP
+The Windows version has also been tested and
+used extensively on the following variants:
+.DS
+.ft B
+Windows '95
+Windows '98
+Windows Me
+.ft R
+.DE
+We have also installed and run the system under Windows 2000, both
+client and server, but there is a problem with the cursor under Windows 2000 client (see below).
+.LP
+Inferno source code is included for the following, but they have neither been
+built nor tested:
+.DS
+.ft B
+Plan 9 (mips, sparc, power)
+Solaris/386
+Unixware v 2.3
+.ft R
+.DE
+.NH 1
+Known problems
+.LP
+See
+.CW www.vitanuova.com/inferno/
+for current pointers to information about Inferno.
+You should particularly check the Frequently Asked Questions at
+.P1
+www.vitanuova.com/inferno/faq.html
+.P2
+and the current Bugs list at
+.P1
+www.vitanuova.com/inferno/bugs.html
+.P2
+The Subscriber area will include online updates after 6 July 2001.
+.LP
+Now, the bad news:
+.IP \(bu
+The Windows NT installation program will create a Start Menu shortcut that invokes
+.I emu
+with a
+.CW "-g800x600"
+argument. The
+.I emu
+display will be incorrect if the screen width available is less than 800 pixels and is not a multiple
+of four. The problem can be seen if the PC is configured with a resolution of 800x600 pixels
+and the Microsoft Office shortcut bar is active. The simplest fix is to change the
+.I emu
+shortcut to use a
+.CW "-g788x600"
+argument instead.
+.IP \(bu
+As mentioned above, the Windows NT installation program looks only for
+.CW "Start Menu"
+not the locale-dependent name.
+.IP \(bu
+Changing the cursor image does not work under Windows 2000 Client;
+this mainly affects
+.I acme ,
+which changes the cursor when rearranging or resizing frames.
+.IP \(bu
+The HP version of hosted Inferno was generated by HP/UX version B.10.20.
+On the HP platform,
+.CW emu
+can currently only be run in interpreted mode; the compiled mode (ie,
+.CW -c1
+option)
+will fault.
+.IP \(bu
+Some Inferno calls return error strings provided by Windows, without modification.
+They can be obscure:
+for instance, ``windows error 10049'' is produced by network calls
+that attempt to use symbolic names when
+.I cs (8)
+has not been started.
+.IP \(bu
+On all systems, the mapping from Inferno names and permissions to the underlying
+operating system's names and permissions needs more work, particularly on Windows.
+Common problems include:
+.RS
+.IP \-
+File names in the Inferno environment cannot be longer than 27 bytes.
+.IP \-
+.I Ftpfs
+cannot access files with long names or names containing spaces.
+.IP \-
+The contents of
+.CW /dev/user
+on Windows will contain the Windows user name, which can contain spaces.
+.IP \-
+Files created inside the Inferno hierarchy by host system applications
+can sometimes have odd permissions when accessed within Inferno.
+.IP \-
+Readonly files and open files cannot be removed under Windows.
+.LP
+In general, the mapping between Inferno users and groups and Windows/Nt users and groups
+is systematic, as described in
+.I sys-stat (2):
+.QS
+.I Emu
+attempts to maintain a limited but consistent map
+between Inferno and NT worlds, specifically between Inferno
+names and NT security IDs.
+Special NT group `Everyone'
+represents `other' for file permissions. The Inferno uid is
+the file owner under NT; the Inferno gid reported is the
+first user in the file's ACL that is neither the owner nor
+Everyone; failing that, the gid is the file's owner.
+.QE
+.LP
+The effects of this mapping are sometimes peculiar: for instance, something that
+is thought of as a user appears as the group name in
+.I ls ,
+and vice-versa.
+Either the implementation or the mapping might need to be rethought.
+.RE
+.IP \(bu
+.I bufio (2)
+maintains an internal list of files open for output,
+to support its little-used
+.CW flush -all
+operation.
+Unfortunately, that means that if several processes
+use the same Bufio module instance (the result of a single
+.CW load )
+concurrently for output to different files, they must separately interlock the open, create and close calls.
+.IP \(bu
+The file
+.CW utils/5l/thumb.c
+contains comments in the C++ style, which (reasonably enough) are not accepted by the
+ANSI C compiler on the HP/UX system we used, and thus the current
+.CW 5l
+is not compiled for HP/UX; they will be changed to ANSI C comments by
+one of the online updates.
+.NH 1
+Contents
+.LP
+This revision offers the following, compared to the July 2000 release.
+.SH
+.I "Repairs and changes"
+.IP \(bu
+Many bug fixes and improvements appear throughout.
+Many commands have been revised to print usage and diagnostic consistently, and give reliable exit status for
+.CW sh .
+.IP \(bu
+The shell
+.CW sh
+has repairs and several visible changes:
+.I sh-expr (1)
+implements a
+.CW %
+operator for remainder;
+a new
+.CW @
+operator creates a sub-shell to execute a command, allowing the calling shell to be insulated
+by
+.CW pctl
+(see
+.I sh-std (1))
+from changes to name space and environment;
+environment variables are stored in printable form;
+a newline is allowed after a caret;
+and everyone's favourite change, the colon character
+.CW : ' `
+is no longer reserved in argument words
+(allowing URLs to be given without quoting).
+.IP \(bu
+Inferno's Acme has been revised to match the version in Plan 9 (Third Edition).
+In particular, the
+.CW Edit
+built-in has been added, allowing the use of structural regular expressions
+and the
+.CW sam
+command language for efficient editing within
+Acme,
+replacing the
+.CW /acme/edit
+suite of commands.
+The Acme panes have acquired a similar touch of colour.
+.IP \(bu
+Charon has also had many fixes and improvements, particularly to
+Javascript extraction, frames and layout code.
+Sometimes the `fix' requires making Charon mimic the interpretation of incorrect HTML
+of other browsers.
+The PNG image format is now supported.
+Cookies are enabled by default (too many sites use them);
+parsing and production of the cookie file has been repaired.
+The progress bar is more compact.
+Support for longer SSL keys is enabled by default.
+.IP \(bu
+The software installation commands
+.CW install/*
+have been extensively revised,
+and documented by
+.I archfs (4)
+and
+.I create (8).
+They are based (though not entirely) on Russ Cox's update
+package for Plan 9.
+.IP \(bu
+.I format (8)
+can format an ordinary file, for instance to prepare flash partition
+contents in a hosted environment for a native Inferno device.
+.IP \(bu
+.CW mount
+allows the certificate file to be named directly.
+.IP \(bu
+.CW ns
+correctly quotes the fields in its output.
+.IP \(bu
+.CW /services/server/config
+no longer gives the unauthenticated
+.CW nobody ') (`
+option to
+.I styx (8);
+some unused entries have also been deleted.
+.IP \(bu
+.I srv (8)
+passes all arguments to servers it spawns, including the command name.
+It also ensures each server has its own process group, file descriptors
+and name space.
+.IP \(bu
+.I stack (1)
+has a new
+.CW -p
+option to add names to the source file search list.
+.IP \(bu
+.I deflate (2)
+correctly detects end-of-file;
+.I inflate (2)
+correctly decodes the combined compressed code-length tables
+.IP \(bu
+Tk's handling of objects in canvases is better:
+raise and lower work properly; stipple is implemented.
+.IP \(bu
+Tk now knows that a window pops up when resized, and adjusts
+the z-order accordingly.
+.IP \(bu
+Tk's scroller always expands the fraction of a
+.CW moveto
+when it evaluates the scrolling command.
+.SH
+.I "New commands and modules"
+.IP \(bu
+.I ftpfs (4)
+provides a way to make a remote FTP site visible in the Inferno name space
+(it was documented in the printed manual but not previously included with the system).
+.IP \(bu
+.I listen (1)
+provides a convenient way to listen for incoming calls to one or more Inferno services,
+with optional use of
+.I ssl (3)
+for authentication and encryption.
+This can replace the clumsy use of
+.I srv (8).
+.IP \(bu
+.I dial
+(see
+.I listen (1))
+is the complement of
+.I listen ;
+it dials a service, with optional authentication and encryption.
+.IP \(bu
+.I lockfs (4)
+enforces multiple reader, exclusive writer access to the contents of a name space.
+.IP \(bu
+The device
+.I prof (3)
+serves a name space for controlling the profiling of Limbo modules,
+and retrieving the resulting data.
+The module
+.I profile (2)
+offers a convenient interface, relating the profiling data to the source code.
+Finally,
+.I prof (1)
+is the command line interface to enable profiling and display the results.
+.IP \(bu
+.CW uuencode
+and
+.CW uudecode
+interpret a format used to encode binary data printably on Usenet and in mail messages;
+see
+.I uuencode (1).
+.IP \(bu
+.I Read (1)
+writes to standard output the result of a single
+.I sys-read (2)
+of a given number of bytes from standard input,
+with optional seek offset.
+(See
+.I getlines
+in
+.I sh-std (1)
+for a way to read a line from standard input.)
+.IP \(bu
+.I Tcs (1)
+uses
+.I convcs (2)
+to offer character set conversion on files.
+.IP \(bu
+.I wm-misc (1)
+mentions
+.CW wm/mand ,
+a browser for fractals,
+and
+.CW wm/polyhedra ,
+a polyhedra viewer
+.IP \(bu
+.I cfg (2)
+provides a module to read configuration files.
+.IP \(bu
+.I dividers (2)
+provides user-draggable dividing lines to separate Tk widgets,
+allowing screen space to be allocated to widgets by dragging a dividing line.
+.IP \(bu
+.I imagefile (2)
+offers support for reading PNG image files
+.SH
+.I "Interface changes and extensions"
+.IP \(bu
+.CW Url
+.CW /module/url.m ) (
+now requires an
+.CW init
+function to be invoked before other functions in the module
+.IP \(bu
+.I convcs (2)
+has changed its interface significantly (see the manual page);
+it also offers support for UTF-7.
+Even the module name has changed, to
+.CW Convcs
+(from
+.CW ConvCS ).
+.IP \(bu
+.I plumber (8)
+now returns an error to a message's sender if it cannot be plumbed,
+as was previously documented;
+it handles
+.CW ^
+correctly in regular expressions
+.IP \(bu
+.I readdir (2)
+returns all file names in union directories
+.IP \(bu
+.I string (2)'s
+quoting and unquoting functions are correct and more efficient
+.IP \(bu
+.I styxlib (2)
+forces an internal process into a new empty name space to
+allow detection of the last unmount of the served space by a file server
+.IP \(bu
+.I translate (2)
+supports writing Unicode characters in hexadecimal using Limbo's \f5\eu\fP\fIXXXX\fP
+syntax
+.IP \(bu
+.I workdir (2)
+returns a better guess at the current directory on native Inferno
+(hosted implementation will be supported in the next update)
+.IP \(bu
+.I cs (8)
+keeps a cache of recent translations;
+.I ipsrv (8)
+uses UDP/IP by default, not TCP/IP, for domain name lookup
+.IP \(bu
+.I httpd (8)
+can now be said to work as documented
+.IP \(bu
+.I wm-sh (1)
+provides a new control file
+.CW /chan/shctl
+to allow it to be kept informed
+of the current directory (and
+.CW /lib/wmsetup
+defines a Shell function to do that)
+and to implement buttons below the title bar,
+as with
+.I mash-tk (1).
+.IP \(bu
+A collection of playing card images has been added in
+.CW /icons/cards .
+.IP \(bu
+.CW /lib/wmsetup
+defines a
+.CW cd
+function to keep
+.CW wm/sh
+informed of the current directory;
+the
+.CW Web
+menu item is now called
+.CW Charon ;
+a new
+.CW Manual
+entry invokes
+.I wm-man (1);
+and the game
+.CW Tetris
+has been added to the
+.CW Misc
+submenu.
+.IP \(bu
+The manual pages
+.I draw-font (2),
+.I draw-image (2),
+and
+.I draw-screen (2)
+now document
+.CW display
+and
+.CW screen
+members of various data structures.
+.IP \(bu
+.I security-auth (2)
+and
+.I security-login (2)
+note that
+.CW keyring.m
+must be included.
+.IP \(bu
+In
+.I sh (2),
+the function
+.CW exec
+has been renamed
+.CW run ,
+to reflect more accurately what it does.
+.IP \(bu
+In
+.I sys-pctl (2),
+the type of the second parameter to
+.CW Sys->pctl
+is actually
+.CW "list of int"
+not
+.CW "list of ref Sys->FD" .
+.IP \(bu
+.I ssl (3)
+documents the new
+.CW encalg
+and
+.CW hashalg
+files, which list the supported algorithms.
+.IP \(bu
+.I canvas (9)
+describes the new
+.CW -winding
+option
+.IP \(bu
+.CW /services/cs/services
+lists the Software Download Server port
+and removes others that are obsolete.
+.IP \(bu
+.CW /services/server/config
+no longer gives the unauthenticated
+.CW nobody ') (`
+option to
+.I styx (8);
+some unused entries have also been deleted.
+.SH
+.I "Limbo compiler"
+.IP \(bu
+The Limbo compiler correctly clears reference values (eg,
+.CW list ,
+.CW ref
+and
+.CW array )
+when they go out of scope when necessary (eg, in loops), causing the storage to be reclaimed,
+and the values to be correctly
+.CW nil
+when the scope is next entered.
+.IP \(bu
+A bug that caused temporaries sometimes to be reused too early has been fixed.
+.IP \(bu
+The compile-time evaluation of floating-point
+.CW >
+does not calculate
+.CW >=
+instead.
+.IP \(bu
+A little context has been added to `syntax error' messages.
+.SH
+.I "Compilers and architectures"
+.IP \(bu
+The system now supports the Thumb variant of the ARM architecture,
+including full interworking of Thumb code and 32-bit ARM code;
+there is a Thumb JIT compiler for the virtual machine, and support for
+Thumb mode in the disassembler and debugger.
+The Thumb compiler is
+.CW tc ;
+the existing ARM linker
+.CW 5l
+links both ARM and Thumb code.
+.IP \(bu
+A bug in
+.CW 5l
+has been fixed that could very occasionally place a literal pool inside a case table.
+.IP \(bu
+The compilers find include files correctly under Nt.
+.SH
+.I "Hosted and Native Inferno"
+.IP \(bu
+.I Emu
+has the following fixes and improvements:
+.RS
+.IP \-
+support for logging of memory pool usage
+.IP \-
+FreeBSD support uses
+.I rfork
+not
+.I pthreads .
+.IP \-
+Linux support no longer relies on being able to set the TSS register.
+.IP \-
+A memory leak when a kernel process exits has been fixed.
+.IP \-
+A start has been made on tidying up the audio support; the
+.CW svp.c
+file has gone and platforms that do not currently support audio
+no longer must include a stub driver.
+.IP \-
+The Linux and
+FreeBSD ports use an alternative implementation of Inferno graphics
+under X11 that should allow the program to run under 16-bit graphics and higher.
+.RE
+.IP \(bu
+For the native kernels only:
+.RS
+.IP \-
+The native kernel implements Rob Pike's `lexical names' (as in Plan 9), which helps
+provide more sensible data to
+.I workdir (2).
+The hosted Inferno implementation of lexical names will appear in a future update.
+Note that
+.CW /os/port/ns.c
+no longer exists, and native kernel configuration files should no longer mention
+.CW ns
+in the
+.CW port
+section.
+Drivers that serve a directory hierarchy might need to support the
+.CW DEVDOTDOT
+value for the table index in their
+.CW devgen
+function.
+.IP \-
+.CW os/ip/bootp.c
+will correctly time out if there is no response.
+.CW os/ip/ihbootp.c
+will now work with an RFC1084 BOOTP server.
+Note that both are likely to be replaced in future by
+Limbo applications that do BOOTP and DHCP.
+.IP \-
+.CW os/pc/cga.c
+provides a replacement for
+.CW screen.c
+for use when only a simple CGA console is needed or possible.
+.IP \-
+The file descriptor array is correctly freed when the file descriptor
+group is closed, fixing a memory leak.
+.IP \-
+A few files that were left off the July 2000 CD have been included this time.
+.IP \-
+ARM/Thumb kernels have been implemented; those implementations
+are not included in this update because the hardware is specialised but ask if you could use them.
+.RE
+.LP
+The remaining points are common to both hosted and native Inferno:
+.IP \(bu
+A write on closed pipe does not produce an exception if the process has been killed.
+.IP \(bu
+.I Devbwrite
+will not lose memory if an error is raised by the device driver (eg, interrupt).
+.IP \(bu
+.I ssl (3)
+has
+.CW encalg
+and
+.CW hashalg
+files
+.IP \(bu
+.I Kfs (3)
+offers
+.CW readonly
+and
+.CW readwrite
+commands, and an
+.CW ro
+(readonly)
+option to the
+.CW init
+request.
+.IP \(bu
+.I Srv (3)
+rejects attempts to create an unusable name containing a `/'.
+.IP \(bu
+The
+.CW NODEVS
+flag of
+.I sys-pctl (2)
+is correctly copied when the name space is duplicated.
+.\" the following is only in the 386 version
+.\" .IP \(bu
+.\" .I Prog (3)
+.\" can optionally give the correct Dis pc for the debugger even for compiled modules; if
+.\" .CW cflag
+.\" (or
+.\" .CW -c
+.\" option for
+.\" .I emu )
+.\" is 2 not 1, a mapping table is retained after JIT compilation.
+.SH
+.I "SA1100 native"
+.IP \(bu
+A new
+.CW archether
+function in
+.CW arch*.c
+(when required)
+is invoked by
+.CW devether.c
+to discover the configuration of Ethernet devices.
+.IP \(bu
+.CW devuart.c
+supports the use of XON/XOFF;
+the first line of the
+.CW stat
+file gives the current UART settings;
+it no longer panics if an overrun occurs;
+and
+.CW setlength
+accesses the correct structures.
+.IP \(bu
+The CS8900 driver
+.CW ether8900.c
+is more general, supporting the I/O port interface as well as the memory interface.
+.IP \(bu
+Obsolete definitions have been removed from several include files
+(eg,
+.CW io.h )
+and obsolete (typically #ifdef'd code) has been removed from source files.
+.NH 1
+IDEA™
+.LP
+The software includes an implementation of the IDEA encryption algorithm,
+for non-commercial use.
+IDEA was patented by Ascom-Tech AG (European patent EP 0 482 154 B1, US patent number
+US005214703, and patent filed in Japan).
+At time of writing, there was no licence fee required for noncommercial use.
+If you intend to use IDEA encryption commercially with Inferno, you should consult
+.CW http://www.it-sec.com/idea_lic_policy.html
+for the current licensing policy of iT_SEC Systec Ltd, which currently holds the patents and trademark.
+Note that IDEA is not required for
+successful use of Inferno.
+It is not by default enabled by
+.I rstyxd (8),
+and otherwise is used only by SSL3 (for the browser), in
+.CW /appl/lib/crypt/ssl3.b ,
+where it can be disabled.
+.NH 1
+Updating the July 2000 Full Source release
+.LP
+A set of update packages for the July 2000 release is provided in the directory
+.CW /updates
+on this June 2001 CD.
+You should install the updates as the host operating system user who owns the Inferno files and directories
+on your system.
+You might like to take a backup copy of the existing tree, just in case.
+Do the following to update the installation.
+(Next time we hope to provide a more automated scheme.
+You might check
+.CW www.vitanuova.com/inferno/
+to see if there are any more recent instructions.)
+.IP 1.
+Copy the directory
+.CW updates
+and its subdirectories from the CD to a directory
+.CW updates
+in the root of your existing Inferno hierarchy.
+Make sure there is sufficient space in the file system holding that hierarchy.
+If all platform files are copied and installed, about 45 Mbytes will be needed
+to hold the compressed update packages in
+.CW updates ,
+with a further
+35 Mbytes needed for an temporary uncompressed copy
+of the largest package, and allow 10 Mbytes for new additional material, giving
+90 Mbytes in all.
+The
+.CW updates
+directory can be removed after installation.
+.IP 2.
+Start the existing Inferno
+.I emu ;
+it will be quicker if you use the
+.CW -c1
+option to force compiled mode.
+It is best to use only the Inferno console; do not start the window system, since
+the updates will change files in the running system.
+On the other hand, it is a good idea to make the window in the host
+operating system a scrolling one, so that you can scroll back to
+see any errors.
+All following commands are run in the Inferno environment.
+.IP 3.
+Change to the directory
+.CW updates
+and load the standard Inferno shell module:
+.RS
+.P1
+cd /updates
+load std
+.P2
+.RE
+.NE 1i
+.IP 4.
+Unpack the updated installation software:
+.RS
+.P1
+gunzip <install.tgz | {cd /; gettar}
+.P2
+.RE
+.IP 5.
+Update the installed Inferno, source and utility source directories
+using the script
+.CW applybase :
+.RS
+.P1
+sh ./applybase
+.P2
+.LP
+That script updates the
+.CW inferno ,
+.CW src
+and
+.CW utils
+packages.
+You will see one warning:
+.P1
+skipping /dis/install/inst.dis: locally modified
+.P2
+because that file was updated by step 4.
+You might see other warnings if you have modified any other files from the original release.
+.RE
+.IP 6.
+Update one or more platform specific files for your platform(s).
+The directories are named after the platforms:
+.CW Solaris
+for Solaris,
+.CW Plan9
+for Plan 9,
+.CW Nt
+for all Windows systems,
+and so on.
+For each
+.I platform
+that you run, do:
+.RS
+.P1
+for (a in \fIplatform\fP/*) {install/inst -v -t $a}
+.P2
+.RE
+.IP 7.
+Quit
+.I emu .
+The new version of
+.I emu
+will be called
+.CW emu.new
+in the platform-specific directory
+(eg,
+.CW Solaris/sparc/bin/emu.new ).
+Rename the old
+.CW emu
+file as
+.CW emu.old ,
+then rename the new
+.CW emu.new
+as
+.CW emu
+on Plan 9 and Unix systems,
+or
+.CW emu.exe
+on Windows.
+When run, it should announce itself as
+``Inferno Third Edition (18 Jun 2001)''.
binary files /dev/null b/doc/20010618.pdf differ
--- /dev/null
+++ b/doc/20011003.ms
@@ -1,0 +1,758 @@
+.TL
+Inferno 3rd Edition \- 3 October 2001 Update
+.br
+Release Notes
+.AI
+Vita Nuova
+support@vitanuova.com
+.br
+3 October 2001
+.SP 4
+.NH 1
+Contents
+.LP
+This set of updates applies to the 18 June 2001 base.
+The installed software must therefore be that of 18 June 2001, whether installed directly,
+or the result of updating the original July 2000 release with update packages.
+.LP
+This update offers the following, compared to the June 2001 release.
+.SH
+.I "Repairs and changes"
+.IP \(bu
+Various minor bug fixes and improvements appear here and there.
+They include corrected usage messages, status returned to the shell on error,
+diagnosing failures to load library modules,
+and use of the
+.CW %r
+format to improve diagnostics.
+Many
+.I wm
+applications adjust their display to suit small screens (eg, on the Compaq iPAQ);
+currently the applications do some of the work themselves but it will soon be automatic.
+Other changes are listed below.
+.IP \(bu
+.I Date (1)
+takes the options
+.CW -u
+(show UTC/GMT)
+and
+.CW -n
+(print time as a number).
+If given a number of seconds as its argument,
+.I date
+takes that as the time to convert.
+.IP \(bu
+.I Format (8)
+supports tiny partitions.
+.IP \(bu
+.CW /appl/env.b
+uses
+.I env (2)
+to access environment variables.
+.IP \(bu
+For packages created after Saturday 8 September 2001,
+.CW install/create
+converts the leading
+.CW 10
+to the letter
+.CW A
+so that the names of update files remain in sorted order.
+.IP \(bu
+.CW install/inst
+takes a
+.CW -c
+option to cause it to carry on even if some files or directories cannot be made or updated.
+(This option is intended for special applications and should not generally be used when applying system updates.)
+.IP \(bu
+.CW install/install
+takes a
+.CW -P
+option that lists the packages to install.
+The
+.CW -g
+option causes
+.CW install
+to install all available packages.
+.IP \(bu
+The installation software regards files that have had carriage returns inserted
+before newlines as identical to the original files when deciding when files
+have been modified locally.
+.IP \(bu
+The
+.CW wm
+applications now check the whole string received on the window
+control channel returned by
+.I wmlib (2)'s
+.CW titlebar,
+not just an initial letter;
+in particular, they check for
+.CW "exit"
+not just
+.CW 'e' .
+.IP \(bu
+.I Wm (1)
+takes the option
+.CW -s
+to suppress the start menu.
+.IP \(bu
+.I Keyring-gensk (2)
+and
+.I createsignerkey (8)
+provide experimental support for the RSA algorithm for signatures instead
+of the default El-Gamal algorithm;
+.CW /keyring/rsaalg.c
+is new.
+.IP \(bu
+.CW /keyring/egalg.c
+uses the correct structure for Public keys.
+.IP \(bu
+.I Listen (1)
+has a new option
+.CW -i
+that takes a shell command for each listener to run to set up appropriate
+context (eg, name space) before listening for incoming calls.
+.IP \(bu
+.I man (1)
+allows non-numerics in section names.
+.IP \(bu
+.CW /appl/cmd/mkfile
+now includes
+.CW /mkfiles/mksubdirs
+and has acquired the list of
+.CW cmd
+subdirectories from
+.CW /appl/mkfile .
+.IP \(bu
+.I Puttar
+gives warnings not fatal errors when files or directories cannot be found.
+.IP \(bu
+.I sh-expr (1)
+implements the
+.CW !=
+operator.
+.IP \(bu
+.I Tail (1)
+no longer gives an array bound error when a binary file does not end with a newline.
+.IP \(bu
+.CW tiny/sh
+does not break when
+.I filepat (2)
+is not available.
+.IP \(bu
+.I Webgrab (1)
+has several repairs to its HTTP protocol implementation, making it work with multi-homed servers.
+.IP \(bu
+.CW wm/sendmail
+no longer fails to save messages when requested(!).
+.IP \(bu
+.I Arg (2)
+allows re-use by ensuring that its globals are reinitialised by its
+.CW init
+function.
+.IP \(bu
+.I Bufio (2)
+correctly implements relative seek.
+.IP \(bu
+.I Convcs (2)
+provides several more character sets.
+.IP \(bu
+.I Cs (8)
+does not complain if it is already running, suppressing a previously confusing diagnostic.
+.IP \(bu
+.CW lib/deflate
+no longer fails on the output of some PC versions of
+.I gzip .
+.IP \(bu
+.I Wmlib (2)
+adapts a little better to different font and screen sizes (though more remains to be done);
+on small screens, defined as those less than 480 pixels wide,
+.I wm (1)
+puts all windows at the screen origin by default.
+.SH
+.I "Interface changes and extensions"
+.IP \(bu
+.I Wm-deb (1)
+has got a
+.CW stack
+button to bring up the stack window if it has previously been dismissed.
+It also allows breakpoints to be set in modules that have not yet been loaded.
+.IP \(bu
+.CW wm/memory 's
+display has been redesigned to be more informative.
+.IP \(bu
+.CW wm/tetris
+allows the use of a stylus (or mouse) to guide the placement of pieces.
+.IP \(bu
+.CW wm/view
+supports PNG format
+.IP \(bu
+.CW wm/view
+has a new option
+.CW -i
+for use in
+.I plumbing (6)
+files, to cause it to listen for messages from the
+.I plumber (8).
+Existing plumbing files that invoke
+.CW wm/view
+will typically need to change to add that option for image viewing
+using the plumber to work as expected.
+.IP \(bu
+.I Newns (2)
+provides more general option parsing by using
+.I arg (2),
+and does error checking unless the
+.CW -i
+option is given to the
+.I namespace (6)
+commands.
+Its internal
+.CW mount
+commandalso accepts the new options
+.CW -k
+.I keyfile
+to select the source of the authentication key, and
+.CW -C
+.I alg
+to select the encryption algorithm.
+.IP \(bu
+.I Plumber (8)
+takes a
+.CW -v
+option to cause it to log the contents of messages (for debugging plumbing applications), and
+also the option
+.CW -c
+.I wmchan
+to select an alternative window manager channel instead of
+.CW /chan/wm
+when the
+.CW -w
+option is used.
+.SH
+.I "Tk changes and extensions"
+.LP
+Many of the Tk changes enforce rules and do more error-checking than before,
+but there are several extensions and interface changes as well.
+.IP \(bu
+Tk applications must create the parent widget before its children.
+Currently the check to enforce this rule has been suppressed, but it will be enabled in future.
+.IP \(bu
+Widget names are now checked for well-formedness: neither trailing dot nor double dot are allowed.
+.IP \(bu
+When text in a text widget is deleted, embedded windows in
+that text are only deleted if they are descendents of the text
+widget.
+.IP \(bu
+Text widget now redisplays correctly when an embedded window
+is destroyed.
+.IP \(bu
+Text widget now checks for embedded windows in the text that have been destroyed since they were added to the text.
+.IP \(bu
+Widgets packed under a destroyed widget that are not
+descendents of that widget are now removed correctly
+from the packing hierarchy.
+.IP \(bu
+.CW -activebackground
+now changes the border appropriately, same as
+.CW -background .
+.IP \(bu
+.CW scrollbar
+now returns currently activated part when
+.CW activate
+is called
+with no arguments.
+.IP \(bu
+Only one part of a scrollbar may be active at any one time.
+.IP \(bu
+Tk can now distinguish between a null argument
+.CW {}
+and a missing argument.
+.IP
+Creating an embedded window in a text widget at index 1.0
+no longer causes the packer to go into an infinite loop.
+.IP \(bu
+Changing the options on an embedded window in a text
+widget caused an uninitialised pointer access.
+.IP \(bu
+Changing the window associated with an embedded window item
+in text and canvas widgets previously did not disassociate the old window correctly.
+.IP \(bu
+Changing the window associated with an embedded window item
+in a text widget did not set the widget's size appropriately.
+.IP \(bu
+The
+.CW -baseline
+alignment option for embedded windows in text widgets previously
+did not calculate the line height correctly.
+.IP \(bu
+The
+.CW -relief
+setting for buttons is now restored after enter/leave or selection.
+.IP \(bu
+Buttons 4, 5 and 6 have been added (for the iPAQ).
+.IP \(bu
+Tk no longer crashes if the `grab' changes during the processing of a mouse event.
+.IP \(bu
+A new event
+.CW <Destroy>
+can be bound to a widget to receive notification when it is destroyed (eg, by the destruction of
+a parent widget).
+The
+.CW <Configure>
+event is propagated to slaves as well as the configured master.
+These two changes make it easier to implement pseudo-widgets such as
+.I dividers (2).
+.IP \(bu
+.CW -anchor
+has been implemented for labels;
+.CW -justify
+should be implemented as documented.
+.IP \(bu
+Submenus are unmapped correctly.
+.IP \(bu
+Tk detects command loops (by limiting recursion depth).
+.IP \(bu
+.CW canvas
+has a new boolean option
+.CW -buffered
+that controls whether the whole canvas, or just the visible region, is allocated an off-screen buffer image.
+It defaults to just the visible area only.
+.IP \(bu
+.CW canvas
+has new operations
+.CW screenx
+and
+.CW screeny
+to map canvas coordinates to screen coordinates.
+.SH
+.I "New commands and modules"
+.IP \(bu
+A collection of small and tiny playing card images have been added, in
+.CW /icons/smallcards
+and
+.CW /icons/tinycards .
+.IP \(bu
+.CW install/wfind
+lists the versions of a given file in a set of installation packages.
+.IP \(bu
+.I Touchcal (8)
+provides touch-screen calibration; it runs both inside and outside the window
+manager
+.I wm (1).
+Both internal and external interfaces are completely different from previous versions.
+.IP \(bu
+.I Wm-keyboard (1)
+describes new commands
+.CW wm/keyboard
+and
+.CW wm/pen
+that provide soft keyboard and single-stroke gesture recognition for touch screen devices.
+.IP \(bu
+.I Gamesrv (4)
+provides a file system interface for multi-player networked games;
+.I gamesrv (2)
+provides the interface for the game-specific engines loaded on demand by the game server.
+.IP \(bu
+.CW utils/awk
+is a new directory containing the source for a version of
+.I awk
+for use in doing Inferno ports for systems that lack it (or a sufficiently recent version), including Windows.
+It is not currently made automatically for any system.
+It is covered by its own licence; see the
+.CW README
+and
+.CW NOTICE
+files in that directory.
+.SH
+.I "Limbo compiler"
+.IP \(bu
+The compiler now adds a source file name (relative to the Inferno root) to each Dis
+file, to allow
+.I debug (2)
+and thus the debugger
+.CW wm/deb
+and other commands such as
+.I profile (1)
+and
+.I stack (1)
+to find source
+and
+.CW .sbl
+files without prompting.
+.IP \(bu
+The initialisation of large arrays avoids deep recursion, preventing a trap on Nt
+and a large stack on other platforms.
+.IP \(bu
+Overflow is avoided when sorting integers for case statements.
+.SH
+.I "Compilers and architectures"
+.IP \(bu
+The linker
+.CW 5l
+has a critical bug fix in
+.CW utils/5l/span.c
+that fixes a bug in the flushing of literal pools.
+.IP \(bu
+.CW 5coff
+has a small change to make the output conform to actual practice
+not COFF documentation.
+.SH
+.I "Hosted and Native Inferno"
+.IP \(bu
+.I Emu
+has the following fixes and improvements:
+.RS
+.IP \(bu
+Trap handling on Windows now (we hope) does all that is required
+to work on many versions, variants, updates and releases.
+.IP \(bu
+The cursor appears correctly under Windows 2000.
+.IP \(bu
+Windows
+.I emu
+passes page up, down scroll, pause, insert, delete and print
+characters through to
+.CW /dev/keyboard .
+.IP \(bu
+.CW styx.c
+prevents bad Styx messages from causing trouble.
+.IP \(bu
+.CW devenv.c
+returns
+.CW "file exists"
+if an attempt is made to create an existing name;
+it implements
+.CW ORCLOSE .
+.IP \(bu
+.CW devroot.c
+makes directories mode 555 not 777.
+.RE
+.IP \(bu
+For the native kernels only:
+.RS
+.IP \(bu
+.I Env (3)
+is now provided for native kernels.
+To add it to a kernel, change the kernel configuration file as follows:
+.RS
+.IP 1.
+Include the device driver
+.CW env
+in the
+.CW dev
+section.
+.IP 2.
+Include the support file
+.CW env
+in the
+.CW port
+section.
+.IP 3.
+Include the name
+.CW /env
+in the
+.CW root
+section.
+.LP
+To exclude it from a kernel, include the support file
+.CW noenv
+in the
+.CW port
+section.
+You should only do this if you are trying to make a small highly specialised kernel;
+general applications are likely to make more use of
+.CW /env
+now that it is there,
+eventually to replace
+.CW sysenv
+and to select locales.
+.RE
+.IP \(bu
+Common floating-point emulator code has moved from platform-specific directories to
+.CW /os/port/fpi.c
+and
+.CW /os/port/fpimem.c ,
+with corresponding changes to configuration files and
+.CW mkfiles .
+.IP \(bu
+The scheduling code in
+.CW /os/port/proc.c
+has changed to support wait-for-interrupt.
+If no process can be scheduled, the platform-specific function
+.CW "void idlehands(void)"
+is called, with interrupts
+.I off
+(unlike the function of the same name in Plan 9).
+On most platforms, it currently is an empty function defined by
+.CW #define
+in
+.CW fns.h ,
+and the scheduler effectively spins waiting for an interrupt to make a kernel process ready,
+but on the iPAQ and a few other platforms it uses the hardware-specific
+``wait for interrupt'' function, for power saving.
+.IP \(bu
+A new package
+.CW ipaq
+is available that populates
+.CW /os/ipaq
+with the preliminary Inferno port to the Compaq iPAQ.
+.IP \(bu
+.CW /os/ip
+has incorporated bug fixes and improvements from Plan 9 to
+keep the source code up to date:
+.RS
+.IP \-
+.CW /net/ndb
+has been added, to allow for future changes in IP configuration code
+.IP \-
+permissions are checked more carefully;
+.CW wstat
+is implemented
+.IP \-
+.CW Conv
+structures are now unlocked on
+.CW close
+by
+.CW devip.c
+not by each protocol's implementation;
+the
+.CW car
+lock for connect/announce no longer exists, because the conversation itself is locked
+.IP \-
+some missing
+.CW waserror
+calls have been added
+.IP \-
+ensure local port is unique across existing conversations
+.IP \-
+.CW tos
+can be set for a converstation by a
+.CW tos
+control message, and is retained during routing
+.IP \-
+.CW qdiscard
+in
+.CW qio.c
+returns the number of bytes discarded
+.IP \-
+protocol handlers
+.CW esp.c ,
+.CW gre.c ,
+.CW icmp.c ,
+.CW ip.c ,
+.CW ipifc.c ,
+.CW ipmux.c ,
+.CW rudp.c
+and
+.CW tcp.c
+have consequentially changed;
+the TCP/IP implementation most extensively;
+.CW il.c
+and
+.CW udp.c
+have not yet been realigned with Plan 9
+.IP \-
+medium drivers use the structure-member initialisation extension of Plan 9 C,
+to insulate driver source text from changes in the layout of the
+.CW Medium
+structure
+.RE
+.IP \(bu
+The SA1100 UART driver now correctly pushes input up the stack when the FIFO empties.
+.RE
+.LP
+The remaining points are common to both hosted and native Inferno:
+.IP \(bu
+.I Cons (3)
+implements the file
+.CW kprint
+to capture Inferno console messages; and a file
+.CW jit
+that can be used to set the compile-on-the-fly option dynamically or read its current state.
+.IP \(bu
+There is a new kernel function:
+.RS
+.DS
+.ft 5
+char* seprint(char *buf, char *ebuf, char *fmt, ...);
+.ft P
+.DE
+which puts a formatted result into
+.CW buf
+never writing beyond
+.CW ebuf-1
+(including the trailing null byte).
+It returns the address of the next available byte in
+.I buf .
+.RE
+.IP \(bu
+.CW kfs 's
+.CW Eexist
+error has become
+.CW Eexists
+to remove a clash with the new
+.CW Eexist
+name in
+.CW error.h
+.IP \(bu
+.CW exportfs.c
+maintains offsets in exported directories correctly.
+.IP \(bu
+The undocumented
+.CW devaudit.c
+has been removed.
+.IP \(bu
+Some Limbo profiler bugs have been fixed.
+.IP \(bu
+A race for the use of a shared semaphore has been fixed in
+.CW devprog.c .
+.IP \(bu
+.CW devprog.c
+has a new debugging event:
+.CW load
+.I filename
+corresponds to the execution of a Dis
+.CW load
+instruction.
+.IP \(bu
+.CW devdraw.c
+implements
+.CW readpixels
+from a window
+.NH 1
+Updating the software
+.LP
+You should install the updates as the host operating system user who owns the Inferno files and directories
+on your system.
+You might like to take a backup copy of the existing tree, just in case.
+Do the following to update the installation.
+.IP 1.
+Fetch the update archives required, namely
+.CW inferno.tgz ,
+.CW src.tgz ,
+.CW utils.tgz
+and any platform-specific packages required for your installation.
+If you are running Windows, for instance, you will need
+.CW Nt.tgz ;
+if running Plan 9, you will need
+.CW Plan9.tgz .
+These are gzip'd tar files containing files starting with the directory
+name
+.CW updates/20011003 .
+Unpack each in your Inferno root directory.
+For instance, you can unpack
+.CW inferno.tgz
+using the Inferno commands:
+.RS
+.P1
+cd /
+gunzip <inferno.tgz | gettar
+.P2
+The following instructions assume they are visible in the Inferno hierarchy.
+Make sure there is sufficient space in the file system holding that hierarchy.
+Each archive can be removed after unpacking, and the
+.CW updates
+directory can be removed after installation.
+.RE
+.IP 2.
+After unpacking the archives,
+(re)start
+the existing Inferno
+.I emu ;
+it will be quicker if you use the
+.CW -c1
+option to force compiled mode.
+It is best to use only the Inferno console; do not start the window system, since
+the updates will change files in the running system.
+On the other hand, it is a good idea to make the window in the host
+operating system a scrolling one, so that you can scroll back to
+see any errors.
+All following commands are run in the Inferno environment.
+.IP 3.
+Change to the directory containing the updates:
+.RS
+.P1
+cd /updates/20011003
+.P2
+.RE
+.NE 1i
+.IP 4.
+Updated installation software was included in
+.CW inferno.tgz .
+You must first unpack that installation software, as follows:
+.RS
+.P1
+sh ./unpacktools
+.P2
+.RE
+.NE 1i
+.IP 5.
+Update the installed Inferno, source and utility source directories
+using the script
+.CW applybase :
+.RS
+.P1
+sh ./applybase
+.P2
+.LP
+That script updates the
+.CW inferno ,
+.CW src
+and
+.CW utils
+packages.
+You might see warnings if you have modified any non-configuration files from the original release.
+.RE
+.IP 6.
+Update one or more platform specific files for your platform(s).
+The directories are named after the platforms:
+.CW Solaris
+for Solaris,
+.CW Plan9
+for Plan 9,
+.CW Nt
+for all Windows systems,
+and so on.
+For each
+.I platform
+that you run, do:
+.RS
+.P1
+sh ./applyplat \fIplatform\fP
+.P2
+For instance, if you use Windows, run
+.P1
+sh ./applyplat Nt
+.P2
+The iPAQ distribution is installed the same way (it is just another platform):
+.P1
+sh ./applyplat ipaq
+.P2
+which populates
+.CW /os/ipaq
+in the Inferno tree.
+.RE
+.IP 6.
+Quit
+.I emu .
+The new version of
+.I emu
+will be called
+.CW emu.new
+in the platform-specific directory
+(eg,
+.CW Solaris/sparc/bin/emu.new ).
+Rename the old
+.CW emu
+file as
+.CW emu.old ,
+then rename the new
+.CW emu.new
+as
+.CW emu
+on Plan 9 and Unix systems,
+or
+.CW emu.exe
+on Windows.
+When run, it should announce itself as
+``Inferno Third Edition (3 October 2001)''.
binary files /dev/null b/doc/20011003.pdf differ
--- /dev/null
+++ b/doc/20020628.ms
@@ -1,0 +1,1030 @@
+.TL
+Inferno 3rd Edition \- 28 June 2002 Update
+.br
+Release Notes
+.AI
+Vita Nuova
+support@vitanuova.com
+.br
+28 June 2002
+.SP 4
+.NH 1
+Base for update
+.LP
+This set of updates applies to the 18 June 2001 base.
+The installed software must therefore be that of 18 June 2001, whether installed directly,
+or the result of updating the original July 2000 release with update packages to the
+18 June 2001 level.
+This set of updates can be applied, however, whether or not the previous update
+of 3 October 2001 was installed; this package includes all those changes too.
+.NH 1
+Contents
+.LP
+This update offers the following, compared to the 3 October 2001 release.
+.LP
+The following sections provide short
+summaries of the more interesting or important changes.
+There are many more minor or cosmetic changes.
+.SH
+.I "New commands and modules"
+.IP \(bu
+.I Fc (1)
+is a floating-point calculator.
+.IP \(bu
+A new page
+.I man (6)
+describes the formatting commands used in manual pages.
+.IP \(bu
+Support for system-level memory monitoring has been made available
+as an optional component of
+.CW emu ,
+with the interface provided by a new driver
+.CW /emu/devmem.c .
+It is not compiled in by default,
+since it is relatively intrusive.
+Details of how to enable it will be provided with the applications that use it.
+.IP \(bu
+.I Strings (1)
+extracts strings from a file.
+.IP \(bu
+.CW 9export
+(see
+.I export (4))
+serves a name space to a 9P client (mainly useful for
+interacting with Third Edition Plan 9 systems at the moment).
+.IP \(bu
+.CW cdfs ,
+which was described by
+.I dossrv (4)
+but not actually shipped is now included.
+.IP \(bu
+.CW csquery ,
+described in
+.I cs (8),
+queries the connection service and prints the result.
+.IP \(bu
+.CW newer ,
+described by
+.I ftest (1),
+is a shell predicate that compares the modification times on two files.
+.IP \(bu
+.I Print (2)
+is a new module that provides an interface to directly-driven printers.
+.SH
+.I "Repairs and changes"
+.IP \(bu
+.CW cp
+has been reworked extensively; amongst other things, it can now safely traverse
+arbitrary name spaces without becoming confused by
+complex mounts.
+.IP \(bu
+.I Listen (1)
+and
+.CW dial
+both accept a
+.CW -A
+option to cause it to authenticate a connection.
+.IP \(bu
+.I Diff (1)
+compares binary files and also does not quit (during recursive diffs) when it finds
+a file it cannot open.
+.IP \(bu
+.I Ls (1)
+implements the
+.CW -u
+and
+.CW -t
+sorting operations properly.
+A new
+.CW -e
+option prints the time as a decimal integer (seconds since the system Epoch).
+.IP \(bu
+.I Sh
+regards all of `../', `./', and `#' at the front of a command name as a request to use the name as-is.
+.IP \(bu
+.I Tail
+has been changed to avoid some boundary cases.
+.IP \(bu
+.I Touch
+uses standard argument processing and returns an error exit status if it fails.
+.IP \(bu
+.I Zeros
+accepts new options
+.CW -r
+to generate random bytes
+and
+.CW -v
+to produce blocks with a given value.
+.IP \(bu
+The network games software in
+.CW /appl/games
+uses port 6660 for its signer, not the standard Inferno signer's port.
+.IP \(bu
+.I Charon :
+disguises itself as Mozilla to satisfy agent-name probes; retries fetches on error; supports multiple windows;
+detects HTML vs plain text correctly; has many Javascript fixes, including fixing a day one bug
+in operator precedence (!).
+In general, it
+has undergone extensive changes,
+particularly to the cookies and Javascript implementation.
+It also insists that it be run under the window manager
+.I wm (1).
+It can be set to plumb schemes that it does not implement internally.
+.IP \(bu
+The installation software now uses the numeric time as-is to name output packages;
+the temporary fix introduced in Ocotober of converting leading
+.CW 10
+to
+.CW A
+has been removed.
+.IP \(bu
+.CW /appl/lib/dis.b
+prints offsets from
+.CW MP
+correctly (it previously printed them
+as offsets from
+.CW FP ).
+.IP \(bu
+.CW /appl/lib/parseman.b
+accounts for enough extra
+.I troff
+commands to display
+.I man (6)
+correctly.
+.IP \(bu
+.CW /appl/lib/profile.b
+binds
+.CW #P
+only if needed.
+.IP \(bu
+.CW /appl/lib/translate.b
+.I translate (2)) (
+now computes the right hash value.
+.IP \(bu
+Several run-time checks that were missing or incomplete for array access and slicing have been added.
+.IP \(bu
+.CW lib/isrv
+no longer starts a new shell.
+.IP \(bu
+.I Wm-ftree (1)
+has several new options:
+.CW -E ,
+.CW -p
+and
+.CW -d .
+.IP \(bu
+.CW wm/rt
+now correctly updates stack size (if set).
+.IP \(bu
+.I Xd (1)
+correctly implements
+.CW -r
+to suppress repeated lines.
+.IP \(bu
+.I gettar (1)
+documents the
+.B lstar
+output format
+.IP \(bu
+.I man (6)
+describes the manual page documentation format
+.SH
+.I "Interface changes and extensions"
+.IP \(bu
+.I Security-password (2)
+provides a new entry
+.CW setpwfile
+to allow the default name
+.CW /keydb/password
+to be changed.
+.IP \(bu
+.I Dossrv (4)
+has changed extensively, to support rename and long names in FAT format correctly.
+It uses a smaller number of IO buffers.
+.IP \(bu
+.I Createsignerkey (8)
+has a completely different invocation, documented in that manual page,
+with a conventional option structure replacing a rather idiosyncratic chain
+of optional arguments.
+The old syntax is temporarily secretly still supported, but only
+for the benefit of any shell scripts that might so use it; if you have any,
+please change them to use the new syntax before the old usage finally vanishes in a later release.
+.IP \(bu
+.I Sum (1)
+documents the new
+.CW sha1sum
+command.
+.IP \(bu
+.I Bufio (2)
+returns an error if a seek fails rather than stopping the process(!).
+.IP \(bu
+.CW /lib/convcs
+has several more character sets:
+.CW koi8-r ,
+.CW windows-1250
+and
+.CW windows-1252 .
+.IP \(bu
+.I Keyring-sha (2)
+documents two new functions,
+.CW hmac_sha1
+and
+.CW hmac_md5 ,
+which are keyed versions of the corresponding secure hashing functions,
+as defined by RFC2104.
+The new definitions are in
+.CW /module/keyring.m .
+.IP \(bu
+.I Keyring-getstring (2)
+makes it clear that it does not
+.I provide
+delimited I/O but rather
+.I requires
+it (eg, as provided by
+.I ssl (3))
+for successful operation.
+.IP \(bu
+.I Security-ssl (2)
+no longer requires
+.CW #D
+to be bound into the name space (since it can only be used locally in any case).
+Consequently,
+.CW bind
+calls have been removed from several modules that used SSL.
+.IP \(bu
+.CW /appl/lib/crypt/ssl3.b
+has several critical bug fixes, allowing secure connections to work correctly in Charon;
+an important bug fix was also made to
+.CW /appl/lib/crypt/x509.b .
+.IP \(bu
+.I Imageremap
+has been changed to allow concurrent use.
+.IP \(bu
+.I Translate (6)
+and
+.CW /appl/lib/translate.b
+have changed as required to put the locale-specific dictionaries in directory
+\f(CW/locale/\fP\fIlocale\f(CW/dict\fP;
+the directory for a chosen
+.I locale
+is then normally bound onto
+.CW /locale/dict ,
+where
+.CW translate
+looks by default.
+.IP \(bu
+The documentation for
+.I button (9)
+no longer claims that
+.CW -padx
+and
+.CW -pady
+are supported options for that widget.
+.IP \(bu
+.CW sys.m
+has some new constants defined for use by a later Styx revision.
+.SH
+.I "Tk changes and extensions"
+.IP \(bu
+The canvas code provides extensions to Tk:
+.CW "grab set tag" ,
+.CW "grab release tag" ,
+and
+.CW "grab ifunset tag" .
+See
+.I canvas (9)
+for details.
+.IP \(bu
+Also in canvases, object-specific hit tests have been added, rather than using a bounding box
+in most cases.
+.IP \(bu
+Borderwidth defaults to zero in the entry widget.
+.IP \(bu
+Tk multiplexes the cursor amongst top-level windows.
+.IP \(bu
+Text and other items selected use foreground/background colours
+.SH
+.I "Limbo compiler"
+.IP \(bu
+Constant tuple and adt values can be used as values in
+.CW con
+constant declarations.
+.IP \(bu
+In an array value, the use of reference values for different
+.CW pick
+alternatives of the same adt no longer draws a diagnostic
+but causes the array value to be an array of
+.CW ref
+to the adt, not a particular pick alternative.
+.IP \(bu
+The C language stub declarations support
+.CW pick
+adts.
+.IP \(bu
+The alignment of
+.CW big
+and
+.CW real
+is now correct in C stubs.
+.IP \(bu
+The string escape
+.CW \ef
+is form-feed (to simplify translation of C programs).
+.SH
+.I "Compilers and utilities"
+.IP \(bu
+.I Iar 's
+source directory has been renamed from
+.CW ar
+to
+.CW iar .
+.IP \(bu
+.CW mk
+understands the long-name table in Windows' archive files, preventing
+spurious out-of-date status and other confusing results in builds.
+.IP \(bu
+.CW sqz
+and
+.CW zqs
+can compress larger ARM and PowerPC executables.
+.IP \(bu
+.CW kprof
+uses a table now provided by
+.CW /dev/kprof
+to provide profiling results to the resolution selected by a given platform.
+.SH
+.I "Hosted and Native Inferno"
+.LP
+Changes common to hosted and native kernels:
+.IP \(bu
+The
+.CW HOSTMODEL
+and
+.CW TARGMODEL
+for Plan 9 are now
+.CW Plan9
+not, rather confusingly,
+.CW Inferno .
+A good few source files have been renamed accordingly.
+.IP \(bu
+The memory allocation functions have been modified slightly to support the addition of
+memory monitoring and profiling.
+Some functions have also been added to the C library supporting
+.I emu
+and the kernels,
+with an eye to starting the revision of Styx, based on the current 9P2000.
+Consequently, the
+include file
+.CW lib9.h
+for all platforms has been modified:
+to add new functions such as
+.CW setmalloctag ;
+to make the types of parameters to the
+.CW malloc
+calls uniform (and reflect the documentation, as it happens),
+so that sizes are always unsigned;
+to change the type of a parameter to
+.CW strchr
+and
+.CW strrchr
+from
+.CW char
+to
+.CW int ;
+to remove obsolete definitions such as
+.CW UMFILE
+and
+.CW UMDIR ;
+and to add new functions for use inside the kernels.
+Several new functions are strictly for internal use
+(and thus might change in future), and
+they have not been added to section 10.
+One exception is the new function
+.CW tokenize ,
+documented in
+.I getfields (10.2)
+and used by
+.I parsecmd (10.2).
+.I Getfields
+replaces the function called
+.CW parsefields ,
+which has been removed, and all calls to it changed to use
+.CW getfields .
+The higher aim of some of these otherwise fussy changes is
+to work towards making Inferno and Plan 9 drivers interchangeable
+(as best we can).
+.IP \(bu
+To help decouple authentication methods from identity setting, two new files
+.CW caphash
+and
+.CW capuse
+have been added to
+.CW #c
+(a temporary location for them), supported by code in
+.CW auth.c
+.CW /os/port/auth.c ). (
+Their use will soon replace the
+.CW setid
+functionality of
+.I keyring-auth .
+They will not be documented until then.
+.IP \(bu
+.CW /emu/exception.c
+and
+.CW /os/port/exception.c
+no longer trap the use of the
+.CW exit
+statement (by accident of implementation).
+.CW \(bu
+.CW /emu/dis.c
+and
+.CW /os/port/dis.c
+do not leave a process in Broken state when it
+receives an exception because a kernel memory allocation failed.
+.IP \(bu
+The JIT compilation of case statements has fixed a day one bug
+that caused a degenerate form of
+.CW case
+(with only a default arm) to be compiled incorrectly.
+.IP \(bu
+The 386 JIT will allow rescheduling, and the scheduling is finer grained on the ARM.
+.IP \(bu
+ARM code generation produces correct code for some list accesses that were previously wrong
+(the Dis operator HEADM)
+.IP \(bu
+.I Emu
+has the following changes specific to it:
+.RS
+.IP \-
+The mouse event queue in
+.CW devcon.c
+is now a circular queue without locks as in the native kernel;
+this prevents a scheduling problem under Linux.
+.IP \-
+The
+.CW READSTR
+constant defined by the native kernels is now also defined by
+.CW emu .
+.IP \-
+The function previously called
+.CW rendezvous
+is now called
+.CW erendezvous
+to avoid a type clash with a library function on Plan 9
+(its `rendezvous' function takes an unsigned long as first parameter, not
+.CW void* ).
+.CW lib9.h
+has changed accordingly where required.
+.IP \-
+.CW devcon.c
+acquires
+.CW caphash
+and
+.CW capuse .
+.IP \-
+A new file
+.CW auth.c
+must be included in every build.
+.IP \-
+Several drivers in
+.CW emu
+have been changed to use
+.RS
+.P1
+ switch((ulong)c->qid.path ...)
+.P2
+.RE
+to force 32-bit operations to be used when
+.CW path
+eventually becomes 64 bits.
+.IP \-
+Also in
+.CW emu
+the function
+.CW oserrstr
+now takes a buffer length, rather than assuming
+.CW ERRLEN .
+.IP \-
+Obsolete code for time and directory mode conversions (!) has been removed from
+.CW os-*.c .
+.IP \-
+Obsolete code for `daemonize' has been removed from
+.CW os-*.c
+and
+.CW lib9 .
+.RE
+.IP \(bu
+For the native kernels:
+.RS
+.IP \-
+.CW /os/port/devprof.c
+has been added but is not yet supported (it is not configured in to any kernel,
+so no existing kernels are affected by its presence).
+.IP \-
+.CW /os/port/devcons.c
+has
+.CW caphash
+and
+.CW capuse
+.IP \-
+Every kernel configuration file must now include
+.CW auth
+in the
+.CW port
+section to include
+.CW /os/port/auth.c .
+.RE
+...#.bp
+...#.NH 1
+...#Description by source file
+...#.LP
+...#.TS
+...#lf(CW)w(2.5i) lf(R)w(4i) .
+...#/appl/charon T{
+...#plumbs schemes that aren't built-in, if on an authorised list
+...#.br
+...#retries on error (but not POST)
+...#.br
+...#identifies itself as Mozilla to pass agent-name tests.
+...#.br
+...#bug fix: doesn't loop (exhausting memory) if a file ends with bad data.
+...#.br
+...#private version of Url
+...#.br
+...#CCI removed
+...#.br
+...#charon_code and charon_guiwm removed
+...#.br
+...#multiple windows
+...#.br
+...#detects HTML vs text correctly
+...#.br
+...#separate layout and gui display
+...#.br
+...#T}
+...#/appl/cmd/diff.b T{
+...#compare binary files as documented
+...#.br
+...#don't quit if files can't be opened
+...#.br
+...#T}
+...#/appl/cmd/strings.b T{
+...#new command
+...#.br
+...#T}
+...#/appl/cmd/sh T{
+...#../ / ./ and # starting a (command) name all cause it to be treated as absolute
+...#.br
+...#T}
+...#/appl/lib/auth.b T{
+...#allow nobody even if setid is 0 provided it appears in the algorithm list
+...#.br
+...#don't bind #D
+...#.br
+...#T}
+...#/appl/lib/createsignerkey.b T{
+...#arguments
+...#.br
+...#don't bother with random
+...#.br
+...#error status
+...#.br
+...#T}
+...#.TE
+...#.TS
+...#lf(CW)w(2.5i) lf(R)w(4i) .
+...#/appl/lib/crypt/ssl3.b T{
+...#delete session id on alert
+...#.br
+...#T}
+...#/appl/lib/ecmascript T{
+...#correct precedence for operators
+...#.br
+...#delete HTML comments
+...#.br
+...#T}
+...#/appl/lib/isrv.b T{
+...#don't start a new shell
+...#.br
+...#T}
+...#/appl/lib/login.b T{
+...#don't bind #D
+...#.br
+...#T}
+...#/appl/lib/logind.b T{
+...#don't bind #D
+...#.br
+...#don't load (unused) Random
+...#.br
+...#minor internal changes.
+...#.br
+...#T}
+...#/appl/lib/profile.b T{
+...#memory profiling
+...#.br
+...#T}
+...#/appl/lib/srv.b T{
+...#be sure to FORKFD so file descriptors don't accumulate in parent
+...#.br
+...#T}
+...#/appl/lib/ssl.b T{
+...#don't require #D to be bound since it can only be used locally
+...#.br
+...#T}
+...#/appl/lib/usb/* T{
+...#see TI925 release
+...#.br
+...#T}
+...#/appl/lib/wmlib.b T{
+...#calculate correct size of file browser (eg when full screen)
+...#.br
+...#don't mess with the cursor
+...#.br
+...#T}
+...#/appl/minicharon T{
+...#moan if no window manager
+...#.br
+...#don't trap if module not yet loaded
+...#.br
+...#T}
+...#/appl/wm/bounce.b
+...#/appl/wm/man.b
+...#/appl/wm/mand.b
+...#/appl/wm/polyhedra.b
+...#/appl/wm/wm.b T{
+...#correct window size in full screen mode
+...#.br
+...#T}
+...#/appl/wm/reversi.b T{
+...#use fittoscreen(0)
+...#.br
+...#T}
+...#/appl/wm/polyhedra.b T{
+...#sys->sleep(0) to yield
+...#.br
+...#T}
+...#/man/2/security-ssl T{
+...#bind not required
+...#.br
+...#conventions documented accurately
+...#.br
+...#T}
+...#/man/2/keyring-getstring T{
+...#makes it clear that it doesn't PROVIDE delimited i/o, but EXPECTS it (eg, via ssl(3))
+...#.br
+...#T}
+...#.TE
+...#.TS
+...#lf(CW)w(2.5i) lf(R)w(4i) .
+...#/crypt/jacobi.c T{
+...#add missing return statement
+...#.br
+...#T}
+...#/emu/alloc.c T{
+...#changes for monitoring
+...#.br
+...#long for size throughout
+...#.br
+...#poolrealloc, now used by malloc
+...#.br
+...#poolmsize
+...#.br
+...#malloc and realloc tagging data with pc of allocation
+...#.br
+...#ud -> lud etc
+...#.br
+...#T}
+...#/emu/chan.c T{
+...#space isn't frog, experimentally
+...#.br
+...#T}
+...#/emu/dat.h T{
+...#READSTR definition
+...#.br
+...#Rept definition (will change)
+...#.br
+...#add BusyGC
+...#.br
+...#remove support for %N
+...#.br
+...#T}
+...#/emu T{
+...#oserrstr takes buffer size (consequential changes throughout)
+...#.br
+...#no %N
+...#.br
+...#Plan 9's HOSTMODEL -> Plan9 not Inferno (!)
+...#.br
+...#msize -> hmsize in some cases
+...#.br
+...#rendezvous -> erendezvous
+...#.br
+...#T}
+...#/emu/devcon.c T{
+...#no %N, Nconv
+...#.br
+...#remove debugging memout file
+...#.br
+...#use of (ulong)c->qid.path ...
+...#.br
+...#remove logmsg calls
+...#.br
+...#T}
+...#/emu/devprof.c T{
+...#memory profiling
+...#.br
+...#T}
+...#/emu/devprog.c T{
+...#msize -> hmsize because malloc and heap addresses are different
+...#.br
+...#T}
+...#/emu/dis.c T{
+...#instrument garbage collections
+...#.br
+...#force periodic garbage collection passes when not idle (BusyGC)
+...#.br
+...#T}
+...#/emu/discall.c T{
+...#tag QLock structures with owner
+...#.br
+...#T}
+...#/emu/fns.h T{
+...#oserrstr definition
+...#.br
+...#obsolete gsleep defn removed
+...#.br
+...#T}
+...#/emu/main.c T{
+...#obsolete gsleep defn removed
+...#.br
+...#T}
+...#.TE
+...#.TS
+...#lf(CW)w(2.5i) lf(R)w(4i) .
+...#/emu/os-* T{
+...#dflag becomes simply don't enable graphics terminal (ie, save/restore tty state)
+...#.br
+...#daemonize calls removed [do it from outside]
+...#.br
+...#rendezvous -> erendezvous
+...#.br
+...#some files had obsolete timeconv and dirmodconv code, now removed
+...#.br
+...#T}
+...#/emu/proc.c T{
+...#provisional rpt code (will change, will move)
+...#.br
+...#T}
+...#/emu/vlrt-Nt.c T{
+...#use dat.h not local definitions
+...#.br
+...#T}
+...#/include/interp.h T{
+...#force HEAP_ALIGN to provide extra cell in heap header for heap profiling
+...#.br
+...#new functions: heapmonitor, hmsize
+...#.br
+...#utfnlen removed (local to interp/runt.c)
+...#.br
+...#T}
+...#/include/pool.h T{
+...#sizes are now unsigned
+...#.br
+...#poolcompact defn, new poolmsize, poolrealloc
+...#.br
+...#T}
+...#/include/tk.h T{
+...#extra state to control cursor
+...#.br
+...#T}
+...#/interp/comp-386.c T{
+...#implement and enable interpreter rescheduling when JIT enabled
+...#.br
+...#T}
+...#/interp/comp-arm.c
+...#/interp/comp-thumb.c T{
+...#change arm rescheduling check to be similar to 386
+...#.br
+...#T}
+...#/interp/gc.c T{
+...#instrument garbage collector
+...#.br
+...#add heapmonitor hook for devmem.c
+...#.br
+...#T}
+...#/interp/heap.c T{
+...#define heapmonitor hook (default: nil)
+...#.br
+...#call it at appropriate places
+...#.br
+...#change // to /* comment
+...#.br
+...#add hmsize to account for alloc.c changes
+...#.br
+...#T}
+...#/interp/keyring.c T{
+...#ensure keyring i/o functions return "failure" as intended (improves diagnostic of login/logind)
+...#.br
+...#T}
+...#/interp/math.c T{
+...#min -> minimum (to avoid clash with C macro)
+...#.br
+...#T}
+...#/interp/runt.c T{
+...#check for nil arrays in utf functions, and negative offsets
+...#.br
+...#T}
+...#.TE
+...#.TS
+...#lf(CW)w(2.5i) lf(R)w(4i) .
+...#/interp/string.c T{
+...#msize -> hmsize
+...#.br
+...#T}
+...#/interp/tk.c T{
+...#cursor switching between apps
+...#.br
+...#T}
+...#/interp/validstk.c T{
+...#msize -> hmsize
+...#.br
+...#T}
+...#/interp/xec.c T{
+...#check that slice offset isn't negative
+...#.br
+...#T}
+...#/kern T{
+...#new function utfecpy, added to directory and mkfile
+...#.br
+...#strchr, strrchr argument -> int not char
+...#.br
+...#T}
+...#/kfs T{
+...#replace DEBUG by KFSDEBUG
+...#.br
+...#remove obsolete malloc definition
+...#.br
+...#ensure HFILES includes emu dat.h and fns.h
+...#.br
+...#T}
+...#/lib9/errstr-* T{
+...#add support for buffer limit to oserrstr
+...#.br
+...#T}
+...#/lib9 T{
+...#exits argument shouldn't be const
+...#.br
+...#add utfecpy
+...#.br
+...#remove log-* and logging stuff from print.c
+...#.br
+...#remove printcol from doprint.c
+...#.br
+...#T}
+...#/man/1/gettar T{
+...#document lstar's format
+...#.br
+...#T}
+...#/man/* T{
+...#extraneous/incorrect cross-references corrected
+...#.br
+...#T}
+...#/usr/inferno/mkfile T{
+...#-Inferno -> -Plan9 for several things
+...#.br
+...#(because of HOSTMODEL/TARGMODEL change)
+...#.br
+...#mkfile-Plan9-* TARGMODEL -> Plan9 not Inferno
+...#.br
+...#T}
+...#/os/ip/ip.c T{
+...#adjust length after options stripped
+...#.br
+...#T}
+...#/os/ip/kernel.h T{
+...#strrchr char -> int
+...#.br
+...#T}
+...#/os/port/alloc.c T{
+...#int -> ulong in sizes
+...#.br
+...#same memory allocation conventions as /emu/alloc.c (re sizing, quanta)
+...#.br
+...#strip last aspects of audit
+...#.br
+...#other changes similar to /emu/alloc.c
+...#.br
+...#T}
+...#/appl/acme T{
+...#raise an non-nil exception, not empty string
+...#.br
+...#T}
+...#/appl/charon T{
+...#error when no window manager running
+...#.br
+...#cookies code being added/improved
+...#.br
+...#java script fixes/enhancements
+...#.br
+...#T}
+...#/appl/cmd/install/install.b global is default now
+...#/appl/cmd/install/wrap.b extra package name check
+...#/appl/cmd/sh code tidy up
+...#/appl/ebook ongoing changes
+...#/appl/lib/dis.b offset from fp to mp fix
+...#/appl/lib/dividers.b extra bind command to fix dividers issue
+...#/appl/lib/ecmascript.b T{
+...#parsing of '/' improved (division or start of
+...#regular expression)
+...#.br
+...#T}
+...#/appl/lib/parseman.b extra troff commands accounted for
+...#/appl/lib/profile.b bind of #P only if needed
+...#/appl/lib/translate.b hash code fix
+...#/appl/wm/c4.b evaluation function improvement
+...#/appl/wm/pen.b namechan() call moved to fix bug
+...#/appl/wm/polyhedra.b cosmetic changes
+...#/appl/wm/readmail.b slight code improvements
+...#/appl/wm/sendmail.b ditto
+...#/man/1/ebook text improvements
+...#/man/1/sh-std ditto
+...#/man/1/sum sha1sum added
+...#/man/2/keyring hmac_sha1, hmac_md5 added
+...#/man/3/kprof slight rewrite
+...#/man/4/export 9export added
+...#/man/6/translate new BUGS section comment
+...#/man/9/button padx, pady removed
+...#/man/9/canvas added grab commands
+...#/module/keyring.m added hmac routines
+...#/module/sys.m added DM* constants for future use
+...#/emu/devcon.c T{
+...#caphash and capuse files added for future
+...#development
+...#.br
+...#T}
+...#/emu/dis.c added Enomem check to broken progs
+...#/emu/exception.c added couple of extra string checks
+...#/emu/exportfs.c T{
+...#nexterror() replaced by return to give
+...#better error recovery
+...#.br
+...#T}
+...#/emu/os-Nt.c prints on console when ran out of kernel processes
+...#image/bezier.c getbezsplinepts() added
+...#interp/comp-arm.c headm bug fix, removed dodgy code
+...#interp/comp-power.c removed dodgy code
+...#interp/comp-thumb.c headm bug fix, removed dodgy code
+...#interp/keyring.c T{
+...#generalization of certain keyring functions
+...#.br
+...#addition of hmac routines
+...#.br
+...#T}
+...#interp/tk.c tkcursorcmd() removed temporarily
+...#/os/ip/devip.c ipremove() replaced by devremove()
+...#/os/ip/ip.c fragoff now a ulong
+...#/os/ip/tcp.c extra safety checks
+...#/os/port/devcons.c caphash and capuse files added
+...#/os/port/devkprof.c general improvements
+...#/os/port/dis.c Enomem check on broken progs
+...#/os/port/exception.c added couple of extra string checks
+...#/os/port/exportfs.c T{
+...#nexterror() replaced by return to give
+...#better error recovery
+...#.br
+...#check against correct file offset when reading directories
+...#.br
+...#T}
+...#/os/port/utils.c parsefields(), stroll() removed
+...#/tk/canvs.c T{
+...#extensions to tk: grab set tag, grab release tag,
+...#.br
+...#grab ifunset tag
+...#.br
+...#T}
+...#/tk/ctext.c T{
+...#text widget tag highlight fix
+...#text widget tag index fix
+...#.br
+...#T}
+...#/tk/entry.c borderwidth default to 0 in entry widget
+...#/tk/menus.c menu button release fix (off by the borderwidth bug)
+...#/tk/scrol.c T{
+...#scrollbar selection fixes (off by 1 bugs)
+...#.br
+...#autorepeat code added but disabled
+...#.br
+...#T}
+...#/tk/utils.c tkinsidepoly() function
+...#/tk/xdata.c unused globals removed
+...#/tk/* T{
+...#draw methods take extra parameter
+...#.br
+...#hit methods added
+...#.br
+...#tkcfirsttag(), tkclasttag() fixes
+...#.br
+...#tkrunpack() argument type change
+...#.br
+...#T}
+...#.TE
binary files /dev/null b/doc/20020628.pdf differ
--- /dev/null
+++ b/doc/20020715.ms
@@ -1,0 +1,1033 @@
+.TL
+Inferno 3rd Edition \- 15 July 2002 Experimental Update
+.br
+Release Notes
+.AI
+Vita Nuova
+support@vitanuova.com
+.br
+15 July 2002
+.SP 4
+.NH 1
+Base for update
+.LP
+This experimental set of updates applies to the 18 June 2001 base.
+The installed software must therefore be that of 18 June 2001, whether installed directly,
+or the result of updating the original July 2000 release with update packages to the
+18 June 2001 level.
+This set of updates can be applied, however, whether or not the previous updates
+of 3 October 2001 and 28 June 2002 were installed; this package includes all those changes too.
+.NH 1
+Contents
+.LP
+This update offers the following, compared to the 28 June 2002 update.
+.LP
+The main change is that the Plan 9 hosted implementation supports Plan9 Fourth Edition.
+This has affected the portability interface for both hosted and native software.
+That, and the introduction of `lexical names' into
+.I emu
+causes this update to be classified as `experimental'.
+.LP
+The following sections provide short
+summaries of the more interesting or important changes.
+There are many more minor or cosmetic changes.
+.SH
+.I "New commands and modules"
+.SH
+.I "Repairs and changes"
+.IP \(bu
+.CW cp
+has been reworked extensively; amongst other things, it can now safely traverse
+arbitrary name spaces without becoming confused by
+complex mounts.
+.IP \(bu
+.I Listen (1)
+and
+.CW dial
+both accept a
+.CW -A
+option to cause it to authenticate a connection.
+.IP \(bu
+.I Diff (1)
+compares binary files and also does not quit (during recursive diffs) when it finds
+a file it cannot open.
+.IP \(bu
+.I Ls (1)
+implements the
+.CW -u
+and
+.CW -t
+sorting operations properly.
+A new
+.CW -e
+option prints the time as a decimal integer (seconds since the system Epoch).
+.IP \(bu
+.I Sh
+regards all of `../', `./', and `#' at the front of a command name as a request to use the name as-is.
+.IP \(bu
+.I Tail
+has been changed to avoid some boundary cases.
+.IP \(bu
+.I Touch
+uses standard argument processing and returns an error exit status if it fails.
+.IP \(bu
+.I Zeros
+accepts new options
+.CW -r
+to generate random bytes
+and
+.CW -v
+to produce blocks with a given value.
+.IP \(bu
+The network games software in
+.CW /appl/games
+uses port 6660 for its signer, not the standard Inferno signer's port.
+.IP \(bu
+.I Charon :
+disguises itself as Mozilla to satisfy agent-name probes; retries fetches on error; supports multiple windows;
+detects HTML vs plain text correctly; has many Javascript fixes, including fixing a day one bug
+in operator precedence (!).
+In general, it
+has undergone extensive changes,
+particularly to the cookies and Javascript implementation.
+It also insists that it be run under the window manager
+.I wm (1).
+It can be set to plumb schemes that it does not implement internally.
+.IP \(bu
+The installation software now uses the numeric time as-is to name output packages;
+the temporary fix introduced in Ocotober of converting leading
+.CW 10
+to
+.CW A
+has been removed.
+.IP \(bu
+.CW /appl/lib/dis.b
+prints offsets from
+.CW MP
+correctly (it previously printed them
+as offsets from
+.CW FP ).
+.IP \(bu
+.CW /appl/lib/parseman.b
+accounts for enough extra
+.I troff
+commands to display
+.I man (6)
+correctly.
+.IP \(bu
+.CW /appl/lib/profile.b
+binds
+.CW #P
+only if needed.
+.IP \(bu
+.CW /appl/lib/translate.b
+.I translate (2)) (
+now computes the right hash value.
+.IP \(bu
+Several run-time checks that were missing or incomplete for array access and slicing have been added.
+.IP \(bu
+.CW lib/isrv
+no longer starts a new shell.
+.IP \(bu
+.I Wm-ftree (1)
+has several new options:
+.CW -E ,
+.CW -p
+and
+.CW -d .
+.IP \(bu
+.CW wm/rt
+now correctly updates stack size (if set).
+.IP \(bu
+.I Xd (1)
+correctly implements
+.CW -r
+to suppress repeated lines.
+.IP \(bu
+.I gettar (1)
+documents the
+.B lstar
+output format
+.IP \(bu
+.I man (6)
+describes the manual page documentation format
+.SH
+.I "Interface changes and extensions"
+.IP \(bu
+.I Security-password (2)
+provides a new entry
+.CW setpwfile
+to allow the default name
+.CW /keydb/password
+to be changed.
+.IP \(bu
+.I Dossrv (4)
+has changed extensively, to support rename and long names in FAT format correctly.
+It uses a smaller number of IO buffers.
+.IP \(bu
+.I Createsignerkey (8)
+has a completely different invocation, documented in that manual page,
+with a conventional option structure replacing a rather idiosyncratic chain
+of optional arguments.
+The old syntax is temporarily secretly still supported, but only
+for the benefit of any shell scripts that might so use it; if you have any,
+please change them to use the new syntax before the old usage finally vanishes in a later release.
+.IP \(bu
+.I Sum (1)
+documents the new
+.CW sha1sum
+command.
+.IP \(bu
+.I Bufio (2)
+returns an error if a seek fails rather than stopping the process(!).
+.IP \(bu
+.CW /lib/convcs
+has several more character sets:
+.CW koi8-r ,
+.CW windows-1250
+and
+.CW windows-1252 .
+.IP \(bu
+.I Keyring-sha (2)
+documents two new functions,
+.CW hmac_sha1
+and
+.CW hmac_md5 ,
+which are keyed versions of the corresponding secure hashing functions,
+as defined by RFC2104.
+The new definitions are in
+.CW /module/keyring.m .
+.IP \(bu
+.I Keyring-getstring (2)
+makes it clear that it does not
+.I provide
+delimited I/O but rather
+.I requires
+it (eg, as provided by
+.I ssl (3))
+for successful operation.
+.IP \(bu
+.I Security-ssl (2)
+no longer requires
+.CW #D
+to be bound into the name space (since it can only be used locally in any case).
+Consequently,
+.CW bind
+calls have been removed from several modules that used SSL.
+.IP \(bu
+.CW /appl/lib/crypt/ssl3.b
+has several critical bug fixes, allowing secure connections to work correctly in Charon;
+an important bug fix was also made to
+.CW /appl/lib/crypt/x509.b .
+.IP \(bu
+.I Imageremap
+has been changed to allow concurrent use.
+.IP \(bu
+.I Translate (6)
+and
+.CW /appl/lib/translate.b
+have changed as required to put the locale-specific dictionaries in directory
+\f(CW/locale/\fP\fIlocale\f(CW/dict\fP;
+the directory for a chosen
+.I locale
+is then normally bound onto
+.CW /locale/dict ,
+where
+.CW translate
+looks by default.
+.IP \(bu
+The documentation for
+.I button (9)
+no longer claims that
+.CW -padx
+and
+.CW -pady
+are supported options for that widget.
+.IP \(bu
+.CW sys.m
+has some new constants defined for use by a later Styx revision.
+.SH
+.I "Tk changes and extensions"
+.IP \(bu
+The canvas code provides extensions to Tk:
+.CW "grab set tag" ,
+.CW "grab release tag" ,
+and
+.CW "grab ifunset tag" .
+See
+.I canvas (9)
+for details.
+.IP \(bu
+Also in canvases, object-specific hit tests have been added, rather than using a bounding box
+in most cases.
+.IP \(bu
+Borderwidth defaults to zero in the entry widget.
+.IP \(bu
+Tk multiplexes the cursor amongst top-level windows.
+.IP \(bu
+Text and other items selected use foreground/background colours
+.SH
+.I "Limbo compiler"
+.IP \(bu
+Constant tuple and adt values can be used as values in
+.CW con
+constant declarations.
+.IP \(bu
+In an array value, the use of reference values for different
+.CW pick
+alternatives of the same adt no longer draws a diagnostic
+but causes the array value to be an array of
+.CW ref
+to the adt, not a particular pick alternative.
+.IP \(bu
+The C language stub declarations support
+.CW pick
+adts.
+.IP \(bu
+The alignment of
+.CW big
+and
+.CW real
+is now correct in C stubs.
+.IP \(bu
+The string escape
+.CW \ef
+is form-feed (to simplify translation of C programs).
+.SH
+.I "Compilers and utilities"
+.IP \(bu
+.I Iar 's
+source directory has been renamed from
+.CW ar
+to
+.CW iar .
+.IP \(bu
+.CW mk
+understands the long-name table in Windows' archive files, preventing
+spurious out-of-date status and other confusing results in builds.
+.IP \(bu
+.CW sqz
+and
+.CW zqs
+can compress larger ARM and PowerPC executables.
+.IP \(bu
+.CW kprof
+uses a table now provided by
+.CW /dev/kprof
+to provide profiling results to the resolution selected by a given platform.
+.SH
+.I "Hosted and Native Inferno"
+.LP
+Changes common to hosted and native kernels:
+.IP \(bu
+The
+.CW HOSTMODEL
+and
+.CW TARGMODEL
+for Plan 9 are now
+.CW Plan9
+not, rather confusingly,
+.CW Inferno .
+A good few source files have been renamed accordingly.
+.IP \(bu
+The memory allocation functions have been modified slightly to support the addition of
+memory monitoring and profiling.
+Some functions have also been added to the C library supporting
+.I emu
+and the kernels,
+with an eye to starting the revision of Styx, based on the current 9P2000.
+Consequently, the
+include file
+.CW lib9.h
+for all platforms has been modified:
+to add new functions such as
+.CW setmalloctag ;
+to make the types of parameters to the
+.CW malloc
+calls uniform (and reflect the documentation, as it happens),
+so that sizes are always unsigned;
+to change the type of a parameter to
+.CW strchr
+and
+.CW strrchr
+from
+.CW char
+to
+.CW int ;
+to remove obsolete definitions such as
+.CW UMFILE
+and
+.CW UMDIR ;
+and to add new functions for use inside the kernels.
+Several new functions are strictly for internal use
+(and thus might change in future), and
+they have not been added to section 10.
+One exception is the new function
+.CW tokenize ,
+documented in
+.I getfields (10.2)
+and used by
+.I parsecmd (10.2).
+.I Getfields
+replaces the function called
+.CW parsefields ,
+which has been removed, and all calls to it changed to use
+.CW getfields .
+The higher aim of some of these otherwise fussy changes is
+to work towards making Inferno and Plan 9 drivers interchangeable
+(as best we can).
+.IP \(bu
+To help decouple authentication methods from identity setting, two new files
+.CW caphash
+and
+.CW capuse
+have been added to
+.CW #c
+(a temporary location for them), supported by code in
+.CW auth.c
+.CW /os/port/auth.c ). (
+Their use will soon replace the
+.CW setid
+functionality of
+.I keyring-auth .
+They will not be documented until then.
+.IP \(bu
+.CW /emu/exception.c
+and
+.CW /os/port/exception.c
+no longer trap the use of the
+.CW exit
+statement (by accident of implementation).
+.CW \(bu
+.CW /emu/dis.c
+and
+.CW /os/port/dis.c
+do not leave a process in Broken state when it
+receives an exception because a kernel memory allocation failed.
+.IP \(bu
+The JIT compilation of case statements has fixed a day one bug
+that caused a degenerate form of
+.CW case
+(with only a default arm) to be compiled incorrectly.
+.IP \(bu
+The 386 JIT will allow rescheduling, and the scheduling is finer grained on the ARM.
+.IP \(bu
+ARM code generation produces correct code for some list accesses that were previously wrong
+(the Dis operator HEADM)
+.IP \(bu
+.I Emu
+has the following changes specific to it:
+.RS
+.IP \-
+The mouse event queue in
+.CW devcon.c
+is now a circular queue without locks as in the native kernel;
+this prevents a scheduling problem under Linux.
+.IP \-
+The
+.CW READSTR
+constant defined by the native kernels is now also defined by
+.CW emu .
+.IP \-
+The function previously called
+.CW rendezvous
+is now called
+.CW erendezvous
+to avoid a type clash with a library function on Plan 9
+(its `rendezvous' function takes an unsigned long as first parameter, not
+.CW void* ).
+.CW lib9.h
+has changed accordingly where required.
+.IP \-
+.CW devcon.c
+acquires
+.CW caphash
+and
+.CW capuse .
+.IP \-
+A new file
+.CW auth.c
+must be included in every build.
+.IP \-
+Several drivers in
+.CW emu
+have been changed to use
+.RS
+.P1
+ switch((ulong)c->qid.path ...)
+.P2
+.RE
+to force 32-bit operations to be used when
+.CW path
+eventually becomes 64 bits.
+.IP \-
+Also in
+.CW emu
+the function
+.CW oserrstr
+now takes a buffer length, rather than assuming
+.CW ERRLEN .
+.IP \-
+Obsolete code for time and directory mode conversions (!) has been removed from
+.CW os-*.c .
+.IP \-
+Obsolete code for `daemonize' has been removed from
+.CW os-*.c
+and
+.CW lib9 .
+.RE
+.IP \(bu
+For the native kernels:
+.RS
+.IP \-
+.CW /os/port/devprof.c
+has been added but is not yet supported (it is not configured in to any kernel,
+so no existing kernels are affected by its presence).
+.IP \-
+.CW /os/port/devcons.c
+has
+.CW caphash
+and
+.CW capuse
+.IP \-
+Every kernel configuration file must now include
+.CW auth
+in the
+.CW port
+section to include
+.CW /os/port/auth.c .
+.RE
+...#.bp
+...#.NH 1
+...#Description by source file
+...#.LP
+...#.TS
+...#lf(CW)w(2.5i) lf(R)w(4i) .
+...#/appl/charon T{
+...#plumbs schemes that aren't built-in, if on an authorised list
+...#.br
+...#retries on error (but not POST)
+...#.br
+...#identifies itself as Mozilla to pass agent-name tests.
+...#.br
+...#bug fix: doesn't loop (exhausting memory) if a file ends with bad data.
+...#.br
+...#private version of Url
+...#.br
+...#CCI removed
+...#.br
+...#charon_code and charon_guiwm removed
+...#.br
+...#multiple windows
+...#.br
+...#detects HTML vs text correctly
+...#.br
+...#separate layout and gui display
+...#.br
+...#T}
+...#/appl/cmd/diff.b T{
+...#compare binary files as documented
+...#.br
+...#don't quit if files can't be opened
+...#.br
+...#T}
+...#/appl/cmd/strings.b T{
+...#new command
+...#.br
+...#T}
+...#/appl/cmd/sh T{
+...#../ / ./ and # starting a (command) name all cause it to be treated as absolute
+...#.br
+...#T}
+...#/appl/lib/auth.b T{
+...#allow nobody even if setid is 0 provided it appears in the algorithm list
+...#.br
+...#don't bind #D
+...#.br
+...#T}
+...#/appl/lib/createsignerkey.b T{
+...#arguments
+...#.br
+...#don't bother with random
+...#.br
+...#error status
+...#.br
+...#T}
+...#.TE
+...#.TS
+...#lf(CW)w(2.5i) lf(R)w(4i) .
+...#/appl/lib/crypt/ssl3.b T{
+...#delete session id on alert
+...#.br
+...#T}
+...#/appl/lib/ecmascript T{
+...#correct precedence for operators
+...#.br
+...#delete HTML comments
+...#.br
+...#T}
+...#/appl/lib/isrv.b T{
+...#don't start a new shell
+...#.br
+...#T}
+...#/appl/lib/login.b T{
+...#don't bind #D
+...#.br
+...#T}
+...#/appl/lib/logind.b T{
+...#don't bind #D
+...#.br
+...#don't load (unused) Random
+...#.br
+...#minor internal changes.
+...#.br
+...#T}
+...#/appl/lib/profile.b T{
+...#memory profiling
+...#.br
+...#T}
+...#/appl/lib/srv.b T{
+...#be sure to FORKFD so file descriptors don't accumulate in parent
+...#.br
+...#T}
+...#/appl/lib/ssl.b T{
+...#don't require #D to be bound since it can only be used locally
+...#.br
+...#T}
+...#/appl/lib/usb/* T{
+...#see TI925 release
+...#.br
+...#T}
+...#/appl/lib/wmlib.b T{
+...#calculate correct size of file browser (eg when full screen)
+...#.br
+...#don't mess with the cursor
+...#.br
+...#T}
+...#/appl/minicharon T{
+...#moan if no window manager
+...#.br
+...#don't trap if module not yet loaded
+...#.br
+...#T}
+...#/appl/wm/bounce.b
+...#/appl/wm/man.b
+...#/appl/wm/mand.b
+...#/appl/wm/polyhedra.b
+...#/appl/wm/wm.b T{
+...#correct window size in full screen mode
+...#.br
+...#T}
+...#/appl/wm/reversi.b T{
+...#use fittoscreen(0)
+...#.br
+...#T}
+...#/appl/wm/polyhedra.b T{
+...#sys->sleep(0) to yield
+...#.br
+...#T}
+...#/man/2/security-ssl T{
+...#bind not required
+...#.br
+...#conventions documented accurately
+...#.br
+...#T}
+...#/man/2/keyring-getstring T{
+...#makes it clear that it doesn't PROVIDE delimited i/o, but EXPECTS it (eg, via ssl(3))
+...#.br
+...#T}
+...#.TE
+...#.TS
+...#lf(CW)w(2.5i) lf(R)w(4i) .
+...#/crypt/jacobi.c T{
+...#add missing return statement
+...#.br
+...#T}
+...#/emu/alloc.c T{
+...#changes for monitoring
+...#.br
+...#long for size throughout
+...#.br
+...#poolrealloc, now used by malloc
+...#.br
+...#poolmsize
+...#.br
+...#malloc and realloc tagging data with pc of allocation
+...#.br
+...#ud -> lud etc
+...#.br
+...#T}
+...#/emu/chan.c T{
+...#space isn't frog, experimentally
+...#.br
+...#T}
+...#/emu/dat.h T{
+...#READSTR definition
+...#.br
+...#Rept definition (will change)
+...#.br
+...#add BusyGC
+...#.br
+...#remove support for %N
+...#.br
+...#T}
+...#/emu T{
+...#oserrstr takes buffer size (consequential changes throughout)
+...#.br
+...#no %N
+...#.br
+...#Plan 9's HOSTMODEL -> Plan9 not Inferno (!)
+...#.br
+...#msize -> hmsize in some cases
+...#.br
+...#rendezvous -> erendezvous
+...#.br
+...#T}
+...#/emu/devcon.c T{
+...#no %N, Nconv
+...#.br
+...#remove debugging memout file
+...#.br
+...#use of (ulong)c->qid.path ...
+...#.br
+...#remove logmsg calls
+...#.br
+...#T}
+...#/emu/devprof.c T{
+...#memory profiling
+...#.br
+...#T}
+...#/emu/devprog.c T{
+...#msize -> hmsize because malloc and heap addresses are different
+...#.br
+...#T}
+...#/emu/dis.c T{
+...#instrument garbage collections
+...#.br
+...#force periodic garbage collection passes when not idle (BusyGC)
+...#.br
+...#T}
+...#/emu/discall.c T{
+...#tag QLock structures with owner
+...#.br
+...#T}
+...#/emu/fns.h T{
+...#oserrstr definition
+...#.br
+...#obsolete gsleep defn removed
+...#.br
+...#T}
+...#/emu/main.c T{
+...#obsolete gsleep defn removed
+...#.br
+...#T}
+...#.TE
+...#.TS
+...#lf(CW)w(2.5i) lf(R)w(4i) .
+...#/emu/os-* T{
+...#dflag becomes simply don't enable graphics terminal (ie, save/restore tty state)
+...#.br
+...#daemonize calls removed [do it from outside]
+...#.br
+...#rendezvous -> erendezvous
+...#.br
+...#some files had obsolete timeconv and dirmodconv code, now removed
+...#.br
+...#T}
+...#/emu/proc.c T{
+...#provisional rpt code (will change, will move)
+...#.br
+...#T}
+...#/emu/vlrt-Nt.c T{
+...#use dat.h not local definitions
+...#.br
+...#T}
+...#/include/interp.h T{
+...#force HEAP_ALIGN to provide extra cell in heap header for heap profiling
+...#.br
+...#new functions: heapmonitor, hmsize
+...#.br
+...#utfnlen removed (local to interp/runt.c)
+...#.br
+...#T}
+...#/include/pool.h T{
+...#sizes are now unsigned
+...#.br
+...#poolcompact defn, new poolmsize, poolrealloc
+...#.br
+...#T}
+...#/include/tk.h T{
+...#extra state to control cursor
+...#.br
+...#T}
+...#/interp/comp-386.c T{
+...#implement and enable interpreter rescheduling when JIT enabled
+...#.br
+...#T}
+...#/interp/comp-arm.c
+...#/interp/comp-thumb.c T{
+...#change arm rescheduling check to be similar to 386
+...#.br
+...#T}
+...#/interp/gc.c T{
+...#instrument garbage collector
+...#.br
+...#add heapmonitor hook for devmem.c
+...#.br
+...#T}
+...#/interp/heap.c T{
+...#define heapmonitor hook (default: nil)
+...#.br
+...#call it at appropriate places
+...#.br
+...#change // to /* comment
+...#.br
+...#add hmsize to account for alloc.c changes
+...#.br
+...#T}
+...#/interp/keyring.c T{
+...#ensure keyring i/o functions return "failure" as intended (improves diagnostic of login/logind)
+...#.br
+...#T}
+...#/interp/math.c T{
+...#min -> minimum (to avoid clash with C macro)
+...#.br
+...#T}
+...#/interp/runt.c T{
+...#check for nil arrays in utf functions, and negative offsets
+...#.br
+...#T}
+...#.TE
+...#.TS
+...#lf(CW)w(2.5i) lf(R)w(4i) .
+...#/interp/string.c T{
+...#msize -> hmsize
+...#.br
+...#T}
+...#/interp/tk.c T{
+...#cursor switching between apps
+...#.br
+...#T}
+...#/interp/validstk.c T{
+...#msize -> hmsize
+...#.br
+...#T}
+...#/interp/xec.c T{
+...#check that slice offset isn't negative
+...#.br
+...#T}
+...#/kern T{
+...#new function utfecpy, added to directory and mkfile
+...#.br
+...#strchr, strrchr argument -> int not char
+...#.br
+...#T}
+...#/kfs T{
+...#replace DEBUG by KFSDEBUG
+...#.br
+...#remove obsolete malloc definition
+...#.br
+...#ensure HFILES includes emu dat.h and fns.h
+...#.br
+...#T}
+...#/lib9/errstr-* T{
+...#add support for buffer limit to oserrstr
+...#.br
+...#T}
+...#/lib9 T{
+...#exits argument shouldn't be const
+...#.br
+...#add utfecpy
+...#.br
+...#remove log-* and logging stuff from print.c
+...#.br
+...#remove printcol from doprint.c
+...#.br
+...#T}
+...#/man/1/gettar T{
+...#document lstar's format
+...#.br
+...#T}
+...#/man/* T{
+...#extraneous/incorrect cross-references corrected
+...#.br
+...#T}
+...#/usr/inferno/mkfile T{
+...#-Inferno -> -Plan9 for several things
+...#.br
+...#(because of HOSTMODEL/TARGMODEL change)
+...#.br
+...#mkfile-Plan9-* TARGMODEL -> Plan9 not Inferno
+...#.br
+...#T}
+...#/os/ip/ip.c T{
+...#adjust length after options stripped
+...#.br
+...#T}
+...#/os/ip/kernel.h T{
+...#strrchr char -> int
+...#.br
+...#T}
+...#/os/port/alloc.c T{
+...#int -> ulong in sizes
+...#.br
+...#same memory allocation conventions as /emu/alloc.c (re sizing, quanta)
+...#.br
+...#strip last aspects of audit
+...#.br
+...#other changes similar to /emu/alloc.c
+...#.br
+...#T}
+...#/appl/acme T{
+...#raise an non-nil exception, not empty string
+...#.br
+...#T}
+...#/appl/charon T{
+...#error when no window manager running
+...#.br
+...#cookies code being added/improved
+...#.br
+...#java script fixes/enhancements
+...#.br
+...#T}
+...#/appl/cmd/install/install.b global is default now
+...#/appl/cmd/install/wrap.b extra package name check
+...#/appl/cmd/sh code tidy up
+...#/appl/ebook ongoing changes
+...#/appl/lib/dis.b offset from fp to mp fix
+...#/appl/lib/dividers.b extra bind command to fix dividers issue
+...#/appl/lib/ecmascript.b T{
+...#parsing of '/' improved (division or start of
+...#regular expression)
+...#.br
+...#T}
+...#/appl/lib/parseman.b extra troff commands accounted for
+...#/appl/lib/profile.b bind of #P only if needed
+...#/appl/lib/translate.b hash code fix
+...#/appl/wm/c4.b evaluation function improvement
+...#/appl/wm/pen.b namechan() call moved to fix bug
+...#/appl/wm/polyhedra.b cosmetic changes
+...#/appl/wm/readmail.b slight code improvements
+...#/appl/wm/sendmail.b ditto
+...#/man/1/ebook text improvements
+...#/man/1/sh-std ditto
+...#/man/1/sum sha1sum added
+...#/man/2/keyring hmac_sha1, hmac_md5 added
+...#/man/3/kprof slight rewrite
+...#/man/4/export 9export added
+...#/man/6/translate new BUGS section comment
+...#/man/9/button padx, pady removed
+...#/man/9/canvas added grab commands
+...#/module/keyring.m added hmac routines
+...#/module/sys.m added DM* constants for future use
+...#/emu/devcon.c T{
+...#caphash and capuse files added for future
+...#development
+...#.br
+...#T}
+...#/emu/dis.c added Enomem check to broken progs
+...#/emu/exception.c added couple of extra string checks
+...#/emu/exportfs.c T{
+...#nexterror() replaced by return to give
+...#better error recovery
+...#.br
+...#T}
+...#/emu/os-Nt.c prints on console when ran out of kernel processes
+...#image/bezier.c getbezsplinepts() added
+...#interp/comp-arm.c headm bug fix, removed dodgy code
+...#interp/comp-power.c removed dodgy code
+...#interp/comp-thumb.c headm bug fix, removed dodgy code
+...#interp/keyring.c T{
+...#generalization of certain keyring functions
+...#.br
+...#addition of hmac routines
+...#.br
+...#T}
+...#interp/tk.c tkcursorcmd() removed temporarily
+...#/os/ip/devip.c ipremove() replaced by devremove()
+...#/os/ip/ip.c fragoff now a ulong
+...#/os/ip/tcp.c extra safety checks
+...#/os/port/devcons.c caphash and capuse files added
+...#/os/port/devkprof.c general improvements
+...#/os/port/dis.c Enomem check on broken progs
+...#/os/port/exception.c added couple of extra string checks
+...#/os/port/exportfs.c T{
+...#nexterror() replaced by return to give
+...#better error recovery
+...#.br
+...#check against correct file offset when reading directories
+...#.br
+...#T}
+...#/os/port/utils.c parsefields(), stroll() removed
+...#/tk/canvs.c T{
+...#extensions to tk: grab set tag, grab release tag,
+...#.br
+...#grab ifunset tag
+...#.br
+...#T}
+...#/tk/ctext.c T{
+...#text widget tag highlight fix
+...#text widget tag index fix
+...#.br
+...#T}
+...#/tk/entry.c borderwidth default to 0 in entry widget
+...#/tk/menus.c menu button release fix (off by the borderwidth bug)
+...#/tk/scrol.c T{
+...#scrollbar selection fixes (off by 1 bugs)
+...#.br
+...#autorepeat code added but disabled
+...#.br
+...#T}
+...#/tk/utils.c tkinsidepoly() function
+...#/tk/xdata.c unused globals removed
+...#/tk/* T{
+...#draw methods take extra parameter
+...#.br
+...#hit methods added
+...#.br
+...#tkcfirsttag(), tkclasttag() fixes
+...#.br
+...#tkrunpack() argument type change
+...#.br
+...#T}
+...#.TE
+.ig
+lib9.h all changed
+Storeinc and IEEE FP parameters default in math/dtoa.c
+Fconv -> Fmt
+doprint -> vseprint
+errstr -> add int size
+icossin, icossin2 -> image.h
+with ICOSSCALE
+Plan9 hosted include files different structure:
+Dir9p1 and Qid9p1
+#define Dir Dir9p1
+Fourth Edition system call interface
+except for Dir* functions
+under ifdef Inferno4, Qid -> Qid9p1, dirstat -> v3dirstat, etc.
+and those map
+Dir.length -> vlong
+Plan9 hosted include files quite different.
+#endif
+Styx module (styx(2)), dossrv, cdfs, acme all use it
+getcallerpc-$SYSTARG-$OBJTYPE.$O
+getwd-posix.$O
+lock-*.$O
+some types long -> int, some int ->long
+all conversion functions change
+detachscreen
+null if-else body
+main should call quotefmtinstall()
+..
+pc: draw screen; screen.$O removed from mkfile
+pc/mouse.c -> pc/ps2mouse.c
+pc config files updated to new ip stack
+dbg references removed/commented out.
+ether2114x driver provided
+env added
+fault removed
+emu and port print.c
+bug in native/hosted directory reading
+lexical names
+pctl etc more efficient for non-blocking ones
+solaris sets sa_handler not sa_sigaction for sigILL
--- /dev/null
+++ b/doc/INSTALL1.ms
@@ -1,0 +1,148 @@
+.\" this is an extract of port.ms: change that too if needed
+.pl 9999
+.SH
+Installing hosted Inferno from source
+.SH
+Overview
+.PP
+Like the native kernels
+.CW emu
+relies on several auxiliary libraries (the source of which
+it often shares with the native kernels).
+Emu itself is built by the
+.CW mkfile
+in the
+.CW emu
+subdirectory containing the platform-specific source for the host platform.
+Each library has its own
+.CW mkfile ;
+the various components are made in the right order by the
+.CW mkfile
+at the root of the Inferno tree.
+The
+.CW mkfile
+for each platform will also invoke
+.CW mk
+recursively to make the appropriate libraries
+for a given configuration.
+.PP
+The Unix emu variant generally is covered by `POSIX' (with common extensions)
+but each Unix port has one file that differs considerably for each port,
+namely \f5emu/\fP\fIplatform\fP\f5/os.c\fP, the differences
+corresponding to the different ways under Unix of implementing kernel-scheduled
+threads efficiently.
+.PP
+There are working emu versions
+for
+FreeBSD/386,
+Irix/mips,
+Linux/386,
+NetBSD/386,
+MacOSX/386,
+MacOSX/power,
+Plan 9,
+Solaris/sparc,
+and Windows (NT, 2000 and Explorer plug-in).
+Each platform typically uses mechanisms specific to the host operating
+system to implement Inferno's internal thread/process structure.
+POSIX threads have often been found to be insufficient (poorly implemented)
+on some platforms, and if so are avoided.
+See
+.CW kproc
+in
+.CW emu/*/os.c .
+.PP
+Source is included for ports to HP/UX (S800 architecture),
+Solaris/386, and Unixware, in case someone wishes to take them up now,
+but we have not determined their fitness.
+.PP
+The Plan 9 hosted implementation is unusual in that it supports
+several processor types:
+.CW 386 ,
+.CW mips ,
+.CW power
+(Power PC)
+and
+.CW sparc .
+Furthermore, all versions of
+.CW emu
+can be built on any processor type, in the usual way for Plan 9.
+.PP
+Otherwise, as distributed,
+.CW emu
+for a platform can only be built when running on that platform.
+.PP
+One unusual variant makes the whole of Inferno a plug-in for Microsoft's
+Internet Explorer, giving the same environment for Inferno applications
+running in an HTML page as is provided by hosted or native Inferno.
+That is, there is not a distinct `applet' environment with special programming interfaces.
+The source for the various plug-in components is found in
+.CW /tools/plugin
+and
+.CW /usr/internet
+within the Inferno tree; they use the version of
+.I emu
+defined by the configuration file
+.CW /emu/Nt/ie .
+.SH
+Build steps
+.PP
+All the libraries and executables can be built in a tree containing only the source code.
+To do that for a supported variant of hosted Inferno, on Unix or Plan 9, do the following
+in the root of the Inferno tree:
+.nr Ci 0 +1
+.de Xx
+.IP \\n+(Ci
+..
+.Xx
+Edit
+.CW mkconfig
+to reflect your host environment,
+specifically ROOT (which must be an absolute path name), SYSHOST and OBJTYPE.
+The comments in the file should help you choose.
+.Xx
+Run
+.CW makemk.sh
+to rebuild the
+.CW mk
+command, which is used to build everything else.
+.Xx
+Set
+.CW PATH
+(or
+.CW path
+on Plan 9)
+to include the
+.CW bin
+directory for the platform, which will now contain the
+.CW mk
+binary just built.
+On Unix, export
+.CW PATH .
+.Xx
+Then
+.CW "mk nuke"
+to remove any extraneous object files.
+.Xx
+Finally,
+.CW "mk install"
+to create and install the libraries,
+.CW limbo
+compiler,
+.CW emu
+for hosted Inferno, and auxiliary commands.
+The rules do that in an order that ensures that the commands or libraries
+needed by a later stage are built and installed first.
+(Note that a plain
+.CW mk
+will not suffice, because it does not put the results in the search path.)
+.LP
+Doing something similar on Windows or Plan 9 currently requires the executable for
+.CW mk
+to be available in the search path,
+since there is no equivalent of
+.CW makemk.sh .
+Otherwise the procedure is the same.
+On Plan 9, of course, the host system's normal version of
+.CW mk
+should be adequate.
--- /dev/null
+++ b/doc/acid.ms
@@ -1,0 +1,2519 @@
+.am DS
+.ft I
+..
+.am DE
+.ft R
+..
+.ta 1i 2.3i 4.5i (optional to set tabs)
+.TL
+Acid Reference Manual
+.AU
+Phil Winterbottom
+philw@plan9.bell-labs.com
+.FS
+\l'1i'
+.br
+Previously appeared with minor differences as the
+``Acid Manual'' in
+.I "Plan 9 Programmer's Manual, Volume 2 (Second Edition)".
+.FE
+.SH
+Introduction
+.PP
+Acid is a general purpose, source level symbolic debugger.
+The debugger is built around a simple command language.
+The command language, distinct from the language of the program being debugged,
+provides a flexible user interface that allows the debugger
+interface to be customized for a specific application or architecture.
+Moreover, it provides an opportunity to write test and
+verification code independently of a program's source code.
+Acid is able to debug multiple
+processes provided they share a common set of symbols, such as the processes in
+a threaded program.
+.PP
+Like other language-based solutions, Acid presents a poor user interface but
+provides a powerful debugging tool.
+Application of Acid to hard problems is best approached by writing functions off-line
+(perhaps loading them with the
+.CW include
+function or using the support provided by
+.I acme (1)),
+rather than by trying to type intricate Acid operations
+at the interactive prompt.
+.PP
+Acid allows the execution of a program to be controlled by operating on its
+state while it is stopped and by monitoring and controlling its execution
+when it is running. Each program action that causes a change
+of execution state is reflected by the execution
+of an Acid function, which may be user defined.
+A library of default functions provides the functionality of a normal debugger.
+.PP
+On Plan 9, a process is controlled by writing messages to a control file in the
+.I proc (3)
+file system. Each control message has a corresponding Acid function, which
+sends the message to the process. These functions take a process id
+.I pid ) (
+as an
+argument. The memory and text file of the program may be manipulated using
+the indirection operators. The symbol table, including source cross reference,
+is available to an Acid program. The combination allows complex operations
+to be performed both in terms of control flow and data manipulation.
+.SH
+Input format and \f(CWwhatis\fP
+.PP
+Comments start with
+.CW //
+and continue to the end of the line.
+Input is a series of statements and expressions separated by semicolons.
+At the top level of the interpreter, the builtin function
+.CW print
+is called automatically to display the result of all expressions except function calls.
+A unary
+.CW +
+may be used as a shorthand to force the result of a function call to be printed.
+.PP
+Also at the top level, newlines are treated as semicolons
+by the parser, so semicolons are unnecessary when evaluating expressions.
+.PP
+When Acid starts, it loads the default program modules,
+enters interactive mode, and prints a prompt. In this state Acid accepts
+either function definitions or statements to be evaluated.
+In this interactive mode
+statements are evaluated immediately, while function definitions are
+stored for later invocation.
+.PP
+The
+.CW whatis
+operator can be used to report the state of identifiers known to the interpreter.
+With no argument,
+.CW whatis
+reports the name of all defined Acid functions; when supplied with an identifier
+as an argument it reports any variable, function, or type definition
+associated with the identifier.
+Because of the way the interpreter handles semicolons,
+the result of a
+.CW whatis
+statement can be returned directly to Acid without adding semicolons.
+A syntax error or interrupt returns Acid to the normal evaluation
+mode; any partially evaluated definitions are lost.
+.SH
+Using the Library Functions
+.PP
+After loading the program binary, Acid loads the portable and architecture-specific
+library functions that form the standard debugging environment.
+These files are Acid source code and are human-readable.
+The following example uses the standard debugging library to show how
+language and program interact:
+.P1
+% acid /bin/ls
+/bin/ls:mips plan 9 executable
+
+/sys/lib/acid/port
+/sys/lib/acid/mips
+acid: new()
+75721: system call _main ADD $-0x14,R29
+75721: breakpoint main+0x4 MOVW R31,0x0(R29)
+acid: bpset(ls)
+acid: cont()
+75721: breakpoint ls ADD $-0x16c8,R29
+acid: stk()
+At pc:0x0000141c:ls /sys/src/cmd/ls.c:87
+ls(s=0x0000004d,multi=0x00000000) /sys/src/cmd/ls.c:87
+ called from main+0xf4 /sys/src/cmd/ls.c:79
+main(argc=0x00000000,argv=0x7ffffff0) /sys/src/cmd/ls.c:48
+ called from _main+0x20 /sys/src/libc/mips/main9.s:10
+acid: PC
+0xc0000f60
+acid: *PC
+0x0000141c
+acid: ls
+0x0000141c
+.P2
+The function
+.CW new()
+creates a new process and stops it at the first instruction.
+This change in state is reported by a call to the
+Acid function
+.CW stopped ,
+which is called by the interpreter whenever the debugged program stops.
+.CW Stopped
+prints the status line giving the pid, the reason the program stopped
+and the address and instruction at the current PC.
+The function
+.CW bpset
+makes an entry in the breakpoint table and plants a breakpoint in memory.
+The
+.CW cont
+function continues the process, allowing it to run until some condition
+causes it to stop. In this case the program hits the breakpoint placed on
+the function
+.CW ls
+in the C program. Once again the
+.CW stopped
+routine is called to print the status of the program. The function
+.CW stk
+prints a C stack trace of the current process. It is implemented using
+a builtin Acid function that returns the stack trace as a list; the code
+that formats the information is all written in Acid.
+The Acid variable
+.CW PC
+holds the address of the
+cell where the current value of the processor register
+.CW PC
+is stored. By indirecting through
+the value of
+.CW PC
+the address where the program is stopped can be found.
+All of the processor registers are available by the same mechanism.
+.SH
+Types
+.PP
+An Acid variable has one of four types:
+.I integer ,
+.I float ,
+.I list ,
+or
+.I string .
+The type of a variable is inferred from the type of the right-hand
+side of the assignment expression which last set its value.
+Referencing a variable that has not yet
+been assigned draws a "used but not set" error. Many of the operators may
+be applied to more than
+one type; for these operators the action of the operator is determined by
+the types of its operands. The action of each operator is defined in the
+.I Expressions
+section of this manual.
+.SH
+Variables
+.PP
+Acid has three kinds of variables: variables defined by the symbol table
+of the debugged program, variables that are defined and maintained
+by the interpreter as the debugged program changes state, and variables
+defined and used by Acid programs.
+.PP
+Some examples of variables maintained by the interpreter are the register
+pointers listed by name in the Acid list variable
+.CW registers ,
+and the symbol table listed by name and contents in the Acid variable
+.CW symbols .
+.PP
+The variable
+.CW pid
+is updated by the interpreter to select the most recently created process
+or the process selected by the
+.CW setproc
+builtin function.
+.SH 1
+Formats
+.PP
+In addition to a type, variables have formats. The format is a code
+letter that determines the printing style and the effect of some of the
+operators on that variable. The format codes are derived from the format
+letters used by
+.I db (1).
+By default, symbol table variables and numeric constants
+are assigned the format code
+.CW X ,
+which specifies 32-bit hexadecimal.
+Printing a variable with this code yields the output
+.CW 0x00123456 .
+The format code of a variable may be changed from the default by using the
+builtin function
+.CW fmt .
+This function takes two arguments, an expression and a format code. After
+the expression is evaluated the new format code is attached to the result
+and forms the return value from
+.CW fmt .
+The backslash operator is a short form of
+.CW fmt .
+The format supplied by the backslash operator must be the format character
+rather than an expression.
+If the result is assigned to a variable the new format code is maintained
+in the variable. For example:
+.P1
+acid: x=10
+acid: print(x)
+0x0000000a
+acid: x = fmt(x, 'D')
+acid: print(x, fmt(x, 'X'))
+10 0x0000000a
+acid: x
+10
+acid: x\eo
+12
+.P2
+The supported format characters are:
+.RS
+.IP \f(CWo\fP
+Print two-byte integer in octal.
+.IP \f(CWO\fP
+Print four-byte integer in octal.
+.IP \f(CWq\fP
+Print two-byte integer in signed octal.
+.IP \f(CWQ\fP
+Print four-byte integer in signed octal.
+.IP \f(CWB\fP
+Print four-byte integer in binary.
+.IP \f(CWd\fP
+Print two-byte integer in signed decimal.
+.IP \f(CWD\fP
+Print four-byte integer in signed decimal.
+.IP \f(CWY\fP
+Print eight-byte integer in signed decimal.
+.IP \f(CWx\fP
+Print two-byte integer in hexadecimal.
+.IP \f(CWX\fP
+Print four-byte integer in hexadecimal.
+.IP \f(CWu\fP
+Print two-byte integer in unsigned decimal.
+.IP \f(CWU\fP
+Print four-byte integer in unsigned decimal.
+.IP \f(CWZ\fP
+Print eight-byte integer in unsigned decimal.
+.IP \f(CWf\fP
+Print single-precision floating point number.
+.IP \f(CWF\fP
+Print double-precision floating point number.
+.IP \f(CWg\fP
+Print a single precision floating point number in string format.
+.IP \f(CWG\fP
+Print a double precision floating point number in string format.
+.IP \f(CWb\fP
+Print byte in hexadecimal.
+.IP \f(CWc\fP
+Print byte as an ASCII character.
+.IP \f(CWC\fP
+Like
+.CW c ,
+with
+printable ASCII characters represented normally and
+others printed in the form \f(CW\ex\fInn\fR.
+.IP \f(CWs\fP
+Interpret the addressed bytes as UTF characters
+and print successive characters until a zero byte is reached.
+.IP \f(CWr\fP
+Print a two-byte integer as a rune.
+.IP \f(CWR\fP
+Print successive two-byte integers as runes
+until a zero rune is reached.
+.IP \f(CWY\fP
+Print successive eight-byte integers in hexadecimal.
+.IP \f(CWi\fP
+Print as machine instructions.
+.IP \f(CWI\fP
+As
+.CW i
+above, but print the machine instructions in
+an alternate form if possible:
+.CW sunsparc
+and
+.CW mipsco
+reproduce the manufacturers' syntax.
+.IP \f(CWa\fP
+Print the value in symbolic form.
+.RE
+.SH
+Complex types
+.PP
+Acid permits the definition of the layout of memory.
+The usual method is to use the
+.CW -a
+flag of the compilers to produce Acid-language descriptions of data structures (see
+.I 2c (1))
+although such definitions can be typed interactively.
+The keywords
+.CW complex ,
+.CW adt ,
+.CW aggr ,
+and
+.CW union
+are all equivalent; the compiler uses the synonyms to document the declarations.
+A complex type is described as a set of members, each containing a format letter,
+an offset in the structure, and a name. For example, the C structure
+.P1
+struct List {
+ int type;
+ struct List *next;
+};
+.P2
+is described by the Acid statement
+.P1
+complex List {
+ 'D' 0 type;
+ 'X' 4 next;
+};
+.P2
+.SH
+Scope
+.PP
+Variables are global unless they are either parameters to functions
+or are declared as
+.CW local
+in a function body. Parameters and local variables are available only in
+the body of the function in which they are instantiated.
+Variables are dynamically bound: if a function declares a local variable
+with the same name as a global variable, the global variable will be hidden
+whenever the function is executing.
+For example, if a function
+.CW f
+has a local called
+.CW main ,
+any function called below
+.CW f
+will see the local version of
+.CW main ,
+not the external symbol.
+.SH 1
+Addressing
+.PP
+Since the symbol table specifies addresses,
+to access the value of program variables
+an extra level of indirection
+is required relative to the source code.
+For consistency, the registers are maintained as pointers as well; Acid variables with the names
+of processor registers point to cells holding the saved registers.
+.PP
+The location in a file or memory image associated with
+an address is calculated from a map
+associated with the file.
+Each map contains one or more quadruples (\c
+.I t ,
+.I b ,
+.I e ,
+.I f \|),
+defining a segment named
+.I t
+(usually
+.CW text ,
+.CW data ,
+.CW regs ,
+or
+.CW fpregs )
+mapping addresses in the range
+.I b
+through
+.I e
+to the part of the file
+beginning at
+offset
+.I f .
+The memory model of a Plan 9 process assumes
+that segments are disjoint. There
+can be more than one segment of a given type (e.g., a process
+may have more than one text segment) but segments
+may not overlap.
+An address
+.I a
+is translated
+to a file address
+by finding a segment
+for which
+.I b
++
+.I a
+<
+.I e ;
+the location in the file
+is then
+.I address
++
+.I f
+\-
+.I b .
+.PP
+Usually,
+the text and initialized data of a program
+are mapped by segments called
+.CW text
+and
+.CW data .
+Since a program file does not contain bss, stack, or register data,
+these data are
+not mapped by the data segment.
+The text segment is mapped similarly in the memory image of
+a normal (i.e., non-kernel) process.
+However, the segment called
+.CW *data
+maps memory from the beginning to the end of the program's data space.
+This region contains the program's static data, the bss, the
+heap and the stack. A segment
+called
+.CW *regs
+maps the registers;
+.CW *fpregs
+maps the floating point registers (if they exist).
+.PP
+Sometimes it is useful to define a map with a single segment
+mapping the region from 0 to 0xFFFFFFFF; such a map
+allows the entire file to be examined
+without address translation. The builtin function
+.CW map
+examines and modifies Acid's map for a process.
+.SH 1
+Name Conflicts
+.PP
+Name conflicts between keywords in the Acid language, symbols in the program,
+and previously defined functions are resolved when the interpreter starts up.
+Each name is made unique by prefixing enough
+.CW $
+characters to the front of the name to make it unique. Acid reports
+a list of each name change at startup. The report looks like this:
+.P1
+/bin/sam: mips plan 9 executable
+/lib/acid/port
+/lib/acid/mips
+Symbol renames:
+ append=$append T/0xa4e40
+acid:
+.P2
+The symbol
+.CW append
+is both a keyword and a text symbol in the program. The message reports
+that the text symbol is now named
+.CW $append .
+.SH
+Expressions
+.PP
+Operators have the same
+binding and precedence as in C.
+For operators of equal precedence, expressions are evaluated from left to right.
+.SH 1
+Boolean expressions
+.PP
+If an expression is evaluated for a boolean condition the test
+performed depends on the type of the result. If the result is of
+.I integer
+or
+.I floating
+type the result is true if the value is non-zero. If the expression is a
+.I list
+the result is true if there are any members in the list.
+If the expression is a
+.I string
+the result is true if there are any characters in the string.
+.DS
+ primary-expression:
+ identifier
+ identifier \f(CW:\fP identifier
+ constant
+ \f(CW(\fP expression \f(CW)\fP
+ \f(CW{\fP elist \f(CW}\fP
+
+ elist:
+ expression
+ elist , expression
+.DE
+An identifier may be any legal Acid variable. The colon operator returns the
+address of parameters or local variables in the current stack of a program.
+For example:
+.P1
+*main:argc
+.P2
+prints the number of arguments passed into main. Local variables and parameters
+can only be referenced after the frame has been established. It may be necessary to
+step a program over the first few instructions of a breakpointed function to properly set
+the frame.
+.PP
+Constants follow the same lexical rules as C.
+A list of expressions delimited by braces forms a list constructor.
+A new list is produced by evaluating each expression when the constructor is executed.
+The empty list is formed from
+.CW {} .
+.P1
+acid: x = 10
+acid: l = { 1, x, 2\eD }
+acid: x = 20
+acid: l
+{0x00000001 , 0x0000000a , 2 }
+.P2
+.SH 1
+Lists
+.PP
+Several operators manipulate lists.
+.DS
+ list-expression:
+ primary-expression
+ \f(CWhead\fP primary-expression
+ \f(CWtail\fP primary-expression
+ \f(CWappend\fP expression \f(CW,\fP primary-expression
+ \f(CWdelete\fP expression \f(CW,\fP primary-expression
+.DE
+The
+.I primary-expression
+for
+.CW head
+and
+.CW tail
+must yield a value of type
+.I list .
+If there are no elements in the list the value of
+.CW head
+or
+.CW tail
+will be the empty list. Otherwise
+.CW head
+evaluates to the first element of the list and
+.CW tail
+evaluates to the rest.
+.P1
+acid: head {}
+{}
+acid: head {1, 2, 3, 4}
+0x00000001
+acid: tail {1, 2, 3, 4}
+{0x00000002 , 0x00000003 , 0x00000004 }
+.P2
+The first operand of
+.CW append
+and
+.CW delete
+must be an expression that yields a
+.I list .
+.CW Append
+places the result of evaluating
+.I primary-expression
+at the end of the list.
+The
+.I primary-expression
+supplied to
+.CW delete
+must evaluate to an integer;
+.CW delete
+removes the
+.I n 'th
+item from the list, where
+.I n
+is integral value of
+.I primary-expression.
+List indices are zero-based.
+.P1
+ acid: append {1, 2}, 3
+ {0x00000001 , 0x00000002 , 0x00000003 }
+ acid: delete {1, 2, 3}, 1
+ {0x00000001 , 0x00000003 }
+.P2
+.PP
+Assigning a list to a variable copies a reference to the list; if a list variable
+is copied it still points at the same list. To copy a list, the elements must
+be copied piecewise using
+.CW head
+and
+.CW append .
+.SH 1
+Operators
+.PP
+.DS
+ postfix-expression:
+ list-expression
+ postfix-expression \f(CW[\fP expression \f(CW]\fP
+ postfix-expression \f(CW(\fP argument-list \f(CW)\fP
+ postfix-expression \f(CW.\fP tag
+ postfix-expression \f(CW->\fP tag
+ postfix-expression \f(CW++\fP
+ postfix-expression \f(CW--\fP
+
+ argument-list:
+ expression
+ argument-list , expression
+.DE
+The
+.CW [
+.I expression
+.CW ]
+operator performs indexing.
+The indexing expression must result in an expression of
+.I integer
+type, say
+.I n .
+The operation depends on the type of
+.I postfix-expression .
+If the
+.I postfix-expression
+yields an
+.I integer
+it is assumed to be the base address of an array in the memory image.
+The index offsets into this array; the size of the array members is
+determined by the format associated with the
+.I postfix-expression .
+If the
+.I postfix-expression
+yields a
+.I string
+the index operator fetches the
+.I n 'th
+character
+of the string. If the index points beyond the end
+of the string, a zero is returned.
+If the
+.I postfix-expression
+yields a
+.I list
+then the indexing operation returns the
+.I n 'th
+item of the list.
+If the list contains less than
+.I n
+items the empty list
+.CW {}
+is returned.
+.PP
+The
+.CW ++
+and
+.CW --
+operators increment and decrement integer variables.
+The amount of increment or decrement depends on the format code. These postfix
+operators return the value of the variable before the increment or decrement
+has taken place.
+.DS
+ unary-expression:
+ postfix-expression
+ \f(CW++\fP unary-expression
+ \f(CW--\fP unary-expression
+
+ unary-operator: one of
+ \f(CW*\fP \f(CW@\fP \f(CW+\fP \f(CW-\fP ~ \f(CW!\fP
+.DE
+The operators
+.CW *
+and
+.CW @
+are the indirection operators.
+.CW @
+references a value from the text file of the program being debugged.
+The size of the value depends on the format code. The
+.CW *
+operator fetches a value from the memory image of a process. If either
+operator appears on the left-hand side of an assignment statement, either the file
+or memory will be written. The file can only be modified when Acid is invoked
+with the
+.CW -w
+option.
+The prefix
+.CW ++
+and
+.CW --
+operators perform the same operation as their postfix counterparts but
+return the value after the increment or decrement has been performed. Since the
+.CW ++
+and
+.CW *
+operators fetch and increment the correct amount for the specified format,
+the following function prints correct machine instructions on a machine with
+variable length instructions, such as the 68020 or 386:
+.P1
+ defn asm(addr)
+ {
+ addr = fmt(addr, 'i');
+ loop 1, 10 do
+ print(*addr++, "\en");
+ }
+.P2
+The operators
+.CW ~
+and
+.CW !
+perform bitwise and logical negation respectively. Their operands must be of
+.I integer
+type.
+.DS
+ cast-expression:
+ unary-expression
+ unary-expression \f(CW\e\fP format-char
+ \f(CW(\fP complex-name \f(CW)\fP unary-expression
+.DE
+A unary expression may be preceded by a cast. The cast has the effect of
+associating the value of
+.I unary-expression
+with a complex type structure.
+The result may then be dereferenced using the
+.CW .
+and
+.CW ->
+operators.
+.PP
+An Acid variable may be associated with a complex type
+to enable accessing the type's members:
+.P1
+acid: complex List {
+ 'D' 0 type;
+ 'X' 4 next;
+};
+acid: complex List lhead
+acid: lhead.type
+10
+acid: lhead = ((List)lhead).next
+acid: lhead.type
+-46
+.P2
+Note that the
+.CW next
+field cannot be given a complex type automatically.
+.PP
+When entered at the top level of the interpreter,
+an expression of complex type
+is treated specially.
+If the type is called
+.CW T
+and an Acid function also called
+.CW T
+exists,
+then that function will be called with the expression as its argument.
+The compiler options
+.CW -a
+and
+.CW -aa
+will generate Acid source code defining such complex types and functions; see
+.I 2c (1).
+.PP
+A
+.I unary-expression
+may be qualified with a format specifier using the
+.CW \e
+operator. This has the same effect as passing the expression to the
+.CW fmt
+builtin function.
+.DS
+ multiplicative-expression:
+ cast-expression
+ multiplicative-expression \f(CW*\fP multiplicative-expression
+ multiplicative-expression \f(CW/\fP multiplicative-expression
+ multiplicative-expression \f(CW%\fP multiplicative-expression
+.DE
+These operate on
+.I integer
+and
+.I float
+types and perform the expected operations:
+.CW *
+multiplication,
+.CW /
+division,
+.CW %
+modulus.
+.DS
+ additive-expression:
+ multiplicative-expression
+ additive-expression \f(CW+\fP multiplicative-expression
+ additive-expression \f(CW-\fP multiplicative-expression
+.DE
+These operators perform as expected for
+.I integer
+and
+.I float
+operands.
+Unlike in C,
+.CW +
+and
+.CW -
+do not scale the addition based on the format of the expression.
+This means that
+.CW i=i+1
+will always add 1 but
+.CW i++
+will add the size corresponding to the format stored with
+.CW i .
+If both operands are of either
+.I string
+or
+.I list
+type then addition is defined as concatenation.
+Adding a string and an integer is treated as concatenation
+with the Unicode character corresponding to the integer.
+Subtraction is undefined for strings and lists.
+.DS
+ shift-expression:
+ additive-expression
+ shift-expression \f(CW<<\fP additive-expression
+ shift-expression \f(CW>>\fP additive-expression
+.DE
+The
+.CW >>
+and
+.CW <<
+operators perform bitwise right and left shifts respectively. Both
+require operands of
+.I integer
+type.
+.DS
+ relational-expression:
+ relational-expression \f(CW<\fP shift-expression
+ relational-expression \f(CW>\fP shift-expression
+ relational-expression \f(CW<=\fP shift-expression
+ relational-expression \f(CW>=\fP shift-expression
+
+ equality-expression:
+ relational-expression
+ relational-expression \f(CW==\fP equality-expression
+ relational-expression \f(CW!=\fP equality-expression
+.DE
+The comparison operators are
+.CW <
+(less than),
+.CW >
+(greater than),
+.CW <=
+(less than or equal to),
+.CW >=
+(greater than or equal to),
+.CW ==
+(equal to) and
+.CW !=
+(not equal to). The result of a comparison is 0
+if the condition is false, otherwise 1. The relational operators can only be
+applied to operands of
+.I integer
+and
+.I float
+type. The equality operators apply to all types. Comparing mixed types is legal.
+Mixed integer and float compare on the integral value. Other mixtures are always unequal.
+Two lists are equal if they
+have the same number of members and a pairwise comparison of the members results
+in equality.
+.DS
+ AND-expression:
+ equality-expression
+ AND-expression \f(CW&\fP equality-expression
+
+ XOR-expression:
+ AND-expression
+ XOR-expression \f(CW^\fP AND-expression
+
+ OR-expression:
+ XOR-expression
+ OR-expression \f(CW|\fP XOR-expression
+.DE
+These operators perform bitwise logical operations and apply only to the
+.I integer
+type.
+The operators are
+.CW &
+(logical and),
+.CW ^
+(exclusive or) and
+.CW |
+(inclusive or).
+.DS
+ logical-AND-expression:
+ OR-expression
+ logical-AND-expression \f(CW&&\fP OR-expression
+
+ logical-OR-expression:
+ logical-AND-expression
+ logical-OR-expression \f(CW||\fP logical-AND-expression
+.DE
+The
+.CW &&
+operator returns 1 if both of its operands evaluate to boolean true, otherwise 0.
+The
+.CW ||
+operator returns 1 if either of its operands evaluates to boolean true,
+otherwise 0.
+.SH
+Statements
+.PP
+.DS
+ \f(CWif\fP expression \f(CWthen\fP statement \f(CWelse\fP statement
+ \f(CWif\fP expression \f(CWthen\fP statement
+.DE
+The
+.I expression
+is evaluated as a boolean. If its value is true the statement after
+the
+.CW then
+is executed, otherwise the statement after the
+.CW else
+is executed. The
+.CW else
+portion may be omitted.
+.DS
+ \f(CWwhile\fP expression \f(CWdo\fP statement
+.DE
+In a while loop, the
+.I statement
+is executed while the boolean
+.I expression
+evaluates
+true.
+.DS
+ \f(CWloop\fP startexpr, endexpr \f(CWdo\fP statement
+.DE
+The two expressions
+.I startexpr
+and
+.I endexpr
+are evaluated prior to loop entry.
+.I Statement
+is evaluated while the value of
+.I startexpr
+is less than or equal to
+.I endexpr .
+Both expressions must yield
+.I integer
+values. The value of
+.I startexpr
+is
+incremented by one for each loop iteration.
+Note that there is no explicit loop variable; the
+.I expressions
+are just values.
+.DS
+ \f(CWreturn\fP expression
+.DE
+.CW return
+terminates execution of the current function and returns to its caller.
+The value of the function is given by expression. Since
+.CW return
+requires an argument, nil-valued functions should return the empty list
+.CW {} .
+.DS
+ \f(CWlocal\fP variable
+.DE
+The
+.CW local
+statement creates a local instance of
+.I variable ,
+which exists for the duration
+of the instance of the function in which it is declared. Binding is dynamic: the local variable,
+rather than the previous value of
+.I variable ,
+is visible to called functions.
+After a return from the current function the previous value of
+.I variable
+is
+restored.
+.PP
+If Acid is interrupted, the values of all local variables are lost,
+as if the function returned.
+.DS
+ \f(CWdefn\fP function-name \f(CW(\fP parameter-list \f(CW)\fP body
+
+ parameter-list:
+ variable
+ parameter-list , variable
+
+ body:
+ \f(CW{\fP statement \f(CW}\fP
+.DE
+Functions are introduced by the
+.CW defn
+statement. The definition of parameter names suppresses any variables
+of the same name until the function returns. The body of a function is a list
+of statements enclosed by braces.
+.SH
+Code variables
+.PP
+Acid permits the delayed evaluation of a parameter to a function. The parameter
+may then be evaluated at any time with the
+.CW eval
+operator. Such parameters are called
+.I "code variables
+and are defined by prefixing their name with an asterisk in their declaration.
+.PP
+For example, this function wraps up an expression for later evaluation:
+.P1
+acid: defn code(*e) { return e; }
+acid: x = code(v+atoi("100")\eD)
+acid: print(x)
+(v+atoi("100"))\eD;
+acid: eval x
+<stdin>:5: (error) v used but not set
+acid: v=5
+acid: eval x
+105
+.P2
+.SH
+Source Code Management
+.PP
+Acid provides the means to examine source code. Source code is
+represented by lists of strings. Builtin functions provide mapping
+from address to lines and vice-versa. The default debugging environment
+has the means to load and display source files.
+.SH
+Builtin Functions
+.PP
+The Acid interpreter has a number of builtin functions, which cannot be redefined.
+These functions perform machine- or operating system-specific functions such as
+symbol table and process management.
+The following section presents a description of each builtin function.
+The notation
+.CW {}
+is used to denote the empty list, which is the default value of a function that
+does not execute a
+.CW return
+statement.
+The type and number of parameters for each function are specified in the
+description; where a parameter can be of any type it is specified as type
+.I item .
+.de Ip
+.KS
+.LP
+.tl '\f2\\$1\fP\ \ \f(CW\\$2(\f2\\$3\f(CW)\f1''\\$4'
+.IP
+..
+.de Ex
+.KE
+.KS
+.IP
+.ft CW
+.ta 4n +4n +4n +4n +4n +4n +4n +4n +4n +4n +4n +4n +4n +4n +4n +4n
+.nf
+.in +4n
+.br
+..
+.de Ee
+.fi
+.ft 1
+.br
+.KE
+..
+.\"
+.\"
+.\"
+.Ip integer access string "Check if a file can be read
+.CW Access
+returns the integer 1 if the file name in
+.I string
+can be read by the builtin functions
+.CW file ,
+.CW readfile ,
+or
+.CW include ,
+otherwise 0. A typical use of this function is to follow
+a search path looking for a source file; it is used by
+.CW findsrc .
+.Ex
+if access("main.c") then
+ return file("main.c");
+.Ee
+.\"
+.\"
+.\"
+.Ip float atof string "Convert a string to float
+.CW atof
+converts the string supplied as its argument into a floating point
+number. The function accepts strings in the same format as the C
+function of the same name. The value returned has the format code
+.CW f .
+.CW atof
+returns the value 0.0 if it is unable to perform the conversion.
+.Ex
+acid: +atof("10.4e6")
+1.04e+07
+.Ee
+.\"
+.\"
+.\"
+.Ip integer atoi string "Convert a string to an integer
+.CW atoi
+converts the argument
+.i string
+to an integer value.
+The function accepts strings in the same format as the C function of the
+same name. The value returned has the format code
+.CW D .
+.CW atoi
+returns the integer 0 if it is unable to perform a conversion.
+.Ex
+acid: +atoi("-1255")
+-1255
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP error string "Generate an interpreter error
+.CW error
+generates an error message and returns the interpreter to interactive
+mode. If an Acid program is running, it is aborted.
+Processes being debugged are not affected. The values of all local variables are lost.
+.CW error
+is commonly used to stop the debugger when some interesting condition arises
+in the debugged program.
+.Ex
+while 1 do {
+ step();
+ if *main != @main then
+ error("memory corrupted");
+}
+.Ee
+.\"
+.\"
+.\"
+.Ip list file string "Read the contents of a file into a list
+.CW file
+reads the contents of the file specified by
+.I string
+into a list.
+Each element in the list is a string corresponding to a line in the file.
+.CW file
+breaks lines at the newline character, but the newline
+characters are not returned as part each string.
+.CW file
+returns the empty list if it encounters an error opening or reading the data.
+.Ex
+acid: print(file("main.c")[0])
+#include <u.h>
+.Ee
+.\"
+.\"
+.\"
+.Ip integer filepc string "Convert source address to text address
+.CW filepc
+interprets its
+.I string
+argument as a source file address in the form of a file name and line offset.
+.CW filepc
+uses the symbol table to map the source address into a text address
+in the debugged program. The
+.I integer
+return value has the format
+.CW X .
+.CW filepc
+returns an address of -1 if the source address is invalid.
+The source file address uses the same format as
+.I acme (1).
+This function is commonly used to set breakpoints from the source text.
+.Ex
+acid: bpset(filepc("main:10"))
+acid: bptab()
+ 0x00001020 usage ADD $-0xc,R29
+.Ee
+.\"
+.\"
+.\"
+.Ip item fmt item,fmt "Set print, \f(CW@\fP and \f(CW*\fP formats
+.CW fmt
+evaluates the expression
+.I item
+and sets the format of the result to
+.I fmt .
+The format of a value determines how it will be printed and
+what kind of object will be fetched by the
+.CW *
+and
+.CW @
+operators. The
+.CW \e
+operator is a short-hand form of the
+.CW fmt
+builtin function. The
+.CW fmt
+function leaves the format of the
+.I item
+unchanged.
+.Ex
+acid: main=fmt(main, 'i') // as instructions
+acid: print(main\eX, "\et", *main)
+0x00001020 ADD $-64,R29
+.Ee
+.\"
+.\"
+.\"
+.Ip list fnbound integer "Find start and end address of a function
+.CW fnbound
+interprets its
+.I integer
+argument as an address in the text of the debugged program.
+.CW fnbound
+returns a list containing two integers corresponding to
+the start and end addresses of the function containing the supplied address.
+If the
+.I integer
+address is not in the text segment of the program then the empty list is returned.
+.CW fnbound
+is used by
+.CW next
+to detect stepping into new functions.
+.Ex
+acid: print(fnbound(main))
+{0x00001050, 0x000014b8}
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP follow integer "Compute follow set
+The follow set is defined as the set of program counter values that could result
+from executing an instruction.
+.CW follow
+interprets its
+.I integer
+argument as a text address, decodes the instruction at
+that address and, with the current register set, builds a list of possible
+next program counter values. If the instruction at the specified address
+cannot be decoded
+.CW follow
+raises an error.
+.CW follow
+is used to plant breakpoints on
+all potential paths of execution. The following code fragment
+plants breakpoints on top of all potential following instructions.
+.Ex
+lst = follow(*PC);
+while lst do
+{
+ *head lst = bpinst;
+ lst = tail lst;
+}
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP include string "Take input from a new file
+.CW include
+opens the file specified by
+.I string
+and uses its contents as command input to the interpreter.
+The interpreter restores input to its previous source when it encounters
+either an end of file or an error.
+.CW include
+can be used to incrementally load symbol table information without
+leaving the interpreter.
+.Ex
+acid: include("/sys/src/cmd/acme/syms")
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP interpret string "Take input from a string
+.CW interpret
+evaluates the
+.I string
+expression and uses its result as command input for the interpreter.
+The interpreter restores input to its previous source when it encounters
+either the end of string or an error. The
+.CW interpret
+function allows Acid programs to write Acid code for later evaluation.
+.Ex
+acid: interpret("main+10;")
+0x0000102a
+.Ee
+.\"
+.\"
+.\"
+.Ip string itoa integer "Convert integer to string
+.CW itoa
+takes an integer argument and converts it into an ASCII string
+in the
+.CW D
+format. This function is commonly used to build
+.CW rc
+command lines.
+.Ex
+acid: rc("cat /proc/"+itoa(pid)+"/segment")
+Stack 7fc00000 80000000 1
+Data 00001000 00009000 1
+Data 00009000 0000a000 1
+Bss 0000a000 0000c000 1
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP kill integer "Kill a process
+.CW kill
+writes a kill control message into the control file of the process
+specified by the
+.I integer
+pid.
+If the process was previously installed by
+.CW setproc
+it will be removed from the list of active processes.
+If the
+.I integer
+has the same value as
+.CW pid ,
+then
+.CW pid
+will be set to 0.
+To continue debugging, a new process must be selected using
+.CW setproc .
+For example, to kill all the active processes:
+.Ex
+while proclist do {
+ kill(head proclist);
+ proclist = tail proclist;
+}
+.Ee
+.\"
+.\"
+.\"
+.Ip list map list "Set or retrieve process memory map
+.CW map
+either retrieves all the mappings associated with a process or sets a single
+map entry to a new value.
+If the
+.I list
+argument is omitted then
+.CW map
+returns a list of lists. Each sublist has four values and describes a
+single region of contiguous addresses in the
+memory or file image of the debugged program. The first entry is the name of the
+mapping. If the name begins with
+.CW *
+it denotes a map into the memory of an active process.
+The second and third values specify the base and end
+address of the region and the fourth number specifies the offset in the file
+corresponding to the first location of the region.
+A map entry may be set by supplying a list in the same format as the sublist
+described above. The name of the mapping must match a region already defined
+by the current map.
+Maps are set automatically for Plan 9 processes and some kernels; they may
+need to be set by hand for other kernels and programs that run on bare hardware.
+.Ex
+acid: map({"text", _start, end, 0x30})
+.Ee
+.\"
+.\"
+.\"
+.Ip integer match item,list "Search list for matching value
+.CW match
+compares each item in
+.I list
+using the equality operator
+.CW ==
+with
+.I item .
+The
+.I item
+can be of any type. If the match succeeds the result is the integer index
+of the matching value, otherwise -1.
+.Ex
+acid: list={8,9,10,11}
+acid: print(list[match(10, list)]\eD)
+10
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP newproc string "Create a new process
+.CW newproc
+starts a new process with an argument vector constructed from
+.I string .
+The argument vector excludes the name of the program to execute and
+each argument in
+.I string
+must be space separated. A new process can accept no more
+than 512 arguments. The internal variable
+.CW pid
+is set to the pid of the newly created process. The new pid
+is also appended to the list of active processes stored in the variable
+.CW proclist .
+The new process is created then halted at the first instruction, causing
+the debugger to call
+.CW stopped .
+The library functions
+.CW new
+and
+.CW win
+should be used to start processes when using the standard debugging
+environment.
+.Ex
+acid: newproc("-l .")
+56720: system call _main ADD $-0x14,R29
+.Ee
+.\"
+.\"
+.\"
+.Ip string pcfile integer "Convert text address to source file name
+.CW pcfile
+interprets its
+.I integer
+argument as a text address in the debugged program. The address and symbol table
+are used to generate a string containing the name of the source file
+corresponding to the text address. If the address does not lie within the
+program the string
+.CW ?file?
+is returned.
+.Ex
+acid: print("Now at ", pcfile(*PC), ":", pcline(*PC))
+Now at ls.c:46
+.Ee
+.\"
+.\"
+.\"
+.Ip integer pcline integer "Convert text address to source line number
+.CW pcline
+interprets its
+.I integer
+argument as a text address in the debugged program. The address and symbol table
+are used to generate an integer containing the line number in the source file
+corresponding to the text address. If the address does not lie within the
+program the integer 0 is returned.
+.Ex
+acid: +file("main.c")[pcline(main)]
+main(int argc, char *argv[])
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP print item,item,... "Print expressions
+.CW print
+evaluates each
+.I item
+supplied in its argument list and prints it to standard output. Each
+argument will be printed according to its associated format character.
+When the interpreter is executing, output is buffered and flushed every
+5000 statements or when the interpreter returns to interactive mode.
+.CW print
+accepts a maximum of 512 arguments.
+.Ex
+acid: print(10, "decimal ", 10\eD, "octal ", 10\eo)
+0x0000000a decimal 10 octal 000000000012
+acid: print({1, 2, 3})
+{0x00000001 , 0x00000002 , 0x00000003 }
+acid: print(main, main\ea, "\et", @main\ei)
+0x00001020 main ADD $-64,R29
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP printto string,item,item,... "Print expressions to file
+.CW printto
+offers a limited form of output redirection. The first
+.I string
+argument is used as the path name of a new file to create.
+Each
+.I item
+is then evaluated and printed to the newly created file. When all items
+have been printed the file is closed.
+.CW printto
+accepts a maximum of 512 arguments.
+.Ex
+acid: printto("/env/foo", "hello")
+acid: rc("echo -n $foo")
+hello
+.Ee
+.\"
+.\"
+.\"
+.Ip string rc string "Execute a shell command
+.CW rc
+evaluates
+.I string
+to form a shell command. A new command interpreter is started
+to execute the command. The Acid interpreter blocks until the command
+completes. The return value is the empty string
+if the command succeeds, otherwise the exit status of the failed command.
+.Ex
+acid: rc("B "+itoa(-pcline(addr))+" "+pcfile(addr));
+.Ee
+.\"
+.\"
+.\"
+.Ip string readfile string "Read file contents into a string
+.CW readfile
+takes the contents of the file specified by
+.I string
+and returns its contents as a new string.
+If
+.CW readfile
+encounters a zero byte in the file, it terminates.
+If
+.CW readfile
+encounters an error opening or reading the file then the empty list
+is returned.
+.CW readfile
+can be used to read the contents of device files whose lines are not
+terminated with newline characters.
+.Ex
+acid: ""+readfile("/dev/label")
+helix
+.Ee
+.\"
+.\"
+.\"
+.Ip string reason integer "Print cause of program stoppage
+.CW reason
+uses machine-dependent information to generate a string explaining
+why a process has stopped. The
+.I integer
+argument is the value of an architecture dependent status register,
+for example
+.CW CAUSE
+on the MIPS.
+.Ex
+acid: print(reason(*CAUSE))
+system call
+.Ee
+.\"
+.\"
+.\"
+.Ip integer regexp pattern,string "Regular expression match
+.CW regexp
+matches the
+.I pattern
+string supplied as its first argument with the
+.I string
+supplied as its second.
+If the pattern matches the result is the value 1, otherwise 0.
+.Ex
+acid: print(regexp(".*bar", "foobar"))
+1
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP setproc integer "Set debugger focus
+.CW setproc
+selects the default process used for memory and control operations. It effectively
+shifts the focus of control between processes. The
+.I integer
+argument specifies the pid of the process to look at.
+The variable
+.CW pid
+is set to the pid of the selected process. If the process is being
+selected for the first time its pid is added to the list of active
+processes
+.CW proclist .
+.Ex
+acid: setproc(68382)
+acid: procs()
+>68382: Stopped at main+0x4 setproc(68382)
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP start integer "Restart execution
+.CW start
+writes a
+.CW start
+message to the control file of the process specified by the pid
+supplied as its
+.I integer
+argument.
+.CW start
+draws an error if the process is not in the
+.CW Stopped
+state.
+.Ex
+acid: start(68382)
+acid: procs()
+>68382: Running at main+0x4 setproc(68382)
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP startstop integer "Restart execution, block until stopped
+.CW startstop
+performs the same actions as a call to
+.CW start
+followed by a call to
+.CW stop .
+The
+.I integer
+argument specifies the pid of the process to control. The process
+must be in the
+.CW Stopped
+state.
+Execution is restarted, the debugger then waits for the process to
+return to the
+.CW Stopped
+state. A process will stop if a startstop message has been written to its control
+file and any of the following conditions becomes true: the process executes or returns from
+a system call, the process generates a trap or the process receives a note.
+.CW startstop
+is used to implement single stepping.
+.Ex
+acid: startstop(pid)
+75374: breakpoint ls ADD $-0x16c8,R29
+.Ee
+.\"
+.\"
+.\"
+.Ip string status integer "Return process state
+.CW status
+uses the pid supplied by its
+.I integer
+argument to generate a string describing the state of the process.
+The string corresponds to the state returned by the
+sixth column of the
+.I ps (1)
+command.
+A process must be in the
+.CW Stopped
+state to modify its memory or registers.
+.Ex
+acid: ""+status(pid)
+Stopped
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP stop integer "Wait for a process to stop
+.CW stop
+writes a
+.CW stop
+message to the control file of the process specified by the
+pid supplied as its
+.I integer
+argument.
+The interpreter blocks until the debugged process enters the
+.CW Stopped
+state.
+A process will stop if a stop message has been written to its control
+file and any of the following conditions becomes true: the process executes or returns from
+a system call, the process generates a trap, the process is scheduled or the
+process receives a note.
+.CW stop
+is used to wait for a process to halt before planting a breakpoint since Plan 9
+only allows a process's memory to be written while it is in the
+.CW Stopped
+state.
+.Ex
+defn bpset(addr) {
+ if (status(pid)!="Stopped") then {
+ print("Waiting...\en");
+ stop(pid);
+ }
+ ...
+}
+.Ee
+.\"
+.\"
+.\"
+.Ip list strace pc,sp,linkreg "Stack trace
+.CW strace
+generates a list of lists corresponding to procedures called by the debugged
+program. Each sublist describes a single stack frame in the active process.
+The first element is an
+.I integer
+of format
+.CW X
+specifying the address of the called function. The second element is the value
+of the program counter when the function was called. The third and fourth elements
+contain lists of parameter and automatic variables respectively.
+Each element of these lists
+contains a string with the name of the variable and an
+.I integer
+value of format
+.CW X
+containing the current value of the variable.
+The arguments to
+.CW strace
+are the current value of the program counter, the current value of the
+stack pointer, and the address of the link register. All three parameters
+must be integers.
+The setting of
+.I linkreg
+is architecture dependent. On the MIPS linkreg is set to the address of saved
+.CW R31 ,
+on the SPARC to the address of saved
+.CW R15 .
+For the other architectures
+.I linkreg
+is not used, but must point to valid memory.
+.Ex
+acid: print(strace(*PC, *SP, linkreg))
+{{0x0000141c, 0xc0000f74,
+{{"s", 0x0000004d}, {"multi", 0x00000000}},
+{{"db", 0x00000000}, {"fd", 0x000010a4},
+{"n", 0x00000001}, {"i", 0x00009824}}}}
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP waitstop integer "Wait for a process to stop
+.CW waitstop
+writes a waitstop message to the control file of the process specified by the
+pid supplied as its
+.I integer
+argument.
+The interpreter will remain blocked until the debugged process enters the
+.CW Stopped
+state.
+A process will stop if a waitstop message has been written to its control
+file and any of the following conditions becomes true: the process generates a trap
+or receives a note. Unlike
+.CW stop ,
+the
+.CW waitstop
+function is passive; it does not itself cause the program to stop.
+.Ex
+acid: waitstop(pid)
+75374: breakpoint ls ADD $-0x16c8,R29
+.Ee
+.\"
+.\"
+.\"
+.SH
+Library Functions
+.PP
+A standard debugging environment is provided by modules automatically
+loaded when
+Acid is started.
+These modules are located in the directory
+.CW /sys/lib/acid .
+These functions may be overridden, personalized, or added to by code defined in
+.CW $home/lib/acid .
+The implementation of these functions can be examined using the
+.CW whatis
+operator and then modified during debugging sessions.
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP Bsrc integer "Load text editor with source
+.CW Bsrc
+interprets the
+.I integer
+argument as a text address. The text address is used to produce a pathname
+and line number suitable for the external
+.CW B
+command
+of the text editor
+(eg,
+.I acme (1)).
+.CW Bsrc
+builds a shell
+command to invoke
+.CW B ,
+which either selects an existing source file or loads a new source file into
+the editor.
+The line of source corresponding to the text address is then selected.
+In the following example
+.CW stopped
+is redefined so that
+the editor
+follows and displays the source line currently being executed.
+.Ex
+defn stopped(pid) {
+ pstop(pid);
+ Bsrc(*PC);
+}
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP Fpr "" "Display double precision floating registers
+For machines equipped with floating point,
+.CW Fpr
+displays the contents of the floating point registers as double precision
+values.
+.Ex
+acid: Fpr()
+F0 0. F2 0.
+F4 0. F6 0.
+F8 0. F10 0.
+\&...
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP Ureg integer "Display contents of Ureg structure
+.CW Ureg
+interprets the integer passed as its first argument as the address of a
+kernel
+.CW Ureg
+structure. Each element of the structure is retrieved and printed.
+The size and contents of the
+.CW Ureg
+structure are architecture dependent.
+This function can be used to decode the first argument passed to a
+.I notify (2)
+function after a process has received a note.
+.Ex
+acid: Ureg(*notehandler:ur)
+ status 0x3000f000
+ pc 0x1020
+ sp 0x7ffffe00
+ cause 0x00004002
+\&...
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP acidinit "" "Interpreter startup
+.CW acidinit
+is called by the interpreter after all
+modules have been loaded at initialization time.
+It is used to set up machine specific variables and the default source path.
+.CW acidinit
+should not be called by user code.
+.KE
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP addsrcdir string "Add element to source search path
+.CW addsrcdir
+interprets its string argument as a new directory
+.CW findsrc
+should search when looking for source code files.
+.CW addsrcdir
+draws an error if the directory is already in the source search path. The search
+path may be examined by looking at the variable
+.CW srcpath .
+.Ex
+acid: rc("9fs fornax")
+acid: addsrcpath("/n/fornax/sys/src/cmd")
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP asm integer "Disassemble machine instructions
+.CW asm
+interprets its integer argument as a text address from which to disassemble
+machine instructions.
+.CW asm
+prints the instruction address in symbolic and hexadecimal form, then prints
+the instructions with addressing modes. Up to twenty instructions will
+be disassembled.
+.CW asm
+stops disassembling when it reaches the end of the current function.
+Instructions are read from the file image using the
+.CW @
+operator.
+.Ex
+acid: asm(main)
+main 0x00001020 ADD $-0x64,R29
+main+0x4 0x00001024 MOVW R31,0x0(R29)
+main+0x8 0x00001028 MOVW R1,argc+4(FP)
+main+0xc 0x0000102c MOVW $bin(SB),R1
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP bpdel integer "Delete breakpoint
+.CW bpdel
+removes a previously set breakpoint from memory.
+The
+.I integer
+supplied as its argument must be the address of a previously set breakpoint.
+The breakpoint address is deleted from the active breakpoint list
+.CW bplist ,
+then the original instruction is copied from the file image to the memory
+image so that the breakpoint is removed.
+.Ex
+acid: bpdel(main+4)
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP bpset integer "Set a breakpoint
+.CW bpset
+places a breakpoint instruction at the address specified
+by its
+.I integer
+argument, which must be in the text segment.
+.CW bpset
+draws an error if a breakpoint has already been set at the specified address.
+A list of current breakpoints is maintained in the variable
+.CW bplist .
+Unlike in
+.I db (1),
+breakpoints are left in memory even when a process is stopped, and
+the process must exist, perhaps by being
+created by either
+.CW new
+or
+.CW win ,
+in order to place a breakpoint.
+.CW Db "" (
+accepts breakpoint commands before the process is started.)
+On the
+MIPS and SPARC architectures,
+breakpoints at function entry points should be set 4 bytes into the function
+because the
+instruction scheduler may fill
+.CW JAL
+branch delay slots with the first instruction of the function.
+.Ex
+acid: bpset(main+4)
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP bptab "" "List active breakpoints
+.CW bptab
+prints a list of currently installed breakpoints. The list contains the
+breakpoint address in symbolic and hexadecimal form as well as the instruction
+the breakpoint replaced. Breakpoints are not maintained across process creation
+using
+.CW new
+and
+.CW win .
+They are maintained across a fork, but care must be taken to keep control of
+the child process.
+.Ex
+acid: bpset(ls+4)
+acid: bptab()
+ 0x00001420 ls+0x4 MOVW R31,0x0(R29)
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP casm "" "Continue disassembly
+.CW casm
+continues to disassemble instructions from where the last
+.CW asm
+or
+.CW casm
+command stopped. Like
+.CW asm ,
+this command stops disassembling at function boundaries.
+.Ex
+acid: casm()
+main+0x10 0x00001030 MOVW $0x1,R3
+main+0x14 0x00001034 MOVW R3,0x8(R29)
+main+0x18 0x00001038 MOVW $0x1,R5
+main+0x1c 0x0000103c JAL Binit(SB)
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP cont "" "Continue program execution
+.CW cont
+restarts execution of the currently active process.
+If the process is stopped on a breakpoint, the breakpoint is first removed,
+the program is single stepped, the breakpoint is replaced and the program
+is then set executing. This may cause
+.CW stopped()
+to be called twice.
+.CW cont
+causes the interpreter to block until the process enters the
+.CW Stopped
+state.
+.Ex
+acid: cont()
+95197: breakpoint ls+0x4 MOVW R31,0x0(R29)
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP dump integer,integer,string "Formatted memory dump
+.CW dump
+interprets its first argument as an address, its second argument as a
+count and its third as a format string.
+.CW dump
+fetches an object from memory at the current address and prints it according
+to the format. The address is incremented by the number of bytes specified by
+the format and the process is repeated count times. The format string is any
+combination of format characters, each preceded by an optional count.
+For each object,
+.CW dump
+prints the address in hexadecimal, a colon, the object and then a newline.
+.CW dump
+uses
+.CW mem
+to fetch each object.
+.Ex
+acid: dump(main+35, 4, "X2bi")
+0x00001043: 0x0c8fa700 108 143 lwc2 r0,0x528f(R4)
+0x0000104d: 0xa9006811 0 0 swc3 r0,0x0(R24)
+0x00001057: 0x2724e800 4 37 ADD $-0x51,R23,R31
+0x00001061: 0xa200688d 6 0 NOOP
+0x0000106b: 0x2710c000 7 0 BREAK
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP findsrc string "Use source path to load source file
+.CW findsrc
+interprets its
+.I string
+argument as a source file. Each directory in the source path is searched
+in turn for the file. If the file is found, the source text is loaded using
+.CW file
+and stored in the list of active source files called
+.CW srctext .
+The name of the file is added to the source file name list
+.CW srcfiles .
+Users are unlikely to call
+.CW findsrc
+from the command line, but may use it from scripts to preload source files
+for a debugging session. This function is used by
+.CW src
+and
+.CW line
+to locate and load source code. The default search path for the MIPS
+is
+.CW ./ ,
+.CW /sys/src/libc/port ,
+.CW /sys/src/libc/9sys ,
+.CW /sys/src/libc/mips .
+.Ex
+acid: findsrc(pcfile(main));
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP fpr "" "Display single precision floating registers
+For machines equipped with floating point,
+.CW fpr
+displays the contents of the floating point registers as single precision
+values. When the interpreter stores or manipulates floating point values
+it converts into double precision values.
+.Ex
+acid: fpr()
+F0 0. F1 0.
+F2 0. F3 0.
+F4 0. F5 0.
+\&...
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP func "" "Step while in function
+.CW func
+single steps the active process until it leaves the current function
+by either calling another function or returning to its caller.
+.CW func
+will execute a single instruction after leaving the current function.
+.Ex
+acid: func()
+95197: breakpoint ls+0x8 MOVW R1,R8
+95197: breakpoint ls+0xc MOVW R8,R1
+95197: breakpoint ls+0x10 MOVW R8,s+4(FP)
+95197: breakpoint ls+0x14 MOVW $0x2f,R5
+95197: breakpoint ls+0x18 JAL utfrrune(SB)
+95197: breakpoint utfrrune ADD $-0x18,R29
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP gpr "" "Display general purpose registers
+.CW gpr
+prints the values of the general purpose processor registers.
+.Ex
+acid: gpr()
+R1 0x00009562 R2 0x000010a4 R3 0x00005d08
+R4 0x0000000a R5 0x0000002f R6 0x00000008
+\&...
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP labstk integer "Print stack trace from label
+.CW labstk
+performs a stack trace from a Plan 9
+.I label.
+The kernel
+and C compilers store continuations in a common format. Since the
+compilers all use caller save conventions a continuation may be saved by
+storing a
+.CW PC
+and
+.CW SP
+pair. This data structure is called a label and is used by the
+C function
+.CW longjmp
+and the kernel to schedule threads and processes.
+.CW labstk
+interprets its
+.I integer
+argument as the address of a label and produces a stack trace for
+the thread of execution. The value of the function
+.CW ALEF_tid
+is a suitable argument for
+.CW labstk .
+.Ex
+acid: labstk(*mousetid)
+At pc:0x00021a70:Rendez_Sleep+0x178 rendez.l:44
+Rendez_Sleep(r=0xcd7d8,bool=0xcd7e0,t=0x0) rendez.l:5
+ called from ALEF_rcvmem+0x198 recvmem.l:45
+ALEF_rcvmem(c=0x000cd764,l=0x00000010) recvmem.l:6
+\&...
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP lstk "" "Stack trace with local variables
+.CW lstk
+produces a long format stack trace.
+The stack trace includes each function in the stack,
+where it was called from, and the value of the parameters and automatic
+variables for each function.
+.CW lstk
+displays the value rather than the address of each variable and all
+variables are assumed to be an integer in format
+.CW X .
+To print a variable in its correct format use the
+.CW :
+operator to find the address and apply the appropriate format before indirection
+with the
+.CW *
+operator. It may be necessary to single step a couple of instructions into
+a function to get a correct stack trace because the frame pointer adjustment
+instruction may get scheduled down into the body of the function.
+.Ex
+acid: lstk()
+At pc:0x00001024:main+0x4 ls.c:48
+main(argc=0x00000001,argv=0x7fffefec) ls.c:48
+ called from _main+0x20 main9.s:10
+ _argc=0x00000000
+ _args=0x00000000
+ fd=0x00000000
+ buf=0x00000000
+ i=0x00000000
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP mem integer,string "Print memory object
+.CW mem
+interprets its first
+.I integer
+argument as the address of an object to be printed according to the
+format supplied in its second
+.I string
+argument.
+The format string can be any combination of format characters, each preceded
+by an optional count.
+.Ex
+acid: mem(bdata+0x326, "2c2Xb")
+P = 0xa94bc464 0x3e5ae44d 19
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP new "" "Create new process
+.CW new
+starts a new copy of the debugged program. The new program is started
+with the program arguments set by the variable
+.CW progargs .
+The new program is stopped in the second instruction of
+.CW main .
+The breakpoint list is reinitialized.
+.CW new
+may be used several times to instantiate several copies of a program
+simultaneously. The user can rotate between the copies using
+.CW setproc .
+.Ex
+acid: progargs="-l"
+acid: new()
+60: external interrupt _main ADD $-0x14,R29
+60: breakpoint main+0x4 MOVW R31,0x0(R29)
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP next "" "Step through language statement
+.CW next
+steps through a single language level statement without tracing down
+through each statement in a called function. For each statement,
+.CW next
+prints the machine instructions executed as part of the statement. After
+the statement has executed, source lines around the current program
+counter are displayed.
+.Ex
+acid: next()
+60: breakpoint Binit+0x4 MOVW R31,0x0(R29)
+60: breakpoint Binit+0x8 MOVW f+8(FP),R4
+binit.c:93
+ 88
+ 89 int
+ 90 Binit(Biobuf *bp, int f, int mode)
+ 91 {
+>92 return Binits(bp, f, mode, bp->b, BSIZE);
+ 93 }
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP notestk integer "Stack trace after receiving a note
+.CW notestk
+interprets its
+.I integer
+argument as the address of a
+.CW Ureg
+structure passed by the kernel to a
+.I notify (2)
+function during note processing.
+.CW notestk
+uses the
+.CW PC ,
+.CW SP ,
+and link register from the
+.CW Ureg
+to print a stack trace corresponding to the point in the program where the note
+was received.
+To get a valid stack trace on the MIPS and SPARC architectures from a notify
+routine, the program must stop in a new function called from the notify routine
+so that the link register is valid and the notify routine's parameters are
+addressable.
+.Ex
+acid: notestk(*notify:ur)
+Note pc:0x00001024:main+0x4 ls.c:48
+main(argc=0x00000001,argv=0x7fffefec) ls.c:48
+ called from _main+0x20 main9.s:10
+ _argc=0x00000000
+ _args=0x00000000
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP pfl integer "Print source file and line
+.CW pfl
+interprets its argument as a text address and uses it to print
+the source file and line number corresponding to the address. The output
+has the same format as file addresses in
+.I acme (1).
+.Ex
+acid: pfl(main)
+ls.c:48
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP procs "" "Print active process list
+.CW procs
+prints a list of active process attached to the debugger. Each process
+produces a single line of output giving the pid, process state, the address
+the process is currently executing, and the
+.CW setproc
+command required to make that process current.
+The current process is marked in the first column with a
+.CW >
+character. The debugger maintains a list of processes in the variable
+.CW proclist .
+.Ex
+acid: procs()
+>62: Stopped at main+0x4 setproc(62)
+ 60: Stopped at Binit+0x8 setproc(60)
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP pstop integer "Print reason process stopped
+.CW pstop
+prints the status of the process specified by the
+.I integer
+pid supplied as its argument.
+.CW pstop
+is usually called from
+.CW stopped
+every time a process enters the
+.CW Stopped
+state.
+.Ex
+acid: pstop(62)
+0x0000003e: breakpoint main+0x4 MOVW R31,0x0(R29)
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP regs "" "Print registers
+.CW regs
+prints the contents of both the general and special purpose registers.
+.CW regs
+calls
+.CW spr
+then
+.CW gpr
+to display the contents of the registers.
+.KE
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP source "" "Summarize source data base
+.CW source
+prints the directory search path followed by a list of currently loaded
+source files. The source management functions
+.CW src
+and
+.CW findsrc
+use the search path to locate and load source files. Source files are
+loaded incrementally into a source data base during debugging. A list
+of loaded files is stored in the variable
+.CW srcfiles
+and the contents of each source file in the variable
+.CW srctext .
+.Ex
+acid: source()
+/n/bootes/sys/src/libbio/
+./
+/sys/src/libc/port/
+/sys/src/libc/9sys/
+/sys/src/libc/mips/
+ binit.c
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP spr "" "Print special purpose registers
+.CW spr
+prints the contents of the processor control and memory management
+registers. Where possible, the contents of the registers are decoded
+to provide extra information; for example the
+.CW CAUSE
+register on the MIPS is
+printed both in hexadecimal and using the
+.CW reason
+function.
+.Ex
+acid: spr()
+PC 0x00001024 main+0x4 ls.c:48
+SP 0x7fffef68 LINK 0x00006264 _main+0x28 main9.s:12
+STATUS 0x0000ff33 CAUSE 0x00000024 breakpoint
+TLBVIR 0x000000d3 BADVADR 0x00001020
+HI 0x00000004 LO 0x00001ff7
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP src integer "Print lines of source
+.CW src
+interprets its
+.I integer
+argument as a text address and uses this address to print 5 lines
+of source before and after the address. The current line is marked with a
+.CW >
+character.
+.CW src
+uses the source search path maintained by
+.CW source
+and
+.CW addsrcdir
+to locate the required source files.
+.Ex
+acid: src(*PC)
+ls.c:47
+ 42 Biobuf bin;
+ 43
+ 44 #define HUNK 50
+ 45
+ 46 void
+>47 main(int argc, char *argv[])
+ 48 {
+ 49 int i, fd;
+ 50 char buf[64];
+ 51
+ 52 Binit(&bin, 1, OWRITE);
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP step "" "Single step process
+.CW step
+causes the debugged process to execute a single machine level instruction.
+If the program is stopped on a breakpoint set by
+.CW bpset
+it is first removed, the single step executed, and the breakpoint replaced.
+.CW step
+uses
+.CW follow
+to predict the address of the program counter after the current instruction
+has been executed. A breakpoint is placed at each of these predicted addresses
+and the process is started. When the process stops the breakpoints are removed.
+.Ex
+acid: step()
+62: breakpoint main+0x8 MOVW R1,argc+4(FP)
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP stk "" "Stack trace
+.CW stk
+produces a short format stack trace. The stack trace includes each function
+in the stack, where it was called from, and the value of the parameters.
+The short format omits the values of automatic variables.
+Parameters are assumed to be integer values in the format
+.CW X ;
+to print a parameter in the correct format use the
+.CW :
+to obtain its address, apply the correct format, and use the
+.CW *
+indirection operator to find its value.
+It may be necessary to single step a couple of instructions into
+a function to get a correct stack trace because the frame pointer adjustment
+instruction may get scheduled down into the body of the function.
+.Ex
+acid: stk()
+At pc:0x00001028:main+0x8 ls.c:48
+main(argc=0x00000002,argv=0x7fffefe4) ls.c:48
+ called from _main+0x20 main9.s:10
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP stmnt "" "Execute a single statement
+.CW stmnt
+executes a single language level statement.
+.CW stmnt
+displays each machine level instruction as it is executed. When the executed
+statement is completed the source for the next statement is displayed.
+Unlike
+.CW next ,
+the
+.CW stmnt
+function will trace down through function calls.
+.Ex
+acid: stmnt()
+62: breakpoint main+0x18 MOVW R5,0xc(R29)
+62: breakpoint main+0x1c JAL Binit(SB)
+62: breakpoint Binit ADD $-0x18,R29
+binit.c:91
+ 89 int
+ 90 Binit(Biobuf *bp, int f, int mode)
+>91 {
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP stopped integer "Report status of stopped process
+.CW stopped
+is called automatically by the interpreter
+every time a process enters the
+.CW Stopped
+state, such as when it hits a breakpoint.
+The pid is passed as the
+.I integer
+argument. The default implementation just calls
+.CW pstop ,
+but the function may be changed to provide more information or perform fine control
+of execution. Note that
+.CW stopped
+should return; for example, calling
+.CW step
+in
+.CW stopped
+will recur until the interpreter runs out of stack space.
+.Ex
+acid: defn stopped(pid) {
+ if *lflag != 0 then error("lflag modified");
+ }
+acid: progargs = "-l"
+acid: new();
+acid: while 1 do step();
+<stdin>:7: (error) lflag modified
+acid: stk()
+At pc:0x00001220:main+0x200 ls.c:54
+main(argc=0x00000001,argv=0x7fffffe8) ls.c:48
+ called from _main+0x20 main9.s:10
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP symbols string "Search symbol table
+.CW symbols
+uses the regular expression supplied by
+.I string
+to search the symbol table for symbols whose name matches the
+regular expression.
+.Ex
+acid: symbols("main")
+main T 0x00001020
+_main T 0x0000623c
+.Ee
+.\"
+.\"
+.\"
+.Ip \f(CW{}\fP win "" "Start new process in a window
+.CW win
+performs exactly the same function as
+.CW new
+but uses the window system to create a new window for the debugged process.
+The variable
+.CW progargs
+supplies arguments to the new process.
+The environment variable
+.CW $8½srv
+must be set to allow the interpreter to locate the mount channel for the
+window system.
+The window is created in the top left corner of the screen and is
+400x600 pixels in size. The
+.CW win
+function may be modified to alter the geometry.
+The window system will not be able to deliver notes in the new window
+since the pid of the created process is not passed when the server is
+mounted to create a new window.
+.Ex
+acid: win()
+.Ee
binary files /dev/null b/doc/acid.pdf differ
--- /dev/null
+++ b/doc/acidpaper.ms
@@ -1,0 +1,1327 @@
+.TL
+Acid: A Debugger Built From A Language
+.AU
+.I "Phil Winterbottom"
+.AI
+.I "Lucent Technologies Inc"
+.AB
+.FS
+\l'1i'
+.br
+Originally appeared in
+.I
+Proc. of the Winter 1994 USENIX Conf.,
+.R
+pp. 211-222,
+San Francisco, CA;
+and subsequently in the
+.I "Plan 9 Programmer's Manual, Volume 2 (Second Edition)" .
+.FE
+Acid is an unusual source-level symbolic debugger for Plan 9. It is implemented
+as a language interpreter with specialized primitives that provide
+debugger support. Programs written in the language manipulate
+one or more target processes; variables in the language represent the
+symbols, state, and resources of those processes.
+This structure allows complex
+interaction between the debugger and the target program and
+provides a convenient method of parameterizing differences between
+machine architectures.
+Although some effort is required to learn
+the debugging language, the richness and flexibility of the
+debugging environment encourages new ways of reasoning about the way
+programs run and the conditions under which they fail.
+.AE
+.NH
+Introduction
+.PP
+The size and complexity
+of programs have increased in proportion to processor speed and memory but
+the interface between debugger and programmer has changed little.
+Graphical user interfaces have eased some of the tedious
+aspects of the interaction. A graphical interface is a convenient
+means for navigating through source and data structures but provides
+little benefit for process control.
+The introduction of a new concurrent language, Alef [Win93], emphasized the
+inadequacies of the existing Plan 9 [Pike90] debugger
+.I db ,
+a distant relative of
+.I adb ,
+and made it clear that a new debugger was required.
+.PP
+Current debuggers like
+.I dbx ,
+.I sdb ,
+and
+.I gdb
+are limited to answering only the questions their authors
+envisage. As a result, they supply a plethora
+of specialized commands, each attempting to anticipate
+a specific question a user may ask.
+When a debugging situation arises that is beyond the scope
+of the command set, the tool is useless.
+Further,
+it is often tedious or impossible to reproduce an anomalous state
+of the program, especially when
+the state is embedded in the program's data structures.
+.PP
+Acid applies some ideas found in CAD software used for
+hardware test and simulation.
+It is based on the notion that the state and resources of a program
+are best represented and manipulated by a language. The state and resources,
+such as memory, registers, variables, type information and source code
+are represented by variables in the language.
+Expressions provide a computation mechanism and control
+statements allow repetitive or selective interpretation based
+on the result of expression evaluation.
+The heart of the Acid debugger is an interpreter for a small typeless
+language whose operators mirror the operations
+of C and Alef, which in turn correspond well to the basic operations of
+the machine. The interpreter itself knows nothing of the underlying
+hardware; it deals with the program state and resources
+in the abstract.
+Fundamental routines to control
+processes, read files, and interface to the system are implemented
+as builtin functions available to the interpreter.
+The actual debugger functionality is coded
+in Acid; commands are implemented as Acid functions.
+.PP
+This language-based approach has several advantages.
+Most importantly, programs written in Acid, including most of the
+debugger itself, are inherently portable.
+Furthermore, Acid avoids the limitations other debuggers impose when
+debugging parallel programs. Instead of embedding a fixed
+process model in the debugger, Acid allows the
+programmer to adapt the debugger to handle an
+arbitrary process partitioning or program structure.
+The ability to
+interact dynamically with an executing process provides clear advantages
+over debuggers constrained to probe a static image.
+Finally, the Acid language is a powerful vehicle for expressing
+assertions about logic, process state, and the contents of data structures.
+When combined with dynamic interaction it allows a
+limited form of automated program verification without requiring
+modification or recompilation of the source code.
+The language is also an
+excellent vehicle for preserving a test suite for later regression testing.
+.PP
+The debugger may be customized by its users; standard
+functions may be modified or extended to suit a particular application
+or preference.
+For example, the kernel developers in our group require a
+command set supporting assembler-level debugging while the application
+programmers prefer source-level functionality.
+Although the default library is biased toward assembler-level debugging,
+it is easily modified to provide a convenient source-level interface.
+The debugger itself does not change; the user combines primitives
+and existing Acid functions in different ways to
+implement the desired interface.
+.NH
+Related Work
+.PP
+DUEL [Gol93], an extension to
+.I gdb
+[Stal91], proposes using a high level expression evaluator to solve
+some of these problems. The evaluator provides iterators to loop over data
+structures and conditionals to control evaluation of expressions.
+The author shows that complex state queries can be formulated
+by combining concise expressions but this only addresses part of the problem.
+A program is a dynamic entity; questions asked when the program is in
+a static state are meaningful only after the program has been `caught' in
+that state. The framework for manipulating the program is still as
+primitive as the underlying debugger. While DUEL provides a means to
+probe data structures it entirely neglects the most beneficial aspect
+of debugging languages: the ability to control processes. Acid is structured
+around a thread of control that passes between the interpreter and the
+target program.
+.PP
+The NeD debugger [May92] is a set of extensions to TCL [Ous90] that provide
+debugging primitives. The resulting language, NeDtcl, is used to implement
+a portable interface between a conventional debugger, pdb [May90], and
+a server that executes NeDtcl programs operating on the target program.
+Execution of the NeDtcl programs implements the debugging primitives
+that pdb expects.
+NeD is targeted at multi-process debugging across a network,
+and proves the flexibility of a language as a means of
+communication between debugging tools. Whereas NeD provides an interface
+between a conventional debugger and the process it debugs, Acid is the
+debugger itself. While NeD has some of the ideas
+found in Acid it is targeted toward a different purpose. Acid seeks to
+integrate the manipulation of a program's resources into the debugger
+while NeD provides a flexible interconnect between components of
+the debugging environment. The choice of TCL is appropriate for its use
+in NeD but is not suitable for Acid. Acid relies on the coupling of the type
+system with expression evaluation, which are the root of its design,
+to provide the debugging primitives.
+.PP
+Dalek [Ols90] is an event based language extension to gdb. State transitions
+in the target program cause events to be queued for processing by the
+debugging language.
+.PP
+Acid has many of the advantages of same process or
+.I local
+.I agent
+debuggers, like Parasight [Aral], without the need for dynamic linking or
+shared memory.
+Acid improves on the ideas of these other systems by completely integrating
+all aspects of the debugging process into the language environment. Of
+particular importance is the relationship between Acid variables,
+program symbols, source code, registers and type information. This
+integration is made possible by the design of the Acid language.
+.PP
+Interpreted languages such as Lisp and Smalltalk are able to provide
+richer debugging environments through more complete information than
+their compiled counterparts. Acid is a means to gather and represent
+similar information about compiled programs through cooperation
+with the compilation tools and library implementers.
+.NH
+Acid the Language
+.PP
+Acid is a small interpreted language targeted to its debugging task.
+It focuses on representing program state and addressing data rather than
+expressing complex computations. Program state is
+.I addressable
+from an Acid program.
+In addition to parsing and executing expressions and providing
+an architecture-independent interface to the target process,
+the interpreter supplies a mark-and-scan garbage collector
+to manage storage.
+.PP
+Every Acid session begins with the loading of the Acid libraries.
+These libraries contain functions, written in Acid, that provide
+a standard debugging environment including breakpoint management,
+stepping by instruction or statement, stack tracing, and
+access to variables, memory, and registers.
+The library contains 600 lines of Acid code and provides
+functionality similar to
+.I dbx .
+Following the loading of the system library, Acid loads
+user-specified libraries; this load sequence allows the
+user to augment or override the standard commands
+to customize the debugging environment. When all libraries
+are loaded, Acid issues an interactive prompt and begins
+evaluating expressions entered by the user. The Acid `commands'
+are actually invocations of builtin primitives or previously defined
+Acid functions. Acid evaluates each expression as it is entered and
+prints the result.
+.NH
+Types and Variables
+.PP
+Acid variables are of four basic types:
+.I integer ,
+.I string ,
+.I float ,
+and
+.I list .
+The type of a variable is inferred by the type of the right-hand side of
+an assignment expression.
+Many of the operators can be applied to more than
+one type; for these operators the action of the operator is determined
+by the type of its operands.
+For example,
+the
+.CW +
+operator adds
+.I integer
+and
+.I float
+operands, and concatenates
+.I string
+and
+.I list
+operands.
+Lists are the only complex type in Acid; there are no arrays, structures
+or pointers. Operators provide
+.CW head ,
+.CW tail ,
+.CW append
+and
+.CW delete
+operations.
+Lists can also be indexed like arrays.
+.PP
+Acid has two levels of scope: global and local.
+Function parameters and variables declared in a function body
+using the
+.CW local
+keyword are created at entry to the function and
+exist for the lifetime of a function.
+Global variables are created by assignment and need not be declared.
+All variables and functions in the program
+being debugged are entered in the Acid symbol table as global
+variables during Acid initialization.
+Conflicting variable names are resolved by prefixing enough `$' characters
+to make them unique.
+Syntactically, Acid variables and target program
+symbols are referenced identically.
+However, the variables are managed differently in the Acid
+symbol table and the user must be aware of this distinction.
+The value of an Acid variable is stored in the symbol
+table; a reference returns the value.
+The symbol table entry for a variable or function in the target
+program contains the address of that symbol in the image
+of the program. Thus, the value of a program variable is
+accessed by indirect reference through the Acid
+variable that has the same name; the value of an Acid variable is the
+address of the corresponding program variable.
+.NH
+Control Flow
+.PP
+The
+.CW while
+and
+.CW loop
+statements implement looping.
+The former
+is similar to the same statement in C.
+The latter evaluates starting and ending expressions yielding
+integers and iterates while an incrementing loop index
+is within the bounds of those expressions.
+.P1
+acid: i = 0; loop 1,5 do print(i=i+1)
+0x00000001
+0x00000002
+0x00000003
+0x00000004
+0x00000005
+acid:
+.P2
+The traditional
+.CW if-then-else
+statement implements conditional execution.
+.NH
+Addressing
+.PP
+Two indirection operators allow Acid to access values in
+the program being debugged.
+The
+.CW *
+operator fetches a value from the memory image of an
+executing process;
+the
+.CW @
+operator fetches a value from the text file of the process.
+When either operator appears on the left side of an assignment, the value
+is written rather than read.
+.PP
+The indirection operator must know the size of the object
+referenced by a variable.
+The Plan 9 compilers neglect to include this
+information in the program symbol table, so Acid cannot
+derive this information implicitly.
+Instead Acid variables have formats.
+The format is a code
+letter specifying the printing style and the effect of some of the
+operators on that variable.
+The indirection operators look at the format code to determine the
+number of bytes to read or write.
+The format codes are derived from the format letters used by
+.I db .
+By default, symbol table variables and numeric constants
+are assigned the format code
+.CW 'X'
+which specifies 32-bit hexadecimal.
+Printing such a variable yields output of the form
+.CW 0x00123456 .
+An indirect reference through the variable fetches 32 bits
+of data at the address indicated by the variable.
+Other formats specify various data types, for example
+.CW i
+an instruction,
+.CW D
+a signed 32 bit decimal,
+.CW s
+a null-terminated string.
+The
+.CW fmt
+function
+allows the user to change the format code of a variable
+to control the printing format and
+operator side effects.
+This function evaluates the expression supplied as the first
+argument, attaches the format code supplied as the second
+argument to the result and returns that value.
+If the result is assigned to a variable,
+the new format code applies to
+that variable. For convenience, Acid provides the
+.CW \e
+operator as a shorthand infix form of
+.CW fmt .
+For example:
+.P1
+acid: x=10
+acid: x // print x in hex
+0x0000000a
+acid: x = fmt(x, 'D') // make x type decimal
+acid: print(x, fmt(x, 'X'), x\eX) // print x in decimal & hex
+10 0x0000000a 0x0000000a
+acid: x // print x in decimal
+10
+acid: x\eo // print x in octal
+000000000012
+.P2
+The
+.CW ++
+and
+.CW --
+operators increment or decrement a variable by an amount
+determined by its format code. Some formats imply a non-fixed size.
+For example, the
+.CW i
+format code disassembles an instruction into a string.
+On a 68020, which has variable length instructions:
+.P1
+acid: p=main\ei // p=addr(main), type INST
+acid: loop 1,5 do print(p\eX, @p++) // disassemble 5 instr's
+0x0000222e LEA 0xffffe948(A7),A7
+0x00002232 MOVL s+0x4(A7),A2
+0x00002236 PEA 0x2f($0)
+0x0000223a MOVL A2,-(A7)
+0x0000223c BSR utfrrune
+acid:
+.P2
+Here,
+.CW main
+is the address of the function of the same name in the program under test.
+The loop retrieves the five instructions beginning at that address and
+then prints the address and the assembly language representation of each.
+Notice that the stride of the increment operator varies with the size of
+the instruction: the
+.CW MOVL
+at
+.CW 0x0000223a
+is a two byte instruction while all others are four bytes long.
+.PP
+Registers are treated as normal program variables referenced
+by their symbolic assembler language names.
+When a
+process stops, the register set is saved by the kernel
+at a known virtual address in the process memory map.
+The Acid variables associated with the registers point
+to the saved values and the
+.CW *
+indirection operator can then be used to read and write the register set.
+Since the registers are accessed via Acid variables they may
+be used in arbitrary expressions.
+.P1
+acid: PC // addr of saved PC
+0xc0000f60
+acid: *PC
+0x0000623c // contents of PC
+acid: *PC\ea
+main
+acid: *R1=10 // modify R1
+acid: asm(*PC+4) // disassemble @ PC+4
+main+0x4 0x00006240 MOVW R31,0x0(R29)
+main+0x8 0x00006244 MOVW $setR30(SB),R30
+main+0x10 0x0000624c MOVW R1,_clock(SB)
+.P2
+Here, the saved
+.CW PC
+is stored at address
+.CW 0xc0000f60 ;
+its current content is
+.CW 0x0000623c .
+The
+.CW a ' `
+format code converts this value to a string specifying
+the address as an offset beyond the nearest symbol.
+After setting the value of register
+.CW 1 ,
+the example uses the
+.CW asm
+command to disassemble a short section of code beginning
+at four bytes beyond the current value of the
+.CW PC .
+.NH
+Process Interface
+.PP
+A program executing under Acid is monitored through the
+.I proc
+file system interface provided by Plan 9.
+Textual messages written to the
+.CW ctl
+file control the execution of the process.
+For example writing
+.CW waitstop
+to the control file causes the write to block until the target
+process enters the kernel and is stopped. When the process is stopped
+the write completes. The
+.CW startstop
+message starts the target process and then does a
+.CW waitstop
+action.
+Synchronization between the debugger and the target process is determined
+by the actions of the various messages. Some operate asynchronously to the
+target process and always complete immediately, others block until the
+action completes. The asynchronous messages allow Acid to control
+several processes simultaneously.
+.PP
+The interpreter has builtin functions named after each of the control
+messages. The functions take a process id as argument.
+Any time a control message causes the program to execute instructions
+the interpreter performs two actions when the control operation has completed.
+The Acid variables pointing at the register set are fixed up to point
+at the saved registers, and then
+the user defined function
+.CW stopped
+is executed.
+The
+.CW stopped
+function may print the current address,
+line of source or instruction and return to interactive mode. Alternatively
+it may traverse a complex data structure, gather statistics and then set
+the program running again.
+.PP
+Several Acid variables are maintained by the debugger rather than the
+programmer.
+These variables allow generic Acid code to deal with the current process,
+architecture specifics or the symbol table.
+The variable
+.CW pid
+is the process id of the current process Acid is debugging.
+The variable
+.CW symbols
+contains a list of lists where each sublist contains the symbol
+name, its type and the value of the symbol.
+The variable
+.CW registers
+contains a list of the machine-specific register names. Global symbols in the target program
+can be referenced directly by name from Acid. Local variables
+are referenced using the colon operator as \f(CWfunction:variable\fP.
+.NH
+Source Level Debugging
+.PP
+Acid provides several builtin functions to manipulate source code.
+The
+.CW file
+function reads a text file, inserting each line into a list.
+The
+.CW pcfile
+and
+.CW pcline
+functions each take an address as an argument.
+The first
+returns a string containing the name of the source file
+and the second returns an integer containing the line number
+of the source line containing the instruction at the address.
+.P1
+acid: pcfile(main) // file containing main
+main.c
+acid: pcline(main) // line # of main in source
+11
+acid: file(pcfile(main))[pcline(main)] // print that line
+main(int argc, char *argv[])
+acid: src(*PC) // print statements nearby
+ 9
+ 10 void
+>11 main(int argc, char *argv[])
+ 12 {
+ 13 int a;
+.P2
+In this example, the three primitives are combined in an expression to print
+a line of source code associated with an address.
+The
+.CW src
+function prints a few lines of source
+around the address supplied as its argument. A companion routine,
+.CW Bsrc ,
+communicates with the external editor
+.CW sam .
+Given an address, it loads the corresponding source file into the editor
+and highlights the line containing the address. This simple interface
+is easily extended to more complex functions.
+For example, the
+.CW step
+function can select the current file and line in the editor
+each time the target program stops, giving the user a visual
+trace of the execution path of the program. A more complete interface
+allowing two way communication between Acid and the
+.CW acme
+user interface [Pike93] is under construction. A filter between the debugger
+and the user interface provides interpretation of results from both
+sides of the interface. This allows the programming environment to
+interact with the debugger and vice-versa, a capability missing from the
+.CW sam
+interface.
+The
+.CW src
+and
+.CW Bsrc
+functions are both written in Acid code using the file and line primitives.
+Acid provides library functions to step through source level
+statements and functions. Furthermore, addresses in Acid expressions can be
+specified by source file and line.
+Source code is manipulated in the Acid
+.I list
+data type.
+.NH
+The Acid Library
+.PP
+The following examples define some useful commands and
+illustrate the interaction of the debugger and the interpreter.
+.P1
+defn bpset(addr) // set breakpoint
+{
+ if match(addr, bplist) >= 0 then
+ print("bkpoint already set:", addr\ea, "\en");
+ else {
+ *fmt(addr, bpfmt) = bpinst; // plant it
+ bplist = append bplist, addr; // add to list
+ }
+}
+.P2
+The
+.CW bpset
+function plants a break point in memory. The function starts by
+using the
+.CW match
+builtin to
+search the breakpoint list to determine if a breakpoint is already
+set at the address.
+The indirection operator, controlled by the format code returned
+by the
+.CW fmt
+primitive, is used to plant the breakpoint in memory.
+The variables
+.CW bpfmt
+and
+.CW bpinst
+are Acid global variables containing the format code specifying
+the size of the breakpoint instruction and the breakpoint instruction
+itself.
+These
+variables are set by architecture-dependent library code
+when the debugger first attaches to the executing image.
+Finally the address of the breakpoint is
+appended to the breakpoint list,
+.CW bplist .
+.P1
+defn step() // single step
+{
+ local lst, lpl, addr, bput;
+
+ bput = 0; // sitting on bkpoint
+ if match(*PC, bplist) >= 0 then {
+ bput = fmt(*PC, bpfmt); // save current addr
+ *bput = @bput; // replace it
+ }
+
+ lst = follow(*PC); // get follow set
+
+ lpl = lst;
+ while lpl do { // place breakpoints
+ *(head lpl) = bpinst;
+ lpl = tail lpl;
+ }
+
+ startstop(pid); // do the step
+
+ while lst do { // remove breakpoints
+ addr = fmt(head lst, bpfmt);
+ *addr = @addr; // replace instr.
+ lst = tail lst;
+ }
+ if bput != 0 then
+ *bput = bpinst; // restore breakpoint
+}
+.P2
+The
+.CW step
+function executes a single assembler instruction.
+If the
+.CW PC
+is sitting
+on a breakpoint, the address and size of
+the breakpoint are saved.
+The breakpoint instruction
+is then removed using the
+.CW @
+operator to fetch
+.CW bpfmt
+bytes from the text file and to place it into the memory
+of the executing process using the
+.CW *
+operator.
+The
+.CW follow
+function is an Acid
+builtin which returns a follow-set: a list of instruction addresses which
+could be executed next.
+If the instruction stored at the
+.CW PC
+is a branch instruction, the
+list contains the addresses of the next instruction and
+the branch destination; otherwise, it contains only the
+address of the next instruction.
+The follow-set is then used to replace each possible following
+instruction with a breakpoint instruction. The original
+instructions need not be saved; they remain
+in their unaltered state in the text file.
+The
+.CW startstop
+builtin writes the `startstop' message to the
+.I proc
+control file for the process named
+.CW pid .
+The target process executes until some condition causes it to
+enter the kernel, in this case, the execution of a breakpoint.
+When the process blocks, the debugger regains control and invokes the
+Acid library function
+.CW stopped
+which reports the address and cause of the blockage.
+The
+.CW startstop
+function completes and returns to the
+.CW step
+function where
+the follow-set is used to replace the breakpoints placed earlier.
+Finally, if the address of the original
+.CW PC
+contained a breakpoint, it is replaced.
+.PP
+Notice that this approach to process control is inherently portable;
+the Acid code is shared by the debuggers for all architectures.
+Acid variables and builtin functions provide a transparent interface
+to architecture-dependent values and functions. Here the breakpoint
+value and format are referenced through Acid variables and the
+.CW follow
+primitive masks the differences in the underlying instruction set.
+.PP
+The
+.CW next
+function, similar to the
+.I dbx
+command of the same name,
+is a simpler example.
+This function steps through
+a single source statement but steps over function calls.
+.P1
+defn next()
+{
+ local sp, bound;
+
+ sp = *SP; // save starting SP
+ bound = fnbound(*PC); // begin & end of fn.
+ stmnt(); // step 1 statement
+ pc = *PC;
+ if pc >= bound[0] && pc < bound[1] then
+ return {};
+
+ while (pc<bound[0] || pc>bound[1]) && sp>=*SP do {
+ step();
+ pc = *PC;
+ }
+ src(*PC);
+}
+.P2
+The
+.CW next
+function
+starts by saving the current stack pointer in a local variable.
+It then uses the Acid library function
+.CW fnbound
+to return the addresses of the first and last instructions in
+the current function in a list.
+The
+.CW stmnt
+function executes a single source statement and then uses
+.CW src
+to print a few lines of source around the new
+.CW PC .
+If the new value of the
+.CW PC
+remains in the current function,
+.CW next
+returns.
+When the executed statement is a function call or a return
+from a function, the new value of the
+.CW PC
+is outside the bounds calculated by
+.CW fnbound
+and the test of the
+.CW while
+loop is evaluated.
+If the statement was a return, the new value of the stack pointer
+is greater than the original value and the loop completes without
+execution.
+Otherwise, the loop is entered and instructions are continually
+executed until the value of the
+.CW PC
+is between the bounds calculated earlier. At that point, execution
+ceases and a few lines of source in the vicinity of the
+.CW PC
+are printed.
+.PP
+Acid provides concise and elegant expression for control and
+manipulation of target programs. These examples demonstrate how a
+few well-chosen primitives can be combined to create a rich debugging environment.
+.NH
+Dealing With Multiple Architectures
+.PP
+A single binary of Acid may be used to debug a program running on any
+of the five processor architectures supported by Plan 9. For example,
+Plan 9 allows a user on a MIPS to import the
+.I proc
+file system from an i486-based PC and remotely debug a program executing
+on that processor.
+.PP
+Two levels of abstraction provide this architecture independence.
+On the lowest level, a Plan 9 library supplies functions to
+decode the file header of the program being debugged and
+select a table of system parameters
+and a jump vector of architecture-dependent
+functions based on the magic number.
+Among these functions are byte-order-independent
+access to memory and text files, stack manipulation, disassembly,
+and floating point number interpretation.
+The second level of abstraction is supplied by Acid.
+It consists of primitives and approximately 200 lines
+of architecture-dependent Acid library code that interface the
+interpreter to the architecture-dependent library.
+This layer performs functions such as mapping register names to
+memory locations, supplying breakpoint values and sizes,
+and converting processor specific data to Acid data types.
+An example of the latter is the stack trace function
+.CW strace ,
+which uses the stack traversal functions in the
+architecture-dependent library to construct a list of lists describing
+the context of a process. The first level of list selects
+each function in the trace; subordinate lists contain the
+names and values of parameters and local variables of
+the functions. Acid commands and library functions that
+manipulate and display process state information operate
+on the list representation and are independent of the
+underlying architecture.
+.NH
+Alef Runtime
+.PP
+Alef is a concurrent programming language,
+designed specifically for systems programming, which supports both
+shared variable and message passing paradigms.
+Alef borrows the C expression syntax but implements
+a substantially different type system.
+The language provides a rich set of
+exception handling, process management, and synchronization
+primitives, which rely on a runtime system.
+Alef program bugs are often deadlocks, synchronization failures,
+or non-termination caused by locks being held incorrectly.
+In such cases, a process stalls deep
+in the runtime code and it is clearly
+unreasonable to expect a programmer using the language
+to understand the detailed
+internal semantics of the runtime support functions.
+.PP
+Instead, there is an Alef support library, coded in Acid, that
+allows the programmer to interpret the program state in terms of
+Alef operations. Consider the example of a multi-process program
+stalling because of improper synchronization. A stack trace of
+the program indicates that it is waiting for an event in some
+obscure Alef runtime
+synchronization function.
+The function itself is irrelevant to the
+programmer; of greater importance is the identity of the
+unfulfilled event.
+Commands in the Alef support library decode
+the runtime data structures and program state to report the cause
+of the blockage in terms of the high-level operations available to
+the Alef programmer.
+Here, the Acid language acts
+as a communications medium between Alef implementer and Alef user.
+.NH
+Parallel Debugging
+.PP
+The central issue in parallel debugging is how the debugger is
+multiplexed between the processes comprising
+the program.
+Acid has no intrinsic model of process partitioning; it
+only assumes that parallel programs share a symbol table,
+though they need not share memory.
+The
+.CW setproc
+primitive attaches the debugger to a running process
+associated with the process ID supplied as its argument
+and assigns that value to the global variable
+.CW pid ,
+thereby allowing simple rotation among a group of processes.
+Further, the stack trace primitive is driven by parameters
+specifying a unique process context, so it is possible to
+examine the state of cooperating processes without switching
+the debugger focus from the process of interest.
+Since Acid is inherently extensible and capable of
+dynamic interaction with subordinate processes, the
+programmer can define Acid commands to detect and control
+complex interactions between processes.
+In short, the programmer is free to specify how the debugger reacts
+to events generated in specific threads of the program.
+.PP
+The support for parallel debugging in Acid depends on a crucial kernel
+modification: when the text segment of a program is written (usually to
+place a breakpoint), the segment is cloned to prevent other threads
+from encountering the breakpoint. Although this incurs a slight performance
+penalty, it is of little importance while debugging.
+.NH
+Communication Between Tools
+.PP
+The Plan 9 Alef and C compilers do not
+embed detailed type information in the symbol table of an
+executable file.
+However, they do accept a command line option causing them to
+emit descriptions of complex data types
+(e.g., aggregates and abstract data types)
+to an auxiliary file.
+The vehicle for expressing this information is Acid source code.
+When an Acid debugging session is
+subsequently started, that file is loaded with the other Acid libraries.
+.PP
+For each complex object in the program the compiler generates
+three pieces of Acid code.
+The first is a table describing the size and offset of each
+member of the complex data type. Following is an Acid function,
+named the same as the object, that formats and prints each member.
+Finally, Acid declarations associate the
+Alef or C program variables of a type with the functions
+to print them.
+The three forms of declaration are shown in the following example:
+.P1
+struct Bitmap {
+ Rectangle 0 r;
+ Rectangle 16 clipr;
+ 'D' 32 ldepth;
+ 'D' 36 id;
+ 'X' 40 cache;
+};
+.P2
+.P1
+defn
+Bitmap(addr) {
+ complex Bitmap addr;
+ print("Rectangle r {\en");
+ Rectangle(addr.r);
+ print("}\en");
+ print("Rectangle clipr {\en");
+ Rectangle(addr.clipr);
+ print("}\en");
+ print(" ldepth ", addr.ldepth, "\en");
+ print(" id ", addr.id, "\en");
+ print(" cache ", addr.cache, "\en");
+};
+
+complex Bitmap darkgrey;
+complex Bitmap Window_settag:b;
+.P2
+The
+.CW struct
+declaration specifies decoding instructions for the complex type named
+.CW Bitmap .
+Although the syntax is superficially similar to a C structure declaration,
+the semantics differ markedly: the C declaration specifies a layout, while
+the Acid declaration tells how to decode it.
+The declaration specifies a type, an offset, and name for each
+member of the complex object. The type is either the name of another
+complex declaration, for example,
+.CW Rectangle ,
+or a format code.
+The offset is the number of bytes from the start
+of the object to the member
+and the name is the member's name in the Alef or C declaration.
+This type description is a close match for C and Alef, but is simple enough
+to be language independent.
+.PP
+The
+.CW Bitmap
+function expects the address of a
+.CW Bitmap
+as its only argument.
+It uses the decoding information contained in the
+.CW Bitmap
+structure declaration to extract, format, and print the
+value of each member of the complex object pointed to by
+the argument.
+The Alef compiler emits code to call other Acid functions
+where a member is another complex type; here,
+.CW Bitmap
+calls
+.CW Rectangle
+to print its contents.
+.PP
+The
+.CW complex
+declarations associate Alef variables with complex types.
+In the example,
+.CW darkgrey
+is the name of a global variable of type
+.CW Bitmap
+in the program being debugged.
+Whenever the name
+.CW darkgrey
+is evaluated by Acid, it automatically calls the
+.CW Bitmap
+function with the address of
+.CW darkgrey
+as the argument.
+The second
+.CW complex
+declaration associates a local variable or parameter named
+.CW b
+in function
+.CW Window_settag
+with the
+.CW Bitmap
+complex data type.
+.PP
+Acid borrows the C operators
+.CW .
+and
+.CW ->
+to access the decoding parameters of a member of a complex type.
+Although this representation is sufficiently general for describing
+the decoding of both C and Alef complex data types, it may
+prove too restrictive for target languages with more complicated
+type systems.
+Further, the assumption that the compiler can select the proper
+Acid format code for each basic type in the language is somewhat
+naive. For example, when a member of a complex type is a pointer,
+it is assigned a hexadecimal type code; integer members are always
+assigned a decimal type code.
+This heuristic proves inaccurate when an integer field is a
+bit mask or set of bit flags which are more appropriately displayed
+in hexadecimal or octal.
+.NH
+Code Verification
+.PP
+Acid's ability to interact dynamically with
+an executing program allows passive test and
+verification of the target program. For example,
+a common concern is leak detection in programs using
+.CW malloc .
+Of interest are two items: finding memory that was allocated
+but never freed and detecting bad pointers passed to
+.CW free .
+An auxiliary Acid library contains Acid functions to
+monitor the execution of a program and detect these
+faults, either as they happen or in the automated
+post-mortem analysis of the memory arena.
+In the following example, the
+.CW sort
+command is run under the control of the
+Acid memory leak library.
+.P1
+helix% acid -l malloc /bin/sort
+/bin/sort: mips plan 9 executable
+/lib/acid/port
+/lib/acid/mips
+/lib/acid/malloc
+acid: go()
+now
+is
+the
+time
+<ctrl-d>
+is
+now
+the
+time
+27680 : breakpoint _exits+0x4 MOVW $0x8,R1
+acid:
+.P2
+The
+.CW go
+command creates a process and plants
+breakpoints at the entry to
+.CW malloc
+and
+.CW free .
+The program is then started and continues until it
+exits or stops. If the reason for stopping is anything
+other than the breakpoints in
+.CW malloc
+and
+.CW free ,
+Acid prints the usual status information and returns to the
+interactive prompt.
+.PP
+When the process stops on entering
+.CW malloc ,
+the debugger must capture and save the address that
+.CW malloc
+will return.
+After saving a stack
+trace so the calling routine can be identified, it places
+a breakpoint at the return address and restarts the program.
+When
+.CW malloc
+returns, the breakpoint stops the program,
+allowing the debugger
+to grab the address of the new memory block from the return register.
+The address and stack trace are added to the list of outstanding
+memory blocks, the breakpoint is removed from the return point, and
+the process is restarted.
+.PP
+When the process stops at the beginning of
+.CW free ,
+the memory address supplied as the argument is compared to the list
+of outstanding memory blocks. If it is not found an error message
+and a stack trace of the call is reported; otherwise, the
+address is deleted from the list.
+.PP
+When the program exits, the list of outstanding memory blocks contains
+the addresses of all blocks that were allocated but never freed.
+The
+.CW leak
+library function traverses the list producing a report describing
+the allocated blocks.
+.P1 1m
+acid: leak()
+Lost a total of 524288 bytes from:
+ malloc() malloc.c:32 called from dofile+0xe8 sort.c:217
+ dofile() sort.c:190 called from main+0xac sort.c:161
+ main() sort.c:128 called from _main+0x20 main9.s:10
+Lost a total of 64 bytes from:
+ malloc() malloc.c:32 called from newline+0xfc sort.c:280
+ newline() sort.c:248 called from dofile+0x110 sort.c:222
+ dofile() sort.c:190 called from main+0xac sort.c:161
+ main() sort.c:128 called from _main+0x20 main9.s:10
+Lost a total of 64 bytes from:
+ malloc() malloc.c:32 called from realloc+0x14 malloc.c:129
+ realloc() malloc.c:123 called from bldkey+0x358 sort.c:1388
+ buildkey() sort.c:1345 called from newline+0x150 sort.c:285
+ newline() sort.c:248 called from dofile+0x110 sort.c:222
+ dofile() sort.c:190 called from main+0xac sort.c:161
+ main() sort.c:128 called from _main+0x20 main9.s:10
+acid: refs()
+data...bss...stack...
+acid: leak()
+acid:
+.P2
+The presence of a block in the allocation list does not imply
+it is there because of a leak; for instance, it may have been
+in use when the program terminated.
+The
+.CW refs()
+library function scans the
+.I data ,
+.I bss ,
+and
+.I stack
+segments of the process looking for pointers
+into the allocated blocks. When one is found, the block is deleted from
+the outstanding block list.
+The
+.CW leak
+function is used again to report the
+blocks remaining allocated and unreferenced.
+This strategy proves effective in detecting
+disconnected (but non-circular) data structures.
+.PP
+The leak detection process is entirely passive.
+The program is not
+specially compiled and the source code is not required.
+As with the Acid support functions for the Alef runtime environment,
+the author of the library routines has encapsulated the
+functionality of the library interface
+in Acid code.
+Any programmer may then check a program's use of the
+library routines without knowledge of either implementation.
+The performance impact of running leak detection is great
+(about 10 times slower),
+but it has not prevented interactive programs like
+.CW sam
+and the
+.CW 8½
+window system from being tested.
+.NH
+Code Coverage
+.PP
+Another common component of software test uses
+.I coverage
+analysis.
+The purpose of the test is to determine which paths through the code have
+not been executed while running the test suite.
+This is usually
+performed by a combination of compiler support and a reporting tool run
+on the output generated by statements compiled into the program.
+The compiler emits code that
+logs the progress of the program as it executes basic blocks and writes the
+results to a file. The file is then processed by the reporting tool
+to determine which basic blocks have not been executed.
+.PP
+Acid can perform the same function in a language independent manner without
+modifying the source, object or binary of the program. The following example
+shows
+.CW ls
+being run under the control of the Acid coverage library.
+.P1
+philw-helix% acid -l coverage /bin/ls
+/bin/ls: mips plan 9 executable
+/lib/acid/port
+/lib/acid/mips
+/lib/acid/coverage
+acid: coverage()
+acid
+newstime
+profile
+tel
+wintool
+2: (error) msg: pid=11419 startstop: process exited
+acid: analyse(ls)
+ls.c:102,105
+ 102: return 1;
+ 103: }
+ 104: if(db[0].qid.path&CHDIR && dflag==0){
+ 105: output();
+ls.c:122,126
+ 122: memmove(dirbuf+ndir, db, sizeof(Dir));
+ 123: dirbuf[ndir].prefix = 0;
+ 124: p = utfrrune(s, '/');
+ 125: if(p){
+ 126: dirbuf[ndir].prefix = s;
+.P2
+The
+.CW coverage
+function begins by looping through the text segment placing
+breakpoints at the entry to each basic block. The start of each basic
+block is found using the Acid builtin function
+.CW follow .
+If the list generated by
+.CW follow
+contains more than one
+element, then the addresses mark the start of basic blocks. A breakpoint
+is placed at each address to detect entry into the block. If the result
+of
+.CW follow
+is a single address then no action is taken, and the next address is
+considered. Acid maintains a list of
+breakpoints already in place and avoids placing duplicates (an address may be
+the destination of several branches).
+.PP
+After placing the breakpoints the program is set running.
+Each time a breakpoint is encountered
+Acid deletes the address from the breakpoint list, removes the breakpoint
+from memory and then restarts the program.
+At any instant the breakpoint list contains the addresses of basic blocks
+which have not been executed.
+The
+.CW analyse
+function reports the lines of source code bounded by basic blocks
+whose addresses are have not been deleted from the breakpoint list.
+These are the basic blocks which have not been executed.
+Program performance is almost unaffected since each breakpoint is executed
+only once and then removed.
+.PP
+The library contains a total of 128 lines of Acid code.
+An obvious extension of this algorithm could be used to provide basic block
+profiling.
+.NH
+Conclusion
+.PP
+Acid has two areas of weakness. As with
+other language-based tools like
+.I awk ,
+a programmer must learn yet another language to step beyond the normal
+debugging functions and use the full power of the debugger.
+Second, the command line interface supplied by the
+.I yacc
+parser is inordinately clumsy.
+Part of the problem relates directly to the use of
+.I yacc
+and could be circumvented with a custom parser.
+However, structural problems would remain: Acid often requires
+too much typing to execute a simple
+command.
+A debugger should prostitute itself to its users, doing whatever
+is wanted with a minimum of encouragement; commands should be
+concise and obvious. The language interface is more consistent than
+an ad hoc command interface but is clumsy to use.
+Most of these problems are addressed by an Acme interface
+which is under construction. This should provide the best of
+both worlds: graphical debugging and access to the underlying acid
+language when required.
+.PP
+The name space clash between Acid variables, keywords, program variables,
+and functions is unavoidable.
+Although it rarely affects a debugging session, it is annoying
+when it happens and is sometimes difficult to circumvent.
+The current renaming scheme
+is too crude; the new names are too hard to remember.
+.PP
+Acid has proved to be a powerful tool whose applications
+have exceeded expectations.
+Of its strengths, portability, extensibility and parallel debugging support
+were by design and provide the expected utility.
+In retrospect,
+its use as a tool for code test and verification and as
+a medium for communicating type information and encapsulating
+interfaces has provided unanticipated benefits and altered our
+view of the debugging process.
+.NH
+Acknowledgments
+.PP
+Bob Flandrena was the first user and helped prepare the paper.
+Rob Pike endured three buggy Alef compilers and a new debugger
+in a single sitting.
+.NH
+References
+.LP
+[Pike90] R. Pike, D. Presotto, K. Thompson, H. Trickey,
+``Plan 9 from Bell Labs'',
+.I
+UKUUG Proc. of the Summer 1990 Conf.,
+.R
+London, England,
+1990.
+.LP
+[Gol93] M. Golan, D. Hanson,
+``DUEL -- A Very High-Level Debugging Language'',
+.I
+USENIX Proc. of the Winter 1993 Conf.,
+.R
+San Diego, CA,
+1993.
+.LP
+[Lin90] M. A. Linton,
+``The Evolution of DBX'',
+.I
+USENIX Proc. of the Summer 1990 Conf.,
+.R
+Anaheim, CA,
+1990.
+.LP
+[Stal91] R. M. Stallman, R. H. Pesch,
+``Using GDB: A guide to the GNU source level debugger'',
+Technical Report, Free Software Foundation,
+Cambridge, MA,
+1991.
+.LP
+[Win93] P. Winterbottom,
+``Alef reference Manual'',
+reprinted in this volume.
+.LP
+[Pike93] Rob Pike,
+``Acme: A User Interface for Programmers'',
+.I
+USENIX Proc. of the Winter 1994 Conf.,
+.R
+San Francisco, CA,
+reprinted in this volume.
+.LP
+[Ols90] Ronald A. Olsson, Richard H. Crawford, and W. Wilson Ho,
+``Dalek: A GNU, improved programmable debugger'',
+.I
+USENIX Proc. of the Summer 1990 Conf.,
+.R
+Anaheim, CA.
+.LP
+[May92] Paul Maybee,
+``NeD: The Network Extensible Debugger''
+.I
+USENIX Proc. of the Summer 1992 Conf.,
+.R
+San Antonio, TX.
+.LP
+[Aral] Ziya Aral, Ilya Gertner, and Greg Schaffer,
+``Efficient debugging primitives for multiprocessors'',
+.I
+Proceedings of the Third International Conference on Architectural
+Support for Programming Languages and Operating Systems,
+.R
+SIGPLAN notices Nr. 22, May 1989.
binary files /dev/null b/doc/acidpaper.pdf differ
--- /dev/null
+++ b/doc/acidtut.ms
@@ -1,0 +1,1062 @@
+.de d0
+.nr dP +1
+.nr dV +1p
+..
+.de d1
+.nr dP -1
+.nr dV -1p
+..
+.nr dT 4
+.de Af \" acid function
+.CW "\\$1(" "\fI\\$2\fP\f(CW)\fP"
+..
+.TL
+Native Kernel Debugging with Acid
+.AU
+Tad Hunt
+tad@plan9.bell-labs.com
+.br
+Lucent Technologies Inc
+.br
+(Revised 22 May 2000 by Vita Nuova)
+.SH
+Introduction
+.PP
+This tutorial provides an introduction to the Acid debugger. It assumes that you are familiar with the features of a typical source-level debugger. The Acid debugger is built round a command language with a syntax similar to C.
+This tutorial is not an
+introduction to Acid as a whole, but
+offers a brief tour
+of the basic built in and standard library functions,
+especially those needed for debugging native Inferno kernels on a target board.
+.PP
+Acid was originally developed by Phil Winterbottom
+to help debug multi-threaded programs in
+the concurrent language Alef, and provide more sophisticated
+debugging for C programs.
+In the paper
+.I "Acid: A Debugger Built From a Language" ,
+Winterbottom
+discusses Acid's design, including some worked examples of unusual
+applications of Acid to find memory leaks and assist code coverage analysis.
+Following that is the
+.I "Acid Reference Manual" ,
+also by Phil Winterbottom,
+which gives a more precise specification of the Acid debugging language and its libraries.
+.SH
+Preliminaries -- the environment
+.PP
+Acid runs under the host operating system used for cross-development,
+in the same way as the Inferno compilers.
+Before running either compilers or Acid, the following
+environment variables must be set appropriately:
+.TS
+center;
+lf(CW) lf(R)w(4i) .
+ROOT T{
+the directory in which Inferno lives (eg,
+.CW /usr/inferno ).
+T}
+SYSHOST T{
+.I host
+operating system type:
+.CW Nt ,
+.CW Solaris ,
+.CW Plan9 ,
+.CW Linux
+or
+.CW FreeBSD
+T}
+OBJTYPE T{
+.I host
+machine's architecture type:
+.CW 386 ,
+.CW sparc ,
+.CW mips ,
+or
+.CW powerpc
+T}
+.TE
+They might be set by a login shell profile
+(eg,
+Unix
+.CW ".profile" ,
+or
+Plan 9
+.CW lib/profile ).
+Also ensure that the directory
+.P1
+$ROOT/$SYSHOST/$OBJTYPE/bin
+.P2
+is on your search path.
+For example, on a Solaris sparc, one might use:
+.P1
+ROOT=\fIinferno_root\fP
+SYSHOST=Solaris
+OBJTYPE=sparc
+ACIDLIB=$ROOT/lib/acid
+PATH=$ROOT/$SYSHOST/$OBJTYPE/bin:$PATH
+export ROOT ACIDLIB PATH OBJTYPE SYSHOST
+.P2
+where
+.I "inferno_root"
+is the directory in which Inferno lives (eg,
+.CW "/usr/inferno" ).
+.SH
+An Example Program
+.PP
+The first example is not kernel code, but a small program that
+will be compiled but not run, to demonstrate basic Acid commands for
+source and object file inspection.
+The code is shown below:
+.P1
+int
+factorial(int n)
+{
+ if (n == 1)
+ return 1;
+ return n * factorial(n-1);
+}
+
+int f;
+void
+main(void)
+{
+ f = factorial(5);
+}
+
+void
+_main(void)
+{
+ main();
+}
+.P2
+.SH
+Compiling and Linking
+.PP
+The first step is to create an executable. The example shows the process for creating ARM executables. Substitute the appropriate compiler and linker for other cpu types.
+.P1
+% 5c factorial.c
+% 5l -o factorial factorial.5
+% ls
+factorial
+factorial.5
+factorial.c
+.P2
+.SH
+Starting Acid
+.PP
+Even without the target machine on which
+to run the program, many Acid features are available.
+The following command starts debugging the
+.CW "factorial"
+executable. Note that, upon startup, Acid will attempt to load some libaries from the directory specified in the
+.CW "ACIDLIB"
+environment variable (defaults to
+.CW "/usr/inferno/lib/acid" ).
+It will also attempt to load the file
+.CW "$HOME/lib/acid" ,
+in which you can place commands to be executed during startup.
+.P1
+% acid factorial
+factorial:Arm plan 9 executable
+
+$ROOT/lib/acid/port
+$ROOT/lib/acid/arm
+acid:
+.P2
+.SH
+Exploring the Executable
+.PP
+To find out what symbols are in the program:
+.P1
+acid: symbols("")
+etext T 0x00001068
+f D 0x00002000
+setR12 D 0x00002ffc
+end B 0x00002008
+bdata D 0x00002000
+edata D 0x00002008
+factorial T 0x00001020
+main T 0x00001048
+_main T 0x0000105c
+acid:
+.P2
+The output from the
+.CW symbols()
+function is similar to the output from the
+.I nm (10.1)
+command. The first column is the symbol name, the second column gives the section the symbol is in, and the third column is the address of the symbol.
+.PP
+There is also a
+.CW "symbols"
+global variable. Variables and functions can have the same names. It holds the list of symbol information that the
+.CW symbols
+function uses to generate the table:
+.d0
+.P1
+acid: symbols
+{{"etext", T, 0x00001068}, {"f", D, 0x00002000}, {"setR12", D, 0x00002ffc},
+ {"end", B, 0x00002008}, {"bdata", D, 0x00002000}, {"edata", D, 0x00002008},
+ {"factorial", T, 0x00001020}, {"main", T, 0x00001048}, {"_main", T, 0x00001
+05c}}
+acid:
+.P2
+.d1
+In large programs, finding the symbol you are interested in from a list that may be thousands of lines long would be difficult. The string argument of
+.CW symbols()
+is a regular expression against which to match symbols.
+All symbols that contain the pattern will be displayed. For example:
+.P1
+acid: symbols("main")
+main T 0x00001048
+_main T 0x0000105c
+acid: symbols("^main")
+main T 0x00001048
+acid:
+.P2
+The
+.CW symbols
+function is written in the
+.I acid
+command language and lives in the
+.CW "port"
+library
+.CW $ACIDLIB/port ). (
+.P1
+defn symbols(pattern)
+{
+ local l, s;
+
+ l = symbols;
+ while l do {
+ s = head l;
+ if regexp(pattern, s[0]) then
+ print(s[0], "\t", s[1], "\t", s[2], "\n");
+ l = tail l;
+ }
+}
+.P2
+Acid retrieves the list of symbols from the executable and turns each one into a global variable whose value is the address of the symbol. If the symbol clashes with a builtin name or keyword or a previously defined function, enough
+.CW "$"
+characters are prepended to the name to make it unique. The list of such renamings is printed at startup.
+.PP
+Most acid functions operate on addresses. For example, to view the source code for a given address, use the
+.CW src
+function:
+.P1
+acid: src(main)
+/usr/jrf/factorial.c:10
+ 5 return n * factorial(n-1);
+ 6 }
+ 7
+ 8 int f;
+ 9 void
+>10 main(void)
+ 11 {
+ 12 f = factorial(5);
+ 13 }
+ 14
+ 15 void
+.P2
+The
+.Af "src" addr
+function displays a section of source code, with the line containing the address passed as an argument in the middle of the display. To print the assembly code beginning at a given address, use the
+.CW asm()
+function.
+.P1
+acid: asm(factorial)
+factorial 0x00001020 MOVW.W R14,#-0x8(R13)
+factorial+0x4 0x00001024 CMP.S $#0x1,R0
+factorial+0x8 0x00001028 MOVW.EQ $#0x1,R0
+factorial+0xc 0x0000102c RET.EQ.P #0x8(R13)
+factorial+0x10 0x00001030 MOVW R0,n+0(FP)
+factorial+0x14 0x00001034 SUB $#0x1,R0,R0
+factorial+0x18 0x00001038 BL factorial
+factorial+0x1c 0x0000103c MOVW n+0(FP),R2
+factorial+0x20 0x00001040 MUL R2,R0,R0
+factorial+0x24 0x00001044 RET.P #0x8(R13)
+main 0x00001048 MOVW.W R14,#-0x8(R13)
+acid:
+.P2
+The output contains the symbolic address (symbol name+offset, where symbol name is the name of the enclosing function) followed by the absolute address, followed by the disassembled code.
+The
+.Af "asm" addr
+function prints the assembly beginning at
+.I "addr"
+and ending after either 30 lines have been printed, or the end of the function has been reached. The
+.CW "casm()"
+function continues the assembly listing from where it left off, even past the end of the function and into the next one.
+.P1
+acid: casm()
+main+0x4 0x0000104c MOVW $#0x5,R0
+main+0x8 0x00001050 BL factorial
+main+0xc 0x00001054 MOVW R0,$f-SB(SB)
+main+0x10 0x00001058 RET.P #0x8(R13)
+_main 0x0000105c MOVW.W R14,#-0x4(R13)
+acid:
+.P2
+All the functions presented so far are written in the acid command language. To see the source of a comand written in the acid command language, use the builtin command
+.CW "whatis [" "\fIname\fP\f(CW ]\fP."
+It prints the definition of the optional argument
+.I "name" .
+If
+.I "name"
+is an Acid builtin,
+.CW whatis
+prints
+.CW "builtin function" .
+.P1
+acid: whatis casm
+defn casm() {
+ asm(lasmaddr);
+}
+acid:
+acid: whatis atof
+builtin function
+acid:
+.P2
+If
+.I name
+is a variable, it prints the type of variable, and for the integer type, gives the format code used to print the value:
+.P1
+acid: whatis pid
+integer variable format D
+acid:
+.P2
+With no arguments,
+.CW whatis
+lists all available functions:
+.P1
+acid: whatis
+Bsrc bpmask follow new sh
+_bpconddel bpneq func newproc source
+_bpcondset bpor gpr next spr
+_stk bpprint include notestk spsrch
+access bppush interpret params src
+acidinit bpset itoa pcfile start
+addsrcdir bptab kill pcline startstop
+asm casm kstk pfl status
+atof cont labstk print stk
+atoi debug line printto stmnt
+bpaddr dump linkreg procs stop
+bpand error lkstk rc stopped
+bpconddel file locals readfile strace
+bpcondset filepc lstk reason symbols
+bpdel findsrc map regexp waitstop
+bpderef fmt match regs
+bpeq fnbound mem setproc
+acid:
+.P2
+The
+.Af "Bsrc" addr
+function brings up an editor on the line containing
+.I "addr" .
+It simply invokes a shell script named
+.CW "B"
+that takes two arguments,
+.I "-line"
+and
+.I "file"
+The shell script invokes
+.CW "$EDITOR +"
+.I "line file" .
+If unset,
+.CW "EDITOR"
+defaults to
+.I vi .
+The shell script, or the
+.CW Bsrc
+function can be easily rewritten to work with your favorite editor.
+.PP
+Entering a symbol name by itself will print the address of the symbol. Prefixing the symbol name with a
+.CW "*"
+will print the value at the address in the variable. Continuing to use our
+.CW "factorial"
+example:
+.P1
+acid: f
+0x00002000
+acid: *f
+0x00000000
+acid:
+.P2
+.SH
+Remote Debugging
+.PP
+Now that you have a basic understanding of how to explore the executable, it is time to examine a real remote debugging session.
+.PP
+We'll use the SA1100 keyboard driver as an example. Examining the kernel configuration file, you'll see the following:
+.P1
+dev
+ keyboard
+link driver/keyboard port
+ scanfujn860 kbd.h keycodes.h
+link ./../driver plat
+ kbdfujitsu ./../common/ssp.h \e
+ /driver/keyboard/kbd.h \e
+ /driver/keyboard/keycodes.h
+port
+ const char *defaultkeyboard = "fujitsu";
+ const char *defaultkeytable = "scanfujn860";
+ int debugkeys = 1; /* 1 = enabled, 0 = disabled */
+.P2
+This describes the pieces of the keyboard driver which are linked into the kernel. The source code lives in two places,
+.CW "$ROOT/os/driver/keyboard" ,
+and
+.CW "$ROOT/os/plat/sa1100/driver" .
+.PP
+The next step is to build a kernel. Use the
+.I mk
+target
+.CW acid
+to ensure that the Acid symbolic debugging data is
+produced.
+For example:
+.P1
+% mk 'CONF=sword' acid isword.p9.gz
+.P2
+This creates the Acid file
+.CW isword.acid ,
+containing Acid declarations describing kernel structures,
+the kernel executable
+.CW isword.p9 ;
+and finally
+.I gzip s
+a copy of the kernel in
+.CW isword.p9.gz
+to load onto the device. Next, copy the gzipped image onto the device and then boot it. Follow the directions found elsewhere for details of this process.
+.PP
+From a shell prompt on the target device, start the remote debugger by writing the letter
+.CW r
+(for run) to
+.CW "#b/dbgctl" .
+Next, start Acid in remote debug mode, specifying the serial port it is connected to with the
+.CW "-R"
+option.
+.CW "$CONF"
+is the name of the configuration file used, for example
+.CW "sword" .
+.P1
+% acid -R /dev/cua/b -l i$CONF.acid i$CONF
+isword:Arm plan 9 executable
+$ROOT/lib/acid/port
+i$CONF.acid
+$ROOT/lib/acid/arm
+/usr/jrf/lib/acid
+acid:
+.P2
+You are now debugging the kernel that is running on the target device. All of the previously listed commands will work as described before, in addition, there are many more commands available.
+.SH
+Kernel Process Listing
+.PP
+To get a list of kernel processes, use the
+.CW "ps()"
+function:
+.P1
+acid: ps()
+PID PC PRI STATE NAME
+1 0x00054684 5 Queueing interp
+2 0x00000000 1 Wakeme consdbg
+3 0x00000000 5 Wakeme tcpack
+4 0x00000000 5 Wakeme Fs.sync
+5 0x00000000 4 Wakeme touchscreen
+6 0x00054684 5 Queueing dis
+7 0x00059788 5 Wakeme dis
+8 0x00054684 5 Queueing dis
+9 0x00054684 5 Queueing dis
+10 0x00054684 5 Wakeme dis
+11 0x0004c26c 1 Running dbg
+acid:
+.P2
+The
+.CW "PC"
+column shows the address the process was executing at when the
+.CW ps
+command retrieved statistics on it. The
+.CW "PRI"
+column lists process priorities. The smaller the number the higher the process priority. Notice that the kernel process (kproc) running the debugger is the highest priority process in the system. The only process you will ever see in the
+.CW "Running"
+state while executing the
+.CW ps
+command will be the debugger, since it is gathering information about the other processes.
+.SH
+Breakpoints
+.PP
+Breakpoints in Inferno, unlike most traditional kernel debuggers, are conditional breakpoints. There are minimally two conditions which must be met. These conditions are address and process id. A breakpoint will only be taken when execution for a specific kernel process reaches the specified address. The user can create additional conditions that are evaluated if the address and process id match. If evaluation of these conditions result in a nonzero value, the breakpoint is taken, otherwise it is ignored, and execution continues.
+.PP
+Again, the best way to proceed is with an example:
+.P1
+acid: setproc(7)
+.P2
+The
+.Af setproc pid
+function selects a kproc to which later commands will be applied;
+the one with process ID (\fIpid\fP)
+in this case.
+.P1
+acid: bpset(keyboardread)
+Waiting...
+7: stopped flush8to4+0x18c MOVW (R3<<#4),R3
+.P2
+After selecting a kproc, we set a breakpoint at the address referred to by the
+.CW "keyboardread"
+symbol. As described before, the value of a global variable created from a symbol in the executable is the address of the symbol. In this case the address is the first instruction in the
+.CW "keyboardread()"
+function. Notice that setting a breakpoint stops the kproc from executing. A bit later, we'll see how to get it to continue execution.
+.PP
+Next, display the list of breakpoints using
+.CW "bptab()" :
+.P1
+acid: bptab()
+ID PID ADDR CONDITIONS
+0 7 keyboardread 0x0003c804 { }
+.P2
+The first column is a unique number that identifies the breakpoint. The second column is the process ID in which the breakpoint will be taken. The third and fourth columns are the address of the breakpoint, first in symbolic form, then in numeric form. Finally, the last column is a list of conditions to evaluate whenever the kproc specified in the
+.CW "PID"
+column hits the the address specified in the
+.CW "ADDR"
+column. When they match, the list of conditions is evaluated. If the result is nonzero, the breakpoint is taken. Since we used the simplified breakpoint creation function,
+.CW "bpset()"
+, there are no additional conditions. Later on, we'll see how to set conditional breakpoints.
+.PP
+Start the selected kproc executing again, and wait for it to hit the breakpoint.
+.P1
+acid: cont()
+.P2
+The
+.CW "cont()"
+function will not return until a breakpoint has been hit, and there is no way to interrupt it. This means you should only set breakpoints that will be hit, otherwise you'll have to reboot the target device and restart your debugging session.
+.PP
+To continue our example, repeatedly hit new line (return, enter)
+on the keyboard on the target device, until the breakpoint occurs:
+.P1
+break 0: pid 7: stopped keyboardread SUB $#0xa4,R13,R13
+acid:
+.P2
+This message, followed by the interactive prompt returning tells you that a breakpoint was hit. It gives the breakpoint id, the kernel process id, then the symbolic address at which execution halted, followed by the disassembly of the instruction at that address.
+.PP
+The
+.CW "kstk()"
+function prints a kernel stack trace, beginning with the current frame, all the way back to the call that started the kproc. For each function, it gives the name name, arguments, source file, and line number, followed by the symbolic address, source file, and line number of the caller.
+.d0
+.P1
+acid: kstk()
+At pc:247812:keyboardread /usr/inferno/os/driver/keyboard/devkey
+board.c:350
+keyboardread(offset=0x0000009d,buf=0x001267f8,n=0x00000001) /usr
+/inferno/os/driver/keyboard/devkeyboard.c:350
+ called from kchanio+0x9c /usr/inferno/os/port/sysfile.c:
+75
+kchanio(buf=0x001267f8,n=0x00000001,mode=0x00000000) /usr/infern
+o/os/port/sysfile.c:64
+ called from consread+0x144 /usr/inferno/os/driver/port/d
+evcons
+consread(offset=0x0000009d,buf=0x0043d4fc,n=0x00000400,c=0x0044e
+c38) /
+usr/inferno/os/driver/port/devcons.c:357
+ called from kread+0x164 /usr/inferno/os/port/sysfile.c:2
+97
+kread(fd=0x00000006,n=0x00000400,va=0x0043d4fc) /usr/inferno/os/
+port/sysfile.c:272
+ called from Sys_read+0x84 /usr/inferno/os/port/inferno.c
+:244
+Sys_read() /usr/inferno/os/port/inferno.c:229
+ called from mcall+0x98 /usr/inferno/interp/xec.c:590
+mcall() /usr/inferno/interp/xec.c:569
+ called from xec+0x128 /usr/inferno/interp/xec.c:1098
+xec(p=0x0044edd8) /usr/inferno/interp/xec.c:1077
+ called from vmachine+0xbc /usr/inferno/os/port/dis.c:706
+vmachine() /usr/inferno/os/port/dis.c:677
+ called from _main+0x50 /usr/inferno/os/plat/sa1100/infern
+o/main.c:237
+acid:
+.P2
+.d1
+There is another kernel stack dump function,
+.CW "lkstk()"
+which shows the same information as
+.CW "kstk()"
+plus the names and values of local variables. Notice that in addition to the
+`called from'
+information, each local variable and its value is listed on a line by itself.
+.d0
+.P1
+acid: lkstk()
+At pc:247812:keyboardread /usr/inferno/os/driver/keyboard/devkeyboard.
+c:350
+keyboardread(offset=0x00000018,buf=0x001267f9,n=0x00000001) /usr/inferno
+/os/driver/keyboard/devkeyboard.c:350
+ called from kchanio+0x9c /usr/inferno/os/port/sysfile.c:75
+ tmp=0x00000000
+kchanio(buf=0x001267f9,n=0x00000001,mode=0x00000000) /usr/inferno/os/por
+t/sysfile.c:64
+ called from consread+0x144 /usr/inferno/os/driver/port/devcons
+ c=0x0045a858
+ r=0x00000001
+consread(offset=0x00000015,buf=0x0043d4fc,n=0x00000400,c=0x0044ec38) /us
+r/inferno/os/driver/port/devcons.c:357
+ called from kread+0x164 /usr/inferno/os/port/sysfile.c:297
+ r=0x00000001
+ ch=0x0000006c
+ eol=0x00000000
+ i=0x00000000
+ mt=0x60000053
+ tmp=0x0007317c
+ l=0x0044ec38
+ p=0x00049754
+kread(fd=0x00000006,n=0x00000400,va=0x0043d4fc) /usr/inferno/os/port/sys
+file.c:272
+ called from Sys_read+0x84 /usr/inferno/os/port/inferno.c:244
+ c=0x0044ec38
+ dir=0x00000000
+Sys_read() /usr/inferno/os/port/inferno.c:229
+ called from mcall+0x98 /usr/inferno/interp/xec.c:590
+ f=0x0044eff0
+ n=0x00000400
+mcall() /usr/inferno/interp/xec.c:569
+ called from xec+0x128 /usr/inferno/interp/xec.c:1098
+ ml=0x0043d92c
+ f=0x0044eff0
+xec(p=0x0044edd8) /usr/inferno/interp/xec.c:1077
+ called from vmachine+0xbc /usr/inferno/os/port/dis.c:706
+vmachine() /usr/inferno/os/port/dis.c:677
+ called from _main+0x50 /usr/inferno/os/plat/sa1100/inferno/main.
+c:237
+ r=0x0044edd8
+ o=0x0044ee50
+.P2
+.d1
+The
+.CW "step()"
+function allows the currently selected process to execute a single instruction, and then stop.
+.P1
+acid: step()
+break 1: pid 7: stopped keyboardread+0x4 MOVW R14,#0x0(R13)
+acid:
+.P2
+The
+.CW "bpdel" (
+.I id )
+command deletes the breakpoint identified by
+.I id :
+.P1
+acid: bpdel(0)
+.P2
+The
+.CW "start()"
+command places the kproc back into the state it was in when it was stopped.
+.P1
+acid: start(7)
+acid:
+.P2
+Now lets look at how to set conditional breakpoints.
+.d0
+.P1
+acid: bpcondset(7, keyboardread, {bppush(_startup), bpderef()})
+Waiting...
+7: stopped sched+0x20 MOVW #0xffffff70(R12),R6
+acid: bptab()
+ID PID ADDR CONDITIONS
+0 7 keyboardread 0x0003c804 {
+ {"p", 0x00008020}
+ {"*", 0x00000000} }
+acid: *_startup = 0
+acid: cont()
+.P2
+.d1
+Conditional breakpoints are set with
+.CW "bpcondset()"
+. It takes three arguments, the kernel process id, the address, and a list of stack based operations which are executed if the pid and addr match. The operations push values onto the stack, and if at the end of execution, a nonzero value is on the top of the stack, the breakpoint is taken. Examining the list of breakpoints with the
+.CW "bptab()"
+function shows the list of conditions to apply. The list is a bit confusing to read, but the
+.CW ""p""
+means push and the
+.CW ""*""
+means
+.I dereference .
+.PP
+No matter how much you type on the keyboard, this particular breakpoint will never be taken. That's because before continuing, we set the value at the address
+.CW "_startup"
+to zero, so whenever execution reaches
+.CW "keyboardread"
+in kproc number 7, it pushes the address
+.CW "_startup" ,
+then pops it and pushes the word at that address. Since the top of the stack is zero, the breakpoint is ignored.
+.PP
+This contrived example may not be all that useful, but you can use a similar method in your driver to examine some state before making the decision to take the breakpoint.
+.SH
+Examining Registers
+.PP
+There are three commands to dump registers:
+.CW gpr() ,
+.CW spr()
+and
+.CW "regs()" .
+The
+.CW "gpr()"
+function dumps the general purpose registers,
+.CW "spr()"
+dumps special purpose registers (such as the
+.CW "PC"
+and
+.CW "LINK "
+registers), and
+.CW "regs()"
+dumps both:
+.d0
+.P1
+acid: regs()
+PC 0x0004a3b0 sched+0x20 /home/tad/inf2.1/os/port/proc.c:82
+LINK 0x0004b8e8 kchanio+0xa4 /home/tad/inf2.1/os/port/sysfile.c:75
+SP 0x00453c4c
+R0 0x00458798 R1 0x000fdf9c R2 0x0003c804 R3 0x00000000
+R4 0xffffffff R5 0x00000001 R6 0x00458798 R7 0x00000001
+R8 0x001267f8 R9 0x00000000 R10 0x0044ee50 R11 0x00029f9c
+R12 0x000fc854
+acid:
+.P2
+.d1
+.SH
+Complex Types
+.PP
+When reading in the symbol table, Acid treats all of the symbols in the executable as pointers to integers. This is fine for global integer variables, but it makes examining more complex types difficult. Luckily there is a solution. Acid allows you to create a description for more complex types, and a function which will automatically be called for these complex types. In fact, the compiler can automatically generate the acid code to describe these complex types. For example, if we wanted to print out the devtab structure for the keyboard driver, we can just give its name:
+.P1
+acid: whatis keyboarddevtab
+integer variable format a complex Dev
+acid: keyboarddevtab
+ dc 107
+ name 0x0010e0ea
+ reset 0x0003c3fc
+ init 0x0003c438
+ attach 0x0003c5dc
+ clone 0x000480d0
+ walk 0x0003c600
+ stat 0x0003c640
+ open 0x0003c680
+ create 0x0004881c
+ close 0x0003c768
+ read 0x0003c804
+ bread 0x0004883c
+ write 0x0003c968
+ bwrite 0x00048900
+ remove 0x00048978
+ wstat 0x00048998
+acid:
+.P2
+Acid knows the keyboarddevtab variable is of type Dev, and it prints it by invoking the function Dev(keyboarddevtab).
+.P1
+acid: whatis Dev
+complex Dev {
+ 'D' 0 dc;
+ 'X' 4 name;
+ 'X' 8 reset;
+ 'X' 12 init;
+ 'X' 16 attach;
+ 'X' 20 clone;
+ 'X' 24 walk;
+ 'X' 28 stat;
+ 'X' 32 open;
+ 'X' 36 create;
+ 'X' 40 close;
+ 'X' 44 read;
+ 'X' 48 bread;
+ 'X' 52 write;
+ 'X' 56 bwrite;
+ 'X' 60 remove;
+ 'X' 64 wstat;
+};
+.P3
+defn Dev(addr) {
+ complex Dev addr;
+ print("\etdct",addr.dc,"\en");
+ print("\etnamet",addr.nameX,"\en");
+ print("\etresett",addr.resetX,"\en");
+ print("\etinitt",addr.initX,"\en");
+ print("\etattacht",addr.attachX,"\en");
+ print("\etclonet",addr.cloneX,"\en");
+ print("\etwalkt",addr.walkX,"\en");
+ print("\etstatt",addr.statX,"\en");
+ print("\etopent",addr.openX,"\en");
+ print("\etcreatet",addr.createX,"\en");
+ print("\etcloset",addr.closeX,"\en");
+ print("\etreadt",addr.readX,"\en");
+ print("\etbreadt",addr.breadX,"\en");
+ print("\etwritet",addr.writeX,"\en");
+ print("\etbwritet",addr.bwriteX,"\en");
+ print("\etremovet",addr.removeX,"\en");
+ print("\etwstatt",addr.wstatX,"\en");
+}
+.P2
+Notice the complex type definition and the function to print the type both have the same name. If we know that an address is the address of a complex type, even though acid may not
+(say we're storing multiple types of data in a void pointer),
+we can print the complex type by calling the type printing function ourselves.
+.P1
+acid: print(fmt(keyboarddevtab, 'X'))
+0x00106d50
+acid: Dev(0x00106d50)
+ dc 107
+ name 0x0010e0ea
+ reset 0x0003c3fc
+ init 0x0003c438
+ attach 0x0003c5dc
+ clone 0x000480d0
+ walk 0x0003c600
+ stat 0x0003c640
+ open 0x0003c680
+ create 0x0004881c
+ close 0x0003c768
+ read 0x0003c804
+ bread 0x0004883c
+ write 0x0003c968
+ bwrite 0x00048900
+ remove 0x00048978
+ wstat 0x00048998
+acid:
+.P2
+.SH
+Conclusion
+.PP
+This introduction to using Acid for remote debugging Inferno kernels should be enough to get you started. As a tutorial, it only describes how to use some of the features of the debugger, and does not attempt to describe how to do advanced debugging such as writing your own functions, or modifying existing ones. Exploring the source, setting breakpoints, single stepping through code, and examining the contents of variables are the usual uses of a debugger. This tutorial gives examples of all of these.
+.PP
+For a more in depth discussion of the acid command language, and how to write your own acid functions, see the manual page
+.I acid (10.1)
+and Phil Winterbottom's papers on the Acid Debugger,
+reprinted in this volume.
+.TL
+Appendix
+.LP
+There are two important differences between Acid described in the
+accompanying paper, and Acid as distributed with Inferno for use in
+kernel debugging.
+.SH
+Connecting Acid to the remote Inferno kernel
+.PP
+A remote Plan 9 kernel can be debugged in the same
+way as a Plan 9 user process, using the
+file server
+.I rdbfs (4).
+It is a user-level file server on Plan 9 that
+uses a special debugging protocol on a serial connection to
+the remote kernel, but on the Plan 9 side serves a file system interface
+like that of
+.I proc (3),
+for use by Acid.
+Acid therefore does not need any special code to access the remote kernel's memory,
+or exert control over it.
+.PP
+Inferno's version of Acid currently runs under the host operating systems,
+which do not support such a mechanism (except for Plan 9).
+Instead, Acid itself provides a special debugging protocol,
+with (host) platform-specific interface code to access a serial port.
+This might well be addressed in future by implementing the native kernel debugger
+in Limbo.
+.SH
+Handling of breakpoints
+.PP
+.de Ip
+.KS
+.LP
+.tl '\f2\\$1\fP\ \ \f(CW\\$2(\f2\\$3\f(CW)\f1''\\$4'
+.IP
+..
+.de Ex
+.KE
+.KS
+.IP
+.ft CW
+.ta 4n +4n +4n +4n +4n +4n +4n +4n +4n +4n +4n +4n +4n +4n +4n +4n
+.nf
+.in +4n
+.br
+..
+.de Ee
+.fi
+.ft 1
+.br
+.in -4n
+.KE
+..
+The following functions are provided by the Acid library
+.CW $ROOT/lib/acid/$OBJTYPE
+for use in native kernel debugging.
+In several cases they change the behavior described in the Acid manual.
+The functions are:
+.P1
+ id = bpset(addr)
+ id = bpcondset(pid, addr, list)
+ bppush(val)
+ bpderef()
+ bpmask()
+ bpeq()
+ bpneq()
+ bpand()
+ bpor()
+ bptab()
+ addr = bpaddr(id)
+ bpdel(id)
+ bpconddel(id)
+.P2
+.PP
+With traditional breakpoints, when a program reaches an address at which a breakpoint is set, execution is halted, and the debugger is notified. In applications programming, this type of breakpoint is sufficient because communicating the break in execution to the debugger is handled by the operating system. The traditional method of handling breakpoints breaks down when program being debugged is the kernel. A breakpoint cannot entirely suspend the execution of the kernel because there is no other program that can handle the communication to the debugger.
+.PP
+Some operating systems solve this problem by including a
+`mini' operating system,
+a self-contained program within the kernel that has its own code to handle the hardware used to communicate with the remote debugger or user. There are many problems with this mechanism. First, the debugger code that lives inside the kernel must duplicate a lot of code contained elsewhere in the kernel. This makes the kernel much bigger, and can increase maintenance costs. Typically this type of debug support treats the kernel as having a single thread of control, so a breakpoint stops everything while the user decides what to do about it. The only places in the kernel breakpoints cannot be set are in the debugger itself, and in the code that handles notifying the debugger of the breakpoint.
+.PP
+The Inferno kernel takes a different approach. The remote debug support is provided by a device driver that makes use of kernel services. Communication with the remote debugger is handled by a kernel process dedicated entirely to that task. All breakpoints can be considered to be minimally conditional on two values. First, the address to take the break at, and second, the kernel process to take the break in. This method allows the kernel debugger to be implemented as a regular Inferno device driver. The device driver can make use of all the APIs available to device drivers, it does not need to be self contained. Additionally, conditional breakpoints can be set anywhere in the kernel, with two exceptions. As with traditional debugger implementations, breakpoints can not be set in the code that handles notifying the debugger of the breakpoint. Unlike traditional implementations, the code that handles the execution and evaluation of the conditions applied to the breakpoint is the only other place breakpoint
+cannot be set. Since both of these parts of the kernel code are self contained, the user can set breakpoints in any other kernel routines. For example, the user could set a breakpoint in
+.CW kread() ,
+for a given kernel process, but the debugger can still call
+.CW kread()
+itself.
+.PP
+Use of conditional breakpoints can help make the debugging process more efficient. If there is a bug that occurs in the Nth iteration of a loop, with unconditional breakpoints, user intervention is required N-1 times before reaching the state the bug occurs in. Conditional breakpoints give the user the ability to automatically check the value of N, and only take the breakpoint when it reaches the critical value.
+.PP
+The following changed
+and additional functions in the Acid library provide access
+to this extended breakpoint support:
+.SH
+Setting Breakpoints
+.LP
+.\"
+.\"
+.\"
+.Ip integer bpset integer "Set a breakpoint
+.CW bpset
+places an unconditional breakpoint for the currently
+selected kernel process at the address specified
+by its
+.I integer
+argument.
+It returns the ID of the newly created breakpoint, or the nil list on error.
+It is simply shorthand for a call
+.Ex
+bpcondset(pid, addr, {})
+.Ee
+where
+.I pid
+is the global variable identifying the currently selected process,
+.I addr
+is the user-supplied address for the breakpoint,
+and
+.CW {}
+is the empty list, signifying no conditions.
+.Ip integer bpcondset "pid,addr,list" "Set conditional breakpoint
+Sets a conditional breakpoint at addr for the kernel process identified by
+.I pid .
+The
+.I list
+argument is a list of operations that are executed when execution reaches
+.I addr .
+If execution results in a a non-zero value on the top of the stack, the breakpoint is taken, otherwise it is skipped.
+The
+.I list
+is in reverse polish notation format, and has these operations:
+.Ex
+PUSH
+DEREF (pop val, push *(ulong*)val)
+MASK (pop mask, pop value, push value & mask)
+EQ (pop v1, pop v2, push v1 == v2)
+NEQ (pop v1, pop v2, push v1 != v2)
+AND (pop v1, pop v2, push v1 && v1)
+OR (pop v1, pop v2, push v1 || v2)
+.Ee
+Condition lists are executed in a single pass, starting with the first command in the list, ending with the last. If a nonzero value is on the top of the stack at the end of execution, the breakpoint is taken, otherwise it is skipped.
+.RS
+.LP
+In effect, there are two mandatory conditions, the address of the breakpoint, and the kernel process id. These two conditions must be met for the condition list to be processed. If these conditions are met, the entire condition list is processed, there is no short circuit evaluation path.
+.LP
+For example, given the following code fragment:
+.P1 +.4i
+int i;
+
+for(i=0; i<1000; i++) {
+ ...
+}
+.P2
+the following call to
+.CW bpcondset()
+sets a conditional breakpoint to be taken when execution reaches
+.I addr
+in kernel process
+.I pid
+on the 500th iteration of the loop:
+.P1 +.4i
+bpcondset(pid, addr, {bppush(i),
+ bpderef(), bppush(500), bpeq()});
+.P2
+.RE
+.SH
+Condition List Construction
+.LP
+.Ip list bppush val "Construct breakpoint stack
+Push val onto the stack.
+.KE
+.Ip list bpderef "" "Construct breakpoint stack
+Replace the value at the top of the stack with the value found at the address obtained by treating value at the top of the stack as an address. Pop the value on the top of the stack, treat it as a ulong*, and push the value at the address.
+.Ex
+addr = pop();
+push(*(ulong*)addr);
+.Ee
+.Ip list bpmask "" "Construct breakpoint stack
+Replace the top two values on the stack with the value obtained by masking the second value on the stack with the top of the stack.
+.Ex
+mask = pop();
+value = pop();
+push(value & mask);
+.Ee
+.Ip list bpeq "" "Construct breakpoint stack
+Comparison of the top two values on the stack. Replace the top two values on the stack with a 1 if the values are equal, or a zero if they are not.
+.Ex
+v1 = pop();
+v2 = pop();
+push(v1 == v2);
+.Ee
+.Ip list bpneq "" "Construct breakpoint stack
+Negative comparison of the top two values on the stack. Replace the top two values on the stack with a 0 if the values are equal, or 1 if they are not.
+.Ex
+v1 = pop();
+v2 = pop();
+push(v1 != v2);
+.Ee
+.Ip list bpand "" "Construct breakpoint stack
+Logical and of the top two values on the stack. Replace the top two values on the stack with a 0 if both are zero, or 1 if both are nonzero.
+.Ex
+v1 = pop();
+v2 = pop();
+push(v1 && v2);
+.Ee
+.Ip list bpor "" "Construct breakpoint stack
+Logical or of the top two values on the stack. Replace the top two values on the stack with a 1 if either is nonzero, 0 otherwise.
+.Ex
+v1 = pop();
+v2 = pop();
+push(v1 || v2);
+.Ee
+.SH
+Breakpoint Status
+.LP
+.Ip {} bptab "" "List active breakpoints
+Prints the list of breakpoints containing the following information in order: breakpoint number, kernel process id, breakpoint address, and the list of conditions to execute to determine if the breakpoint will be taken.
+.Ex
+acid: bptab()
+ID PID ADDR CONDITIONS
+0 1 consread+0x20 0x216cc {}
+acid:
+.Ee
+.Ip integer bpaddr id "Address of breakpoint
+Returns the address the breakpoint identified by
+.I id
+is set to trigger on.
+.KE
+.SH
+Deleting breakpoints
+.Ip {} bpdel id "Delete breakpoint
+Delete the breakpoint identified by
+.I id .
+Shorthand for bpconddel().
+.KE
+.Ip {} bpconddel id "Delete conditional breakpoint
+Delete the conditional breakpoint identified by the integer
+.I id .
+.KE
binary files /dev/null b/doc/acidtut.pdf differ
--- /dev/null
+++ b/doc/acme/acme.ms
@@ -1,0 +1,1295 @@
+.de EX
+.nr x \\$1v
+\\!h0c n \\nx 0
+..
+.de FG \" start figure caption: .FG filename.ps verticalsize
+.KF
+.BP \\$1 \\$2
+.sp .5v
+.EX \\$2v
+.ps -1
+.vs -1
+..
+.de fg \" end figure caption (yes, it is clumsy)
+.ps
+.vs
+.br
+\l'1i'
+.KE
+..
+.TL
+Acme: A User Interface for Programmers
+.AU
+.I "Rob Pike
+.I rob@plan9.bell-labs.com
+.SP .22i exactly
+.AB
+.FS
+\l'1i'
+.br
+Originally appeared in
+.I
+Proc. of the Winter 1994 USENIX Conf.,
+.R
+pp. 223-234,
+San Francisco, CA
+.br
+Reprinted in
+.I "Plan 9 Programmer's Manual: Volume 2"
+(Second Edition), AT&T 1995.
+.FE
+A hybrid of window system, shell, and editor, Acme gives text-oriented
+applications a clean, expressive, and consistent style of interaction.
+Traditional window systems support interactive client programs and offer libraries of
+pre-defined operations such as pop-up menus
+and buttons to promote a consistent
+user interface among the clients.
+Acme instead provides its clients with a fixed user interface and
+simple conventions to encourage its uniform use.
+Clients access the facilities of Acme through a file system interface;
+Acme is in part a file server that exports device-like files that may be
+manipulated to access and control the contents of its windows.
+Written in a concurrent programming language,
+Acme is structured as a set of communicating processes that neatly subdivide
+the various aspects of its tasks: display management, input, file server, and so on.
+.PP
+Acme attaches distinct functions to the three mouse buttons:
+the left selects text;
+the middle executes textual commands;
+and the right combines context search and file opening
+functions to integrate the various applications and files in
+the system.
+.PP
+Acme works well enough to have developed
+a community that uses it exclusively.
+Although Acme discourages the traditional style of interaction
+based on typescript windows\(emteletypes\(emits
+users find Acme's other services render
+typescripts obsolete.
+.AE
+.SH
+History and motivation
+.PP
+The usual typescript style of interaction with
+Unix and its relatives is an old one.
+The typescript\(eman intermingling of textual commands and their
+output\(emoriginates with the scrolls of paper on teletypes.
+The advent of windowed terminals has given each user what
+amounts to an array of teletypes, a limited and unimaginative
+use of the powers of bitmap displays and mice.
+Systems like the Macintosh
+that do involve the mouse as an integral part of the interaction
+are geared towards general users, not experts, and certainly
+not programmers.
+Software developers, at least on time-sharing systems, have been left behind.
+.FG ./acme.fig1 5i
+Figure 1. A small Acme screen\(emnormally it runs on a larger display\(emdemonstrating
+some of the details discussed in the text.
+The right column contains some guide files,
+a mailbox presented by Acme's mail program,
+the columnated display of files in Acme's own source directory,
+a couple of windows from the OED browser,
+a debugger window,
+and an error window showing diagnostics from a compilation.
+The left column holds a couple of source files
+.CW dat.h "" (
+and
+.CW acme.l ),
+another debugger window displaying a stack trace,
+and a third source file
+.CW time.l ). (
+.CW Time.l
+was opened from the debugger by clicking the right mouse button
+on a line in the stack window;
+the mouse cursor landed on the offending line of
+.CW acme.l
+after a click on the compiler message.
+.fg
+.PP
+Some programs have mouse-based editing of
+text files and typescripts;
+ones I have built include
+the window systems
+.CW mux
+[Pike88]
+and
+.CW 8½
+[Pike91]
+and the text editor
+Sam [Pike87].
+These have put the programmer's mouse to some productive work,
+but not wholeheartedly. Even experienced users of these programs
+often retype text that could be grabbed with the mouse,
+partly because the menu-driven interface is imperfect
+and partly because the various pieces are not well enough integrated.
+.PP
+Other programs\(emEMACS [Stal93] is the prime example\(emoffer a high
+degree of integration but with a user interface built around the
+ideas of cursor-addressed terminals that date from the 1970's.
+They are still keyboard-intensive and
+dauntingly complex.
+.PP
+The most ambitious attempt to face these issues was the Cedar
+system, developed at Xerox [Swei86].
+It combined a new programming language, compilers,
+window system, even microcode\(ema complete system\(emto
+construct a productive, highly
+integrated and interactive environment
+for experienced users of compiled languages.
+Although successful internally, the system was so large
+and so tied to specific hardware that it never fledged.
+.PP
+Cedar was, however, the major inspiration for Oberon [Wirt89],
+a system of similar scope but much smaller scale.
+Through careful selection of Cedar's ideas, Oberon shows
+that its lessons can be applied to a small, coherent system
+that can run efficiently on modest hardware.
+In fact, Oberon probably
+errs too far towards simplicity: a single-process system
+with weak networking, it seems an architectural throwback.
+.PP
+Acme is a new program,
+a combined window system, editor, and shell,
+that applies
+some of the ideas distilled by Oberon.
+Where Oberon uses objects and modules within a programming language (also called Oberon),
+Acme uses files and commands within an existing operating system (Plan 9).
+Unlike Oberon, Acme does not yet have support for graphical output, just text.
+At least for now, the work on Acme has concentrated on
+producing the smoothest user interface possible for a programmer
+at work.
+.PP
+The rest of this paper describes Acme's interface,
+explains how programs can access it,
+compares it to existing systems,
+and finally presents some unusual aspects of its implementation.
+.SH
+User interface
+.PP
+.FG ./acme.fig2 3i
+Figure 2. An Acme window showing a section of code.
+The upper line of text is the tag containing the file name,
+relevant commands, and a scratch area (right of the vertical bar);
+the lower portion of the window is the
+body, or contents, of the file.
+Here the scratch area contains a command for the middle button
+.CW mk ) (
+and a word to search for with the right button
+.CW cxfidalloc ). (
+The user has just
+clicked the right button on
+.CW cxfidalloc
+and Acme has searched for the word, highlighted it,
+and moved the mouse cursor there. The file has been modified:
+the center of the layout box is black and the command
+.CW Put
+appears in the tag.
+.fg
+Acme windows are arrayed in columns (Figure 1) and are used more
+dynamically than in an environment like X Windows or
+.CW 8½
+[Sche86, Pike91].
+The system frequently creates them automatically and the user
+can order a new one with a single mouse button click.
+The initial placement of a new window is determined
+automatically, but the user may move an existing window anywhere
+by clicking or dragging a
+.I "layout box
+in the upper left corner of
+the window.
+.PP
+Acme windows have two parts: a
+.I tag
+holding a single line of text,
+above a
+.I body
+holding zero or more lines (Figure 2).
+The body typically contains an image of a file being edited
+or the editable output of a
+program, analogous to an
+EMACS shell
+window. The tag contains
+the name of the window
+(usually the name of the associated
+file or directory), some built-in commands, and a scratch area to hold arbitrary text.
+If a window represents a directory, the name in the tag ends with
+a slash and the body contains a list of the names of the files
+in the directory.
+Finally, each non-empty body holds a scroll bar at the left of the text.
+.PP
+Each column of windows also has a layout box and a tag.
+The tag has no special meaning, although Acme pre-loads it with a few
+built-in commands.
+There is also a tag across the whole display, also loaded with
+helpful commands and a list of active processes started
+by Acme.
+.PP
+Typing with the keyboard and selecting with the left button are as in
+many other systems, including the Macintosh,
+.CW 8½ ,
+and Sam.
+The middle and right buttons are used, somewhat like the left button,
+to `sweep' text, but the indicated text is treated in a way
+that depends on the text's location\(em\f2context\f1\(emas well as its content.
+This context, based on the directory of the file containing the text,
+is a central component of Acme's style of interaction.
+.PP
+Acme has no single notion of `current directory'.
+Instead, every command, file name,
+action, and so on is interpreted or executed in the directory named by the
+tag of the window containing the command. For example, the string
+.CW mammals
+in a window labeled
+.CW /lib/
+or
+.CW /lib/insects
+will be interpreted as the file name
+.CW /lib/mammals
+if such a file exists.
+.PP
+Throughout Acme, the middle mouse button is used to execute commands
+and the right mouse button is used to locate and select files and text.
+Even when there are no true files on which to operate\(emfor example
+when editing mail messages\(emAcme and its applications use
+consistent extensions of these basic functions.
+This idea is as vital to Acme as icons are to the Macintosh.
+.PP
+The middle button executes commands: text swept with the button
+pressed is underlined; when the button is released, the underline is
+removed and the indicated text is executed.
+A modest number of commands are recognized as built-ins: words like
+.CW Cut ,
+.CW Paste ,
+and
+.CW New
+name
+functions performed directly by Acme.
+These words often appear in tags to make them always available,
+but the tags are not menus: any text anywhere in Acme may be a command.
+For example, in the tag or body of any window one may type
+.CW Cut ,
+select it with the left button, use the middle button to execute it,
+and watch it disappear again.
+.PP
+If the middle button indicates a command that is not recognized as a built-in,
+it is executed in the directory
+named by the tag of the window holding the text.
+Also, the file to be executed is searched for first in that directory.
+Standard input is connected to
+.CW /dev/null ,
+but standard and error outputs are connected to an Acme window,
+created if needed, called
+\f2dir\f(CW/+Errors\f1 where
+.I dir
+is the directory of the window.
+(Programs that need interactive input use a different interface, described below.)
+A typical use of this is to type
+.CW mk
+(Plan 9's
+.CW make )
+in the scratch area in the tag of a C source window, say
+.CW /sys/src/cmd/sam/regexp.c ,
+and execute it.
+Output, including compiler errors, appears in the window labeled
+.CW /sys/src/cmd/sam/+Errors ,
+so file names in the output are associated with the windows and directory
+holding the source.
+The
+.CW mk
+command remains in the tag, serving as a sort of menu item for the associated
+window.
+.PP
+Like the middle button, the right button is used to indicate text by sweeping it out.
+The indicated text is not a command, however, but the argument of a generalized
+search operator.
+If the text, perhaps after appending it to the directory of the window containing it,
+is the name of an existing file, Acme creates a new window to hold the file
+and reads it in. It then moves the mouse cursor to that window. If the file is
+already loaded into Acme, the mouse motion happens but no new window is made.
+For example, indicating the string
+.CW sam.h
+in
+.P1
+#include "sam.h"
+.P2
+in a window on the file
+.CW /sys/src/cmd/sam/regexp.c
+will open the file
+.CW /sys/src/cmd/sam/sam.h .
+.PP
+If the file name is followed immediately by a colon and a legal address in
+Sam notation (for example a line number or a regular expression delimited in
+slashes or a comma-separated compound of such addresses), Acme highlights
+the target of that address in the file and places the mouse there. One may jump to
+line 27 of
+.CW dat.h
+by indicating with the right button the text
+.CW dat.h:27 .
+If the file is not already open, Acme loads it.
+If the file name is null, for example if the indicated string is
+.CW :/^main/ ,
+the file is assumed to be that of the window containing the string.
+Such strings, when typed and evaluated in the tag of a window, amount to
+context searches.
+.PP
+If the indicated text is not the name of an existing file, it is taken to be literal
+text and is searched for in the body of the window containing the text, highlighting
+the result as if it were the result of a context search.
+.PP
+For the rare occasion when a file name
+.I is
+just text to search for, it can be selected with the left button and used as the
+argument to a built-in
+.CW Look
+command that always searches for literal text.
+.SH
+Nuances and heuristics
+.PP
+A user interface should not only provide the necessary functions, it should also
+.I feel
+right.
+In fact, it should almost not be felt at all; when one notices a
+user interface, one is distracted from the job at hand [Pike88].
+To approach this invisibility, some of Acme's properties and features
+are there just to make the others easy to use.
+Many are based on a fundamental principle of good design:
+let the machine do the work.
+.PP
+Acme tries to avoid needless clicking and typing.
+There is no `click-to-type', eliminating a button click.
+There are no pop-up or pull-down menus, eliminating the mouse action needed to
+make a menu appear.
+The overall design is intended to make text on the screen useful without
+copying or retyping; the ways in which this happens involve
+the combination of many aspects of the interface.
+.PP
+Acme tiles its windows and places them automatically
+to avoid asking the user to place and arrange them.
+For this policy to succeed, the automatic placement must behave well enough
+that the user is usually content with the location of a new window.
+The system will never get it right all the time, but in practice most
+windows are used at least for a while where Acme first places them.
+There have been several complete rewrites of the
+heuristics for placing a new window,
+and with each rewrite the system became
+noticeably more comfortable. The rules are as follows, although
+they are still subject to improvement.
+The window appears in the `active' column, that most recently used for typing or
+selecting.
+Executing and searching do not affect the choice of active column,
+so windows of commands and such do not draw new windows towards them,
+but rather let them form near the targets of their actions.
+Output (error) windows always appear towards the right, away from
+edited text, which is typically kept towards the left.
+Within the column, several competing desires are balanced to decide where
+and how large the window should be:
+large blank spaces should be consumed;
+existing text should remain visible;
+existing large windows should be divided before small ones;
+and the window should appear near the one containing the action that caused
+its creation.
+.PP
+Acme binds some actions to chords of mouse buttons.
+These include
+.CW Cut
+and
+.CW Paste
+so these common operations can be done without
+moving the mouse.
+Another is a way to apply a command in one window to text (often a file name)
+in another, avoiding the actions needed to assemble the command textually.
+.PP
+Another way Acme avoids the need to move the mouse is instead to move the cursor
+to where it is likely to be used next. When a new window is made, Acme
+moves the cursor to the new window; in fact, to the selected text in that window.
+When the user deletes a newly made window, the cursor is
+returned to the point it was before the window was made,
+reducing the irritation of windows that pop up to report annoying errors.
+.PP
+When a window is moved, Acme moves the cursor to the layout box in
+its new place, to permit further adjustment without moving the mouse.
+For example, when a click of the left mouse button on the layout box grows
+the window, the cursor moves to the new location of the box so repeated clicks,
+without moving the mouse, continue to grow it.
+.PP
+Another form of assistance the system can offer is to supply precision in
+pointing the mouse. The best-known form of this is `double-clicking' to
+select a word rather than carefully sweeping out the entire word.
+Acme provides this feature, using context to decide whether to select
+a word, line, quoted string, parenthesized expression, and so on.
+But Acme takes the idea much further by applying it to execution
+and searching.
+A
+.I single
+click, that is, a null selection, with either the middle or right buttons,
+is expanded automatically to indicate the appropriate text containing
+the click. What is appropriate depends on the context.
+.PP
+For example, to execute a single-word command
+such as
+.CW Cut ,
+it is not necessary to sweep the entire word; just clicking the button once with
+the mouse pointing at the word is sufficient. `Word'
+means the largest string of likely file name characters surrounding the location
+of the click: click on a file name, run that program.
+On the right button, the rules are more complicated because
+the target of the click might be a file name, file name with address,
+or just plain text. Acme examines the text near the click to find
+a likely file name;
+if it finds one, it checks that it names an existing file (in the directory named in the tag, if the name is relative)
+and if so, takes that as the result, after extending it with any address
+that may be present. If there is no file with that name, Acme
+just takes the largest alphanumeric string under the click.
+The effect is a natural overloading of the button to refer to plain text as
+well as file names.
+.PP
+First, though, if the click occurs over the left-button-selected text in the window,
+that text is taken to be what is selected.
+This makes it easy to skip through the occurrences of a string in a file: just click
+the right button
+on some occurrence of the text in the window (perhaps after typing it in the tag)
+and click once for each subsequent occurrence. It isn't even necessary to move
+the mouse between clicks; Acme does that.
+To turn a complicated command into a sort of menu item, select it:
+thereafter, clicking the middle button on it will execute the full command.
+.PP
+As an extra feature, Acme recognizes file names in angle brackets
+.CW <>
+as names of files in standard directories of include files,
+making it possible for instance to look at
+.CW <stdio.h>
+with a single click.
+.PP
+Here's an example to demonstrate how the actions and defaults work together.
+Assume
+.CW /sys/src/cmd/sam/regexp.c
+is
+open and has been edited. We write it (execute
+.CW Put
+in the tag; once the file is written, Acme removes the word from the tag)
+and type
+.CW mk
+in the tag. We execute
+.CW mk
+and get some errors, which appear in a new window labeled
+.CW /sys/src/cmd/sam/+Errors .
+The cursor moves automatically to that window.
+Say the error is
+.P1
+main.c:112: incompatible types on assignment to `pattern'
+.P2
+We move the mouse slightly and click the right button
+at the left of the error message; Acme
+makes a new window, reads
+.CW /sys/src/cmd/main.c
+into it, selects line 112
+and places the mouse there, right on the offending line.
+.SH
+Coupling to existing programs
+.PP
+Acme's syntax for file names and addresses makes it easy for other programs
+to connect automatically to Acme's capabilities. For example, the output of
+.P1
+grep -n variable *.[ch]
+.P2
+can be used to help Acme step through the occurrences of a variable in a program;
+every line of output is potentially a command to open a file.
+The file names need not be absolute, either: the output
+appears in a window labeled with the directory in which
+.CW grep
+was run, from which Acme can derive the full path names.
+.PP
+When necessary, we have changed the output of some programs,
+such as compiler error messages, to match
+Acme's syntax.
+Some might argue that it shouldn't be necessary to change old programs,
+but sometimes programs need to be updated when systems change,
+and consistent output benefits people as well as programs.
+A historical example is the retrofitting of standard error output to the
+early Unix programs when pipes were invented.
+.PP
+Another change was to record full path names in
+the symbol table of executables, so line numbers reported by the debugger
+are absolute names that may be used directly by Acme; it's not necessary
+to run the debugger in the source directory. (This aids debugging
+even without Acme.)
+.PP
+A related change was to add lines of the form
+.P1
+#pragma src "/sys/src/libregexp"
+.P2
+to header files; coupled with Acme's ability to locate a header file,
+this provides a fast, keyboardless way to get the source associated with a library.
+.PP
+Finally, Acme directs the standard output of programs it runs to
+windows labeled by the directory in which the program is run.
+Acme's splitting of the
+output into directory-labeled windows is a small feature that has a major effect:
+local file names printed by programs can be interpreted directly by Acme.
+By indirectly coupling the output of programs to the input,
+it also simplifies the management of software that occupies multiple
+directories.
+.SH
+Coupling to new programs
+.PP
+Like many Plan 9 programs,
+Acme offers a programmable interface to
+other programs by acting as a file server.
+The best example of such a file server is the window system
+.CW 8½
+[Pike91],
+which exports files with names such as
+.CW screen ,
+.CW cons ,
+and
+.CW mouse
+through which applications may access the I/O capabilities of the windows.
+.CW 8½
+provides a
+.I distinct
+set of files for each window and builds a private file name space
+for the clients running `in' each window;
+clients in separate windows see distinct files with the same names
+(for example
+.CW /dev/mouse ).
+Acme, like the process file system [PPTTW93], instead associates each
+window with a directory of files; the files of each window are visible
+to any application.
+This difference reflects a difference in how the systems are used:
+.CW 8½
+tells a client what keyboard and mouse activity has happened in its window;
+Acme tells a client what changes that activity wrought on any window it asks about.
+Putting it another way,
+.CW 8½
+enables the construction of interactive applications;
+Acme provides the interaction for applications.
+.PP
+The root of
+Acme's file system is mounted using Plan 9 operations on the directory
+.CW /mnt/acme .
+In
+that root directory appears a directory for each window, numbered with the window's identifier,
+analogous to a process identifier, for example
+.CW /mnt/acme/27 .
+The window's directory
+contains 6 files:
+.CW /mnt/acme/27/addr ,
+.CW body ,
+.CW ctl ,
+.CW data ,
+.CW event ,
+and
+.CW tag .
+The
+.CW body
+and
+.CW tag
+files contain the text of the respective parts of the window; they may be
+read to recover the contents. Data written to these files is appended to the text;
+.CW seeks
+are ignored.
+The
+.CW addr
+and
+.CW data
+files provide random access to the contents of the body.
+The
+.CW addr
+file is written to set a character position within the body; the
+.CW data
+file may then be read to recover the contents at that position,
+or written to change them.
+(The tag is assumed
+small and special-purpose enough not to need special treatment.
+Also,
+.CW addr
+indexes by character position, which is not the same as byte offset
+in Plan 9's multi-byte character set [Pike93]).
+The format accepted by the
+.CW addr
+file is exactly the syntax of addresses within the user interface,
+permitting regular expressions, line numbers, and compound addresses
+to be specified. For example, to replace the contents of lines 3 through 7,
+write the text
+.P1
+3,7
+.P2
+to the
+.CW addr
+file, then write the replacement text to the
+.CW data
+file. A zero-length write deletes the addressed text; further writes extend the replacement.
+.PP
+The control file,
+.CW ctl ,
+may be written with commands to effect actions on the window; for example
+the command
+.P1
+name /adm/users
+.P2
+sets the name in the tag of the window to
+.CW /adm/users .
+Other commands allow deleting the window, writing it to a file, and so on.
+Reading the
+.CW ctl
+file recovers a fixed-format string containing 5 textual numbers\(emthe window
+identifier, the number of characters in the tag, the number in the body,
+and some status information\(emfollowed by the text of the tag, up to a newline.
+.PP
+The last file,
+.CW event ,
+is the most unusual.
+A program reading a window's
+.CW event
+file is notified of all changes to the text of the window, and
+is asked to interpret all middle- and right-button actions.
+The data passed to the program is fixed-format and reports
+the source of the action (keyboard, mouse, external program, etc.),
+its location (what was pointed at or modified), and its nature (change,
+search, execution, etc.).
+This message, for example,
+.P1
+MI15 19 0 4 time
+.P2
+reports that actions of the mouse
+.CW M ) (
+inserted in the body (capital
+.CW I )
+the 4 characters of
+.CW time
+at character positions 15 through 19; the zero is a flag word.
+Programs may apply their own interpretations of searching and
+execution, or may simply reflect the events back to Acme,
+by writing them back to the
+.CW event
+file, to have the default interpretation applied.
+Some examples of these ideas in action are presented below.
+.PP
+Notice that changes to the window are reported
+after the fact; the program is told about them but is not required to act
+on them. Compare this to a more traditional interface in which a program
+is told, for example, that a character has been typed on the keyboard and
+must then display and interpret it.
+Acme's style stems from the basic model of the system, in which any
+number of agents\(emthe keyboard, mouse, external programs
+writing to
+.CW data
+or
+.CW body ,
+and so on\(emmay
+change the contents of a window.
+The style is efficient: many programs are content
+to have Acme do most of the work and act only when the editing is completed.
+An example is the Acme mail program, which can ignore the changes
+made to a message being composed
+and just read its body when asked to send it.
+A disadvantage is that some traditional ways of working are impossible.
+For example, there is no way `to turn off echo': characters appear on the
+screen and are read from there; no agent or buffer stands between
+the keyboard and the display.
+.PP
+There are a couple of other files made available by Acme in its root directory
+rather than in the directory of each window.
+The text file
+.CW /mnt/acme/index
+holds a list of all window names and numerical identifiers,
+somewhat analogous to the output of the
+.CW ps
+command for processes.
+The most important, though, is
+.CW /mnt/acme/new ,
+a directory that makes new windows, similar to the
+.CW clone
+directory in the Plan 9 network devices [Pres93].
+The act of opening any file in
+.CW new
+creates a new Acme window; thus the shell command
+.P1
+grep -n var *.c > /mnt/acme/new/body
+.P2
+places its output in the body of a fresh window.
+More sophisticated applications may open
+.CW new/ctl ,
+read it to discover the new window's identifier, and then
+open the window's other files in the numbered directory.
+.SH
+Acme-specific programs
+.PP
+Although Acme is in part an attempt to move beyond typescripts,
+they will probably always have utility.
+The first program written for Acme was therefore one
+to run a shell or other traditional interactive application
+in a window, the Acme analog of
+.CW xterm .
+This program,
+.CW win ,
+has a simple structure:
+it acts as a two-way intermediary between Acme and the shell,
+cross-connecting the standard input and output of the shell to the
+text of the window.
+The style of interaction is modeled after
+.CW mux
+[Pike88]: standard output is added to the window at the
+.I "output point;
+text typed after the output point
+is made available on standard input when a newline is typed.
+After either of these actions, the output point is advanced.
+This is different from the working of a regular terminal,
+permitting cut-and-paste editing of an input line until the newline is typed.
+Arbitrary editing may be done to any text in the window.
+The implementation of
+.CW win ,
+using the
+.CW event ,
+.CW addr ,
+and
+.CW data
+files, is straightforward.
+.CW Win
+needs no code for handling the keyboard and mouse; it just monitors the
+contents of the window. Nonetheless, it allows Acme's full editing to be
+applied to shell commands.
+The division of labor between
+.CW win
+and
+.CW Acme
+contrasted with
+.CW xterm
+and the X server demonstrates how much work Acme handles automatically.
+.CW Win
+is implemented by a single source file 560 lines long and has no graphics code.
+.PP
+.CW Win
+uses the middle and right buttons to connect itself in a consistent way
+with the rest of Acme.
+The middle button still executes commands, but in a style more suited
+to typescripts. Text selected with the middle button is treated as if
+it had been typed after the output point, much as a similar feature in
+.CW xterm
+or
+.CW 8½ ,
+and therefore causes it to be `executed' by the application running in the window.
+Right button actions are reflected back to Acme but refer to the appropriate
+files because
+.CW win
+places the name of the current directory in the tag of the window.
+If the shell is running, a simple shell function replacing the
+.CW cd
+command can maintain the tag as the shell navigates the file system.
+This means, for example, that a right button click on a file mentioned in an
+.CW ls
+listing opens the file within Acme.
+.PP
+Another Acme-specific program is a mail reader that begins by presenting,
+in a window, a listing of the messages in the user's mailbox, one per line.
+Here the middle and right button actions are modified to refer to
+mail commands
+and messages, but the change feels natural.
+Clicking the right button on a line creates a new window and displays the
+message there, or, if it's already displayed, moves the mouse to that window.
+The metaphor is that the mailbox is a directory whose constituent files are messages.
+The mail program also places some relevant commands in the tag lines of
+the windows; for example, executing the word
+.CW Reply
+in a message's tag creates a new window
+in which to compose a message to the sender of the original;
+.CW Post
+then dispatches it.
+In such windows, the addressee is just a list of names
+on the first line of the body, which may be edited to add or change recipients.
+The program also monitors the mailbox, updating the `directory' as new messages
+arrive.
+.PP
+The mail program is as simple as it sounds; all the work of interaction,
+editing, and management of the display is done by Acme.
+The only
+difficult sections of the 1200
+lines of code concern honoring the external protocols for managing
+the mailbox and connecting to
+.CW sendmail .
+.PP
+One of the things Acme does not provide directly is a facility like
+Sam's command language to enable actions such as global substitution;
+within Acme, all editing is done manually.
+It is easy, though, to write external programs for such tasks.
+In this, Acme comes closer to the original intent of Oberon:
+a directory,
+.CW /acme/edit ,
+contains a set of tools for repetitive editing and a template
+or `guide' file that gives examples
+of its use.
+Acme's editing guide,
+.CW /acme/edit/guide ,
+looks like this:
+.P1
+e file | x '/regexp/' | c 'replacement'
+e file:'0,$' | x '/.*word.*\en/' | p -n
+e file | pipe command args ...
+.P2
+The syntax is reminiscent of Sam's command language, but here the individual
+one-letter commands are all stand-alone programs connected by pipes.
+Passed along the pipes are addresses, analogous to structural expressions
+in Sam terminology.
+The
+.CW e
+command, unlike that of Sam, starts the process by generating the address
+(default dot, the highlighted selection) in the named files.
+The other commands are as in Sam:
+.CW p
+prints the addressed text on standard output (the
+.CW -n
+option is analogous to that of
+.CW grep ,
+useful in combination with the right mouse button);
+.CW x
+matches a regular expression to the addressed (incoming) text,
+subdividing the text;
+.CW c
+replaces the text; and so on. Thus, global substitution throughout a file,
+which would be expressed in Sam as
+.P1
+0,$ x/regexp/ c/replacement/
+.P2
+in Acme's editor becomes
+.P1
+e 'file:0,$' | x '/regexp/' | c 'replacement'
+.P2
+.PP
+To use the Acme editing commands, open
+.CW /acme/edit/guide ,
+use the mouse and keyboard to edit one of the commands to the right form,
+and execute it with the middle button.
+Acme's context rules find the appropriate binaries in
+.CW /acme/edit
+rather than
+.CW /bin ;
+the effect is to turn
+.CW /acme/edit
+into a toolbox containing tools and instructions (the guide file) for their use.
+In fact, the source for these tools is also there, in the directory
+.CW /acme/edit/src .
+This setup allows some control of the file name space for binary programs;
+not only does it group related programs, it permits the use of common
+names for uncommon jobs. For example, the single-letter names would
+be unwise in a directory in everyone's search path; here they are only
+visible when running editing commands.
+.PP
+In Oberon,
+such a collection would be called a
+.I tool
+and would consist
+of a set of entry points in a module and a menu-like piece of text containing
+representative commands that may be edited to suit and executed.
+There is, in fact, a tool called
+.CW Edit
+in Oberon.
+To provide related functionality,
+Acme exploits the directory and file structure of the underlying
+system, rather than the module structure of the language;
+this fits well with Plan 9's
+file-oriented philosophy.
+Such tools are central to the working of Oberon but they are
+less used in Acme, at least so far.
+The main reason is probably that Acme's program interface permits
+an external program to remain executing in the background, providing
+its own commands as needed (for example, the
+.CW Reply
+command in the mail program); Oberon uses tools to
+implement such services because its must invoke
+a fresh program for each command.
+Also,
+Acme's better integration allows more
+basic functions to be handled internally; the right mouse button
+covers a lot of the basic utility of the editing tools in Oberon.
+Nonetheless, as more applications are written for Acme,
+many are sure to take this Oberon tool-like form.
+.SH
+Comparison with other systems
+.PP
+Acme's immediate ancestor is Help [Pike92], an experimental system written
+a few years ago as a first try at exploring some of Oberon's ideas
+in an existing operating system.
+Besides much better engineering, Acme's advances over Help
+include the actions of the right button (Help had nothing comparable),
+the ability to connect long-running programs to the user interface
+(Help had no analog of the
+.CW event
+file),
+and the small but important change to split command output into
+windows labeled with the directory in which the commands run.
+.PP
+Most of Acme's style, however, derives from the user interface and window
+system of Oberon [Wirt89, Reis91].
+Oberon includes a programming language and operating system,
+which Acme instead borrows from an existing system, Plan 9.
+When I first saw Oberon, in 1988, I was struck by the
+simplicity of its user interface, particularly its lack of menus
+and its elegant use of multiple mouse buttons.
+The system seemed restrictive, though\(emsingle process,
+single language, no networking, event-driven programming\(emand
+failed to follow through on some of its own ideas.
+For example, the middle mouse button had to be pointed accurately and
+the right button was essentially unused.
+Acme does follow through:
+to the basic idea planted by Oberon, it adds
+the ability to run on different operating systems and hardware,
+connection to existing applications including
+interactive ones such as shells and debuggers,
+support for multiple processes,
+the right mouse button's features,
+the default actions and context-dependent properties
+of execution and searching,
+and a host of little touches such as moving the mouse cursor that make the system
+more pleasant.
+At the moment, though, Oberon does have one distinct advantage: it incorporates
+graphical programs well into its model, an issue Acme has not yet faced.
+.PP
+Acme shares with the Macintosh a desire to use the mouse well and it is
+worth comparing the results.
+The mouse on the Macintosh has a single button, so menus are essential
+and the mouse must frequently move a long way
+to reach the appropriate function.
+An indication that this style has trouble is that applications provide
+keyboard sequences to invoke menu selections and users often prefer them.
+A deeper comparison is that the Macintosh uses pictures where Acme uses text.
+In contrast to pictures, text can be edited quickly, created on demand,
+and fine-tuned to the job at hand; consider adding an option to a command.
+It is also self-referential; Acme doesn't need menus because any text can be
+in effect a menu item.
+The result is that, although a Macintosh screen is certainly prettier and probably
+more attractive, especially to beginners, an Acme screen is more dynamic
+and expressive, at least for programmers and experienced users.
+.PP
+For its role in the overall system,
+Acme most resembles EMACS [Stal93].
+It is tricky to compare Acme to EMACS, though, because there are
+many versions of EMACS and, since it is fully programmable, EMACS
+can in principle do anything Acme does.
+Also, Acme is much younger and therefore has not
+had the time to acquire as many features.
+The issue therefore is less what the systems can be programmed to do than
+how they are used.
+The EMACS versions that come closest to Acme's style are those that
+have been extended to provide a programming environment, usually
+for a language such as LISP [Alle92, Lucid92].
+For richness of the existing interface, these EMACS versions are certainly superior to Acme.
+On the other hand, Acme's interface works equally well already for a variety
+of languages; for example, one of its most enthusiastic users works almost
+exclusively in Standard ML, a language nothing like C.
+.PP
+Where Acme excels is in the smoothness of its interface.
+Until recently, EMACS did not support the mouse especially well,
+and even with the latest version providing features such as `extents'
+that can be programmed to behave much like Acme commands,
+many users don't bother to upgrade.
+Moreover, in the versions that provide extents,
+most EMACS packages don't take advantage of them.
+.PP
+The most important distinction is just that
+EMACS is fundamentally keyboard-based, while
+Acme is mouse-based.
+.PP
+People who try Acme find it hard to go back to their previous environment.
+Acme automates so much that to return to a traditional interface
+is to draw attention to the extra work it requires.
+.SH
+Concurrency in the implementation
+.PP
+Acme is about 8,000 lines of code in Alef, a concurrent object-oriented language syntactically similar to C [Alef].
+Acme's structure is a set of communicating
+processes in a single address space.
+One subset of the processes drives the display and user interface,
+maintaining the windows; other processes forward mouse and keyboard
+activity and implement the file server interface for external programs.
+The language and design worked out well;
+as explained elsewhere [Pike89, Gans93, Reppy93],
+user interfaces built with concurrent systems
+can avoid the clumsy
+top-level event loop typical of traditional interactive systems.
+.PP
+An example of the benefits of the multi-process style
+is the management of the state of open
+files held by clients of the file system interface.
+The problem is that some I/O requests,
+such as reading the
+.CW event
+file, may block if no data is available, and the server must
+maintain the state of (possibly many) requests until data appears.
+For example,
+in
+.CW 8½ ,
+a single-process window system written in C, pending requests were queued in
+a data structure associated with each window.
+After activity in the window that might complete pending I/O,
+the data structure was scanned for requests that could now finish.
+This structure did not fit well with the rest of the program and, worse,
+required meticulous effort
+to guarantee correct behavior under all conditions
+(consider raw mode, reads of partial lines, deleting a window,
+multibyte characters, etc.).
+.PP
+Acme instead creates a new dedicated process
+for each I/O request.
+This process coordinates with the rest of the system
+using Alef's synchronous communication;
+its state implicitly encodes the state of
+the I/O request and obviates the need for queuing.
+The passage of the request through Acme proceeds as follows.
+.PP
+Acme contains a file server process, F, that executes a
+.CW read
+system call to receive a Plan 9 file protocol (9P) message from the client [AT&T92].
+The client blocks until Acme answers the request.
+F communicates with an allocation process, M,
+to acquire an object of type
+.CW Xfid
+(`executing fid'; fid is a 9P term)
+to hold the request.
+M sits in a loop (reproduced in Figure 2) waiting for either a request for
+a new
+.CW Xfid
+or notification that an existing one has finished its task.
+When an
+.CW Xfid
+is created, an associated process, X,
+is also made.
+M queues idle
+.CW Xfids ,
+allocating new ones only when the list is empty.
+Thus, there is always a pool of
+.CW Xfids ,
+some executing, some idle.
+.PP
+The
+.CW Xfid
+object contains a channel,
+.CW Xfid.c ,
+for communication with its process;
+the unpacked message; and some associated functions,
+mostly corresponding to 9P messages such as
+.CW Xfid.write
+to handle a 9P write request.
+.PP
+The file server process F parses the message to see its nature\(emopen,
+close, read, write, etc. Many messages, such as directory
+lookups, can be handled immediately; these are responded to directly
+and efficiently
+by F without invoking the
+.CW Xfid ,
+which is therefore maintained until the next message.
+When a message, such as a write to the display, requires the attention
+of the main display process and interlocked access to its data structures,
+F enables X
+by sending a function pointer on
+.CW Xfid.c .
+For example, if the message is a write, F executes
+.P1
+x->c <-= Xfid.write;
+.P2
+which sends
+the address of
+.CW Xfid.write
+on
+.CW Xfid.c ,
+waking up X.
+.PP
+The
+.CW Xfid
+process, X, executes a simple loop:
+.P1
+void
+Xfid.ctl(Xfid *x)
+{
+ for(;;){
+ (*<-x->c)(x); /* receive and execute message */
+ bflush(); /* synchronize bitmap display */
+ cxfidfree <-= x; /* return to free list */
+ }
+}
+.P2
+Thus X
+will wake up with the address of a function to call (here
+.CW Xfid.write )
+and execute it; once that completes, it returns itself to the pool of
+free processes by sending its address back to the allocator.
+.PP
+Although this sequence may seem complicated, it is just a few lines
+of code and is in fact far simpler
+than the management of the I/O queues in
+.CW 8½ .
+The hard work of synchronization is done by the Alef run time system.
+Moreover, the code worked the first time, which cannot be said for the code in
+.CW 8½ .
+.SH
+Undo
+.PP
+Acme provides a general undo facility like that of Sam, permitting
+textual changes to be unwound arbitrarily.
+The implementation is superior to Sam's, though,
+with much higher performance and the ability to `redo' changes.
+.PP
+Sam uses
+a multi-pass algorithm that builds
+a transcript of changes to be made simultaneously
+and then executes them atomically.
+This was thought necessary because the elements of a repetitive
+command such as a global substitution should all be applied to the same
+initial file and implemented simultaneously; forming the complete
+transcript before executing any of the changes avoids the
+cumbersome management of addresses in a changing file.
+Acme, however, doesn't have this problem; global substitution
+is controlled externally and may be made incrementally by exploiting
+an observation: if the changes are sorted in address order and
+executed in reverse, changes will not invalidate the addresses of
+pending changes.
+.PP
+Acme therefore avoids the initial transcript. Instead, changes are applied
+directly to the file, with an undo transcript recorded in a separate list.
+For example, when text is added to a window, it is added directly and a record
+of what to delete to restore the state is appended to the undo list.
+Each undo action and the file are marked with a sequence number;
+actions with the same sequence number are considered a unit
+to be undone together.
+The invariant state of the structure
+is that the last action in the undo list applies to the current state of the file,
+even if that action is one of a related set from, for example, a global substitute.
+(In Sam, a related set of actions needed to be undone simultaneously.)
+To undo an action, pop the last item on the undo list, apply it to the file,
+revert it, and append it to a second, redo list.
+To redo an action, do the identical operation with the lists interchanged.
+The expensive operations occur
+only when actually undoing; in normal editing the overhead is minor.
+For example, Acme reads files about seven times faster than Sam, partly
+because of this improvement and partly because of a cleaner implementation.
+.PP
+Acme uses a temporary file to hold the text, keeping in memory only the
+visible portion, and therefore can edit large files comfortably
+even on small-memory machines such as laptops.
+.SH
+Future
+.PP
+Acme is still under development.
+Some things are simply missing.
+For example, Acme should support non-textual graphics, but this is being
+deferred until it can be done using a new graphics model being developed
+for Plan 9. Also, it is undecided how Acme's style of interaction should best be
+extended to graphical applications.
+On a smaller scale, although the system feels smooth and comfortable,
+work continues to tune the heuristics and
+try new ideas for the user interface.
+.PP
+There need to be more programs that use Acme. Browsers for
+Usenet and AP News articles, the Oxford English Dictionary, and other
+such text sources exist, but more imaginative applications will
+be necessary to prove that Acme's approach is viable.
+One that has recently been started is an interface to the debugger Acid [Wint94],
+although it is still
+unclear what form it will ultimately take.
+.PP
+Acme shows that it is possible to make a user interface a stand-alone component
+of an interactive environment. By absorbing more of the interactive
+functionality than a simple window system, Acme off-loads much of the
+computation from its applications, which helps keep them small and
+consistent in their interface. Acme can afford to dedicate
+considerable effort to making that interface as good as possible; the result
+will benefit the entire system.
+.PP
+Acme is complete and useful enough to attract users.
+Its comfortable user interface,
+the ease with which it handles multiple tasks and
+programs in multiple directories,
+and its high level of integration
+make it addictive.
+Perhaps most telling,
+Acme shows that typescripts may not be the most
+productive interface to a time-sharing system.
+.SH
+Acknowledgements
+.PP
+Howard Trickey, Acme's first user, suffered buggy versions gracefully and made
+many helpful suggestions. Chris Fraser provided the necessary insight for the Acme editing
+commands.
+.SH
+References
+.LP
+[Alef] P. Winterbottom,
+``Alef Language Reference Manual'',
+.I
+Plan 9 Programmer's Manual,
+.R
+AT&T Bell Laboratories,
+Murray Hill, NJ,
+1992;
+revised in this volume.
+.br
+[Alle92]
+.I
+Allegro Common Lisp user Guide, Vol 2,
+.R
+Chapter 14, "The Emacs-Lisp Interface".
+March 1992.
+.br
+[AT&T92] Plan 9 Programmer's manual, Murray Hill, New Jersey, 1992.
+.br
+[Far89] Far too many people, XTERM(1), Massachusetts Institute of Technology, 1989.
+.br
+[Gans93] Emden R. Gansner and John H. Reppy, ``A Multi-threaded Higher-order User Interface Toolkit'', in
+.I
+Software Trends, Volume 1,
+User Interface Software,
+.R
+Bass and Dewan (Eds.),
+John Wiley & Sons 1993,
+pp. 61-80.
+.br
+[Lucid92] Richard Stallman and Lucid, Inc.,
+.I
+Lucid GNU EMACS Manual,
+.R
+March 1992.
+.br
+[Pike87] Rob Pike, ``The Text Editor \f(CWsam\fP'', Softw. - Pract. and Exp., Nov 1987, Vol 17 #11, pp. 813-845; reprinted in this volume.
+.br
+[Pike88] Rob Pike, ``Window Systems Should Be Transparent'', Comp. Sys., Summer 1988, Vol 1 #3, pp. 279-296.
+.br
+[Pike89] Rob Pike, ``A Concurrent Window System'', Comp. Sys., Spring 1989, Vol 2 #2, pp. 133-153.
+.br
+[PPTTW93] Rob Pike, Dave Presotto, Ken Thompson, Howard Trickey, and Phil Winterbottom, ``The Use of Name Spaces in Plan 9'',
+Op. Sys. Rev., Vol. 27, No. 2, April 1993, pp. 72-76,
+reprinted in this volume.
+.br
+[Pike91] Rob Pike, ``8½, the Plan 9 Window System'', USENIX Summer Conf. Proc., Nashville, June, 1991, pp. 257-265,
+reprinted in this volume.
+.br
+[Pike92] Rob Pike, ``A Minimalist Global User Interface'', Graphics Interface '92 Proc., Vancouver, 1992, pp. 282-293. An earlier version appeared under the same title in USENIX Summer Conf. Proc., Nashville, June, 1991, pp. 267-279.
+.br
+[Pike93] Rob Pike and Ken Thompson, ``Hello World or Καλημέρα κόσμε or
+\f(Jpこんにちは 世界\fP'', USENIX Winter Conf. Proc., San Diego, 1993, pp. 43-50,
+reprinted in this volume.
+.br
+[Pres93] Dave Presotto and Phil Winterbottom, ``The Organization of Networks in Plan 9'', Proc. Usenix Winter 1993, pp. 271-287, San Diego, CA,
+reprinted in this volume.
+.br
+[Reis91] Martin Reiser, \fIThe Oberon System,\fP Addison Wesley, New York, 1991.
+.br
+[Reppy93] John H. Reppy,
+``CML: A higher-order concurrent language'', Proc. SIGPLAN'91 Conf. on Programming, Lang. Design and Impl., June, 1991, pp. 293-305.
+.br
+[Sche86] Robert W. Scheifler and Jim Gettys,
+``The X Window System'',
+ACM Trans. on Graph., Vol 5 #2, pp. 79-109.
+.br
+[Stal93] Richard Stallman,
+.I
+Gnu Emacs Manual, 9th edition, Emacs version 19.19,
+.R
+MIT.
+.br
+[Swei86] Daniel Sweinhart, Polle Zellweger, Richard Beach, and Robert Hagmann,
+``A Structural View of the Cedar Programming Environment'',
+ACM Trans. Prog. Lang. and Sys., Vol. 8, No. 4, pp. 419-490, Oct. 1986.
+.br
+[Wint94], Philip Winterbottom, ``Acid: A Debugger based on a Language'', USENIX Winter Conf. Proc., San Francisco, CA, 1993,
+reprinted in this volume.
+.br
+[Wirt89] N. Wirth and J. Gutknecht, ``The Oberon System'', Softw. - Prac. and Exp., Sep 1989, Vol 19 #9, pp 857-894.
binary files /dev/null b/doc/acme/acme.pdf differ
--- /dev/null
+++ b/doc/acme/mkfile
@@ -1,0 +1,4 @@
+<../fonts
+
+acme.ps:D: acme.ms
+ {echo $FONTS; cat acme.ms} | troff -mpm -mpictures -mnihongo | lp -dstdout >acme.ps
--- /dev/null
+++ b/doc/asm.ms
@@ -1,0 +1,1394 @@
+.ft CW
+.ta 8n +8n +8n +8n +8n +8n +8n
+.ft
+.TL
+A Manual for the Plan 9 assembler
+.AU
+.I "Rob Pike"
+.AI
+rob@plan9.bell-labs.com
+.SH
+Machines
+.PP
+There is an assembler for each of the MIPS, SPARC, Intel 386,
+Motorola 68020 and 68000, IBM Power PC, DEC Alpha, and ARM.
+The 68020 assembler,
+.CW 2a ,
+is the oldest and in many ways the prototype.
+The assemblers are really just variations of a single program:
+they share many properties such as left-to-right assignment order for
+instruction operands and the synthesis of macro instructions
+such as
+.CW MOVE
+to hide the peculiarities of the load and store structure of the machines.
+To keep things concrete, the first part of this manual is
+specifically about the 68020.
+At the end is a description of the differences among
+the other assemblers.
+.ig
+.PP
+The document, ``How to Use the Plan 9 C Compiler'', by Rob Pike,
+is a prerequisite for this manual.
+..
+.SH
+Registers
+.PP
+All pre-defined symbols in the assembler are upper-case.
+Data registers are
+.CW R0
+through
+.CW R7 ;
+address registers are
+.CW A0
+through
+.CW A7 ;
+floating-point registers are
+.CW F0
+through
+.CW F7 .
+.PP
+A pointer in
+.CW A6
+is used by the C compiler to point to data, enabling short addresses to
+be used more often.
+The value of
+.CW A6
+is constant and must be set during C program initialization
+to the address of the externally-defined symbol
+.CW a6base .
+.PP
+The following hardware registers are defined in the assembler; their
+meaning should be obvious given a 68020 manual:
+.CW CAAR ,
+.CW CACR ,
+.CW CCR ,
+.CW DFC ,
+.CW ISP ,
+.CW MSP ,
+.CW SFC ,
+.CW SR ,
+.CW USP ,
+and
+.CW VBR .
+.PP
+The assembler also defines several pseudo-registers that
+manipulate the stack:
+.CW FP ,
+.CW SP ,
+and
+.CW TOS .
+.CW FP
+is the frame pointer, so
+.CW 0(FP)
+is the first argument,
+.CW 4(FP)
+is the second, and so on.
+.CW SP
+is the local stack pointer, where automatic variables are held
+(SP is a pseudo-register only on the 68020);
+.CW 0(SP)
+is the first automatic, and so on as with
+.CW FP .
+Finally,
+.CW TOS
+is the top-of-stack register, used for pushing parameters to procedures,
+saving temporary values, and so on.
+.PP
+The assembler and loader track these pseudo-registers so
+the above statements are true regardless of what has been
+pushed on the hardware stack, pointed to by
+.CW A7 .
+The name
+.CW A7
+refers to the hardware stack pointer, but beware of mixed use of
+.CW A7
+and the above stack-related pseudo-registers, which will cause trouble.
+Note, too, that the
+.CW PEA
+instruction is observed by the loader to
+alter SP and thus will insert a corresponding pop before all returns.
+The assembler accepts a label-like name to be attached to
+.CW FP
+and
+.CW SP
+uses, such as
+.CW p+0(FP) ,
+to help document that
+.CW p
+is the first argument to a routine.
+The name goes in the symbol table but has no significance to the result
+of the program.
+.SH
+Referring to data
+.PP
+All external references must be made relative to some pseudo-register,
+either
+.CW PC
+(the virtual program counter) or
+.CW SB
+(the ``static base'' register).
+.CW PC
+counts instructions, not bytes of data.
+For example, to branch to the second following instruction, that is,
+to skip one instruction, one may write
+.P1
+ BRA 2(PC)
+.P2
+Labels are also allowed, as in
+.P1
+ BRA return
+ NOP
+return:
+ RTS
+.P2
+When using labels, there is no
+.CW (PC)
+annotation.
+.PP
+The pseudo-register
+.CW SB
+refers to the beginning of the address space of the program.
+Thus, references to global data and procedures are written as
+offsets to
+.CW SB ,
+as in
+.P1
+ MOVL $array(SB), TOS
+.P2
+to push the address of a global array on the stack, or
+.P1
+ MOVL array+4(SB), TOS
+.P2
+to push the second (4-byte) element of the array.
+Note the use of an offset; the complete list of addressing modes is given below.
+Similarly, subroutine calls must use
+.CW SB :
+.P1
+ BSR exit(SB)
+.P2
+File-static variables have syntax
+.P1
+ local<>+4(SB)
+.P2
+The
+.CW <>
+will be filled in at load time by a unique integer.
+.PP
+When a program starts, it must execute
+.P1
+ MOVL $a6base(SB), A6
+.P2
+before accessing any global data.
+(On machines such as the MIPS and SPARC that cannot load a register
+in a single instruction, constants are loaded through the static base
+register. The loader recognizes code that initializes the static
+base register and treats it specially. You must be careful, however,
+not to load large constants on such machines when the static base
+register is not set up, such as early in interrupt routines.)
+.SH
+Expressions
+.PP
+Expressions are mostly what one might expect.
+Where an offset or a constant is expected,
+a primary expression with unary operators is allowed.
+A general C constant expression is allowed in parentheses.
+.PP
+Source files are preprocessed exactly as in the C compiler, so
+.CW #define
+and
+.CW #include
+work.
+.SH
+Addressing modes
+.PP
+The simple addressing modes are shared by all the assemblers.
+Here, for completeness, follows a table of all the 68020 addressing modes,
+since that machine has the richest set.
+In the table,
+.CW o
+is an offset, which if zero may be elided, and
+.CW d
+is a displacement, which is a constant between -128 and 127 inclusive.
+Many of the modes listed have the same name;
+scrutiny of the format will show what default is being applied.
+For instance, indexed mode with no address register supplied operates
+as though a zero-valued register were used.
+For "offset" read "displacement."
+For "\f(CW.s\fP" read one of
+.CW .L ,
+or
+.CW .W
+followed by
+.CW *1 ,
+.CW *2 ,
+.CW *4 ,
+or
+.CW *8
+to indicate the size and scaling of the data.
+.IP
+.TS
+l lfCW.
+data register R0
+address register A0
+floating-point register F0
+special names CAAR, CACR, etc.
+constant $con
+floating point constant $fcon
+external symbol name+o(SB)
+local symbol name<>+o(SB)
+automatic symbol name+o(SP)
+argument name+o(FP)
+address of external $name+o(SB)
+address of local $name<>+o(SB)
+indirect post-increment (A0)+
+indirect pre-decrement -(A0)
+indirect with offset o(A0)
+indexed with offset o()(R0.s)
+indexed with offset o(A0)(R0.s)
+external indexed name+o(SB)(R0.s)
+local indexed name<>+o(SB)(R0.s)
+automatic indexed name+o(SP)(R0.s)
+parameter indexed name+o(FP)(R0.s)
+offset indirect post-indexed d(o())(R0.s)
+offset indirect post-indexed d(o(A0))(R0.s)
+external indirect post-indexed d(name+o(SB))(R0.s)
+local indirect post-indexed d(name<>+o(SB))(R0.s)
+automatic indirect post-indexed d(name+o(SP))(R0.s)
+parameter indirect post-indexed d(name+o(FP))(R0.s)
+offset indirect pre-indexed d(o()(R0.s))
+offset indirect pre-indexed d(o(A0))
+offset indirect pre-indexed d(o(A0)(R0.s))
+external indirect pre-indexed d(name+o(SB))
+external indirect pre-indexed d(name+o(SB)(R0.s))
+local indirect pre-indexed d(name<>+o(SB))
+local indirect pre-indexed d(name<>+o(SB)(R0.s))
+automatic indirect pre-indexed d(name+o(SP))
+automatic indirect pre-indexed d(name+o(SP)(R0.s))
+parameter indirect pre-indexed d(name+o(FP))
+parameter indirect pre-indexed d(name+o(FP)(R0.s))
+.TE
+.in
+.SH
+Laying down data
+.PP
+Placing data in the instruction stream, say for interrupt vectors, is easy:
+the pseudo-instructions
+.CW LONG
+and
+.CW WORD
+(but not
+.CW BYTE )
+lay down the value of their single argument, of the appropriate size,
+as if it were an instruction:
+.P1
+ LONG $12345
+.P2
+places the long 12345 (base 10)
+in the instruction stream.
+(On most machines,
+the only such operator is
+.CW WORD
+and it lays down 32-bit quantities.
+The 386 has all three:
+.CW LONG ,
+.CW WORD ,
+and
+.CW BYTE .
+The AMD64 adds
+.CW QUAD
+for 64-bit values.)
+.PP
+Placing information in the data section is more painful.
+The pseudo-instruction
+.CW DATA
+does the work, given two arguments: an address at which to place the item,
+including its size,
+and the value to place there. For example, to define a character array
+.CW array
+containing the characters
+.CW abc
+and a terminating null:
+.P1
+ DATA array+0(SB)/1, $'a'
+ DATA array+1(SB)/1, $'b'
+ DATA array+2(SB)/1, $'c'
+ GLOBL array(SB), $4
+.P2
+or
+.P1
+ DATA array+0(SB)/4, $"abc\ez"
+ GLOBL array(SB), $4
+.P2
+The
+.CW /1
+defines the number of bytes to define,
+.CW GLOBL
+makes the symbol global, and the
+.CW $4
+says how many bytes the symbol occupies.
+Uninitialized data is zeroed automatically.
+The character
+.CW \ez
+is equivalent to the C
+.CW \e0.
+The string in a
+.CW DATA
+statement may contain a maximum of eight bytes;
+build larger strings piecewise.
+Two pseudo-instructions,
+.CW DYNT
+and
+.CW INIT ,
+allow the (obsolete) Alef compilers to build dynamic type information during the load
+phase.
+The
+.CW DYNT
+pseudo-instruction has two forms:
+.P1
+ DYNT , ALEF_SI_5+0(SB)
+ DYNT ALEF_AS+0(SB), ALEF_SI_5+0(SB)
+.P2
+In the first form,
+.CW DYNT
+defines the symbol to be a small unique integer constant, chosen by the loader,
+which is some multiple of the word size. In the second form,
+.CW DYNT
+defines the second symbol in the same way,
+places the address of the most recently
+defined text symbol in the array specified by the first symbol at the
+index defined by the value of the second symbol,
+and then adjusts the size of the array accordingly.
+.PP
+The
+.CW INIT
+pseudo-instruction takes the same parameters as a
+.CW DATA
+statement. Its symbol is used as the base of an array and the
+data item is installed in the array at the offset specified by the most recent
+.CW DYNT
+pseudo-instruction.
+The size of the array is adjusted accordingly.
+The
+.CW DYNT
+and
+.CW INIT
+pseudo-instructions are not implemented on the 68020.
+.SH
+Defining a procedure
+.PP
+Entry points are defined by the pseudo-operation
+.CW TEXT ,
+which takes as arguments the name of the procedure (including the ubiquitous
+.CW (SB) )
+and the number of bytes of automatic storage to pre-allocate on the stack,
+which will usually be zero when writing assembly language programs.
+On machines with a link register, such as the MIPS and SPARC,
+the special value -4 instructs the loader to generate no PC save
+and restore instructions, even if the function is not a leaf.
+Here is a complete procedure that returns the sum
+of its two arguments:
+.P1
+TEXT sum(SB), $0
+ MOVL arg1+0(FP), R0
+ ADDL arg2+4(FP), R0
+ RTS
+.P2
+An optional middle argument
+to the
+.CW TEXT
+pseudo-op is a bit field of options to the loader.
+Setting the 1 bit suspends profiling the function when profiling is enabled for the rest of
+the program.
+For example,
+.P1
+TEXT sum(SB), 1, $0
+ MOVL arg1+0(FP), R0
+ ADDL arg2+4(FP), R0
+ RTS
+.P2
+will not be profiled; the first version above would be.
+Subroutines with peculiar state, such as system call routines,
+should not be profiled.
+.PP
+Setting the 2 bit allows multiple definitions of the same
+.CW TEXT
+symbol in a program; the loader will place only one such function in the image.
+It was emitted only by the Alef compilers.
+.PP
+Subroutines to be called from C should place their result in
+.CW R0 ,
+even if it is an address.
+Floating point values are returned in
+.CW F0 .
+Functions that return a structure to a C program
+receive as their first argument the address of the location to
+store the result;
+.CW R0
+is unused in the calling protocol for such procedures.
+A subroutine is responsible for saving its own registers,
+and therefore is free to use any registers without saving them (``caller saves'').
+.CW A6
+and
+.CW A7
+are the exceptions as described above.
+.SH
+When in doubt
+.PP
+If you get confused, try using the
+.CW -S
+option to
+.CW 2c
+and compiling a sample program.
+The standard output is valid input to the assembler.
+.SH
+Instructions
+.PP
+The instruction set of the assembler is not identical to that
+of the machine.
+It is chosen to match what the compiler generates, augmented
+slightly by specific needs of the operating system.
+For example,
+.CW 2a
+does not distinguish between the various forms of
+.CW MOVE
+instruction: move quick, move address, etc. Instead the context
+does the job. For example,
+.P1
+ MOVL $1, R1
+ MOVL A0, R2
+ MOVW SR, R3
+.P2
+generates official
+.CW MOVEQ ,
+.CW MOVEA ,
+and
+.CW MOVESR
+instructions.
+A number of instructions do not have the syntax necessary to specify
+their entire capabilities. Notable examples are the bitfield
+instructions, the
+multiply and divide instructions, etc.
+For a complete set of generated instruction names (in
+.CW 2a
+notation, not Motorola's) see the file
+.CW /sys/src/cmd/2c/2.out.h .
+Despite its name, this file contains an enumeration of the
+instructions that appear in the intermediate files generated
+by the compiler, which correspond exactly to lines of assembly language.
+.PP
+The MC68000 assembler,
+.CW 1a ,
+is essentially the same, honoring the appropriate subset of the instructions
+and addressing modes.
+The definitions of these are, nonetheless, part of
+.CW 2.out.h .
+.SH
+Laying down instructions
+.PP
+The loader modifies the code produced by the assembler and compiler.
+It folds branches,
+copies short sequences of code to eliminate branches,
+and discards unreachable code.
+The first instruction of every function is assumed to be reachable.
+The pseudo-instruction
+.CW NOP ,
+which you may see in compiler output,
+means no instruction at all, rather than an instruction that does nothing.
+The loader discards all
+.CW NOP 's.
+.PP
+To generate a true
+.CW NOP
+instruction, or any other instruction not known to the assembler, use a
+.CW WORD
+pseudo-instruction.
+Such instructions on RISCs are not scheduled by the loader and must have
+their delay slots filled manually.
+.SH
+MIPS
+.PP
+The registers are only addressed by number:
+.CW R0
+through
+.CW R31 .
+.CW R29
+is the stack pointer;
+.CW R30
+is used as the static base pointer, the analogue of
+.CW A6
+on the 68020.
+Its value is the address of the global symbol
+.CW setR30(SB) .
+The register holding returned values from subroutines is
+.CW R1 .
+When a function is called, space for the first argument
+is reserved at
+.CW 0(FP)
+but in C (not Alef) the value is passed in
+.CW R1
+instead.
+.PP
+The loader uses
+.CW R28
+as a temporary. The system uses
+.CW R26
+and
+.CW R27
+as interrupt-time temporaries. Therefore none of these registers
+should be used in user code.
+.PP
+The control registers are not known to the assembler.
+Instead they are numbered registers
+.CW M0 ,
+.CW M1 ,
+etc.
+Use this trick to access, say,
+.CW STATUS :
+.P1
+#define STATUS 12
+ MOVW M(STATUS), R1
+.P2
+.PP
+Floating point registers are called
+.CW F0
+through
+.CW F31 .
+By convention,
+.CW F24
+must be initialized to the value 0.0,
+.CW F26
+to 0.5,
+.CW F28
+to 1.0, and
+.CW F30
+to 2.0;
+this is done by the operating system.
+.PP
+The instructions and their syntax are different from those of the manufacturer's
+manual.
+There are no
+.CW lui
+and kin; instead there are
+.CW MOVW
+(move word),
+.CW MOVH
+(move halfword),
+and
+.CW MOVB
+(move byte) pseudo-instructions. If the operand is unsigned, the instructions
+are
+.CW MOVHU
+and
+.CW MOVBU .
+The order of operands is from left to right in dataflow order, just as
+on the 68020 but not as in MIPS documentation.
+This means that the
+.CW Bcond
+instructions are reversed with respect to the book; for example, a
+.CW va
+.CW BGTZ
+generates a MIPS
+.CW bltz
+instruction.
+.PP
+The assembler is for the R2000, R3000, and most of the R4000 and R6000 architectures.
+It understands the 64-bit instructions
+.CW MOVV ,
+.CW MOVVL ,
+.CW ADDV ,
+.CW ADDVU ,
+.CW SUBV ,
+.CW SUBVU ,
+.CW MULV ,
+.CW MULVU ,
+.CW DIVV ,
+.CW DIVVU ,
+.CW SLLV ,
+.CW SRLV ,
+and
+.CW SRAV .
+The assembler does not have any cache, load-linked, or store-conditional instructions.
+.PP
+Some assembler instructions are expanded into multiple instructions by the loader.
+For example the loader may convert the load of a 32 bit constant into an
+.CW lui
+followed by an
+.CW ori .
+.PP
+Assembler instructions should be laid out as if there
+were no load, branch, or floating point compare delay slots;
+the loader will rearrange\(em\f2schedule\f1\(emthe instructions
+to guarantee correctness and improve performance.
+The only exception is that the correct scheduling of instructions
+that use control registers varies from model to model of machine
+(and is often undocumented) so you should schedule such instructions
+by hand to guarantee correct behavior.
+The loader generates
+.P1
+ NOR R0, R0, R0
+.P2
+when it needs a true no-op instruction.
+Use exactly this instruction when scheduling code manually;
+the loader recognizes it and schedules the code before it and after it independently. Also,
+.CW WORD
+pseudo-ops are scheduled like no-ops.
+.PP
+The
+.CW NOSCHED
+pseudo-op disables instruction scheduling
+(scheduling is enabled by default);
+.CW SCHED
+re-enables it.
+Branch folding, code copying, and dead code elimination are
+disabled for instructions that are not scheduled.
+.SH
+SPARC
+.PP
+Once you understand the Plan 9 model for the MIPS, the SPARC is familiar.
+Registers have numerical names only:
+.CW R0
+through
+.CW R31 .
+Forget about register windows: Plan 9 doesn't use them at all.
+The machine has 32 global registers, period.
+.CW R1
+[sic] is the stack pointer.
+.CW R2
+is the static base register, with value the address of
+.CW setSB(SB) .
+.CW R7
+is the return register and also the register holding the first
+argument to a C (not Alef) function, again with space reserved at
+.CW 0(FP) .
+.CW R14
+is the loader temporary.
+.PP
+Floating-point registers are exactly as on the MIPS.
+.PP
+The control registers are known by names such as
+.CW FSR .
+The instructions to access these registers are
+.CW MOVW
+instructions, for example
+.P1
+ MOVW Y, R8
+.P2
+for the SPARC instruction
+.P1
+ rdy %r8
+.P2
+.PP
+Move instructions are similar to those on the MIPS: pseudo-operations
+that turn into appropriate sequences of
+.CW sethi
+instructions, adds, etc.
+Instructions read from left to right. Because the arguments are
+flipped to
+.CW SUBCC ,
+the condition codes are not inverted as on the MIPS.
+.PP
+The syntax for the ASI stuff is, for example to move a word from ASI 2:
+.P1
+ MOVW (R7, 2), R8
+.P2
+The syntax for double indexing is
+.P1
+ MOVW (R7+R8), R9
+.P2
+.PP
+The SPARC's instruction scheduling is similar to the MIPS's.
+The official no-op instruction is:
+.P1
+ ORN R0, R0, R0
+.P2
+.SH
+i386
+.PP
+The assembler assumes 32-bit protected mode.
+The register names are
+.CW SP ,
+.CW AX ,
+.CW BX ,
+.CW CX ,
+.CW DX ,
+.CW BP ,
+.CW DI ,
+and
+.CW SI .
+The stack pointer (not a pseudo-register) is
+.CW SP
+and the return register is
+.CW AX .
+There is no physical frame pointer but, as for the MIPS,
+.CW FP
+is a pseudo-register that acts as
+a frame pointer.
+.PP
+Opcode names are mostly the same as those listed in the Intel manual
+with an
+.CW L ,
+.CW W ,
+or
+.CW B
+appended to identify 32-bit,
+16-bit, and 8-bit operations.
+The exceptions are loads, stores, and conditionals.
+All load and store opcodes to and from general registers, special registers
+(such as
+.CW CR0,
+.CW CR3,
+.CW GDTR,
+.CW IDTR,
+.CW SS,
+.CW CS,
+.CW DS,
+.CW ES,
+.CW FS,
+and
+.CW GS )
+or memory are written
+as
+.P1
+ MOV\f2x\fP src,dst
+.P2
+where
+.I x
+is
+.CW L ,
+.CW W ,
+or
+.CW B .
+Thus to get
+.CW AL
+use a
+.CW MOVB
+instruction. If you need to access
+.CW AH ,
+you must mention it explicitly in a
+.CW MOVB :
+.P1
+ MOVB AH, BX
+.P2
+There are many examples of illegal moves, for example,
+.P1
+ MOVB BP, DI
+.P2
+that the loader actually implements as pseudo-operations.
+.PP
+The names of conditions in all conditional instructions
+.CW J , (
+.CW SET )
+follow the conventions of the 68020 instead of those of the Intel
+assembler:
+.CW JOS ,
+.CW JOC ,
+.CW JCS ,
+.CW JCC ,
+.CW JEQ ,
+.CW JNE ,
+.CW JLS ,
+.CW JHI ,
+.CW JMI ,
+.CW JPL ,
+.CW JPS ,
+.CW JPC ,
+.CW JLT ,
+.CW JGE ,
+.CW JLE ,
+and
+.CW JGT
+instead of
+.CW JO ,
+.CW JNO ,
+.CW JB ,
+.CW JNB ,
+.CW JZ ,
+.CW JNZ ,
+.CW JBE ,
+.CW JNBE ,
+.CW JS ,
+.CW JNS ,
+.CW JP ,
+.CW JNP ,
+.CW JL ,
+.CW JNL ,
+.CW JLE ,
+and
+.CW JNLE .
+.PP
+The addressing modes have syntax like
+.CW AX ,
+.CW (AX) ,
+.CW (AX)(BX*4) ,
+.CW 10(AX) ,
+and
+.CW 10(AX)(BX*4) .
+The offsets from
+.CW AX
+can be replaced by offsets from
+.CW FP
+or
+.CW SB
+to access names, for example
+.CW extern+5(SB)(AX*2) .
+.PP
+Other notes: Non-relative
+.CW JMP
+and
+.CW CALL
+have a
+.CW *
+added to the syntax.
+Only
+.CW LOOP ,
+.CW LOOPEQ ,
+and
+.CW LOOPNE
+are legal loop instructions. Only
+.CW REP
+and
+.CW REPN
+are recognized repeaters. These are not prefixes, but rather
+stand-alone opcodes that precede the strings, for example
+.P1
+ CLD; REP; MOVSL
+.P2
+Segment override prefixes in
+.CW MOD/RM
+fields are not supported.
+.SH
+AMD64
+.PP
+The assembler's conventions are similar to those for the 386, above.
+The architecture provides extra fixed-point registers
+.CW R8
+to
+.CW R15 .
+All registers are 64 bit, but instructions access low-order 8, 16 and 32 bits
+as described in the processor handbook.
+For example,
+.CW MOVL
+to
+.CW AX
+puts a value in the low-order 32 bits and clears the top 32 bits to zero.
+Literal operands are limited to signed 32 bit values, which are sign-extended
+to 64 bits in 64 bit operations; the exception is
+.CW MOVQ ,
+which allows 64-bit literals.
+MMX registers are
+.CW M0
+to
+.CW M7 ,
+and
+XMM registers are
+.CW X0
+to
+.CW X15 .
+.PP
+There are many new instructions, including the MMX and XMM media instructions,
+and conditional move instructions.
+As with the 386 instruction names,
+all new 64-bit integer instructions, and the MMX and XMM instructions
+uniformly use
+.CW L
+for `long word' (32 bits) and
+.CW Q
+for `quad word' (64 bits).
+Some instructions use
+.CW O
+(`octword') for 128-bit values, where the processor handbook
+variously uses
+.CW O
+or
+.CW DQ .
+The assembler also consistently uses
+.CW PL
+for `packed long' in
+XMM instructions, instead of
+.CW Q ,
+.CW DQ
+or
+.CW PI .
+Either
+.CW MOVL
+or
+.CW MOVQ
+can be used to move values to and from control registers, even when
+the registers might be 64 bits.
+The assembler often accepts the handbook's name to ease conversion
+of existing code (but remember that the operand order is uniformly
+source then destination).
+.PP
+C's
+.CW "long long"
+type is 64 bits, but passed and returned by value, not by reference.
+More notably, C pointer values are 64 bits, and thus
+.CW "long long"
+and
+.CW "unsigned long long"
+are the only integer types wide enough to hold a pointer value.
+The C compiler and library use the XMM floating-point instructions, not
+the old 387 ones, although the latter are implemented by assembler and loader.
+The compiler provides external registers,
+allocated from
+.CW R15
+down.
+.PP
+The calling conventions are different from the 386.
+.CW CALL
+pushes, and
+.CW RET
+pops a 64-bit return address on the stack.
+The first integer or pointer argument is passed in a register, which is
+.CW BP
+for an integer or pointer (it can be referred to in assembly code by the pseudonym
+.CW RARG ).
+.CW AX
+holds the return value from subroutines as before.
+Floating-point results are returned in
+.CW X0 ,
+although currently the first parameter is not passed in a register if floating-point.
+All parameters less than 8 bytes in length have 8 byte slots reserved on the stack
+to preserve alignment and simplify variable-length argument list access,
+including the first parameter when passed in a register,
+although bytes 4 to 7 are not initialized.
+.PP
+The assembler assumes 64-bit mode unless a
+.CW MODE
+pseudo-operation is given:
+.P1
+ MODE $32
+.P2
+to change to 32-bit mode.
+The effect is mainly to diagnose instructions that are illegal in
+the given mode, but the loader will also assume 32-bit operands and addresses,
+and 32-bit PC values for call and return.
+.SH
+Alpha
+.PP
+On the Alpha, all registers are 64 bits. The architecture handles 32-bit values
+by giving them a canonical format (sign extension in the case of integer registers).
+Registers are numbered
+.CW R0
+through
+.CW R31 .
+.CW R0
+holds the return value from subroutines, and also the first parameter.
+.CW R30
+is the stack pointer,
+.CW R29
+is the static base,
+.CW R26
+is the link register, and
+.CW R27
+and
+.CW R28
+are linker temporaries.
+.PP
+Floating point registers are numbered
+.CW F0
+to
+.CW F31 .
+.CW F28
+contains
+.CW 0.5 ,
+.CW F29
+contains
+.CW 1.0 ,
+and
+.CW F30
+contains
+.CW 2.0 .
+.CW F31
+is always
+.CW 0.0
+on the Alpha.
+.PP
+The extension character for
+.CW MOV
+follows DEC's notation:
+.CW B
+for byte (8 bits),
+.CW W
+for word (16 bits),
+.CW L
+for long (32 bits),
+and
+.CW Q
+for quadword (64 bits).
+Byte and ``word'' loads and stores may be made unsigned
+by appending a
+.CW U .
+.CW S
+and
+.CW T
+refer to IEEE floating point single precision (32 bits) and double precision (64 bits), respectively.
+.SH
+PowerPC
+.PP
+The PowerPC follows the Plan 9 model set by the MIPS and SPARC,
+not the elaborate ABIs.
+The 32-bit instructions of the 60x and 8xx PowerPC architectures are supported;
+there is no support for the older POWER instructions.
+Registers are
+.CW R0
+through
+.CW R31 .
+.CW R0
+is initialized to zero; this is done by C start up code
+and assumed by the compiler and loader.
+.CW R1
+is the stack pointer.
+.CW R2
+is the static base register, with value the address of
+.CW setSB(SB) .
+.CW R3
+is the return register and also the register holding the first
+argument to a C function, with space reserved at
+.CW 0(FP)
+as on the MIPS.
+.CW R31
+is the loader temporary.
+The external registers in Plan 9's C are allocated from
+.CW R30
+down.
+.PP
+Floating point registers are called
+.CW F0
+through
+.CW F31 .
+By convention, several registers are initialized
+to specific values; this is done by the operating system.
+.CW F27
+must be initialized to the value
+.CW 0x4330000080000000
+(used by float-to-int conversion),
+.CW F28
+to the value 0.0,
+.CW F29
+to 0.5,
+.CW F30
+to 1.0, and
+.CW F31
+to 2.0.
+.PP
+As on the MIPS and SPARC, the assembler accepts arbitrary literals
+as operands to
+.CW MOVW ,
+and also to
+.CW ADD
+and others where `immediate' variants exist,
+and the loader generates sequences
+of
+.CW addi ,
+.CW addis ,
+.CW oris ,
+etc. as required.
+The register indirect addressing modes use the same syntax as the SPARC,
+including double indexing when allowed.
+.PP
+The instruction names are generally derived from the Motorola ones,
+subject to slight transformation:
+the
+.CW . ' `
+marking the setting of condition codes is replaced by
+.CW CC ,
+and when the letter
+.CW o ' `
+represents `OE=1' it is replaced by
+.CW V .
+Thus
+.CW add ,
+.CW addo.
+and
+.CW subfzeo.
+become
+.CW ADD ,
+.CW ADDVCC
+and
+.CW SUBFZEVCC .
+As well as the three-operand conditional branch instruction
+.CW BC ,
+the assembler provides pseudo-instructions for the common cases:
+.CW BEQ ,
+.CW BNE ,
+.CW BGT ,
+.CW BGE ,
+.CW BLT ,
+.CW BLE ,
+.CW BVC ,
+and
+.CW BVS .
+The unconditional branch instruction is
+.CW BR .
+Indirect branches use
+.CW "(CTR)"
+or
+.CW "(LR)"
+as target.
+.PP
+Load or store operations are replaced by
+.CW MOV
+variants in the usual way:
+.CW MOVW
+(move word),
+.CW MOVH
+(move halfword with sign extension), and
+.CW MOVB
+(move byte with sign extension, a pseudo-instruction),
+with unsigned variants
+.CW MOVHZ
+and
+.CW MOVBZ ,
+and byte-reversing
+.CW MOVWBR
+and
+.CW MOVHBR .
+`Load or store with update' versions are
+.CW MOVWU ,
+.CW MOVHU ,
+and
+.CW MOVBZU .
+Load or store multiple is
+.CW MOVMW .
+The exceptions are the string instructions, which are
+.CW LSW
+and
+.CW STSW ,
+and the reservation instructions
+.CW lwarx
+and
+.CW stwcx. ,
+which are
+.CW LWAR
+and
+.CW STWCCC ,
+all with operands in the usual data-flow order.
+Floating-point load or store instructions are
+.CW FMOVD ,
+.CW FMOVDU ,
+.CW FMOVS ,
+and
+.CW FMOVSU .
+The register to register move instructions
+.CW fmr
+and
+.CW fmr.
+are written
+.CW FMOVD
+and
+.CW FMOVDCC .
+.PP
+The assembler knows the commonly used special purpose registers:
+.CW CR ,
+.CW CTR ,
+.CW DEC ,
+.CW LR ,
+.CW MSR ,
+and
+.CW XER .
+The rest, which are often architecture-dependent, are referenced as
+.CW SPR(n) .
+The segment registers of the 60x series are similarly
+.CW SEG(n) ,
+but
+.I n
+can also be a register name, as in
+.CW SEG(R3) .
+Moves between special purpose registers and general purpose ones,
+when allowed by the architecture,
+are written as
+.CW MOVW ,
+replacing
+.CW mfcr ,
+.CW mtcr ,
+.CW mfmsr ,
+.CW mtmsr ,
+.CW mtspr ,
+.CW mfspr ,
+.CW mftb ,
+and many others.
+.PP
+The fields of the condition register
+.CW CR
+are referenced as
+.CW CR(0)
+through
+.CW CR(7) .
+They are used by the
+.CW MOVFL
+(move field) pseudo-instruction,
+which produces
+.CW mcrf
+or
+.CW mtcrf .
+For example:
+.P1
+ MOVFL CR(3), CR(0)
+ MOVFL R3, CR(1)
+ MOVFL R3, $7, CR
+.P2
+They are also accepted in
+the conditional branch instruction, for example
+.P1
+ BEQ CR(7), label
+.P2
+Fields of the
+.CW FPSCR
+are accessed using
+.CW MOVFL
+in a similar way:
+.P1
+ MOVFL FPSCR, F0
+ MOVFL F0, FPSCR
+ MOVFL F0, $7, FPSCR
+ MOVFL $0, FPSCR(3)
+.P2
+producing
+.CW mffs ,
+.CW mtfsf ,
+or
+.CW mtfsfi
+as appropriate.
+.SH
+ARM
+.PP
+The assembler provides access to
+.CW R0
+through
+.CW R14
+and the
+.CW PC .
+The stack pointer is
+.CW R13 ,
+the link register is
+.CW R14 ,
+and the static base register is
+.CW R12 .
+.CW R0
+is the return register and also the register holding
+the first argument to a subroutine.
+The assembler supports the
+.CW CPSR
+and
+.CW SPSR
+registers.
+It also knows about coprocessor registers
+.CW C0
+through
+.CW C15 .
+Floating registers are
+.CW F0
+through
+.CW F7 ,
+.CW FPSR
+and
+.CW FPCR .
+.PP
+As with the other architectures, loads and stores are called
+.CW MOV ,
+e.g.
+.CW MOVW
+for load word or store word, and
+.CW MOVM
+for
+load or store multiple,
+depending on the operands.
+.PP
+Addressing modes are supported by suffixes to the instructions:
+.CW .IA
+(increment after),
+.CW .IB
+(increment before),
+.CW .DA
+(decrement after), and
+.CW .DB
+(decrement before).
+These can only be used with the
+.CW MOV
+instructions.
+The move multiple instruction,
+.CW MOVM ,
+defines a range of registers using brackets, e.g.
+.CW [R0-R12] .
+The special
+.CW MOVM
+addressing mode bits
+.CW W ,
+.CW U ,
+and
+.CW P
+are written in the same manner, for example,
+.CW MOVM.DB.W .
+A
+.CW .S
+suffix allows a
+.CW MOVM
+instruction to access user
+.CW R13
+and
+.CW R14
+when in another processor mode.
+Shifts and rotates in addressing modes are supported by binary operators
+.CW <<
+(logical left shift),
+.CW >>
+(logical right shift),
+.CW ->
+(arithmetic right shift), and
+.CW @>
+(rotate right); for example
+.CW "R7>>R2" or
+.CW "R2@>2" .
+The assembler does not support indexing by a shifted expression;
+only names can be doubly indexed.
+.PP
+Any instruction can be followed by a suffix that makes the instruction conditional:
+.CW .EQ ,
+.CW .NE ,
+and so on, as in the ARM manual, with synonyms
+.CW .HS
+(for
+.CW .CS )
+and
+.CW .LO
+(for
+.CW .CC ),
+for example
+.CW ADD.NE .
+Arithmetic
+and logical instructions
+can have a
+.CW .S
+suffix, as ARM allows, to set condition codes.
+.PP
+The syntax of the
+.CW MCR
+and
+.CW MRC
+coprocessor instructions is largely as in the manual, with the usual adjustments.
+The assembler directly supports only the ARM floating-point coprocessor
+operations used by the compiler:
+.CW CMP ,
+.CW ADD ,
+.CW SUB ,
+.CW MUL ,
+and
+.CW DIV ,
+all with
+.CW F
+or
+.CW D
+suffix selecting single or double precision.
+Floating-point load or store become
+.CW MOVF
+and
+.CW MOVD .
+Conversion instructions are also specified by moves:
+.CW MOVWD ,
+.CW MOVWF ,
+.CW MOVDW ,
+.CW MOVWD ,
+.CW MOVFD ,
+and
+.CW MOVDF .
binary files /dev/null b/doc/asm.pdf differ
binary files /dev/null b/doc/backmatter.pdf differ
--- /dev/null
+++ b/doc/bltj.ms
@@ -1,0 +1,1073 @@
+.TL
+The Inferno Operating System
+.AU
+Sean Dorward
+Rob Pike
+David Leo Presotto
+Dennis M. Ritchie
+Howard Trickey
+Phil Winterbottom
+.AI
+Computing Science Research Center
+Lucent Technologies, Bell Labs
+Murray Hill, New Jersey
+USA
+.FS
+.FA
+Originally appeared in the
+.I "Bell Labs Technical Journal" ,
+Vol. 2, No. 1, Winter 1997, pp. 5-18.
+.br
+Minor revisions have been made by Vita Nuova to reflect subsequent changes to Inferno.
+.br
+Copyright © 1997 Lucent Technologies Inc. All rights reserved.
+.FE
+.AB
+Inferno is an operating system for creating and supporting distributed services.
+It was originally developed by the Computing Science Research Center of Bell Labs, the R&D arm of Lucent Technologies, and
+further developed by other groups in Lucent.
+.LP
+Inferno was designed specifically as a commercial product, both for licensing
+in the marketplace and for use within new Lucent offerings.
+It encapsulates many years of Bell Labs research in operating systems, languages, on-the-fly compilers, graphics, security, networking and portability.
+.AE
+.SH
+Introduction
+.LP
+Inferno is intended to be used in a variety of network environments, for example those supporting
+advanced telephones, hand-held devices, TV set-top boxes attached to cable or satellite systems, and inexpensive Internet computers, but also in conjunction with traditional computing systems.
+.LP
+The most visible new environments involve cable television, direct satellite broadcast, the Internet, and other networks. As the entertainment, telecommunications, and computing industries converge and interconnect, a variety of public data networks are emerging, each potentially as useful and profitable as the telephone system. Unlike the telephone system, which started with standard terminals and signaling, these networks are developing in a world of diverse terminals, network hardware, and protocols. Only a well-designed, economical operating system can insulate the various providers of content and services from the equally varied transport and presentation
+platforms. Inferno is a network operating system for this new world.
+.LP
+Inferno's definitive strength lies in its portability and versatility across several dimensions:
+.IP •
+Portability across processors: it currently runs on Intel, Sparc, MIPS, ARM, HP-PA, and PowerPC architectures and is readily portable to others.
+.IP •
+Portability across environments: it runs as a stand-alone operating system on small terminals, and also as a user application under Windows NT, Windows 95, Unix (Irix, Solaris, FreeBSD, Linux, AIX, HP/UX) and Plan 9. In all of these environments, Inferno applications see an identical interface.
+.IP •
+Distributed design: the identical environment is established at the user's terminal and at the server, and each may import the resources (for example, the attached I/O devices or networks) of the other. Aided by the communications facilities of the run-time system, applications may be split easily (and even dynamically) between client and server.
+.IP •
+Minimal hardware requirements: it runs useful applications stand-alone on machines with as little as 1 MB of memory, and does not require memory-mapping hardware.
+.IP •
+Portable applications: Inferno applications are written in the type-safe language Limbo, whose binary representation is identical over all platforms.
+.IP •
+Dynamic adaptability: applications may, depending on the hardware or other resources available, load different program modules to perform a specific function. For example, a video player application might use any of several different decoder modules.
+.LP
+Underlying the design of Inferno is a model of the diversity of application areas it intends to stimulate. Many providers are interested in purveying media and services: telephone network service providers, WWW servers, cable companies, merchants, various information providers.
+There are many connection technologies: ordinary telephone modems, ISDN, ATM, the Internet, analog broadcast or cable TV, cable modems, digital video on demand, and other interactive TV systems.
+.LP
+Applications more clearly related to Lucent's current and planned product offerings include
+control of switches and routers, and the associated operations system facilities needed to support them.
+For example, Inferno software controls an IP switch/router for voice and data being
+developed by Lucent's Bell Labs research and Network Systems organizations.
+An Inferno-based firewall (Signet) is being used to secure outside access to the Research
+Internet connection.
+.LP
+Finally, there are existing or potential hardware endpoints. Some are in consumers' homes: PCs,
+game consoles, newer set-top boxes. Some are inside the networks themselves: nodes for billing, network monitoring or provisioning. The higher ends of these spectra, epitomized by fully interactive TV with video on demand, may be fascinating, but have developed more slowly than expected. One reason is the cost of the set-top box, especially its memory requirements. Portable terminals, because of weight and cost considerations, are similarly constrained.
+.LP
+Inferno is parsimonious enough in its resource requirements to support interesting applications on today's hardware, while being versatile enough to grow into the future. In particular, it enables developers to create applications that will work across a range of facilities. An example: an interactive shopping catalog that works in text mode over a POTS modem, shows still pictures (perhaps with audio) of the merchandise over ISDN, and includes video clips over digital cable.
+.LP
+Clearly not everyone who deploys an Inferno-based solution will want to span the whole range of possibilities, but the system architecture should be constrained only by the desired markets and the available interconnection and server technologies, not by the software.
+.SH
+Inferno interfaces
+.LP
+The role of the Inferno system is to
+.I "create"
+several standard interfaces for its applications:
+.IP •
+Applications use various resources internal to the system, such as a consistent virtual machine that runs the application programs, together with library modules that perform services as simple as string manipulation through more sophisticated graphics services for dealing with text, pictures,
+higher-level toolkits, and video.
+.IP •
+Applications exist in an external environment containing resources such as data files that can be read and manipulated, together with objects that are named and manipulated like files but are more active. Devices (for example a hand-held remote control, an MPEG decoder or a network interface) present themselves to the application as files.
+.IP •
+Standard protocols exist for communication within and between separate machines running Inferno, so that applications can cooperate.
+.LP
+At the same time, Inferno
+.I uses
+interfaces supplied by an existing environment, either bare hardware or standard operating systems and protocols.
+.LP
+Most typically, an Inferno-based service would consist of many relatively cheap terminals running Inferno as a native system, and a smaller number of large machines running Inferno as a hosted system. On these server machines Inferno might interface to databases, transaction systems, existing OA&M facilities, and other resources provided under the native operating system. The Inferno applications themselves would run either on the client or server machines, or both.
+.SH
+External Environment of Inferno Applications
+.LP
+The purpose of most Inferno applications is to present information or media to the user; thus applications must locate the information sources in the network and construct a local representation of them. The information flow is not one-way: the user's terminal (whether a network computer, TV set-top, PC, or videophone) is also an information source and its devices represent resources to applications. Inferno draws heavily on the design of the Plan 9 operating system [1] in the way it presents resources to these applications.
+.LP
+The design has three principles.
+.IP •
+All resources are named and accessed like files in a forest of hierarchical file systems.
+.IP •
+The disjoint resource hierarchies provided by different services are joined together into a single private hierarchical
+.I "name space" .
+.IP •
+A communication protocol, called
+.I "Styx" ,
+is applied uniformly to access these resources, whether local or remote.
+.LP
+In practice, most applications see a fixed set of files organized as a directory tree. Some of the files contain ordinary data, but others represent more active resources. Devices are represented as files, and device drivers (such as a modem, an MPEG decoder, a network interface, or the TV screen) attached to a particular hardware box present themselves as small directories. These directories typically containing two files,
+.CW "data"
+and
+.CW "ctl" ,
+which respectively perform actual device input/output and control operations. System services also live behind file names. For example, an Internet domain name server might be attached to an agreed-upon name (say
+.CW "/net/dns" );
+after writing to this file a string representing a symbolic Internet domain name, a subsequent read from the file would return the corresponding numeric Internet address.
+.LP
+The glue that connects the separate parts of the resource name space together is the Styx protocol.
+Within an instance of Inferno, all the device drivers and other internal resources respond to the procedural version of Styx. The Inferno kernel implements a
+.I "mount driver"
+that transforms file system operations into remote procedure calls for transport over a network. On the other side of the connection, a server unwraps the Styx messages and implements them using resources local to it. Thus, it is possible to import parts of the name space (and thus resources) from other machines.
+.LP
+To extend the example above, it is unlikely that a set-top box would store the code needed for an Internet domain name-server within itself. Instead, an Internet browser would import the
+.CW "/net/dns"
+resource into its own name space from a server machine across a network.
+.LP
+The Styx protocol lies above and is independent of the communications transport layer; it is readily carried over TCP/IP, PPP, ATM or various modem transport protocols.
+.SH
+Internal Environment of Inferno Applications
+.LP
+Inferno applications are written in a new language called Limbo [2], which was designed specifically for the Inferno environment. Its syntax is influenced by C and Pascal, and it supports the standard data types common to them, together with several higher-level data types such as lists, tuples, strings, dynamic arrays, and simple abstract data types.
+.LP
+In addition, Limbo supplies several advanced constructs carefully integrated into the Inferno virtual machine. In particular, a communication mechanism called a
+.I "channel"
+is used to connect different Limbo tasks on the same machine or across the network.
+A channel transports typed data in a machine-independent fashion, so that complex data structures (including channels themselves) may be passed between Limbo tasks or attached to files in the name space for language-level communication between machines.
+.LP
+Multi-tasking is supported directly by the Limbo language: independently scheduled threads of control may be spawned, and an
+.CW "alt"
+statement is used to coordinate the channel communication
+between tasks (that is,
+.CW "alt"
+is used to select one of several channels that are ready to communicate).
+By building channels and tasks into the language and its virtual machine, Inferno encourages a communication style that is easy to use and safe.
+.LP
+Limbo programs are built of
+.I "modules" ,
+which are self-contained units with a well-defined interface
+containing functions (methods), abstract data types, and constants defined by the module and visible outside it. Modules are accessed dynamically; that is, when one module wishes to make use of another, it dynamically executes a
+.CW "load"
+statement naming the desired module, and uses a returned handle to access the new module.
+When the module is no longer in use, its storage and code will be released.
+The flexibility of the modular structure contributes to the smallness of typical Inferno applications, and also to their adaptability.
+For example, in the shopping catalog described above,
+the application's main module checks dynamically for the existence of the video resource.
+If it is unavailable, the video-decoder module is never loaded.
+.LP
+Limbo is fully type-checked at compile- and run-time; for example, pointers, besides being more
+restricted than in C, are checked before being dereferenced, and the type-consistency of a dynamically loaded module is checked when it is loaded. Limbo programs run safely on a machine
+without memory-protection hardware.
+Moreover, all Limbo data and program objects are subject to
+a garbage collector, built deeply into the Limbo run-time system. All system data objects are tracked by the virtual machine and freed as soon as they become unused. For example, if an application task creates a graphics window and then terminates, the window automatically disappears the instant the last reference to it has gone away.
+.LP
+Limbo programs are compiled into byte-codes representing instructions for a virtual machine called
+Dis. The architecture of the arithmetic part of Dis is a simple 3-address machine, supplemented with a few specialized operations for handling some of the higher-level data types like arrays and strings. Garbage collection is handled below the level of the machine language; the scheduling of tasks is similarly hidden. When loaded into memory for execution, the byte-codes are expanded
+into a format more efficient for execution; there is also an optional on-the-fly compiler that turns a Dis instruction stream into native machine instructions for the appropriate real hardware. This can be done efficiently because Dis instructions match well with the instruction-set architecture of today's machines. The resulting code executes at a speed approaching that of compiled C.
+.LP
+Underlying Dis is the Inferno kernel, which contains the interpreter and on-the-fly compiler as well as memory management, scheduling, device drivers, protocol stacks, and the like.
+The kernel also contains the core of the file system (the name evaluator and the code that turns file system operations into remote procedure calls over communications links) as well as the small file systems implemented internally.
+.LP
+Finally, the Inferno virtual machine implements several standard modules internally. These include
+.CW "Sys" ,
+which provides system calls and a small library of useful routines (e.g. creation of network connections, string manipulations). Module
+.CW "Draw"
+is a basic graphics library that handles raster graphics, fonts, and windows. Module
+.CW "Prefab"
+builds on
+.CW "Draw"
+to provide structured complexes containing images and text inside of windows; these elements may be scrolled, selected, and changed by the methods of
+.CW "Prefab" .
+Module
+.CW "Tk"
+is an all-new implementation of the Tk graphics toolkit [18], with a Limbo interface. A
+.CW "Math"
+module encapsulates the procedures for numerical programming.
+.SH
+The Environment of the Inferno System
+.LP
+Inferno creates a standard environment for applications. Identical application programs can run
+under any instance of this environment, even in distributed fashion, and see the same resources.
+Depending on the environment in which Inferno itself is implemented, there are several versions of the Inferno kernel, Dis/Limbo interpreter, and device driver set.
+.LP
+When running as the native operating system, the kernel includes all the low-level glue (interrupt handlers, graphics and other device drivers) needed to implement the abstractions presented to applications.
+For a hosted system, for example under Unix, Windows NT or Windows 95, Inferno runs as a set of ordinary processes.
+Instead of mapping its device-control functionality to real hardware,
+it adapts to the resources provided by the operating system under which it runs.
+For example, under Unix, the graphics library might be implemented using the X window system and the networking using the socket interface; under Windows, it uses the native Windows graphics and Winsock calls.
+.LP
+Inferno is, to the extent possible, written in standard C and most of its components are independent of the many operating systems that can host it.
+.SH
+Security in Inferno
+.LP
+Inferno provides security of communication, resource control, and
+system integrity.
+.LP
+Each external communication channel may be transmitted in the clear,
+accompanied by message digests to prevent corruption, or encrypted to
+prevent corruption and interception. Once communication is set up,
+the encryption is transparent to the application. Key exchange is
+provided through standard public-key mechanisms; after key exchange,
+message digesting and line encryption likewise use standard symmetric
+mechanisms.
+.LP
+Inferno is secure against erroneous or malicious applications, and
+encourages safe collaboration between mutually suspicious service
+providers and clients. The resources available to applications appear
+exclusively in the name space of the application, and standard
+protection modes are available. This applies to data, to
+communication resources, and to the executable modules that constitute
+the applications. Security-sensitive resources of the system are
+accessible only by calling the modules that provide them; in
+particular, adding new files and servers to the name space is
+controlled and is an authenticated operation. For example, if the
+network resources are removed from an application's name space, then
+it is impossible for it to establish new network connections.
+.LP
+Object modules may be signed by trusted authorities who guarantee
+their validity and behavior, and these signatures may be checked by
+the system the modules are accessed.
+.LP
+Although Inferno provides a rich variety of authentication and security
+mechanisms, as detailed below, few application programs need to
+be aware of them or explicitly include coding to make use of them.
+Most often, access to resources across a secure communications link
+is arranged in advance by the larger system in which the application operates.
+For example, when a client system uses a server system
+and connection authentication or link encryption is appropriate,
+the server resources will most naturally be supplied
+as a part of the application's name space.
+The communications channel that carries the Styx protocol
+can be set to authenticate or encrypt; thereafter,
+all use of the resource is automatically protected.
+.SH
+Security mechanisms
+.LP
+Authentication and digital signatures are performed using
+public key cryptography. Public keys are certified by
+Inferno-based or other certifying authorities that sign the public keys with their
+own private key.
+.LP
+Inferno uses encryption for:
+.IP •
+mutual authentication of communicating parties;
+.IP •
+authentication of messages between these parties; and
+.IP •
+encryption of messages between these parties.
+.LP
+The encryption algorithms provided by Inferno
+include the SHA, MD4, and MD5 secure hashes;
+Elgamal public key signatures and signature verification [4];
+RC4 encryption;
+DES encryption;
+and public key exchange based on the Diffie-Hellman scheme.
+The public key signatures use keys with moduli up to 4096 bits,
+512 bits by default.
+.LP
+There is no generally accepted national or international authority
+for storing or generating public or private encryption keys.
+Thus Inferno includes tools for using or implementing a trusted authority,
+but it does not itself provide the authority,
+which is an administrative function.
+Thus an organization using Inferno (or any other security
+and key-distribution scheme) must design its system to suit its
+own needs, and in particular decide whom to trust as a Certifying
+Authority (CA). However, the Inferno design is sufficiently flexible
+and modular to accommodate the protocols likely to be attractive in practice.
+.LP
+The certifying authority that signs a user's
+public key determines the size of the key and the public key
+algorithm used. Tools provided with
+Inferno use these signatures for authentication. Library
+interfaces are provided for Limbo programs to sign and verify
+signatures.
+.LP
+Generally authentication is performed using public key cryptography. Parties
+register by having their public keys signed by the certifying authority (CA).
+The signature covers a secure hash (SHA, MD4, or MD5) of
+the name of the party, his public key, and an expiration time. The signature,
+which contains the name of the signer, along with the signed information,
+is termed a
+.I "certificate" .
+.LP
+When parties communicate, they use the Station to Station protocol[5] to
+establish the identities of the two parties and to create a mutually known secret.
+This STS protocol uses the Diffie-Hellman algorithm [6] to create this shared
+secret.
+The protocol is protected against replay attacks by choosing new random
+parameters for each conversation. It is secured against `man in
+the middle' attacks by having the parties exchange certificates and then
+digitally signing key parts of the protocol. To masquerade as another
+party an attacker would have to be able to forge that party's signature.
+.SH
+Line Security
+.LP
+A network conversation can be secured against modification alone
+or against both modification and snooping. To secure against
+modification, Inferno can append a secure MD5 or SHA hash (called a digest),
+.P1
+hash(secret, message, messageid)
+.P2
+to each message.
+.I "Messageid"
+is a 32 bit number that starts at 0 and is incremented by
+one for each message sent. Thus messages can be neither
+changed, removed, reordered or inserted into the stream without knowing
+the secret or breaking the secure hash algorithm.
+.LP
+To secure against snooping, Inferno supports encryption of the complete conversation
+using either RC4 or DES with either DES chain block coding (DESCBC)
+and electronic code book (DESECB).
+.LP
+Inferno uses the same encapsulation format as Netscape's Secure Sockets Layer [7].
+It is possible to encapsulate
+a message stream in multiple encapsulations to provide varying degrees of
+security.
+.SH
+Random Numbers
+.LP
+The strength of cryptographic algorithms depends in part on strength
+of the random numbers
+used for choosing keys, Diffie-Hellman parameters, initialization vectors, etc.
+Inferno achieves this in two steps: a slow (100 to 200 bit
+per second) random bit stream comes from sampling the low order bits of a
+free running counter whenever a clock ticks. The clock must be unsynchronized,
+or at least poorly synchronized, with the counter. This generator is then used to
+alter the state of a faster pseudo-random number generator.
+Both the slow and fast generators were tested on a number of architectures
+using self correlation, random walk, and repeatability tests.
+.SH
+Introduction to Limbo
+.LP
+Limbo is the application programming language for the Inferno operating system. Although Limbo looks syntactically like C, it has a number of features that make it easier to use, safer, and more suited to the heterogeneous, networked Inferno environment: a rich set of basic types, strong typing, garbage collection, concurrency, communications, and modules. Limbo may be interpreted or compiled `just in time' for efficient, portable execution.
+.LP
+This paper introduces the language by studying an example of a complete, useful Limbo program. The program illustrates general programming as well as aspects of concurrency, graphics, module loading, and other features of Limbo and Inferno.
+.SH
+The problem
+.LP
+Our example program is a stripped-down version of the Inferno[14] program
+.CW "view" ,
+which displays graphical image files on the screen, one per window. This version sacrifices some functionality, generality, and error-checking but performs the basic job. The files may be in either GIF[12, 13] or JPEG[19] format and must be converted before display, or they may already be in the Inferno standard format that needs no conversion.
+.CW "View"
+`sniffs' each file to determine what processing it requires, maps the colors if necessary, creates a new window, and copies the converted image to it. Each window is given a title bar across the top to identify it and hold the buttons to move and delete the window.
+.SH
+The Source
+.LP
+Here is the complete Limbo source for our version of
+.CW "view" ,
+annotated with line numbers for easy reference (Limbo, of course, does not use line numbers). Subsequent sections explain the workings of the program. Although the program is too large to absorb as a first example without some assistance, it's worth skimming before moving to the next section, to get an idea of the style of the language. Control syntax derives from C[11], while declaration syntax comes from the Pascal family of languages[17]. Limbo borrows features from a number of languages (e.g., tuples on lines 45 and 48) and introduces a few new ones (e.g. explicit module loading on lines 90 and 92).
+.P1
+ 1 implement View;
+.P3
+ 2 include "sys.m";
+ 3 sys: Sys;
+.P3
+ 4 include "draw.m";
+ 5 draw: Draw;
+ 6 Rect, Display, Image: import draw;
+.P3
+ 7 include "bufio.m";
+.P3
+ 8 include "imagefile.m";
+.P3
+ 9 include "tk.m";
+10 tk: Tk;
+.P3
+11 include "wmlib.m";
+12 wmlib: Wmlib;
+.P3
+13 include "string.m";
+14 str: String;
+.P3
+15 View: module
+16 {
+17 init: fn(ctxt: ref Draw->Context,
+ argv: list of string);
+18 };
+.P3
+19 init(ctxt: ref Draw->Context,
+ argv: list of string)
+20 {
+21 sys = load Sys Sys->PATH;
+22 draw = load Draw Draw->PATH;
+23 tk = load Tk Tk->PATH;
+24 wmlib = load Wmlib Wmlib->PATH;
+25 str = load String String->PATH;
+26 wmlib->init();
+.P3
+27 imageremap := load Imageremap
+ Imageremap->PATH;
+28 bufio := load Bufio Bufio->PATH;
+.P3
+29 argv = tl argv;
+30 if(argv != nil
+ && str->prefix("-x ", hd argv))
+31 argv = tl argv;
+.P3
+32 viewer := 0;
+33 while(argv != nil){
+34 file := hd argv;
+35 argv = tl argv;
+.P3
+36 im := ctxt.display.open(file);
+37 if(im == nil){
+38 idec := filetype(file);
+39 if(idec == nil)
+40 continue;
+.P3
+41 fd := bufio->open(file,
+ Bufio->OREAD);
+42 if(fd == nil)
+43 continue;
+.P3
+44 idec->init(bufio);
+45 (ri, err) := idec->read(fd);
+46 if(ri == nil)
+47 continue;
+.P3
+48 (im, err) = imageremap->remap(
+ ri, ctxt.display, 1);
+49 if(im == nil)
+50 continue;
+51 }
+.P3
+52 spawn view(ctxt, im, file,
+ viewer++);
+53 }
+54 }
+.P3
+55 view(ctxt: ref Draw->Context,
+ im: ref Image, file: string,
+ viewer: int)
+56 {
+57 corner := string(25+20*(viewer%5));
+.P3
+58 (nil, file) = str->splitr(file, "/");
+59 (t, menubut) := wmlib->titlebar(ctxt.screen,
+ " -x "+corner+" -y "+corner+
+ " -bd 2 -relief raised",
+ "View: "+file, Wmlib->Hide);
+.P3
+60 event := chan of string;
+61 tk->namechan(t, event, "event");
+.P3
+62 tk->cmd(t, "frame .im -height " +
+ string im.r.dy() +
+ " -width " +
+ string im.r.dx());
+63 tk->cmd(t, "bind . <Configure> "+
+ "{send event resize}");
+64 tk->cmd(t, "bind . <Map> "+
+ "{send event resize}");
+65 tk->cmd(t, "pack .im -side bottom"+
+ " -fill both -expand 1");
+66 tk->cmd(t, "update");
+.P3
+67 t.image.draw(posn(t), im, ctxt.display.ones, im.r.min);
+68 for(;;) alt{
+69 menu := <-menubut =>
+70 if(menu == "exit")
+71 return;
+72 wmlib->titlectl(t, menu);
+73 <-event =>
+74 t.image.draw(posn(t), im,
+ ctxt.display.ones, im.r.min);
+75 }
+76 }
+.P3
+77 posn(t: ref Tk->Toplevel): Rect
+78 {
+79 minx := int tk->cmd(t,
+ ".im cget -actx");
+80 miny := int tk->cmd(t,
+ ".im cget -acty");
+81 maxx := minx + int tk->cmd(t,
+ ".im cget -actwidth");
+82 maxy := miny + int tk->cmd(t,
+ ".im cget -actheight");
+.P3
+83 return ((minx, miny), (maxx, maxy));
+84 }
+.P3
+85 filetype(file: string): RImagefile
+86 {
+87 if(len file>4
+ && file[len file-4:]==".gif")
+88 r := load RImagefile
+ RImagefile->READGIFPATH;
+89 if(len file>4
+ && file[len file-4:]==".jpg")
+90 r = load RImagefile
+ RImagefile->READJPGPATH;
+91 return r;
+92 }
+.P2
+.SH
+Modules
+.LP
+Limbo programs are composed of modules that are loaded and linked at run-time. Each Limbo source file is the implementation of a single module; here line 1 states this file implements a module called
+.CW "View" ,
+whose declaration appears in the
+.CW "module"
+declaration on lines 15-18. The declaration states that the module has one publicly visible element, the function
+.CW "init" .
+Other functions and variables defined in the file will be compiled into the module but only accessible internally.
+.LP
+The function
+.CW "init"
+has a type signature (argument and return types) that makes it callable from the Inferno shell, a convention not made explicit here. The type of
+.CW "init"
+allows
+.CW "View"
+to be invoked by typing, for example,
+.P1
+view *.jpg
+.P2
+at the Inferno command prompt to view all the JPEG files in a directory. This interface is all that is required for the module to be callable from the shell; all programs are constructed from modules, and some modules are directly callable by the shell because of their type. In fact the shell invokes
+.CW "View"
+by loading it and calling
+.CW "init" ,
+not for example through the services of a system
+.CW "exec"
+function as in a traditional operating system.
+.LP
+Not all modules, of course, implement shell commands; modules are also used to construct libraries, services, and other program components. The module
+.CW "View"
+uses the services of other modules for I/O, graphics, file format conversion, and string processing. These modules are identified on lines 2-14. Each module's interface is stored in a public `include file' that holds a definition of a module much like lines 15-18 of the
+.CW "View"
+program. For example, here is an excerpt from the include file
+.CW "sys.m" :
+.P1
+Sys: module
+{
+ PATH: con "$Sys";
+
+ FD: adt # File descriptor
+ {
+ fd: int;
+ };
+
+ OREAD: con 0;
+ OWRITE: con 1;
+ ORDWR: con 2;
+
+ open: fn(s: string, mode: int): ref FD;
+ print: fn(s: string, *): int;
+ read: fn(fd: ref FD, buf: array of byte, n: int): int;
+ write: fn(fd: ref FD, buf: array of byte, n: int): int;
+};
+.P2
+This defines a module type, called
+.CW "Sys" ,
+that has functions with familiar names like
+.CW "open"
+and
+.CW "print" ,
+constants like
+.CW "OREAD"
+to specify the mode for opening a file, an aggregate type
+.CW "adt" ) (
+called
+.CW "FD" ,
+returned by
+.CW "open" ,
+and a constant string called
+.CW "PATH" .
+.LP
+After including the definition of each module,
+.CW "View"
+declares variables to access the module. Line 3, for example, declares the variable
+.CW "sys"
+to have type
+.CW "Sys" ;
+it will be used to hold a reference to the implementation of the module. Line 6 imports a number of types from the
+.CW "draw"
+(graphics) module to simplify their use; this line states that the implementation of these types is by default to be that provided by the module referenced by the variable
+.CW "draw" .
+Without such an
+.CW "import"
+statement, calls to methods of these types would require explicit mention of the module providing the implementation.
+.LP
+Unlike most module languages, which resolve unbound references to modules automatically, Limbo requires explicit `loading' of module implementations.
+Although this requires more bookkeeping, it allows a program to have fine control over the loading (and unloading) of modules, an important property in the small-memory systems in which Inferno is intended to run.
+Also, it allows easy garbage collection of unused modules and allows multiple implementations to serve a single interface, a style of programming we will exploit in
+.CW "View" .
+.LP
+Declaring a module variable such as
+.CW "sys"
+is not sufficient to access a module; an implementation must also be loaded and bound to the variable. Lines 21-25 load the implementations of the standard modules used by
+.CW "View" .
+The
+.CW "load"
+operator, for example
+.P1
+sys = load Sys Sys->PATH;
+.P2
+takes a type
+.CW "Sys" ), (
+the file name of the implementation
+.CW "Sys->PATH" ), (
+and loads it into memory. If the implementation matches the specified type, a reference to the implementation is returned and stored in the variable
+.CW "sys" ). (
+If not, the constant
+.CW "nil"
+will be returned to indicate an error. Conventionally, the
+.CW "PATH"
+constant defined by a module names the default implementation. Because
+.CW "Sys"
+is a built-in module provided by the system, it has a special form of name; other modules'
+.CW "PATH"
+variables name files containing actual code. For example,
+.CW "Wmlib->PATH"
+is \f5"/dis/lib/wmlib.dis"\fP.
+Note, though, that the name of the implementation of the module in a
+.CW "load"
+statement can be any string.
+.LP
+Line 26 initializes the
+.CW "wmlib"
+module by invoking its
+.CW "init"
+function (unrelated to the
+.CW "init"
+of
+.CW "View" ).
+Note the use of the
+.CW "->"
+operator to access the member function of the module. The next two lines load modules, but add a new wrinkle: they also
+.I "declare"
+and
+.I "initialize"
+the module variables storing the reference. Limbo declarations have the general form
+.P1
+\fIvar\fP: \fItype\fP = \fIvalue\fP;
+.P2
+If the type is missing, it is taken to be the type of the value, so for example,
+.P1
+bufio := load Bufio Bufio->PATH;
+.P2
+on line 28 declares a variable of type
+.CW "Bufio"
+and initializes it to the result of the
+.CW "load"
+expression.
+.SH
+The main loop
+.LP
+The
+.CW "init"
+function takes two parameters, a graphics context,
+.CW "ctxt" ,
+for the program and a list of command-line argument strings,
+.CW "argv" .
+.CW "Argv"
+is a
+.CW "list"
+.CW "of"
+.CW "string" ;
+strings are a built-in type in Limbo and lists are a built-in form of constructor. Lists have several operations defined:
+.CW "hd"
+(head) returns the first element in the list,
+.CW "tl"
+(tail) the remainder after the head, and
+.CW "len"
+(length) the number of elements in the list.
+.LP
+Line 29 throws away the first element of
+.CW "argv" ,
+which is conventionally the name of the program being invoked by the shell, and lines 30-31 ignore a geometry argument passed by the window system. The loop from lines 33 to 53 processes each file named in the remaining arguments; when
+.CW "argv"
+is a
+.CW "nil"
+list, the loop is complete. Line 34 picks off the next file name and line 35 updates the list.
+.LP
+Line 36 is the first method call we have seen:
+.P1
+im := ctxt.display.open(file);
+.P2
+The parameter
+.CW "ctxt"
+is an
+.CW "adt"
+that contains all the relevant information for the program to access its graphics environment. One of its elements, called
+.CW "display" ,
+represents the connection to the frame buffer on which the program may write. The
+.CW "adt"
+.CW "display"
+(whose type is imported on line 6) has a member function
+.CW "open"
+that reads a named image file into the memory associated with the frame buffer, returning a reference to the new image. (In X[20] terminology,
+.CW "display"
+represents a connection to the server and
+.CW "open"
+reads a pixmap from a file and instantiates it on that server.)
+.LP
+The
+.CW "display.open"
+method succeeds only if the file exists and is in the standard Inferno image format. If it fails, it will return
+.CW "nil"
+and lines 38-50 will attempt to convert the file into the right form.
+.SH
+Decoding the file
+.LP
+Line 38 calls
+.CW "filetype"
+to determine what format the file has. The simple version here, on lines 85-92, just looks at the file suffix to determine the type. A realistic implementation would work harder, but even this version illustrates the utility of program-controlled loading of modules.
+.LP
+The decoding interface for an image file format is specified by the module type
+.CW "RImagefile" .
+However, unlike the other modules we have looked at,
+.CW "RImagefile"
+has a number of implementations. If the file is a GIF file,
+.CW "filetype"
+returns the implementation of
+.CW "RImagefile"
+that decodes GIFs; if it is a JPEG file,
+.CW "filetype"
+returns an implementation that decodes JPEGs. In either case, the
+.CW "read"
+method has the same interface. Since reference variables like
+.CW "r"
+are implicitly initialized to
+.CW "nil" ,
+that is what
+.CW "filetype"
+will return if it does not recognize the image format.
+.LP
+Thus,
+.CW "filetype"
+accepts a file name and returns the implementation of a module to decode it.
+.LP
+A couple of other points about
+.CW "filetype" .
+First, the expression
+.CW "file[len file-4:]"
+is a
+.I "slice"
+of the string
+.CW "file" ;
+it creates a string holding the last four characters of the file name. The colon separates the starting and ending indices of the slice; the missing second index defaults to the end of the string. As with lists,
+.CW "len"
+returns the number of characters (not bytes; Limbo uses Unicode[21] throughout) in the string.
+.LP
+Second, and more important, this version of
+.CW "filetype"
+loads the decoder module anew every time it is called, which is clearly inefficient. It's easy to do better, though: just store the module in a global, as in this fragment:
+.P1
+readjpg: RImagefile;
+filetype(...)...
+{
+ if(isjpg()){
+ if(readjpg == nil)
+ readjpg = load RImagefile
+ RImagefile->READJPGPATH;
+ return readjpg;
+ }
+}
+.P2
+The program can form its own policies on loading and unloading modules based on time/space or other tradeoffs; the system does not impose its own.
+.LP
+Returning to the main loop, after the type of the file has been discovered, line 41 opens the file for I/O using the buffered I/O package. Line 44 calls the
+.CW "init"
+function of the decoder module, passing it the instance of the buffered I/O module being used (if we were caching decoder modules, this call to
+.CW "init"
+would be done only when the decoder is first loaded.) Finally, the Limbo-characteristic line 45 reads in the file:
+.P1
+(ri, err) := idec->read(fd);
+.P2
+The
+.CW "read"
+method of the decoder does the hard job of cracking the image format, which is beyond the scope of this paper. The result is a
+.I "tuple" :
+a pair of values. The first element of the pair is the image, while the second is an error string. If all goes well, the
+.CW "err"
+will be
+.CW "nil" ;
+if there is a problem, however,
+.CW "err"
+may be printed by the application to report what went wrong. The interesting property of this style of error reporting, common to Limbo programs, is that an error can be returned even if the decoding was successful (that is, even if
+.CW "ri"
+is non-
+.CW "nil" ).
+For example, the error may be recoverable, in which case it is worth returning the result but also worth reporting that an error did occur, leaving the application to decide whether to display the error or ignore it.
+.CW "View" "\ " (
+ignores it, for brevity.)
+.LP
+In a similar manner, line 48 remaps the colors from the incoming colormap associated with the file to the standard Inferno color map. The result is an image ready to be displayed.
+.SH
+Creating a process
+.LP
+By line 52 in the main loop, we have an image ready in the variable
+.CW "im"
+and use the Limbo primitive
+.CW "spawn"
+to create a new process to display that image on the screen.
+.CW "Spawn"
+operates on a function call, creating a new process to execute that function. The process doing the spawning, here the main loop, continues immediately, while the new process begins execution in the specified function with the specified parameters. Thus line 52 begins a new process in the function
+.CW "view"
+with arguments the graphics context, the image to display, the file name, and a unique identification number used in placing the windows.
+.LP
+The new process shares with the calling process all variables except the stack. Shared memory can therefore be used to communicate between them; for synchronization, a more sophisticated mechanism is needed, a subject we will cover in the section on communications.
+.SH
+Starting Tk
+.LP
+The function
+.CW "view"
+uses the Inferno Tk graphics toolkit (a re-implementation for Limbo of Ousterhout's Tcl/Tk toolkit [18]) to place the image on the screen in a new window. Line 57 computes the position of the corner of the window, using the viewer number to stagger the positions of successive windows. The
+.CW "string"
+keyword is a conversion; in this example the conversion does an automatic translation from an integer expression into a decimal representation of the number. Thus
+.CW "corner"
+is a string variable, a form more useful in the calls to the Tk library.
+.LP
+The Inferno Tk implementation uses Limbo as its controlling language.
+Rather than building a rich procedural interface, the interface passes strings to a generic Tk command processor, which returns strings as results.
+This is similar to the use Tk within Tcl, but with most of the control flow, arithmetic, and so on written in Limbo.
+.LP
+A good introduction to the style is the function
+.CW "posn"
+on lines 77-84. The calls to
+.CW "tk->cmd"
+evaluate the textual command in the context defined by the
+.CW "Tk->Toplevel"
+variable
+.CW "t"
+(created on line 57 and passed to
+.CW "posn" );
+the result is a decimal integer, converted to binary by the explicit
+.CW "int"
+conversion. On line 83, all the coordinates of the rectangle are known, and the function returns a nested tuple defining the rectangular position of the
+.CW ".im"
+component of the Toplevel. This tuple is automatically promoted to the
+.CW "Rect"
+type by the return statement.
+.LP
+Back in function
+.CW "view" ,
+line 58 uses a function from the higher-level
+.CW "String"
+module to strip off the basename of the file name, for use in the banner of the window. Note that one component of the tuple is nil; the value of this component is discarded.
+Line 58 calls the window manager function
+.CW "wmlib->titlebar"
+to establish a title bar on the window
+The arguments are
+.CW "ctxt.screen" ,
+a data structure representing the window stack on the frame buffer,
+a string specifying the size and properties of the new window, the window's
+label, and the set of control buttons required.
+The
+.CW "+"
+operator on strings performs concatenation.
+The window is labelled \f5"View"\fP
+and the file basename, with a control button to hide the window.
+Titlebars always include a control button to dismiss the window.
+(The size and properties argument is more commonly nil or the empty string,
+leaving the choice of position and style to the window manager.)
+The first value
+in the tuple returned by
+.CW "wmlib->titlebar"
+is a reference to a `top-level' widget\-a window\-upon which the program will assemble its display.
+.SH
+Communications
+.LP
+The second value in the tuple
+returned from
+.CW "wmlib->titlebar"
+is a built-in Limbo type called a channel
+.CW "chan" "" (
+is the keyword). A channel is a communications mechanism in the manner of Hoare's CSP[15]. Two processes that wish to communicate do so using a shared channel; data sent on the channel by one process may be received by another process. The communication is
+.I "synchronous" :
+both processes must be ready to communicate before the data changes hands, and if one is not ready the other blocks until it is. Channels are a feature of the Limbo language: they have a declared type
+.CW "chan" "" (
+.CW "of"
+.CW "int" ,
+.CW "chan"
+.CW "of"
+.CW "list"
+.CW "of"
+.CW "string" ,
+etc.) and only data of the correct type may be sent. There is no restriction on what may be sent; one may even send a channel on a channel. Channels therefore serve both to communicate and to synchronize.
+.LP
+Channels are used throughout Inferno to provide interfaces to system functions. The threading and communications primitives in Limbo are not designed to implement efficient multicomputer algorithms, but rather to provide an elegant way to build active interfaces to devices and other programs.
+.LP
+One example is the
+.CW "menubut"
+channel returned by
+.CW "wmlib->titlebar" ,
+a channel of textual commands sent by the window manager. The expression on line 69,
+.P1
+menu := <-menubut
+.P2
+receives the next message on the channel and assigns it to the variable menu. The communications operator,
+.CW "<-" ,
+receives a datum when prefixed to channel and transmits a datum when combined with an assignment operator (e.g.
+.CW "channel<-=2" ).
+This use of menubut appears inside an
+.CW "alt"
+(alternation) statement, a construct we'll discuss later.
+.LP
+Lines 60 and 61 create and register a new channel,
+.CW "event" ,
+to be used by the Tk module to report user interface events. Lines 62-66 use simple Tk operations to make the window in which the image may be drawn. Lines 63 and 64 bind events within this window to messages to be sent on the channel
+.CW "event" .
+For example, line 63 defines that when the configuration of the window is changed, presumably by actions of the window manager, the string
+\f5"resize"\fP
+is to be transmitted on
+.CW "event"
+for interpretation by the application. This translation of events into messages on explicit channels is fundamental to the Limbo style of programming.
+.SH
+Displaying the image
+.LP
+The payoff occurs on line 67, which steps outside the Tk model to draw the image
+.CW "im"
+directly on the window:
+.P1
+t.image.draw(posn(t), im, ctxt.display.ones, im.r.min);
+.P2
+.CW "Posn"
+calculates where on the screen the image is to go. The
+.CW "draw"
+method is the fundamental graphics operation in Inferno, whose design is outside our scope here. In this statement, it just copies the pixels from
+.CW "im"
+to the window's own image,
+.CW "t.image" ;
+the argument
+.CW "ctxt.display.ones"
+is a mask that selects every pixel.
+.SH
+Multi-way communications
+.LP
+Once the image is on the screen,
+.CW "view"
+waits for any changes in the status of the window. Two things may happen: either the buttons on the title bar may be used, in which case a message will appear on
+.CW "menubut" ,
+or a configuration or mapping operation will apply to the window, in which case a message will appear on
+.CW "event" .
+.LP
+The Limbo
+.CW "alt"
+statement provides control when more than one communication may proceed. Analogous to a
+.CW "case"
+statement, the
+.CW "alt"
+evaluates a set of expressions and executes the statements associated with the correct expression. Unlike a
+.CW "case" ,
+though, the expressions in an
+.CW "alt"
+must each be a communication, and the
+.CW "alt"
+will execute the statements associated with the communication that can first proceed. If none can proceed, the
+.CW "alt"
+waits until one can; if more than one can proceed, it chooses one randomly.
+.LP
+Thus the loop on lines 68-75 processes messages received by the two classes of actions. When the window is moved or resized, line 73 will receive a \f5"resize"\fP
+message due to the bindings on lines 63 and 64. The message is discarded but the action of receiving it triggers the repainting of the newly placed window on line 74. Similarly, messages triggered by buttons on the title bar send a message on
+.CW "menubut" ,
+and the value of that is examined to see if it is
+\f5"exit"\fP,
+which should be handled locally, or anything else, which can be passed on to the underlying library.
+.SH
+Cleanup
+.LP
+If the exit button is pushed, line 71 will return from
+.CW "view" .
+Since
+.CW "view"
+was the top-level function in this process, the process will exit, freeing all its resources. All memory, open file descriptors, windows, and other resources held by the process will be garbage collected when the return executes.
+.LP
+The Limbo garbage collector [16] uses a hybrid scheme that combines reference counting to reclaim memory the instant its last reference disappears with a real-time sweeping algorithm that runs as an idle-time process to reclaim unreferenced circular structures.
+The instant-free property means that system resources like file descriptors and windows can be tied to the collector for recovery as soon as they become unused; there is no pause until a sweeper discovers it.
+This property allows Inferno to run in smaller memory arenas than are required for efficient mark-and-sweep algorithms, as well as providing an extra level of programmer convenience.
+.SH
+Summary
+.LP
+Inferno supplies a rich environment for constructing distributed applications that are portable\-in fact identical\-even when running on widely divergent underlying hardware. Its unique advantage over other solutions is that it encompasses not only a virtual machine, but also a complete virtual operating system including network facilities.
+.SH
+Acknowledgment
+.LP
+The cryptographic elements of Inferno owe much
+to the cryptographic library of Lacy et al. [22].
+.SH
+References
+.LP
+.nr PS -1
+.nr VS -1
+.IP 1.
+R. Pike, D. Presotto, S. Dorward, B. Flandrena, K. Thompson, H. Trickey, and P. Winterbottom. ``Plan 9 from Bell Labs'',
+.I "J. Computing Systems"
+8:3, Summer 1995, pp. 221-254.
+.IP 2.
+S. Dorward, R. Pike, and P. Winterbottom. ``Programming in Limbo'',
+.I "IEEE Compcon 97 Proceedings" ,
+1997.
+.IP 3.
+J. K. Ousterhout.
+.I "Tcl and the Tk Toolkit" ,
+Addison-Wesley, 1994.
+.IP 4.
+T. Elgamal, ``A Public-Key Cryptosystem and a Signature Scheme Based on Discrete Logarithms'',
+.I "Advances in Cryptography: Proceedings of CRYPTO 84, "
+Springer Verlag, 1985, pp. 10-18
+.IP 5.
+B. Schneier, ``Applied Cryptography'', Wiley, 1996, p. 516
+.IP 6.
+D. Stinson, ``Cryptography, Theory and Practice'',
+.I "CRC Press" ,
+1996, p. 271
+.IP 7.
+K. Hickman and T. Elgamal, ``The SSL Protocol (V3.0)'',
+.I "IETF Internet-draft"
+.IP 8.
+S. M. Bellovin and M. Merritt, ``Encrypted Key Exchange: Password-Based Protocols Secure Against Dictionary Attack'', Proceedings of the 1992 IEEE Computer Society Conference on Research in Security and Privacy, 1992, pp. 72-84
+.IP 9.
+M. Blaze, J. Feigenbaum, J. Lacy, ``Decentralized Trust Management'',
+.I "Proceedings 1996 IEEE Symposium on Security and Privacy" ,
+May 1996
+.IP 10.
+R. Rivest and B. Lampson, ``SDSI - A Simple Distributed Security Architecture'', unpublished,
+.I "http://theory.lcs.mit.edu/~rivest/sdsi10.ps"
+.IP 11.
+.I "American National Standard for Information Systems Programming Language C" ,
+American National Standards Institute, X3.159-1989.
+.IP 12.
+.I "GIF Graphics Interchange Format: A standard defining a mechanism for the storage and transmission of bitmap-based graphics information" ,
+CompuServe Incorporated, Columbus, OH, 1987.
+.IP 13.
+.I "GIF Graphics Interchange Format: Version 89a" ,
+CompuServe Incorporated, Columbus, OH, 1990.
+.IP 14.
+S. Dorward et al., ``Inferno'',
+.I "IEEE Compcon 97 Proceedings" ,
+1997.
+.IP 15.
+C. A. R. Hoare, ``Communicating Sequential Processes''.
+.I "Comm. ACM"
+21:8, pp. 666-677, 1978.
+.IP 16.
+L. Huelsbergen, and P. Winterbottom, ``Very Concurrent Mark & Sweep Garbage Collection without Fine-Grain Synchronization'', Submitted
+.I "International Conference of Functional Programming" ,
+Amsterdam, 1997.
+.IP 17.
+K. Jensen, and N. Wirth,
+.I "PascalUser Manual and Report" .
+Springer-Verlag, 1974.
+.IP 18.
+John K. Ousterhout,
+.I "Tcl and the Tk Toolkit" ,
+Addison-Wesley, 1994.
+.IP 19.
+W. B. Pennebaker. and J. L. Mitchell,
+.I "JPEG Still Image Data Compression" ,
+Van Nostrand Reinhold, New York, 1992.
+.IP 20.
+R. W. Scheifler, J. Gettys, and R. Newman,
+.I "X Window System" ,
+Digital Press, 1988.
+.IP 21.
+The Unicode Consortium,
+.I "The Unicode Standard, Version 2.0, "
+Addison Wesley, 1996.
+.IP 22.
+J. B. Lacy, D. P. Mitchell, and W. M. Schell, ``CryptoLib: Cryptography in Software,''
+.I "UNIX Security Symposium IV Proceedings" ,
+USENIX Association, 1993 pp. 1-17.
+.nr PS +1
+.nr VS +1
binary files /dev/null b/doc/bltj.pdf differ
--- /dev/null
+++ b/doc/changes.ms
@@ -1,0 +1,2053 @@
+.\"<-xtx-*> tbl changes.ms | troff -ms | lp -d stdout
+.FP palatino
+.ps 9
+.nr PS 9
+.vs 11
+.nr VS 11
+.nr dP 1
+.nr dV 1p
+.nr dT 4m
+.nr XT 4
+.TL
+System and Interface Changes to Inferno
+.AU
+C H Forsyth
+.br
+Vita Nuova
+.br
+forsyth@vitanuova.com
+.br
+9 June 2003
+.SH
+Overview
+.LP
+This paper describes some of the changes made to Inferno
+interfaces as they stood in the published Third Edition manuals,
+to form the current Fourth Edition of the system,
+and the broad effects on internal and external interfaces.
+Changes include: extensions to the Limbo language;
+new instructions in Dis and the virtual machine; extra content
+in Dis object files; structure of the source tree; configuration of
+.CW emu ;
+replacement of the window system with changes to the client interface;
+commands renamed, replaced, and removed;
+revised support for network booting;
+9P2000 becomes the basis for Styx;
+a graphics model offering alpha-blended compositing and general pixel structure;
+and improvements to Tk.
+.NH 1
+Limbo
+.LP
+Exceptions and fixed point have been added to the Limbo language.
+They are described in more detail in separate notes by John Firth,
+shortly to be available on the Vita Nuova web site
+.CW www.vitanuova.com .
+Channels can now be buffered.
+A form of polymorphism is now available in Limbo.
+.NH 2
+Exceptions
+.LP
+Discussion of exceptions will be restricted here to implications for existing source code.
+The most obvious changes are that
+.CW Sys->rescue ,
+.CW Sys->rescued ,
+.CW Sys->unrescue
+and
+.CW Sys->raise
+have vanished.
+Instead the exception handling is expressed using constructions in the Limbo language.
+Named exceptions can be declared and used (these are described in the note by Firth), and
+they are declared as part of the type of functions that raise them.
+There is also a general `failure' exception that effectively subsumes the old
+.CW Sys->rescue
+scheme, including run-time errors such as `out of memory' that can happen in almost any function.
+Unlike named exceptions a `failure' exception can be raised or caught by any function,
+and its value is a string.
+The
+.CW raise
+statement raises an exception.
+This is most obvious in commands that wish to produce an `exit status'.
+Instead of
+.P1
+sys->raise("fail:usage");
+.P2
+one must now write
+.P1
+raise "fail:usage";
+.P2
+(That is one of the more common source changes required to Third Edition Limbo commands,
+since that was the most common use of exceptions before.)
+A block can have an
+.CW exception
+handler:
+.P1
+{
+ a := array[128] of byte;
+ dosomething(a);
+} exception e {
+"out of memory:*" =>
+ sys->print("i need more space: %s\en", e);
+"fail:*" =>
+ sys->print("exit status: %s\en", e);
+"*" =>
+ sys->print("unexpected error: %s\en", e);
+ raise; # propagate it
+}
+.P2
+If an exception is raised during the execution of the block (including functions it calls),
+execution of the block is abandoned, and control transfers to the appropriate exception handler
+(which is outside the block).
+Because the compiler and run-time system know the scope of the exception,
+values such as
+.CW a
+above are correctly reclaimed on exit from the faulty block.
+Unhandled failures are propagated to callers; unhandled named exceptions (currently) become failures.
+.LP
+A process group can cause unhandled exceptions in any process in the group either to
+propagate to all members of the group, or to be propagated to the process group leader
+after destroying the other processes in the group.
+This makes it easier to program recovery from exceptions within a group of concurrent processes.
+For instance, if a process is expected to send to another on a channel, but fails unexpectedly instead
+(eg, because memory was exhausted),
+instead of leaving the intended recipient blocked on a receive operation, it can be sent
+an exception to notify it of the failure of the other process, allowing it to take appropriate recovery action.
+(This could sometimes be programmed using the
+.CW wait
+file of
+.I prog (3),
+but not always.)
+.LP
+Exception handling is intended for recovering from disaster.
+We still think it is better Limbo style
+to use tuples, channels and processes to make ordinary error handling explicit.
+The few attempts to use failure exceptions to achieve `pretty' but peculiar control flow have had exactly the usual
+effect of making the code hard to follow and error-prone.
+.NH 2
+Channels
+.LP
+Buffered channels have been added:
+.P1
+c := chan [N] of int;
+.P2
+where
+.I N
+is an integer value,
+creates a channel that will allow up to
+.I N
+integer values to be sent to it without an intervening receive without blocking the sender.
+If
+.I N
+is zero, the channel is unbuffered, equivalent to plain
+.CW "chan of int" ,
+and synchronises sender and receiver as before.
+.LP
+The restriction that a given channel value could not be sent to or received from in two
+.CW alt
+statements simultaneously has been removed.
+.NH 2
+Polymorphism
+.LP
+John Firth has implemented a form of parametric polymorphism in Limbo.
+It too will be described in a separate note.
+Currently we are still fussing over aspects of the constraint syntax
+and some other implications of the most general form, and since some aspects are
+therefore subject to change, including syntax, we have not yet published the details.
+We think it is possible to use the following subset without having to change the code later:
+.IP 1.
+Function declarations can be parametrised by one or more type variables:
+For example:
+.RS
+.P1
+reverse[T](l: list of T): list of T
+{
+ rl: list of T;
+ for(; l != nil; l = tl l)
+ rl = hd l :: rl;
+ return rl;
+}
+.P2
+Such a function can then be invoked on any compatible set of values.
+The function invocation does not specify the type (the compiler does type unification on the parameters).
+Thus the above can be used as:
+.P1
+l1: list of string;
+l2: list of ref Item;
+l3: list of list of string;
+l1 = reverse(l1);
+l2 = reverse(l2);
+l3 = reverse(l3);
+.P2
+.RE
+.IP 2.
+ADTs can also be parametrised:
+.P1
+Tree: adt[T] {
+ v: T;
+ l, r: cyclic ref Tree[T];
+};
+.P2
+allowing declaration of
+.CW "Tree[ref Item]"
+and
+.CW "Tree[string]"
+for instance.
+.IP 3.
+Values of the parametrised type can only be declared, assigned, passed as parameters, returned,
+or sent down channels.
+The only types that can be used as actual parameter types are reference types (ie,
+.CW ref " ADT,"
+.CW array ,
+.CW chan ,
+.CW list
+and
+.CW module ),
+and
+.CW string
+(which is a value type but is implemented using a reference).
+At some point we shall allow a function such as
+.CW reverse
+above to be invoked with any compatible type (not just reference types) but
+that requires changes to Dis and the virtual machine not yet made.
+.LP
+The formal type parameters can be further constrained by listing a set
+of operations that they must have (which currently implies the actual parameters
+must be ADT types with compatible operations).
+We are not completely happy with the current constraint syntax, and some other
+aspects of the scheme, and so that
+be described here later once we have settled it.
+.NH 1
+Dis and virtual machine
+.LP
+To make the Limbo changes and extensions some new operators were added to
+the virtual machine.
+(We also added a
+.CW casel
+operator to allow
+.CW case
+statements to work on
+.CW big
+values.)
+Modules that have exception handlers also have a (new) exception table,
+added to the Dis object format.
+Furthermore, we moved the import table used by the
+.CW load
+operator out of the Dis data space into the object format
+(which also makes it available for inspection by
+.CW wm/rt
+amongst others).
+.LP
+There is now an internal interface to set conditions under
+which modules must be signed to be loaded, and to check a signature on a module.
+Appropriate stubs are defined when module signing is not configured; if
+.I sign (3)
+is configured, however, it replaces them by ones that enforce its signing policy.
+.NH 1
+Window manager
+.LP
+The window manager
+.I wm (1)
+has been reimplemented by Roger Peppe.
+It now multiplexes pointer and keyboard input to applications,
+and manages windows on the display.
+.I Tk (2)
+no longer manages windows from inside the kernel.
+In some ways the structure is closer to that of
+.I mux (1)
+and more specifically the design described in Rob Pike's paper ``A Concurrent Window System''.
+It is possible to import and export window system environments between hosts.
+.LP
+This is one of the bigger causes of source file changes, although many of them
+can be done by global substitutions (eg, using
+.I acme (1)).
+Appendix A gives details.
+.CW Wmlib
+is no longer the application's interface to the window system.
+Instead that is done through a new
+.CW Tkclient
+module; see
+.I tkclient (2).
+(It uses a different
+.CW Wmlib
+as an auxiliary module,
+and also uses a new
+.CW Titlebar
+module to allow the look of the window decoration to be changed more easily).
+An application acquires a window by a call to
+.CW Tkclient->toplevel ;
+starts pointer or keyboard input if desired by calling
+.CW Tkclient->startinput ;
+and puts the window on screen (after sending it Tk configuration commands)
+using
+.CW Tkclient->onscreen .
+Nothing appears on screen until that is called (which amongst other things avoids the resizing on start up that afflicted
+the original scheme).
+.CW Onscreen
+gives it a connection to the window manager for pointer, keyboard and control input,
+with a separate channel for each.
+When it receives data from any of the channels
+(typically using
+.CW alt )
+it must pass it to Tk using calls to appropriate
+.CW Tkclient
+functions.
+.LP
+The toolbar used by the old
+.I wm
+is now provided by a separate program
+.CW wm/toolbar
+(see
+.I toolbar (1)),
+and it is
+.CW toolbar
+that interprets the
+.CW /lib/wmsetup
+file.
+.CW Wm
+invokes
+.CW wm/toolbar
+by default so most users will see no difference, but it does make it easier to develop alternative interfaces.
+More visible is that
+.CW wm/logon
+is now a
+.I client
+of the window manager, and must be invoked as follows:
+.P1
+wm/wm wm/logon
+.P2
+.LP
+Applications need not even use
+.I tk (2).
+There is an interface for
+.CW draw -only
+clients,
+.I wmclient (2).
+.NH 1
+Inferno source tree
+.LP
+The structure of the Inferno source tree has changed in the following ways.
+.NH 2
+Library source
+.LP
+The
+.CW image
+and
+.CW memimage
+directories have gone, replaced by
+.CW libdraw
+and
+.CW libmemdraw .
+The directories in the Inferno root that contain the source for libraries
+now
+always have names starting `\f5lib\f1':
+.CW libcrypt ,
+.CW libinterp ,
+.CW libkeyring ,
+.CW libmath ,
+etc.
+.NH 2
+Emu source
+.LP
+The
+.CW emu
+directory now contains a subdirectory structure similar to the
+.CW os
+kernels, and uses a similar configuration file (parts list) to say what goes in
+a given instance of
+.CW emu .
+This allows platform-dependent selection of drivers, libraries and even
+.CW #/
+(ie,
+.I root (3))
+contents to be done easily.
+.LP
+The top directory,
+.CW /emu ,
+contains:
+.CW mkfile
+that simply moves to the platform configured by
+.CW /mkconfig ,
+allowing builds in the Inferno root as before;
+a subdirectory
+.CW port
+containing portable code (including some code shared by several platforms, such as
+.CW devfs-posix.c );
+and a subdirectory for each hosting platform, distinguished by an upper-case initial letter.
+Current platforms include
+.CW FreeBSD ,
+.CW Irix ,
+.CW Linux ,
+.CW Nt
+(for all Windows platforms after 95),
+.CW Plan9 ,
+.CW Solaris ,
+and several others.
+.NH 2
+Emu configuration
+.LP
+Each platform-specific directory contains a configuration file with the
+same structure and indeed similar contents to the ones used for the native kernel.
+The default configuration file is called
+.CW emu .
+Another can be chosen, again in a similar way to the native kernel, by using
+.P1
+mk 'CONF=\fIcfile\fP'
+.P2
+where
+.I cfile
+is the name of the configuration file.
+The name of the resulting executable file contains the configuration file name but depends on the platform:
+it is \fIcfile\fP\f5.exe\fP on Windows, \f5o.\fP\fIcfile\fP on Unix systems, and \f58.\fP\fIcfile\fP on 386 Plan 9 systems.
+The configuration file format and contents is documented for all types of kernels by
+.I conf (10.6).
+.NH 2
+Tk source
+.LP
+The Tk implementation in
+.CW libtk
+has been made more modular.
+It allows a significantly different `style' to be implemented,
+and although that is by no means trivial to do, there is at least an interface to do it.
+We hope to change various aspects of the standard style further, but that has not yet been done.
+.NH 1
+Commands and modules
+.LP
+There are new commands and library modules, others have become obsolete and been removed,
+and a few existing ones have been given new names (typically when ones with similar function have been
+collected together).
+The biggest change has been to
+.I wm (1),
+which retains the same name but slightly different invocation and completely different
+implementation,
+as discussed above.
+Here I shall simply note the bigger changes, rather than discuss new functionality.
+.NH 2
+Renamed commands
+.LP
+As part of a mild reorganisation of the
+.CW /appl
+and
+.CW /dis
+trees, we have moved commands out of
+.CW /dis/lib
+so that it now contains only library modules except for a few commands left
+there temporarily for compatibility.
+Commands themselves have sometimes been shuffled to subdirectories,
+often copying seemingly better structure from Plan 9,
+so that authentication commands are
+.CW auth/ ...,
+naming service commands are
+.CW ndb/ ...,
+and
+IP-specific commands are
+.CW ip/ "... ."
+.LP
+One noticeable change is that
+.CW lib/cs
+is now
+.CW ndb/cs .
+More dramatically, the command
+.CW lib/srv
+(ie,
+.I srv (8))
+has been replaced by
+.I sh (1)
+scripts, all described by
+.I svc (8),
+that contain appropriate calls to
+.I listen (1)
+after setting up any locally-desired environment.
+.LP
+Other commands have also moved:
+.IP •
+.CW lib/plumber
+is now simply
+.CW plumber
+.IP •
+.CW lib/bootp
+and
+.CW lib/tfptd
+have become
+.CW ip/bootpd
+and
+.CW ip/tftpd ,
+documented in
+.I bootpd (8)
+.IP •
+.CW lib/virgild
+has become
+.CW ip/virgild
+(see
+.I virgild (8))
+.IP •
+.CW lib/chatsrv ,
+.CW lib/rdbgsrv
+and
+.CW cpuslave
+have moved to
+.CW auxi
+(ie,
+.CW /dis/auxi
+and
+.CW /appl/cmd/auxi)
+.IP •
+.CW csquery
+has become
+.CW ndb/csquery
+.NH 2
+New or newly-documented commands
+.IP •
+an authentication server (signer) can use
+.I keyfs (4)
+to store its keys securely in the encrypted file
+.CW /keydb/keys
+(instead of the unencrypted
+.CW /keydb/password ),
+and run
+.I keysrv (4)
+to offer secure change of password remotely.
+They are typically started, with other signing services, by
+.CW svc/auth
+described in
+.I svc (8).
+.IP •
+.CW /dis/auth
+and
+.CW /appl/cmd/auth
+contain commands related to authentication;
+they rely on
+.I keyfs (4)
+in most cases.
+The older ones that use
+.CW /keydb/passwd
+are still in
+.CW /dis/lib
+and
+.CW /appl/lib
+during the transition
+.IP •
+.I dns (8)
+has replaced the
+.CW lib/ipsrv
+implementation of
+.I srv (2);
+when used, it must be started before
+.CW ndb/cs .
+.I Srv (2)
+has reverted to being a hosted-only interface to the hosting system's native
+DNS resolver.
+It is automatically used by
+.I cs (8)
+if it cannot find
+.I dns (8),
+and
+.I dns (8)
+will also use it if available before consulting the DNS network.
+.IP •
+.I chgrp (1),
+.I cpuview (1),
+.I grid (1),
+.I 9660srv (4),
+.I cpuslave (4),
+.I dossrv (4),
+.I keyfs (4),
+.I keysrv (4),
+.I nsslave (4),
+.I palmsrv (4),
+.I registry (4),
+.I rioimport ,
+.I styxchat (1),
+.I styxlisten ,
+.I wmexport ,
+.I wmimport ,
+and
+.I uniq (1)
+are new
+.IP •
+the multiplayer games software previously in
+.CW /appl/games
+has been replaced by a related but significantly different system in
+.CW /appl/spree .
+(Also see
+.I spree (2)
+for supporting modules.)
+.IP •
+.I Registry (4)
+provides dynamic registration and location of services using sets of attributes/value pairs,
+through a name space.
+.I Registries (2)
+provides a convenient Limbo interface for registration and query.
+.NH 2
+Commands removed
+.IP •
+.CW lib/csget
+(see
+.I cs (8)
+for its replacement
+.CW csquery )
+.IP •
+the undocumented and obsolete commands
+.CW lib/isrv
+and
+.CW lib/istyxd
+have been removed, since either the
+.CW none
+authentication protocol, or the
+.CW -A
+option to
+.CW mount
+can be used if no authentication is needed
+.IP •
+.CW lib/srv
+has been replaced by
+.I svc (8)
+as mentioned above.
+.IP •
+.CW getenv
+and
+.CW setenv
+have been removed since the Shell provides alternatives
+.IP •
+.CW wm/license
+is no longer needed
+.NH 2
+New modules
+.LP
+There are library modules to support: registries and configuration files of attribute/value pairs;
+Internet address parsing and manipulation; management of windows and subwindows (used by
+.I wm (1)
+itself); timers; Styx; Styx servers; exception handling; memory
+and performance profiling; Freetype interface; parsing Palm databases; and navigating XML files (without reading them all into memory) and interpreting style sheets.
+.NH 1
+Styx
+.LP
+Styx was derived from the 9P protocol used by Plan 9 in 1995, with changes that reflected the requirements
+of the Inferno project of the time, mainly by removing features that were thought too closely tied to the Plan 9
+environment.
+Some 9P messages were removed, particularly those
+that incorporated details of the Plan 9 authentication methods;
+Styx moved authentication outside the file service protocol.
+Other changes eliminated file locking and append-only files.
+Some restrictions that 9P imposed were retained, however, such as limiting file names to 27 bytes.
+This last restriction is fine for synthetic network services, but
+has been troublesome when trying to access Unix and Windows systems, amongst others.
+.LP
+A recent revision of 9P adds support for much longer file names
+and takes the opportunity to improve other aspects of the protocol.
+It also removes details of authentication algorithms from the protocol.
+The Styx implementation now uses the new version of 9P as the default file service protocol.
+(It is possible that for interoperation with older Inferno systems the system will be able to
+interact with both old and new versions of Styx.)
+.NH 2
+Protocol changes
+.LP
+The messages
+.CW Tauth
+and
+.CW Tversion
+are new to Styx.
+.CW Tversion
+includes negotiation (at connection start) of the message size and protocol version;
+it also introduces a new session.
+.CW Tauth
+obtains access to a special authentication file if the server requires
+authentication within a Styx session.
+.CW Tclone
+has been replaced by a more elaborate form of
+.CW Twalk
+that allows zero to MAXWELEM (16) elements to be walked, perhaps to a new fid, in a single message,
+returning a sequence of qid values in
+.CW Rwalk .
+(A clone is simply a walk of a fid to a new fid with zero elements.)
+A walk of several elements can return partial results if the walk of the first element succeeds but
+subsequent ones fail.
+A partial walk leaves the state of the fids unchanged.
+.CW Ropen
+and
+.CW Rcreate
+return a suggested size for atomic I/O on the fid (0 means `not given').
+All strings are variable length, and consequently
+.CW Twstat
+and
+.CW Rstat
+data is variable length and formatted differently.
+Data returned from
+.CW Tread
+of a directory is similarly changed, because
+directory entries are not fixed length.
+.CW Tnop
+has gone.
+.LP
+Tags remain 16-bit integers, but fids and counts
+become 32-bit integers (mainly of interest to large systems),
+and qids have a different structure.
+Previously a qid was a pair of 32-bit integers, path and vers, where
+path had the top bit set for a directory.
+Now a qid is a triple: a 64-bit path, 32-bit vers, and 8-bit type.
+The type is defined to be the top 8 bits of the file's mode.
+The path does not have the top bit set for a directory, and indeed the
+path value is not interpreted by the protocol.
+There are now bits in the file mode for append-only and exclusive-use
+files (new for Inferno), and for authentication files (new for both Plan 9 and Inferno).
+The stat information includes the user name that last caused the file's mtime to be changed.
+All strings in the protocol are variable length: file names, attach names, user names, and error text.
+.LP
+The message format on the wire is significantly different.
+The message size is negotiated for a connection by
+.CW Tversion ,
+and messages can be large, allowing much more data to be sent in single
+.CW Twrite
+and
+.CW Rread
+messages.
+The header includes a 32-bit message size, making it easy to find message boundaries without
+parsing the contents.
+Strings are
+represented as a 16-bit size followed by the string's UTF-8 encoding (without zero byte).
+R-messages do not carry a copy of the fid from the T-message.
+Padding bytes have gone.
+The order of some fields has changed of course to match message parameter changes.
+.LP
+Authentication of the connection itself, and optionally
+establishing the keys for digesting and encryption,
+is done before the protocol starts, in both Inferno and Plan 9.
+Details will follow on the protocol for that, and Limbo interfaces.
+For now, it can be assumed that the old authentication messages can still be used,
+even after a more flexible protocol has been implemented.
+.CW Tauth
+can be used to authenticate particular accesses within such a session, but
+implies trust by the server that the client system will not cheat its users.
+(That trust is typically established by the connection level authentication which is needed
+anyway for link encryption, and thus for single-user clients further authentication
+seems extraneous in most cases.)
+Most Inferno services that run as file servers within a system (eg,
+.CW 9660srv )
+will, like Plan 9's, reply to
+.CW Tauth
+with an
+.CW Rerror
+stating ``authentication not required''.
+Access to them when exported is typically controlled as now by verifying the incoming connection.
+.NH 2
+Limbo interface changes
+.LP
+Because Limbo's interface to file service via
+.CW Sys
+and other modules uses Limbo
+.CW string
+for names, and that is inherently
+variable length, there are no interface changes required for that aspect of the protocol change,
+and consequently no source changes
+(in contrast to the introduction of 9P2000 in C implementations).
+Similarly the Inferno directory reading interfaces remain unchanged.
+.LP
+The `directory mode' bit previously called
+.CW CHDIR
+is now called
+.CW DMDIR .
+It is used
+.I only
+in
+.CW Dir.mode .
+.CW CHDIR
+is no longer defined, partly because it was used both
+in
+.CW Dir.mode
+and
+.CW Qid.path ,
+and the latter instances must change (discussed below).
+There are bits (new to Inferno) for
+.CW DMAPPEND
+(append-only file),
+.CW DMEXCL
+(exclusive-use file),
+and
+.CW DMAUTH
+(authentication file).
+The protocol can return the user name of the user that caused
+.CW mtime
+to be changed on a file; that is now available as
+.CW Dir.muid .
+.LP
+The structure of
+.CW Qid
+has changed.
+Previously a Qid had a 32-bit
+.CW path
+and a 32-bit version number,
+.CW vers .
+The top bit
+.CW CHDIR ) (
+of
+.CW path
+was set iff the Qid was that of a directory.
+The
+.CW path
+is now 64 bits (which is
+.CW big
+in Limbo and
+.CW vlong
+in the kernel), and there is no longer the convention that the top bit of
+.CW path
+must be 1 for a directory.
+Instead, there is a new, separate
+.CW type
+field (called
+.CW qtype
+in Limbo)
+that has the value of the top 8 bits of the file's mode.
+Each bit \f5DM\fIx\f1 in
+.CW Dir.mode ,
+has got a corresponding bit \f5QT\fIx\f1
+in
+.CW Qid.qtype :
+.CW QTDIR ,
+.CW QTAPPEND ,
+.CW QTEXCL
+and
+.CW QTAUTH .
+The bit
+.CW QTDIR
+.I must
+be set in the
+.CW Qid.qtype
+for a directory, and only then.
+There is an extra constant
+.CW QTFILE
+that is defined to be zero, and is used for clarity when neither
+.CW QTDIR
+nor
+.CW QTAUTH
+is set.
+.LP
+In Styx file servers, changes are required to reflect the slightly different set of message types
+and a few new parameters, but the main changes are:
+handling zero or more name elements at once in
+.CW Twalk
+and
+.CW Rwalk ;
+changing
+.CW CHDIR
+to
+.CW DMDIR
+in
+.CW Dir.mode
+(easy);
+the use of the new
+.CW Qid.qtype
+field
+and
+.CW QTDIR
+instead of
+.CW CHDIR
+in
+.CW Qid.path
+(a little more effort);
+and (typically) the insertion of casts to force
+.CW Qid.path
+to
+.CW int
+and thus ensure the use of 32-bit operations except where 64-bit paths really are needed
+(hardly ever in synthetic file servers).
+The new modules for use by file servers are discussed in the next section.
+.LP
+The revised definition of
+.CW Twstat
+in
+.I stat (5),
+and thus
+.CW sys->wstat ,
+provides for ``don't care'' values in
+.CW Dir
+that are tedious to provide directly; a new adt value
+.CW Sys->nulldir
+provides the right initial value for a
+.CW Dir
+which is then changed as needed for
+.CW wstat .
+.SH
+.I "Examples"
+.LP
+Create a directory:
+.P1
+ \fIold:\f5
+fd := sys->create(name, Sys->OREAD, Sys->CHDIR | 8r777);
+
+ \fInew:\f5
+fd := sys->create(name, Sys->OREAD, Sys->DMDIR | 8r777); # not CHDIR
+.P2
+.LP
+Make Qids
+for a file and a directory:
+.P1
+ \fIold:\f5
+Qdir, Qdata: con iota;
+qd := Sys->Qid(Sys->CHDIR | Qdir, 0);
+qf := Sys->Qid(Qdata, 0);
+
+ \fInew:\f5
+Qdir, Qdata: con iota;
+qd := Sys->Qid(big Qdir, 0, Sys->QTDIR);
+qf := Sys->Qid(big Qdata, 0, Sys->QTFILE);
+.P2
+.LP
+Test if a file is a directory:
+.P1
+ \fIold:\f5
+isdir(d: Sys->Dir): int
+{
+ return (d.mode & Sys->CHDIR) != 0;
+\fIOR:\f5
+ return (d.qid.path & Sys->CHDIR) != 0;
+}
+
+ \fInew:\f5
+isdir(d: Sys->Dir): int
+{
+ return (d.mode & Sys->DMDIR) != 0;
+\fIOR:\f5
+ return (d.qid.qtype & Sys->QTDIR) != 0;
+}
+.P2
+.LP
+If one wishes to have values
+.CW big
+only when required, one can write:
+.P1
+case int dir.qid.path {
+Qdir =>
+ ...
+Qdata =>
+ ...
+Qctl =>
+ ...
+}
+.P2
+Of course with the Dis change mentioned above,
+.CW case
+can now be applied to
+.CW big
+values, so it is no longer necessary to add the cast (as it once was).
+Even so, 32-bit operations are faster when they suffice.
+.NH 2
+Styx protocol in Limbo: Styx and Styxservers
+.LP
+A new module
+.CW Styx ,
+defined by
+.CW styx.m ,
+provides access to the Styx protocol messages, as variants of pick adts
+.CW Tmsg
+and
+.CW Rmsg .
+(There was an old, undocumented
+.CW Styx
+module but this new interface is completely different.)
+It is used by several file servers, such as
+.CW dossrv ,
+.CW cdfs ,
+and the new
+.CW logfs .
+See the attached manual page.
+There are several implementations with the same signature, covering different
+combinations of old and new Inferno and old and new protocols, through
+the same interface.
+There are slight differences in the application code for old and new
+systems because of the changed
+type and structure of
+.CW Qid .
+The versions that talk the old protocol need to store some internal state,
+and are intended only to meet compatibility requirements during the transition.
+.LP
+Many file service applications, however, serve a simple name space,
+requiring more than can be done with
+.CW file2chan ,
+but wishing some help in handling the protocol details.
+Two new modules
+.CW Styxservers
+and
+.CW Nametree
+are provided to make such applications easier to write.
+They are closely related and thus both modules are defined by
+.CW styxservers.m .
+.LP
+.CW Styxservers
+provides help in handling fids and interpreting the Styx requests for navigating a
+name space, and provides a reasonable set of default actions,
+allowing the application to focus on implementing
+read and write access to the files in the name space.
+It uses
+.CW Styx
+to talk to the Styx client on a connection.
+It interacts with the application through a channel interface and
+the
+.CW Navigator
+adt to navigate an abstract
+representation of the application's name space.
+The module can be used on its own, with the application doing the work
+of replying to those queries itself, or it can get extra help in the common cases from
+.CW Nametree .
+.CW Nametree
+provides a
+.CW Tree
+adt and operations for the application to build an abstract representation of a name space
+and maintain it dynamically quite simply, and it exports the channel interface used by
+.CW Styxservers
+for navigation, thus connecting the two, but leaving the application in complete
+control of the name space contents viewed by Styx.
+See the manual pages
+.I styxservers (2)
+and
+.I styxservers-nametree (2),
+attached.
+The latter includes a short working example of combining the two modules.
+.LP
+The previous release of the system had a module
+.CW Styxlib
+that combined the functions of
+.CW Styx
+and
+.CW Styxservers .
+It remains for a time for transition, but newer applications should use either
+.CW Styx
+or
+.CW Styxservers .
+.LP
+A new command
+.I styxchat (8)
+exchanges Styx messages with a server, reading a textual representation of T-messages
+on standard input.
+It can be helpful when testing a Styx server implementation.
+(It was originally developed to test the
+.CW Styx
+module implementations in several configurations.)
+See the attached manual page for details.
+It also supports an option that allows it to act as a server,
+printing T-messages as they are received from clients, and
+reading R-messages in a textual form from standard input for replies.
+.NH 2
+Device driver changes
+.LP
+Most of the differences for most drivers are relatively minor
+(in
+.CW diff
+terms).
+.LP
+Throughout the hosted and emulated kernels:
+.IP \(bu
+.CW Qid
+now is the structure:
+.RS
+.P1
+struct Qid {
+ vlong path;
+ ulong vers;
+ uchar type;
+};
+.P2
+The
+.CW type
+field has values
+.CW QTDIR ,
+.CW QTFILE ,
+.CW QTAPPEND ,
+etc.
+The test previously written
+.P1
+if(qid.path & CHDIR)
+.P2
+is now written
+.P1
+if(qid.type & QTDIR)
+.P2
+Because of that change, the various
+.CW switch
+statements in the drivers that previously read
+.P1
+switch(c->qid.path){
+.P2
+or
+.P1
+switch(c->qid.path & ~Sys->CHDIR){
+.P2
+now read
+.P1
+switch((ulong)c->qid.path){
+.P2
+to keep operations to 32 bits (except where otherwise required).
+.RE
+.IP \(bu
+The first entry of a driver's
+.CW Dirtab
+.I must
+be an entry for
+\f5"."\fP,
+if the driver uses
+.CW devgen
+to help implement
+.I walk ,
+.I stat ,
+.I devdirread
+or
+.I open
+operations.
+.IP \(bu
+Offsets passed to the driver's
+.I read
+and
+.I write
+entry points are
+64-bit
+.CW vlong ,
+not 32-bit
+.CW ulong .
+.IP \(bu
+The
+.I stat
+entry point has an extra buffer size parameter:
+.RS
+.P1
+int \fIxyz\f5stat(Chan *c, uchar *dp, int n)
+.P2
+It also returns an integer: the size of the result.
+.CW Devstat
+accepts the extra parameter and returns an appropriate result:
+.P1
+static int
+\fIxyz\f5stat(Chan *c, uchar *dp, int n)
+{
+ return devstat(c, dp, n, rtcdir, nelem(\fIxyz\f5dir), devgen);
+}
+.P2
+.RE
+.IP \(bu
+The biggest change is to
+.I walk .
+It has the signature:
+.RS
+.P1
+Walkqid *\fIxyz\f5walk(Chan *c, Chan *nc, char **names, int nname);
+.P2
+and it allows zero or more elements to be walked in a single call,
+returning its result in a newly-allocated
+.CW Walkqid
+structure:
+.P1
+struct Walkqid {
+ Chan* clone;
+ int nqid;
+ Qid qid[1];
+};
+.P2
+Note that the array
+.CW Walkqid.qid
+must actually hold up to
+.I nname
+Qids, and thus is allocated as follows:
+.P1
+wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid));
+.P2
+The driver must take care that the space is reclaimed if
+.CW error
+is called before its
+.I walk
+function returns, by using
+.CW waserror
+as required.
+Fortunately,
+.CW devwalk
+looks after the details of
+.I walk
+and
+.CW walkqid
+for most drivers:
+.P1
+static Walkqid*
+\fIxyz\f5walk(Chan* c, Chan *nc, char** name, int nname)
+{
+ return devwalk(c, nc, name, nname, \fIxyz\f5dir,
+ nelem(\fIxyz\f5dir), devgen);
+}
+.P2
+.RE
+.IP \(bu
+The
+.I clone
+entry point has gone, since cloning is seen by a driver as a particular form of call to its
+.I walk
+entry,
+where the parameter values satisfy:
+.RS
+.P1
+c != nc && nwname == 0
+.P2
+One difference is that a node can be cloned and walked in a single operation,
+in other words
+.CW nwname
+can be non-zero,
+and the incoming
+.CW nc
+is often nil and a new
+.CW Chan
+must be allocated.
+Note that if the driver found it adequate to call
+.CW devclone
+previously, then
+the new
+.CW devwalk
+will
+generally look after it as well.
+.CW Devclone
+remains for use as a utility function for the few drivers that need to
+clone a channel themselves,
+in their
+.I walk
+operations or elsewhere.
+.RE
+.IP \(bu
+The
+.I detach
+entry has been renamed
+.I shutdown
+(it was never the opposite of
+.I attach ).
+The stub
+.CW devshutdown
+can be used by devices that do not need it.
+.LP
+For drivers that serve a simple name space using the functions of
+.CW dev.c
+(described in
+.I devattach (10.2)),
+only a handful of simple changes are required.
+Most are pointed out by the compilers as type clashes.
+The main exception is the need for a
+.CW Dirtab
+to have its first entry be an entry for \f5"."\fP if the
+.CW Dirtab
+will be passed to
+.CW devgen
+via
+.CW devwalk ,
+.CW devstat
+and
+.CW devdirread .
+.NH 1
+Sys module changes
+.LP
+.NH 2
+Sys: name change(s)
+.LP
+The name
+.CW ERRLEN
+has become
+.CW ERRMAX
+(since it is the limit to any error string, not its necessary length).
+.CW NAMELEN
+has been removed,
+to allow each instance to be found (by compilation) and either removed
+(where it was simply limiting the length of a file name), or replaced by
+.CW NAMEMAX
+where it was used as a buffer size to read in names such as
+.CW /dev/sysname
+or
+.CW /dev/user .
+.NH 2
+Sys: file sizes
+.LP
+The Styx protocol has always supported 64-bit file sizes and file offsets.
+The Inferno interface has not.
+.CW Sys
+has changed so that length and offset values become
+.CW big ,
+specifically:
+file size
+.CW Dir.length ,
+the offset parameter to
+.CW seek ,
+and
+.CW seek 's
+result.
+.LP
+These and the Qid changes account for quite a few changes in
+our own source tree.
+Typically, applications did things like this:
+.P1
+ \fIold:\f5
+buf := array[d.length] of byte;
+
+sys->seek(fd, 0, Sys->SEEKSTART);
+off := sys->seek(fd, 0, Sys->SEEKRELA); rec := off + HDRLEN;
+for(offset := 0; offset < d.length; offset += RECSIZE){
+ sys->seek(fd, offset, Sys->SEEKSTART);
+ ...
+}
+.P2
+The compiler now objects in each case because
+.CW big
+values are now appearing where
+.CW int
+is required, or conversely.
+In some cases it is obvious that adding a cast is correct;
+in others it is worth considering whether the calculation should indeed
+be
+.CW big
+because file sizes for instance can in practice exceed the range of a
+signed integer without too much trouble today, especially when the `file'
+is a storage device.
+The case that some people like and some dislike is:
+.P1
+if(sys->seek(fd, big offset, Sys->SEEKSTART) < big 0) ...
+.P2
+where the
+.CW "big 0"
+is needed because
+.CW sys->seek
+is
+.CW big ,
+and there are no `usual arithmetic conversions' as in C.
+(Given the tangle that several languages have made of such conversions, perhaps
+being strict is correct.)
+.NH 2
+Sys: export
+.LP
+.CW Sys->export
+now has the signature:
+.P1
+export: fn(c: ref Sys->FD, dir: string, flag: int): int;
+.P2
+allowing a directory
+.I dir
+other than \f5"/"\f1
+to be exported.
+It replaces the
+.CW exportdir
+function of (later) Third Edition.
+.NH 2
+Sys: Styx support
+.LP
+The revision of Styx has caused three calls to be added:
+.P1
+fauth: fn(fd: ref Sys->FD, aname: string): ref Sys->FD;
+fversion: fn(fd: ref Sys->FD, msize: int, version: string): (int, string);
+iounit: fn(fd: ref Sys->FD): int;
+.P2
+.CW Fversion
+initialises a Styx session on connection
+.I fd ,
+sending the message size
+.I msize
+and protocol version string
+.I version ;
+it returns a tuple giving the message size and version returned by the Styx server.
+It is rarely called directly; the
+.CW mount
+operation does it automatically on an uninitialised connection.
+.LP
+.CW Fauth
+sends a Styx
+.CW Tauth
+message on connection
+.I fd ,
+and if successful, returns a file descriptor that
+refers to an authentication file provided by the file server,
+which may be read and written by
+.CW Sys->read
+and
+.CW Sys->write
+to implement the authentication protocol(s) supported by the server.
+.CW Fauth
+is needed only when the server requires authentication.
+.LP
+.CW Iounit
+returns the `atomic IO unit' suggested for the file
+.I fd
+by its file server when it was opened.
+.NH 2
+Sys: mount
+.LP
+The
+.CW mount
+system call has acquired a second file descriptor parameter:
+.P1
+mount: fn(fd: ref Sys->FD, afd: ref Sys->FD, on: string,
+ flags: int, spec: string): int;
+.P2
+.I Afd
+is nil if the file server is known not to require authentication within a Styx session.
+(The connection might itself have been authenticated previously, for instance,
+and most file servers such as
+.CW dossrv ,
+.CW ftpfs
+and
+.CW dbfs
+are invoked to provide services to an already-authenticated user, and therefore
+do not require authentication within a session.)
+If the server does require authentication,
+.I afd
+refers to a file descriptor returned by a previous
+.CW fauth
+on connection
+.I fd ,
+on which an authentication protocol has subsequently been executed as required by the file server connected to
+.I fd .
+.NH 2
+Sys: other new system calls
+.LP
+There are two more new system calls:
+.P1
+fd2path: fn(fd: ref Sys->FD): string;
+werrstr: fn(s: string): int;
+.P2
+.CW Fd2path
+returns the path name under which the file descriptor
+.I fd
+was originally opened (if known).
+One result is that
+.I workdir (2)
+produces reasonable results for the name of the current directory
+in the presence of mounts and binds.
+.LP
+.CW Werrstr
+sets the per-process system error string to
+.I s ,
+to allow a Limbo function to save and restore an error string over
+other system calls, to present a similar interface
+as the system calls on errors, or to annotate the error from a system call
+for its own caller.
+.NH 2
+Sys: directory reading
+.LP
+The
+.I sys-dirread (2)
+system call's signature has changed:
+.P1
+dirread: fn(fd: ref Sys->FD): (int, array of Sys->Dir);
+.P2
+Previously it accepted an array of
+.CW Dir
+to fill and returned a count;
+now it returns a tuple containing the count and the array of values read.
+The change was needed because the representation of directory entries
+is now variable length, and it is difficult to limit the number returned
+(it is possible, but all the methods have disadvantages).
+.CW Dirread
+still reads a directory incrementally, requesting a block of directory entries
+of reasonable size from the file server, and unpacking them into the returned array.
+Use
+.I readdir (2)
+to read whole directories at once.
+.NH 1
+Bufio
+.LP
+There are several changes to
+.CW Bufio :
+.P1
+Iobuf: adt {
+ ...
+ seek: fn(b: self ref Iobuf, n: big, where: int): big;
+ offset: fn(b: self ref Iobuf): big;
+};
+# flush: fn(); # deleted
+.P2
+The module-level function
+.CW Bufio->flush
+has been removed
+(\fInot\fP
+.CW Iobuf.flush ),
+to allow concurrent use of a single
+.CW Bufio
+instance; applications must
+.CW close
+or
+.CW flush
+each output file explicitly.
+.LP
+As a result of the change to 64-bit offsets for
+.CW Sys->seek ,
+.CW Iobuf.seek
+also accepts and returns
+.CW big
+offsets.
+.CW Iobuf.offset
+is new, and returns the current file offset in bytes, taking account of any buffering.
+.LP
+.CW Iobuf.flush
+has been extended to flush any data buffered on input files.
+.NH 1
+Draw
+.LP
+The graphics model represented by the
+.I draw (3)
+device and the
+.CW Draw
+module is significantly different, including support for a range of pixel formats,
+and compositing in the drawing operations.
+Most source code that uses Images
+directly will require some changes, but the scope of them is limited: needing only extra
+or different parameter values to individual operations, not radical restructuring.
+The following changes affect most non-Tk graphics application code:
+.IP \(bu
+Pixels in an
+.CW Image
+can now be more than 8 bits and have a more flexible structure
+(eg, several colour channels, and an optional alpha channel, of up to 8 bits each).
+To support that, the old
+.CW ldepth
+field has gone, replaced by a channel descriptor
+.CW chans
+of type
+.CW Chans ,
+which describes the pixel structure, and an integer
+.CW depth
+field, which gives the total pixel size (depth) in bits.
+.IP \(bu
+The colour parameters are now 32-bit RGBA values
+(red, green, blue and alpha components, 8-bit each, and big-endian
+only when an
+.CW int ).
+.IP \(bu
+The graphics subsystem supports Porter-Duff compositing,
+combining a destination image with a source image (within an optional matte)
+according to a compositing operator.
+The interpretation of the old `mask' Image parameter to
+.CW draw
+and
+.CW gendraw
+has changed.
+Previously it provided a simple binary mask;
+it now provides a `matte', and its
+alpha channel shapes the source image and adds partial transparencies.
+If the matte parameter is nil, the source image is used unmodified.
+If it lacks an alpha channel, one is computed from the matte image colour channels.
+The drawing operations
+.CW draw ,
+.CW gendraw ,
+.CW line ,
+.CW text ,
+and so on,
+have all got variants
+.CW drawop ,
+.CW gendrawop ,
+.CW lineop ,
+.CW textop ,
+and so on,
+each taking an extra final parameter that specifies a Porter-Duff
+compositing operator from a set predefined by
+.CW Draw :
+.CW SoverD ,
+.CW SinD ,
+.CW DatopS ,
+and so on.
+In each case,
+.CW S
+refers to the source image (within a matte, if provided), and
+.CW D
+refers to the destination image.
+Most of them are useful only when either or both source or destination images have got
+alpha channels (or a matte is used to shape the source).
+The old function names without the
+.CW op
+suffix use the most common compositing operation
+.CW Draw->SoverD ,
+drawing the source image over the destination,
+taking account of the shaping of the source and destination images by their alpha channels,
+with the source further shaped by the optional matte.
+Thus
+.CW Image.draw
+continues to do the `obvious' thing.
+.IP \(bu
+There are new colour map conversion functions.
+.LP
+The
+.CW Chans
+adt is the following:
+.P1
+Chans: adt
+{
+ # interpret standard channel string
+ mk: fn(s: string): Chans;
+ # standard printable form
+ text: fn(c: self Chans): string;
+ # equality
+ eq: fn(c: self Chans, d: Chans): int;
+ # bits per pixel
+ depth: fn(c: self Chans): int;
+};
+.P2
+Values are created by
+.CW Chans.mk ,
+which accepts a string that is a sequence of channel descriptors,
+each being a letter representing a channel type followed by an integer giving the channel's size (depth, width) in bits.
+The letters include:
+.CW r ,
+.CW g
+and
+.CW b
+for red, green and blue;
+.CW a
+for alpha;
+.CW k
+(!) for greyscale; and
+.CW x
+for padding (``unspecified'', ``don't care'').
+Thus
+.CW Chans.mk("r8g8b8a8")
+produces a descriptor for a 32-bit pixel with 8-bit colour and alpha components.
+The same descriptor is used in the revised
+.I image (6)
+format, although the older image file format with ldepth only is still recognised.
+Given a Chans value
+.I c ,
+\fIc\fP\f5.text()\fP returns such a descriptor for it as a string.
+.LP
+When
+.CW newimage
+previously was called with a specific value for
+.CW ldepth ,
+an appropriate
+.CW Chans
+value must replace it.
+A few common variants are defined as constants of type
+.CW Chans
+in
+.CW Draw .
+(We extended the Limbo compiler last year to support the use of
+.CW con
+with adt and tuple constants with this use in mind.)
+For example, the value
+.CW Draw->CMAP8
+is the descriptor for the 8-bit deep
+.I rgbv
+colour-mapped Image format previously used by Inferno.
+The list of predefined channels includes:
+.TS
+center;
+cfI cfI cfI cfI
+n lf(CW) n lw(3i) .
+Old ldepth Name Bit depth Description
+0 GREY1 1 single 1-bit deep greyscale channel
+1 GREY2 2 single 2-bit deep greyscale
+2 GREY4 4 single 4-bit deep greyscale
+\- GREY8 8 single 8-bit deep greyscale
+3 CMAP8 8 single 8-bit deep \fIrgbv\f1 colour-mapped channel
+\- RGB15 15 three channels RGB: r5g5b5
+\- RGB16 16 three channels RGB: r5g6b5
+\- RGB24 24 three channels RGB: r8g8b8
+\- RGBA32 32 four channels: RGB and alpha: r8g8b8a8
+.TE
+.LP
+The use of
+.CW Chans
+instead of
+.CW ldepth
+means that calls to
+.CW Display.newimage
+must be changed.
+For instance:
+.P1
+\fI(old)\f5
+buffer := display.newimage(r.inset(3), t.image.ldepth, 0, Draw->White);
+.P2
+becomes
+.P1
+\fI(new)\f5
+buffer := display.newimage(r.inset(3), t.image.chans, 0, Draw->White);
+.P2
+There is an obvious difference: the
+use of
+.CW t.image.chans
+instead of
+.CW t.image.ldepth
+to create a buffer Image with the same pixel structure as
+.CW t .
+There is, however, another difference.
+The final colour parameter to
+.CW newimage
+is also different in structure: in the new graphics model, it is a 32-bit integer value giving RGBA
+components,
+not a colour map index, and the name
+.CW Draw->White
+has the value
+.CW 16rFFFFFFFF
+not
+.CW 0 .
+Because a symbolic name was used, however, the source need not change.
+As another example,
+.CW Draw->Palegreyblue
+is
+.CW "int 16r4993DDFF" .
+Note the final
+.CW FF
+for the alpha component (creating a fully opaque colour).
+When the top bit is set, the
+.CW int
+cast shown here is needed to force the otherwise
+.CW big
+value to 32 bits.
+.LP
+The values of colour components are now uniformly expressed as
+intensity, so that a pixel with all zero colour components is black and
+one with all colour components at maximum (all ones, full intensity)
+is white.
+The
+.I rgbv
+map has therefore been reversed.
+Given a map index,
+.CW Display.cmap2rgba
+returns the 32-bit RGBA format used as a parameter in other calls.
+All colour components are
+.I linear
+values, as required for compositing to work properly;
+gamma correction is done as required by the display subsystem.
+.LP
+The colour components of a pixel with an alpha component are always
+.I pre-multiplied
+by the alpha value, following Porter and Duff, as further justified by Alvy Ray Smith and Jim Blinn.
+``Thus a 50% red is
+.CW 16r7F00007F
+not
+.CW 16rFF00007F .''
+The function
+.CW Draw->setalpha
+does the computation.
+.LP
+Because of the changes to colours and the replacement of simple masks by mattes, the Images
+.CW Display.ones
+and
+.CW Display.zeros
+are no longer defined.
+Instead, when they were intended to represent colours, the new Images
+.CW Display.black
+and
+.CW Display.white
+provide the obvious colours.
+When
+.CW ones
+and
+.CW zeros
+were used as masks, the new predefined Images
+.CW Display.opaque
+and
+.CW Display.transparent
+are used instead as constant mattes, with alpha channels (fully opaque and fully transparent, respectively).
+As noted above, where
+.CW Display.ones
+was used as a mask parameter in drawing operations, one can
+simply specify a nil Image as a matte (`no matte') instead.
+(That has been allowed for quite some time and is in use but might not be widely known.)
+.LP
+For example, Charon allocated a mask using:
+.P1
+dpicmask = display.newimage(pic.r, 0, 0, Draw->White);
+.P2
+which becomes
+.P1
+dpicmask = display.newimage(pic.r, Draw->GREY1, 0, Draw->Opaque);
+.P2
+where
+.CW GREY1
+is a constant value of the
+.CW Chans
+adt type, predefined by Draw, for Images that have a single 1-bit deep grey channel (ie, a bitmap).
+(Note that to form a fully-opaque matte,
+.CW Draw->Opaque
+was used for clarity, not
+.CW Draw->White ;
+.CW Draw->Transparent
+could also be used, as the basis for building a matte with transparency.)
+.LP
+A small if obscure change is that
+.CW Display.newwindow
+has a new parameter:
+.P1
+newwindow: fn(screen: self ref Screen, r: Rect,
+ backing: int, color: int): ref Image;
+.P2
+The
+.I backing
+parameter should usually be
+.CW Draw->Refbackup ,
+except for windows allocated on an image that already has got backing store
+assigned, for instance because it is an image on a screen on an existing window image, in which case it should be
+.CW Draw->Refnone ,
+because the parent window already provides the backing.
+.LP
+As a small but helpful change, the adt
+.CW Draw->Pointer
+has a new element
+.CW msec
+that reports a
+relative time stamp in milliseconds.
+.LP
+The
+.CW Draw->Context
+content is significantly different, for the benefit of the new
+window system implementation.
+.NH 1
+Tk module
+.LP
+There is a new function in
+.CW Tk :
+.P1
+quote: fn(s: string): string;
+.P2
+.CW Quote
+returns string
+.I s
+quoted according to Tk's `\f5{}\f1' quoting conventions.
+It replaces
+.CW Wmlib->tkquote .
+.LP
+There is a new widget type:
+.I panel (9).
+A panel instance can be packed and otherwise manipulated in the same way as any other Tk widget.
+An image is associated with it by calling
+.CW Tk->putimage
+defined in
+.I tk (2).
+The associated images can be drawn on directly by the application, using all the operations provided by
+.CW Draw .
+The coordinates of the changed rectangle must be given to Tk
+using the
+.CW panel
+widget command
+.CW dirty ;
+that part of the image will be redrawn if necessary at the next Tk
+.CW update .
+A panel has no default bindings.
+See
+.I panel (9)
+for details.
+.LP
+For example,
+.CW wm/coffee
+now uses the following:
+.P1
+r := Rect((0, 0), (400, 300));
+buffer := display.newimage(r, t.image.chans, 0, Draw->Black);
+tk->cmd(t, "panel .f.p -bd 3 -relief flat");
+tk->cmd(t, "pack .f.p -fill both -expand 1");
+tk->cmd(t, "update");
+org := buffer.r.min;
+tk->putimage(t, ".f.p", buffer, nil);
+.P2
+When it has updated the
+.CW buffer ,
+it tells Tk:
+.P1
+tk->cmd(t, ".f.p dirty; update");
+.P2
+In this case the whole image is marked dirty, but
+.CW dirty
+can be given an optional rectangle parameter to restrict redrawing.
+.LP
+.CW Tk->putimage
+and
+.CW Tk->getimage
+replace
+.CW imageput
+and
+.CW imageget .
+.NH 1
+Selectfile, Tabs and Dialog
+.LP
+The functions
+.CW filename ,
+.CW mktabs
+(and
+.CW tabsctl ),
+.CW dialog
+and
+.CW getstring
+have been moved to separate new modules, to allow those aspects of the
+user interface to be changed by replacing the implementations,
+and to allow standard modules to be provided for picking colours (for instance).
+.CW Selectfile
+acquires
+.CW filename ,
+.CW Tabs
+acquires the `tabs' Tk pseudo-widget, and
+.CW Dialog
+acquires
+.CW dialog ,
+which is renamed
+.CW prompt ,
+and
+.CW getstring .
+In cases where the functions took a
+.CW Tk->Toplevel
+as a parameter to specify a
+.CW parent
+window,
+they now take a
+.CW Draw->Context
+and (parent)
+.CW Image
+parameter;
+given a Toplevel
+.CW t ,
+use
+.CW t.image .
+See
+.I dialog (2),
+.I selectfile (2)
+and
+.I tabs (2).
+.TL
+Appendix A: Tk client conversion
+.LP
+.I Wm (1)
+applications now have to feed their own pointer and keyboard
+input to Tk. The window manager is now kept informed about the placement
+of windows.
+.LP
+A Tk toplevel now holds a window manager context:
+.P1
+Wmcontext: adt
+{
+ kbd: chan of int; # incoming characters from keyboard
+ ptr: chan of ref Pointer; # incoming stream of mouse positions
+ ctl: chan of string; # commands from wm to application
+ wctl: chan of string; # commands from application to wm
+ images: chan of ref Image; # exchange of images
+ connfd: ref Sys->FD; # connection control
+ ctxt: ref Context;
+};
+.P2
+It contains some channels on which the window manager
+sends information to the application, and a file
+descriptor that can be used to write requests to the window
+manager.
+The channels used directly by the application are:
+.RS
+.IP \f(CWkbd\fP
+characters typed by the user (pass them to
+.CW Tk->pointer )
+.IP \f(CWptr\fP
+pointer events (pass them to
+.CW Tk->keyboard )
+.IP \f(CWctl\fP
+application control requests.
+Passing these to
+.CW Tkclient->wmctl
+will do the default action.
+Requests starting with an exclamation mark
+.CW ! ) (
+can cause the application's image to change.
+.RE
+.LP
+The toplevel also holds a channel
+.CW wreq
+on which it sends application
+control requests; these have the same form as those
+sent on
+.CW Wmcontext.ctl ,
+and can be forwarded to
+.CW Tkclient->wmctl
+in the same way.
+.LP
+Control requests currently understood by
+.I wm (1)
+are:
+.RS
+.IP "\f(CW!reshape \fItag\fP \fIreqid\fP \fIminx\fP \fIminy\fP \fImaxx\fP \fImaxy\fP [\fIhow\fP]\fR
+.br
+Reshape the window referenced by
+.I tag ,
+creating a new image if
+.I tag
+did not previously exist.
+.I Reqid
+is ignored.
+.I How
+can be one of:
+.RS
+.IP \f(CWplace\fP 15
+.I Wm
+attempts to find a suitable patch of screen real estate on which to place
+the window; the size of the given rectangle
+is taken to be the minimum size for that window.
+.IP \f(CWexact\fP
+Reshape to the exact rectangle requested.
+This is the default if
+.I how
+is not given.
+.IP \f(CWonscreen\fP
+The given rectangle is adjusted so that it is no bigger than the available
+screen space, and is entirely on screen.
+.RE
+.IP "\f(CWdelete \fItag\fP\fR
+.br
+Delete the image associated with
+.I tag .
+.IP "\f(CWraise\fP
+.br
+Raise the window
+.IP "\f(CWlower\fP
+.br
+Lower the window
+.IP "\f(CW!move \fItag\fP \fIreqid\fP \fIstartx\fP \fIstarty\fP\fR
+.br
+Request the user to move the window to a new place.
+.I Startx
+and
+.I starty
+are the coordinates of the pointer when the request was initiated.
+.IP "\f(CW!size \fItag\fP\fR
+.br
+Request the user to resize the window.
+.RE
+.LP
+To convert a typical Tk application, do the following.
+.IP 1.
+Use an editor to make the following changes:
+.RS
+.TS
+cfI cfI
+lf(CW) lf(CW) .
+Old New
+Wmlib Tkclient
+wmlib tkclient
+tkclient->titlebar tkclient->toplevel
+tkclient->titlectl tkclient->wmctl
+tkclient->taskbar tkclient->settitle
+tk->imageput tk->putimage
+tk->imageget tk->getimage
+.TE
+.RE
+.IP 2.
+Insert the following code at the top of the central
+.CW alt
+statement.
+The names
+.CW wmctl ' `
+and
+.CW top ` '
+will need changing to the appropriate variables in the program:
+.RS
+.P1
+s := <-top.ctxt.kbd =>
+ tk->keyboard(top, s);
+s := <-top.ctxt.ptr =>
+ tk->pointer(top, *s);
+s := <-top.ctxt.ctl or
+s = <-top.wreq or
+s = <-wmctl =>
+ tkclient->wmctl(top, s);
+.P2
+.RE
+.IP 3.
+Add the following just after the Tk configuration code and
+before the main processing starts:
+.RS
+.P1
+tkclient->onscreen(top, nil);
+tkclient->startinput(top, "kbd"::"ptr"::nil);
+.P2
+This is possibly the easiest part to forget.
+.RE
+.LP
+Be careful of cases where a blocking function is called
+from the main loop that relies on keyboard/mouse input.
+The easiest solution can be to spawn a thread to handle the
+keyboard and mouse independently.
binary files /dev/null b/doc/changes.pdf differ
--- /dev/null
+++ b/doc/compiler.ms
@@ -1,0 +1,1174 @@
+.TL
+Plan 9 C Compilers \(dg
+.AU
+.I "Ken Thompson"
+.AI
+ken@plan9.bell-labs.com
+.AB
+.FS
+\l'1i'
+.br
+\(dg Originally appeared, in a different form, in
+.I
+Proceedings of the Summer 1990 UKUUG Conference,
+.R
+pp. 41-51,
+London, 1990.
+This version first appeared in
+.I "Plan 9 Programmer's Manual, Volume 2 (Second Edition)" .
+The Plan 9 compiler suite forms the basis for the portable Inferno compiler suite,
+making this paper still relevant.
+.FE
+This paper describes the overall structure and function of the Plan 9 C compilers.
+A more detailed implementation document
+for any one of the compilers
+is yet to be written.
+.AE
+.NH
+Introduction
+.LP
+There are many compilers in the series.
+Eight of the compilers (MIPS 3000, SPARC, Intel 386, AMD64, Power PC, ARM, DEC Alpha, and Motorola 68020)
+are considered active and are used to compile
+current versions of Plan 9 or Inferno.
+Several others (Motorola 68000, Intel 960, AMD 29000) have had only limited use, such as
+to program peripherals or experimental devices.
+.NH
+Structure
+.LP
+The compiler is a single program that produces an
+object file.
+Combined in the compiler are the traditional
+roles of preprocessor, lexical analyzer, parser, code generator,
+local optimizer,
+and first half of the assembler.
+The object files are binary forms of assembly
+language,
+similar to what might be passed between
+the first and second passes of an assembler.
+.LP
+Object files and libraries
+are combined by a loader
+program to produce the executable binary.
+The loader combines the roles of second half
+of the assembler, global optimizer, and loader.
+The names of the compliers, loaders, and assemblers
+are as follows:
+.DS
+.ta 1.5i
+.de Ta
+\\$1 \f(CW\\$2\fP \f(CW\\$3\fP \f(CW\\$4\fP
+..
+.Ta SPARC kc kl ka
+.Ta PowerPC qc ql qa
+.Ta MIPS vc vl va
+.Ta Motorola\ 68000 1c 1l 1a
+.Ta Motorola\ 68020 2c 2l 2a
+.Ta ARM 5c 5l 5a
+.Ta AMD64 6c 6l 6a
+.Ta DEC\ Alpha 7c 7l 7a
+.Ta Intel\ 386 8c 8l 8a
+.Ta AMD\ 29000 9c 9l 9a
+.DE
+There is a further breakdown
+in the source of the compilers into
+object-independent and
+object-dependent
+parts.
+All of the object-independent parts
+are combined into source files in the
+directory
+.CW /sys/src/cmd/cc .
+The object-dependent parts are collected
+in a separate directory for each compiler,
+for example
+.CW /sys/src/cmd/vc .
+All of the code,
+both object-independent and
+object-dependent,
+is machine-independent
+and may be cross-compiled and executed on any
+of the architectures.
+.NH
+The Language
+.LP
+The compiler implements ANSI C with some
+restrictions and extensions
+[ANSI90].
+Most of the restrictions are due to
+personal preference, while
+most of the extensions were to help in
+the implementation of Plan 9.
+There are other departures from the standard,
+particularly in the libraries,
+that are beyond the scope of this
+paper.
+.NH 2
+Register, volatile, const
+.LP
+The keyword
+.CW register
+is recognized syntactically
+but is semantically ignored.
+Thus taking the address of a
+.CW register
+variable is not diagnosed.
+The keyword
+.CW volatile
+disables all optimizations, in particular registerization, of the corresponding variable.
+The keyword
+.CW const
+generates warnings (if warnings are enabled by the compiler's
+.CW -w
+option) of non-constant use of the variable,
+but does not affect the generated code.
+.NH 2
+The preprocessor
+.LP
+The C preprocessor is probably the
+biggest departure from the ANSI standard.
+.LP
+The preprocessor built into the Plan 9 compilers does not support
+.CW #if ,
+although it does handle
+.CW #ifdef
+and
+.CW #include .
+If it is necessary to be more standard,
+the source text can first be run through the separate ANSI C
+preprocessor,
+.CW cpp .
+.NH 2
+Unnamed substructures
+.LP
+The most important and most heavily used of the
+extensions is the declaration of an
+unnamed substructure or subunion.
+For example:
+.DS
+.CW
+.ta .1i .6i 1.1i 1.6i
+ typedef
+ struct lock
+ {
+ int locked;
+ } Lock;
+
+ typedef
+ struct node
+ {
+ int type;
+ union
+ {
+ double dval;
+ float fval;
+ long lval;
+ };
+ Lock;
+ } Node;
+
+ Lock* lock;
+ Node* node;
+.R
+.DE
+The declaration of
+.CW Node
+has an unnamed substructure of type
+.CW Lock
+and an unnamed subunion.
+One use of this feature allows references to elements of the
+subunit to be accessed as if they were in
+the outer structure.
+Thus
+.CW node->dval
+and
+.CW node->locked
+are legitimate references.
+.LP
+When an outer structure is used
+in a context that is only legal for
+an unnamed substructure,
+the compiler promotes the reference to the
+unnamed substructure.
+This is true for references to structures and
+to references to pointers to structures.
+This happens in assignment statements and
+in argument passing where prototypes have been
+declared.
+Thus, continuing with the example,
+.DS
+.CW
+.ta .1i .6i 1.1i 1.6i
+ lock = node;
+.R
+.DE
+would assign a pointer to the unnamed
+.CW Lock
+in
+the
+.CW Node
+to the variable
+.CW lock .
+Another example,
+.DS
+.CW
+.ta .1i .6i 1.1i 1.6i
+ extern void lock(Lock*);
+ func(...)
+ {
+ ...
+ lock(node);
+ ...
+ }
+.R
+.DE
+will pass a pointer to the
+.CW Lock
+substructure.
+.LP
+Finally, in places where context is insufficient to identify the unnamed structure,
+the type name (it must be a
+.CW typedef )
+of the unnamed structure can be used as an identifier.
+In our example,
+.CW &node->Lock
+gives the address of the anonymous
+.CW Lock
+structure.
+.NH 2
+Structure displays
+.LP
+A structure cast followed by a list of expressions in braces is
+an expression with the type of the structure and elements assigned from
+the corresponding list.
+Structures are now almost first-class citizens of the language.
+It is common to see code like this:
+.DS
+.CW
+.ta .1i
+ r = (Rectangle){point1, (Point){x,y+2}};
+.R
+.DE
+.NH 2
+Initialization indexes
+.LP
+In initializers of arrays,
+one may place a constant expression
+in square brackets before an initializer.
+This causes the next initializer to assign
+the indicated element.
+For example:
+.DS
+.CW
+.ta .1i .6i 1.6i
+ enum errors
+ {
+ Etoobig,
+ Ealarm,
+ Egreg
+ };
+ char* errstrings[] =
+ {
+ [Ealarm] "Alarm call",
+ [Egreg] "Panic: out of mbufs",
+ [Etoobig] "Arg list too long",
+ };
+.R
+.DE
+In the same way,
+individual structures members may
+be initialized in any order by preceding the initialization with
+.CW .tagname .
+Both forms allow an optional
+.CW = ,
+to be compatible with a proposed
+extension to ANSI C.
+.NH 2
+External register
+.LP
+The declaration
+.CW extern
+.CW register
+will dedicate a register to
+a variable on a global basis.
+It can be used only under special circumstances.
+External register variables must be identically
+declared in all modules and
+libraries.
+The feature is not intended for efficiency,
+although it can produce efficient code;
+rather it represents a unique storage class that
+would be hard to get any other way.
+On a shared-memory multi-processor,
+an external register is
+one-per-processor and neither one-per-procedure (automatic)
+or one-per-system (external).
+It is used for two variables in the Plan 9 kernel,
+.CW u
+and
+.CW m .
+.CW U
+is a pointer to the structure representing the currently running process
+and
+.CW m
+is a pointer to the per-machine data structure.
+.NH 2
+Long long
+.LP
+The compilers accept
+.CW long
+.CW long
+as a basic type meaning 64-bit integer.
+On all of the machines
+this type is synthesized from 32-bit instructions.
+.NH 2
+Pragma
+.LP
+The compilers accept
+.CW #pragma
+.CW lib
+.I libname
+and pass the
+library name string uninterpreted
+to the loader.
+The loader uses the library name to
+find libraries to load.
+If the name contains
+.CW $O ,
+it is replaced with
+the single character object type of the compiler
+(e.g.,
+.CW v
+for the MIPS).
+If the name contains
+.CW $M ,
+it is replaced with
+the architecture type for the compiler
+(e.g.,
+.CW mips
+for the MIPS).
+If the name starts with
+.CW /
+it is an absolute pathname;
+if it starts with
+.CW .
+then it is searched for in the loader's current directory.
+Otherwise, the name is searched from
+.CW /$M/lib .
+Such
+.CW #pragma
+statements in header files guarantee that the correct
+libraries are always linked with a program without the
+need to specify them explicitly at link time.
+.LP
+They also accept
+.CW #pragma
+.CW packed
+.CW on
+(or
+.CW yes
+or
+.CW 1 )
+to cause subsequently declared data, until
+.CW #pragma
+.CW packed
+.CW off
+(or
+.CW no
+or
+.CW 0 ),
+to be laid out in memory tightly packed in successive bytes, disregarding
+the usual alignment rules.
+Accessing such data can cause faults.
+.LP
+Similarly,
+.CW #pragma
+.CW profile
+.CW off
+(or
+.CW no
+or
+.CW 0 )
+causes subsequently declared functions, until
+.CW #pragma
+.CW profile
+.CW on
+(or
+.CW yes
+or
+.CW 1 ),
+to be marked as unprofiled.
+Such functions will not be profiled when
+profiling is enabled for the rest of the program.
+.LP
+Two
+.CW #pragma
+statements allow type-checking of
+.CW print -like
+functions.
+The first, of the form
+.P1
+#pragma varargck argpos error 2
+.P2
+tells the compiler that the second argument to
+.CW error
+is a
+.CW print
+format string (see the manual page
+.I print (2))
+that specifies how to format
+.CW error 's
+subsequent arguments.
+The second, of the form
+.P1
+#pragma varargck type "s" char*
+.P2
+says that the
+.CW print
+format verb
+.CW s
+processes an argument of
+type
+.CW char* .
+If the compiler's
+.CW -F
+option is enabled, the compiler will use this information
+to report type violations in the arguments to
+.CW print ,
+.CW error ,
+and similar routines.
+.NH
+Object module conventions
+.LP
+The overall conventions of the runtime environment
+are important
+to runtime efficiency.
+In this section,
+several of these conventions are discussed.
+.NH 2
+Register saving
+.LP
+In the Plan 9 compilers,
+the caller of a procedure saves the registers.
+With caller-saves,
+the leaf procedures can use all the
+registers and never save them.
+If you spend a lot of time at the leaves,
+this seems preferable.
+With callee-saves,
+the saving of the registers is done
+in the single point of entry and return.
+If you are interested in space,
+this seems preferable.
+In both,
+there is a degree of uncertainty
+about what registers need to be saved.
+Callee-saved registers make it difficult to
+find variables in registers in debuggers.
+Callee-saved registers also complicate
+the implementation of
+.CW longjmp .
+The convincing argument is
+that with caller-saves,
+the decision to registerize a variable
+can include the cost of saving the register
+across calls.
+For a further discussion of caller- vs. callee-saves,
+see the paper by Davidson and Whalley [Dav91].
+.LP
+In the Plan 9 operating system,
+calls to the kernel look like normal procedure
+calls, which means
+the caller
+has saved the registers and the system
+entry does not have to.
+This makes system calls considerably faster.
+Since this is a potential security hole,
+and can lead to non-determinism,
+the system may eventually save the registers
+on entry,
+or more likely clear the registers on return.
+.NH 2
+Calling convention
+.LP
+Older C compilers maintain a frame pointer, which is at a known constant
+offset from the stack pointer within each function.
+For machines where the stack grows towards zero,
+the argument pointer is at a known constant offset
+from the frame pointer.
+Since the stack grows down in Plan 9,
+the Plan 9 compilers
+keep neither an
+explicit frame pointer nor
+an explicit argument pointer;
+instead they generate addresses relative to the stack pointer.
+.LP
+On some architectures, the first argument to a subroutine is passed in a register.
+.NH 2
+Functions returning structures
+.LP
+Structures longer than one word are awkward to implement
+since they do not fit in registers and must
+be passed around in memory.
+Functions that return structures
+are particularly clumsy.
+The Plan 9 compilers pass the return address of
+a structure as the first argument of a
+function that has a structure return value.
+Thus
+.DS
+.CW
+.ta .1i .6i 1.1i 1.6i
+ x = f(...)
+.R
+.DE
+is rewritten as
+.DS
+.CW
+.ta .1i .6i 1.1i 1.6i
+ f(&x, ...)\f1.
+.R
+.DE
+This saves a copy and makes the compilation
+much less clumsy.
+A disadvantage is that if you call this
+function without an assignment,
+a dummy location must be invented.
+.LP
+There is also a danger of calling a function
+that returns a structure without declaring
+it as such.
+With ANSI C function prototypes,
+this error need never occur.
+.NH
+Implementation
+.LP
+The compiler is divided internally into
+four machine-independent passes,
+four machine-dependent passes,
+and an output pass.
+The next nine sections describe each pass in order.
+.NH 2
+Parsing
+.LP
+The first pass is a YACC-based parser
+[Joh79].
+Declarations are interpreted immediately,
+building a block structured symbol table.
+Executable statements are put into a parse tree
+and collected,
+without interpretation.
+At the end of each procedure,
+the parse tree for the function is
+examined by the other passes of the compiler.
+.LP
+The input stream of the parser is
+a pushdown list of input activations.
+The preprocessor
+expansions of
+macros
+and
+.CW #include
+are implemented as pushdowns.
+Thus there is no separate
+pass for preprocessing.
+.NH 2
+Typing
+.LP
+The next pass distributes typing information
+to every node of the tree.
+Implicit operations on the tree are added,
+such as type promotions and taking the
+address of arrays and functions.
+.NH 2
+Machine-independent optimization
+.LP
+The next pass performs optimizations
+and transformations of the tree, such as converting
+.CW &*x
+and
+.CW *&x
+into
+.CW x .
+Constant expressions are converted to constants in this pass.
+.NH 2
+Arithmetic rewrites
+.LP
+This is another machine-independent optimization.
+Subtrees of add, subtract, and multiply of integers are
+rewritten for easier compilation.
+The major transformation is factoring:
+.CW 4+8*a+16*b+5
+is transformed into
+.CW 9+8*(a+2*b) .
+Such expressions arise from address
+manipulation and array indexing.
+.NH 2
+Addressability
+.LP
+This is the first of the machine-dependent passes.
+The addressability of a processor is defined as the set of
+expressions that is legal in the address field
+of a machine language instruction.
+The addressability of different processors varies widely.
+At one end of the spectrum are the 68020 and VAX,
+which allow a complex mix of incrementing,
+decrementing,
+indexing, and relative addressing.
+At the other end is the MIPS,
+which allows only registers and constant offsets from the
+contents of a register.
+The addressability can be different for different instructions
+within the same processor.
+.LP
+It is important to the code generator to know when a
+subtree represents an address of a particular type.
+This is done with a bottom-up walk of the tree.
+In this pass, the leaves are labeled with small integers.
+When an internal node is encountered,
+it is labeled by consulting a table indexed by the
+labels on the left and right subtrees.
+For example,
+on the 68020 processor,
+it is possible to address an
+offset from a named location.
+In C, this is represented by the expression
+.CW *(&name+constant) .
+This is marked addressable by the following table.
+In the table,
+a node represented by the left column is marked
+with a small integer from the right column.
+Marks of the form
+.CW A\s-2\di\u\s0
+are addressable while
+marks of the form
+.CW N\s-2\di\u\s0
+are not addressable.
+.DS
+.B
+.ta .1i 1.1i
+ Node Marked
+.CW
+ name A\s-2\d1\u\s0
+ const A\s-2\d2\u\s0
+ &A\s-2\d1\u\s0 A\s-2\d3\u\s0
+ A\s-2\d3\u\s0+A\s-2\d1\u\s0 N\s-2\d1\u\s0 \fR(note that this is not addressable)\fP
+ *N\s-2\d1\u\s0 A\s-2\d4\u\s0
+.R
+.DE
+Here there is a distinction between
+a node marked
+.CW A\s-2\d1\u\s0
+and a node marked
+.CW A\s-2\d4\u\s0
+because the address operator of an
+.CW A\s-2\d4\u\s0
+node is not addressable.
+So to extend the table:
+.DS
+.B
+.ta .1i 1.1i
+ Node Marked
+.CW
+ &A\s-2\d4\u\s0 N\s-2\d2\u\s0
+ N\s-2\d2\u\s0+N\s-2\d1\u\s0 N\s-2\d1\u\s0
+.R
+.DE
+The full addressability of the 68020 is expressed
+in 18 rules like this,
+while the addressability of the MIPS is expressed
+in 11 rules.
+When one ports the compiler,
+this table is usually initialized
+so that leaves are labeled as addressable and nothing else.
+The code produced is poor,
+but porting is easy.
+The table can be extended later.
+.LP
+This pass also rewrites some complex operators
+into procedure calls.
+Examples include 64-bit multiply and divide.
+.LP
+In the same bottom-up pass of the tree,
+the nodes are labeled with a Sethi-Ullman complexity
+[Set70].
+This number is roughly the number of registers required
+to compile the tree on an ideal machine.
+An addressable node is marked 0.
+A function call is marked infinite.
+A unary operator is marked as the
+maximum of 1 and the mark of its subtree.
+A binary operator with equal marks on its subtrees is
+marked with a subtree mark plus 1.
+A binary operator with unequal marks on its subtrees is
+marked with the maximum mark of its subtrees.
+The actual values of the marks are not too important,
+but the relative values are.
+The goal is to compile the harder
+(larger mark)
+subtree first.
+.NH 2
+Code generation
+.LP
+Code is generated by recursive
+descent.
+The Sethi-Ullman complexity completely guides the
+order.
+The addressability defines the leaves.
+The only difficult part is compiling a tree
+that has two infinite (function call)
+subtrees.
+In this case,
+one subtree is compiled into the return register
+(usually the most convenient place for a function call)
+and then stored on the stack.
+The other subtree is compiled into the return register
+and then the operation is compiled with
+operands from the stack and the return register.
+.LP
+There is a separate boolean code generator that compiles
+conditional expressions.
+This is fundamentally different from compiling an arithmetic expression.
+The result of the boolean code generator is the
+position of the program counter and not an expression.
+The boolean code generator makes extensive use of De Morgan's rule.
+The boolean code generator is an expanded version of that described
+in chapter 8 of Aho, Sethi, and Ullman
+[Aho87].
+.LP
+There is a considerable amount of talk in the literature
+about automating this part of a compiler with a machine
+description.
+Since this code generator is so small
+(less than 500 lines of C)
+and easy,
+it hardly seems worth the effort.
+.NH 2
+Registerization
+.LP
+Up to now,
+the compiler has operated on syntax trees
+that are roughly equivalent to the original source language.
+The previous pass has produced machine language in an internal
+format.
+The next two passes operate on the internal machine language
+structures.
+The purpose of the next pass is to reintroduce
+registers for heavily used variables.
+.LP
+All of the variables that can be
+potentially registerized within a procedure are
+placed in a table.
+(Suitable variables are any automatic or external
+scalars that do not have their addresses extracted.
+Some constants that are hard to reference are also
+considered for registerization.)
+Four separate data flow equations are evaluated
+over the procedure on all of these variables.
+Two of the equations are the normal set-behind
+and used-ahead
+bits that define the life of a variable.
+The two new bits tell if a variable life
+crosses a function call ahead or behind.
+By examining a variable over its lifetime,
+it is possible to get a cost
+for registerizing.
+Loops are detected and the costs are multiplied
+by three for every level of loop nesting.
+Costs are sorted and the variables
+are replaced by available registers on a greedy basis.
+.LP
+The 68020 has two different
+types of registers.
+For the 68020,
+two different costs are calculated for
+each variable life and the register type that
+affords the better cost is used.
+Ties are broken by counting the number of available
+registers of each type.
+.LP
+Note that externals are registerized together with automatics.
+This is done by evaluating the semantics of a ``call'' instruction
+differently for externals and automatics.
+Since a call goes outside the local procedure,
+it is assumed that a call references all externals.
+Similarly,
+externals are assumed to be set before an ``entry'' instruction
+and assumed to be referenced after a ``return'' instruction.
+This makes sure that externals are in memory across calls.
+.LP
+The overall results are satisfactory.
+It would be nice to be able to do this processing in
+a machine-independent way,
+but it is impossible to get all of the costs and
+side effects of different choices by examining the parse tree.
+.LP
+Most of the code in the registerization pass is machine-independent.
+The major machine-dependency is in
+examining a machine instruction to ask if it sets or references
+a variable.
+.NH 2
+Machine code optimization
+.LP
+The next pass walks the machine code
+for opportunistic optimizations.
+For the most part,
+this is highly specific to a particular
+processor.
+One optimization that is performed
+on all of the processors is the
+removal of unnecessary ``move''
+instructions.
+Ironically,
+most of these instructions were inserted by
+the previous pass.
+There are two patterns that are repetitively
+matched and replaced until no more matches are
+found.
+The first tries to remove ``move'' instructions
+by relabeling variables.
+.LP
+When a ``move'' instruction is encountered,
+if the destination variable is set before the
+source variable is referenced,
+then all of the references to the destination
+variable can be renamed to the source and the ``move''
+can be deleted.
+This transformation uses the reverse data flow
+set up in the previous pass.
+.LP
+An example of this pattern is depicted in the following
+table.
+The pattern is in the left column and the
+replacement action is in the right column.
+.DS
+.CW
+.ta .1i .6i 1.6i 2.1i 2.6i
+ MOVE a->b \fR(remove)\fP
+.R
+ (sequence with no mention of \f(CWa\fP)
+.CW
+ USE b USE a
+.R
+ (sequence with no mention of \f(CWa\fP)
+.CW
+ SET b SET b
+.R
+.DE
+.LP
+Experiments have shown that it is marginally
+worthwhile to rename uses of the destination variable
+with uses of the source variable up to
+the first use of the source variable.
+.LP
+The second transform will do relabeling
+without deleting instructions.
+When a ``move'' instruction is encountered,
+if the source variable has been set prior
+to the use of the destination variable
+then all of the references to the source
+variable are replaced by the destination and
+the ``move'' is inverted.
+Typically,
+this transformation will alter two ``move''
+instructions and allow the first transformation
+another chance to remove code.
+This transformation uses the forward data flow
+set up in the previous pass.
+.LP
+Again,
+the following is a depiction of the transformation where
+the pattern is in the left column and the
+rewrite is in the right column.
+.DS
+.CW
+.ta .1i .6i 1.6i 2.1i 2.6i
+ SET a SET b
+.R
+ (sequence with no use of \f(CWb\fP)
+.CW
+ USE a USE b
+.R
+ (sequence with no use of \f(CWb\fP)
+.CW
+ MOVE a->b MOVE b->a
+.R
+.DE
+Iterating these transformations
+will usually get rid of all redundant ``move'' instructions.
+.LP
+A problem with this organization is that the costs
+of registerization calculated in the previous pass
+must depend on how well this pass can detect and remove
+redundant instructions.
+Often,
+a fine candidate for registerization is rejected
+because of the cost of instructions that are later
+removed.
+.NH 2
+Writing the object file
+.LP
+The last pass walks the internal assembly language
+and writes the object file.
+The object file is reduced in size by about a factor
+of three with simple compression
+techniques.
+The most important aspect of the object file
+format is that it is independent of the compiling machine.
+All integer and floating numbers in the object
+code are converted to known formats and byte
+orders.
+.NH
+The loader
+.LP
+The loader is a multiple pass program that
+reads object files and libraries and produces
+an executable binary.
+The loader also does some minimal
+optimizations and code rewriting.
+Many of the operations performed by the
+loader are machine-dependent.
+.LP
+The first pass of the loader reads the
+object modules into an internal data
+structure that looks like binary assembly language.
+As the instructions are read,
+code is reordered to remove
+unconditional branch instructions.
+Conditional branch instructions are inverted
+to prevent the insertion of unconditional branches.
+The loader will also make a copy of a few instructions
+to remove an unconditional branch.
+.LP
+The next pass allocates addresses for
+all external data.
+Typical of processors is the MIPS,
+which can reference ±32K bytes from a
+register.
+The loader allocates the register
+.CW R30
+as the static pointer.
+The value placed in
+.CW R30
+is the base of the data segment plus 32K.
+It is then cheap to reference all data in the
+first 64K of the data segment.
+External variables are allocated to
+the data segment
+with the smallest variables allocated first.
+If all of the data cannot fit into the first
+64K of the data segment,
+then usually only a few large arrays
+need more expensive addressing modes.
+.LP
+For the MIPS processor,
+the loader makes a pass over the internal
+structures,
+exchanging instructions to try
+to fill ``delay slots'' with useful work.
+If a useful instruction cannot be found
+to fill a delay slot,
+the loader will insert
+``noop''
+instructions.
+This pass is very expensive and does not
+do a good job.
+About 40% of all instructions are in
+delay slots.
+About 65% of these are useful instructions and
+35% are ``noops.''
+The vendor-supplied assembler does this job
+more effectively,
+filling about 80%
+of the delay slots with useful instructions.
+.LP
+On the 68020 processor,
+branch instructions come in a variety of
+sizes depending on the relative distance
+of the branch.
+Thus the size of branch instructions
+can be mutually dependent.
+The loader uses a multiple pass algorithm
+to resolve the branch lengths
+[Szy78].
+Initially, all branches are assumed minimal length.
+On each subsequent pass,
+the branches are reassessed
+and expanded if necessary.
+When no more expansions occur,
+the locations of the instructions in
+the text segment are known.
+.LP
+On the MIPS processor,
+all instructions are one size.
+A single pass over the instructions will
+determine the locations of all addresses
+in the text segment.
+.LP
+The last pass of the loader produces the
+executable binary.
+A symbol table and other tables are
+produced to help the debugger to
+interpret the binary symbolically.
+.LP
+The loader places absolute source line numbers in the symbol table.
+The name and absolute line number of all
+.CW #include
+files is also placed in the
+symbol table so that the debuggers can
+associate object code to source files.
+.NH
+Performance
+.LP
+The following is a table of the source size of the MIPS
+compiler.
+.DS
+.ta .1i .6i
+ lines module
+ \0509 machine-independent headers
+ 1070 machine-independent YACC source
+ 6090 machine-independent C source
+
+ \0545 machine-dependent headers
+ 6532 machine-dependent C source
+
+ \0298 loader headers
+ 5215 loader C source
+.DE
+.LP
+The following table shows timing
+of a test program
+that plays checkers, running on a MIPS R4000.
+The test program is 26 files totaling 12600 lines of C.
+The execution time does not significantly
+depend on library implementation.
+Since no other compiler runs on Plan 9,
+the Plan 9 tests were done with the Plan 9 operating system;
+the other tests were done on the vendor's operating system.
+The hardware was identical in both cases.
+The optimizer in the vendor's compiler
+is reputed to be extremely good.
+.DS
+.ta .1i .9i
+ \0\04.49s Plan 9 \f(CWvc\fP \f(CW-N\fP compile time (opposite of \f(CW-O\fP)
+ \0\01.72s Plan 9 \f(CWvc\fP \f(CW-N\fP load time
+ 148.69s Plan 9 \f(CWvc\fP \f(CW-N\fP run time
+
+ \015.07s Plan 9 \f(CWvc\fP compile time (\f(CW-O\fP implicit)
+ \0\01.66s Plan 9 \f(CWvc\fP load time
+ \089.96s Plan 9 \f(CWvc\fP run time
+
+ \014.83s vendor \f(CWcc\fP compile time
+ \0\00.38s vendor \f(CWcc\fP load time
+ 104.75s vendor \f(CWcc\fP run time
+
+ \043.59s vendor \f(CWcc\fP \f(CW-O\fP compile time
+ \0\00.38s vendor \f(CWcc\fP \f(CW-O\fP load time
+ \076.19s vendor \f(CWcc\fP \f(CW-O\fP run time
+
+ \0\08.19s vendor \f(CWcc\fP \f(CW-O3\fP compile time
+ \035.97s vendor \f(CWcc\fP \f(CW-O3\fP load time
+ \071.16s vendor \f(CWcc\fP \f(CW-O3\fP run time
+.DE
+.LP
+To compare the Intel compiler,
+a program that is about 40% bit manipulation and
+about 60% single precision floating point was
+run on the same 33 MHz 486, once under Windows
+compiled with the Watcom compiler, version 10.0,
+in 16-bit mode and once under
+Plan 9 in 32-bit mode.
+The Plan 9 execution time was 27 sec while the Windows
+execution time was 31 sec.
+.NH
+Conclusions
+.LP
+The new compilers compile
+quickly,
+load slowly,
+and produce
+medium quality
+object code.
+The compilers are relatively
+portable,
+requiring but a couple of weeks' work to
+produce a compiler for a different computer.
+For Plan 9,
+where we needed several compilers
+with specialized features and
+our own object formats,
+this project was indispensable.
+It is also necessary for us to
+be able to freely distribute our compilers
+with the Plan 9 distribution.
+.LP
+Two problems have come up in retrospect.
+The first has to do with the
+division of labor between compiler and loader.
+Plan 9 runs on multi-processors and as such
+compilations are often done in parallel.
+Unfortunately,
+all compilations must be complete before loading
+can begin.
+The load is then single-threaded.
+With this model,
+any shift of work from compile to load
+results in a significant increase in real time.
+The same is true of libraries that are compiled
+infrequently and loaded often.
+In the future,
+we may try to put some of the loader work
+back into the compiler.
+.LP
+The second problem comes from
+the various optimizations performed over several
+passes.
+Often optimizations in different passes depend
+on each other.
+Iterating the passes could compromise efficiency,
+or even loop.
+We see no real solution to this problem.
+.NH
+References
+.LP
+[Aho87] A. V. Aho, R. Sethi, and J. D. Ullman,
+.I
+Compilers \- Principles, Techniques, and Tools,
+.R
+Addison Wesley,
+Reading, MA,
+1987.
+.LP
+[ANSI90] \f2American National Standard for Information Systems \-
+Programming Language C\f1, American National Standards Institute, Inc.,
+New York, 1990.
+.LP
+[Dav91] J. W. Davidson and D. B. Whalley,
+``Methods for Saving and Restoring Register Values across Function Calls'',
+.I
+Software\-Practice and Experience,
+.R
+Vol 21(2), pp. 149-165, February 1991.
+.LP
+[Joh79] S. C. Johnson,
+``YACC \- Yet Another Compiler Compiler'',
+.I
+UNIX Programmer's Manual, Seventh Ed., Vol. 2A,
+.R
+AT&T Bell Laboratories,
+Murray Hill, NJ,
+1979.
+.LP
+[Set70] R. Sethi and J. D. Ullman,
+``The Generation of Optimal Code for Arithmetic Expressions'',
+.I
+Journal of the ACM,
+.R
+Vol 17(4), pp. 715-728, 1970.
+.LP
+[Szy78] T. G. Szymanski,
+``Assembling Code for Machines with Span-dependent Instructions'',
+.I
+Communications of the ACM,
+.R
+Vol 21(4), pp. 300-308, 1978.
binary files /dev/null b/doc/compiler.pdf differ
--- /dev/null
+++ b/doc/descent/descent.ms
@@ -1,0 +1,2056 @@
+.de EX
+.nr x \\$1v
+\\!h0c n \\nx 0
+..
+.de FG \" start figure caption: .FG filename.ps verticalsize
+.KF
+.BP \\$1 \\$2
+.sp .5v
+.EX \\$2v
+.ps -1
+.vs -1
+..
+.de fg \" end figure caption (yes, it is clumsy)
+.ps
+.vs
+.br
+.KE
+..
+.TL
+A Descent into Limbo
+.AU
+Brian W. Kernighan
+.AI
+bwk@bell-labs.com
+.br
+Revised April 2005 by Vita Nuova
+.AB
+.DS B
+.ps -2
+.vs -1
+``If, reader, you are slow now to believe
+What I shall tell, that is no cause for wonder,
+For I who saw it hardly can accept it.''
+.ft R
+ Dante Alighieri, \fIInferno\fP, Canto XXV.
+.ps +2
+.vs +1
+.DE
+.LP
+Limbo is a new programming language, designed by
+Sean Dorward, Phil Winterbottom, and Rob Pike.
+Limbo borrows from, among other things,
+C (expression syntax and control flow),
+Pascal (declarations),
+Winterbottom's Alef (abstract data types and channels),
+and Hoare's CSP and Pike's Newsqueak (processes).
+Limbo is strongly typed, provides automatic garbage collection,
+supports only very restricted pointers,
+and compiles into machine-independent byte code for execution on
+a virtual machine.
+.LP
+This paper is a brief introduction to Limbo.
+Since Limbo is an integral part of the Inferno system,
+the examples here illustrate not only
+the language but also a certain amount about how to write
+programs to run within Inferno.
+.AE
+.NH 1
+Introduction
+.LP
+This document is a quick look at the basics
+of Limbo; it is not a replacement for the reference manual.
+The first section is a short overview of
+concepts and constructs;
+subsequent sections illustrate the language with examples.
+Although Limbo is intended to be used in Inferno,
+which emphasizes networking and graphical interfaces,
+the discussion here begins with standard text-manipulation
+examples, since they require less background to understand.
+.SH
+Modules:
+.LP
+A Limbo program is a set of modules that cooperate
+to perform a task.
+In source form, a module consists of a
+.CW "module"
+declaration that specifies the public interface \- the functions,
+abstract data types,
+and constants that the module makes visible to other modules \-
+and an implementation that provides the actual code.
+By convention, the module declaration is usually placed in a separate
+.CW ".m"
+file so it can be included by other modules,
+and the implementation is stored in a
+.CW ".b"
+file.
+Modules may have multiple implementations,
+each in a separate implementation file.
+.LP
+Modules are always loaded dynamically, at run time: the Limbo
+.CW "load"
+operator fetches the code and performs run-time type checking.
+Once a module has been loaded, its functions can be called.
+Several instances of the same module type can be in use at once,
+with possibly different implementations.
+.LP
+Limbo is strongly typed; programs are checked at compile time,
+and further when modules are loaded.
+The Limbo compiler compiles each source file into a
+machine-independent byte-coded
+.CW ".dis"
+file that can be loaded at run time.
+.SH
+Functions and variables:
+.LP
+Functions are associated with specific modules, either directly or
+as members of abstract data types within a module.
+Functions are visible outside their module only
+if they are part of the module interface.
+If the target module is loaded, specific names
+can be used in a qualified form like
+.CW "sys->print"
+or without the qualifier if imported with an explicit
+.CW "import"
+statement.
+.LP
+Besides normal block structure within functions,
+variables may have global scope within a module;
+module data can be accessed via the module pointer.
+.SH
+Data:
+.LP
+The numeric types are:
+.RS
+.TS
+lf(CW) lf(R)w(3i) .
+byte unsigned, 8 bits
+int signed, 32 bits
+big signed, 64 bits
+real IEEE long float, 64 bits
+.TE
+.RE
+The size and signedness of integral types are
+as specified above, and will be the same everywhere.
+Character constants are enclosed in single quotes
+and may use escapes like
+.CW "'\en'"
+or
+.CW "'\eudddd'" ,
+but the characters themselves
+are in Unicode and have type
+.CW "int" .
+There is no enumeration type, but there is a
+.CW "con"
+declaration that creates a named constant, and a special
+.CW "iota"
+operation that can be used to generate unique values.
+.LP
+Limbo also provides
+Unicode strings,
+arrays of arbitrary types,
+lists of arbitrary types,
+tuples (in effect, unnamed structures with unnamed members of arbitrary types),
+abstract data types or adt's (in effect, named structures with function
+members as well as data members),
+reference types (in effect, restricted pointers that can point only to adt objects),
+and
+typed channels (for passing objects between processes).
+.LP
+A channel is a mechanism for synchronized communication.
+It provides a place for one process to send or receive
+an object of a specific type;
+the attempt to send or receive blocks until a matching receive or send
+is attempted by another process.
+The
+.CW "alt"
+statement selects randomly but fairly among channels
+that are ready to read or write.
+The
+.CW "spawn"
+statement creates a new process that,
+except for its stack, shares memory with other processes.
+Processes are pre-emptively scheduled by the Inferno kernel.
+(Inferno processes are sometimes called ``threads'' in
+other operating systems.)
+.LP
+Limbo performs automatic garbage collection, so there is no
+need to free dynamically created objects.
+Objects are deleted and their resources freed when
+the last reference to them goes away.
+This release of resources happens immediately
+(``instant free'') for non-cyclic structures;
+release of cyclic data structures might be delayed but will happen eventually.
+(The language allows the programmer to ensure a given structure is non-cyclic
+when required.)
+.SH
+Operators and expressions:
+.LP
+Limbo provides many of C's operators,
+but not the
+.CW "?:"
+or
+`comma' (sequential execution) operators.
+Pointers, or `references', created with
+.CW "ref" ,
+are restricted compared to C: they can only refer to adt values on the heap.
+There is no
+.CW "&"
+(address of) operator, nor is address arithmetic possible.
+Arrays are also reference types, however,
+and since
+array slicing is supported, that replaces
+many of C's pointer constructions.
+.LP
+There are no implicit coercions between types,
+and only a handful of explicit casts.
+The numeric types
+.CW "byte" ,
+.CW "int" ,
+etc., can be used to convert a numeric expression, as in
+.P1
+nl := byte 10;
+.P2
+and
+.CW "string"
+can be used as a unary operator to convert any numeric expression
+to a string (in
+.CW "%g"
+format) and to convert an array of bytes in UTF-8 format to a Limbo
+.CW string
+value.
+In the other direction, the cast
+.CW "array of byte"
+converts a string to its UTF-8 representation in an array of bytes.
+.SH
+Statements:
+.LP
+Statements and control flow in Limbo are similar to those in C.
+A statement is an expression followed by a semicolon,
+or a sequence of statements enclosed in braces.
+The similar control flow statements are
+.P1
+if (\fIexpr\fP) \fIstat\fP
+if (\fIexpr\fP) \fIstat\fP else \fIstat\fP
+while (\fIexpr\fP) \fIstat\fP
+for (\fIexpr\fP; \fIexpr\fP; \fIexpr\fP) \fIstat\fP
+do \fIstat\fP while (\fIexpr\fP) ;
+return \fIexpr\fP ;
+exit ;
+.P2
+The
+.CW "exit"
+statement terminates a process and frees its resources.
+There is also a
+.CW "case"
+statement analogous to C's
+.CW "switch" ,
+but it differs in that it also supports string and range tests,
+and more critically, control flow does not ``flow through'' one arm of the case to another
+but stops without requiring an explicit
+.CW break
+(in that respect it is closer to Pascal's
+.CW case
+statement, hence the change of name).
+A
+.CW "break"
+or
+.CW "continue"
+followed by a label
+causes a break out of, or the next iteration of, the enclosing
+construct that is labeled with the same label.
+.LP
+Comments begin with
+.CW "#"
+and extend to the end of the line.
+There is no preprocessor, but an
+.CW "include"
+statement can be used to include source code, usually module declaration files.
+.SH
+Libraries:
+.LP
+Limbo has an extensive and growing set of standard libraries,
+each implemented as a module.
+A handful of these
+(notably
+.CW "Sys" ,
+.CW "Draw" ,
+and
+.CW "Tk" )
+are included in the Inferno kernel because they will be
+needed to support almost any Limbo program.
+Among the others are
+.CW "Bufio" ,
+a buffered I/O package based on Plan 9's Bio;
+.CW "Regex" ,
+for regular expressions;
+and
+.CW "Math" ,
+for mathematical functions.
+Some of the examples that follow provide the sort
+of functionality that might be a suitable module.
+.NH 1
+Examples
+.LP
+The examples in this section are each complete, in the sense that they
+will run as presented; I have tried to avoid code fragments
+that merely illustrate syntax.
+.NH 2
+Hello, World
+.LP
+The first example is the traditional ``hello, world'',
+in the file
+.CW "hello.b" :
+.P1
+implement Hello;
+
+include "sys.m";
+ sys: Sys;
+include "draw.m";
+
+Hello: module
+{
+ init: fn(ctxt: ref Draw->Context, args: list of string);
+};
+
+init(ctxt: ref Draw->Context, args: list of string)
+{
+ sys = load Sys Sys->PATH;
+ sys->print("hello, world\en");
+}
+.P2
+An implementation file implements a single module,
+named in the
+.CW "implement"
+declaration at the top of the file.
+The two
+.CW "include"
+lines copy interface definitions from two other modules,
+.CW "Sys"
+(which describes a variety of system functions like
+.CW "print" ),
+and
+.CW "Draw"
+(which describes a variety of graphics types and functions,
+only one of which,
+.CW "Context" ,
+is used here).
+.LP
+The
+.CW "module"
+declaration defines the external interface that this module
+presents to the rest of the world.
+In this case, it's a single function named
+.CW "init" .
+Since this module is to be called from a command interpreter
+(shell), by convention its
+.CW "init"
+function takes two arguments,
+the graphical context
+and a list of strings, the command-line arguments,
+though neither is used here.
+This is like
+.CW "main"
+in a C program.
+Essentially all of the other examples begin with this standard code.
+Commands are unusual, though, in that a command's module declaration
+appears in the same file as its implementation.
+.LP
+Most modules have a more extensive set of declarations; for example,
+.CW "draw.m"
+is 298 lines of constants, function prototypes, and
+type declarations for graphics types like
+.CW "Point"
+and
+.CW "Rect" ,
+and
+.CW "sys.m"
+is 160 lines of declarations for functions like
+.CW "open" ,
+.CW "read" ,
+and
+.CW "print" .
+Most module declarations are therefore stored in separate files,
+conventionally suffixed with
+.CW ".m" ,
+so they can be included in other modules.
+The system library module declaration files are collected in the
+.CW module
+directory at the root of the Inferno source tree.
+Modules that are components of a single program are typically
+stored in that program's source directory.
+.LP
+The last few lines of
+.CW "hello.b"
+are the implementation of the
+.CW "init"
+function, which loads the
+.CW "Sys"
+module, then calls its
+.CW "print"
+function.
+By convention, each module declaration includes a pathname constant
+that points to the code for the module; this is the second parameter
+.CW "Sys->PATH"
+of the
+.CW "load"
+statement.
+Note that the
+.CW Draw
+module is not loaded because none of its functions is used, but
+it is included to define the type
+.CW Draw->Context .
+.SH
+Compiling and Running Limbo Programs
+.LP
+With this much of the language described,
+we can compile and run this program.
+On Unix or Windows, the command
+.P1
+$ limbo -g hello.b
+.P2
+creates
+.CW "hello.dis" ,
+a byte-coded version of the program for the Dis
+virtual machine.
+The
+.CW "-g"
+argument adds a symbol table, useful for subsequent debugging.
+(Another common option is
+.CW -w ,
+which causes the compiler to produce helpful warnings about possible errors.)
+The program can then be run as
+.CW "hello"
+in Inferno; this shows execution under the Inferno emulator
+on a Unix system:
+.P1
+$ limbo -g hello.b
+$ emu
+; /usr/bwk/hello
+hello, world
+;
+.P2
+From within Inferno, it's also possible to run a
+program by selecting it from a menu.
+In any case, as the program runs, it loads as necessary other modules that it uses.
+.NH 2
+A Graphical "Hello World"
+.LP
+The following module creates and displays a window containing only
+a button with the label ``hello, world'' as shown in the screen shot in Figure 1.
+.P1
+implement Hello2;
+
+include "sys.m";
+ sys: Sys;
+include "draw.m";
+ draw: Draw;
+include "tk.m";
+ tk: Tk;
+include "tkclient.m";
+ tkclient: Tkclient;
+
+Hello2: module
+{
+ init: fn(ctxt: ref Draw->Context, args: list of string);
+};
+
+init(ctxt: ref Draw->Context, args: list of string)
+{
+ sys = load Sys Sys->PATH;
+ tk = load Tk Tk->PATH;
+ tkclient = load Tkclient Tkclient->PATH;
+
+ tkclient->init();
+
+ (t, nil) := tkclient->toplevel(ctxt, "", "Hello", Tkclient->Plain);
+
+ tk->cmd(t, "button .b -text {hello, world}");
+ tk->cmd(t, "pack .b");
+ tk->cmd(t, "update");
+
+ tkclient->onscreen(t, nil);
+
+ sys->sleep(10000); # wait 10 seconds
+}
+.P2
+.FG "f1.ps" 3i
+.ce
+.I "Figure 1. `Hello, world' button."
+.fg
+This is not very exciting, but it illustrates the absolute
+minimum required to get a picture on the screen.
+The
+.CW "Tk"
+module is modeled closely after John Ousterhout's Tk interface toolkit,
+but Limbo is used as the programming language instead of Tcl.
+The Inferno version
+is similar in functionality to the original Tk
+but it does not support any Tcl constructs,
+such as variables, procedures, or expression evaluation,
+since all processing is done using Limbo.
+There are ten functions in the
+.CW "Tk"
+interface, only one of which
+is used here:
+.CW "cmd" ,
+which executes a command string.
+(It is the most commonly used
+.CW Tk
+function.)
+.LP
+Tk itself displays graphics and handles mouse and keyboard interaction
+within a window.
+There can however be many different windows on a display.
+A separate window manager,
+.CW wm ,
+multiplexes control of input and output among those windows.
+The module
+.CW Tkclient
+provides the interface between the window manager and Tk.
+Its function
+.CW "toplevel" ,
+used above,
+makes a top-level window and returns a reference to it, for subsequent use by Tk.
+The contents of the window are prepared by calls to
+.CW tk->cmd
+before the window is finally displayed by the call to
+.CW onscreen .
+(The second parameter to
+.CW onscreen ,
+a string,
+controls the position and style of window;
+here we take the default by making that
+.CW nil .)
+.LP
+Note that
+.CW Tkclient
+must also be explicitly initialized by calling its
+.CW init
+function after loading.
+This is a common convention, although some modules do
+not require it (typically those built in
+to the system, such as
+.CW Sys
+or
+.CW Tk ).
+.LP
+The
+.CW "sleep"
+delays exit for 10 seconds so the button can be seen.
+If you try to interact with the window, for instance by pressing the button,
+you will see no response.
+That is because the program has not done what is required to receive mouse or keyboard input in the window.
+In a real application, some action would also be bound to pressing the button.
+Such actions are handled by setting up a connection (a `channel') from
+the Tk module to one's own code, and processing the
+messages (`events') that appear on this channel.
+The Tk module and its interface to the window manager
+is explained in more detail later,
+as are a couple of other constructions,
+after we have introduced processes and channels.
+.NH 2
+Echo
+.LP
+The next example,
+.CW "echo" ,
+prints its command-line arguments.
+Declarations are the same as in the first
+example, and have been omitted.
+.P1
+# declarations omitted...
+
+init(ctxt: ref Draw->Context, args: list of string)
+{
+ sys = load Sys Sys->PATH;
+
+ args = tl args; # skip over program name
+ for (s := ""; args != nil; args = tl args)
+ s += " " + hd args;
+ if (s != "") # something was stored in s
+ sys->print("%s\en", s[1:]);
+}
+.P2
+The arguments are stored in a
+.CW "list" .
+Lists may be of any type;
+.CW "args"
+is a
+.CW "list"
+.CW "of"
+.CW "string" .
+There are three list operators:
+.CW "hd"
+and
+.CW "tl"
+return the head and tail of a list, and
+.CW "::"
+adds a new element to the head.
+In this example, the
+.CW "for"
+loop walks along the
+.CW "args"
+list until the end,
+printing the head element
+.CW "hd args" ), (
+then advancing
+.CW "args = tl args" ). (
+.LP
+The value
+.CW "nil"
+is the ``undefined'' or ``explicitly empty'' value
+for non-numeric types.
+.LP
+The operator
+.CW ":="
+combines the declaration of a variable and assignment of a value to it.
+The type of the variable on the left of
+.CW ":="
+is the type
+of the expression on the right.
+Thus, the expression
+.P1
+s := ""
+.P2
+in the
+.CW "for"
+statement
+declares a string
+.CW "s"
+and initializes it to empty;
+if after the loop,
+.CW "s"
+is not empty,
+something has been written in it.
+By the way, there is no distinction between the values
+.CW "nil"
+and
+\f5""\fP
+for strings.
+.LP
+The
+.CW "+"
+and
+.CW "+="
+operators concatenate strings.
+The expression
+.CW "s[1:]"
+is a
+.I slice
+of the string
+.CW "s"
+that starts at index 1
+(the second character of the string) and goes
+to the end; this excludes the unwanted
+blank at the beginning of
+.CW "s" .
+.NH 2
+Word Count
+.LP
+The word count program
+.CW "wc"
+reads its standard input
+and counts the number of lines, words, and characters.
+Declarations have again been omitted.
+.P1
+# declarations omitted...
+
+init(nil: ref Draw->Context, args: list of string)
+{
+ sys = load Sys Sys->PATH;
+ buf := array[1] of byte;
+
+ stdin := sys->fildes(0);
+
+ OUT: con 0;
+ IN: con 1;
+
+ state := OUT;
+ nl := 0; nw := 0; nc := 0;
+ for (;;) {
+ n := sys->read(stdin, buf, 1);
+ if (n <= 0)
+ break;
+ c := int buf[0];
+ nc++;
+ if (c == '\en')
+ nl++;
+ if (c == ' ' || c == '\et' || c == '\en')
+ state = OUT;
+ else if (state == OUT) {
+ state = IN;
+ nw++;
+ }
+ }
+ sys->print("%d %d %d\en", nl, nw, nc);
+}
+.P2
+.LP
+This program contains several instances of the
+.CW ":="
+operator.
+For example, the line
+.P1
+ nl := 0; nw := 0; nc := 0;
+.P2
+declares three integer variables
+and assigns zero to each.
+.LP
+A Limbo program starts with three open files for standard
+input, standard output, and standard error, as in Unix.
+The line
+.P1
+ stdin := sys->fildes(0);
+.P2
+declares a variable
+.CW "stdin"
+and assigns the corresponding file descriptor to it.
+The type of
+.CW "stdin"
+is whatever the type of
+.CW "sys->fildes(0)"
+is, and it's possible to get by without
+ever knowing the name of that type.
+(We will return to this shortly.)
+.NE 3v
+.LP
+The lines
+.P1
+ OUT: con 0;
+ IN: con 1;
+.P2
+declare two integer constants with values zero and one.
+There is no
+.CW "enum"
+type in Limbo; the
+.CW "con"
+declaration is the closest equivalent.
+When the values are arbitrary, a different form is normally used:
+.P1
+ OUT, IN: con iota;
+.P2
+The operator
+.CW "iota" ,
+when used in
+.CW con
+declarations will produce the sequence of values 0, 1, ....,
+one value in turn for each name declared in the same declaration.
+It can appear in more complex expressions:
+.P1
+ M1, M2, M4, M8: con 1 << iota;
+ N1, N3, N5, N7: con (2*iota)+1;
+.P2
+The first example generates a set of bitmask values; the second generates a
+sequence of odd numbers.
+.LP
+Given the declarations of
+.CW "IN"
+and
+.CW "OUT" ,
+the line
+.P1
+ state := OUT;
+.P2
+declares
+.CW "state"
+to be an integer with initial value zero.
+.LP
+The line
+.P1
+ buf := array[1] of byte;
+.P2
+declares
+.CW "buf"
+to be a one-element array of
+.CW "byte" s.
+Arrays are indexed from zero, so
+.CW "buf[0]"
+is the only element.
+Arrays in Limbo are dynamic, so this array is created at
+the point of the declaration.
+An alternative would be to declare the array and
+create it in separate statements:
+.P1
+ buf : array of byte; # no size at declaration
+
+ buf = array[1] of byte; # size needed at creation
+.P2
+.LP
+Limbo does no automatic coercions between types,
+so an explicit coercion is required to convert the
+single byte read from
+.CW "stdin"
+into an
+.CW "int"
+that can be used in subsequent comparisons with
+.CW "int" 's;
+this is done by the line
+.P1
+ c := int buf[0];
+.P2
+which declares
+.CW "c"
+and assigns the integer value of the input byte to it.
+.NH 2
+Word Count Version 2
+.LP
+The word count program above tacitly assumes that its input is
+in the ASCII subset of Unicode, since it reads
+input one byte at a time instead of one Unicode character
+at a time.
+If the input contains any multi-byte Unicode characters,
+this code is plain wrong.
+The assignment to
+.CW "c"
+is a specific example: the integer value of the first byte
+of a multi-byte Unicode character is not the character.
+.LP
+There are several ways to address this shortcoming.
+Among the possibilities are
+rewriting to use the
+.CW "Bufio"
+module, which does string I/O,
+or checking each input byte sequence to see if it is
+a multi-byte character.
+The second version of word counting uses
+.CW "Bufio" .
+This example will also illustrate rules for accessing objects
+within modules.
+.P1
+# declarations omitted...
+
+include "bufio.m";
+ bufio: Bufio;
+ Iobuf: import bufio;
+
+init(nil: ref Draw->Context, nil: list of string)
+{
+ sys = load Sys Sys->PATH;
+ bufio = load Bufio Bufio->PATH;
+ if (bufio == nil) {
+ sys->fprint(sys->fildes(2), "wc: can't load %s: %r\en", Bufio->PATH);
+ raise "fail:load";
+ }
+
+ stdin := sys->fildes(0);
+ iob := bufio->fopen(stdin, bufio->OREAD);
+ if (iob == nil) {
+ sys->fprint(sys->fildes(2), "wc: can't open stdin: %r\en");
+ raise "fail:open";
+ }
+
+ OUT, IN: con iota;
+
+ state := OUT;
+ nl := big 0; nw := big 0; nc := big 0;
+ for (;;) {
+ c := iob.getc();
+ if (c == Bufio->EOF)
+ break;
+ nc++;
+ if (c == '\en')
+ nl++;
+ if (c == ' ' || c == '\et' || c == '\en')
+ state = OUT;
+ else if (state == OUT) {
+ state = IN;
+ nw++;
+ }
+ }
+ sys->print("%bd %bd %bd\en", nl, nw, nc);
+}
+.P2
+The lines
+.P1
+include "bufio.m";
+ bufio: Bufio;
+.P2
+include the declarations from
+.CW "bufio.m"
+and declare a variable
+.CW "bufio"
+that will serve as a handle when we load an implementation of the
+.CW "Bufio"
+module.
+(The use of a module's type in lower case as the name of a loaded instance is a common convention in Limbo programs.)
+With this handle, we can
+refer to the functions and types
+the module defines, which are in the file
+.CW "/usr/inferno/module/bufio.m"
+(the full name might be different on your system).
+Parts of this declaration are shown here:
+.P1
+Bufio: module # edited to fit your screen
+{
+ PATH: con "/dis/bufio.dis";
+ EOF: con -1;
+ Iobuf: adt {
+ fd: ref Sys->FD; # the file
+ buffer: array of byte; # the buffer
+ # other variables omitted
+ getc: fn(b: self ref Iobuf) : int;
+ gets: fn(b: self ref Iobuf, sep: int) : string;
+ close: fn(b: self ref Iobuf);
+ };
+ open: fn(name: string, mode: int) : ref Iobuf;
+ fopen: fn(fd: ref Sys->FD, mode: int) : ref Iobuf;
+};
+.P2
+.LP
+The
+.CW "bufio"
+module defines
+.CW "open"
+and
+.CW "fopen"
+functions that return references to an
+.CW "Iobuf" ;
+this is much like a
+.CW "FILE*"
+in the C standard I/O library.
+A reference is necessary so that all uses
+refer to the same entity, the object maintained by the module.
+.LP
+Given the name of a module (e.g.,
+.CW "Bufio" ),
+how do we refer to its contents?
+It is always possible to use fully-qualified names,
+and the
+.CW "import"
+statement permits certain abbreviations.
+We must also distinguish between the name of the module itself
+and a specific implementation returned by
+.CW "load" ,
+such as
+.CW "bufio" .
+.LP
+The fully-qualified name of a type or constant from a module
+is
+.P1
+\fIModulename\fP->\fIname\fP
+.P2
+as in
+.CW "Bufio->Iobuf"
+or
+.CW "Bufio->EOF" .
+To refer to members of an adt or functions or variables from a module, however,
+it is necessary to use a module value instead of a module name:
+although the interface
+is always the same, the implementations of different instances
+of a module will be different, and we must refer to a specific
+implementation.
+A fully-qualified name is
+.P1
+\fImoduleval\fP->\fIfunctionname\fP
+\fImoduleval\fP->\fIvariablename\fP
+\fImoduleval\fP->\fIadtname\fP.\fImembername\fP
+.P2
+where adt members can be variables or functions.
+Thus:
+.P1
+iob: ref bufio->Iobuf;
+...
+bufio->open(...)
+bufio->iob.getc()
+bufio->iob.fd
+.P2
+It is also legal to refer to module types, constants, and variables
+with a module handle, as in
+.CW "bufio->EOF" .
+.LP
+An
+.CW "import"
+statement makes a specific list of names from
+a module accessible without need for a fully-qualified name.
+Each name must be imported explicitly, and adt member names
+can not be imported.
+Thus, the line
+.P1
+Iobuf: import bufio;
+.P2
+imports the adt name
+.CW "Iobuf" ,
+which means that functions within that adt (like
+.CW "getc)"
+can be used
+without module qualification, i.e., without
+.CW "bufio->" .
+(It is still necessary to say
+.CW "iob.getc()"
+for reasons given below.)
+In all cases, imported names must be unique.
+.LP
+The second parameter of
+.CW "load"
+is a string giving the location of the module implementation,
+typically a
+.CW ".dis"
+file.
+(The string need not be static.)
+Some modules are part of the system;
+these have location names that begin with
+.CW "$"
+but are otherwise the same for users.
+By convention, modules include a constant called
+.CW "PATH"
+that points to their default location.
+.LP
+The call to
+.CW "bufio->fopen"
+attaches the I/O buffer to the already open file
+.CW "stdin" ;
+this is rather like
+.CW "freopen"
+in
+.CW "stdio" .
+.LP
+The function
+.CW "iob.getc"
+returns the next Unicode character,
+or
+.CW "bufio->EOF"
+if end of file was encountered.
+.LP
+A close look at the calls to
+.CW "sys->print"
+shows a new format conversion character,
+.CW "%r" ,
+for which there is no corresponding argument in the
+expression list.
+The value of
+.CW "%r"
+is the text of the most recent system error message.
+.LP
+Several other small changes were made as realistic examples:
+it keeps the counts as
+.CW big
+to cope with larger files (hence the use of
+.CW %bd
+as the output format);
+it prints diagnostics on the standard error stream,
+.CW sys->fildes(2) ,
+using
+.CW sys->fprint ,
+a variant of
+.CW sys->print
+that takes an explicit file descriptor;
+and it returns an error status to its caller (typically the shell) by
+raising an exception.
+.NH 2
+An Associative Array Module
+.LP
+This section describes a module that implements a conventional
+associative array (a hash table
+pointing to chained lists of name-value strings).
+This module is meant to be part of a larger program,
+not a standalone program like the previous examples.
+.LP
+The
+.CW "Hashtab"
+module stores a name-value pair as a tuple of
+.CW "(string,"
+.CW "string)" .
+A tuple is a type consisting of an ordered collection
+of objects, each with its own type.
+The hash table implementation uses several different tuples.
+.LP
+The hash table module defines a type to hold the
+data, using an
+.CW "adt"
+declaration.
+An adt defines a type and optionally a set of functions
+that manipulate an object of that type.
+Since it provides only the ability to group variables and functions,
+it is like a really slimmed-down version of a C++ class,
+or a slightly fancier C
+.CW "struct" .
+In particular, an adt does not provide information hiding
+(all member names are visible if the adt itself is visible),
+does not support inheritance,
+and has no constructors, destructors or overloaded method names.
+It is different from C or C++, however: when an adt is declared by a
+.CW module
+declaration, the adt's implementation (the bodies of its functions)
+will be defined by the module's implementation, and there can be more than one.
+To create an instance of an adt,
+.P1
+\fIadtvar\fP := \fIadtname\fP(\fIlist of values for all members, in order\fP);
+\fIadtvar\fP := ref \fIadtname\fP(\fIlist of values for all members, in order\fP);
+.P2
+Technically these are casts, from tuple to adt;
+that is, the adt is created from a tuple that
+specifies all of its members in order.
+.LP
+The
+.CW "Hashtab"
+module contains an
+.CW "adt"
+declaration for a type
+.CW "Table" ;
+the operations are a function
+.CW "alloc"
+for initial allocation
+(in effect a constructor),
+a hash function, and methods to add and look up elements by name.
+Here is the module declaration, which is contained in file
+.CW "hashtab.m" :
+.nr dT 4
+.nr dP \n(dP+1
+.P1
+Hashtab: module
+{
+ PATH: con "/usr/bwk/hashtab.dis"; # temporary name
+
+ Table: adt {
+ tab: array of list of (string, string);
+
+ alloc: fn(n: int) : ref Table;
+
+ hash: fn(ht: self ref Table, name: string) : int;
+ add: fn(ht: self ref Table, name: string, val: string);
+ lookup: fn(ht: self ref Table, name: string) : (int, string);
+ };
+};
+.P2
+.nr dT 8
+.nr dP \n(dP-1
+The implementation is in file
+.CW "hashtab.b" :
+.P1
+implement Hashtab;
+
+include "hashtab.m";
+
+Table.alloc(n: int) : ref Table
+{
+ return ref Table(array[n] of list of (string,string));
+}
+
+Table.hash(ht: self ref Table, s: string) : int
+{
+ h := 0;
+ for (i := 0; i < len s; i++)
+ h = (h << 1) ^ int s[i];
+ h %= len ht.tab;
+ if (h < 0)
+ h += len ht.tab;
+ return h;
+}
+
+Table.add(ht: self ref Table, name: string, val: string)
+{
+ h := ht.hash(name);
+ for (p := ht.tab[h]; p != nil; p = tl p) {
+ (tname, nil) := hd p;
+ if (tname == name) {
+ # illegal: hd p = (tname, val);
+ return;
+ }
+ }
+ ht.tab[h] = (name, val) :: ht.tab[h];
+}
+
+Table.lookup(ht: self ref Table, name: string) : (int, string)
+{
+ h := ht.hash(name);
+ for (p := ht.tab[h]; p != nil; p = tl p) {
+ (tname, tval) := hd p;
+ if (tname == name)
+ return (1, tval);
+ }
+ return (0, "");
+}
+
+.P2
+This is intentionally simple-minded, to focus on the language
+rather than efficiency or flexibility.
+The function
+.CW "Table.alloc"
+creates and returns a
+.CW "Table"
+with a specified size and an array of elements,
+each of which is a list of
+.CW "(string,"
+.CW "string)" .
+.LP
+The
+.CW "hash"
+function is trivial; the only interesting point
+is the
+.CW "len"
+operator, which returns the number of items in a string, array or list.
+For a string,
+.CW "len"
+.CW "s"
+is the number of Unicode characters.
+.LP
+The
+.CW "self"
+declaration says that the first
+argument of every call of this function is implicit, and refers to the
+value itself; this argument does not appear in the actual parameter list at any call site.
+.CW "Self"
+is similar to
+.CW "this"
+in C++.
+.LP
+The
+.CW "lookup"
+function searches down the appropriate list for
+an instance of the
+.CW "name"
+argument.
+If a match is found,
+.CW "lookup"
+returns a tuple consisting of 1 and the value field;
+if no match is found, it returns a tuple of 0 and an empty string.
+These return types match the function return type,
+.CW "(int,"
+.CW "string)" .
+.LP
+The line
+.P1
+ (tname, tval) := hd p;
+.P2
+shows a tuple on the left side of a declaration-assignment.
+This splits the pair of strings referred to by
+.CW "hd"
+.CW "p"
+into components and assigns them to the newly declared variables
+.CW "tname"
+and
+.CW "tval" .
+.LP
+The
+.CW "add"
+function is similar;
+it searches the right list for an instance of
+the name.
+If none is found,
+.P1
+ ht.tab[h] = (name, val) :: ht.tab[h];
+.P2
+combines the name and value into a tuple, then uses
+.CW "::"
+to stick it on the front of the proper list.
+.LP
+The line
+.P1
+ (tname, nil) := hd p;
+.P2
+in the loop body is a less obvious use of a tuple.
+In this case, only the first component, the name,
+is assigned, to a variable
+.CW "tname"
+that is declared here.
+The other component is ``assigned'' to
+.CW "nil" ,
+which causes it to be ignored.
+.LP
+The line
+.P1
+ # illegal: hd p = (tname, val);
+.P2
+is commented out because it's illegal:
+Limbo does not permit the assignment of a new name-value
+to a list element;
+list elements are immutable.
+.LP
+To create a new
+.CW "Table" ,
+add some values, then retrieve one, we can write:
+.P1
+ nvtab = Table.alloc(101); # make a Table
+
+ nvtab.add("Rob", "Pike");
+ nvtab.add("Howard", "Trickey");
+ (p, phil) := nvtab.lookup("Phil");
+ (q, sean) := nvtab.lookup("Sean");
+.P2
+Note that the
+.CW "ref"
+.CW "Table"
+argument does not appear in these calls;
+the
+.CW "self"
+mechanism renders it unnecessary.
+Remember that a module using
+.CW Table
+must
+.CW import
+it from some instance of
+.CW Hashtab ,
+or qualify all references to it by a module value.
+.NH 2
+An AWK-like Input Module
+.LP
+This example presents a simple module based on Awk's input mechanism:
+it reads input a line at a time from a list of of files,
+splits each line into an array of
+.CW "NF+1"
+strings (the original input line and the individual fields), and
+sets
+.CW "NF" ,
+.CW "NR" ,
+and
+.CW "FILENAME" .
+It comes in the usual two parts, a module:
+.P1
+.nr dP \n(dP+1
+.nr dT 4
+Awk: module
+{
+ PATH: con "/usr/bwk/awk.dis";
+
+ init: fn(args: list of string);
+ getline: fn() : array of string;
+ NR: fn() : int;
+ NF: fn() : int;
+ FILENAME: fn() : string;
+};
+.P2
+.nr dP \n(dP-1
+.nr dT 8
+and an implementation:
+.nr dP \n(dP+1
+.nr dT 4
+.P1
+implement Awk;
+
+include "sys.m";
+ sys: Sys;
+include "bufio.m";
+ bufio: Bufio;
+Iobuf: import bufio;
+ iobuf: ref Iobuf;
+
+include "awk.m";
+
+_NR: int;
+_NF: int;
+_FILENAME: string;
+args: list of string;
+
+.P3
+init(av: list of string)
+{
+ args = tl av;
+ if (len args == 0) # no args => stdin
+ args = "-" :: nil;
+
+ sys = load Sys Sys->PATH;
+ bufio = load Bufio Bufio->PATH;
+}
+
+.P3
+getline() : array of string
+{
+ t := array[100] of string;
+ fl: list of string;
+
+ top:
+ while (args != nil) {
+ if (_FILENAME == nil) { # advance to next file
+ _FILENAME = hd args;
+ if (_FILENAME == "-")
+ iobuf = bufio->fopen(sys->fildes(0), bufio->OREAD);
+ else
+ iobuf = bufio->open(_FILENAME, bufio->OREAD);
+ if (iobuf == nil) {
+ sys->fprint(sys->fildes(2), "can't open %s: %r\en", _FILENAME);
+ args = nil;
+ return nil;
+ }
+ }
+
+.P3
+ s := iobuf.gets('\en');
+ if (s == nil) {
+ iobuf.close();
+ _FILENAME = nil;
+ args = tl args;
+ continue top;
+ }
+
+.P3
+ t[0] = s[0:len s - 1];
+ _NR++;
+ (_NF, fl) = sys->tokenize(t[0], " \et\en\er");
+ for (i := 1; fl != nil; fl = tl fl)
+ t[i++] = hd fl;
+ return t[0:i];
+ }
+ return nil;
+}
+
+NR() : int { return _NR; }
+NF() : int { return _NF; }
+FILENAME() : string { return _FILENAME; }
+.P2
+.nr dT 8
+.nr dP \n(dP-1
+Since
+.CW "NR" ,
+.CW "NF"
+and
+.CW "FILENAME"
+should not be modified by users, they
+are accessed as functions; the actual variables have
+related names like
+.CW "_NF" .
+It would also be possible to make them ordinary variables
+in the
+.CW "Awk"
+module, and refer to them via a module value (i.e.,
+.CW awk->NR ).
+.LP
+The
+.CW "tokenize"
+function in the line
+.P1
+ (_NF, fl) = sys->tokenize(t[0], " \et\en\er");
+.P2
+breaks the argument string
+.CW "t[0]"
+into tokens, as separated by the characters of the second argument.
+It returns a tuple consisting of a length and a list
+of tokens.
+Note that this module has an
+.CW "init"
+function that must be called explicitly before
+any of its other functions are called.
+.NH 2
+A Simple Formatter
+.LP
+This program is a simple-minded text formatter, modeled after
+.CW "fmt" ,
+that tests the Awk module:
+.P1
+implement Fmt;
+
+include "sys.m";
+ sys: Sys;
+include "draw.m";
+
+Fmt: module
+{
+ init: fn(nil: ref Draw->Context, args: list of string);
+};
+
+include "awk.m";
+ awk: Awk;
+ getline, NF: import awk;
+
+out: array of string;
+nout: int;
+length: int;
+linelen := 65;
+
+.P3
+init(nil: ref Draw->Context, args: list of string)
+{
+ t: array of string;
+ out = array[100] of string;
+
+ sys = load Sys Sys->PATH;
+ awk = load Awk Awk->PATH;
+ if (awk == nil) {
+ sys->fprint(sys->fildes(2), "fmt: can't load %s: %r\en",
+ Awk->PATH);
+ raise "fail:load";
+ }
+ awk->init(args);
+
+ nout = 0;
+ length = 0;
+ while ((t = getline()) != nil) {
+ nf := NF();
+ if (nf == 0) {
+ printline();
+ sys->print("\en");
+ } else for (i := 1; i <= nf; i++) {
+ if (length + len t[i] > linelen)
+ printline();
+ out[nout++] = t[i];
+ length += len t[i] + 1;
+ }
+ }
+ printline();
+}
+.P3
+printline()
+{
+ if (nout == 0)
+ return;
+ for (i := 0; i < nout-1; i++)
+ sys->print("%s ", out[i]);
+ sys->print("%s\en", out[i]);
+ nout = 0;
+ length = 0;
+}
+.P2
+The functions
+.CW "getline"
+and
+.CW "NF"
+have been imported so their names need no qualification.
+It is more usual Limbo style to use explicit references such as
+.CW sys->read
+or
+.CW Bufio->EOF
+for clarity, and import only adts (and perhaps commonly used constants).
+.NH 2
+Channels and Communications
+.LP
+Another approach to a formatter is to use one process to fetch words and
+pass them to another process that formats and prints them.
+This is easily done with a channel, as in this
+alternative version:
+.P1
+# declarations omitted...
+
+WORD, BREAK, EOF: con iota;
+wds: chan of (int, string);
+
+init(nil: ref Draw->Context, nil: list of string)
+{
+ sys = load Sys Sys->PATH;
+ bufio = load Bufio Bufio->PATH;
+
+ stdin := sys->fildes(0);
+ iob = bufio->fopen(stdin, bufio->OREAD);
+
+ wds = chan of (int, string);
+ spawn getword(wds);
+ putword(wds);
+}
+
+.P3
+getword(wds: chan of (int, string))
+{
+ while ((s := iob.gets('\en')) != nil) {
+ (n, fl) := sys->tokenize(s, " \et\en");
+ if (n == 0)
+ wds <-= (BREAK, "");
+ else for ( ; fl != nil; fl = tl fl)
+ wds <-= (WORD, hd fl);
+ }
+ wds <-= (EOF, "");
+}
+
+.P3
+putword(wds: chan of (int, string))
+{
+ for (length := 0;;) {
+ (wd, s) := <-wds;
+ case wd {
+ BREAK =>
+ sys->print("\en\en");
+ length = 0;
+ WORD =>
+ if (length + len s > 65) {
+ sys->print("\en");
+ length = 0;
+ }
+ sys->print("%s ", s);
+ length += len s + 1;
+ EOF =>
+ sys->print("\en");
+ exit;
+ }
+ }
+}
+.P2
+This omits declarations and error checking in the interest
+of brevity.
+.LP
+The channel passes a tuple of
+.CW "int" , (
+.CW "string" );
+the
+.CW "int"
+indicates what kind of string is present \-
+a real word, a break caused by an empty input line,
+or
+.CW "EOF" .
+.LP
+The
+.CW "spawn"
+statement creates a separate process by calling the specified function;
+except for its own stack,
+this process shares memory with the process that spawned it.
+Any synchronization between processes is handled by channels.
+.LP
+The operator
+.CW "<-="
+sends an expression to a channel;
+the operator
+.CW "<-"
+receives from a channel.
+(Receive is combined here with
+.CW ":="
+to receive a tuple, and assign its elements to newly-declared variables.)
+In this example,
+.CW "getword"
+and
+.CW "putword"
+alternate, because each input word
+is sent immediately on the shared channel,
+and no subsequent word is processed until the previous one has been
+received and printed.
+.LP
+The
+.CW "case"
+statement consists of a list of case values,
+which must be string or numeric constants, followed by
+.CW "=>"
+and associated code.
+The value
+.CW "*"
+(not used here) labels the default.
+Multiple labels can be used, separated by the
+.CW "or"
+operator,
+and ranges of values can appear delimited by
+.CW "to" ,
+as in
+.P1
+ 'a' to 'z' or 'A' to 'Z' =>
+.P2
+Remember that control does not flow from one case arm to the next, unlike C,
+thus no
+.CW break
+statements appear.
+.NH 2
+Tk and Interface Construction
+.LP
+Inferno supports a rather complete implementation of
+the Tk interface toolkit developed by John Ousterhout.
+In other environments, Tk is normally accessed from
+Tcl programs, although there are also versions for Perl,
+Scheme and other languages that call Ousterhout's C code.
+The Inferno Tk was implemented from scratch, and is meant to be called
+from Limbo programs.
+As we saw earlier,
+there is a module declaration
+.CW "tk.m"
+and a kernel module
+.CW "Tk" .
+.LP
+The
+.CW "Tk"
+module provides all the widgets of the original Tk
+with almost all their options,
+the
+.CW "pack"
+command for geometry management,
+and the
+.CW "bind"
+command for attaching code to user actions.
+It also provides a
+.CW grid
+command to simplify the common case of objects arranged in a matrix or grid.
+In this implementation
+.CW "Tk"
+commands are
+written as strings and presented to one function,
+.CW "tk->cmd" ;
+Limbo calls this function and captures
+its return value, which is the string that the Tk command produces.
+For example, widget creation commands like
+.CW "button"
+return the widget name, so this will be the string
+returned by
+.CW "tk->cmd" .
+.LP
+There is one unconventional aspect:
+the use of channels to send data and events from the interface
+into the Limbo program.
+To create a widget, as we saw earlier, one writes
+.P1
+tk->cmd("button .b -text {Push me} -command {send cmd .bpush}");
+.P2
+to create a button
+.CW ".b"
+and attach a command to be executed when the button is pushed.
+That command sends
+the (arbitrary) string
+.CW ".bpush"
+on the channel named
+.CW "cmd" .
+The Limbo code that reads from this channel will look
+for the string
+.CW ".bpush"
+and act accordingly.
+The function
+.CW "tk->namechan"
+establishes a correspondence between a Limbo channel value
+and a channel named as a string in the Tk module.
+When an event occurs in a Tk widget with a
+.CW "-command"
+option,
+.CW "send"
+causes the string to be sent on the channel and the Limbo code
+can act on it.
+The program will often use a
+.CW "case"
+to process the strings that might appear on the channel,
+particularly when the same channel is used for several widgets.
+.LP
+We observed earlier that
+.CW Tk
+provides a user interface for an application's window,
+but there might be many windows on the screen.
+Normally, a graphical application is meant to run under
+the window manager
+.CW "wm"
+as a window that can be managed,
+reshaped, etc.
+This is done by calling functions in the module
+.CW "Tkclient" ,
+which provides the interface between
+.CW Tk
+and
+.CW wm .
+.LP
+Several functions must be called to create a window,
+put it on the screen, and start giving it input.
+We have already seen
+.CW Tkclient 's
+.CW toplevel
+for window creation and
+.CW onscreen
+to give a window space on the screen.
+Input arrives from several sources:
+from the mouse and keyboard, from the
+higher-level Tk widgets such as buttons,
+and from the window manager itself.
+In Limbo, each input source is represented by a channel, either given to the program
+by the window manager, or associated with one by
+.CW namechan ,
+as above.
+.LP
+This is all illustrated in the complete program below, which
+implements a trivial version of Etch-a-Sketch, shown in action in Figure 2.
+.FG "f3.ps" 4.8i
+.ce
+.I "Figure 2. Etch-a-Sketch display."
+.fg
+.nr dT 4
+.nr dP \n(dP+1
+.P1
+implement Etch;
+
+include "sys.m";
+ sys: Sys;
+include "draw.m";
+include "tk.m";
+ tk: Tk;
+include "tkclient.m";
+ tkclient: Tkclient;
+
+Etch: module
+{
+ init: fn(ctxt: ref Draw->Context, args: list of string);
+};
+.P3
+init(ctxt: ref Draw->Context, nil: list of string)
+{
+ sys = load Sys Sys->PATH;
+ tk = load Tk Tk->PATH;
+ tkclient = load Tkclient Tkclient->PATH;
+
+ tkclient->init();
+
+ (t, winctl) := tkclient->toplevel(ctxt, nil, "Etch", Tkclient->Appl);
+
+ cmd := chan of string;
+ tk->namechan(t, cmd, "cmd");
+ tk->cmd(t, "canvas .c -height 400 -width 600 -background white");
+ tk->cmd(t, "frame .f");
+ tk->cmd(t, "button .f.c -text {Clear} -command {send cmd clear}");
+ tk->cmd(t, "button .f.d -text {Done} -command {send cmd quit}");
+ tk->cmd(t, "pack .f.c .f.d -side left -fill x -expand 1");
+ tk->cmd(t, "pack .c .f -side top -fill x");
+ tk->cmd(t, "bind .c <ButtonPress-1> {send cmd b1down %x %y}");
+ tk->cmd(t, "bind .c <Button-1-Motion> {send cmd b1motion %x %y}");
+ tk->cmd(t, "update");
+
+ tkclient->startinput(t, "ptr" :: "kbd" :: nil);
+ tkclient->onscreen(t, nil);
+
+ lastx, lasty: int;
+ for (;;) {
+ alt {
+ s := <-cmd =>
+ (nil, cmdstr) := sys->tokenize(s, " \et\en");
+ case hd cmdstr {
+ "quit" =>
+ exit;
+ "clear" =>
+ tk->cmd(t, ".c delete all; update");
+ "b1down" =>
+ lastx = int hd tl cmdstr;
+ lasty = int hd tl tl cmdstr;
+ cstr := sys->sprint(".c create line %d %d %d %d -width 2",
+ lastx, lasty, lastx, lasty);
+ tk->cmd(t, cstr);
+ "b1motion" =>
+ x := int hd tl cmdstr;
+ y := int hd tl tl cmdstr;
+ cstr := sys->sprint(".c create line %d %d %d %d -width 2",
+ lastx, lasty, x, y);
+ tk->cmd(t, cstr);
+ lastx = x; lasty = y;
+ }
+
+ p := <-t.ctxt.ptr =>
+ tk->pointer(t, *p);
+
+ c := <-t.ctxt.kbd =>
+ tk->keyboard(t, c);
+
+ ctl := <-winctl or
+ ctl = <-t.ctxt.ctl or
+ ctl = <-t.wreq =>
+ tkclient->wmctl(t, ctl);
+ }
+ tk->cmd(t, "update");
+ }
+}
+.P2
+.nr dT 8
+.nr dP \n(dP-1
+.LP
+The function
+.CW "toplevel"
+returns a tuple containing the
+.CW Tk->Toplevel
+for the new window and a channel upon which the
+window manager will send messages for events such as
+hitting the exit button.
+An earlier example assigned the channel value to
+.CW nil ,
+discarding it; here it is assigned the name
+.CW winctl .
+The parameters to
+.CW toplevel
+includes a graphics context
+.CW ctxt
+where the window will be created,
+a configuration string (simply
+.CW nil
+here),
+the program name (which appears in the window's ``title bar'' if it has one),
+and a value
+.CW Tkclient->Appl
+that denotes a style of window suitable for most applications.
+Note that
+.CW ctxt
+was one of the arguments to
+.CW init .
+(We do not use the argument list for
+.CW init ,
+and so declare it as
+.CW nil ).
+.LP
+The program creates a canvas for drawing,
+a button to clear the canvas, and a button to quit.
+The sequence of calls to
+.CW "tk->cmd"
+creates the picture and sets up the bindings.
+The buttons are created with a
+.CW -command
+to send a suitable string on channel
+.CW cmd ,
+and two
+.CW bind
+commands make the same channel the target
+for messages about mouse button presses and movement in the canvas.
+Note the
+.CW %x
+and
+.CW %y
+parameters in the latter case to include the mouse's coordinates in the string.
+.LP
+The window manager sends keyboard and mouse input
+to the currently selected window using two more channels
+.CW t.ctxt.kbd
+and
+.CW t.ctxt.ptr .
+A further channel
+.CW t.wreq
+is used by the
+.CW Tk
+module itself to request changes to the window displaying
+.CW Toplevel
+.CW t .
+.LP
+Now there are many channels watching events:
+one for the buttons and canvas created by the drawing program
+itself, one for the mouse,
+and three for window management.
+We use an
+.CW "alt"
+statement to select from events on any of those channels.
+The expression
+.P1
+s := <-cmd
+.P2
+declares a variable
+.CW "s"
+of the type carried by the channel
+.CW "cmd" ,
+i.e., a
+.CW "string" ;
+when a string is received on the channel, the assignment is executed,
+and the subsequent
+.CW case
+decodes the message.
+The channel
+.CW t.ctxt.ptr
+carries references to
+.CW Draw->Pointer
+values, which give the state and position of the pointing device
+(mouse or stylus).
+They are handed as received to
+.CW tk->pointer
+for processing by Tk.
+Similarly, Unicode characters from the keyboard are given to Tk using
+.CW tk->keyboard .
+Internally, Tk hands those values on to the various widgets for processing, possibly
+resulting in messages being sent on one of the other channels.
+Finally, a value received from any of the
+.CW "winctl" ,
+.CW t.ctxt.ctl
+or
+.CW t.wreq
+channels is passed back to
+.CW Tkclient 's
+.CW "wmctl"
+function to be handled there.
+.LP
+As another example,
+here is the startup code for an implementation of
+Othello, adapted from a Java version
+by Muffy Barkocy, Arthur van Hoff, and Ben Fry.
+.nr dT 4
+.nr dP \n(dP+1
+.P1
+init(ctxt: ref Draw->Context, args: list of string)
+{
+ sys = load Sys Sys->PATH;
+ tk = load Tk Tk->PATH;
+ tkclient = load Tkclient Tkclient->PATH;
+
+ sys->pctl(Sys->NEWPGRP, nil);
+
+ tkclient->init();
+.P3
+ (t, winctl) := tkclient->toplevel(ctxt, nil, "Othello", Tkclient->Appl);
+.P3
+ cmd := chan of string;
+ tk->namechan(t, cmd, "cmd");
+ tk->cmd(t, "canvas .c -height 400 -width 400 -background green");
+ tk->cmd(t, "frame .f");
+ tk->cmd(t, "label .f.l -text {Othello?} -background white");
+ tk->cmd(t, "button .f.c -text {Reset} -command {send cmd Reset}");
+ tk->cmd(t, "button .f.d -text {Quit} -command {send cmd Quit}");
+ tk->cmd(t, "pack .f.l .f.c .f.d -side left -fill x -expand 1");
+ tk->cmd(t, "pack .c .f -side top -fill x");
+ tk->cmd(t, "bind .c <ButtonRelease-1> {send cmd B1up %x %y}");
+
+ for (i := 1; i < 9; i++)
+ for (j := 1; j < 9; j++) {
+ coord := sys->sprint("%d %d %d %d",
+ SQ*i, SQ*j, SQ*(i+1), SQ*(j+1));
+ tk->cmd(t, ".c create rectangle " + coord +
+ " -outline black -width 2");
+ }
+ tk->cmd(t, "update");
+ lasterror(t, "init");
+ tkclient->startinput(t, "ptr" :: "kbd" :: nil);
+ tkclient->onscreen(t, nil);
+
+ board = array[10] of {* => array[10] of int};
+ score = array[10] of {* => array[10] of int};
+ reinit();
+.P3
+ for (;;) {
+ alt {
+ s := <- cmd =>
+ (n, l) := sys->tokenize(s, " \et");
+ case hd l {
+ "Quit" =>
+ exit;
+ "Reset" =>
+ reinit();
+ "B1up" =>
+ x := int hd tl l;
+ y := int hd tl tl l;
+ mouseUp(int x, int y);
+ }
+
+ p := <-t.ctxt.ptr =>
+ tk->pointer(t, *p);
+
+ c := <-t.ctxt.kbd =>
+ tk->keyboard(t, c);
+
+ ctl := <-winctl or
+ ctl = <-t.ctxt.ctl or
+ ctl = <-t.wreq =>
+ tkclient->wmctl(t, ctl);
+ }
+ }
+}
+.P2
+.nr dP \n(dP-1
+.nr dT 4
+.FG "f2.ps" 4.8i
+.ce
+.I "Figure 3. Screen shot of Inferno display showing Othello window."
+.fg
+.LP
+If some call to the
+.CW "Tk"
+module results in an error,
+an error string is made available in a pseudo-variable
+.CW "lasterror"
+maintained by
+.CW "Tk" .
+When this variable is read, it is reset.
+The function
+.CW "lasterror"
+shows how to test and print this variable:
+.P1
+lasterror(t: ref Tk->Toplevel, where: string)
+{
+ s := tk->cmd(t, "variable lasterror");
+ if (s != nil)
+ sys->print("%s: tk error %s\en", where, s);
+}
+.P2
+In general, the Inferno implementation of
+.CW "Tk"
+does not provide variables except for a few special ones like this.
+The most common instance is a variable that links
+a set of radiobuttons.
+.NH 2
+Acknowledgements
+.LP
+I am very grateful to
+Steven Breitstein,
+Ken Clarkson,
+Sean Dorward,
+Eric Grosse,
+Doug McIlroy,
+Rob Pike,
+Jon Riecke,
+Dennis Ritchie,
+Howard Trickey,
+Phil Winterbottom,
+and
+Margaret Wright
+for explaining mysteries of Limbo and Inferno
+and for valuable suggestions on this paper.
binary files /dev/null b/doc/descent/descent.pdf differ
--- /dev/null
+++ b/doc/descent/mkfile
@@ -1,0 +1,15 @@
+<../fonts.pal
+
+descent.pdf:D: descent.ps
+
+descent.ps:D: descent.ms f1.ps f2.ps f3.ps mkfile
+ {echo $FONTS; cat descent.ms} | tbl | troff -mpm -mpictures | dpost >$target
+
+%.ps: %.gif
+ dpost <$stem.gif >$stem.ps
+
+%.ps: %.bit
+ aux/p9bitpost -b100 <$stem.bit >$stem.ps
+
+%.pdf: %.ps
+ ps2pdf <$stem.ps >$stem.pdf
--- /dev/null
+++ b/doc/dev.ms
@@ -1,0 +1,497 @@
+.TL
+Program Development under Inferno
+.AU
+Roger Peppé
+rog@vitanuova.com
+.SH
+Introduction
+.PP
+Inferno provides a set of programs that, used in
+combination, provide a powerful development environment
+in which to write Limbo programs.
+.I Limbo (1)
+is the compiler for the Limbo language; there
+are versions that run inside and outside the Inferno
+environment.
+.I Acme (1)
+is an integrated window system and editor, and the
+preferred source-code editing tool within Inferno.
+The Limbo debugger,
+.I wm-debug (1),
+allows interactive inspection of running Limbo programs.
+.I Stack (1)
+allows a quick inspection of the execution stack of a
+currently running process.
+.SH
+Getting started
+.PP
+This document assumes that you have already managed
+to install Inferno and have managed to obtain an Inferno
+window, running the Inferno window manager,
+.I wm (1).
+The document
+\&``Installing Inferno'' in this volume has details on this.
+If running within emu, it is worth giving Inferno
+as large a window as possible, as it cannot be resized later.
+This paper assumes that you are using a three-button mouse, as it is
+not feasible to use Acme without a three-button mouse.
+(if you have a two button mouse with a ``mouse wheel'',
+the wheel can be used as the middle button).
+The first thing to do is to get Acme going. By clicking
+on the Vita Nuova logo at the bottom left of the window,
+you can display a menu naming some preconfigured commands.
+If this has an ``Acme'' entry, then just clicking on that entry
+will start acme. If not, then click on the ``Shell'' entry,
+and type
+.P1
+acme
+.P2
+to start it up. The Acme window should then appear,
+filling most of the screen (the window manager toolbar
+should still be visible).
+.SH
+Acme basics
+.PP
+For a general overview and the rationale behind Acme, see ``Acme:
+A User Interface for Programmers'', elsewhere in this volume,
+and for detailed documentation, see
+.I acme (1).
+The basics are as follows:
+.PP
+Acme windows are text-only and organised into columns.
+A distinctive feature of Acme is that there are no graphical
+title bars to windows; instead, each window (and additionally
+each column, and the whole Acme window itself) has
+a textual
+.I tag ,
+which can be edited at will, and is initially primed to contain
+a few appropriate commands.
+.PP
+An Acme command is just represented by text; any textual
+command word may be executed simply by clicking with the middle
+mouse button on the word. (See ``Acme mouse commands'', below).
+If Acme recognizes the word that has been clicked on
+as one of its internal commands (e.g. Put, Undo), then it will take the appropriate
+action; otherwise it will run the text as a shell command.
+(See
+.I sh (1)).
+.SH
+Acme mouse commands
+.PP
+Mouse usage within Acme is somewhat more versatile
+than in most other window systems. Each of the three
+mouse buttons has its own action, and there are also
+actions bound to
+.I chords
+of mouse buttons (i.e. mouse buttons depressed simultaneously).
+Mouse buttons are numbered from left (1) to right (3).
+Button 1 follows similar conventions to other window systems -
+it selects text; a double click will select a line if at the beginning or end
+of a line, or match brackets if on a bracket character, or select
+a word otherwise.
+Button 2, as mentioned above, executes an
+Acme command; a single click with button 2 will execute
+the single word under the click, otherwise the swept text
+will be executed.
+Button 3 is a general ``look'' operator; if the text under the
+click represents a filename, then Acme will open a new
+window for the file and read it in, otherwise it will search
+within the current window for the next occurrence of the
+text.
+Clicking button 2 or button 3 on some text already selected
+by button 1 causes the click to refer exactly to the text
+selected, rather than gathering likely-looking characters
+from around the click as is the default.
+.PP
+There are two mouse chord sequences which are
+commonly used in Acme (and you will find that some
+other programs in the system also recognise these sequences,
+e.g.
+.I wm-sh (1)).
+They are both available once some text
+has been selected by dragging the mouse with button 1,
+but before the button has been released. At this point,
+touching button 2 will delete the selected text and save
+it in Acme's
+.I snarf
+buffer; clicking button 3 replaces the selected text with the contents
+of the snarf buffer. Before button 1 has been released,
+these two buttons reverse each other's actions, so, for
+example, selecting some text with button 1, keeping button 1
+held down, then clicking button 2 and button 3 in succession,
+will save the selected text in the snarf buffer while leaving the
+original intact.
+The following table summarises the mouse commands in
+Acme:
+.KS
+.TS
+center box;
+l l .
+B1 Select text.
+B2 Execute text.
+B3 Open file or search for text.
+B1-B2 Cut text.
+B1-B3 Paste text.
+B2-B3 Cancel the pending B2 action.
+B3-B2 Cancel the pending B3 action.
+.TE
+.ce
+.I "Acme mouse command summary"
+.KE
+
+.SH
+Scrolling and resizing Acme windows
+.PP
+The scroll bars in Acme are somewhat different from
+conventional scroll bars (including the scroll bars found
+in other parts of Inferno). Clicking, or dragging, with
+button-2 on the scrollbar acts the most like the conventional
+behaviour, namely that the further down the scroll bar
+you click, the further down the file you are shown.
+.PP
+True to form, however, Acme doesn't omit to make
+the other buttons useful: button-1 and button-3
+move backwards and forwards through the file respectively.
+The nearer the top of the scrollbar the mouse, the
+slower the movement. Holding one of these buttons
+down on the scrollbar will cause the scrolling motion
+to auto-repeat, so it is easy to scroll gently through the
+entire file, for instance.
+.PP
+The small square at the top left of each Acme window is
+the handle for resizing the window. Dragging this square
+from one place to another (within Acme) will move the
+window to the new place. A single button click in this square
+will grow the window: button 1 grows it a little bit; button 2
+grows it as much as possible without obscuring the other
+window titles in the column; button 3 grows it so it covers
+the whole column (all other windows in the column are
+obscured).
+.SH
+Creating a new file
+.PP
+All Limbo programs are composed of
+.I modules
+and each module is stored in its own file. To write a Limbo
+program, you need to write at least one module,
+the Limbo
+.I "source file" ,
+which will then be compiled into Dis code which can
+then be run by the Inferno Virtual Machine (VM).
+The first step is to decide where to store the file.
+When Acme starts up, it creates a new window containing
+a list of all the files in the directory in which it was started
+(usually your home directory). As a consequence of the
+mouse rules above, a click of button-3 on any of those
+filenames in that window will open a new window
+showing that file or, if it is a directory, a list of the
+files and directories it contains.
+.PP
+An important aspect in Acme's mouse commands, is
+that the command is interpreted
+.I "relative to the window's current directory",
+where the current directory is determined from
+the filename in the window's tag. For instance,
+Acme commands executed in the tag or body of
+a window on the file
+.CW "/usr/joebloggs/myfile.txt"
+would run in the directory
+.CW /usr/joebloggs .
+.PP
+So, to create a new file in Acme, first open the
+directory in which to create the file. (If this is
+your home directory, then it's probably already on the screen;
+otherwise, you can just type (anywhere) the name of
+the directory, and button-3 click on it. If the directory
+does not exist, then no window will be created.
+Then, within the directory's window or its tag,
+choose a name,
+.I filename ,
+for your file (I'll use
+.CW myprog
+from here on,
+for explanatory convenience)
+, type the text:
+.P1
+New \fIfilename\fP.b
+.P2
+select this text (the Escape key can also be used to highlight
+text that you have just typed), and button-2 click on it.
+This should create a new empty window in which you
+can edit your Limbo source file. It will also create a
+window giving a warning that the file does not
+currently exist - you can get rid of this by clicking
+with button-2 on the text
+.CW Del
+in the tag of that window.
+.SH
+Editing the source file
+.PP
+You can now edit text in the new window.
+Type in the following program:
+.P1
+implement Myprog;
+include "sys.m";
+ sys: Sys;
+include "draw.m";
+
+Myprog: module {
+ init: fn(nil: ref Draw->Context, argv: list of string);
+};
+
+init(nil: ref Draw->Context, argv: list of string)
+{
+ sys = load Sys Sys->PATH;
+ sys->print("Hello, world\en");
+}
+.P2
+When typing it in, note that two new commands have appeared
+in the tag of the new window:
+.CW Put
+and
+.CW Undo .
+.CW Put
+saves the file;
+.CW Undo
+undoes the last change to the file, and successive
+executions of
+.CW Undo
+will move further back in time. In case you move
+too far back accidentally, there is also
+.CW Redo ,
+which redoes a change that you have just undone.
+Changes in the body of any window in Acme can be undone
+this way.
+.PP
+Click with button-2 on the
+.CW Put
+command, and the file is now saved and ready to be
+compiled. If you have problems at this point (say
+Acme complains about not being able to write the
+file), you have probably chosen an inappropriate
+directory, one in which you do not have write permission,
+in which to put the file. In this case you can change the
+name of the file simply by editing its name in the window's
+tag, and clicking on
+.CW Put
+again.
+.SH
+Compiling the source file
+.PP
+Now, you are in a position to compile the Limbo program.
+Although you can execute the Limbo compiler directly
+from the tag of the new file's window, it is usually more
+convenient to do it from a shell window. To start a shell
+window, type
+.CW win '' ``
+at the right of the tag of the new file's window, select
+it, and click with button-2 on it.
+A new window should appear showing a shell prompt (usually
+.CW "; " '' ``
+or
+.CW "% " ''). ``
+At this, you can type any of the commands mentioned
+in Section 1 of the Programmer's Manual.
+Note that, following Acme's usual rule, the shell has
+started up in the same directory as the new file;
+typing
+.P1
+lc
+.P2
+at the prompt will show all the files in the directory,
+including hopefully the newly written Limbo file.
+.PP
+Type the following command to the shell:
+.P1
+limbo -g myprog.b
+.P2
+If you typed in the example program correctly,
+then you'll get a short pause, and then another shell
+prompt. This indicates a successful compilation (no
+news is good news), in which case you will now have
+two new files in the current directory,
+.CW myprog.sbl
+and
+.CW myprog.dis .
+The
+.CW -g
+option to the
+.CW limbo
+command directed it to produce the
+.CW myprog.sbl
+file, which contains symbolic information
+relating the source code to the Dis executable file.
+The
+.CW myprog.dis
+file contains the actual executable file.
+At this point, if you type
+.CW lc ,
+to get a listing of the files in the current directory,
+and then click with button-2 on the
+.CW myprog.dis
+file, and you should see the output ``Hello, world''.
+You could also just type
+.CW myprog
+at the shell prompt.
+.PP
+If you are normal, however, the above compilation
+probably failed because of some mistyped characters
+in the source code; and for larger newly created programs,
+in my experience, this
+is almost invariably the case.
+If you got no errors in the above
+compilation, try changing
+.CW sys->print
+to
+.CW print ,
+saving the file again,
+and continue with the next section.
+.SH
+Finding compilation errors
+.PP
+When the Limbo compiler finds errors, it prints
+the errors, one per line, each one looking something
+like the following:
+.P1
+myprog.b:13: print is not declared
+.P2
+This shows the filename where the error has occurred,
+its line number in the file, and a description of the error.
+Acme's button-3 mouse clicking makes it extremely easy
+to see where in the source code the error has occurred.
+Click with button-3 anywhere in the filename on the
+line of the compilation error, and Acme will automatically
+take the cursor to the file of that name and highlight
+the correct line.
+.PP
+If there had been no currently appropriate open Acme
+window representing the file, then a new one would
+be created, and the appropriate line selected.
+.PP
+Edit
+.CW myprog.b
+until you have a program that compiles successfully
+and produces the ``Hello, world'' output.
+For a program as simple as this, that's all there
+is to it - you now know the essential stages involved in
+writing a Limbo program; there's just the small matter
+of absorbing the Limbo language and familiarising
+yourself with the libraries (``The Limbo Programming Language''
+elsewhere in this volume,
+and
+.I intro (2)
+are the two essential starting points here).
+.SH
+Finding run-time errors
+.PP
+For larger programs, there is the problem of programs
+that die unexpectedly with a run-time error. This
+will happen when, for instance, a Limbo program uses a reference
+that has not been initialised, or refers to an out-of-bounds
+array element.
+.PP
+When a Limbo program dies with a run-time exception,
+it does not go away completely, but remains hanging
+around, dormant, in a
+.I broken
+state; the state that it was in when it died may
+now be examined at leisure. To experiment with this,
+edit the Myprog module above to delete the line
+that loads the
+.CW Sys
+module
+.CW "sys = load Sys" ...), (
+and recompile the program.
+.PP
+This time when you come to run
+.CW myprog ,
+it will die, printing a message like:
+.P1
+sh: 319 "Myprog":module not loaded
+.P2
+The number
+.CW 319
+is the
+.I "process id"
+(or just
+.I pid )
+of the broken process. The command
+.CW ps ,
+which shows all currently running processes,
+can be used at this point - you will see a line like this:
+.P1
+ 319 245 rog broken 64K Myprog
+.P2
+The first number is the pid of the process;
+the second is the
+.I "process group"
+id of the process; the third field gives the
+owner of the process; the fourth gives its state
+(broken, in this case); the fifth shows the current
+size of the process, and the last gives the name
+of the module that the process is currently running.
+.PP
+The
+.CW stack
+command can be used to quickly find the line
+at which the process has broken; type:
+.P1
+ stack \fIpid\fP
+.P2
+where
+.I pid
+is the number mentioned in the ``module not loaded''
+message (319 in this case).
+It produces something like the following output:
+.P1
+init() myprog.b:12.1, 29
+unknown fn() Module /dis/sh.dis PC 1706
+.P2
+As usual, a quick button-3 click on the
+.CW myprog.b
+part of the first line takes you to the appropriate
+part of the source file. The reason that the program
+has died here is that, in Limbo, all external modules
+must be explicitly loaded before they can be used; to
+try to call an uninitialised module is an error
+and causes an exception.
+.SH
+More sophisticated debugging
+.PP
+.CW Stack
+is fine for getting a quick summary of the state
+in which a program has died, but there are
+times when such a simple post-mortem analysis
+is inadequate. The
+.CW wm/deb
+(see
+.I wm-deb\fR(1))\fP
+command provides an interactive windowing
+debugger for such occasions.
+It runs outside Acme,
+in the default window system. A convenient way
+to start debugging an existing process is
+to raise
+.CW wm/task
+(``Task Manager'' on the
+main menu), select with the mouse the process
+to debug, and click ``Debug''. This will start
+.CW wm/deb
+on that process. Before it can start, the debugger will ask
+for the names of any source files that it has not been
+able to find (usually this includes the source for
+the shell, as the module being debugged is often
+started by the shell, and so the top-level function will
+be in the shell's module).
+.PP
+.CW Wm/deb
+can be used to debug multiple threads, to inspect
+the data structures in a thread, and to interactively
+step through the running of a thread (single stepping).
+See
+.I wm-deb (1)
+for details.
+
+\" further afield?
+\" other development tools?
+\" tools to come?
binary files /dev/null b/doc/dev.pdf differ
--- /dev/null
+++ b/doc/dis.ms
@@ -1,0 +1,1824 @@
+.so /sys/lib/tmac/tmac.uni
+.TL
+Dis Virtual Machine Specification
+.AU
+.I "Lucent Technologies Inc"
+.I "30 September 1999"
+
+.I "Extensively revised by Vita Nuova Limited"
+.I "5 June 2000, 9 January 2003"
+.NH 1
+Introduction
+.LP
+The Dis virtual machine provides the execution environment for programs running under the Inferno operating system. The virtual machine models a CISC-like, three operand, memory-to-memory architecture. Code can either be interpreted by a C library or compiled on-the-fly into machine code for the target architecture.
+.LP
+This paper defines the virtual machine informally.
+A separate paper by Winterbottom and Pike[2] discusses its design.
+The Dis object file format is also defined here.
+Literals and keywords are in
+.CW typewriter
+typeface.
+.NH 1
+Addressing Modes
+.SH
+Operand Size
+.LP
+Operand sizes are defined as follows: a byte is 8 bits, a word or pointer is 32 bits, a float is 64 bits, a big integer is 64 bits. The operand size of each instruction is encoded explicitly by the operand code. The operand size and type are specified by the last character of the instruction mnemonic:
+.IP
+.TS
+lf(CW) lfR .
+W word, 32-bit two's complement
+B byte, 8-bit unsigned
+F float, 64-bit IEEE format
+L big, 64-bit two's complement
+P pointer
+C Unicode string encoded in UTF-8
+M memory
+MP memory containing pointers
+.TE
+.LP
+Two more operand types are defined to provide `short'
+types for use by languages other than Limbo:
+signed 16-bit integers, called `short word'
+here, and 32-bit IEEE format floating-point numbers, called `short float' or `short real' here.
+Support for them is limited to conversion to and from words or floats respectively;
+the instructions are marked below with a dagger (†).
+.SH
+Memory Organization
+.LP
+Memory for a thread is divided into several separate regions. The code segment stores either a decoded virtual machine instruction stream suitable for execution by the interpreter or flash compiled native machine code for the host CPU. Neither type of code segment is addressable from the instruction set. At the object code level, PC values are offsets, counted in instructions, from the beginning of the code space.
+.LP
+Data memory is a linear array of bytes, addressed using 32-bit pointers. Words are stored in the native representation of the host CPU. Data types larger than a byte must be stored at addresses aligned to
+a multiple of the data size. A thread executing a module has access to two regions of addressable data memory. A module pointer
+.CW "mp" \& (
+register) defines a region of global storage for a particular module, a frame pointer
+.CW "fp" \& (
+register) defines the current activation record or frame for the thread. Frames are allocated dynamically from a stack by function call and return instructions. The stack is extended automatically from the heap.
+.LP
+The
+.CW mp
+and
+.CW fp
+registers cannot be addressed directly, and therefore, can be modified only by call and return instructions.
+.SH
+Effective Addresses
+.LP
+Each instruction can potentially address three operands. The source and destination operands are general, but the middle operand can use any address mode except double indirect. If the middle operand of a three address instruction is omitted, it is assumed to be the same as the destination operand.
+.LP
+The general operands generate an effective address from three basic modes: immediate, indirect and double indirect. The assembler syntax for each mode is:
+.IP
+.TS
+lf(CW) lfR .
+10(fp) 30-bit signed indirect from fp
+20(mp) 30-bit signed indirect from mp
+$0x123 30-bit signed immediate value
+10(20(fp)) two 16-bit unsigned offsets double indirect from fp
+10(20(mp)) two 16-bit unsigned offsets double indirect from mp
+.TE
+.SH
+Garbage Collection
+.LP
+The Dis machine performs both reference counted and real time mark and sweep garbage collection. This hyrbrid approach allows code to be generated in several styles: pure reference counted, mark and sweep, or a hybrid of the two approaches. Compiler writers have the freedom to choose how specific types are handled by the machine to optimize code for performance or language implementation. Instruction selection determines which algorithm will be applied to specific types.
+.LP
+When using reference counting, pointers are a special operand type and should only be manipulated using the pointer instructions in order to ensure the correct functioning of the garbage collector. Every memory location that stores a pointer must be known to the interpreter so that it can be initialized and deallocated correctly. The information is transmitted in the form of type descriptors in the object module. Each type descriptor contains a bit vector for a particular type where each bit corresponds to a word in memory. Type descriptors are generated automatically by the Limbo compiler. The assembler syntax for a type descriptor is:
+.P1
+desc $10, 132, "001F"
+.P2
+The first parameter is the descriptor number, the second is the size in bytes, and the third a pointer map. The map contains a list of hex bytes where each byte maps eight 32 bit words. The most significant bit represents the lowest memory address.
+A one bit indicates a pointer in memory. The map need not have an entry for every byte and unspecified bytes are assumed zero.
+.LP
+Throughout this description, the symbolic constant
+.CW H
+refers to a nil pointer.
+.NH 1
+Instruction Set
+.SH
+add\fIx\fP \- Add
+.P1
+Syntax: addb src1, src2, dst
+ addf src1, src2, dst
+ addw src1, src2, dst
+ addl src1, src2, dst
+Function: dst = src1 + src2
+.P2
+.LP
+The
+.CW "add"
+instructions compute the sum of the operands addressed by
+.CW "src1"
+and
+.CW "src2"
+and stores the result in the
+.CW " dst"
+operand. For
+.CW "addb"
+the result is truncated to eight bits.
+.SH
+addc \- Add strings
+.P1
+Syntax: addc src1, src2, dst
+Function: dst = src1 + src2
+.P2
+.LP
+The
+.CW "addc"
+instruction concatenates the two UTF strings pointed to by
+.CW " src1"
+and
+.CW "src2" ;
+the result is placed in the pointer addressed by
+.CW "dst" .
+If both pointers are
+.CW "H"
+the result will be a zero length string rather than
+.CW "H" .
+.SH
+alt \- Alternate between communications
+.P1
+Syntax: alt src, dst
+.P2
+The
+.CW "alt"
+instruction selects between a set of channels ready to communicate. The
+.CW src
+argument is the address of a structure of the following form:
+.P1
+struct Alt {
+ int nsend; /* Number of senders */
+ int nrecv; /* Number of receivers */
+ struct {
+ Channel* c; /* Channel */
+ void* val; /* Address of lval/rval */
+ } entry[];
+};
+.P2
+The vector is divided into two sections; the first lists the channels ready to send values, the second lists channels either ready to receive or an array of channels each of which may be ready to receive. The counts of the sender and receiver channels are stored as the first and second words addressed by
+.CW src .
+An
+.CW "alt"
+instruction proceeds by testing each channel for readiness to communicate. A ready channel is added to a list. If the list is empty after each channel has been considered, the thread blocks at the
+.CW "alt"
+instruction waiting for a channel to become ready; otherwise, a channel is picked at random from the ready set.
+.LP
+The
+.CW "alt"
+instruction then uses the selected channel to perform the communication using the
+.CW "val"
+address as either a source for send or a destination for receive. The numeric index of the selected vector element is placed in
+.CW "dst" .
+.SH
+and\fIx\fP \- Logical AND
+.P1
+Syntax: andb src1, src2, dst
+ andw src1, src2, dst
+ andl src1, src2, dst
+Function: dst = src1 & src2
+.P2
+The instructions compute the bitwise AND of the two operands addressed by
+.CW "src1"
+and
+.CW "src2"
+and stores the result in the
+.CW "dst"
+operand.
+.SH
+beq\fIx\fP \- Branch equal
+.P1
+Syntax: beqb src1, src2, dst
+ beqc src1, src2, dst
+ beqf src1, src2, dst
+ beqw src1, src2, dst
+ beql src1, src2, dst
+Function: if src1 == src2 then pc = dst
+.P2
+If the
+.CW "src1"
+operand is equal to the
+.CW "src2"
+operand, then control is transferred to the program counter specified by the
+.CW "dst"
+operand.
+.SH
+bge\fIx\fP \- Branch greater or equal
+.P1
+Syntax: bgeb src1, src2, dst
+ bgec src1, src2, dst
+ bgef src1, src2, dst
+ bgew src1, src2, dst
+ bgel src1, src2, dst
+Function: if src1 >= src2 then pc = dst
+.P2
+If the
+.CW "src1"
+operand is greater than or equal to the
+.CW "src2"
+operand, then control is transferred to program counter specified by the
+.CW "dst"
+operand. This instruction performs a signed comparison.
+.SH
+bgt\fIx\fP \- Branch greater
+.P1
+Syntax: bgtb src1, src2, dst
+ bgtc src1, src2, dst
+ bgtf src1, src2, dst
+ bgtw src1, src2, dst
+ bgtl src1, src2, dst
+Function: if src1 > src2 then pc = dst
+.P2
+If the
+.CW "src1"
+operand is greater than the
+.CW "src2"
+operand, then control is transferred to the program counter specified by the
+.CW "dst"
+operand. This instruction performs a signed comparison.
+.SH
+ble\fIx\fP \- Branch less than or equal
+.P1
+Syntax: bleb src1, src2, dst
+ blec src1, src2, dst
+ blef src1, src2, dst
+ blew src1, src2, dst
+ blel src1, src2, dst
+Function: if src1 <= src2 then pc = dst
+.P2
+If the
+.CW "src1"
+operand is less than or equal to the
+.CW "src2"
+operand, then control is transferred to the program counter specified by the
+.CW "dst"
+operand. This instruction performs a signed comparison.
+.SH
+blt\fIx\fP \- Branch less than
+.P1
+Syntax: bltb src1, src2, dst
+ bltc src1, src2, dst
+ bltf src1, src2, dst
+ bltw src1, src2, dst
+ bltl src1, src2, dst
+Function: if src1 < src2 then pc = dst
+.P2
+If the
+.CW "src1"
+operand is less than the
+.CW "src2"
+operand, then control is transferred to the program counter specified by the
+.CW "dst"
+operand.
+.SH
+bne\fIx\fP \- Branch not equal
+.P1
+Syntax: bneb src1, src2, dst
+ bnec src1, src2, dst
+ bnef src1, src2, dst
+ bnew src1, src2, dst
+ bnel src1, src2, dst
+Function: if src1 != src2 then pc = dst
+.P2
+If the
+.CW "src1"
+operand is not equal to the
+.CW "src2"
+operand, then control is transferred to the program counter specified by the
+.CW "dst"
+operand.
+.SH
+call \- Call local function
+.P1
+Syntax: call src, dst
+Function: link(src) = pc
+ frame(src) = fp
+ mod(src) = 0
+ fp = src
+ pc = dst
+.P2
+The
+.CW "call"
+instruction performs a function call to a routine in the same module. The
+.CW "src"
+argument specifies a frame created by
+.CW "new" .
+The current value of
+.CW "pc"
+is stored in link(src), the current value of
+.CW "fp"
+is stored in frame(src) and the module link register is set to 0. The value of
+.CW "fp"
+is then set to
+.CW "src"
+and control is transferred to the program counter specified by
+.CW dst .
+.SH
+case \- Case compare integer and branch
+.P1
+Syntax: case src, dst
+Function: pc = 0..i: dst[i].pc where
+ dst[i].lo >= src && dst[i].hi < src
+.P2
+The
+.CW "case"
+instruction jumps to a new location specified by a range of values. The
+.CW "dst"
+operand points to a table in memory containing a table of
+.CW "i"
+values. Each value is three words long: the first word specifies a low value, the second word specifies a high value, and the third word specifies a program counter. The first word of the table gives the number of entries. The
+.CW "case"
+instruction searches the table for the first matching value where the
+.CW "src"
+operand is greater than or equal to the low word and less than the high word. Control is transferred to the program counter stored in the first word of the matching entry.
+.SH
+casec \- Case compare string and branch
+.P1
+Syntax: casec src, dst
+Function: pc = 0..i: dst[i].pc where
+ dst[i].lo >= src && dst[i].hi < src
+.P2
+The
+.CW "casec"
+instruction jumps to a new location specified by a range of string constants. The table is the same as described for the
+.CW case
+instruction.
+.SH
+cons\fIx\fP \- Allocate new list element
+.P1
+Syntax: consb src, dst
+ consc src, dst
+ consf src, dst
+ consl src, dst
+ consm src, dst
+ consmp src, dst
+ consp src, dst
+ consw src, dst
+Function: p = new(src, dst)
+ dst = p
+.P2
+The
+.CW "cons"
+instructions add a new element to the head of a list. A new list element is composed from the
+.CW "src"
+operand and a pointer to the head of an extant list specified by
+.CW "dst" .
+The resulting element is stored back into
+.CW "dst" .
+.SH
+cvtac \- Convert byte array to string
+.P1
+Syntax: cvtac src, dst
+Function: dst = string(src)
+.P2
+The
+.CW "src"
+operand must be an array of bytes, which is converted into a character string and stored in
+.CW "dst" .
+The new string is a copy of the bytes in
+.CW "src" .
+.SH
+cvtbw \- Convert byte to word
+.P1
+Syntax: cvtbw src, dst
+Function: dst = src & 0xff
+.P2
+A byte is fetched from the
+.CW "src"
+operand extended to the size of a word and then stored into
+.CW "dst" .
+.SH
+cvtca \- Convert string to byte array
+.P1
+Syntax: cvtca src, dst
+Function: dst = array(src)
+.P2
+The
+.CW "src"
+operand must be a string which is converted into an array of bytes and stored in
+.CW "dst" .
+The new array is a copy of the characters in src.
+.SH
+cvtcf \- Convert string to real
+.P1
+Syntax: cvtcf src, dst
+Function: dst = (float)src
+.P2
+The string addressed by the
+.CW "src"
+operand is converted to a floating point value and stored in the
+.CW "dst"
+operand. Initial white space is ignored; conversion ceases at the first character in the string that is not part of the representation of the floating point value.
+.SH
+cvtcl \- Convert string to big
+.P1
+Syntax: cvtcl src, dst
+Function: dst = (big)src
+.P2
+The string addressed by the
+.CW "src"
+operand is converted to a big integer and stored in the
+.CW "dst"
+operand. Initial white space is ignored; conversion ceases at the first non-digit in the string.
+.SH
+cvtcw \- Convert string to word
+.P1
+Syntax: cvtcw src, dst
+Function: dst = (int)src
+.P2
+The string addressed by the
+.CW "src"
+operand is converted to a word and stored in the
+.CW "dst"
+operand. Initial white space is ignored; after a possible sign, conversion ceases at the first non-digit in the string.
+.SH
+cvtfc \- Convert real to string
+.P1
+Syntax: cvtfc src, dst
+Function: dst = string(src)
+.P2
+The floating point value addressed by the
+.CW "src"
+operand is converted to a string and stored in the
+.CW "dst"
+operand. The string is a floating point representation of the value.
+.SH
+cvtfw \- Convert real to word
+.P1
+Syntax: cvtfw src, dst
+Function: dst = (int)src
+.P2
+The floating point value addressed by
+.CW "src"
+is converted into a word and stored into
+.CW "dst" .
+The floating point value is rounded to the nearest integer.
+.SH
+cvtfl \- Convert real to big
+.P1
+Syntax: cvtfl src, dst
+Function: dst = (big)src
+.P2
+The floating point value addressed by
+.CW "src"
+is converted into a big integer and stored into
+.CW "dst" .
+The floating point value is rounded to the nearest integer.
+.SH
+cvtfr \- Convert real to short real†
+.P1
+Syntax: cvtfr src, dst
+Function: dst = (short float)src
+.P2
+The floating point value addressed by
+.CW "src"
+is converted to a short (32-bit) floating point value and stored into
+.CW "dst" .
+The floating point value is rounded to the nearest integer.
+.SH
+cvtlc \- Convert big to string
+.P1
+Syntax: cvtlc src, dst
+Function: dst = string(src)
+.P2
+The big integer addressed by the
+.CW "src"
+operand is converted to a string and stored in the
+.CW "dst"
+operand. The string is the decimal representation of the big integer.
+.SH
+cvtlw \- Convert big to word
+.P1
+Syntax: cvtlw src, dst
+Function: dst = (int)src
+.P2
+The big integer addressed by the
+.CW "src"
+operand is converted to a word and stored in the
+.CW "dst"
+operand.
+.SH
+cvtsw \- Convert short word to word†
+.P1
+Syntax: cvtsw src, dst
+Function: dst = (int)src
+.P2
+The short word addressed by the
+.CW "src"
+operand is converted to a word and stored in the
+.CW "dst"
+operand.
+.SH
+cvtwb \- Convert word to byte
+.P1
+Syntax: cvtwb src, dst
+Function: dst = (byte)src;
+.P2
+The
+.CW "src"
+operand is converted to a byte and stored in the
+.CW "dst"
+operand.
+.SH
+cvtwc \- Convert word to string
+.P1
+Syntax: cvtwc src, dst
+Function: dst = string(src)
+.P2
+The word addressed by the
+.CW "src"
+operand is converted to a string and stored in the
+.CW "dst"
+operand. The string is the decimal representation of the word.
+.SH
+cvtwl \- Convert word to big
+.P1
+Syntax: cvtwl src, dst
+Function: dst = (big)src;
+.P2
+The word addressed by the
+.CW "src"
+operand is converted to a big integer and stored in the
+.CW "dst"
+operand.
+.SH
+cvtwf \- Convert word to real
+.P1
+Syntax: cvtwf src, dst
+Function: dst = (float)src;
+.P2
+The word addressed by the
+.CW "src"
+operand is converted to a floating point value and stored in the
+.CW "dst"
+operand.
+.SH
+cvtws \- Convert word to short word†
+.P1
+Syntax: cvtws src, dst
+Function: dst = (short)src;
+.P2
+The word addressed by the
+.CW "src"
+operand is converted to a short word and stored in the
+.CW "dst"
+operand.
+.SH
+cvtlf \- Convert big to real
+.P1
+Syntax: cvtlf src, dst
+Function: dst = (float)src;
+.P2
+The big integer addressed by the
+.CW "src"
+operand is converted to a floating point value and stored in the
+.CW "dst"
+operand.
+.SH
+cvtrf \- Convert short real to real†
+.P1
+Syntax: cvtrf src, dst
+Function: dst = (float)src;
+.P2
+The short (32 bit) floating point value addressed by the
+.CW "src"
+operand is converted to a 64-bit floating point value and stored in the
+.CW "dst"
+operand.
+.SH
+div\fIx\fP \- Divide
+.P1
+Syntax: divb src1, src2, dst
+ divf src1, src2, dst
+ divw src1, src2, dst
+ divl src1, src2, dst
+Function: dst = src2/src1
+.P2
+The
+.CW "src2"
+operand is divided by the
+.CW "src1"
+operand and the quotient is stored in the
+.CW "dst"
+operand. Division by zero causes the thread to terminate.
+.SH
+exit \- Terminate thread
+.P1
+Syntax: exit
+Function: exit()
+.P2
+The executing thread terminates. All resources held in the stack are deallocated.
+.SH
+frame \- Allocate frame for local call
+.P1
+Syntax: frame src1, src2
+Function: src2 = fp + src1->size
+ initmem(src2, src1);
+.P2
+The frame instruction creates a new stack frame
+for a call to a function in the same module. The frame is initialized according to the type descriptor supplied as the
+.CW src1
+operand. A pointer to the newly created frame is stored in the
+.CW src2
+operand.
+.SH
+goto \- Computed goto
+.P1
+Syntax: goto src, dst
+Function: pc = dst[src]
+.P2
+The
+.CW "goto"
+instruction performs a computed goto. The
+.CW "src"
+operand must be an integer index into a table of PC values specified by the
+.CW "dst"
+operand.
+.SH
+head\fIx\fP \- Head of list
+.P1
+Syntax: headb src, dst
+ headf src, dst
+ headm src, dst
+ headmp src, dst
+ headp src, dst
+ headw src, dst
+ headl src, dst
+Function: dst = hd src
+.P2
+The
+.CW "head"
+instructions make a copy of the first data item stored in a list. The
+.CW "src"
+operand must be a list of the correct type. The first item is copied into the
+.CW "dst"
+operand. The list is not modified.
+.SH
+indc \- Index by character
+.P1
+Syntax: indc src1, src2, dst
+Function: dst = src1[src2]
+.P2
+The
+.CW "indc"
+instruction indexes Unicode strings. The
+.CW "src1"
+instruction must be a string. The
+.CW "src2"
+operand must be an integer specifying the origin-0 index in
+.CW src1
+of the (Unicode) character to store in the
+.CW "dst"
+operand.
+.SH
+indx \- Array index
+.P1
+Syntax: indx src1, dst, src2
+Function: dst = &src1[src2]
+.P2
+The
+.CW "indx"
+instruction computes the effective address of an array element. The
+.CW "src1"
+operand must be an array created by the
+.CW "newa"
+instruction. The
+.CW "src2"
+operand must be an integer. The effective address of the
+.CW "src2"
+element of the array is stored in the
+.CW "dst"
+operand.
+.SH
+ind\fIx\fP \- Index by type
+.P1
+Syntax: indb src1, dst, src2
+ indw src1, dst, src2
+ indf src1, dst, src2
+ indl src1, dst, src2
+Function: dst = &src1[src2]
+.P2
+The
+.CW "indb" ,
+.CW "indw" ,
+.CW "indf"
+and
+.CW "indl"
+instructions index arrays of the basic types. The
+.CW "src1"
+operand must be an array created by the
+.CW "newa"
+instruction. The
+.CW "src2"
+operand must be a non-negative integer index less than the array size. The effective address of the element at the index is stored in the
+.CW "dst"
+operand.
+.SH
+insc \- Insert character into string
+.P1
+Syntax: insc src1, src2, dst
+Function: src1[src2] = dst
+.P2
+The
+.CW "insc"
+instruction inserts a character into an existing string.
+The index in
+.CW "src2"
+must be a non-negative integer less than the length of the string plus one.
+(The character will be appended to the string if the index is equal to
+the string's length.)
+The
+.CW "src1"
+operand must be a string (or nil).
+The character to insert must be a valid 21-bit unicode value represented as a word.
+.SH
+jmp \- Branch always
+.P1
+Syntax: jmp dst
+Function: pc = dst
+.P2
+Control is transferred to the location specified by the
+.CW "dst"
+operand.
+.SH
+lea \- Load effective address
+.P1
+Syntax: lea src, dst
+Function: dst = &src
+.P2
+The
+.CW "lea"
+instruction computes the effective address of the
+.CW "src"
+operand and stores it in the
+.CW "dst"
+operand.
+.SH
+lena \- Length of array
+.P1
+Syntax: lena src, dst
+Function: dst = nelem(src)
+.P2
+The
+.CW "lena"
+instruction computes the length of the array specified by the
+.CW "src"
+operand and stores it in the
+.CW "dst"
+operand.
+.SH
+lenc \- Length of string
+.P1
+Syntax: lenc src, dst
+Function: dst = utflen(src)
+.P2
+The
+.CW "lenc"
+instruction computes the number of characters in the UTF string addressed by the
+.CW "src"
+operand and stores it in the
+.CW "dst"
+operand.
+.SH
+lenl \- Length of list
+.P1
+Syntax: lenl src, dst
+Function: dst = 0;
+ for(l = src; l; l = tl l)
+ dst++;
+.P2
+The
+.CW "lenl"
+instruction computes the number of elements in the list addressed by the
+.CW "src"
+operand and stores the result in the
+.CW "dst"
+operand.
+.SH
+load \- Load module
+.P1
+Syntax: load src1, src2, dst
+Function: dst = load src2 src1
+.P2
+The
+.CW "load"
+instruction loads a new module into the heap. The module might optionally be compiled into machine code depending on the module header. The
+.CW "src1"
+operand is a pathname to the file containing the object code for the module. The
+.CW "src2"
+operand specifies the address
+of a linkage descriptor for the module (see below).
+A reference to the newly loaded module is stored in the
+.CW "dst"
+operand.
+If the module could not be loaded for any reason, then
+.CW "dst"
+will be set to
+.CW H .
+.LP
+The linkage descriptor referenced by the
+.CW src2
+operand is a table in data space that lists the functions
+imported by the current module from the module to be loaded.
+It has the following layout:
+.P1
+int nentries;
+struct { /* word aligned */
+ int sig;
+ byte name[]; /* UTF encoded name, 0-terminated */
+} entry[];
+.P2
+The
+.CW nentries
+value gives the number of entries in the table and can be zero.
+It is followed by that many linkage entries.
+Each entry is aligned on a word boundary; there can therefore
+be padding before each structure.
+The entry names the imported function in the UTF-encoded string in
+.CW name ,
+which is terminated by a byte containing zero.
+The MD5 hash of the function's type signature is given in the value
+.CW sig .
+For each entry,
+.CW load
+instruction checks that a function with the same name in the newly loaded
+exists, with the same signature.
+Otherwise the load will fail and
+.CW dst
+will be set to
+.CW H .
+.LP
+The entries in the linkage descriptor form an array of linkage records
+(internal to the virtual machine) associated with the
+module pointer returned in
+.CW dst ,
+that is indexed by operators
+.CW mframe ,
+.CW mcall
+and
+.CW mspawn
+to refer to functions in that module.
+The linkage scheme provides a level of indirection that allows
+a module to be loaded using any module declaration that is a valid
+subset of the implementation module's declaration,
+and allows entry points to be added to modules without invalidating
+calling modules.
+.SH
+lsr\fIx\fP \- Logical shift right
+.P1
+Syntax: lsrw src1, src2, dst
+ lsrl src1, src2, dst
+Function: dst = (unsigned)src2 >> src1
+.P2
+The
+.CW "lsr"
+instructions shift the
+.CW "src2"
+operand right by the number of bits specified by the
+.CW "src1"
+operand, replacing the vacated bits by 0, and store the result in the
+.CW "dst"
+operand. Shift counts less than 0 or greater than the number of bits in the object have undefined results.
+This instruction is included for support of languages other than Limbo,
+and is not used by the Limbo compiler.
+.SH
+mcall \- Inter-module call
+.P1
+Syntax: mcall src1, src2, src3
+Function: link(src1) = pc
+ frame(src1) = fp
+ mod(src1) = current_moduleptr
+ current_moduleptr = src3->moduleptr
+ fp = src1
+ pc = src3->links[src2]->pc
+.P2
+The
+.CW "mcall"
+instruction calls a function in another module. The first argument specifies a new frame for the called procedure and must have been built using the
+.CW "mframe"
+instruction.
+The
+.CW "src3"
+operand is a module reference generated by a successful
+.CW "load"
+instruction.
+The
+.CW "src2"
+operand specifies the index for the called
+function in the array of linkage records associated with that module reference
+(see the
+.CW load
+instruction).
+.SH
+mframe \- Allocate inter-module frame
+.P1
+Syntax: mframe src1, src2, dst
+Function: dst = fp + src1->links[src2]->t->size
+ initmem(dst, src1->links[src2])
+.P2
+The
+.CW mframe
+instruction allocates a new frame for a procedure call into another module. The
+.CW src1
+operand specifies the location of a module pointer created as the result of a successful load instruction. The
+.CW src2
+operand specifies the index for the called function in
+the array of linkage records associated
+with that module pointer (see the
+.CW load
+instruction).
+A pointer to the initialized frame is stored in
+.CW dst .
+The
+.CW src2
+operand specifies the linkage number of the function to be called in the module specified by
+.CW src1 .
+.SH
+mnewz \- Allocate object given type from another module
+.P1
+Syntax: mnewz src1, src2, dst
+Function: dst = malloc(src1->types[src2]->size)
+ initmem(dst, src1->types[src2]->map)
+.P2
+The
+.CW mnewz
+instruction allocates and initializes storage to a new
+area of memory.
+The
+.CW src1
+operand specifies the location of a module pointer created as the result of a successful load instruction.
+The size of the new memory area and the location of
+pointers within it are specified by the
+.CW src2
+operand, which gives a
+type descriptor number within that module.
+Space not occupied by pointers is initialized to zero.
+A pointer to the initialized object is stored in
+.CW dst .
+This instruction is not used by Limbo; it was added to implement other languages.
+.SH
+mod\fIx\fP \- Modulus
+.P1
+Syntax: modb src1, src2, dst
+ modw src1, src2, dst
+ modl src1, src2, dst
+Function: dst = src2 % src1
+.P2
+The modulus instructions compute the remainder of the
+.CW "src2"
+operand divided by the
+.CW "src1"
+operand and store the result in
+.CW "dst" .
+The operator preserves the condition that the absolute value of a%b is less than the absolute value of
+.CW "b" ;
+.CW "(a/b)*b + a%b"
+is always equal to
+.CW a .
+.SH
+mov\fIx\fP \- Move scalar
+.P1
+Syntax: movb src, dst
+ movw src, dst
+ movf src, dst
+ movl src, dst
+Function: dst = src
+.P2
+The move operators perform assignment. The value specified by the
+.CW "src"
+operand is copied to the
+.CW "dst"
+operand.
+.SH
+movm \- Move memory
+.P1
+Syntax: movm src1, src2, dst
+Function: memmove(&dst, &src1, src2)
+.P2
+The
+.CW "movm"
+instruction copies memory from the
+.CW "src1"
+operand to the
+.CW "dst"
+operand for
+.CW "src2"
+bytes. The
+.CW "src1"
+and
+.CW "dst"
+operands specify the effective address of the memory rather than a pointer to the memory.
+.SH
+movmp \- Move memory and update reference counts
+.P1
+Syntax: movmp src1, src2, dst
+Function: decmem(&dst, src2)
+ memmove(&dst, &src1, src2->size)
+ incmem(&src, src2)
+.P2
+The
+.CW "movmp"
+instructions performs the same function as the
+.CW "movm"
+instruction but increments the reference count of pointers contained in the data type. For each pointer specified by the
+.CW "src2"
+type descriptor, the corresponding pointer reference count in the destination is decremented. The
+.CW "movmp"
+instruction then copies memory from the
+.CW "src1"
+operand to the
+.CW "dst"
+operand for the number of bytes described by the type descriptor. For each pointer specified by the type descriptor the corresponding pointer reference count in the source is incremented.
+.SH
+movp \- Move pointer
+.P1
+Syntax: movp src, dst
+Function: destroy(dst)
+ dst = src
+ incref(src)
+.P2
+The
+.CW "movp"
+instruction copies a pointer adjusting the reference counts to reflect the new pointers.
+.SH
+movpc \- Move program counter
+.P1
+Syntax: movpc src, dst
+Function: dst = PC(src);
+.P2
+The
+.CW "movpc"
+instruction computes the actual address of an immediate PC value. The
+.CW "dst"
+operand is set to the actual machine address of the instruction addressed by the
+.CW "src"
+operand. This instruction must be used to calculate PC values for computed branches.
+.SH
+mspawn \- Module spawn function
+.P1
+Syntax: mspawn src1, src2, src3
+Function: fork();
+ if(child){
+ link(src1) = 0
+ frame(src1) = 0
+ mod(src1) = src3->moduleptr
+ current_moduleptr = src3->moduleptr
+ fp = src1
+ pc = src3->links[src2]->pc
+ }
+.P2
+The
+.CW "mspawn"
+instruction creates a new thread, which starts executing a function in another module.
+The first argument specifies a new frame for the called procedure and must have been built using the
+.CW "mframe"
+instruction.
+The
+.CW "src3"
+operand is a module reference generated by a successful
+.CW "load"
+instruction.
+The
+.CW "src2"
+operand specifies the index for the called function in
+the array of linkage records associated with that module reference (see the
+.CW load
+instruction above).
+.SH
+mul\fIx\fP - Multiply
+.P1
+Syntax: mulb src1, src2, dst
+ mulw src1, src2, dst
+ mulf src1, src2, dst
+ mull src1, src2, dst
+Function: dst = src1 * src2
+.P2
+The
+.CW src1
+operand is multiplied by the
+.CW src2
+operand and the product is stored in the
+.CW dst
+operand.
+.SH
+nbalt \- Non blocking alternate
+.P1
+Syntax: nbalt src, dst
+.P2
+The
+.CW "nbalt"
+instruction has the same operands and function as
+.CW "alt"
+, except that if no channel is ready to communicate, the instruction does not block. When no channels are ready, control is transferred to the PC in the last element of the table addressed by
+.CW dst .
+.SH
+negf \- Negate real
+.P1
+Syntax: negf src, dst
+Function: dst = -src
+.P2
+The floating point value addressed by the
+.CW "src"
+operand is negated and stored in the
+.CW "dst"
+operand.
+.SH
+new, newz \- Allocate object
+.P1
+Syntax: new src, dst
+ newz src, dst
+Function: dst = malloc(src->size);
+ initmem(dst, src->map);
+.P2
+The
+.CW "new"
+instruction allocates and initializes storage to a new area of memory. The size and locations of pointers are specified by the type descriptor number given as the
+.CW "src"
+operand. A pointer to the newly allocated object is placed in
+.CW "dst" .
+Any space not occupied by pointers has undefined value.
+.LP
+The
+.CW "newz"
+instruction additionally guarantees that all non-pointer values are set to zero.
+It is not used by Limbo.
+.SH
+newa, newaz \- Allocate array
+.P1
+Syntax: newa src1, src2, dst
+ newaz src1, src2, dst
+Function: dst = malloc(src2->size * src1);
+ for(i = 0; i < src1; i++)
+ initmem(dst + i*src2->size, src2->map);
+.P2
+The
+.CW "newa"
+instruction allocates and initializes an array. The number of elements is specified by the
+.CW "src1"
+operand. The type of each element is specified by the type descriptor number given as the
+.CW "src2"
+operand.
+Space not occupied by pointers has undefined value.
+The
+.CW newaz
+instruction additionally guarantees that all non-pointer values are set to zero;
+it is not used by Limbo.
+.SH
+newc\fIx\fP \- Allocate channel
+.P1
+Syntax: newcw dst
+ newcb dst
+ newcl dst
+ newcf dst
+ newcp dst
+ newcm src, dst
+ newcmp src, dst
+Function: dst = new(Channel)
+.P2
+The
+.CW "newc"
+instruction allocates a new channel of the specified type and stores a reference to the channel in
+.CW "dst" .
+For the
+.CW "newcm"
+instruction the source specifies the number of bytes of memory used by values sent on the channel (see the
+.CW movm
+instruction above).
+For the
+.CW "newcmp"
+instruction the first operand specifies a type descriptor giving the length of the structure and the location of pointers within the structure (see the
+.CW movmp
+instruction above).
+.SH
+or\fIx\fP \- Logical OR
+.P1
+Syntax: orb src1, src2, dst
+ orw src1, src2, dst
+ orl src1, src2, dst
+Function: dst = src1 | src
+.P2
+These instructions compute the bitwise OR of the two operands addressed by
+.CW "src1"
+and
+.CW "src2"
+and store the result in the
+.CW "dst"
+operand.
+.SH
+recv \- Receive from channel
+.P1
+Syntax: recv src, dst
+Function: dst = <-src
+.P2
+The
+.CW "recv"
+instruction receives a value from some other thread on the channel specified by the
+.CW "src"
+operand. Communication is synchronous, so the calling thread will block until a corresponding
+.CW "send"
+or
+.CW "alt"
+is performed on the channel. The type of the received value is determined by the channel type and the
+.CW "dst"
+operand specifies where to place the received value.
+.SH
+ret \- Return from function
+.P1
+Syntax: ret
+Function: npc = link(fp)
+ mod = mod(fp)
+ fp = frame(fp)
+ pc = npc
+.P2
+The
+.CW "ret"
+instruction returns control to the instruction after the call of the current function.
+.SH
+send \- Send to channel
+.P1
+Syntax: send src, dst
+Function: dst <-= src
+.P2
+The
+.CW "send"
+instruction sends a value from this thread to some other thread on the channel specified by the
+.CW "dst"
+operand. Communication is synchronous so the calling thread will block until a corresponding
+.CW "recv"
+or
+.CW "alt"
+is performed on the channel. The type of the sent value is determined by the channel type and the
+.CW "dst"
+operand specifies where to retrieve the sent value.
+.SH
+shl\fIx\fP \- Shift left arithmetic
+.P1
+Syntax: shlb src1, src2, dst
+ shlw src1, src2, dst
+ shll src1, src2, dst
+Function: dst = src2 << src1
+.P2
+The
+.CW "shl"
+instructions shift the
+.CW "src2"
+operand left by the number of bits specified by the
+.CW "src1"
+operand and store the result in the
+.CW "dst"
+operand. Shift counts less than 0 or greater than the number of bits in the object have undefined results.
+.SH
+shr\fIx\fP \- Shift right arithmetic
+.P1
+Syntax: shrb src1, src2, dst
+ shrw src1, src2, dst
+ shrl src1, src2, dst
+Function: dst = src2 >> src1
+.P2
+The
+.CW "shr"
+instructions shift the
+.CW "src2"
+operand right by the number of bits specified by the
+.CW "src1"
+operand and store the result in the
+.CW "dst"
+operand. Shift counts less than 0 or greater than the number of bits in the object have undefined results.
+.SH
+slicea \- Slice array
+.P1
+Syntax: slicea src1, src2, dst
+Function: dst = dst[src1:src2]
+.P2
+The
+.CW "slicea"
+instruction creates a new array, which contains the elements from the index at
+.CW "src1"
+to the index
+.CW "src2-1" .
+The new array is a reference array which points at the elements in the initial array. The initial array will remain allocated until both arrays are no longer referenced.
+.SH
+slicec \- Slice string
+.P1
+Syntax: slicec src1, src2, dst
+Function: dst = dst[src1:src2]
+.P2
+The
+.CW "slicec"
+instruction creates a new string, which contains characters from the index at
+.CW "src1"
+to the index
+.CW "src2-1" .
+Unlike
+.CW "slicea"
+, the new string is a copy of the elements from the initial string.
+.SH
+slicela \- Assign to array slice
+.P1
+Syntax: slicela src1, src2, dst
+Function: dst[src2:] = src1
+.P2
+The
+.CW "src1"
+and
+.CW "dst"
+operands must be arrays of equal types. The
+.CW "src2"
+operand is a non-negative integer index. The
+.CW "src1"
+array is assigned to the array slice
+.CW "dst[src2:]" ;
+.CW "src2 + nelem(src1)"
+must not exceed
+.CW "nelem(dst)" .
+.SH
+spawn \- Spawn function
+.P1
+Syntax: spawn src, dst
+Function: fork();
+ if(child)
+ dst(src);
+.P2
+The
+.CW "spawn"
+instruction creates a new thread and calls the function specified by the
+.CW "dst"
+operand. The argument frame passed to the thread function is specified by the
+.CW "src"
+operand and should have been created by the
+.CW "frame"
+instruction.
+.SH
+sub\fIx\fP \- Subtract
+.P1
+Syntax: subb src1, src2, dst
+ subf src1, src2, dst
+ subw src1, src2, dst
+ subl src1, src2, dst
+Function: dst = src2 - src1
+.P2
+The
+.CW "sub"
+instructions subtract the operands addressed by
+.CW "src1"
+and
+.CW "src2"
+and stores the result in the
+.CW "dst"
+operand. For
+.CW "subb" ,
+the result is truncated to eight bits.
+.SH
+tail \- Tail of list
+.P1
+Syntax: tail src, dst
+Function: dst = src->next
+.P2
+The
+.CW "tail"
+instruction takes the list specified by the
+.CW "src"
+operand and creates a reference to a new list with the head removed, which is stored in the
+.CW "dst"
+operand.
+.SH
+tcmp \- Compare types
+.P1
+Syntax: tcmp src, dst
+Function: if(typeof(src) != typeof(dst))
+ error("typecheck");
+.P2
+The
+.CW "tcmp"
+instruction compares the types of the two pointers supplied by the
+.CW "src"
+and
+.CW "dst"
+operands. The comparison will succeed if the two pointers were created from the same type descriptor or the
+.CW "src"
+operand is
+.CW "nil" ;
+otherwise, the program will error. The
+.CW "dst"
+operand must be a valid pointer.
+.SH
+xor\fIx\fP \- Exclusive OR
+.P1
+Syntax: xorb src1, src2, dst
+ xorw src1, src2, dst
+ xorl src1, src2, dst
+Function: dst = src1 ^ src2
+.P2
+These instructions compute the bitwise exclusive-OR of the two operands addressed by
+.CW "src1"
+and
+.CW "src2"
+and store the result in the
+.CW "dst"
+operand.
+.NH 1
+Object File Format
+.LP
+An object file defines a single module. The file has the following structure:
+.P1
+Objfile
+{
+ Header;
+ Code_section;
+ Type_section;
+ Data_section;
+ Module_name;
+ Link_section;
+};
+.P2
+The following data types are used in the description of the file encoding:
+.IP
+.TS
+lf(CW) lw(4i)fR .
+OP T{
+encoded integer operand, encoding selected by the two most significant bits as follows:
+.nf
+00 signed 7 bits, 1 byte
+.br
+10 signed 14 bits, 2 bytes
+.br
+11 signed 30 bits, 4 bytes
+T}
+B unsigned byte
+W 32 bit signed integer
+F canonicalized 64-bit IEEE754 floating point value
+SO 16 bit unsigned small offset from register
+SI 16 bit signed immediate value
+LO 30 bit signed large offset from register
+.TE
+.LP
+All binary values are encoded in two's complement format, most significant byte first.
+.SH
+The Header Section
+.P1
+Header
+{
+ OP: magic_number;
+ Signature;
+ OP: runtime_flag;
+ OP: stack_extent;
+ OP: code_size;
+ OP: data_size;
+ OP: type_size;
+ OP: link_size;
+ OP: entry_pc;
+ OP: entry_type;
+};
+.P2
+The magic number is defined as 819248
+(symbolically
+.CW XMAGIC ),
+for modules that have not been signed cryptographically, and 923426
+(symbolically
+.CW "SMAGIC" ),
+for modules that contain a signature.
+On the Inferno system, the symbolic names
+.CW "XMAGIC"
+and
+.CW SMAGIC
+are defined by the C include file
+.CW "/include/isa.h"
+and the Limbo module
+.CW /module/dis.m .
+.LP
+The signature field is only present if the magic number is
+.CW "SMAGIC" .
+It has the form:
+.P1
+Signature
+{
+ OP: length;
+ array[length] of byte: signature;
+};
+.P2
+A digital signature is defined by a length, followed by an array of untyped bytes.
+Data within the signature should identify the signing authority, algorithm, and data to be signed.
+.LP
+The
+.CW runtime_flag
+is a bit mask that defines various execution options for a Dis module. The flags currently defined are:
+.P1
+MUSTCOMPILE = 1<<0
+DONTCOMPILE = 1<<1
+SHAREMP = 1<<2
+.P2
+The
+.CW "MUSTCOMPILE"
+flag indicates that a
+.CW "load"
+instruction should draw an error if the implementation is unable to compile the module into native instructions using a just-in-time compiler.
+.LP
+The
+.CW "DONTCOMPILE"
+flag indicates that the module should not be compiled into native instructions, even though it is the default for the runtime environment. This flag may be set to allow debugging or to save memory.
+.LP
+The
+.CW "SHAREMP"
+flag indicates that each instance of the module should use the same module data for all instances of the module. There is no implicit synchronization between threads using the shared data.
+.LP
+The
+.CW stack_extent
+value indicates the number of bytes by which the thread stack of this module should be extended in the event that procedure calls exhaust the allocated stack. While stack extension is transparent to programs, increasing this value may improve the efficiency of execution at the expense of using more memory.
+.LP
+The
+.CW code_size
+is a count of the number of instructions stored in the Code_section.
+.LP
+The
+.CW data_size
+gives the size in bytes of the module's global data, which is initialized
+by evaluating the contents of the data section.
+.LP
+The
+.CW type_size
+is a count of the number of type descriptors stored in the Type_section.
+.LP
+The
+.CW link_size
+is a count of the number of external linkage directives stored in the Link_section.
+.LP
+The
+.CW entry_pc
+is an integer index into the instruction stream that is the default entry point for this module. The
+.CW entry_pc
+should point to the first instruction of a function. Instructions are numbered from a program counter value of zero.
+.LP
+The
+.CW entry_type
+is the index of the type descriptor that corresponds to the function entry point set by
+.CW entry_pc .
+.SH
+The Code Section
+.LP
+The code section describes a sequence of instructions for the virtual machine. An instruction is encoded as follows:
+.P1
+Instruction
+{
+ B: opcode;
+ B: address_mode;
+ Middle_data;
+ Source_data;
+ Dest_data;
+};
+.P2
+.LP
+The
+.CW opcode
+specifies the instruction to execute, encoded as follows:
+.IP
+.TS
+tab(:);
+l l l l l .
+00 nop:20 headb:40 mulw:60 blew:80 shrl
+01 alt:21 headw:41 mulf:61 bgtw:81 bnel
+02 nbalt:22 headp:42 divb:62 bgew:82 bltl
+03 goto:23 headf:43 divw:63 beqf:83 blel
+04 call:24 headm:44 divf:64 bnef:84 bgtl
+05 frame:25 headmp:45 modw:65 bltf:85 bgel
+06 spawn:26 tail:46 modb:66 blef:86 beql
+07 runt:27 lea:47 andb:67 bgtf:87 cvtlf
+08 load:28 indx:48 andw:68 bgef:88 cvtfl
+09 mcall:29 movp:49 orb:69 beqc:89 cvtlw
+0A mspawn:2A movm:4A orw:6A bnec:8A cvtwl
+0B mframe:2B movmp:4B xorb:6B bltc:8B cvtlc
+0C ret:2C movb:4C xorw:6C blec:8C cvtcl
+0D jmp:2D movw:4D shlb:6D bgtc:8D headl
+0E case:2E movf:4E shlw:6E bgec:8E consl
+0F exit:2F cvtbw:4F shrb:6F slicea:8F newcl
+10 new:30 cvtwb:50 shrw:70 slicela:90 casec
+11 newa:31 cvtfw:51 insc:71 slicec:91 indl
+12 newcb:32 cvtwf:52 indc:72 indw:92 movpc
+13 newcw:33 cvtca:53 addc:73 indf:93 tcmp
+14 newcf:34 cvtac:54 lenc:74 indb:94 mnewz
+15 newcp:35 cvtwc:55 lena:75 negf:95 cvtrf
+16 newcm:36 cvtcw:56 lenl:76 movl:96 cvtfr
+17 newcmp:37 cvtfc:57 beqb:77 addl:97 cvtws
+18 send:38 cvtcf:58 bneb:78 subl:98 cvtsw
+19 recv:39 addb:59 bltb:79 divl:99 lsrw
+1A consb:3A addw:5A bleb:7A modl:9A lsrl
+1B consw:3B addf:5B bgtb:7B mull:9B eclr
+1C consp:3C subb:5C bgeb:7C andl:9C newz
+1D consf:3D subw:5D beqw:7D orl:9D newaz
+1E consm:3E subf:5E bnew:7E xorl
+1F consmp:3F mulb:5F bltw:7F shll
+.TE
+.LP
+The
+.CW address_mode
+byte specifies the addressing mode of each of the three operands: middle, source and destination. The source and destination operands are encoded by three bits and the middle operand by two bits. The bits are packed as follows:
+.P1
+bit 7 6 5 4 3 2 1 0
+ m1 m0 s2 s1 s0 d2 d1 d0
+.P2
+The middle operand is encoded as follows:
+.IP
+.TS
+lf(CW) lf(CW) lw(3i)fR .
+00 \fInone\fP no middle operand
+01 $SI small immediate
+10 SO(FP) small offset indirect from FP
+11 SO(MP) small offset indirect from MP
+.TE
+.LP
+The source and destination operands are encoded as follows:
+.IP
+.TS
+lf(CW) lf(CW) lw(3i)fR .
+000 LO(MP) offset indirect from MP
+001 LO(FP) offset indirect from FP
+010 $OP 30 bit immediate
+011 \fInone\fP no operand
+100 SO(SO(MP)) double indirect from MP
+101 SO(SO(FP)) double indirect from FP
+110 \fIreserved\fP
+111 \fIreserved\fP
+.TE
+.LP
+The
+.CW middle_data
+field is only present if the middle operand specifier of the address_mode is not `none'.
+If the field is present it is encoded as an
+.CW "OP" .
+.LP
+The
+.CW source_data
+and
+.CW dest_data
+fields are present only if the corresponding
+.CW address_mode
+field is not `none'.
+For offset indirect and immediate modes the field contains a single
+.CW "OP" .
+For double indirect modes the values are encoded as two
+.CW "OP"
+values: the first value is the register indirect offset, and the second value is the final indirect offset. The offsets for double indirect addressing cannot be larger than 16 bits.
+.SH
+The Type Section
+.LP
+The type section contains type descriptors describing the layout of pointers within data types. The format of each descriptor is:
+.P1
+Type_descriptor
+{
+ OP: desc_number;
+ OP: size;
+ OP: number_ptrs;
+ array[number_ptrs] of B: map;
+};
+.P2
+.LP
+The
+.CW desc_number
+is a small integer index used to identify the descriptor to instructions such as
+.CW "new" .
+.LP
+The
+.CW "size"
+field is the size in bytes of the memory described by this type.
+.LP
+The
+.CW number_ptrs
+field gives the size in bytes of the
+.CW "map"
+array.
+.LP
+The
+.CW "map"
+array is a bit vector where each bit corresponds to a word in memory.
+The most significant bit corresponds to the lowest address.
+For each bit in the map,
+the word at the corresponding offset in the type is a pointer iff the bit is set to 1.
+.SH
+The Data Section
+.LP
+The data section encodes the contents of the
+.CW "MP"
+data for the module. The section contains a sequence of items; each item contains
+a control byte and an offset into the section,
+followed by one or more data items.
+A control byte of zero marks the end of the data section.
+Otherwise, it gives the type of data to be loaded and selects between
+two representations of an item:
+.P1
+Short_item
+{
+ B: code;
+ OP: offset;
+ array[code & 16rF] of type[code>>4]: data;
+};
+.P3
+Long_item
+{
+ B: code;
+ OP: count;
+ OP: offset;
+ array[ndata] of type[code>>4]: data;
+};
+.P2
+A
+.CW Short_item
+is generated for 15 or fewer items, otherwise a
+.CW "Long_item"
+is generated. In a
+.CW "Long_item"
+the count field (bottom 4 bits of code) is set to zero and the count follows as an
+.CW "OP" .
+The top 4 bits of code determine the type of the datum.
+The defined values are:
+.IP
+.TS
+lf(CW) lw(3i)f(R) .
+0001 8 bit bytes
+0010 32 bit words
+0011 utf encoded string
+0100 real value IEEE754 canonical representation
+0101 Array
+0110 Set array address
+0111 Restore load address
+1000 64 bit big
+.TE
+.LP
+The byte, word, real and big operands are encoded as sequences
+of bytes (of appropriate length) in big-endian form, converted to native
+format before being stored in the data space.
+The `string' code takes a UTF-encoded sequence of
+.CW count
+bytes, which is converted to an array of 21-bit Unicode values stored in an
+implementation-dependent structure on
+the heap; a 4-byte pointer to the string descriptor is stored in the data space.
+The `array' code takes two 4-byte operands: the first is the index of the array's type
+descriptor in the type section; the second is the length of the array to be created.
+The result in memory is a 4-byte pointer to an implementation-dependent
+array descriptor in the heap.
+.LP
+Each item's data is stored at the address formed by adding the
+.CW offset
+in that item to a base address maintained by the loader.
+Initially that address is the base of the data space of the module instance.
+A new base for loading subsequent items can be set or restored by
+the following operations, used to initialize arrays.
+The `set array index' item must appear immediately following an `array'
+item.
+Its operand is a 4-byte big-endian integer that gives an index into that
+array, at which address subsequent data should be loaded; the
+previous load address is stacked internally.
+Subsequent data will be loaded at offsets from the new base address.
+The `restore load address' item has no operands; it pops a load address
+from the internal address stack and makes that the new
+base address.
+.SH
+The Module Name
+.LP
+The module name immediately follows the data section.
+It contains the name of the implementation module, in UTF encoding,
+terminated by a zero byte.
+.SH
+The Link Section
+.LP
+The link section contains an array of external linkage items:
+the list of functions exported by this module.
+Each item describes one exported function in the following form:
+.P1
+Linkage_item
+{
+ OP: pc;
+ OP: desc_number;
+ W: sig;
+ array[] of byte: name;
+};
+.P2
+The
+.CW pc
+is the instruction number of the function's entry point.
+The
+.CW desc_number
+is the index, in the type section, of the type descriptor for the function's stack frame.
+The
+.CW sig
+word is a 32-bit hash of the function's type signature.
+Finally,
+the name of the function is stored as a variable length array of bytes
+in UTF-8 encoding,
+with the end of the array marked by a zero byte.
+The names of member functions of an exported adt are qualified
+by the name of the adt.
+The next linkage item, if any, follows immediately.
+.NH 1
+Symbol Table File Format
+.LP
+The object file format does not include type information for debuggers.
+The Limbo compiler can optionally produce a separate symbol table file.
+Its format is defined in the entry
+.I sbl (6)
+of [1].
+.NH 1
+References
+.IP 1.
+.I "Inferno Programmer's Manual"
+(Third Edition),
+Volume 1 (`the manual'),
+Vita Nuova Holdings Limited, June 2000.
+.IP 2.
+P Winterbottom and R Pike,
+``The Design of the Inferno Virtual Machine'',
+reprinted in this volume.
binary files /dev/null b/doc/dis.pdf differ
--- /dev/null
+++ b/doc/ebookimp.ms
@@ -1,0 +1,389 @@
+.TL
+Navigating Large XML Documents on Small Devices
+.AU
+Roger Peppe
+.AI
+Vita Nuova
+.br
+April 2002
+.AB
+Browsing eBooks on platforms with limited memory presents an
+interesting problem: how can memory usage be bounded despite
+the need to view documents that may be much larger than the
+available memory. A simple interface to an XML parser enables
+this whilst retaining much of the ease of access afforded
+by XML parsers that read all of a document into memory at once.
+.AE
+.SH
+Introduction
+.LP
+The Open Ebook Publication Structure was devised by the Open Ebook Forum
+in order to ``provide a specification for representing the content of electronic
+books''. It is based on many existing standards, notably XML and HTML.
+An Open eBook publication consists of a set of documents bound together
+with an Open eBook package file which enumerates all the documents,
+pictures and other items that make up the book
+.LP
+The underlying document format is essentially HTML compatible,
+which is where the first problem arises: HTML was not designed to
+make it easy to view partial sections of a document. Conventionally
+an entire HTML document is read in at once and rendered onto
+the device. When viewing an eBook on a limited-memory device,
+however, this may not be possible; books tend to be fairly large.
+For such a device, the ideal format would keep the book itself
+in non-volatile storage (e.g. flash or disk) and make it possible
+for reader to seek to an arbitrary position in the book and render
+what it finds there.
+.LP
+This is not possible in an HTML or XML document, as the
+arbitrarily nested nature of the format means that every
+position in the document has some unknown surrounding context,
+which cannot be discovered without reading sequentially through
+the document from the beginning.
+.SH
+SAX and DOM
+.LP
+There are two conventional programming interfaces to an XML
+parser. A SAX parser provides a stream of XML entities, leaving
+it up to the application to maintain the context. It is not possible
+to rewind the stream, except, perhaps, to the beginning.
+Using a SAX parser is
+fairly straightforward, but awkward: the stream-like nature
+of the interface does not map well to the tree-like structure
+that is XML. A DOM parser reads a whole document into an internal
+data structure representation, so a program can treat it exactly
+as a tree. This also enables a program to access parts of the
+document in an arbitrary order.
+The DOM approach is all very well for small documents, but for large
+documents the memory usage can rapidly grow to exceed
+the available memory capacity. For eBook documents, this is unacceptable.
+.SH
+A different approach
+.LP
+The XML parser used in the eBook browser is akin to a SAX parser,
+in that only a little of the XML structure is held in memory at one time.
+The first significant difference is that the XML entities returned are
+taken from one level of the tree - if the program does not wish to
+see the contents of a particular XML tag, it is trivial to skip over.
+The second significant difference is that random access is possible.
+This possibility comes from the observation that if we have visited
+a part of the document we can record the context that we found there
+and restore it later if necessary. In this scheme, if we wish to return later to
+a part of a document that we are currently at, we can create a ``mark'',
+a token that holds the current context; at some later time we can use
+that mark to return to this position.
+.LP
+The eBook browser uses this technique to enable random access
+to the document on a page-by-page basis. Moreover a mark
+can be written to external storage, thus allowing an external
+``index'' into the document so it is not always necessary to
+read the entire document from the start in order to jump to a particular
+page in that document.
+.SH
+The programming interface
+.LP
+The interface is implemented by a module named
+.CW Xml ,
+which provides a
+.CW Parser
+adt which gives access to the contents of an XML document.
+Xml items are represented by an
+.CW Item
+pick adt with one branch of the pick corresponding to each
+type of item that might be encountered.
+.LP
+The interface to the parser looks like this:
+.P1
+open: fn(f: string, warning: chan of (Locator, string)): (ref Parser, string);
+Parser: adt {
+ next: fn(p: self ref Parser): ref Item;
+ down: fn(p: self ref Parser);
+ up: fn(p: self ref Parser);
+ mark: fn(p: self ref Parser): ref Mark;
+ atmark: fn(p: self ref Parser, m: ref Mark): int;
+ goto: fn(p: self ref Parser, m: ref Mark);
+ str2mark: fn(p: self ref Parser, s: string): ref Mark;
+};
+.P2
+To start parsing an XML document, it must first be
+.CW open ed;
+.CW warning
+is a channel on which non-fatal error messages will be sent
+if they are encountered during the parsing of the document.
+It can be nil, in which case warnings are ignored.
+If the document is opened successfully, a new
+.CW Parser
+adt, say
+.I p ,
+is returned.
+Calling
+.CW \fIp\fP.next
+returns the next XML item at the current level of the tree. If there
+are no more items in the current branch at the current level, it
+returns
+.CW nil .
+When a
+.CW Tag
+item is returned,
+.CW \fIp\fP.down
+can be used to descend ``into'' that tag; subsequent calls of
+.CW \fIp\fP.next
+will return XML items contained within the tag,
+and
+.CW \fIp\fP.up
+returns to the previous level.
+.LP
+An
+.CW Item
+is a pick adt:
+.P1
+Item: adt {
+ fileoffset: int;
+ pick {
+ Tag =>
+ name: string;
+ attrs: Attributes;
+ Text =>
+ ch: string;
+ ws1, ws2: int;
+ Process =>
+ target: string;
+ data: string;
+ Doctype =>
+ name: string;
+ public: int;
+ params: list of string;
+ Stylesheet =>
+ attrs: Attributes;
+ Error =>
+ loc: Locator;
+ msg: string;
+ }
+};
+.P2
+.CW Item.Tag
+represents a XML tag, empty or not. The XML
+fragments
+.CW "<tag></tag>" '' ``
+and
+.CW "<tag />" '' ``
+look identical from the point of view of this interface.
+A
+.CW Text
+item holds text found in between tags, with adjacent whitespaces merged
+and whitespace at the beginning and end of the text elided.
+.CW Ws1
+and
+.CW ws2
+are non-zero if there was originally whitespace at the beginning
+or end of the text respectively.
+.CW Process
+represents an XML processing request, as found between
+.CW "<?....?>" '' ``
+delimiters.
+.CW Doctype
+and
+.CW Stylesheet
+are items found in an XML document's prolog, the
+former representing a
+.CW "<!DOCTYPE...>" '' ``
+document type declaration, and the latter an XML
+stylesheet processing request.
+.LP
+When most applications are processing documents, they
+will wish to ignore all items other than
+.CW Tag
+and
+.CW Text .
+To this end, it is conventional to define a ``front-end'' function
+to return desired items, discard others, and take an appropriate
+action when an error is encountered. Here's an example:
+.P1
+nextitem(p: ref Parser): ref Item
+{
+ while ((gi := p.next()) != nil) {
+ pick i := gi {
+ Error =>
+ sys->print("error at %s:%d: %s\n",
+ i.loc.systemid, i.loc.line, i.msg);
+ exit;
+ Process =>
+ ; # ignore
+ Stylesheet =>
+ ; # ignore
+ Doctype =>
+ ; # ignore
+ * =>
+ return gi;
+ }
+ }
+ return nil;
+}
+.P2
+When
+.CW nextitem
+encounters an error, it exits; it might instead handle the
+error another way, say by raising an exception to be caught at the
+outermost level of the parsing code.
+.SH
+A small example
+.LP
+Suppose we have an XML document that contains some data that we would
+like to extract, ignoring the rest of the document. For this example we will
+assume that the data is held within
+.CW <data>
+tags, which contain zero or more
+.CW <item>
+tags, holding the actual data as text within them.
+Tags that we do not recognize we choose to ignore.
+So for example, given the following XML document:
+.P1
+<metadata>
+ <a>hello</a>
+ <b>goodbye</b>
+</metadata>
+<data>
+ <item>one</item>
+ <item>two</item>
+ <item>three</item>
+</data>
+<data>
+ <item>four</item>
+</data>
+.P2
+we wish to extract all the data items, but ignore everything inside
+the
+.CW <metadata>
+tag. First, let us define another little convenience function to get
+the next XML tag, ignoring extraneous items:
+.P1
+nexttag(p: ref Parser): ref Item.Tag
+{
+ while ((gi := nextitem(p)) != nil) {
+ pick i := gi {
+ Tag =>
+ return i;
+ }
+ }
+ return nil;
+}
+.P2
+Assuming that the document has already been opened,
+the following function scans through the document, looking
+for top level
+.CW <data>
+tags, and ignoring others:
+.P1
+document(p: ref Parser)
+{
+ while ((i := nexttag(p)) != nil) {
+ if (i.name == "data") {
+ p.down();
+ data(p);
+ p.up();
+ }
+ }
+}
+.P2
+The function to parse a
+.CW <data>
+tag is almost as straightforward; it scans for
+.CW <item>
+tags and extracts any textual data contained therein:
+.P1
+data(p: ref Parser)
+{
+ while ((i := nexttag(p)) != nil) {
+ if (i.name == "item") {
+ p.down();
+ if ((gni := p.next()) != nil) {
+ pick ni := gni {
+ Text =>
+ sys->print("item data: %s\n", ni.ch);
+ }
+ }
+ p.up();
+ }
+ }
+}
+.P2
+The above program is all very well and works fine, but
+suppose that the document that we are parsing is very
+large, with data items scattered through its length, and that
+we wish to access those items in an order that is not necessarily
+that in which they appear in the document.
+This is quite straightforward; every time we see a
+data item, we record the current position with a mark.
+Assuming the global declaration:
+.P1
+marks: list of ref Mark;
+.P2
+the
+.CW document
+function might become:
+.P1
+document(p: ref Parser)
+{
+ while ((i := nexttag(p)) != nil) {
+ if (i.name == "data") {
+ p.down();
+ marks = p.mark() :: marks;
+ p.up();
+ }
+ }
+}
+.P2
+At some later time, we can access the data items arbitrarily,
+for instance:
+.P1
+ for (m := marks; m != nil; m = tl m) {
+ p.goto(hd m);
+ data(p);
+ }
+.P2
+If we wish to store the data item marks in some external index
+(in a file, perhaps), the
+.CW Mark
+adt provides a
+.CW str
+function which returns a string representation of the mark.
+.CW Parser 's
+.CW str2mark
+function can later be used to recover the mark. Care must
+be taken that the document it refers to has not been changed,
+otherwise it is likely that the mark will be invalid.
+.SH
+The eBook implementation
+.LP
+The Open eBook reader software uses the primitives described above
+to maintain display-page-based access to arbitrarily large documents
+while trying to bound memory usage.
+Unfortunately it is difficult to unconditionally bound memory usage,
+given that any element in an XML document may be arbitrarily
+large. For instance a perfectly legal document might have 100MB
+of continuous text containing no tags whatsoever. The described
+interface would attempt to put all this text in one single item, rapidly
+running out of memory! Similar types of problems can occur when
+gathering the items necessary to format a particular tag.
+For instance, to format the first row of a table, it is necessary to lay out
+the entire table to determine the column widths.
+.LP
+I chose to make the simplifying assumption that top-level items within
+the document would be small enough to fit into memory.
+From the point of view of the display module, the document
+looks like a simple sequence of items, one after another.
+One item might cover more than one page, in which case a different
+part of it will be displayed on each of those pages.
+.LP
+One difficulty is that the displayed size of an item depends on many
+factors, such as stylesheet parameters, size of installed fonts, etc.
+When a document is read, the page index must have been created
+from the same document with the same parameters. It is difficult in
+general to enumerate all the relevant parameters; they would need
+to be stored inside, or alongside the index; any change would invalidate
+the index. Instead of doing this, as the document is being displayed,
+the eBook display program constantly checks to see if the results
+it is getting from the index match with the results it is getting
+when actually laying out the document. If the results differ, the
+index is remade; the discrepancy will hopefully not be noticed by
+the user!
binary files /dev/null b/doc/ebookimp.pdf differ
--- /dev/null
+++ b/doc/fonts
@@ -1,0 +1,8 @@
+# mkfile rules to get fonts in Lucida Sans.
+# if you don't have Lucida fonts, change this next line to
+# FONTS=''
+FONTS='.fp 1 R LucidaSans
+.fp 2 I LucidaSansI
+.fp 3 B LucidaSansB
+.fp 5 CW LucidaCW
+'
--- /dev/null
+++ b/doc/fonts.bem
@@ -1,0 +1,7 @@
+# FONTS=''
+FONTS='.fp 1 R BemboBookMTStd-Regular
+.fp 2 I BemboBookMTStd-Italic
+.fp 3 B BemboBookMTStd-Bold
+.fp 4 BI BemboBookMTStd-BoldIt
+....fp 5 L LucidaCW
+'
--- /dev/null
+++ b/doc/fonts.pal
@@ -1,0 +1,9 @@
+# mkfile rules to get fonts in Lucida Sans.
+# if you don't have Lucida fonts, change this next line to
+# FONTS=''
+FONTS='.fp 1 R PA
+.fp 2 I PI
+.fp 3 B PB
+.fp 4 PX
+....fp 5 L LucidaCW
+'
binary files /dev/null b/doc/frontmatter.pdf differ
--- /dev/null
+++ b/doc/gridinstall.ms
@@ -1,0 +1,136 @@
+.FP palatino
+.TL
+Installing the Vita Nuova grid software
+.AU
+Vita Nuova
+.br
+5 May 2005
+.NH 1
+Package contents
+.LP
+The installation CD contains software for both grid client and the server (scheduler),
+in separate directories in the root directory of the CD:
+.B client
+and
+.B server .
+.NH 1
+Client software
+.LP
+The grid client software will be installed on Windows NT4/2000/XP machines,
+in the directory (folder)
+.CW C:\eVNClient .
+.IP 1.
+On a Windows machine with the CD loaded,
+use Windows Explorer (or equivalent) to move to the directory named
+.CW \eclient\einstall
+on the CD.
+.IP 2.
+Double-click
+.CW setup.exe
+in that directory.
+It will display a new window that prompts for a destination directory.
+The directory need not exist but if it does, it should be empty.
+The default should be
+.CW C:\eVNClient .
+You can change the name if required (eg, because
+.CW C:
+lacks space), but
+you will then need to edit several files, as discussed below,
+and make appropriate changes to the instructions below.
+Hit the
+.SM ENTER
+key to start installation.
+The program will prompt for permission to create the directory if it does not already exist.
+It will then populate it with all files required by the client.
+.IP 3.
+Move in Explorer to the directory
+.CW C:\eVNClient\egrid\eslave .
+Check that the file
+.CW schedaddr
+contains the right address for your scheduler machine.
+If you changed the drive letter, you must also change the
+four
+.CW .bat
+files in the directory to replace the
+.CW C:
+drive letter by the one you used.
+.IP 4.
+You can now add the grid client as a Windows service by running the appropriate
+.CW .bat
+file on the client.
+Use
+.RS
+.IP
+\f5install_service.bat\fP
+for Windows 2000 and Windows XP
+.IP \fIOR\fP
+\f5install_service_nt4.bat\fP
+for Windows NT4
+.LP
+Just double-clicking in Explorer on the chosen name should install the service.
+.RE
+.LP
+Once installed as a service the client software will start automatically when
+the client machine next boots.
+You can start it manually using the Windows Services Manager in the usual way.
+There are two
+.CW .bat
+files to remove the service (when desired): \f5remove_service.bat\fP
+for 2000/XP and \f5remove_service_nt4.bat\fP for NT4.
+.LP
+The manual page
+.I scheduler-intro (1)
+in the PDF file
+.CW \escheduler.pdf
+on the CD gives more details on running and configuring the client software.
+The manual page
+.I scheduler-monitor (1)
+in the same PDF file describes the use of the Client Monitor software.
+.LP
+On Windows machines you can remove the directory
+.CW C:\eVNClient\eLinux
+to reduce the space required on Windows clients.
+.NH 1
+Server software
+.LP
+The grid server software will be installed on Linux (Redhat 8 or 9), in the directory
+.CW /grid/inferno ,
+which should either not exist or be empty.
+.LP
+Linux will usually mount the CD at
+.CW /mnt/cdrom .
+.IP 1.
+In a shell (`New Terminal') window, type the following command:
+.P1
+sh /mnt/cdrom/server/install/Linux-grid-386.sh
+.P2
+Assuming it has permission to do so, it will populate
+.CW /grid/inferno
+with the Inferno distribution, including the grid scheduler components.
+.IP 2.
+The file
+.CW /mnt/cdrom/server/install/gridsched.sh
+contains a Bourne shell script that can be copied to an appropriate
+place on your system, or used as the basis for one of your own,
+to simplify starting the scheduler.
+In particular it sets the right bin directory in
+.CW PATH
+to find Inferno's
+.I emu ,
+and starts
+.I emu
+with the right parameters to find the
+.CW /grid/inferno
+directory and start the scheduler in the right environment.
+.LP
+Now check that
+.CW /grid/inferno/grid/master/config
+contains the right network address for your scheduler.
+The manual pages
+.I scheduler-intro (1)
+and
+.I scheduler (1)
+in
+.CW scheduler.pdf
+on the CD give more details on invoking the scheduler in
+different ways.
binary files /dev/null b/doc/gridinstall.pdf differ
--- /dev/null
+++ b/doc/hotchips.ms
@@ -1,0 +1,125 @@
+.TL
+The design of the Inferno virtual machine
+.AU
+.I "Phil Winterbottom"
+.I "Rob Pike"
+.AI
+.I "Bell Labs, Lucent Technologies"
+.FS
+Originally appeared in
+.I "IEEE Compcon 97 Proceedings" ,
+1997.
+.FE
+.SP .22i exactly
+.AB
+Virtual machines are an important component of modern portable environments such as Inferno and Java because they provide an architecture-independent representation of executable code. Their performance is critical to the success of such environments, but they are difficult to design well because they are subject to conflicting goals. On the one hand, they offer a way to hide the differences between instruction architectures; on the other, they must be implemented efficiently on a variety of underlying machines. A comparison of the engineering and evolution of the Inferno and Java virtual machines provides insight into the tradeoffs in their design and implementation. We argue that the design of virtual machines should be rooted in the nature of modern processors, not language interpreters, with an eye towards on-the-fly compilation rather than interpretation or special-purpose silicon.
+.AE
+.SH
+Dis, the Inferno Virtual Machine
+.LP
+In early 1995, we set out to apply the ideas of the Plan 9 operating system [1] to a wider range of devices and networks. The resulting system, Inferno [2], is a small operating system and execution environment that supports application portability across a wide variety of processors and operating systems. Unaware of the contemporary work to establish Java [3] from the technology of the Oak project, we independently concluded that a virtual machine (VM) was a necessary component of such a system [4]. Because of improvements in processor speed and the feasibility of on-the-fly compilers, a VM can execute quickly enough to be economically viable.
+.LP
+The Inferno virtual machine, called Dis, has several unusual aspects to its design: the instruction set, the module system, and the garbage collector.
+.LP
+The Dis instruction set provides a close match to the architecture of existing processors. Instructions are of the form
+.DS
+.ft I
+OP src1, src2, dst
+.ft P
+.DE
+The
+.I "src1"
+and
+.I "dst"
+operands specify general addresses or arbitrary-sized constants, while the
+.I "src2"
+operand is restricted to smaller constants and stack offsets to reduce code space. Each operand specifies an address either in the stack frame of the executing procedure or in the global data of its module.
+.LP
+The types of operands are set by the instructions. Basic types are
+.CW "word"
+(32-bit signed),
+.CW "big"
+(64-bit signed),
+.CW "byte"
+(8-bit unsigned),
+.CW "real"
+(64-bit IEEE floating point), and pointer (implementation-dependent). The instruction set follows the example of CISC processors, providing three-operand memory-to-memory operations for arithmetic, data motion, and so on. It also has instructions to allocate memory, to load modules, and to create, synchronize, and communicate between processes.
+.LP
+A module is the unit of dynamically loaded code and data. Modules are loaded by a VM instruction that returns a pointer to a method table for the module. That pointer is managed by the VM's garbage collector, so code and data for the module are garbage collected like any other memory. Type safety is preserved by checking method types at module load time using an MD5 signature of the type.
+.LP
+Memory management is intimately tied to the instruction set of the VM. Dis uses a hybrid garbage collection scheme: most garbage is collected by simple reference counting, while a real-time coloring collector gathers cyclic data. Because reference counting is an exact rather than conservative form of garbage collection, the type of all data items must be known to the VM run-time system. For this reason, the language-to-VM compiler generates a type descriptor for all compound types. This descriptor reports the location of all pointers within the type, allowing the VM to track references as items are copied.
+.SH
+Garbage collection
+.LP
+Memory dominates the cost of small systems, so the VM should be designed to keep memory usage as small as possible. Through reference-counted garbage collection, Dis reclaims memory the moment it becomes unused. Reference counting also eliminates the need for a large arena as required for efficient mark-and-sweep collection. Both these results reduce the memory requirements of the VM and its applications.
+.LP
+Compare this to the Java VM, whose instruction set makes it difficult to track references as objects are copied. This biases against reference counting, so JVM implementations choose lazier techniques such as mark-and-sweep, inducing a larger arena and delayed collection, both of which increase the memory use and therefore the cost of the overall system.
+.SH
+Issues in compiling
+.LP
+It is easy to interpret the individual instructions of a stack-based virtual machine (SM) such as the Java virtual machine (JVM), because most operands are implicit. However, a high-level language implementation of the interpreter generates more memory traffic than the equivalent set of instructions in a memory transfer machine (MM) such as Dis. Consider the code to execute
+.P1
+c = a + b;
+.P2
+An SM would execute this by a code burst such as this, which we have annotated with its memory traffic using
+.I L
+for load and
+.I S
+for store:
+.P1
+push a # \fILS\fP
+push b # \fILS\fP
+add # \fILLS\fP
+store c # \fILS\fP
+.P2
+The corresponding MM code burst would be the plain three-operand instruction
+.P1
+add a,b,c # \fILLS\fP
+.P2
+When interpreting, the extra memory traffic of the SM is masked by the time saved by not decoding any operand fields. The operand fields are implicit in the SM instructions, while the MM they are explicit: three operand fields must be decoded in every instruction, even those without operands.
+.LP
+When compiling, the tradeoffs are different. Clearly, either design can produce the same native instructions from its just-in-time compiler (JIT), but in the SM case most of the work must be done in the JIT, whereas in the MM design the front end has done most of the work and the JIT can be substantially simpler and faster.
+.LP
+A JIT for an SM is forced to do most of the work of register allocation in the JIT itself. Because the types of stack cells change as the program executes, the JIT must track their types as it compiles. In an MM, however, the architecture maps well to native instructions. This produces a continuum of register allocation strategies from none, to simple mapping of known cells to registers, to flow-based register allocation. Most of the work of any of these strategies can be done in the language-to-VM compiler. It can generate code for an infinite-register machine, and the JIT can then allocate as many as are available in the native architecture. Again, this distribution of work keeps the JIT simple.
+.SH
+Processors
+.LP
+The same issues that face the JIT writer also face the designer of special-purpose processors to support a VM. Register allocation in the JIT is analogous to register relabeling in silicon, and an SM design adds unnecessary complexity to an already difficult problem. One might argue that a stack-based processor design would mitigate the difficulties, but our experience with the implementation of a stack machine in the AT&T Crisp microprocessor [5] leads us to believe that stack architectures are inherently slower than register-based machines. Their design lengthens the critical path by replacing simple registers with a complex stack cache mechanism.
+.LP
+In other words, it is a better idea to match the design of the VM to the processor than the other way around.
+.LP
+Dis fits this criterion better, but we do not plan to implement Dis in silicon. The idea of a VM is to be architecture-independent; offering a special processor to run it negates the original goal by favoring one instruction set. Ignoring that for the moment, though, there could still be two reasons to consider designing silicon for Dis: performance and cost.
+.LP
+On performance, history shows that language-specific CPUs are not competitive. The investment in the special design takes energy away from the systems issues that ultimately dominate performance. Performance gains realized through language-specific support tend to be offset by parallel improvements in general-purpose processors during the life cycle of the CPU.
+.LP
+Dis compiles quickly into native code that runs only 30-50% slower than native C. At the current rate of processor improvement, that is only a few months of processor design time. It is wiser to focus on improving execution on commodity, general purpose processors than on inventing a new architecture.
+.LP
+The issue of cost is more subtle. Dis is close enough to familiar architectures that a special chip with high integration of systems facilities could be cost-effective on small platforms. The real reason for that, though, is that the memory management design of the virtual machine makes it easy to implement Dis in small memory. By contrast, whatever cost gains an integrated Java processor might realize will likely be lost in the extra memory required by its conservative garbage collection scheme [6].
+.SH
+References
+.nr PS -1
+.nr VS -1
+.IP 1.
+R. Pike, D. Presotto, S. Dorward, B. Flandrena, K. Thompson, H. Trickey, and P. Winterbottom. ``Plan 9 from Bell Labs'',
+.I "J. Computing Systems"
+8:3, Summer 1995, pp. 221-254.
+.IP 2.
+Dorward, S., et al., ``Inferno'',
+.I "IEEE Compcon 97 Proceedings" ,
+1997.
+.IP 3.
+Arnold, K. and Gosling, J.,
+.I "The Java Programming Language" ,
+Addison-Wesley, 1996.
+.IP 4.
+Nori, K. V., Ammann, U., Nabeli, H. H., and Jacobi, Ch., ``Pascal P Implementation notes'', in Barron, D. W. (ed.),
+.I "Pascal\-The Language and its Implementation" ,
+Wiley, 1981, pp. 125-170.
+.IP 5.
+Ditzel, D. R. and McLellan, R., ``Register Allocation for Free: The C Machine Stack Cache'',
+.I "Proc. of Symp. on Arch. Supp. for Prog. Lang. and Op. Sys." ,
+March, 1982, pp. 48-56.
+.IP 6.
+Case, B., ``Implementing the Java Virtual Machine'',
+.I "Microprocessor Report" ,
+March 25, 1996, pp. 12-17.
binary files /dev/null b/doc/hotchips.pdf differ
--- /dev/null
+++ b/doc/install.ms
@@ -1,0 +1,1423 @@
+.de EX
+.nr x \\$1v
+\\!h0c n \\nx 0
+..
+.de FG \" start figure caption: .FG filename.ps verticalsize
+.KF
+.BP \\$1 \\$2
+.sp .5v
+.EX \\$2v
+.ps -1
+.vs -1
+..
+.de fg \" end figure caption (yes, it is clumsy)
+.ps
+.vs
+.br
+\l'1i'
+.KE
+..
+\" step numbers
+.nr ,s 0 1
+.af ,s a
+.am NH
+.nr ,s 0 1
+..
+.de Sn \" .Sn "step"
+•\ Step \\n(H1\\n+(,s: \\$1
+..
+.de Ss
+.P1
+.B
+.Sn "\\$1"
+.P2
+..
+.TL
+Installing the Inferno Software
+.AU
+Vita Nuova
+.br
+support@vitanuova.com
+.br
+12 June 2003
+.SP 4
+.LP
+Inferno can run as either a native operating system, in the usual way, or as a
+.I hosted
+virtual operating system,
+running as an application on another operating system.
+This paper explains how to install Inferno from the distribution media
+to a hosted environment and how to configure the system for
+basic networking.
+.LP
+Inferno can run as a hosted virtual operating system on top of
+Plan 9, Unix or Windows.
+In this paper, the term
+.I Unix
+is used to cover all supported variants, currently FreeBSD, Linux, HP/UX, Irix and Solaris,
+and the term
+.I Windows
+covers Microsoft Windows (98, Me, Nt, 2000, and XP).
+(Windows 98 might first require installation of the Unicode layer update from Microsoft.)
+.NH
+Preparation
+.LP
+You should ensure at least 150 Mbytes of free space on the filesystem.
+The installation program will copy files from the distribution CD to a
+directory on the filesystem called the
+.I inferno_root
+directory.
+You can choose the location of this directory.
+If you are installing to a multiuser filesystem outside your control a subdirectory of your home
+directory might be most sensible. If you plan to share the Inferno
+system with other users then common choices for
+.I inferno_root
+are
+.CW /usr/inferno
+on Unix and Plan 9 systems, and
+.CW c:\einferno
+on Windows systems.
+Where these appear in examples in this paper you should substitute
+your own
+.I inferno_root
+directory.
+.Ss "Choose the \fIinferno_root\fP directory."
+Ensure that the user who will run the installation program has
+appropriate filesystem permissions to create the
+.I inferno_root
+directory and
+files and subdirectories beneath it.
+.NH
+Copying Files
+.LP
+On all platforms the files will be owned by the user doing the installation,
+except for installation onto a FAT file system (eg, on Windows), where the files
+appear to be owned by
+.CW Everyone
+because FAT does not record ownership.
+.Ss "Insert the distribution CD into the CD drive."
+On Unix and Plan 9,
+mount the CD to a suitable location on the filesystem, call this location
+.I cd_path .
+On Windows, note the drive letter of the CD, call this drive letter
+.I cd_drive .
+The files will be copied by an Inferno hosted installation program which runs
+directly from the CD.
+The directory
+.CW /install
+on the CD contains an installation program for each supported platform \- a shell
+script for Unix and Plan 9 and an executable for Windows.
+The Plan 9 install script is called
+.CW Plan9.rc
+and determines the CPU type from the environment variable
+.CW cputype .
+The Unix install scripts all have names of the form
+.CW \fIhost_os\fP-\fIhost_arch\fP.sh
+where
+.I host_os
+will be one of:
+.CW FreeBSD ,
+.CW Linux ,
+or
+.CW Solaris
+and
+.I host_arch
+will be one of:
+.CW 386 ,
+.CW mips ,
+.CW power
+or
+.CW sparc .
+Most platforms offer just the one obvious combination.
+The Windows installation program is called
+.CW setup.exe ;
+it is used on all varieties of Windows.
+The next step describes how to begin the installation by running the program
+that corresponds to your host system.
+.Ss "Run the installation script."
+The installation program will copy files from the CD to the filesystem.
+The Windows installation program will also create registry entries and add
+an Inferno item to the Windows
+.I start
+menu.
+On Plan 9, run
+.P1
+rc \fIcd_path\fP/install/Plan9.rc \fIinferno_root\fP
+.P2
+Where
+.I inferno_root
+is the path to the chosen Inferno root directory. The CPU architecture
+will be inferred from the environment variable
+.CW cputype .
+On Unix, run
+.P1
+sh \fIcd_path\fP/install/\fIhost-os\fP-\fIhost_arch\fP.sh \fIinferno_root\fP
+.P2
+Where
+.I host_os
+is the Unix variant name
+.CW FreeBSD , (
+.CW Irix ,
+.CW Linux
+or
+.CW Solaris ).
+.I host_arch
+is the CPU type (eg,
+.CW 386 ),
+and
+.I inferno_root
+is the path to the chosen Inferno directory.
+On Windows, run
+.P1
+\fIcd_drive\f(CW:\einstall\esetup.exe
+.P2
+The Windows installation program will ask you to choose the location of the installation
+directory on the hard disk.
+.LP
+On all platforms, a copy of Inferno
+on the CD will install from various installation packages on the CD to the
+.I inferno_root
+subtree on the filesystem.
+On any platform it installs support for all.
+.LP
+Inferno is now installed, but it needs to be configured
+for your site.
+The process acts as a quick tour of parts of the system.
+The main tasks are to add local parameters to the network data base,
+and to set up the authentication system.
+If you are going to run Inferno standalone, for instance to experiment with Limbo
+and the file serving interface,
+most of what follows can be deferred indefinitely.
+It is still worthwhile skimming through it, because the first few sections tell how
+to start up Inferno with correct parameters (eg, root directory and graphics resolution).
+(A configuration program that runs under the window system would be more convenient,
+and fairly easy to do, but that has not yet been done.)
+.NH
+Running Inferno
+.LP
+Inferno host executables are all kept in a single directory corresponding
+to the combination of host operating system and CPU architecture \- the Inferno
+.CW bin
+directory.
+.P1
+\fIinferno_root\fP/\fIhost_os\fP/\fIhost_arch\fP/bin
+.P2
+(On Windows the path might need
+.CW \e
+not
+.CW /
+of course.)
+That directory can be added to the search path of the host system's command interpreter,
+and that process will be described first, although as discussed later one can use a script
+instead and that is sometimes more convenient.
+(Of course, the script will still need to refer to that directory.)
+.LP
+.I "Plan 9:\ \ "
+Plan 9 users should add a line to their
+.CW lib/profile
+file that binds this directory after their
+.CW /bin
+directory.
+.P1
+bind -a /usr/inferno/Plan9/$cputype/bin /bin
+.P2
+The bind is done after the existing
+.I bin
+directory to avoid hiding the existing Plan 9 compilers.
+If, at a later stage, you build either the hosted or native Inferno kernels for ARM or StrongARM
+you should ensure that the Inferno compilers are used rather than
+the Plan 9 compilers, since they differ in the implementation of
+floating-point instructions (the Plan 9 ARM suite uses a byte order that is more plausible
+than the order ARM dictates but therefore wrong).
+That difference is likely to be resolved at some point but it has not yet been done.
+.LP
+.I "Windows:\ \"
+The
+.I host_os
+is always
+.CW Nt
+(even for Windows 98, 2000 or XP)
+and
+.I host_arch
+is always
+.CW 386
+and the installation program will create an entry on the
+.I "start menu"
+to invoke Inferno.
+For Unix systems or Windows systems in which Inferno will be started
+from a command shell, the environment variable
+.CW PATH
+should be set to include the Inferno
+.CW bin
+directory.
+For Windows 95 and Windows 98 this should be done in the
+.CW \eautoexec.bat
+file by adding a line like
+.P1
+PATH=c:\einferno\eNt\e386\ebin;%PATH%
+.P2
+You will need to reboot Windows to have the system reread the
+.CW \eautoexec.bat
+file.
+For Windows NT and Windows 2000 modify the
+.CW Path
+environment variable through
+.I "Control Panel -> System -> Environment" .
+.LP
+If you are using an MKS or Cygwin Unix-like shell environment,
+you might instead set:
+.P1
+PATH="c:/inferno/Nt/386/bin;$PATH"
+.P2
+and export it if necessary.
+.LP
+.I "Unix:\ \"
+For Unix systems, for
+.CW sh
+derivatives, the environment variable
+.CW PATH
+should be set to include the Inferno
+.CW bin
+directory.
+This might be done in your
+.CW .profile
+file by adding a line like
+.P1
+PATH="/usr/inferno/Linux/386/bin:$PATH"
+.P2
+Don't forget to ensure that
+.CW PATH
+is exported.
+You may need to log out and back in again for the changes to take effect.
+.KS
+.Ss "Start Inferno."
+Hosted inferno is run by invoking an executable called
+.I emu .
+.KE
+On Windows, select the Inferno option from the
+.I "start menu" .
+This will invoke
+.I emu
+with appropriate arguments to find its files in
+.I inferno_root .
+If you need to change any of the options passed to
+.I emu
+when invoked from the
+.I "start menu"
+you need to do this by clicking the right mouse button
+on the Windows task bar and choosing
+.I "Properties -> Start Menu Programs -> Advanced"
+to modify the shortcut used for Inferno.
+For Unix and Plan 9, you will need to tell
+.I emu
+where to find the Inferno file tree by passing it the
+.CW -r\fIrootpath\f(CW
+command line option. For example
+.P1
+emu -r/usr/john/inferno
+.P2
+Without the
+.CW -r
+option it will look for the file tree in
+.CW /usr/inferno
+on Plan 9 and Unix and, when invoked from the command line on WIndows,
+the default is
+.CW \einferno
+on the current drive.
+(The Windows start menu by contrast has already been set to use the right directory by the installation software.)
+.LP
+When using graphics,
+.I emu
+will use a window with a resolution of 640 x 480 pixels by default. To use a larger resolution
+you will need to pass
+.I emu
+an option
+.CW -g\fIXsize\f(CWx\fIYsize\f(CW
+on the command line. So, for example, to invoke
+.I emu
+as above but with a resolution of 1024 x 768 pixels the full command line
+would be
+.P1
+emu -r/usr/john/inferno -g1024x768
+.P2
+When invoked in this way
+.I emu
+displays a command window running the Inferno shell
+.CW /dis/sh.dis .
+To avoid typing the command line options each time you invoke
+.I emu
+you can store them in the environment variable
+.CW EMU
+which is interrogated when
+.I emu
+is started and might as well be set along side the
+.CW PATH
+environment variable if the same configuration options are to be used on
+each invocation.
+.P1
+set EMU="-rd:\eDocuments and Settings\ejohn\einferno -g1024x768"
+.P2
+for Windows.
+.P1
+EMU=(-r/usr/john/inferno -g1024x768)
+.P2
+for Plan 9, and
+.P1
+EMU="-r/usr/john/inferno -g1024x768"
+.P2
+for Unix.
+An alternative to using the
+.CW EMU
+environment variable is to place the correct invocation in a
+script file (or batch file, for Windows) and invoke that instead
+of running
+.I emu
+directly.
+It is important to note that for Windows the
+.CW -r
+option also serves to indicate both the drive and directory on to which the software
+has been installed. Without a drive letter the system will assume the
+current drive and will fail if the user changes to an alternative drive.
+Once the environment variables or scripts are set up, as described above, invoking plain
+.P1
+emu
+.P2
+or the appropriate script file,
+should result in it starting up Inferno's command interpreter
+.I sh (1),
+which prompts with a semicolon:
+.P1
+;
+.P2
+You can add a further option
+.CW -c1
+to start up
+.I emu
+in a
+mode in which the system compiles a module's
+Dis operations to native machine instructions when a module
+is loaded.
+(See the
+.I emu (1)
+manual page.)
+In
+.I compile
+mode programs that do significant computation will run much faster.
+Whether in compiled or interpreted mode you should now have a functional
+hosted Inferno system.
+When Inferno starts the initial
+.CW /dis/sh.dis
+it reads commands from the file
+.CW /lib/sh/profile
+before becoming interactive. See the manual pages for the shell
+.I sh (1)
+to learn more about tailoring the initial environment.
+.LP
+The semicolon is the default shell prompt. From this command window
+you should be able to see the installed Inferno files and directories
+.P1
+lc /
+.P2
+The command
+.I lc
+presents the contents of its directory argument in columnar fashion to standard
+output in the command window.
+.P1
+; lc /
+FreeBSD/ Unixware/ icons/ libkern/ man/ prof/
+Hp/ acme/ include/ libkeyring/ mkconfig prog/
+Inferno/ appl/ keydb/ libmath/ mkfile services/
+Irix/ asm/ legal/ libmemdraw/ mkfiles/ tmp/
+LICENCE chan/ lib/ libmemlayer/ mnt/ tools/
+Linux/ dev/ lib9/ libtk/ module/ usr/
+MacOSX/ dis/ libbio/ licencedb/ n/ utils/
+NOTICE doc/ libcrypt/ limbo/ net/ wrap/
+Nt/ emu/ libdraw/ locale/ nvfs/
+Plan9/ env/ libfreetype/ mail/ o/
+Solaris/ fonts/ libinterp/ makemk.sh os/
+;
+.P2
+Only the files and directories in and below the
+.I inferno_root
+directory on the host filesystem are immediately visible to an Inferno process;
+these files are made visible in the root of the Inferno file namespace.
+If you wish to import or export files
+from and to the host filesystem you will need to use tools on your
+host to move them in or out of the Inferno visible portion of your host
+filesystem (see the manual pages
+.I os (1)
+and
+.I cmd (3)
+for an interface to host commands).
+(We plan to make such access direct, but the details are still being worked out.)
+From this point onwards in this paper all file paths not qualified with
+.I inferno_root
+are assumed to be in the Inferno namespace.
+Files created in the host filesystem will be created with the user id of
+the user that started
+.I emu
+and on Unix systems with that user's group id.
+.NH
+Setting the site's time zone
+.LP
+Time zone settings are defined by
+files in the directory
+.CW /locale .
+The setting affects only how the time is displayed; the internal representation does not vary.
+For instance, the file
+.CW /locale/GMT
+defines Greenwich Mean Time,
+.CW /locale/GB-Eire
+defines time zones for Great Britain and the Irish Republic
+(GMT and British Summer Time), and
+.CW /locale/US_Eastern
+defines United States
+Eastern Standard Time and Eastern Daylight Time.
+The time zone settings used by applications are read
+(by
+.I daytime (2))
+from the file
+.CW /locale/timezone ,
+which is initially a copy of
+.CW /locale/GB-Eire .
+If displaying time as the time in London is adequate, you need change nothing.
+To set a different time zone for the whole site,
+copy the appropriate time zone file into
+.CW /locale/timezone :
+.P1
+cp /locale/US_Eastern /locale/timezone
+.P2
+To set a different time zone for a user or window,
+.I bind (1)
+the file containing the time zone setting over
+.CW /locale/timezone ,
+either in the user's profile or in a name space description file:
+.P1
+bind /locale/US_Eastern /locale/timezone
+.P2
+.NH
+Running the
+Window Manager
+.I wm
+.LP
+Graphical Inferno programs normally run under the window manager
+.I wm (1).
+Inferno has a simple editor,
+.I wm/edit ,
+that can be used to edit the inferno configuration files.
+The `power environment' for editing and program development is
+.I acme (1),
+but rather that throwing you in at the deep end, we shall stick to
+the simpler one for now.
+If you already know Acme from
+Plan 9, however, or perhaps Wily from Unix, feel free to use Inferno's
+.I acme
+instead of
+.I edit .
+.Ss "Start the window manager."
+Invoke
+.I wm
+by typing
+.P1
+wm/wm
+.P2
+You should see a new window open with a blue-grey background and a small
+.I "Vita Nuova"
+logo in the bottom left hand corner. Click on the logo with mouse button 1
+to reveal a small menu.
+Selecting the
+.I Edit
+entry will start
+.I wm/edit .
+In common with most
+.I wm
+programs the editor has three small buttons in a line at its top right hand corner.
+Clicking on the X button, the rightmost button,
+will close the program down. The leftmost of the three buttons will allow the window
+to be resized \- after clicking it drag the window from a point near to either one of its
+edges or one of its corners. The middle button will minimise the window, creating
+an entry for it in the application bar along the bottom of the main
+.I wm
+window. You can restore a minimised window by clicking on its entry in the application bar.
+The initial
+.I wm
+configuration is determined by the contents of the shell
+script
+.CW /lib/wmsetup
+(see
+.I toolbar (1)
+and
+.I sh (1)).
+.Ss "Open a shell window."
+Choose the
+.I shell
+option from the menu to open up a shell window. The configuration of Inferno
+will be done from this shell window.
+.NH
+Manual Pages
+.LP
+Manual pages for all of the system commands are available from a shell
+window. Use the
+.I man
+or
+.I wm/man
+commands. For example,
+.P1
+man wm
+.P2
+will give information about
+.I wm .
+And
+.P1
+man man
+.P2
+will give information about using
+.I man .
+.I Wm/man
+makes use of the Tk text widget to produce slightly more
+attractive output than the plain command
+.I man .
+Here, and in other Inferno documentation you will see references to manual page
+entries of the form \fIcommand\f(CW(\fIsection\f(CW)\fR.
+You can display the manual page for the command by running
+.P1
+man \fIcommand\fP
+.P2
+or
+.P1
+man \fIsection\fP \fIcommand\fP
+.P2
+if the manual page appears in more than one section.
+.NH
+Initial Namespace
+.LP
+The initial Inferno namespace is built
+by placing the root device '#/' (see
+.I root (3))
+at the root of the namespace and binding
+.nr ,i 0 1
+.af ,i i
+.IP \n+(,i)
+the host filesystem device '#U' (see
+.I fs (3))
+containing the
+.I inferno_root
+subtree of the host filesystem at the root of the Inferno filesystem,
+.IP \n+(,i)
+the console device '#c' (see
+.I cons (3))
+in
+.CW /dev ,
+.IP \n+(,i)
+the prog device '#p' (see
+.I prog (3))
+onto
+.CW /prog ,
+.IP \n+(,i)
+the IP device '#I' (see
+.I ip (3))
+in
+.CW /net ,
+and
+.IP \n+(,i)
+the environment device '#e' (see
+.I env (3))
+at
+.CW /dev/env .
+.rr ,i
+.LP
+You can see the sequence of commands required to construct the current namespace
+by running
+.P1
+ns
+.P2
+.NH
+Inferno's network
+.LP
+If you are just going to use Inferno for local Limbo programming, and not use its
+networking interface, you can skip to the section ``Adding new users'' at the end of this document.
+You can always come back to this step later.
+.LP
+To use IP networking, the IP device
+.I ip (3)) (
+must have been bound into
+.CW /net .
+Typing
+.P1
+ls -l /net
+.P2
+(see
+.I ls (1))
+should result in something like
+.P1
+--rw-rw-r-- I 0 network john 0 May 31 07:11 /net/arp
+--rw-rw-r-- I 0 network john 0 May 31 07:11 /net/ndb
+d-r-xr-xr-x I 0 network john 0 May 31 07:11 /net/tcp
+d-r-xr-xr-x I 0 network john 0 May 31 07:11 /net/udp
+.P2
+There might be many more names on some systems.
+.LP
+A system running Inferno, whether native or hosted, can by agreement attach to any or all resources that
+are in the name space of another Inferno system (or even its own).
+That requires:
+.IP •
+the importing system must know where to find them
+.IP •
+the exporting system must agree to export them
+.IP •
+the two systems must authenticate the access (not all resources will be permitted to all systems or users)
+.IP •
+the conversation can be encrypted to keep it safe from prying eyes and interference
+.LP
+On an Inferno network, there is usually one secure machine that acts as authentication server.
+All other systems variously play the rôles of server and client as required: any system can import some resources (or none)
+and export others (or none), simultaneously, and differently in different name spaces.
+In following sections, we shall write as though there were three distinct machines:
+authentication server (signer); server (exporting resources); and client (importing resources).
+With Inferno, you can achieve a similar effect on a single machine by starting up distinct
+instances of
+.I emu
+instead.
+That is the easiest way to become familiar with the process (and also avoids having to install
+the system on several machines to start).
+It is still worthwhile setting up a secured
+authentication server later, especially if you are using Windows on a FAT file system
+where the host system's file protections are limited.
+.LP
+We shall now configure Inferno to allow each of the functions listed above:
+.IP •
+change the network database to tell where to find local network resources
+.IP •
+set up the authentication system, specifically the authentication server or `signer'
+.IP •
+start network services (two distinct sets: one for the authentication services and the other for
+all other network services)
+.NH
+Network database files
+.LP
+In both hosted and native modes, Inferno uses a collection of text files
+of a particular form to store all details of network and service configuration.
+When running hosted, Inferno typically gets most of its data from the host operating system,
+and the database contains mainly Inferno-specific data.
+.LP
+The file
+.CW /lib/ndb/local
+is the root of the collection of network database files.
+The format is defined by
+.I ndb (6),
+but essentially it is a collection of groups of attribute/value pairs of the form
+\fIattribute\fP\f(CW=\fP\fIvalue\fP.
+Attribute names and most values are case-sensitive.
+.LP
+Related attribute/value pairs are grouped into database `entries'.
+An entry can span one or more
+lines: the first line starts with a non-blank character,
+and any subsequent lines in that entry start
+with white space (blank or tab).
+.NH 2
+Site parameters
+.LP
+The version of
+.CW /lib/ndb/local
+at time of writing looks like this:
+.P1
+database=
+ file=/lib/ndb/local
+ file=/lib/ndb/dns
+ file=/lib/ndb/inferno
+ file=/lib/ndb/common
+
+infernosite=
+ #dnsdomain=your.domain.com
+ #dns=1.2.3.4 # resolver
+ SIGNER=your_Inferno_signer_here
+ FILESERVER=your_Inferno_fileserver_here
+ smtp=your_smtpserver_here
+ pop3=your_pop3server_here
+ registry=your_registry_server
+.P2
+The individual files forming the data base are listed in order in the
+.CW database
+entry.
+They can be ignored for the moment.
+The entry labelled
+.CW infernosite=
+defines a mapping from symbolic host names of the form
+.CW $\fIservice\f(CW
+to a host name, domain name, or a numeric Internet address.
+For instance, an application that needs an authentication service
+will refer to
+.CW $SIGNER
+and an Inferno naming service will translate that at run-time to the appropriate network name for
+that environment.
+Consequently,
+the entries above need to be customised for a given site.
+(The items that are commented out are not needed when the host's own DNS resolver is used instead
+of Inferno's own
+.I dns (8).)
+For example, our
+.CW infernosite
+entry in the
+.CW local
+file might look something like this
+.P1
+infernosite=
+ dnsdomain=vitanuova.com
+ dns=200.1.1.11 # resolver
+ SIGNER=doppio
+ FILESERVER=doppio
+ smtp=doppio
+ pop3=doppio
+ registry=doppio
+.P2
+where
+.CW doppio
+is the host name of a machine that is offering the given services to Inferno,
+and
+.CW 200.1.1.11
+is the Internet address of a local DNS resolver.
+.Ss "Enter defaults for your site"
+.LP
+The only important names initially are:
+.IP \f(CWSIGNER\fP 20
+the host or domain name, or address of the machine that will act as signer
+.IP \f(CWregistry\fP
+the name or address of a machine that provides the local dynamic service
+.I registry (4)
+.IP \f(CWFILESERVER\fP
+the primary file server (actually needed only by clients with no storage of their own)
+.LP
+All others are used by specific applications such as
+.I acme (1)
+mail or
+.I ftpfs (4).
+.LP
+If you are using a single machine for signer and server/client, put its name in those three entries.
+.NH 2
+Connection server
+.I cs (8)
+and name translation
+.LP
+The connection server
+.I cs (8)
+uses the network database
+and other
+data (such as that provided by the host system and
+the Internet DNS servers) to translate symbolic network names and services into instructions
+for connecting to a given service.
+In hosted mode,
+network and service names are passed through to the host for conversion to numeric IP
+addresses and port numbers. If the host is unable to convert a service name
+the connection server will attempt to convert the name using mappings
+of service and protocol names to Internet port numbers
+in the file
+.CW /lib/ndb/inferno :
+.P1
+tcp=infgamelogin port=6660 # inferno games login service
+tcp=styx port=6666 # main file service
+tcp=mpeg port=6667 # mpeg stream
+tcp=rstyx port=6668 # remote invocation
+tcp=infdb port=6669 # database server
+tcp=infweb port=6670 # inferno web server
+tcp=infsigner port=6671 # inferno signing services
+tcp=infcsigner port=6672 # inferno countersigner
+tcp=inflogin port=6673 # inferno credential service
+tcp=infsds port=6674 # software download
+tcp=registry port=6675 # registry(4)
+udp=virgil port=2202 # naming service
+.P2
+For the moment, leave that file as it is.
+You will only need to modify this file if in future
+you add new statically-configured services to Inferno.
+(Services that come and go dynamically might use
+.I registry (4)
+instead, a registry manager that allows a service to be found
+using a description of it.)
+.NH
+Configuring a Signer
+.LP
+Before an Inferno machine can authenticate establish a secure connection to an Inferno
+service on another machine, each system needs to obtain a certificate from a common signer.†
+We talk here as though there is only one `signer' per site but in fact there can be application- or
+group-specific ones.
+For instance, a version of the Inferno games server automatically starts its own signing service to
+keep the identities and keys used for game service separate from those of the primary
+system, allowing users to set up their own gaming groups without fuss.
+.FS
+.FA
+†The authentication system will shortly expand to a rôle-based one allowing a chain of certificates to be used,
+from several signers, with delegation etc.
+.FE
+To use authenticated connections for the primary
+file services we need to set up a signer to generate
+certificates for users (see
+.I createsignerkey (8)
+and
+.I logind (8)).
+.LP
+Choose an Inferno machine to become the signer.
+If this is the first or only
+Inferno machine on your network then make this machine the signer.
+(It is more realistic if you start up a separate copy of
+.I emu
+and leave it in `console' mode without starting the window system.)
+You can always move the function elsewhere later.
+.Ss "Empty the secret file of secrets."
+The authentication server verifies a user's identity by checking that the user knows a shared secret.
+(In fact the secret is not used directly, but instead a scrambled value that was derived from it.)
+The file
+.CW /keydb/keys
+holds those secrets; it is encrypted using a secret password or phrase known only to the
+manager of the authentication server.
+Having just installed Inferno, the file
+should exist and be readable only by you (or the user as which the authentication service will run).
+On the signer machine, type
+.P1
+ls -l /keydb/keys
+.P2
+You should see something like:
+.P1
+--rw------- M 7772 yourname inf 0 Jun 12 03:08 /keydb/keys
+.P2
+You should see something like the above.
+If the file does not exist or is not empty or has the wrong mode, use:
+.P1
+cp /dev/null /keydb/keys; chmod 600 /keydb/keys
+.P2
+to set it right.
+.Ss "Generate a signer key."
+Next on the signer machine, run
+.P1
+auth/createsignerkey \fIname\fP
+.P2
+In place of
+.I name
+enter the network name of the signer. A fully-qualified domain name of a
+host or individual is fine.
+This value will appear as the signer name in each
+certificate generated by the signer.
+.I Createsignerkey
+creates public and private keys that are used by the signer when generating
+certificates.
+They are stored in
+.CW /keydb/signerkey ;
+check that it has permissions that limit access to the user that will run the
+authentication services:
+.P1
+; ls -l /keydb/signerkey
+--rw------- M 32685 secrets inf 1010 Jul 07 2000 /keydb/signerkey
+.P2
+Use
+.I chmod (1)
+to set the mode to read/write only for the owner if necessary:
+.P1
+chmod 600 /keydb/signerkey
+.P2
+.Ss "Start the authentication network services"
+Still at the signer console, type
+.P1
+svc/auth
+.P2
+That script (see
+.I svc (8))
+will check that the
+.CW /keydb/keys
+and
+.CW /keydb/signerkey
+files exist, and then
+start the program
+.I keyfs (4),
+which manages the
+.CW keys
+file.
+It will prompt for the password (pass phrase) you wish to use to protect the
+.CW keys
+file, now and on subsequent runs:
+.P1
+; svc/auth
+Key:
+Confirm key:
+.P2
+It prompts twice to confirm it.
+If successfully confirmed, it will then
+start the
+network services used by Inferno to authenticate local and remote users and hosts.
+(If confirmation fails, retry by running
+.CW svc/auth
+again.)
+.LP
+You can check that they are running by typing:
+.P1
+ps
+.P2
+which should show something like the following:
+.P1
+ 1 1 john release 74K Sh[$Sys]
+ 3 2 john alt 15K Cs
+ 10 9 john recv 25K Keyfs
+ 11 9 john release 44K Styx[$Sys]
+ 12 9 john recv 25K Keyfs
+ 14 1 john alt 8K Listen
+ 16 1 john release 8K Listen[$Sys]
+ 18 1 john alt 9K Listen
+ 20 1 john release 9K Listen[$Sys]
+ 22 1 john alt 9K Listen
+ 24 1 john release 9K Listen[$Sys]
+ 26 1 john alt 8K Listen
+ 28 1 john release 8K Listen[$Sys]
+ 29 1 john ready 73K Ps[$Sys]
+.P2
+There should be
+.CW Keyfs
+and
+.CW Listen
+processes.
+.Ss "Enter user names and secrets."
+For each user to be authenticated by the signer run
+.P1
+auth/changelogin \fIusername\fP
+.P2
+You will be prompted to supply a secret (ie, password or pass phrase) and expiration date.
+The expiration date will be used
+as the maximum expiration date of authentication certificates granted to that user.
+.I Changelogin
+(see
+.I changelogin (8))
+accesses the name space generated by
+.I keyfs (4),
+which has just been started above by
+.CW svc/auth .
+A user can later change the stored secret using the
+.I passwd (1)
+command.
+For the signer to generate a certificate there must be at least one entry in the
+password file.
+If you are not sure at this stage of the names of the users that you want to
+authenticate then create an entry for the user
+.CW inferno
+and yourself.
+.NH
+Establishing a Secure Connection
+.LP
+To establish a secure connection between two Inferno machines, each needs to present a public key with
+a certificate signed by a common signer.
+We shall make two public/private key sets, one for the server and one for a client
+(they differ only in where they are stored).
+We shall do the server first, because the usual network services require
+the server possess some keys before they can start.
+We shall then start those services, and finally sort out the client.
+.Ss "Start the connection service."
+The server still needs to make contact with the signer, so we need to start the basic connection service
+.I cs (8).
+If you are using the same instance of
+.I emu
+in which you invoked
+.CW svc/auth
+above, you should skip this step.
+To check, you should see a new file in the
+.CW /net
+directory called
+.CW cs .
+Run the command
+.P1
+ls /net
+.P2
+You should see at least the following names in the output:
+.P1
+/net/cs
+/net/ndb
+/net/tcp
+/net/udp
+.P2
+Otherwise, type
+.P1
+ndb/cs
+.P2
+That starts
+.I cs (8).
+Try the
+.CW "ls /net"
+again to check that the
+.CW cs
+file has appeared.
+.LP
+.Ss "Generate a server key set."
+On the server machine (or in the `server' window),
+use
+.I getauthinfo (8)
+to obtain a certificate and save it in a file named
+.CW default
+by running
+.P1
+getauthinfo default
+.P2
+.I Getauthinfo
+will prompt for the address of your signer (you can often
+just use its host name or even
+.CW localhost )
+and for a remote username and password
+combination.
+.I Getauthinfo
+will connect to the
+.I inflogin
+service on the signer and authenticate you against its user and password database,
+.CW /keydb/keys ,
+using the username and password that you entered above.
+Answer
+.CW yes
+to the question that asks if you want to save the certificate in a file.
+.I Getauthinfo
+will save a certificate in the file
+.CW /usr/\fIuser\f(CW/keyring/default
+where
+.I user
+is the name in
+.CW /dev/user .
+.NH
+Network Services
+.LP
+As mentioned above, in a full Inferno network
+the authentication services will usually be run on a secured machine of their own (the signer),
+and the ordinary network services such as file service are not run on a signer.
+If you are, however, using one machine for all functions, you can get the right
+effect by starting another instance of
+.I emu ,
+to act as an Inferno host that is not a signer.
+This one will run the services of a primary file server
+and the site
+.I registry (4).
+.LP
+Commands described in
+.I svc (8)
+start listeners for various local network services.
+(The commands are actually shell scripts.)
+As we saw above,
+.CW svc/auth
+starts the services on a signer.
+.LP
+Here we shall start the usual set of services.
+.KS
+.Ss "Start the network listener services."
+Type
+.P1
+svc/net
+.P2
+.KE
+Various network services will (should!) now be running. To confirm this type
+.P1
+ps
+.P2
+which should show something like the following:
+.P1
+; ps
+ 1 1 inferno release 74K Sh[$Sys]
+ 7 6 inferno alt 15K Cs
+ 13 1 inferno recv 15K Registry
+ 14 1 inferno release 44K Styx[$Sys]
+ 15 1 inferno recv 15K Registry
+ 17 1 inferno alt 8K Listen
+ 19 1 inferno release 8K Listen[$Sys]
+ 22 1 inferno alt 8K Listen
+ 24 1 inferno release 8K Listen[$Sys]
+ 25 1 inferno ready 74K Ps[$Sys]
+.P2
+There should be a few
+.CW Listen
+processes and perhaps a
+.CW Registry .
+.LP
+You can also try
+.P1
+netstat
+.P2
+.I Netstat
+prints information about network connections. You should see
+several lines of output, each one describing an announced TCP or UDP service.
+Depending upon the contents of the network configuration files we included on the CD,
+you might see output something like this:
+.P1
+tcp/1 Announced inferno 200.1.1.89!6668 ::!0
+tcp/2 Announced inferno 200.1.1.89!6666 ::!0
+tcp/3 Announced inferno 200.1.1.89!6675 ::!0
+.P2
+Each line corresponds to a network connection:
+the connection name, the name of the user running the server,
+the address of the local end of the connection,
+the address of the remote end of the connection,
+and the connection status.
+The connection name is actually the protocol and conversation directory
+in
+.CW /net .
+The connection addresses are all of the form \fIhost\f(CW!\fIport\fR
+for these IP based services, and the remote addresses are not filled in
+because they all represent listening services that are in the
+.CW Announced
+state.
+In this example the third line shows a TCP service listening on port 6675.
+Examining
+.CW /lib/ndb/inferno
+with
+.CW grep
+(see
+.I grep (1))
+shows that the listener on port 6675 is the Inferno registry service
+.P1
+grep 6675 /lib/ndb/inferno
+.P2
+gives
+.P1
+tcp=registry port=6675 # default registry
+.P2
+.LP
+Now the server is ready but we need a client.
+.LP
+Either use a third machine or (more likely at first) simply start another
+.I emu
+instance in a new window.
+Start its connection server, again by typing
+.P1
+ndb/cs
+.P2
+The connection server is fundamental to the Inferno network.
+Once networking is set up, when subsequently starting up
+a client you should start
+.I cs
+before starting the window system.
+Note that if you are running the Inferno instance as a server, or combined
+server and client,
+the
+.CW svc/net
+that starts the network services
+automatically starts
+.I cs ,
+and you need not do so explicitly.
+.LP
+.Ss "Generate a client certificate."
+Obtain a certificate for the client in the same way as on the server.
+We shall obtain a certificate for use with a specific server
+by storing
+it in a file whose name exactly matches the network address of the server
+.P1
+getauthinfo tcp!\fIhostname\fP
+.P2
+Use the current machine's
+.I hostname .
+.I Getauthinfo
+stores the certificate in the file
+.CW /usr/\fIuser\fP/keyring/\fIkeyname\fP
+where
+.I user
+is the name in
+.CW /dev/user
+and
+.I keyname
+is the argument given to
+.I getauthinfo .
+Again,
+answer
+.CW yes
+to the question that asks if you want to save the certificate in a file.
+.LP
+Now that both client and server have a certificate obtained from the same signer
+it is possible to establish a secure connection between them.
+Note that getting keys and certificates with
+.I getauthinfo
+is normally done just once (or at most once per server when the
+.CW default
+key is not used).
+In short, all the work done up to now need not be repeated.
+After this, provided the keys were saved to a keyring file,
+as many authenticated connections can be made as desired
+until the certificate expires (which by default is whenever the password entry
+was set to expire).
+Also note that the certificates for different machines can have
+different signers, and one can even use different certificates for the same machine
+when the remote user name is to differ
+(the
+.CW -f
+option of
+.I getauthinfo
+can then be useful to force an appropriate keyring name).
+.Ss "Make an authenticated connection."
+The script
+.CW svc/net
+on the server started fundamental name services and also a Styx file service.
+That can also be started separately using
+.CW svc/styx .
+In either case the namespace that is served
+is the one in which the command was invoked.
+Now you can test the service.
+.LP
+Confirm that
+.CW /n/remote
+is an empty directory by typing
+.P1
+lc /n/remote
+.P2
+You can now mount the server's name space
+onto the client's directory
+.CW /n/remote
+by typing
+.P1
+mount \fIserveraddr\fP /n/remote
+.P2
+Where
+.I serveraddr
+is the IP address of the server or a name that the host can resolve to the
+IP address of the server.
+Now
+.P1
+lc /n/remote
+.P2
+should reveal the files and directories in the namespace being served by the server.
+Those files are now also visible in the namespace of your shell.
+You will notice that these changes only affect the shell in which you ran the
+.I mount
+command \- other windows are unaffected.
+You can create, remove or modify files and directories in and under
+.CW /n/remote
+much as you can any other file or directory in your namespace.
+In fact, in general, a process does not need to know whether a file
+actually resides locally or remotely.
+You can unmount the mounted directory with
+.I unmount .
+Type
+.P1
+unmount /n/remote
+.P2
+You can confirm that it has gone by running
+.P1
+ls /n/remote
+.P2
+All connections made by Inferno are authenticated. The default connection
+made by
+.I mount
+is authenticated but uses neither encryption nor secure digests.
+You can pass an argument to
+.I mount
+to specify
+a more secure connection:
+its
+.CW -C
+option gives it a hashing and an encryption algorithm to be applied to
+the connection.
+.KS
+.Ss "Make a secure authenticated connection."
+For example,
+.P1
+mount -C sha1/rc4_256 \fIserveraddr\fP /n/remote
+.P2
+makes an authenticated connection to the machine given by
+.I serveraddr ,
+then engages SHA1 hashing for message digesting and 256-bit RC4 for encryption.
+.KE
+It mounts the namespace served by
+.I serveraddr 's
+Styx service on the local Inferno directory
+.CW /n/remote .
+.NH
+Adding new users
+.LP
+Every inferno process has an associated
+.I "user name" .
+At boot time the user name is set equal to your login name on the host
+operating system.
+The user name is used by
+.I wm/logon
+to select the home directory, and
+by other programs like
+.I mount
+when it searches for certificates.
+(It can also control permission for file access on the local system in native Inferno
+and some hosted Inferno configurations.)
+When you attach to a server on another
+system the user name in the authenticating certificate can be used by
+the remote file service to set the user name appropriately there.†
+.FS
+.FA
+†The details are system-dependent and currently subject to change.
+.FE
+.LP
+To create a new user, copy the directory
+.CW /usr/inferno
+into
+\f(CW/usr/\fP\fIusername\fP.
+If the user is to have access to services on the network,
+make an authentication server entry using
+.I changelogin (8).
+The user can change the stored secret using
+.I passwd (1),
+if desired.
+Having logged in for the first time, the user should generate
+a default public/private key set using
+.I getauthinfo (8).
+(The authentication services must be running somewhere.)
+.LP
+The
+.I wm
+window manager program
+.I wm/logon
+allows a user to login to the local Inferno system as an Inferno
+user (different from the host user name).
+Its use is shown next.
+.Ss "Re-start Inferno."
+You should now close down any instances of
+.I emu
+that you are currently running.
+The quickest way to do this is to
+type
+.I control-c
+in the emu window in which you ran
+.I wm/wm .
+Start a new
+.I emu ,
+as before, by either running
+.P1
+emu
+.P2
+or by choosing the appropriate entry from your start menu on
+Windows machines. This time, start network services
+.P1
+svc/net
+.P2
+and then run
+.P1
+wm/wm wm/logon
+.P2
+and log in as user
+.I inferno .
+When you log in,
+.I wm/logon
+will change directory to
+.CW /usr/inferno
+and then write the name
+.CW inferno
+to
+.CW /dev/user .
+If the file
+.CW /usr/inferno/namespace
+exists it will be used to construct a new namespace for the user
+based on the commands that it contains (see
+.I newns (2)).
+.NH
+What next
+.LP
+You should now have a fully functional Inferno system.
+You will need to have a three button mouse to use
+.I acme ,
+.I wm ,
+or
+.I plumbing .
+.LP
+To learn more you could start with the manual pages for:
+.I intro (1),
+.I emu (1),
+.I wm (1),
+.I wm-misc (1),
+.I sh (1),
+.I acme (1),
+and
+.I limbo (1)
+and also the papers in sections 1, 2 and 3
+of Volume 2 of
+.I "The Inferno Programmer's Manual" .
binary files /dev/null b/doc/install.pdf differ
--- /dev/null
+++ b/doc/lego.ms
@@ -1,0 +1,642 @@
+.TL
+Styx-on-a-Brick
+.AU
+Chris Locke
+.br
+chris@vitanuova.com
+.AI
+Vita Nuova
+.br
+June 2000
+.SH
+Background
+.LP
+The aim of the Vita-Nuova ``styx-on-a-brick'' project was
+to demonstrate the simplicity of the Styx protocol and the ease
+with which a Styx `stub' can be implemented on tiny devices.
+We also aimed to demonstrate the effectiveness of a protocol based approach
+to resource management and sharing, whether the resource be a physical device
+or a software service.
+.LP
+Adopting a protocol-centric view of resource and service management, as opposed to
+a language-centric approach (as emphasised for instance by Jini™ with Java)
+greatly eased the software burden on our tiny target device \-
+implementing a simple protocol in firmware required much less work than trying to
+implement a virtual machine. We are confident that if we had adopted a language-centric
+approach, we would not have completed the project within our aggressive space and implementation time constraints.†
+.FS
+.FA
+†Indeed, we later discovered that in the application of Jini to load code into an RCX robot no part
+of Jini was actually on the brick.
+.FE
+.LP
+The project took 2 weeks from start to finish.
+In this time the firmware was developed and all client software
+was written: firmware download, IR-link protocol support,
+clockface application and worldclock application.
+Two people worked on the project, one full-time, the other (Nigel Roles) part-time.
+.LP
+The demo was then taken on a Press Conference tour of the US
+and later appeared at the Usenix2000 Plan 9/Inferno BOF at the request
+of Dennis Ritchie.
+.LP
+I should stress that the project was a demonstration of the ease of
+supporting Styx on small devices \- it was not a demo of robotics!
+(Indeed, the design of the IR-link protocol, Styx name space and the
+services provided by the firmware would be considerably different for
+serious robotics.)
+.LP
+The project used a standard Lego™ Mindstorms™ robotics kit \-
+the ``Robotics Invention System''. This consists of the RCX brick,
+2 motors, 2 button sensors, a light sensor and a whole load of
+lego pieces \- including wheels, gears and axles; which all adds up
+to a whole load of fun!
+.LP
+The RCX brick is an Hitachi H8 microcontroller with 32K of RAM and
+a 16K ROM BIOS. The RCX provides 3 motor outputs and 3 sensor inputs.
+Communication with the RCX is via IR. An IR tower is supplied with the
+``Robotics Invention System'' that connects to a PC via a serial port.
+.SH
+Acknowledgements
+.LP
+Before going any further I must acknowledge the work of Kekoa Proudfoot at
+Stanford and Russ Nelson at Crynwr Software.
+Without their valiant efforts we would not have been able to pursue this project.
+Our work relied on the documents and librcx suite provided by Kekoa:
+.P1
+http://graphics.stanford.edu/~kekoa/rcx/
+.P2
+and on information from Russ Nelson's web site
+.P1
+http://www.crynwr.com/lego-robotics/
+.P2
+.SH
+Files
+.LP
+The files in the
+.CW legostyx.tar
+file are shown in Table 1.
+.KF
+.TS
+center;
+lf(CW) lfR .
+llp.h Link level protocol constants
+styx.c The firmware implementation
+styx.srec The firmware image (S-record format)
+styx_abp.srec The firmware with the alternating bit part of the link protocol enabled
+send.b Test app \- sends RCX op codes to the brick
+firmdl.b Firmware download app
+rcxsend.m Util module header
+rcxsend.b Util module \- supports RCX ROM message format on serial link
+timers.m Timer module header
+timers.b Util module \- general purpose timers
+legolink.b Implements the link protocol via a limbo file2chan()
+clockface.b The controller app for our Clockface robot
+.TE
+.fi
+.ce 10
+.I "Table 1.\ "\c
+Files in the Styx-on-a-Brick package
+.ce 0
+.KE
+.SH
+Project details
+.NH 1
+Firmware Download
+.LP
+The RCX brick comes supplied with Lego firmware to be downloaded into the RAM via
+the IR link. The ROM implements a monitor which provides for the firmware download,
+as well as other 'op-codes'.
+.LP
+We wrote our own firmware in C using the GNU H8 compiler suite on a FreeBSD machine.
+The code used Kekoa's
+.CW librcx
+library for interfacing to the RCX ROM routines.
+(We should have liked to have done an H8 code generator for our own compiler suite,
+but time did not permit this!)
+The
+.CW gnuh8
+list is accessible via:
+.P1
+http://www.pcserv.demon.co.uk/
+.P2
+First up we had to write a Limbo application to communicate with the ROM, via
+the IR tower in order that we could get our firmware downloaded onto the RCX.
+This is the firmdl application. Source files:
+.CW firmdl.b ,
+.CW rcxsend.b
+and
+.CW timers.b
+.NH 1
+Styx Comms Link
+.LP
+Having got a means of installing our firmware we needed a means of delivering
+Styx messages to and from the Brick.
+.LP
+Styx makes certain demands of its transport media:
+.TS
+l l .
+Reliable messages must not get 'lost'
+Ordered messages must not get transposed
+.TE
+The RCX ROM provides a couple of functions for IR comms \- a routine to check
+for message reception and a routine for message delivery.
+The message reception routine receives the data of a RCX "Transfer Data"
+message (RCX op-code 0x45)
+.LP
+We chose to use this facility as a means of delivering Styx messages to our Firmware
+on the Brick. But it did not provide the Transport properties that Styx requires.
+To meet the Styx requirements we implemented a simple 'alternating bit' protocol whose
+payload was the Styx messages themselves. These Link protocol messages become the
+payload of the RCX "Transfer Data" messages.
+.LP
+The IR link is very slow, the baud rate of the IR tower serial link is 2400
+and the ROM message format requires that every byte of a message be doubled up with
+its complement. (e.g. the byte 0x7e is transmitted as 0x7e, 0x81)
+This is because of the simple way that the RCX ROM and hardware handle elimination
+of the ambient IR signal level \- all message have the same number of 1s and 0s so
+the ambient IR level can be negated by subtracting the average level.
+All RCX messages are also prefixed by a header and suffixed with a checksum:
+.P1
+0x55 0xff 0x00 \fID1 ~D1 D2 ~D2 ... Dn ~Dn C ~C\fP
+.P2
+where
+.I D1
+\&...
+.I Dn
+are the bytes in the message body and \fIC = D1+D2+ ... Dn\fP.
+.LP
+Therefore, the effective data rate is considerably less than 1200 baud.
+.LP
+We noted that many Styx messages, especially
+.CW Twstat
+and
+.CW Rstat ,
+contained a high
+proportion of 0 byte values.†
+.FS
+.FA
+The protocol has since been revised to reduce that.
+.FE
+Consequently, we decided to incorporate a 0-run-length
+compression scheme in our simple link protocol.
+.LP
+Within the payload of the link messages:
+.TS
+l l .
+0x88 0x00 represents 0x88
+0x88 n represents n + 2 0's
+others represent themselves
+.TE
+.LP
+An additional burden is that communication with the Brick via the IR tower has to be strictly
+synchronous. The IR tower echoes back all data transmitted to it on the serial link
+as well as any data received on the IR link. Therefore the brick must not send IR data
+while the PC is sending serial data to the tower. In order to achieve this a 'ping-pong'
+communication scheme must be employed. The PC is the master, the brick is the slave.
+The master sends a request and waits for the reply from the slave.
+Only the master is allowed to start an exchange.
+.LP
+The problem with the master/slave style of communication is that a Styx Server
+implements blocking requests, e.g. reads and writes, by simply not responding to the
+request until the operation is completed. This does not fit with the link protocol
+requirement that the server (slave) always respond and the requirement that the brick
+cannot instigate a data exchange.
+The firmware could simply reply with an empty Link protocol message but it then has no
+way of giving timely notification of the completion of a pending Styx request as it is not
+allowed to start a link-protocol message exchange.
+.LP
+To get around the pending Styx reply problem, the link protocol header incorporates a flag
+that the slave (brick) can set to indicate that it is holding outstanding requests and that the
+master (PC) should continue to poll the slave in order to receive their replies in a timely
+fashion.
+.LP
+The link protocol message format is as follows.
+Request from Master (PC) to Slave (RCX):
+.LP
+.TS
+l l .
+0x45/4d RCX Transfer Data op-code (including RCX alternating bit)
+0 LSB of "Data" block number
+0 MSB of "Data" block number
+* LSB of "Data" payload length (lost to ROM firmware)
+* MSB of "Data" payload length (lost to ROM firmware) (n+2)
+* LSB of Link protocol payload length
+* MSB of Link protocol payload length (n+1)
+* Link protocol header
+*[n-1] Link protocol payload (0 or 1 Styx messages)
+* "Transfer Data" cksum (Last byte of Link protocol payload)
+.TE
+.LP
+Note that the 0x45 ROM op-code ("Transfer Data") message incorporates a checksum byte at the
+end, but the ROM doesn't bother to check it so we moved the last byte of the Link protocol
+payload (or the link header if the payload is empty) into the checksum position of
+the ROM message.
+.LP
+Reply from Slave to Master:
+.LP
+.TS
+l l .
+? Junk from ROM
+* LSB of Link protocol payload length
+* MSB of Link protocol payload length (n+1)
+* Link protocol header
+*[n] Link protocol payload
+.TE
+.LP
+The Link protocol header has the following flags:
+.LP
+.TS
+l l .
+bit 0 Alternating bit
+bit 1 Poll immediate (requested by slave)
+bit 2 Poll periodic (requested by slave)
+bit 3 compressed (payload is 0-run-length compressed)
+bits 4-7 reserved (should be 0)
+.TE
+.LP
+The master flips the
+.I Alternating
+.I bit
+for every message that it successfully delivers.
+If a slave reply is lost or corrupted the master will re-send the message using the same
+alternating bit value. The slave should not act on a repeated message but should
+re-send it's last response. The value of the alternating bit in the slave response
+is the same as in the request from the master.
+.LP
+The
+.I Poll
+.I immediate
+bit indicates that the slave has more data to send to the master.
+The master should immediately send another Link-protocol message, even if it has no
+data to send, so as the slave can reply with its pending data.
+.LP
+The
+.I Poll
+.I periodic
+bit indicates that the slave has pending (blocked) requests that
+it will reply to sometime in the future. The master should periodically poll the
+slave, even if the master has no data to send. The polling period should be small
+enough that reply latencies are acceptable.
+.NH 1
+The name space
+.LP
+We now have a means of getting Styx messages to and from the brick.
+But what does the name space provided by the firmware on the brick look like?
+.LP
+We wanted a generic name space; one that reflected the functions of the brick, not
+the model attached to it, so that the same firmware could be used with many
+different robots.
+.LP
+The brick has 3 motor outputs and 3 sensor inputs.
+The motors can be run forwards or reverse with 8 different power settings.
+They can be stalled, also with 8 power levels, and they can be left 'floating'
+[A stalled motor presents resistance to turning proportional to the stall power level]
+.LP
+There are 2 types of sensor \- buttons and light-sensors.
+[You can also get a 'rotation sensor', but we had not got one in our kit!]
+.LP
+We decided on a name space comprised of 2 directories,
+.CW motor
+and
+.CW sensor .
+We didn't need to use subdirectories for our name space but it was easy, so we did!
+.LP
+The motor directory contains 4 files \-
+.CW 0 ,
+.CW 1 ,
+.CW 2
+and
+.CW 012 .
+The files
+.CW 0 ,
+.CW 1
+and
+.CW 2
+represent the individual motor outputs and
+accept command messages of the form
+.I 'XP'
+where
+.I X
+is a direction and
+.I P
+is the power level.
+.LP
+.I X
+can be one of
+.TS
+l l .
+f forward
+r reverse
+s stall
+F float
+.TE
+.LP
+.I P
+is a digit in the range
+.CW '0..7'
+.LP
+The file
+.CW 012
+takes messages of the form
+.I 'XPXPXP'
+enabling the state of all the motors to be modified with a single message.
+The first
+.I XP
+pair affects motor 0, the middle pair affects motor 1 and the
+last pair affects motor 2.
+.I XP
+can be
+.CW '--'
+indicating that the state should remain the same as before.
+.LP
+.LP
+The sensor directory contains three files
+.CW 0 ,
+.CW 1
+and
+.CW 2 ,
+corresponding to the three sensor inputs on the brick.
+.LP
+Before a sensor file can be read it must be configured by writing a configuration
+message to the file. These message take the form
+.I 'Tv*'
+where
+.I T
+is the sensor type and
+.I v*
+is a threshold value.
+The idea of the threshold value is that reads of the sensor file wil block until
+the threshold value has been achieved.
+.LP
+Reads of a sensor file return its current value.
+When a sensor file is configured any pending reads of the sensor are
+failed with the error message
+.CW 'reset' .
+.LP
+The available sensor types are:
+.LP
+.TS
+l l .
+b button
+l light sensor
+.TE
+.LP
+The threshold value for a button sensor is a click count.
+So the control message
+.CW 'b0'
+configures a sensor to be a button and subsequent reads
+of the file will yield the current click count.
+.br
+The message
+.CW 'b20'
+will cause subsequent reads to block until the click count reaches
+20 or more.
+.LP
+The threshold value for a light sensor is a raw sensor value qualified by
+.CW '<'
+or
+.CW '>' .
+.LP
+The control message
+.CW 'l>600'
+configures the input to be a light sensor and subsequent
+reads will block until the sensor value exceeds 600.
+If the
+.CW '<'
+qualifier is used, reads block until the value drops below the threshold.
+.SH
+Using the Styx firmware
+.NH 1
+Download the firmware
+.LP
+Use the
+.CW firmdl
+command to download the firmware to the brick
+.P1
+% firmdl 0 styx.srec
+%
+.P2
+.LP
+The first argument is the number of the inferno serial port (
+.CW /dev/eia0
+in this example).
+The second argument is the file containing the firmware image in s-record format.
+.LP
+The firmdl app prints the response code from the ROM.
+On successful download the ROM reports:
+.P1
+Just a bit off the block!
+.P2
+.LP
+Once the firmware is downloaded it is immediately run.
+The RCX display should be showing the 'running man' symbol.
+If at any time the Styx firmware encounters an error, the 'running man'
+is changed to a 'standing man' and the source code line number of the error
+is displayed on the LCD.
+The firmware doesn't stay resident: it monitors the on/off button and
+restarts the ROM monitor when it is pressed.
+.NH 1
+Start the link protocol
+.LP
+.P1
+% legolink 0
+%
+.P2
+.LP
+The legolink argument is the serial port over which to run the link protocol.
+This will be the same as the first argument to the firmdl command.
+.LP
+Once started the legolink command creates the file
+.CW /net/legolink
+in the Inferno
+name space. Any reads/writes of this file are the payload data of the link protocol.
+.NH 1
+Mount the brick name space
+.LP
+.P1
+% mount -o -A /net/legolink /n/remote
+.P2
+.LP
+The
+.CW -A
+flag to mount prevents the command from trying to
+do authentication
+on the link before running the Styx protocol over it.
+The
+.CW -o
+option uses an older version of Styx.
+The second argument to mount is the the file over which the Styx protocol will be run.
+Raw Styx messages are written to and read from this file.
+The third argument is the directory on which to mount the name space presented by the
+Styx server on the other end of the link \- the firmware on the Brick.
+.NH 1
+Explore the name space
+.LP
+.P1
+% cd /n/remote
+% ls
+motor
+sensor
+% ls motor
+motor/0
+motor/1
+motor/2
+motor/012
+% ls sensor
+sensor/0
+sensor/1
+sensor/2
+%
+.P2
+.LP
+Attach a motor to the first output and a button sensor to the first input
+and then try the following...
+.LP
+Start motor...
+.P1
+% cd motor
+% echo -n f7 > 0
+%
+.P2
+.LP
+Reverse the motor...
+.P1
+% echo -n r7 > 0
+%
+.P2
+.LP
+Stop the motor (float)...
+.P1
+% echo -n F0 > 0
+%
+.P2
+.LP
+Notice the need for the
+.CW -n
+flag to echo. The firmware is a bit touchy about
+the format of the motor control messages \- they have to be 2 bytes long.
+.LP
+Run the motor for (a little more than) 5 seconds...
+.P1
+% echo -n r7 > 0; sleep 5; echo -n F0 > 0
+%
+.P2
+.LP
+It takes time on the slow link to open the file for the control message to
+stop the motor. It should be possible to reduce the delay by keeping the file open:
+.P1
+% {echo -n r7; sleep 5; echo -n F0} > 0
+%
+.P2
+but the firmware only accepts command messages written to file offset 0.
+.br
+[Fixing this is left as an exercise for the reader!]
+.LP
+Ok, lets play with a sensor...
+.P1
+% cd /n/remote/sensor
+% echo b0 > 0
+% cat 0
+0%
+.P2
+.LP
+Note that the sensor file isn't as fussy about its message format as the motor file.
+.LP
+Click the button a few times and then try reading the sensor file again
+.P1
+% cat 0
+4%
+.P2
+.LP
+Let's try a blocking read on the sensor
+.P1
+% echo b5 > 0
+% cat 0
+\fR[click the button 5 times]\fP
+5%
+.P2
+.LP
+Ok, we're done playing \- unmount the brick name space
+.P1
+% cd
+% ls /n/remote
+/n/remote/motor
+/n/remote/sensor
+% unmount /n/remote
+% ls /n/remote
+%
+.P2
+.SH
+The Clockface robot
+.LP
+So we have a means of controlling the brick via Styx.
+We now needed to design a robot suitable for demonstrating the software.
+.LP
+The robot needed to be static; the IR link needs to maintain line-of-sight contact
+between the IR tower and the brick.
+The operation of the robot needed to be clearly visible to a group of people in a
+conference room.
+We also wanted a robot that we could layer services on top of each other to demonstrate
+the versatility of Inferno name spaces.
+.LP
+We decided on a clock robot. The robot is static; it doesn't move around the room!
+The clockface would be visible and its operation obvious
+to a group of people in a reasonably large room.
+.LP
+The clockface robot also allowed us to layer services:
+.LP
+Initially we just mount the Brick name space.
+This name space represents the services of the brick \- nothing is known of the
+robot model that is attached to the brick.
+.LP
+We then start the clockface service. This knows how to use the name space of
+the brick to control the motors and sensors of the clockface model.
+The clockface service provides a
+.CW clockface
+file which accepts
+time values (e.g.
+.CW '14:35' ),
+the service then runs motors and reads sensors
+to set the hands of the robot to the specified time.
+.LP
+On top of the clockface service we can run a world-clock service.
+This periodically reads the system clock and writes time messages to the
+.CW clockface
+file resented by the clockface service.
+The world-clock service also provides a configuration file so that the user
+can set the time zone of the clock display. Writing a time zone abbreviation into
+the control file causes the world-clock service to write new time messages into
+the
+.CW clockface
+file to reflect the new time zone setting.
+.LP
+By using Inferno's ability to export a name space, any of the clock services
+could be running anywhere in the network.
+The Lego brick could be attached to machine A.
+Machine B could be running the legolink application using
+.CW /dev/eia0
+imported from machine A.
+Machine C could mount the
+.CW /net/legolink
+file imported from machine B's
+name space.
+Machine D could then run the clockface service over the brick's name space
+imported from machine C, etc. etc.
+.LP
+The source of the clockface service is
+.CW clockface.b .
+.br
+The source of the world-clock service is
+.CW worldclock.b .
+.SH
+Final Notes
+.LP
+The firmware could do with some more work on it, such as the overly strict
+length restriction on motor control messages, or the fact that control messages
+must be written at offset 0.
+.LP
+Please feel free to fix problems and make modifications. I am more than happy
+to discuss the software and answer any questions you may have.
+.LP
+Have Fun!
--- /dev/null
+++ b/doc/lego.pdf
@@ -1,0 +1,953 @@
+%PDF-1.2
+%�쏢
+6 0 obj
+<</Length 7 0 R/Filter /FlateDecode>>
+stream
+x��Z�r���k��d#�ʢ�)8�X��F���J&W�!�I�D�x��&�L?��� ��x1%��}���{_'�i4����r{����6��۳������+���;���3�&w�3�J4��|2��&w۳g���oO�~*��Y><��Ӽ�Lr��b��\D�i6�[�={�idkV��4�;�g�T� ̳�t��F�ai�}/���վ��jk����zM�75������h��f��-��C��m_Xy+��l�Μ��4�\ı]p]��F����A�Tq�����F<?w2�-�R�'je��A�qrd�������Z7�×/-��ޘ��ܬX���F�)��<Kf��P��f��@��ت�횢��d18����]%K�=Z�b���2qa]=��,q�JUY�$�T8+k��ю��(Z�(''d���Dt�a#K�lAoZ����h�Hۺ����Y����ysR�� �i�@b+�NX��l���ܻ +$�G�qA���R�S����]��xJQ�*_k��x�D__��Eri���G,�Z鈒{Q��R��C9?nT߹�Ix��v����d���G�����#Z�7�pƁ�ۢ.���V���A�Fk7E#���~�ŇЊ7 �8ڲ#Ǜ`%�AD����9I��<��,*87��Z��\5nj�{�j��fh�V4f����dn1т����R�t��!ac߫�UO���F{&���`�L�����F�m6�A �]�)�N���<m�$�E�v
+H�c�r��Y��^��_��d�MًA⛟Q��D�ݦh%H�2���{)�-u�5��8r���⾕����CQI(P�:,7G���m�/>?���F\7���GW�LA��I�Q��e����R��F��1�EՇ1��͓+������@.T:���$[cx�8| �!2f�]��]jm���(Fn�,EV�ْ�rҶ_{�@��) �=$6s��0�<��cHܸ��t�#����ih@�+?�}$�˦������Y;�I9�,�6��D���\���Մ5��tS崠��?���)B4)���;P�X�ϙSa�[�I9��p���\��{k�A����{$%+���i�Y��Cb�p1Ki��\�D����y�3�m�;�;��Pi�b3�5I�I�� 1q�B/b�*!����e2�ɋd���t8�~2�(�r��'ǎid�,�����[5�C�d57���Z�G��B��P[�k�g�h�g�J�@� �� :s�������SraU���e%!�<P7�����@EY��t(�G���:Q��
+�Ӆ}�u���K'����S%��G����u�oHXײ�m+�8e3�� El�x����KQ���`p�Y����?�(��*@ݝPT(��l+�%�U�+�
+r����&���aw���v����J'?��v�瑂[�iV�]Gf��0��)D�o7X> Vu�@_���y v�B棈P;����Ga��D,��zP�,fq<Z�Z�-ฎ����s�aUM�S\�y���a��]t�=������� (��FݫN��O�ȃ�u�\
+�*@2��;���:�T�)���J2��j\��Ϥ�؊ �|zD���'hf]b��0Xn32�^��%�C����|0h,�� ���!?ӧ6Ž��2.K���ف���#Q�(U��x���E<�ҟ��g/mq�[�h8��Z2�?/�f9���ZA`��{��e���d�l;�l���i��7Q���.�8C��f� l�����;entS�M�
+��G%��Nl�ϧPhp�����?�>�OZ�v���������@����9���Yٴ/J��|�w�B�1��[z1=��\oB6�ރ�y�b� Ro�Q��XnCaa��U�����N�h��'BB�e�/�r\$y� A!*���Z3 dA����}��+�������V ���c}h��ԟ�n`
+2���u8k`�h�:_ـ+kN B /yxB�n�(�)A�0����:����h���+� ߡ��T���x�%j:�HّA&��+B��a�e/� Y�/�ZH��c�j �ԫJ�Z��&L������o:<���� ������؟��S����x�6�,�%Zf�J���f��Mx��#���1���<�k�v���� o��O�a����)x�|w)�R�^yg�]����-B,F������$�`ZA�<���GX.� ���dU�a�)p���`:�z�<l�����+endobj
+7 0 obj
+3204
+endobj
+31 0 obj
+<</Length 32 0 R/Filter /FlateDecode>>
+stream
+x��ZY��~����/�aqĹ���F��FV4�����INv.�A�����L���MnlD�i��>�����j~^�w���Ϭ��|�y�Nc�#+�67o���b���o�Tw�%+'X�A�ؔ7��o��n�/9���ĥr��-6���E�8G5�J|'�{��~ȫ��Co�D0T��(�1��`�i����i��5gu��i�w��+e\��4�럟�����?scLJ�}ޖ紝��5 �eS�RT}��ue���ّ]+�ʩ�a�"R����K�y��`��{�m����y�h&ڧt�|%��y4����I`$-z�VRm�a�$��m�Os=�i��j(�I�~Xѡ� ��8~�gD�n�34����A:���^W��PD�5m��A�Ĥ�?�7�H����u��6���'�O��PL^�沾��*ڶy�h:�T{�h�]����k>�t֮>WE�N: |rF҉�Ɉp\�=M�.���k�`���z7� ���Hw�5����Qׯ��QlV:��Q���[I>{�m��_����lj��P��UE�4��N��t��<��S�|%� �ͽ�P+}^��{A��q`��{ xZD�Q��D%Z��8�mSw�\����K�P!���� �´O��#��:�)�EeL�G�V�v
+y/tЁ�y!���V��$瀬���}���@�+����#��ҋU�G����b����!�[
+��s2^ɹ��h���w<j� ��X7SrH���Ͽ\���~D�.���3��=j�2�Q�;kL�z�
+��� "JP��1����oy���༐n���2p9y�U<��+#�}�M�oe�{Ȕ����}�M?�8�+Ie��2��R��R:� +Fr�59 �����ۡ�@Ñ�aC�j��I(FU�2�l#�2�T�Fλo�J(����݄ns��cb���b�ȁ[r��'���O�LR�p��}�T������{ɔ�c��c�7?�}{>��&�����DYWNV;��۹\KX��&���N�ѡ�GG=#��Y;0��|�ɹET�+DPm(�%<�i�<�r,��L��1�P���s�+Ǝ\<]�� B�#�h{����i��n~&F�{���Ⱥ&qT�G�%�EZ聲#-2+ܜ���Ox���D&$�VB�'����G��( ���8�T�n����A[����ۺ�h�&m�W(�D,'�.]U��]P��H�>���2���Bo�ݰL����M5Pg���#�i�������Ҋ�#����K]"��WW�܈�3@�`W�,WC�+��B���VZ�����u1!Y"\3�P���dI��q(CR?%��5Qdj��I����KN�kD&�����u�f����i?7�Ϗ�vϝ]��^Iv�������4 lb�9��ɸ<]Y�b��l��3W���{I�
+4�:�+endobj
+32 0 obj
+3178
+endobj
+40 0 obj
+<</Length 41 0 R/Filter /FlateDecode>>
+stream
+x��ZI��6���P�b;6e�"�K*����=ɴ�0U�9P�☋�E���o���q�R>������+ӗ�]Y|R�"Z�\�����w��C�C�{ѩ�64��+�� �ph��������A�3TJ>I�?4űk�v��J�Q�I��n@<�2��]7ű�F�� P�h�������}>��Z4ty���0�����=3
+W*+f���\9ʦ㋮Ԁ cZ�*�O���+����D�i��h�iﲹS
+�I��e#����\�]�{ N��5�Z�0�#�--��q��X��� bG}"���fV<���<�wj����h��X�/$}�f�kM�(أE}���WǎY*&��m���mlu�y?��5���Q&��W�b '櫾��B�I�h&��O�z0��4ǴN|�V�/s�}����RO�=%P��s��X��Z�C�][�k�A�'.���\>{L�l:aUI?��(r���wXe�D�}3E�Kq̛;-�LQ}
+����O]����@�2S� �ݐ��`o�fT����@;̯�7v]���7|X'D,�V J�qx�b����Z�N*��I���+�8����p�m'D�${�S��X߭-V�D+�X3���*�z�KN�5P^ �I���w��"dB�ZTxȘVʃA�1�*kMFNBVQ^O3��<p���1���U�KlJ��;fh���;�2�����09�a"gá?�(9���31��z&&���A;�6�Y�FS���
+�6˻v�{�M�M*B�� Ux n���qz+�Y�A��!��A)EZct<H��"�*���Xb7�.q[JZ$�Ëo5�S�;@ ���"� �i����'C�`����)�>�Y��k�A��l����+�S�~�H�NF3��+Eì/:0�,���n�HL.PBN�������\���QR"xw�,��\>������0k,s�,���]�_��C;џnSE�� �e/TM+�f+�A>�i��n_\���ۗ?*�EQ�z�؝���ɛX��8���y3�� UB���N�ۓW�{�� !ɨ)ÎX-�^y%��Ș cy�]9hxa��o����[� j���M�?p��S��C4c������K�~Л���.���7��;���?Tm����h� �K �T���B��]��a�0�D{����)�����1��/�W!�m�e�,����4\���X���h�>A��O����Wh+�um}����x�oV?����?�����n��sD�&_������Q�C��QY��K<�1����n���S?�\9�x�S��ч�V�+S���FA�� ��\ڣ��[K8��^�YJ��fAi+���p�Z������i�c7��Rי��Pڊ���<�4/�}���<xo7P����x����F���f�n��F*�N3�r���i�$pa�F�pVq�bc��'�PR4>.����bg��U���F����vÀ��A��m��/���v�w����|r�,Q:�����\.��ۥ� �:�k��i�'�c��o#�����p/���h,�G�8}D��E�N3;R��zJ���y���ɋg�U"n�Y �Ǝ!"����Kf���������Q�t��nLJ�QJ��0���F?�]0�����u-�%�Wb��[��kN7�����ѕ�|Y�+Q�u�N�+�}Y�i��S �~��@�%��v�$��#V��G�E��nl<��$\X��a��vpk\�^
+�j\UMw#��Tn�������F��t�f~/ �a8��\ɊDo��^�q:b#��!` ��j /���$�ز��-��+9�0V:Z%�g܋��A㆓�w����=�� "����+j0�Eb�G�}e�í_訉c�ҦN������Ʊap�`�c0.�r�]�X�U��j?���&���c�WWv�y�)��%�7=f��C�TA�jF���c03bZ
+��;���a������9�����A��=�{�;V���B�V%�d�Ҹ�g����ic9��žy�IZ��f/�����
+��w��y����n��p��-�����ӽ�f���l���F�D��Z��Q����nh�����y��|��Oo����� �qqʦ�������_Wӿ�O�·endstream
+endobj
+41 0 obj
+3002
+endobj
+46 0 obj
+<</Length 47 0 R/Filter /FlateDecode>>
+stream
+x��ZK������@>�5F2��b�䰱��vI���H-3����fw��Mi�N0��p�Q]��W���+o민�~�经wW������ꛇ�����U�z8ޙ��*H�m��G���|�f��V�����^��o��{�p*��jz���?��][��?է>]ʮj�*�9�eh��j�S�m_�F�φ�����6���)3C'q��ƏiP_gO�[�˝2����1�R��<���m
+_~s���CY��v�O䑈]�q,���&,�cΒ�Q�+PHBK]�#imh�o��3��r������I/�Q��l|�+U���eӎ�'�f�@oWx�Z�P�W�G;�%�̾���yy�Cm`��45~� �<��j�X�� rd��1�d�
+���K�#k+�;LFEL>�6�1t����9�k��"����B�,��,iQ��@�,.�A3�"� /��0oϗ���� B; ;NM��SiH۩J���'�~"�<��2�T����g��!+�{<����8�ZQ�z�HNLk�r�ѐx�~<�o'����Co8Bp
+9�rL/�,'t0�i�99g�=� �[f��=�Z�N��l��s�I���d)�@4�@����6CV5�"�-�gǪ6ZdrR�6 O������dLK��yF0����/����I�I��g�r�*haV��|b����'u%�^M�B�H=���T�7�Hq�C�Q�r�8OQ-)E�1]�_L0;�ah��\�
+��ݨ;��:�~��^�����a�����,�~>+��Z����_;:6�P4Mq�w� ����jҲ��� �X�jHW�G�����>��6q����?�]���NՁ�'M�5P����5�������O���������� �>���J�6��汜���D��v��0�I#�Ѹ<O-_EEE��.�%\?d0#]�D'M�y��Y�D:��wӏu���Z�dl����F�}(gJwd��>X0u�����VGd�O�TZA~�Ճ��f��MH�����nǂƵ�Fܹ�ƪOV�z�"༷P,r�KV/K9&����[��J�F�<�҅N�*�������ob��}�����z읦��+�N���k`Ѩh{�ھI��1�J�jG'ND�<"� �O���E<v����<g���%ϾѦ�\���C��߀xz���t�a���&�ϐyi,:]�BQj!#c�{mF�a�3�v]=+��>��md5ש���U��c���t���& ��U�lʃ5��ٚ�hK��� $q��hBs{�b܀j
+}ѿ��Xϣ�|�Nk�c�8vP9smG�t��Uw�����r�ш�2��!�9]-�g�Ya��B�+��D(��������6n��s����Ith3f���Ρ��z?�P���+�[��Y��<}i�1S�-�e�ɑ9n��0��z4 8�1�Q�_����W�ژM�U
+ۂ �>ӂh9����}pf:��sz�/���l$r�]����j�䐤��̨���
+۪�o�/Sb�����L��*U>@\a4#��H'l}Њo�c�R9�e"���Ԩ�q���0�ϗ����5W�3���?��x���N��8�XtȷL/�nJ��Kf.�����S��s��Ǭ�� ZJ�mz�Ae���܀l�[<�YO}��⽐�<L~���h�'%���¤/�=j�@��fo��t�LƩ�N���PY�گpt����E�t��wqJ�3w�`R�$Jw��"�p�J�y����5^�zȊg�o���-����"���]�u2�/��;���gG._ɧ�{��J��>���n�ɜN��j<���� �~<���5h�E��wD��P���Pҗ��2��kɃ���c�ƛ �͎낟t�C�X���Βgp� ��t�d��?R^Ռ��J����W���y�|��v�v�����1۽^�p|�����݆��g+l-��$��1���#�r��1$>��d!H�.^��4���k{�uѠ����`�8]��� ��˿u��γa/�Lq�N�ʮ���
+�+�/��G"3w��/�*�ol|�~r�v��Mtcו���T>≶�t?����
+E"
+�T���e�W#�U`(G��~�G��d�P쾄�Ԃp)��V�3=�����L�"[K��^��%e]{1;p���w�{���<�h�z�j�����S/��Z���jW<��:�ߗmv��qkd?n�k��ԭ�@D����W��}0{,�C��Yn�^��+���!'��iN�)��!��ûW�����>Fb� �Sp �+s5�W&��]��e�-�Pv��a�ϻ�����]endstream
+endobj
+47 0 obj
+3155
+endobj
+54 0 obj
+<</Length 55 0 R/Filter /FlateDecode>>
+stream
+x��XM��6���@=�j�"%����&M� �n|�a/�D晴DG����/?���+��o����"2�
+�걿N��h_ �8"�o��E���1�D��B�r(8� ��3��z��mpA���QD�`@;f�-�X���b�_�J�2ڝ��b�����|x�O�̲��5ӛQ��|��֞����F��3� k,s�n�_��t���j������/�^�1 ���0���,�6־+h6�bk�(L�����߿�#��jR:�B�+�� �JI� ��y�NI�U)�J�]c����}oD[ �b����R���ݮݟ���Y&g{1�ҕ�uF��\��g�7�����͙)&(�T(�G�B���7������ cE�I�}A�2"�����Pw�D!�P!��<���I���
+�g�^��n�����������d�C���k;8����j��+��sU<C�+�R�}HrR�_L}p�DҲ�������~��\�5�����2A�wo�Xѵ�a=�DK��[���f��?A���o�&�V!I���X%�ر�vIF���T6s��.Ӯ��Ӣ���%��z��bo���l����E��i�ƒi�|�M�ܷ6������H�E��r��TWV��~y�*�d�W� Lth�����ˣ�������d>��c����&�hϫ���n-���!�}P��e�:��}W��h&9�$\� �|�c�Tب�����&�۲���0���R��~�6�f�P��@}'U��hl��|�0�L�R��b"�Ό6��L��%OJ��@v�g�CU��2J�y���t���͞���䷒�i5 D���������fD�2siB=��ڷ��ڊG��|깕lB������#������AIZWԭmg��]O\%���'FZ��>�`p���PՂt�͎uhr�Xym�y8�B/��|�'��m�r27]�K=�3��O��{7��cO&�)zb)�U?���Nb�G`�<ㆦ+p���I��O�g�w���k��I�����`zrc�8�NW�&�U��|zǠM
+CHs�e��]⯨�%]>��dž��1C�'��w_+endobj
+55 0 obj
+1942
+endobj
+61 0 obj
+<</Length 62 0 R/Filter /FlateDecode>>
+stream
+x��YM��6��u��rzX��O�` 6+ʭ_s?�A&��_!ڕ���b�q/�������M�W>t}4t�#<�{(/27nFk/1�D���1yMr+� ���a�#��{�yG v)�z�Bt�Gá������3hd��,�Y�=���9���ATq��n0�Y����\DhHG��Υ./>��Mx������;˘Y1�o䄴���v�ݶ�,�p�9���D�$����uT�`�\PD��s�� ���`��������������j[���!�P��� �6"��f� �}ec� ��"���;�f�����]�����x�+K�I����U�k'�3goH��P�1j�l����42����βx�(�Y:}4�6���|�J�0 1�
+�)�En���7Ҫão��bw�q�S�<�9��lX�Q&�Q���K�:�s�� (��w���>�T�K[}r��A�+���_�0,kn��e��Wj��Ko�5�1���3��s� >s%��)@ �4$˷a���"�W�W�z��( �1!�,�䇅y��މ6ڿ���U��.���̬w�� ������JLD���^d ���j��_1�\�#��ҝr�Lf��&$p���s�w5�e8�� �Tܯͻ�2������e��U����s�È�l�N� �������x=�ͺ��:/�l��Ή?i�+��K��/iZ ���1䕁��g��rj7�W�%�Uj[�eV�gӥ|+>�t����e'Od�LDgq���F�Z��g���n[^;���u|����4!�G~9%"�3��>��l�3����*�6�(��6r~�4P��y b�� ��o3H�X>��+g��i�
+P�gǚ+g04�9�K�:�m'��ڵ���ᝀw�-3!����2ށH�f0į�����"jK+w�W6
+�վ�+e�uQ��Z��8��q���+l+:N��WV�\�A��p���l��P���l��w<����5DJ�S�*;�r\��N�{����!���#�dk�=���Nvj�[�V"��EH �ۢ��箃q�G��(�<pfj� �3�x���퓉���ydJs[X*���GS������)u+y~��D�<��Sej� ��6�E�U�S�f1D�̵��N|�z� $Ղ��p�F*�t��\��7�$���k���W~u�Қ���t�0F��ϭ�\�L��,@QN$�,����1�\�:Iݦ�3��fM�JLB+>����$;�z�m);����9X2R������RL��j�� z�~s2�4�y��JXWS�F�0W��QbV����߱%咂���+=R����צ�0������X��NM� [�Y�CQ=N-,(*�ߛ��U��Ь�+���e���]�� �K��;���E\�g3\�&Վ�ƭ��7��H���D�δ�g�&0S�Ԅ���������V��endstream
+endobj
+62 0 obj
+2278
+endobj
+68 0 obj
+<</Length 69 0 R/Filter /FlateDecode>>
+stream
+x��XɎ�6��+�S&@[�͒uLO2+ؔ�e���KU��=)h� ���a���l��A�����%�h-��|�����n<˾9�̽��0�\��K����X�)�ȓ�ky��e�\�����.g/9�5^u�h!����A:�� �(�t q<������Tu+�O4�b�g�2e����x>~�C�_e�ɲ�(�U�`|�0�N �w������������VjR�a�sf�,���Q�4Luz �f��l�S/���.a܁J�����y�KUKúuF�+0��iڧڈi!�bZY�v�x���_w������.���8�F'Q��A�嵹�]��V̹�Է��cjM�V��gOl����^]�}f^sek��A�W�|�������^T��+��C�7Bp��\4'%w5�Ȱk����>�6��P�a�r1+�Ǯ}'���������r��v��${�1�k,]�b2���4�+������0+endobj
+69 0 obj
+1455
+endobj
+5 0 obj
+<</Type/Page/MediaBox [0 0 612 792]
+/Rotate 0/Parent 3 0 R
+/Resources<</ProcSet[/PDF /Text]
+/ExtGState 27 0 R
+/Font 28 0 R
+>>
+/Contents 6 0 R
+>>
+endobj
+30 0 obj
+<</Type/Page/MediaBox [0 0 612 792]
+/Rotate 0/Parent 3 0 R
+/Resources<</ProcSet[/PDF /Text]
+/Font 37 0 R
+>>
+/Contents 31 0 R
+>>
+endobj
+39 0 obj
+<</Type/Page/MediaBox [0 0 612 792]
+/Rotate 0/Parent 3 0 R
+/Resources<</ProcSet[/PDF /Text]
+/Font 43 0 R
+>>
+/Contents 40 0 R
+>>
+endobj
+45 0 obj
+<</Type/Page/MediaBox [0 0 612 792]
+/Rotate 0/Parent 3 0 R
+/Resources<</ProcSet[/PDF /Text]
+/Font 51 0 R
+>>
+/Contents 46 0 R
+>>
+endobj
+53 0 obj
+<</Type/Page/MediaBox [0 0 612 792]
+/Rotate 0/Parent 3 0 R
+/Resources<</ProcSet[/PDF /Text]
+/Font 58 0 R
+>>
+/Contents 54 0 R
+>>
+endobj
+60 0 obj
+<</Type/Page/MediaBox [0 0 612 792]
+/Rotate 0/Parent 3 0 R
+/Resources<</ProcSet[/PDF /Text]
+/Font 65 0 R
+>>
+/Contents 61 0 R
+>>
+endobj
+67 0 obj
+<</Type/Page/MediaBox [0 0 612 792]
+/Rotate 0/Parent 3 0 R
+/Resources<</ProcSet[/PDF /Text]
+/Font 72 0 R
+>>
+/Contents 68 0 R
+>>
+endobj
+3 0 obj
+<< /Type /Pages /Kids [
+5 0 R
+30 0 R
+39 0 R
+45 0 R
+53 0 R
+60 0 R
+67 0 R
+] /Count 7
+>>
+endobj
+1 0 obj
+<</Type /Catalog /Pages 3 0 R
+>>
+endobj
+4 0 obj
+<</Type/ExtGState/Name/R4/TR/Identity>>
+endobj
+27 0 obj
+<</R4
+4 0 R>>
+endobj
+28 0 obj
+<</R22
+22 0 R/R26
+26 0 R/R24
+24 0 R/R10
+10 0 R/R13
+13 0 R/R16
+16 0 R/R19
+19 0 R>>
+endobj
+37 0 obj
+<</R22
+22 0 R/R36
+36 0 R/R29
+29 0 R/R33
+33 0 R/R34
+34 0 R/R35
+35 0 R>>
+endobj
+43 0 obj
+<</R42
+42 0 R/R38
+38 0 R>>
+endobj
+51 0 obj
+<</R22
+22 0 R/R44
+44 0 R/R48
+48 0 R/R49
+49 0 R/R50
+50 0 R>>
+endobj
+58 0 obj
+<</R22
+22 0 R/R52
+52 0 R/R56
+56 0 R/R57
+57 0 R>>
+endobj
+65 0 obj
+<</R22
+22 0 R/R59
+59 0 R/R63
+63 0 R/R64
+64 0 R>>
+endobj
+72 0 obj
+<</R66
+66 0 R/R70
+70 0 R/R71
+71 0 R>>
+endobj
+21 0 obj
+<</Type/FontDescriptor/FontName/KORKOY+LucidaSansUnicode20/FontBBox[-302 -205 1349 976]/Flags 4
+/Ascent 976
+/CapHeight 976
+/Descent -205
+/ItalicAngle 0
+/StemV 202
+/MissingWidth 316
+/CharSet(/2013/2020)
+/FontFile3 20 0 R>>
+endobj
+20 0 obj
+<</Subtype/Type1C/Filter/FlateDecode/Length 73 0 R>>stream
+x�cd`ab`dd��������)M�LIN�+��L�OI52+endstream
+endobj
+73 0 obj
+303
+endobj
+18 0 obj
+<</Type/FontDescriptor/FontName/KERJOY+LucidaSansUnicode21/FontBBox[-30 -325 1384 883]/Flags 4
+/Ascent 883
+/CapHeight 883
+/Descent -325
+/ItalicAngle 0
+/StemV 207
+/MissingWidth 316
+/CharSet(/2122)
+/FontFile3 17 0 R>>
+endobj
+17 0 obj
+<</Subtype/Type1C/Filter/FlateDecode/Length 74 0 R>>stream
+x�cd`ab`dd��v �����)M�LIN�+��L�OI52I���f�!��C�9��M_쬲�
+����O��$�ݞ+P���8�Ȉ���Q����������������]�}�^��b�^��{�OS���{?��.���5��ߗ���^z��?6�ߓX��L�Ob�������=l~O`=��W9�g����ӿWNg��q��I��^��~��5�Ke>���<<�'���q���b`+endstream
+endobj
+74 0 obj
+295
+endobj
+15 0 obj
+<</Type/FontDescriptor/FontName/GPQJOY+Palatino-Roman/FontBBox[-166 -283 1021 943]/Flags 34
+/Ascent 943
+/CapHeight 709
+/Descent -283
+/ItalicAngle 0
+/StemV 116
+/MissingWidth 250
+/XHeight 469
+/CharSet(/space/exclam/quotedbl/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/question/A/B/C/D/F/G/H/I/J/K/L/M/N/O/P/R/S/T/U/V/W/X/Y/bracketleft/bracketright/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/guilsinglright)
+/FontFile3 14 0 R>>
+endobj
+14 0 obj
+<</Subtype/Type1C/Filter/FlateDecode/Length 75 0 R>>stream
+x��yyXW��PLfZ�ZґQ�u�֥�Z�uEpAW��$@�a�$' k��MEeq�[ݭUk���պ����뙼����3H[��}���]�a��<�s?�}Ǝ�agg7z���5�>Ӽ�����2���~2�e2�lǍ}�g��C��2�k�`�^qcd��ɧmٯp^�,�{~�]�]�� [�N�6}�<2!:48D)�=�|��d�E�B� �I&���pyd�T��!�(�J�!RIPh�T������c�d�*o�*�L�.��� ���He
+�TI�<Z��I�\���3$K?�"R�I���|�tI�4:"T���%�
+Ip��L) �(��PY@xL �<~$�)%��r��[�T^r�R����V�>ݣ2�Oɯ���y�(��O�{��/T��(��J~�$0T��SEF�n!F*�c���hi�_t`�T18/o�?�'y��~��� �c僽~_?T������`�����%��A���A�Kd[�-K��x,��z��
+��vU�lX�ݸ:f�&��0�5q�~���G�o������xo���f�5��)��L}���ms�I�MOo_XA�'f�m���x��I�F�'\�Y���b1��H�&&�7�mb
+�M�!�S���Z�� b�N�%�[�u�2b1��!<��Ļ�"�%{b�2�L�"�c�WGBDPīċ��������p"�XH8#;�!F/���0"��M�3/l}��~�0�a���p����DvP�ԧ/�x��KA/}1\1�ሾ�I#�����/?�xT�+�]�Ģ�W�_-�'�m�����'��\bw�ywL��v����ǪǞ��8�qY���z�AW�1+^(� yI�"���z¸ �&������}&���k�������V��f�<tE�p� nz ���\��[�P�����_ݫ6f��쀌������$FI^2��zP�@��������Y��
++̠���F�W�4�o���+��4���J�� O��W4x����<CȞK�?�|�g���w���ف�칉� z�݅��!E�`��)]�+h%x�B���1�nV��]�Z�K���2����̯݇G�~s�?.�B��!p����a��aQe�@G� ���,Z���}���T�v͓H�ՠWa�rory��E�#�Q=�ZMǞ�M,|����@��5�����!+�Ei�d�p6�ḁ撺���0�+0��銝@ ���w��Z����߂� 3
+v%��\���O��ibQ���a`�&]��o� ���ݿ�á݉��ݯRt��R�U ��#���VGx��Xh[H��&u{α-��p
+7�R@�&�`aN���A�z��t�a�u�/a+��� J�E������#�����D4l���7�Wtb+��C�v��͎s��V��J���x7�Ƿe5jNSp��*8h�Z�+��b
+�Ko�4�[��w��}�:0��z7H�o�~t����*K��Z��-�6+���4�*�"+�2K�i��s8�p�£������4T/a�:����6?:� ՠa $1&z�#ۣ� �(?�5\C^���g�,�2������9p����)W� IK㩆���Z�b.�~�W��Z�ѽ|��pͅ���tGAS^;� q�g�l�9����(�9�6��%�+����Y��a0:��*B��E�����d2�j7�Bu�z
+Z��+��Nf�d�fr��Z�A�����C���n �2���q���8�l��(�3V� �y8X���ks��(ro8�tÉ4pUGdKܗՋ�����'-5�VqTݞ�����EZA/u���C���GC������в�"8�o��Vl���:�7Vܐz<�JrOze,�R�>�xԲ-G�����7�`ɷM�O
+k���?��[����_��.>�>�=�����(Cl�Y�a(P-8P�����ԟOo�;s�zDee+_%O�qق�$8`�,��Z�(�#T���]<��V���bIxhCK��B{Nj�~�Q�����ɧԶb�����;��i�%"**BV���P���(��Eu�!���=xg��\ �絛O,h�iބ�?o"'_KpS��=�7���VZGZ��>�X�-0{ɚ���ם��yY&�%`E� vhb�w��>�:��mt��ާj�C��,hX)r(��nQ�Ο�j_Wfr�K[bQ�Af��8خrЧ�`=Y���~E���"��~��Mr%c��Z�H%�1�8]����ٶ���
+�A_�c#���1S6`i����ᖧv��LT$��ޝG���R)���� /J�L)�j�(�O��?�JSxEtu���S���{������� �&��SX�^ցR,f�J$P�:���V�s{�G�j�;{+�ߒ�)2�
+d|�$�!@Vւ9�&�#͒h���L_gCq;�Ɠɵk�+_��p;��J�q�lD��Y���鼝�o1���h�*7�:{~+X��I�Q� ��6�� �Ҟe�l��R� &�����K�_�˳W�z��Er�܇�w����>�s+0]����i���W�r�a�%�$��������l�!��,-U}��^�~�fMI`��� ۱\����y���`�w����]�����]֎�Jq]�%�a��a�M����t3�^�6R��#/<�p�Ҙ3,,��oY\R��V�+nk��q���E�VC3�~D��R'ӱ9�I:<���ZkI�,HW�d'������yZ�cAqq�U�w��Yv1���SڜD_ �����uY��M�O�%�7��.�+aVCm��^���I�����[��"I��JLJB-���{�?Rؿe,�ښ��MiL�:�$���X��g�/�+lI�|!��/�>Dru�%�Qq�1�JS��N1��pZ���Y��t�&F�����+����n<a~Esu�(�0� � �-1��Y�f�:��/��hC�.� ��u��ǽ��{0��s*�V�y@�����k/����s�}�D���.h��3�)�;������w}Z�w�K>��n���?����f��2�\�
+���+� �HHr]�|A�\�Q�GR�[(;\�~i߰���O&�:md�ʲlf�����������J��9��q\� ������ QQ.�6
+<��sEYEcӾ�n@�;�J��y�?w���j�ÿ�ql̶�٢3��RC��h044�7��Ta.�ַ>%�t|����Q�P��p�R�V������ŜUd��a��u�;��1W�ɜ��X[�,�66�/䑣:����l��&uqZa0�[6+"�� R+ �M�:9=#5=6;PRan� �4e�׃:����wUSha�k�-�[�X��BrE���~sK�f���T�n������&̺����B����OL���J�v�-�kwC ��Qw�"�1ѭoϵ8;�������9�'�j�~����|�������������Mg\o��уGT~G����G�K�=�o[�!:p��6 ��v�0��r�Q�ʄ���9��Ba��/8��:=�=[c�����w�!��V�1��6[��bb������Ya����6;���_�?���}g͉��w���
+�P���~Bzu�d�p�漟���V�|t:-Dv�e䶋�$��m2����*}�Nj��u�x_���c�?�g0�`z���HyDD�������Y�.�� e_~^�d�3��[q?qe������
+`�m%^b�m)�a�tu�;�Yl6-5ݮ���I���+�x�[�����+tdFB������k�O+Ic�+?�e���[�*���,��밉:x)U��Yf[I���rЋU�:|��'����� FC!�����rB?�7e�P��3����ap�݇�_[�t1ɳ1�/s�h�ҧu:�֤�P�H�%-�[�q�B+Z�����nk*6!�[rE4r�����*0E����
+4��{�^`&WA��'�.,�#���Xq��.]W���&N"H��bH�F�w�>]�W�łb��˔*8-���{�_!w�NF��1�+���'s��0ĘR���І9�J�Lu�5��ׁ6Ciaa���+endstream
+endobj
+75 0 obj
+8093
+endobj
+12 0 obj
+<</Type/FontDescriptor/FontName/MYPKOY+Palatino-Italic/FontBBox[-170 -305 1010 941]/Flags 98
+/Ascent 941
+/CapHeight 706
+/Descent -305
+/ItalicAngle -10
+/StemV 105
+/MissingWidth 250
+/XHeight 482
+/CharSet(/space/quoteright/asterisk/plus/period/zero/one/two/equal/at/A/C/D/J/L/N/P/T/V/X/a/b/c/d/e/g/h/i/k/l/m/n/o/p/r/s/t/u/v/tilde)
+/FontFile3 11 0 R>>
+endobj
+11 0 obj
+<</Subtype/Type1C/Filter/FlateDecode/Length 76 0 R>>stream
+x��W XSWھ� ץXI3��6����ժ�vƺQ�ED+�X�e�v��v�3�vl���tz.s��� �3�>g�'�s��{�=����{�0l�$,,,lֶ}�[v���"JQŒ76)RD´��kTt��$��p�����[�x�Z��3/�L5ΞI�͠��bᡍa�a�s���}��$R�L����/Z�b?U�+?F f�����@$�+Ċ�8�����3�"ݎ�}��o��ݰ}�@,��������T���4�X.x��!��EO���$�t�B(�����)|�T�&D
+����|�T �����/��3e)b� ������4Q~z�<z�!+�R�����U�D���ɄRY��Y�EȮ\�����f�$-?��?�)B���(BvR�t�\*JQ#�h+�L8q�|�P��/���2Af�,]$�O��ʿ������T���V2��?�r�(c
+8%U��.��������1��u�8-A��}�T+˔g)����9�E){sS,\�����V�|���^�v`1�
+,{{{ۉ��^�aq�Fl7� ۃm��bK�xl+6ۆ�Ŗa۱u�l&�q1�cZl66 ���a����&c�0^�褟M�7y����0�M��q�7��)���uj���i�3�w>���3�"�3�g<xV�l��_��=S6�~����U�jd�@g$u�:8�L0>��v�1��E�"��Hb��*9ak���@M�b��,Z���X�ZS�ɜ� ;��d0�ʨ`V�f��8�f��U�q�p�!�Ph0%�-��`?������PMzH��T;���v�:���k�0+�Px0���R����Ly���8u��H�̌��j+PD�|���#��������uz@�J�>�#�x�a���� �F]�*e�`w,W�%Ư��K9e��J��덕ez~�Zn$5Ow�zq4|����k�^o�ܟ+A.�J$Q�Zl��JS0���ҍ���ѨZ���X� {�Y�#��~,t�����T�z(��{�fXā�h�W�*�h�ʸEvF$�룖���A3�_�d��s��y�U@Gⳇw=8w�ep�{��!���_�[���/u\6O4;y/O��ӊ+�f;-+�`���J~���9����?g��g�ԗT �����>��}W�6�����HO��z*��������{t����G��7vūW�^��\û���eމ��M��mp��|f(kt{�Nd�����Q���'�ke�>2����+�{�p%�x���\^@T� �F�ʦ����w,T-"���zw���"~M+ڭi�T+�"$���@Y+�A��$�b¸����ȡ��QakI�C�-���9�H���Y�������?�v�͏����x�.�xf�d���S���5x�������R�Pq
+����T�B{f���}w{���?���>/��Ԣ�����A�yc��8�mN(��%��� =`�=�����gs��T�pv+`+��U����^�!�0x��3�{Ws��p�-ge�������&M@�*������i���m�[�@����ɋ�t�3��]�q��~Y��: qF&��B}�f�l�(��]�2& �F�7P��r5��`���Q ��:Ce������c�Y�z����>i3���5X:�_����!�!��5�����ǟg���1;�N�����l��1[������ v��2�r)9������v�����]S�&��}��!'3�>�-ZhC�F$X-�1n���v�&�t؏"p� !p��1�Mp���/��`Թ;���,�0���%�W�-�:�3�5�4z���e����}{��_�H��Ve(�J+G]�vj�&��z&�G�C�v��u����$�����h^�ݗP\H�ә���*���,8}��~M���{�S�<� �>$�B=�~�I���j�5�t�v��fQ_��4(�����(G)��� ����*���C�J��zo���j���I�%@e��le���'�%����x�_X�������;:|�C1��X
+mjP�����%�Ɓ������K�V��B�H5 � �����t���.;�+���Z�}g���U�W����OxM�kG@#��iB�������C5�ݶ:��0I�$E�=�.���2���mCV�ѝA|��I�Q&I}���A*�� }�k��!A�G�3�Lz*(��uz�6@g�iU!N����f�J'P�x�,�� ���W$�m�n=����a�"�,��7^��,�M�O��M���wA�SV��"����� ����7<n���H>�pw��$+�f���xE]�[���j�w04J��t�����Hn-�_�+�Z�C/4H,y � I�!����Gw¡�'��d��Ky�>A|��D�H���SuǸ�n^�/�}��Z��[+u�Z���Y,�7W����˝�[�כ������I�7F?�m��მ6d,ݲ���'f�;���sX.u+�q�}�R4�u ܱߴnqJ=V�1Ih͊F@Be��;�����\C�E�J�-q�����:ua����3��b�{Q�՟S�lweE3�����is�I��s�4����f��G�*���J�3���&��&k�W�tD��\�Z�RZ�0�fe���G���>�� �b=_+��F�8&j�HU�� ¤ �o��ӸS�}�|?}J�k�t�T��ӣ0�t��
+endstream
+endobj
+76 0 obj
+5031
+endobj
+9 0 obj
+<</Type/FontDescriptor/FontName/YCYKOY+Palatino-Bold/FontBBox[-152 -301 1000 935]/Flags 34
+/Ascent 935
+/CapHeight 695
+/Descent -301
+/ItalicAngle 0
+/StemV 156
+/MissingWidth 250
+/XHeight 471
+/CharSet(/hyphen/period/one/two/three/four/five/six/seven/A/B/C/D/E/F/L/M/N/P/S/T/U/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/r/s/t/u/w/x/y/guilsinglright)
+/FontFile3 8 0 R>>
+endobj
+8 0 obj
+<</Subtype/Type1C/Filter/FlateDecode/Length 77 0 R>>stream
+x��X XSWھ�ɍV�rM�W,D�K;�Z�:j�(���"� �%$���5!������ �,A@Q�J]jk�[�Z[k���t�Ӟ����..Ŷ���?O�'��{��{��{���M��999����߶s�#�y����JE?������7���3�ō�|�終DZ��g��s']�>��<�a��9�Ә������������Te��c�4�gW�^-�ʔ��l����I���K�T�T%J�4�${�R�&N*��R�����[vl�,ݼc�d�4I����F)�ђ+Þ�`���&l��^Ğ���va��"l3�,�ۃ��-���-�^l+��c۰�X+� #�g���X���ӹ)�S�:�M �Z#xA��p���+ʙ�`��t�#[fL��<s�L��Q��.wf������َG�Ε!�'sb��s:Ğb�c.�չ-t���K.���]��9��ނ���s�����L��%�p�+&Єf�4����K�1ר_̙�U0 0�RC)UPo(���ZV͈P�v����Y���]�7C7�iv���l>�8%���8#+�;8a?�q+F}��a{Y��������T}���1
+�/�����kX�ҝ���َ�e}2��T���ˎ�y�.�:Ί�}p�MÊd���Ɖ�X8�.w¿0+�n.��䈄g�?�^��qɅY*�0喘�����V�i|��G�ٜ�����h@��m)'��tM�3"�&�K.T���vq�PT�a&�!ٿ6�]As�i)��<]�W��< x�&��p������-d��i��N~@]{����F����]��6s��ܸ�6 Z�A�=Ɋ~E�x}��4 \��L��֠���?��B5lK�������lJ� d2)ŨVP����\o�4��� 1�e�J+-�u�&$5��̚R�;\���a+T�(Pd̥�b9�����<�;�~�������J
+��u9�#��@�N��t90�*-eV�3&A/ι�����7+Ͻ%�o�;!/�k�L�;V�*�&����r�Հ���6�Z��L/S �@�苝�GF�jd� ���q�-m+m�[�x,�zE&ɹ&�ǀ�D��?���Z�+�g$�2�(!���P���z��
+$�*��gs%|a���)�$]���0R�/�c�V����I"�o�:��1� }����`���.zC/�;(��)/�3���0[��̦�*.C���K��Rda:A]��C"��gN�$��Z���*J��%l��6���~y�)�Tt�u�w�]j����֡w�
+�����?+HX%4�Y{jz��I�� J��'đ2YddO\�����_��7s|�\�:H� p����Ę��YhS!H���ARF���Ƿ�W�+LrTL{�pG���/�*Q�=ė���ԔQ �)�!FM�[�Ԝr�s ����� �8�<Yt��+�����������uPZ��T�
+42���"����-�ܭ� ���*���{���pm�n�Ln��P���}����8��7f��u��Zn ~���/��:���ˮ5����pV]�v �S�<&\�@�=�����R�Vn���u^�{c��A�9��<�2A������ z�D\ж��͞q �z[I��Pĵ������1N^٘��i�nH1\t��i�j���bh�+ӓe�m|d���L �l s��,a��}�'��XV�f������8�
+V�G��#� 3\RX�b���q�7qsvs�wN�K*L�e6�Qk���5("�����Ya�֕W��[�u ��� ��;�'=b�[��햑*��5�
+TP�f�27YH�E�rS���
+�~L"�S�p�F����璝m�����s{W�q���N\��L̬�$�$��gu�'"L@jB��͌H,Hލ�G�p���nңͭ���\�8�G���G�\�ࣦ�'?s(=;�N����eƐ̭���p�s����?~�g߅�w�N���p�w����#�����s��^}��=P,����!�-���K'v,�Iطg�������_����28��-��/��I����a�As��+ ٭LE�N-Wͧ��3Ƞ�
+�u�����\��+�5d�'����K�ml�m�M84�z�c��uѿfL�̘g�f���.��W�ⱩM
+endstream
+endobj
+77 0 obj
+5531
+endobj
+22 0 obj
+<</Subtype/Type1/BaseFont/KORKOY+LucidaSansUnicode20/Type/Font/Name/R22/FontDescriptor 21 0 R/FirstChar 0/LastChar 170/Widths[
+500 1000 500 1000 333 250 167 633 316 125 56 0 0 0 0 0
+325 325 633 500 1000 1000 578 500 316 316 316 316 373 373 373 373
+633 633 561 356 333 667 1000 325 0 0 0 0 0 0 0 0
+1012 1355 325 542 759 325 542 759 353 331 331 723 518 422 500 316
+590 465 916 325 0 602 316 316 316 316 316 316 316 316 316 316
+316 316 316 316 316 316 316 316 316 316 316 316 316 316 316 316
+316 316 316 316 316 316 316 316 316 316 316 316 316 316 316 316
+422 422 422 422 422 422 422 422 422 422 422 422 422 226 226 383
+422 422 422 422 422 422 422 422 422 422 422 422 422 226 226 316
+316 316 316 316 316 316 316 316 316 316 316 316 316 316 316 316
+696 706 687 633 633 934 817 1319 1014 1046 1060]
+>>
+endobj
+42 0 obj
+<</Subtype/Type1/BaseFont/MYPKOY+Palatino-Italic/Type/Font/Name/R42/FontDescriptor 12 0 R/FirstChar 32/LastChar 255/Widths[
+250 333 500 500 500 889 778 278 333 333 389 606 250 606 250 296
+500 500 500 500 500 500 500 500 500 500 250 250 606 606 606 500
+747 722 611 667 778 611 556 722 778 333 333 667 556 944 778 778
+611 778 667 556 611 778 722 944 722 667 667 333 606 333 606 500
+278 444 463 407 500 389 278 500 500 278 278 444 278 778 556 444
+500 463 389 389 333 556 500 722 500 500 444 333 606 333 606 250
+250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250
+278 333 333 333 333 333 333 333 333 250 333 333 250 333 333 333
+250 333 500 500 500 500 606 500 333 747 333 500 606 333 747 333
+400 606 300 300 333 556 500 250 333 300 333 500 750 750 750 500
+722 722 722 722 722 722 941 667 611 611 611 611 333 333 333 333
+778 778 778 778 778 778 778 606 778 778 778 778 778 667 611 500
+444 444 444 444 444 444 638 407 389 389 389 389 278 278 278 278
+444 556 444 444 444 444 444 606 444 556 556 556 556 500 500 500]
+>>
+endobj
+25 0 obj
+<</Type/FontDescriptor/FontName/Times-Roman>>
+endobj
+59 0 obj
+<</Subtype/Type1/BaseFont/GPQJOY+Palatino-Roman/Type/Font/Name/R59/FontDescriptor 15 0 R/FirstChar 32/LastChar 255/Widths[
+250 278 371 500 500 840 778 278 333 333 389 606 250 606 250 606
+500 500 500 500 500 500 500 500 500 500 250 250 606 606 606 444
+747 778 611 709 774 611 556 763 832 337 333 726 611 946 831 786
+604 786 668 525 613 778 722 1000 667 667 667 333 606 333 606 500
+278 500 553 444 611 479 333 556 582 291 234 556 291 883 582 546
+601 560 395 424 326 603 565 834 516 556 500 333 606 333 606 250
+250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250
+287 333 333 333 333 333 333 250 333 250 333 333 250 380 313 333
+250 278 500 500 500 500 606 500 333 747 333 500 606 333 747 333
+400 606 300 300 333 603 628 250 333 300 333 500 750 750 750 444
+778 778 778 778 778 778 944 709 611 611 611 611 337 337 337 337
+774 831 786 786 786 786 786 606 833 778 778 778 778 667 604 556
+500 500 500 500 500 500 758 444 479 479 479 479 287 287 287 287
+546 582 546 546 546 546 546 606 556 603 603 603 603 556 601 556]
+>>
+endobj
+63 0 obj
+<</Subtype/Type1/BaseFont/Courier/Type/Font/Name/R63>>
+endobj
+36 0 obj
+<</Subtype/Type1/BaseFont/Times-Roman/Type/Font/Name/R36/FirstChar 32/LastChar 251/Widths[
+250 333 408 500 500 833 778 333 333 333 500 564 250 333 250 278
+500 500 500 500 500 500 500 500 500 500 278 278 564 564 564 444
+921 722 667 667 722 611 556 722 722 333 389 722 611 889 722 722
+556 722 667 556 611 722 722 944 722 722 611 333 278 333 469 500
+333 444 500 444 500 444 333 500 500 278 278 500 278 778 500 500
+500 500 333 389 278 500 500 722 500 500 444 480 200 480 541 250
+250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250
+250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250
+250 333 500 500 167 500 500 500 500 180 444 500 333 333 556 556
+250 650 500 500 250 250 453 350 333 444 444 500 1000 1000 250 444
+250 333 333 333 333 333 333 333 333 250 333 333 250 333 333 333
+1000 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250
+250 889 250 276 250 250 250 250 611 722 889 310 250 250 250 250
+250 667 250 250 250 278 250 250 278 500 722 500]
+>>
+endobj
+26 0 obj
+<</Subtype/Type1/BaseFont/Times-Roman/Type/Font/Name/R26/FirstChar 32/LastChar 251/Widths[
+250 333 408 500 500 833 778 333 333 333 500 564 250 333 250 278
+500 500 500 500 500 500 500 500 500 500 278 278 564 564 564 444
+921 722 667 667 722 611 556 722 722 333 389 722 611 889 722 722
+556 722 667 556 611 722 722 944 722 722 611 333 278 333 469 500
+333 444 500 444 500 444 333 500 500 278 278 500 278 778 500 500
+500 500 333 389 278 500 500 722 500 500 444 480 200 480 541 250
+250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250
+250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250
+250 333 500 500 167 500 500 500 500 180 444 500 333 333 556 556
+250 650 500 500 250 250 453 350 333 444 444 500 1000 1000 250 444
+250 333 333 333 333 333 333 333 333 250 333 333 250 333 333 333
+1000 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250
+250 889 250 276 250 250 250 250 611 722 889 310 250 250 250 250
+250 667 250 250 250 278 250 250 278 500 722 500]
+>>
+endobj
+23 0 obj
+<</Type/FontDescriptor/FontName/Courier>>
+endobj
+24 0 obj
+<</Subtype/Type1/BaseFont/Courier/Type/Font/Name/R24/Encoding 78 0 R>>
+endobj
+78 0 obj
+<</Type/Encoding/Differences[
+173/hyphen]>>
+endobj
+64 0 obj
+<</Subtype/Type1/BaseFont/YCYKOY+Palatino-Bold/Type/Font/Name/R64/FontDescriptor 9 0 R/FirstChar 32/LastChar 255/Widths[
+250 278 402 500 500 889 833 278 333 333 444 606 250 606 250 296
+500 500 500 500 500 500 500 500 500 500 250 250 606 606 606 444
+747 778 667 722 833 611 556 833 833 389 389 778 611 1000 833 833
+611 833 722 611 667 778 778 1000 667 667 667 333 606 333 606 500
+278 500 611 444 611 500 389 556 611 333 333 611 333 889 611 556
+611 611 389 444 333 611 556 833 500 556 500 310 606 310 606 250
+250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250
+333 333 333 333 333 333 333 333 333 250 333 333 250 333 333 333
+250 278 500 500 500 500 606 500 333 747 438 500 606 333 747 333
+400 606 300 300 333 611 641 250 333 300 488 500 750 750 750 444
+778 778 778 778 778 778 1000 722 611 611 611 611 389 389 389 389
+833 833 833 833 833 833 833 606 833 778 778 778 778 667 611 611
+500 500 500 500 500 500 778 444 500 500 500 500 333 333 333 333
+556 611 556 556 556 556 556 606 556 611 611 611 611 556 611 556]
+>>
+endobj
+44 0 obj
+<</Subtype/Type1/BaseFont/GPQJOY+Palatino-Roman/Type/Font/Name/R44/FontDescriptor 15 0 R/FirstChar 32/LastChar 255/Widths[
+250 278 371 500 500 840 778 278 333 333 389 606 250 606 250 606
+500 500 500 500 500 500 500 500 500 500 250 250 606 606 606 444
+747 778 611 709 774 611 556 763 832 337 333 726 611 946 831 786
+604 786 668 525 613 778 722 1000 667 667 667 333 606 333 606 500
+278 500 553 444 611 479 333 556 582 291 234 556 291 883 582 546
+601 560 395 424 326 603 565 834 516 556 500 333 606 333 606 250
+250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250
+287 333 333 333 333 333 333 250 333 250 333 333 250 380 313 333
+250 278 500 500 500 500 606 500 333 747 333 500 606 333 747 333
+400 606 300 300 333 603 628 250 333 300 333 500 750 750 750 444
+778 778 778 778 778 778 944 709 611 611 611 611 337 337 337 337
+774 831 786 786 786 786 786 606 833 778 778 778 778 667 604 556
+500 500 500 500 500 500 758 444 479 479 479 479 287 287 287 287
+546 582 546 546 546 546 546 606 556 603 603 603 603 556 601 556]
+>>
+endobj
+48 0 obj
+<</Subtype/Type1/BaseFont/MYPKOY+Palatino-Italic/Type/Font/Name/R48/FontDescriptor 12 0 R/FirstChar 32/LastChar 255/Widths[
+250 333 500 500 500 889 778 278 333 333 389 606 250 606 250 296
+500 500 500 500 500 500 500 500 500 500 250 250 606 606 606 500
+747 722 611 667 778 611 556 722 778 333 333 667 556 944 778 778
+611 778 667 556 611 778 722 944 722 667 667 333 606 333 606 500
+278 444 463 407 500 389 278 500 500 278 278 444 278 778 556 444
+500 463 389 389 333 556 500 722 500 500 444 333 606 333 606 250
+250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250
+278 333 333 333 333 333 333 333 333 250 333 333 250 333 333 333
+250 333 500 500 500 500 606 500 333 747 333 500 606 333 747 333
+400 606 300 300 333 556 500 250 333 300 333 500 750 750 750 500
+722 722 722 722 722 722 941 667 611 611 611 611 333 333 333 333
+778 778 778 778 778 778 778 606 778 778 778 778 778 667 611 500
+444 444 444 444 444 444 638 407 389 389 389 389 278 278 278 278
+444 556 444 444 444 444 444 606 444 556 556 556 556 500 500 500]
+>>
+endobj
+49 0 obj
+<</Subtype/Type1/BaseFont/YCYKOY+Palatino-Bold/Type/Font/Name/R49/FontDescriptor 9 0 R/FirstChar 32/LastChar 255/Widths[
+250 278 402 500 500 889 833 278 333 333 444 606 250 606 250 296
+500 500 500 500 500 500 500 500 500 500 250 250 606 606 606 444
+747 778 667 722 833 611 556 833 833 389 389 778 611 1000 833 833
+611 833 722 611 667 778 778 1000 667 667 667 333 606 333 606 500
+278 500 611 444 611 500 389 556 611 333 333 611 333 889 611 556
+611 611 389 444 333 611 556 833 500 556 500 310 606 310 606 250
+250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250
+333 333 333 333 333 333 333 333 333 250 333 333 250 333 333 333
+250 278 500 500 500 500 606 500 333 747 438 500 606 333 747 333
+400 606 300 300 333 611 641 250 333 300 488 500 750 750 750 444
+778 778 778 778 778 778 1000 722 611 611 611 611 389 389 389 389
+833 833 833 833 833 833 833 606 833 778 778 778 778 667 611 611
+500 500 500 500 500 500 778 444 500 500 500 500 333 333 333 333
+556 611 556 556 556 556 556 606 556 611 611 611 611 556 611 556]
+>>
+endobj
+50 0 obj
+<</Subtype/Type1/BaseFont/Courier/Type/Font/Name/R50/Encoding 79 0 R>>
+endobj
+79 0 obj
+<</Type/Encoding/Differences[
+173/hyphen]>>
+endobj
+29 0 obj
+<</Subtype/Type1/BaseFont/GPQJOY+Palatino-Roman/Type/Font/Name/R29/FontDescriptor 15 0 R/FirstChar 32/LastChar 255/Widths[
+250 278 371 500 500 840 778 278 333 333 389 606 250 606 250 606
+500 500 500 500 500 500 500 500 500 500 250 250 606 606 606 444
+747 778 611 709 774 611 556 763 832 337 333 726 611 946 831 786
+604 786 668 525 613 778 722 1000 667 667 667 333 606 333 606 500
+278 500 553 444 611 479 333 556 582 291 234 556 291 883 582 546
+601 560 395 424 326 603 565 834 516 556 500 333 606 333 606 250
+250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250
+287 333 333 333 333 333 333 250 333 250 333 333 250 380 313 333
+250 278 500 500 500 500 606 500 333 747 333 500 606 333 747 333
+400 606 300 300 333 603 628 250 333 300 333 500 750 750 750 444
+778 778 778 778 778 778 944 709 611 611 611 611 337 337 337 337
+774 831 786 786 786 786 786 606 833 778 778 778 778 667 604 556
+500 500 500 500 500 500 758 444 479 479 479 479 287 287 287 287
+546 582 546 546 546 546 546 606 556 603 603 603 603 556 601 556]
+>>
+endobj
+10 0 obj
+<</Subtype/Type1/BaseFont/YCYKOY+Palatino-Bold/Type/Font/Name/R10/FontDescriptor 9 0 R/FirstChar 32/LastChar 255/Widths[
+250 278 402 500 500 889 833 278 333 333 444 606 250 606 250 296
+500 500 500 500 500 500 500 500 500 500 250 250 606 606 606 444
+747 778 667 722 833 611 556 833 833 389 389 778 611 1000 833 833
+611 833 722 611 667 778 778 1000 667 667 667 333 606 333 606 500
+278 500 611 444 611 500 389 556 611 333 333 611 333 889 611 556
+611 611 389 444 333 611 556 833 500 556 500 310 606 310 606 250
+250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250
+333 333 333 333 333 333 333 333 333 250 333 333 250 333 333 333
+250 278 500 500 500 500 606 500 333 747 438 500 606 333 747 333
+400 606 300 300 333 611 641 250 333 300 488 500 750 750 750 444
+778 778 778 778 778 778 1000 722 611 611 611 611 389 389 389 389
+833 833 833 833 833 833 833 606 833 778 778 778 778 667 611 611
+500 500 500 500 500 500 778 444 500 500 500 500 333 333 333 333
+556 611 556 556 556 556 556 606 556 611 611 611 611 556 611 556]
+/Encoding 80 0 R>>
+endobj
+80 0 obj
+<</Type/Encoding/Differences[
+173/hyphen]>>
+endobj
+66 0 obj
+<</Subtype/Type1/BaseFont/GPQJOY+Palatino-Roman/Type/Font/Name/R66/FontDescriptor 15 0 R/FirstChar 32/LastChar 255/Widths[
+250 278 371 500 500 840 778 278 333 333 389 606 250 606 250 606
+500 500 500 500 500 500 500 500 500 500 250 250 606 606 606 444
+747 778 611 709 774 611 556 763 832 337 333 726 611 946 831 786
+604 786 668 525 613 778 722 1000 667 667 667 333 606 333 606 500
+278 500 553 444 611 479 333 556 582 291 234 556 291 883 582 546
+601 560 395 424 326 603 565 834 516 556 500 333 606 333 606 250
+250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250
+287 333 333 333 333 333 333 250 333 250 333 333 250 380 313 333
+250 278 500 500 500 500 606 500 333 747 333 500 606 333 747 333
+400 606 300 300 333 603 628 250 333 300 333 500 750 750 750 444
+778 778 778 778 778 778 944 709 611 611 611 611 337 337 337 337
+774 831 786 786 786 786 786 606 833 778 778 778 778 667 604 556
+500 500 500 500 500 500 758 444 479 479 479 479 287 287 287 287
+546 582 546 546 546 546 546 606 556 603 603 603 603 556 601 556]
+>>
+endobj
+33 0 obj
+<</Subtype/Type1/BaseFont/Courier/Type/Font/Name/R33>>
+endobj
+70 0 obj
+<</Subtype/Type1/BaseFont/Courier/Type/Font/Name/R70>>
+endobj
+34 0 obj
+<</Subtype/Type1/BaseFont/MYPKOY+Palatino-Italic/Type/Font/Name/R34/FontDescriptor 12 0 R/FirstChar 32/LastChar 255/Widths[
+250 333 500 500 500 889 778 278 333 333 389 606 250 606 250 296
+500 500 500 500 500 500 500 500 500 500 250 250 606 606 606 500
+747 722 611 667 778 611 556 722 778 333 333 667 556 944 778 778
+611 778 667 556 611 778 722 944 722 667 667 333 606 333 606 500
+278 444 463 407 500 389 278 500 500 278 278 444 278 778 556 444
+500 463 389 389 333 556 500 722 500 500 444 333 606 333 606 250
+250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250
+278 333 333 333 333 333 333 333 333 250 333 333 250 333 333 333
+250 333 500 500 500 500 606 500 333 747 333 500 606 333 747 333
+400 606 300 300 333 556 500 250 333 300 333 500 750 750 750 500
+722 722 722 722 722 722 941 667 611 611 611 611 333 333 333 333
+778 778 778 778 778 778 778 606 778 778 778 778 778 667 611 500
+444 444 444 444 444 444 638 407 389 389 389 389 278 278 278 278
+444 556 444 444 444 444 444 606 444 556 556 556 556 500 500 500]
+/Encoding 81 0 R>>
+endobj
+81 0 obj
+<</Type/Encoding/Differences[
+148/tilde]>>
+endobj
+71 0 obj
+<</Subtype/Type1/BaseFont/YCYKOY+Palatino-Bold/Type/Font/Name/R71/FontDescriptor 9 0 R/FirstChar 32/LastChar 255/Widths[
+250 278 402 500 500 889 833 278 333 333 444 606 250 606 250 296
+500 500 500 500 500 500 500 500 500 500 250 250 606 606 606 444
+747 778 667 722 833 611 556 833 833 389 389 778 611 1000 833 833
+611 833 722 611 667 778 778 1000 667 667 667 333 606 333 606 500
+278 500 611 444 611 500 389 556 611 333 333 611 333 889 611 556
+611 611 389 444 333 611 556 833 500 556 500 310 606 310 606 250
+250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250
+333 333 333 333 333 333 333 333 333 250 333 333 250 333 333 333
+250 278 500 500 500 500 606 500 333 747 438 500 606 333 747 333
+400 606 300 300 333 611 641 250 333 300 488 500 750 750 750 444
+778 778 778 778 778 778 1000 722 611 611 611 611 389 389 389 389
+833 833 833 833 833 833 833 606 833 778 778 778 778 667 611 611
+500 500 500 500 500 500 778 444 500 500 500 500 333 333 333 333
+556 611 556 556 556 556 556 606 556 611 611 611 611 556 611 556]
+>>
+endobj
+35 0 obj
+<</Subtype/Type1/BaseFont/YCYKOY+Palatino-Bold/Type/Font/Name/R35/FontDescriptor 9 0 R/FirstChar 32/LastChar 255/Widths[
+250 278 402 500 500 889 833 278 333 333 444 606 250 606 250 296
+500 500 500 500 500 500 500 500 500 500 250 250 606 606 606 444
+747 778 667 722 833 611 556 833 833 389 389 778 611 1000 833 833
+611 833 722 611 667 778 778 1000 667 667 667 333 606 333 606 500
+278 500 611 444 611 500 389 556 611 333 333 611 333 889 611 556
+611 611 389 444 333 611 556 833 500 556 500 310 606 310 606 250
+250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250
+333 333 333 333 333 333 333 333 333 250 333 333 250 333 333 333
+250 278 500 500 500 500 606 500 333 747 438 500 606 333 747 333
+400 606 300 300 333 611 641 250 333 300 488 500 750 750 750 444
+778 778 778 778 778 778 1000 722 611 611 611 611 389 389 389 389
+833 833 833 833 833 833 833 606 833 778 778 778 778 667 611 611
+500 500 500 500 500 500 778 444 500 500 500 500 333 333 333 333
+556 611 556 556 556 556 556 606 556 611 611 611 611 556 611 556]
+>>
+endobj
+13 0 obj
+<</Subtype/Type1/BaseFont/MYPKOY+Palatino-Italic/Type/Font/Name/R13/FontDescriptor 12 0 R/FirstChar 32/LastChar 255/Widths[
+250 333 500 500 500 889 778 278 333 333 389 606 250 606 250 296
+500 500 500 500 500 500 500 500 500 500 250 250 606 606 606 500
+747 722 611 667 778 611 556 722 778 333 333 667 556 944 778 778
+611 778 667 556 611 778 722 944 722 667 667 333 606 333 606 500
+278 444 463 407 500 389 278 500 500 278 278 444 278 778 556 444
+500 463 389 389 333 556 500 722 500 500 444 333 606 333 606 250
+250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250
+278 333 333 333 333 333 333 333 333 250 333 333 250 333 333 333
+250 333 500 500 500 500 606 500 333 747 333 500 606 333 747 333
+400 606 300 300 333 556 500 250 333 300 333 500 750 750 750 500
+722 722 722 722 722 722 941 667 611 611 611 611 333 333 333 333
+778 778 778 778 778 778 778 606 778 778 778 778 778 667 611 500
+444 444 444 444 444 444 638 407 389 389 389 389 278 278 278 278
+444 556 444 444 444 444 444 606 444 556 556 556 556 500 500 500]
+>>
+endobj
+52 0 obj
+<</Subtype/Type1/BaseFont/GPQJOY+Palatino-Roman/Type/Font/Name/R52/FontDescriptor 15 0 R/FirstChar 32/LastChar 255/Widths[
+250 278 371 500 500 840 778 278 333 333 389 606 250 606 250 606
+500 500 500 500 500 500 500 500 500 500 250 250 606 606 606 444
+747 778 611 709 774 611 556 763 832 337 333 726 611 946 831 786
+604 786 668 525 613 778 722 1000 667 667 667 333 606 333 606 500
+278 500 553 444 611 479 333 556 582 291 234 556 291 883 582 546
+601 560 395 424 326 603 565 834 516 556 500 333 606 333 606 250
+250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250
+287 333 333 333 333 333 333 250 333 250 333 333 250 380 313 333
+250 278 500 500 500 500 606 500 333 747 333 500 606 333 747 333
+400 606 300 300 333 603 628 250 333 300 333 500 750 750 750 444
+778 778 778 778 778 778 944 709 611 611 611 611 337 337 337 337
+774 831 786 786 786 786 786 606 833 778 778 778 778 667 604 556
+500 500 500 500 500 500 758 444 479 479 479 479 287 287 287 287
+546 582 546 546 546 546 546 606 556 603 603 603 603 556 601 556]
+>>
+endobj
+56 0 obj
+<</Subtype/Type1/BaseFont/Courier/Type/Font/Name/R56>>
+endobj
+57 0 obj
+<</Subtype/Type1/BaseFont/YCYKOY+Palatino-Bold/Type/Font/Name/R57/FontDescriptor 9 0 R/FirstChar 32/LastChar 255/Widths[
+250 278 402 500 500 889 833 278 333 333 444 606 250 606 250 296
+500 500 500 500 500 500 500 500 500 500 250 250 606 606 606 444
+747 778 667 722 833 611 556 833 833 389 389 778 611 1000 833 833
+611 833 722 611 667 778 778 1000 667 667 667 333 606 333 606 500
+278 500 611 444 611 500 389 556 611 333 333 611 333 889 611 556
+611 611 389 444 333 611 556 833 500 556 500 310 606 310 606 250
+250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250
+333 333 333 333 333 333 333 333 333 250 333 333 250 333 333 333
+250 278 500 500 500 500 606 500 333 747 438 500 606 333 747 333
+400 606 300 300 333 611 641 250 333 300 488 500 750 750 750 444
+778 778 778 778 778 778 1000 722 611 611 611 611 389 389 389 389
+833 833 833 833 833 833 833 606 833 778 778 778 778 667 611 611
+500 500 500 500 500 500 778 444 500 500 500 500 333 333 333 333
+556 611 556 556 556 556 556 606 556 611 611 611 611 556 611 556]
+>>
+endobj
+16 0 obj
+<</Subtype/Type1/BaseFont/GPQJOY+Palatino-Roman/Type/Font/Name/R16/FontDescriptor 15 0 R/FirstChar 32/LastChar 255/Widths[
+250 278 371 500 500 840 778 278 333 333 389 606 250 606 250 606
+500 500 500 500 500 500 500 500 500 500 250 250 606 606 606 444
+747 778 611 709 774 611 556 763 832 337 333 726 611 946 831 786
+604 786 668 525 613 778 722 1000 667 667 667 333 606 333 606 500
+278 500 553 444 611 479 333 556 582 291 234 556 291 883 582 546
+601 560 395 424 326 603 565 834 516 556 500 333 606 333 606 250
+250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250
+287 333 333 333 333 333 333 250 333 250 333 333 250 380 313 333
+250 278 500 500 500 500 606 500 333 747 333 500 606 333 747 333
+400 606 300 300 333 603 628 250 333 300 333 500 750 750 750 444
+778 778 778 778 778 778 944 709 611 611 611 611 337 337 337 337
+774 831 786 786 786 786 786 606 833 778 778 778 778 667 604 556
+500 500 500 500 500 500 758 444 479 479 479 479 287 287 287 287
+546 582 546 546 546 546 546 606 556 603 603 603 603 556 601 556]
+/Encoding 82 0 R>>
+endobj
+82 0 obj
+<</Type/Encoding/Differences[
+173/hyphen]>>
+endobj
+38 0 obj
+<</Subtype/Type1/BaseFont/GPQJOY+Palatino-Roman/Type/Font/Name/R38/FontDescriptor 15 0 R/FirstChar 32/LastChar 255/Widths[
+250 278 371 500 500 840 778 278 333 333 389 606 250 606 250 606
+500 500 500 500 500 500 500 500 500 500 250 250 606 606 606 444
+747 778 611 709 774 611 556 763 832 337 333 726 611 946 831 786
+604 786 668 525 613 778 722 1000 667 667 667 333 606 333 606 500
+278 500 553 444 611 479 333 556 582 291 234 556 291 883 582 546
+601 560 395 424 326 603 565 834 516 556 500 333 606 333 606 250
+250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250
+287 333 333 333 333 333 333 250 333 250 333 333 250 380 313 333
+250 278 500 500 500 500 606 500 333 747 333 500 606 333 747 333
+400 606 300 300 333 603 628 250 333 300 333 500 750 750 750 444
+778 778 778 778 778 778 944 709 611 611 611 611 337 337 337 337
+774 831 786 786 786 786 786 606 833 778 778 778 778 667 604 556
+500 500 500 500 500 500 758 444 479 479 479 479 287 287 287 287
+546 582 546 546 546 546 546 606 556 603 603 603 603 556 601 556]
+>>
+endobj
+19 0 obj
+<</Subtype/Type1/BaseFont/KERJOY+LucidaSansUnicode21/Type/Font/Name/R19/FontDescriptor 18 0 R/FirstChar 0/LastChar 234/Widths[
+750 750 738 922 648 750 750 630 602 780 773 1121 643 880 704 704
+675 704 787 590 979 819 967 855 725 705 904 938 909 782 633 633
+807 1481 807 654 645 512 876 876 582 401 653 690 799 678 853 488
+572 828 664 1043 574 676 666 463 607 316 316 316 316 316 316 316
+316 316 316 316 316 316 316 316 316 316 316 316 316 316 316 316
+316 316 316 316 316 316 316 316 316 316 316 316 316 316 316 316
+316 316 316 316 316 316 316 316 316 316 316 316 316 316 316 316
+316 316 316 316 316 316 316 316 316 316 316 316 316 316 316 316
+316 316 316 316 316 316 316 316 316 316 316 316 316 316 316 316
+940 530 940 530 1205 530 745 745 745 745 940 940 795 795 940 530
+940 530 940 940 940 530 940 530 530 940 940 940 940 1217 1205 660
+687 687 687 687 687 940 983 983 940 940 940 940 940 940 434 434
+940 940 434 434 940 771 940 940 771 940 771 940 940 940 1205 940
+940 771 940 771 1205 772 813 813 813 813 940 940 1205 1205 530 530
+940 530 940 530 940 940 940 772 940 772 772]
+>>
+endobj
+2 0 obj
+<</Producer(AFPL Ghostscript 7.04)>>endobj
+xref
+0 83
+0000000000 65535 f
+0000020002 00000 n
+0000064668 00000 n
+0000019901 00000 n
+0000020050 00000 n
+0000018877 00000 n
+0000000015 00000 n
+0000003289 00000 n
+0000036528 00000 n
+0000036159 00000 n
+0000052731 00000 n
+0000031021 00000 n
+0000030657 00000 n
+0000058224 00000 n
+0000022457 00000 n
+0000021903 00000 n
+0000061415 00000 n
+0000021502 00000 n
+0000021270 00000 n
+0000063571 00000 n
+0000020861 00000 n
+0000020623 00000 n
+0000042165 00000 n
+0000047179 00000 n
+0000047237 00000 n
+0000044018 00000 n
+0000046185 00000 n
+0000020105 00000 n
+0000020135 00000 n
+0000051691 00000 n
+0000019037 00000 n
+0000003309 00000 n
+0000006559 00000 n
+0000054887 00000 n
+0000055029 00000 n
+0000057184 00000 n
+0000045191 00000 n
+0000020233 00000 n
+0000062531 00000 n
+0000019181 00000 n
+0000006580 00000 n
+0000009654 00000 n
+0000042978 00000 n
+0000020320 00000 n
+0000048424 00000 n
+0000019325 00000 n
+0000009675 00000 n
+0000012902 00000 n
+0000049464 00000 n
+0000050504 00000 n
+0000051544 00000 n
+0000020363 00000 n
+0000059264 00000 n
+0000019469 00000 n
+0000012923 00000 n
+0000014937 00000 n
+0000060304 00000 n
+0000060375 00000 n
+0000020439 00000 n
+0000044080 00000 n
+0000019613 00000 n
+0000014958 00000 n
+0000017308 00000 n
+0000045120 00000 n
+0000047384 00000 n
+0000020504 00000 n
+0000053847 00000 n
+0000019757 00000 n
+0000017329 00000 n
+0000018856 00000 n
+0000054958 00000 n
+0000056144 00000 n
+0000020569 00000 n
+0000021250 00000 n
+0000021883 00000 n
+0000030636 00000 n
+0000036138 00000 n
+0000042144 00000 n
+0000047324 00000 n
+0000051631 00000 n
+0000053787 00000 n
+0000056085 00000 n
+0000062471 00000 n
+trailer
+<< /Size 83 /Root 1 0 R /Info 2 0 R
+>>
+startxref
+64719
+%%EOF
--- /dev/null
+++ b/doc/limbo/addendum.ms
@@ -1,0 +1,495 @@
+.TL
+Addendum to
+.I "The Limbo Programming Language"
+.AU
+Vita Nuova
+.br
+30 March 2005
+.NH 1
+Introduction
+.LP
+This addendum provides a brief summary of several language changes to
+Limbo since
+.I "The Limbo Programming Language"
+was last revised:
+.RS
+.IP •
+buffered channels
+.IP •
+unrestricted \f5alt\f1
+.IP •
+function references
+.IP •
+exceptions
+.IP •
+exponentiation
+.IP •
+fixed-point types
+.RE
+.NH 1
+Buffered channels
+.LP
+A buffered channel can now be declared:
+.P1
+c := chan[1] of int;
+.P2
+Here the buffer size is 1. A send on this channel will succeed immediately
+if there is a receiver waiting or if the buffer is empty. A receive on this
+channel will succeed immediately if there is a data item in the buffer. This allows us to
+write a very simple locking mechanism:
+.P1
+acquire(c: chan of int)
+{
+ c <-= 0;
+}
+
+release(c: chan of int)
+{
+ <-c;
+}
+
+new(): chan of int
+{
+ return chan[1] of int;
+}
+.P2
+The declaration
+.P1
+c := chan[0] of int;
+.P2
+is equivalent to
+.P1
+ c := chan of int;
+.P2
+An attempt to create a channel with a negative buffer size will raise
+an exception. An attempt to create a channel with a very large buffer
+may result in an immediate memory exception if there is not enough
+room for the buffer.
+.NH 1
+Unrestricted
+.B alt
+.LP
+The implementation has changed to remove the restriction that only one process can be
+waiting in an
+.CW alt
+to send or receive on a particular channel.
+The busy exception never occurs now. Thus you can do
+.P1
+i()
+{
+ c := chan of int;
+ c1 := chan of int;
+ spawn p(c, c1);
+ <-c;
+ spawn p(c, c1);
+ <-c;
+ for(i := 0; i < 20; i++)
+ c1 <-= i;
+}
+
+p(c: chan of int, c1: chan of int)
+{
+ c <-= 0;
+ for(;;)
+ alt{
+ i := <-c1 =>
+ ;
+ }
+}
+.P2
+The two spawned processes can both wait on
+.CW c1
+without fuss.
+Processes are queued on a strict FIFO basis so, in
+the example above, the two processes receive on
+.CW c1
+alternately.
+.NH 1
+Function references
+.LP
+Function references may be declared as follows:
+.P1
+fp: ref fn(s1: string, s2: string): int;
+.P2
+Given the function
+.P1
+cmp(s1: string, s2: string): int
+{
+ if(s1 < s2)
+ return -1;
+ if(s1 > s2)
+ return 1;
+ return 0;
+}
+.P2
+a reference to it can be created by assignment:
+.P1
+fp = cmp;
+.P2
+where the name can be qualified by an explicit module reference as usual:
+.P1
+fp = mod->cmp;
+.P2
+or it can be returned from a function:
+.P1
+Cmp: type ref fn(s1: string, s2: string): int;
+
+rcmp(s1: string, s2: string): int
+{
+ return -cmp(s1, s2);
+}
+
+choose(i: int): Cmp
+{
+ if(i)
+ return rcmp;
+ return cmp;
+}
+.P2
+(the declaration of the synonym
+.CW Cmp
+was done only for clarity).
+They may be declared and passed as parameters:
+.P1
+sort(a: array of string, f: ref fn(s1, s2: string): int): array of string
+{
+ # ...
+}
+ # ...
+b := sort(a, cmp);
+c := sort(a, rcmp);
+.P2
+The function is called via the reference by
+.P1
+ r := fp("fred", "bloggs");
+.P2
+Otherwise function references behave just like any other reference type.
+.NH 1
+Exceptions
+.LP
+Both string exceptions and user defined exceptions are now provided.
+The
+.CW Sys
+module interface to exceptions
+has been removed and replaced by new language constructs in limbo.
+.NH 2
+String exceptions
+.LP
+Simple string exceptions can be raised as follows
+.P1
+raise \fIs\fP;
+.P2
+where
+.I s
+is any value of type string (it need not be constant).
+.LP
+Exception handlers may be attached to a block (or sequence of statements) :-
+.P1
+{
+ foo();
+ bar();
+} exception e {
+"a" or "b" =>
+ sys->print("caught %s\en", e);
+ raise;
+"ab*" =>
+ sys->print("caught %s\en", e);
+ exit;
+"abcd*" =>
+ sys->print("caught %s\en", e);
+ raise e;
+"a*" =>
+ sys->print("caught %s\en", e);
+ raise "c";
+"*" =>
+ sys->print("caught %s\en", e);
+}
+LL:
+.P2
+.LP
+Any exception occurring within the block (and in nested function calls within the block) can
+potentially be caught by the exception handler. An exception is caught by a guard exactly
+maching the exception string or by a guard
+\f5\&"\fP\fIs\fP\f5*"\fP
+where
+.I s
+is a prefix of the exception string.
+The most specific match is used. Thus a raise of "a" will be caught by the first
+guard and not by the fourth guard. A raise of "abcde" is caught by the third and not the second
+or fourth. If a match is found, the sequence of statements following the guard are executed.
+If not, the system searches for a handler at a higher level.
+.LP
+As shown above, the exception is available through the exception identifier (e in this case) if given following the exception keyword.
+.LP
+The exception is reraised using
+.P1
+raise;
+.P2
+or
+.P1
+raise e;
+.P2
+.LP
+Both the block and the exception code will fall through to the statement labelled
+LL unless, of course, they do an explicit exit, return or raise first.
+.NH 2
+User-defined exceptions
+.LP
+You can declare your own exceptions:
+.P1
+implement Fibonacci;
+
+include "sys.m";
+include "draw.m";
+
+Fibonacci: module
+{
+ init: fn(nil: ref Draw->Context, argv: list of string);
+};
+.P3
+
+init(nil: ref Draw->Context, nil: list of string)
+{
+ sys := load Sys Sys->PATH;
+ for(i := 0; ; i++){
+ f := fibonacci(i);
+ if(f < 0)
+ break;
+ sys->print("F(%d) = %d\en", i, f);
+ }
+}
+.P3
+
+FIB: exception(int, int);
+.P3
+
+fibonacci(n: int): int
+{
+ {
+ fib(1, n, 1, 1);
+ }exception e{
+ FIB =>
+ (x, nil) := e;
+ return x;
+ "*" =>
+ sys->print("unexpected string exception %s raised\en", e);
+ * =>
+ sys->print("unexpected exception raised\en");
+ }
+ return 0;
+}
+.P3
+
+fib(n: int, m: int, x: int, y: int) raises (FIB)
+{
+ if(n >= m)
+ raise FIB(x, y);
+
+ {
+ fib(n+1, m, x, y);
+ }exception e{
+ FIB =>
+ (x, y) = e;
+ x = x+y;
+ y = x-y;
+ raise FIB(x, y);
+ }
+}
+.P2
+.LP
+.CW FIB
+is a declared exception that returns two integers. The values are supplied when raising the exception:
+.P1
+raise FIB(3, 4);
+.P2
+When caught the values can be recovered by treating the declared exception identifier
+as if it were a tuple of 2 integers:
+.P1
+(x, y) = e;
+.P2
+In general each exception alternative treats the exception identifier appropriately : as a string
+when the exception qualifier is a string, as the relevant tuple when the exception is declared.
+.LP
+If you do
+.P1
+"abcde" or FIB =>
+ (x, y) = e;
+ sys->print("%s\en", e);
+.P2
+you will get a compiler error as
+.CW e 's
+type is indeterminate within this alternative.
+.LP
+Reraising is the same as in the case of string exceptions.
+.LP
+Note also the difference between the string guard
+\&\f5"*"\fP and the guard
+.CW *
+in
+the function fibonacci.
+The former will match any string exception, the latter any exception. If a
+string exception does occur it matches the former as it is the most specific.
+If an unexpected user defined
+exception occurs it matches the latter.
+.LP
+The main difference between declared exceptions and string exceptions is
+that the former must be caught by the immediate caller of a function that
+raises them, otherwise they turn into a string exception whose name is derived
+from that of the exception declaration.
+.NH 2
+The
+.CW raises
+clause
+.LP
+The definition of the function fib in the above example also lists the user defined exceptions it can raise via the use of a
+.CW raises
+clause. In this case there is just the one exception (\f5FIB\f1). These
+clauses (if given) must be compatible between any declaration and definition of the function.
+.LP
+The compiler reports instances of functions which either raise some exception which
+is not mentioned in their raises clause or does not raise some exception which is
+mentioned in their raises clause. Currently the report is a warning.
+.NH 1
+Exponentiation
+.LP
+The exponentiation operator (written as
+.CW ** )
+is now part of the Limbo language.
+Its precedence is above that of multiplication, division and modulus but below
+that of the unary operators. It is right associative. Thus
+.P1
+3**4*2 = (3**4)*2 = 81*2 = 162
+-3**4 = (-3)**4 = 81
+2**3**2 = 2**(3**2) = 2**9 = 512
+.P2
+The type of the left operand must be
+.CW int ,
+.CW big
+or
+.CW real .
+The type of the right operand must be
+.CW int .
+The type of the result is the type of the left operand.
+.NH 1
+Fixed point types
+.LP
+A declaration of the form
+.P1
+x: fixed(0.2, 12345.0);
+.P2
+declares
+.CW x
+to be a variable of a fixed point type. The scale of the type is
+1/5 and the maximum absolute value of the type is 12345.0.
+.LP
+Similarly
+.P1
+x: fixed(0.125, 4096.0)
+.P2
+specifies a scale of 0.125 and a maximum absolute value of 4096.
+This requires only 17 bits so the underlying type will be
+.CW int
+and the compiler
+is free to allocate the remaining 15 bits to greater range or greater
+accuracy. In fact the compiler always chooses the latter.
+.LP
+The maximum absolute value is optional :-
+.P1
+x: fixed(0.125);
+.P2
+is equivalent to
+.P1
+x: fixed(0.125, 2147483647.0 * 0.125);
+.P2
+and ensures the underlying type is exactly an int ie the compiler has
+no scope to add any extra bits for more accuracy.
+.LP
+A binary fixed point type with 8 bits before the binary point and 24 after
+might therefore be declared as
+.P1
+x: fixed(2.0**-24);
+.P2
+.LP
+The scale must be static: its value known at compile time and
+it must be positive and real; similarly for the maximum absolute
+value when specified.
+.LP
+Currently the only underlying base type supported is
+.CW int .
+.LP
+A shorthand for fixed point types is available through the use of
+.CW type
+declarations:
+.P1
+fpt: type fixed(2.0**-16);
+.P2
+We can then do
+.P1
+x, y, z: fpt;
+zero: con fpt(0);
+
+x = fpt(3.21);
+y = fpt(4.678);
+z = fpt(16r1234.5678);
+z = -x;
+z = x+y;
+z = x-y;
+z = x*y;
+z = x/y;
+sys->print("z=%f", real z);
+.P2
+There is no implicit numerical casting in Limbo so we have to use explicit
+casts to initialize fixed point variables. Note the use of a base to
+initialize
+.CW z
+using a new literal representation.
+.LP
+Given
+.P1
+fpt1: type fixed(0.12345);
+x: fpt1;
+fpt2: type fixed(0.1234);
+y: fpt2;
+fpt3: type fixed(0.123);
+z: fpt3;
+.P2
+then
+.P1
+z = x*y;
+.P2
+is illegal. We must add casts and do
+.P1
+z = fpt3(x)*fpt3(y);
+.P2
+ie type equivalence between fixed point types requires equivalence of scale
+(and of maximum absolute value when specified).
+.LP
+Fixed point types may be used where any other numerical type (byte, int, big, real) can be used. So you can compare them, have a list of them, have a channel of them, cast them to or from string and so on.
+.LP
+You cannot use complement(~), not(!), and(&), or(|), xor(^) or modulus(%) on them as fixed point types are basically a form of real type.
+.NH 2
+Accuracy
+.LP
+A fixed point value is a multiple of its scale. Given fixed point values X, Y and
+Z of scale s, t and u respectively, we can write
+.P1
+X = sx
+Y = ty
+Z = uz
+.P2
+where x, y and z are integers.
+.LP
+For the multiplication Z = X*Y the accuracy achieved is given by
+.P1
+| z - (st/u)xy | < 1
+.P2
+and for the division Z = X/Y
+.P1
+| z - (s/(tu))x/y | < 1
+.P2
+That is, the result is always within the result scale of the correct real value.
+.LP
+This also applies when casting a fixed point type to another, casting an
+integer to a fixed point type and casting a fixed point type to an integer. These
+are all examples of the multiplication law with t = y = 1 since an
+integer may be thought of as a fixed point type with a scale of 1.
binary files /dev/null b/doc/limbo/addendum.pdf differ
--- /dev/null
+++ b/doc/limbo/limbo.ms
@@ -1,0 +1,5046 @@
+...FP lucidasans
+...FP palatino
+.FP palatino
+." .fp 6 RR R
+.nr PI 2n
+.de P1
+.DS L
+.ft CW
+.ps -1
+.vs -1u
+.ta .75i 1.5i 2.25i 3i 3.75i 4.5i 5.25i 6i 6.75i 7.5i
+..
+.de P2
+.ft R
+.ps +1
+.vs +1u
+.DE
+..
+.de s1
+.DS
+.br
+.ft I
+..
+.de s2
+.br
+.DE
+.ft R
+..
+...ds CF "Copyright 2000 Lucent Technologies Inc. Modifications Vita Nuova Limited.
+.TL
+The Limbo Programming Language
+.AU
+Dennis M. Ritchie
+.br
+(Revised 2005 by Vita Nuova)
+.SP .5i exactly
+.PP
+Limbo is a programming language intended for applications
+running distributed systems on small computers.
+It supports modular programming,
+strong type checking at compile- and run-time,
+interprocess communication over typed channels,
+automatic garbage collection,
+and simple abstract data types.
+It is designed for safe execution even on
+small machines without hardware memory protection.
+.PP
+In its implementation for the Inferno operating system,
+object programs generated by the Limbo compiler run
+using an interpreter for a fixed virtual machine.
+Inferno and its accompanying virtual machine run either stand-alone
+on bare hardware
+or as an application under conventional operating systems like
+Unix, Windows 2000, Linux, FreeBSD, MacOSX, and Plan 9.
+For most architectures, including
+Intel x86, ARM, PowerPC, MIPS and Sparc, Limbo object programs
+are transformed on-the-fly into instructions for the underlying hardware.
+.NH 1
+Overview and introduction
+.PP
+A Limbo application consists of one or more
+.I modules ,
+each of which supplies an interface declaration and
+an implementation part.
+A module that uses another module
+includes its declaration part.
+During
+execution, a module dynamically attaches another module by
+stating the other module's type identifier and a place from which to load
+the object code for its implementation.
+.PP
+A module declaration specifies the functions and data it will make visible,
+its data types, and constants.
+Its implementation part defines the functions and data visible at its interface and
+any functions associated with its data types;
+it may also contain definitions for functions used only internally and
+for data local to the module.
+.PP
+Here is a simple module to illustrate the flavour of the language.
+.P1
+1 implement Command;
+
+2 include "sys.m";
+3 include "draw.m";
+
+4 sys: Sys;
+
+5 Command: module
+ {
+6 init: fn (ctxt: ref Draw->Context, argv: list of string);
+7 };
+.P2
+.P1
+8 # The canonical "Hello world" program, enhanced
+9 init(ctxt: ref Draw->Context, argv: list of string)
+10 {
+11 sys = load Sys Sys->PATH;
+12 sys->print("hello world\en");
+13 for (; argv!=nil; argv = tl argv)
+14 sys->print("%s ", hd argv);
+15 sys->print("\en");
+16 }
+.P2
+A quick glance at the program reveals that
+the syntax of Limbo is influenced by C in its expressions,
+statements, and some conventions (for example, look at lines 13-14),
+and also by Pascal and its successors (the declarations on lines 4, 6, 9).
+When executed in the Inferno environment, the program writes
+.CW hello
+.CW world
+somewhere, then echoes its arguments.
+.PP
+Let's look at the program line-by-line.
+It begins (line 1) by saying that this is the implementation of module
+.CW Command .
+Line 2 includes a file (found in a way analogous to C's
+.CW #include
+mechanism) named
+.CW sys.m .
+This file defines the interface to module
+.CW Sys ;
+.ds CF
+it says, in part,
+.P1
+Sys: module {
+ PATH: con "$Sys";
+ . . .
+ print: fn (s: string, *): int;
+ . . .
+};
+.P2
+This declares
+.CW Sys
+to be the type name for a module containing among other things a
+function named
+.CW print ;
+the first argument of
+.CW print
+is a string.
+The
+.CW *
+in the argument list specifies that further arguments, of
+unspecified type, may be given.
+.PP
+Line 3 includes
+.CW draw.m ;
+only one piece of information, mentioned below,
+is used from it.
+Line 4 declares the variable
+.CW sys
+to be of type
+.CW Sys ;
+its name will be visible throughout the remainder of the file
+describing this module.
+It will be used later to refer to an instance of the
+.CW Sys
+module.
+This declaration initializes it to
+.CW nil ;
+it still needs to be set to a useful value.
+.PP
+Lines 5-7 constitute the declaration of
+.CW Command ,
+the module being implemented.
+It contains only a function named
+.CW init ,
+with two arguments, a
+.CW ref
+.CW Draw->Context
+and a list of strings,
+and it doesn't
+return any value.
+The
+.CW ref
+.CW Draw->Context
+argument would be used if the program did any
+graphics; it is a data type defined in
+.CW draw.m
+and refers to the display.
+Since the program just writes text, it won't be used.
+The
+.CW init
+function isn't special to the Limbo language,
+but it is conventional in the environment,
+like
+.CW main
+in C.
+.PP
+In a module designed to be useful
+to other modules in an application, it would be wise to
+take the module declaration for
+.CW Command
+out, put it in a separate file called
+.CW command.m
+and use
+.CW "include
+.CW command.m
+to allow this module and others to refer to it.
+It is called, for example, by the program loader in the Inferno
+system to start the execution of applications.
+.PP
+Line 8 is a comment; everything from the
+.CW #
+to the end of line is ignored.
+.PP
+Line 9 begins the definition for the
+.CW init
+function that was promised in the module's declaration
+(line 6).
+The argument that is a list of strings is named
+.CW argv .
+.PP
+Line 11 connects the program
+being written to the
+.CW Sys
+module.
+The first token after
+.CW load
+is the target module's name as defined by its interface
+(here found in the
+.CW include
+on line 2)
+The next token is the place
+where the code for the module can be found; it is a string
+that usually names a file.
+Conventionally, in the Inferno system,
+each module contains a constant declaration for the name
+.CW PATH
+as a string that names the file where
+the object module can be found.
+Loading the file is performed dynamically during
+execution except for a few modules built
+into the execution environment.
+(These include
+.CW Sys ;
+this accounts for the peculiar file name
+.CW "$Sys"
+as
+the value of
+.CW PATH .)
+.PP
+The value of
+.CW load
+is a reference to the
+named module; line 11 assigns it
+to the variable
+.CW sys
+for later use.
+The
+.CW load
+operator dynamically loads the code for the named
+module if it is not already present and instantiates
+a new instance of it.
+.PP
+Line 12 starts the work by printing a familiar message,
+using the facilities provided by module
+.CW Sys
+through its handle
+.CW sys ;
+the notation
+.CW sys->print(...)
+means to call the
+.CW print
+function of the module referred to by
+.CW sys .
+The interface of
+.CW Sys
+resembles a binding to some of
+the mechanisms of Unix and the ISO/ANSI C library.
+.PP
+The loop at lines 13-14 takes the
+.CW "list
+.CW of
+.CW string
+argument to
+.CW init
+and iterates over it using the
+.CW hd
+(head) and
+.CW tl
+(tail) operators.
+When executed, this module combines the
+traditional `Hello world' and
+.CW echo .
+.NH 1
+Lexical conventions
+.PP
+There are several kinds of tokens:
+keywords, identifiers, constants, strings, expression operators,
+and other separators.
+White space (blanks, tabs, new-lines) is ignored except that
+it serves to separate tokens; sometimes it is required
+to separate tokens.
+If the input has been parsed into tokens up to a particular
+character, the next token is taken to include the longest
+string of characters that could constitute a token.
+.PP
+The native character set of Limbo is Unicode,
+which is identical with the first 16-bit plane of the ISO 10646 standard.
+Any Unicode character may be used in comments, or in strings
+and character constants.
+The implementation assumes that source files use the UTF-8 representation,
+in which 16-bit Unicode characters are represented as sequences
+of one, two, or three bytes.
+.NH 2
+Comments
+.PP
+Comments begin with the
+.CW #
+character and extend to the end of the line.
+Comments are ignored.
+.NH 2
+Identifiers
+.PP
+An identifier is a sequence of letters and digits
+of which the first is a letter.
+Letters are the Unicode characters
+.CW a
+through
+.CW z
+and
+.CW A
+through
+.CW Z ,
+together with the underscore character, and
+all Unicode characters with encoded values greater than 160
+(A0 hexadecimal, the beginning of the range corresponding to Latin-1).
+.PP
+Only the first 256 characters in an identifier
+are significant.
+.NH 2
+Keywords
+.PP
+The following identifiers are reserved for use as keywords,
+and may not be used otherwise:
+.P1
+.ta 1i 2i 3i 4i 5i
+ adt alt array big
+ break byte case chan
+ con continue cyclic do
+ else exit fn for
+ hd if implement import
+ include int len list
+ load module nil of
+ or pick real ref
+ return self spawn string
+ tagof tl to type
+ while
+.P2
+The word
+.CW union
+is not currently used by the language.
+.NH 2
+Constants
+.PP
+There are several kinds of constants for denoting values of the
+basic types.
+.PP
+.NH 3
+Integer constants
+.PP
+Integer constants have type
+.CW int
+or
+.CW big .
+They can be represented in several ways.
+.PP
+Decimal integer constants consist of a sequence of decimal
+digits.
+A constant with an explicit radix
+consists of a decimal radix followed by
+.CW R
+or
+.CW r
+followed by the digits of the number.
+The radix is between 2 and 36 inclusive;
+digits above 10 in the number
+are expressed using letters
+.CW A
+to
+.CW Z
+or
+.CW a
+to
+.CW z .
+For example,
+.CW 16r20
+has value 32.
+.PP
+The type of a decimal or explicit-radix number is
+.CW big
+if its value exceeds
+.CW 2\u31\d\(mi1 ,
+otherwise it is
+.CW int .
+.PP
+Character constants consist of a single Unicode
+character enclosed within single-quote characters
+.CW ' .
+Inside the quotes the following escape sequences represent
+special characters:
+.DS
+\f(CW\e\e\fR backslash
+\f(CW\e'\fR single quote
+\f(CW\e"\fR double quote
+\f(CW\ea\fR bell (BEL)
+\f(CW\eb\fR backspace (BS)
+\f(CW\et\fR horizontal tabulation (HT)
+\f(CW\en\fR line feed (LF)
+\f(CW\ev\fR vertical tabulation (VT)
+\f(CW\ef\fR form feed (FF)
+\f(CW\er\fR carriage return (CR)
+\f(CW\eu\fIdddd \fRUnicode character named by 4 hexadecimal digits
+\f(CW\e0\fR NUL
+.DE
+Character constants have type
+.CW int .
+.NH 3
+Real constants
+.PP
+Real constants consist of a sequence of decimal digits
+containing one period
+.CW .
+and optionally followed by
+.CW e
+or
+.CW E
+and then by a possibly signed integer.
+If there is an explicit exponent, the period is
+not required.
+Real constants have type
+.CW real .
+.NH 3
+Strings
+.PP
+String constants are sequences of Unicode characters contained in double
+quotes.
+They cannot extend across source lines.
+The same escape sequences listed above for character
+constants are usable within string constants.
+.PP
+Raw (uninterpreted) string constants are sequences of Unicode characters
+contained in backquotes.
+They can extend across source lines and thus include newlines.
+They contain no character escapes.
+The only character that cannot appear inside an uninterpreted string is a backquote, because that delimits the string.
+.PP
+Both forms of string constant have type
+.CW string .
+.NH 3
+The nil constant
+.PP
+The constant
+.CW nil
+denotes a reference to nothing.
+It may be used where an object of a reference
+type is expected;
+otherwise uninitialized values of reference type
+start off with this value, it can be assigned to
+reference objects, and reference types can be
+tested for equality with it.
+(The keyword has other uses as well.)
+.NH 2
+Operators and other separators
+.PP
+The operators are
+.P1
+.ta .5i 1i 1.5i 2i 2.5i 3i 3.5i 4i 4.5i 5i 5.5i 6.0i 6.5i
+ + - * / % & | ^
+ == < > <= >= != << >>
+ && || <- ::
+ = += -= *= /= %= &= |= ^= <<= >>=
+ :=
+ ~ ++ -- ! **
+.P2
+The other separators are
+.P1
+.ta .5i 1i 1.5i 2i 2.5i 3i 3.5i 4i 4.5i 5i 5.5i
+ : ; ( ) { } [ ]
+ , . -> =>
+.P2
+.NH 1
+Syntax notation
+.PP
+In this manual, Limbo syntax is described by a modified BNF
+in which syntactic categories are named in an
+.I italic
+font, and literals in
+.CW typewriter
+font.
+Alternative productions are listed on separate lines, and
+an optional symbol is indicated with
+the subscript ``opt.''
+.NH 1
+Types and objects
+.PP
+Limbo has three kinds of objects.
+.I Data
+objects exist in the storage associated with
+a module; they can be manipulated by arithmetic operations,
+assignment, selection of component entities, and other concrete
+operations.
+Each data object has a type that determines what can be stored
+in it and what operations are applicable.
+.PP
+The second kind of object is the
+.I function .
+Functions are characterized by the types of the arguments they
+accept and the values they return, and are associated with
+the modules in which they are defined.
+Their names can be made visible in their module's declaration,
+or they can be encapsulated within the
+.CW adt
+(abstract data types) of their modules,
+or they can exist privately within their module.
+.PP
+Finally, Limbo programs are organized into
+.I modules :
+a named collection of constants, abstract data types,
+data, and functions made available by that module.
+A module declaration displays the
+members visible to other modules;
+the module's implementation
+defines both the publicly visible members and its
+private parts, including the data objects it uses.
+A module that wishes to use
+the facilities of another includes its declaration in order to
+understand what it exports, but
+before using them it explicitly loads the new module.
+.NH 2
+Types
+.PP
+Limbo has several basic types, some built-in higher abstractions,
+and other ways of composing new types.
+In declarations and some other places, constructions naming
+a type are used.
+The syntax is:
+.s1
+type:
+ data-type
+ function-type
+.s2
+Functions will be discussed in §7 below.
+First, data types will be explored.
+.NH 2
+Data types
+.PP
+The syntax of data types is
+.s1
+data-type:
+ CbyteI
+ CintI
+ CbigI
+ CrealI
+ CstringI
+ tuple-type
+ Carray of Idata-type
+ Clist of Idata-type
+ Cchan of Idata-type
+ adt-type
+ Cref Iadt-type
+ Cref Ifunction-type
+ module-type
+ module-qualified-type
+ type-name
+
+data-type-list:
+ data-type
+ data-type-list C,I data-type
+.s2
+Objects of most data types have
+.I value
+semantics; when they
+are assigned or passed to functions, the destination receives a copy of the
+object.
+Subsequent changes to the assigned object itself have no effect on
+the original object.
+The value types are
+.CW byte ,
+.CW int ,
+.CW big ,
+.CW real ,
+.CW string ,
+the
+.CW tuple
+types, and
+abstract data types or
+.CW adt .
+The rest have
+.I reference
+semantics.
+When they are assigned, the quantity actually assigned
+is a reference to (a pointer to) an underlying object
+that is not copied; thus changes or operations on
+the assigned value affect the original object.
+Reference types include lists, arrays, channels, modules,
+.CW ref
+.CW adt ,
+and
+.CW ref
+.CW fn
+types.
+.NH 3
+Basic types
+.PP
+The five basic data types are denoted by
+.CW byte ,
+.CW int ,
+.CW big ,
+.CW real ,
+and
+.CW string .
+.PP
+Bytes are unsigned 8-bit quantities.
+.PP
+Integers
+.CW int ) (
+are 32-bit signed quantities represented in two's complement
+notation.
+Large integers
+.CW big ) (
+are 64-bit signed quantities represented in two's complement notation.
+.PP
+Real numbers
+.CW real ) (
+are 64-bit quantities represented in the
+IEEE long floating notation.
+.PP
+The
+.CW byte ,
+.CW int ,
+.CW big ,
+and
+.CW real
+types are collectively called arithmetic types.
+.PP
+Strings are rows of Unicode characters.
+They may be concatenated and extended character-by-character.
+When a string is indexed with a single subscript, it yields an integer
+with the Unicode encoding of the character;
+when it is indexed by a range, it yields another string.
+.NH 3
+Tuple type
+.PP
+The
+.I tuple
+type, denoted
+.s1
+tuple-type:
+ C( Idata-type-listC )I
+.s2
+is a type consisting of an ordered collection of two or more objects,
+each having its own data type.
+For each tuple type, the types of the members are
+fixed, but need not be identical;
+for example, a function might return a tuple containing
+an integer and a string.
+Each tuple type is characterized solely by the
+the order and identity of the types it contains.
+Objects of tuple type may be assigned to a list of identifiers (to pick out the
+components), and a parenthesized, comma-separated list of expressions
+denotes a tuple.
+.NH 3
+Array types
+.PP
+The
+.I array
+type describes a dynamically-sized row of objects, all of the same
+type; it is indexed starting from 0.
+An array type is denoted by
+.s1
+ Carray of Idata-type
+.s2
+The size of an array is not part of its type; instead
+it is part of the value.
+The
+.I data-type
+may itself be an array, to achieve a multidimensional array.
+.NH 3
+List types
+.PP
+A
+.I list
+is a sequence of like-typed objects; its denotation is
+.s1
+ Clist of Idata-type
+.s2
+A list is a stack-like object, optimized for
+a few operations: get the head (the first object),
+get the tail (the rest of the list), place an object at the beginning.
+.NH 3
+Channel types
+.PP
+A
+.I channel ,
+whose type is written
+.s1
+ Cchan of Idata-type
+.s2
+is a communication mechanism capable of sending and receiving objects of the
+specified type to another agent in the system.
+Channels may be used to communicate between local processes;
+using library procedures, they may be connected
+to named destinations.
+In either case
+.I send
+and
+.I receive
+operations may be directed to them.
+For example,
+.P1
+ chan of (int, string)
+.P2
+is the type of a channel that transmits tuples consisting of
+an integer and an string.
+Once an instance of such a channel (say
+.CW c )
+has been declared and initialized,
+the statement
+.P1
+ c <-= (123, "Hello");
+.P2
+sends such a tuple across it.
+.NH 3
+Abstract data types
+.PP
+An abstract data type or
+.I adt
+is an object that can contain data objects of several
+different types and declare
+functions that operate on them.
+The syntax for declaring an
+.CW adt
+is given later.
+Once an
+.CW adt
+has been declared, the identifier associated with it
+becomes a data-type name.
+.s1
+adt-type:
+ identifier
+ module-qualified-type
+.s2
+.PP
+There is also a
+.CW ref
+.CW adt
+type representing a reference (pointer) to an
+.CW adt .
+It is denoted
+.s1
+ Cref Iadt-type
+.s2
+where the identifier is the name of an
+.CW adt
+type.
+.NH 3
+Module types
+.PP
+A module type name is an identifier:
+.s1
+module-type:
+ identifier
+.s2
+The identifier is declared as a module identifier by a
+.I module-declaration ,
+as described in §6.5 below.
+An object of module type serves as a handle for the
+module, and is used to access its functions.
+.NH 3
+Module-qualified type
+.PP
+When an
+.CW adt
+is declared within a module declaration, the type name of that
+.CW adt
+is not generally visible to the rest of the program unless a specific
+.CW import
+request is given (see §6.6, §10 below).
+Without such a request, when
+.CW adt
+objects implemented by a module are declared by a client
+of that module, the
+.CW adt
+type name is qualified:
+.s1
+module-qualified-type:
+ identifier C->I identifier
+.s2
+Here the first identifier is either the name of a module
+or a variable of the module type;
+the second is the name of a type
+mentioned in the module declaration.
+.NH 3
+Function reference types
+.PP
+A function reference type represents a reference to a function of a given type.
+It is written as
+.s1
+ Cref Ifunction-type
+.s2
+Function types are discussed in §4.3 below.
+.NH 3
+Named types
+.PP
+Finally, data types may be named, using a
+.CW type
+declaration; this is discussed in §6.4 below.
+.s1
+type-name:
+ identifier
+.s2
+.NH 2
+Function types
+.PP
+A function type characterizes the arguments and return value of
+a function. The syntax is
+.s1
+function-type:
+ Cfn Ifunction-arg-ret
+
+function-arg-ret:
+ C( Iformal-arg-listOC ) IraisesO
+ C( Iformal-arg-listOC ) : Idata-type raisesO
+
+formal-arg-list:
+ formal-arg
+ formal-arg-listC , Iformal-arg
+
+formal-arg:
+ nil-or-ID-listC : Itype
+ nil-or-IDC : self refO Iidentifier
+ nil-or-IDC : self Iidentifier
+ C*I
+
+nil-or-ID-list:
+ nil-or-ID
+ nil-or-ID-list C, Inil-or-ID
+
+nil-or-ID:
+ identifier
+ CnilI
+
+raises:
+ Craises ( Inil-or-ID-listC )I
+ CraisesI nil-or-ID
+
+.s2
+That is, the denotation of a function type has the keyword
+.CW fn
+followed by a comma-separated list of its arguments
+enclosed in parentheses,
+and perhaps followed by the type the function returns.
+Absence of a return value means that the function returns no
+value: it is a procedure.
+The names and types of arguments are specified.
+However, the name of an argument may be replaced by
+.CW nil ;
+in this case it is nameless.
+For example,
+.P1
+ fn (nil: int, nil: int): int
+ fn (radius: int, angle: int): int
+ fn (radius, angle: int): int
+.P2
+all denote exactly the same type,
+namely a function of two integers that returns an integer.
+As another example,
+.P1
+ fn (nil: string)
+.P2
+is the type of a function that takes a string argument
+and returns no value.
+.PP
+The
+.CW self
+keyword has a specialized use within
+.CW adt
+declarations.
+It may be used only for the first argument
+of a function declared within an
+.CW adt ;
+its meaning is discussed in §6.3 below.
+.PP
+The star character
+.CW *
+may be given as the last argument in a function type.
+It declares that
+the function is variadic; during a call, actual arguments at its
+position and following are passed in a manner
+unspecified by the language.
+For example, the type of the
+.CW print
+function of the
+.CW Sys
+module is
+.P1
+ fn (s: string, *): int
+.P2
+This means that the first argument of
+.CW print
+is a string and that other arguments may be given when the function
+is called.
+The Limbo language itself has no way of accessing these arguments;
+the notation is an artifice for describing facilities
+built into the runtime system, such as the
+.CW Sys
+module.
+.PP
+The type of a function includes user-defined exceptions that it raises,
+which must be listed in a corresponding
+.CW raises
+clause.
+.NH 1
+Limbo programs
+.PP
+Limbo source programs that implement modules are stored in files,
+conventionally named with the suffix
+.CW .b .
+Each such file begins with a single
+.CW implement
+directive naming the type of the module being implemented,
+followed by a sequence of declarations.
+Other files, conventionally named with the suffix
+.CW .m ,
+contain declarations for things obtainable from other modules.
+These files are incorporated by an
+.CW include
+declaration in the implementation modules that need them.
+At the top level, a program consists of a sequence
+of declarations.
+The syntax is
+.s1
+program:
+ Cimplement Iidentifier-listC ; Itop-declaration-sequence
+
+top-declaration-sequence:
+ top-declaration
+ top-declaration-sequence top-declaration
+
+top-declaration:
+ declaration
+ identifier-listC := IexpressionC ;I
+ identifier-listC = IexpressionC ;I
+ C( Iidentifier-listC ) := IexpressionC ;I
+ module-declaration
+ function-definition
+ adt-declaration
+.s2
+The
+.CW implement
+declaration at the start identifies the type of the module that
+is being implemented.
+The rest of the program consists of a sequence of various kinds of
+declarations and definitions that announce the names
+of data objects, types, and functions, and also create
+and initialize them.
+It must include a module declaration for the module
+being implemented and the objects it announces,
+and may also include declarations for the functions, data
+objects, types, and constants used privately within the module
+as well as declarations for modules used by it.
+.PP
+Declarations are used both at the top
+level (outside of functions) and also inside functions
+and module declarations.
+Some styles of declaration
+are allowed only in certain of these places,
+but all will be discussed together.
+.PP
+Most implementation modules provide an implementation for one type of module.
+Several module types may be listed, however, in the
+.CW implement
+declaration, when the implementation module implements them all.
+When the same name appears in more than one such module type, it must
+have the same type.
+.NH 1
+Declarations
+.PP
+Declarations take several forms:
+.s1
+declaration:
+ identifier-listC : ItypeC ;I
+ identifier-listC : ItypeC = IexpressionC ;I
+ identifier-listC : con IexpressionC ;I
+ Iidentifier-listC : import Iidentifier C;I
+ identifier-listC : typeI typeC ;I
+ identifier-listC : exceptionI tuple-typeO
+ Cinclude Istring-constantC ;I
+
+identifier-list:
+ identifier
+ identifier-listC , Iidentifier
+
+expression-list:
+ expression
+ expression-listC , Iexpression
+.s2
+.NH 2
+Data declarations
+.PP
+These forms constitute the basic way to declare and
+initialize data:
+.s1
+ identifier-listC : ItypeC ;I
+ identifier-listC : ItypeC = IexpressionC ;I
+.s2
+A comma-separated sequence of identifiers is followed by a colon
+and then the name of a type.
+Each identifier is declared as having that type and denotes a
+particular object
+for rest of its scope (see §11 below).
+If the declaration contains
+.CW =
+and an expression, the type must be a data type, and
+all the objects are initialized from
+the value of the expression.
+In a declaration at the top level
+(outside of a function), the expression must be
+constant (see §8.5) or an array initialized with constant expressions;
+the bound of any array must be a constant expression.
+Lists and
+.CW ref
+.CW adt
+types may not be initialized at the top level.
+If an object is not explicitly initialized, then
+it is always set to
+.CW nil
+if it has a reference type;
+if it has arithmetic type, then it is set to 0
+at the top level and is undefined if it occurs
+within a function.
+.PP
+For example,
+.P1
+ i, j: int = 1;
+ r, s: real = 1.0;
+.P2
+declares
+.CW i
+and
+.CW j
+as integers,
+.CW r
+and
+.CW s
+as real.
+It sets
+.CW i
+and
+.CW j
+to 1,
+and
+.CW r
+and
+.CW s
+to 1.0.
+.PP
+Another kind of declaration is a shorthand.
+In either of
+.s1
+ identifierC := IexpressionC ;I
+ C( Iidentifier-listC ) := IexpressionC ;I
+
+.s2
+identifiers on the left are declared using the type of the expression,
+and are initialized with the value of the expression.
+In the second case, the expression must be a tuple or an
+.CW adt ,
+and the types and values attributed to the identifiers
+in the list are taken from the members of the tuple, or the
+data members of the
+.CW adt
+respectively.
+For example,
+.P1
+ x: int = 1;
+.P2
+and
+.P1
+ x := 1;
+.P2
+are the same.
+Similarly,
+.P1
+ (p, q) := (1, 2.1);
+.P2
+declares the identifiers on the left as
+.CW int
+and
+.CW real
+and initializes them to 1 and 2.1 respectively.
+Declarations with
+.CW :=
+can also be expressions, and are discussed again in §8.4.4 below.
+.NH 2
+Constant declarations
+.PP
+The
+.CW con
+declaration
+.s1
+ Iidentifier-listC : conI expressionC ;I
+.s2
+declares a name (or names) for constants.
+The
+.I expression
+must be constant (see §8.5).
+After the declaration,
+each identifier in the list may be used anywhere a constant
+of the appropriate type is needed;
+the type is taken from the type of the constant.
+For example, after
+.P1
+ Seven: con 3+4;
+.P2
+the name
+.CW Seven
+is exactly the same as the constant 7.
+.PP
+The identifier
+.CW iota
+has a special meaning in the expression in a
+.CW con
+declaration.
+It is equivalent to the integer constant
+.CW 0
+when evaluating the expression for the first (leftmost) identifier declared,
+.CW 1
+for the second, and so on numerically.
+For example, the declaration
+.P1
+ M0, M1, M2, M3, M4: con (1<<iota);
+.P2
+declares several constants
+.CW M0
+through
+.CW M4
+with the values 1, 2, 4, 8, 16 respectively.
+.PP
+The identifier
+.CW iota
+is not reserved except inside the expression
+of the
+.CW con
+declaration.
+.NH 2
+adt declarations
+.PP
+An
+.CW adt
+or abstract data type contains data objects and functions that
+operate on them.
+The syntax is
+.s1
+adt-declaration:
+ IidentifierC : adt { Iadt-member-listOC } ;I
+
+adt-member-list:
+ adt-member
+ adt-member-list adt-member
+
+adt-member:
+ identifier-listC : cyclicO Idata-typeC ;I
+ identifier-listC : con IexpressionC ;I
+ identifier-listC : Ifunction-typeC ;I
+ Cpick { Ipick-member-listC }I
+.s2
+After an
+.I adt-declaration ,
+the identifier becomes the name of the type of that
+.CW adt .
+For example, after
+.P1
+ Point: adt {
+ x, y: int;
+ add: fn (p: Point, q: Point): Point;
+ eq: fn (p: Point, q: Point): int;
+ };
+.P2
+the name
+.CW Point
+is a type name for an
+.CW adt
+of two integers and two
+functions; the fragment
+.P1
+ r, s: Point;
+ xcoord: int;
+ ...
+ xcoord = s.x;
+ r = r.add(r, s);
+.P2
+makes sense.
+The first assignment selects one of the data members of
+.CW s ;
+the second calls one of the function members of
+.CW r .
+.PP
+As this example indicates,
+.CW adt
+members are accessed by mentioning an object with the
+.CW adt
+type, a dot, and then the name of the member;
+the details will be discussed in §8.13 below.
+A special syntactic indulgence is available for functions declared within an
+.CW adt :
+frequently such a function
+receives as an argument the same object used to access it
+(that is, the object before the dot).
+In the example just above,
+.CW r
+was both the object being operated on and the first argument to the
+.CW add
+function.
+If the first formal argument of a function declared in an
+.CW adt
+is marked with the
+.CW self
+keyword, then in any calls to the function, the
+.CW adt
+object is implicitly passed to the function, and
+is not mentioned explicitly in the actual argument list
+at the call site.
+For example, in
+.P1
+ Rect: adt {
+ min, max: Point;
+ contains: fn(r: self Rect, p: Point): int;
+ };
+
+ r1: Rect;
+ p1: Point;
+ ...
+ if (r1.contains(p1)) ...
+.P2
+because the first argument of the
+.CW contains
+function is declared with
+.CW self ,
+the subsequent call to it automatically passes
+.CW r1
+as its first argument. The
+.CW contains
+function itself is defined elsewhere with this first
+argument explicit.
+(This mechanism is analogous to the
+.I this
+construct in C++ and other languages,
+but puts the special-casing at the declaration site and makes it explicit.)
+.PP
+If
+.CW self
+is specified in the declaration of a function, it must also be
+specified in the definition as well. For example,
+.CW contains
+would be defined
+.P1
+ Rect.contains(r: self Rect, p: Point)
+ {
+ . . .
+ }
+.P2
+.PP
+The
+.CW adt
+type in Limbo
+does not provide control over the visibility
+of its individual members; if any are accessible, all are.
+.PP
+Constant
+.CW adt
+members follow the same rules as ordinary constants (§6.2).
+.PP
+The obsolete
+.CW cyclic
+modifier will be discussed in §11.1.
+.NH 3
+pick adts
+.PP
+An
+.CW adt
+which contains a
+.CW pick
+member is known as a
+.I pick
+.I adt .
+A
+.CW pick
+.CW adt
+is Limbo's version of a
+.I "discriminated union" .
+An
+.CW adt
+can only contain one
+.CW pick
+member and it must be the last component of the
+.CW adt .
+Each
+.I identifier
+enumerated in the
+.I pick-tag-list
+names a variant type of the
+.CW pick
+.CW adt .
+The syntax is
+.s1
+pick-member-list:
+ pick-tag-listC =>I
+ pick-member-list pick-tag-listC =>I
+ pick-member-list identifier-listC : cyclicO Idata-typeC ;I
+.s2
+.s1
+pick-tag-list:
+ identifier
+ pick-tag-listC or Iidentifier
+.s2
+.PP
+The
+.I pick-member-list
+contains a set of data members for each
+.I pick-tag-list .
+These data members are specific to those variants of the
+.CW pick
+.CW adt
+enumerated in the
+.I pick-tag-list .
+The
+.CW adt
+data members found outside of the
+.CW pick
+are common to all variants of the
+.CW adt .
+A
+.CW pick
+.CW adt
+can only be used as a
+.CW ref
+.CW adt
+and can only be initialized from a value of one of its variants.
+For example, if
+.CW Constant
+is a
+.CW pick
+.CW adt
+and
+.CW Constant.Real
+is one of its variant types then
+.P1
+ c : ref Constant = ref Constant.Real("pi", 3.1);
+.P2
+will declare
+.CW c
+to have type
+.CW ref
+.CW Constant
+and initialize it with a value of the variant type
+.CW ref
+.CW Constant.Real .
+.NH 2
+Type declarations
+.PP
+The type declaration
+.s1
+ Iidentifier-listC : typeI data-type ;I
+.s2
+introduces the identifiers as synonyms for the
+given type.
+Type declarations are transparent; that is,
+an object declared with the newly-named
+type has the same type as the one it abbreviates.
+.NH 2
+Module declarations
+.PP
+A module declaration collects and packages declarations of
+.CW adt ,
+functions, constants and simple types, and creates an
+interface with a name
+that serves to identify the type of the module.
+The syntax is
+.s1
+module-declaration:
+ IidentifierC : module { Imod-member-listOC } ;I
+
+mod-member-list:
+ mod-member
+ mod-member-list mod-member
+
+mod-member:
+ identifier-listC : Ifunction-typeC ;I
+ identifier-listC : Idata-typeC ;I
+ adt-declarationC ;I
+ identifier-listC : con Iexpression C;I
+ identifier-listC : type Itype C;I
+.s2
+After a module declaration, the named
+.I identifier
+becomes the name of the type of that module.
+For example, the declaration
+.P1
+Linear: module {
+ setflags: fn (flag: int);
+ TRUNCATE: con 1;
+ Vector: adt {
+ v: array of real;
+ add: fn (v1: self Vector, v2: Vector): Vector;
+ cross: fn (v1: self Vector, v2: Vector): Vector;
+ dot: fn (v1: self Vector, v2: Vector);
+ make: fn (a: array of real): Vector;
+ };
+ Matrix: adt {
+ m: array of array of real;
+ add: fn (m1: self Matrix, m2: Matrix): Matrix;
+ mul: fn (m1: self Matrix, m2: Matrix): Matrix;
+ make: fn (a: array of array of real): Matrix;
+ };
+};
+.P2
+is a module declaration for a linear algebra package that
+implements two
+.CW adt ,
+namely
+.CW Vector
+and
+.CW Matrix ,
+a constant,
+and a function
+.CW setflags .
+The name
+.CW Linear
+is the type name for the module, and it may be used to declare
+an object referring to an instance of the module:
+.P1
+ linearmodule: Linear;
+.P2
+Before the module can be used, it must be loaded, for example in
+the style:
+.P1
+ linearmodule = load Linear "/usr/dmr/limbo/linear.dis";
+ if (linearmodule == nil) {
+ sys->print("Can't load Linear\en");
+ exit;
+ }
+.P2
+The
+.CW load
+operator is discussed more fully in §8.4.5 below.
+.PP
+To initialize data declared as part of a module
+declaration, an assignment expression may be used at the top level.
+For example:
+.P1
+ implement testmod;
+ testmod: module {
+ num: int;
+ };
+ . . .
+ num = 5;
+.P2
+The right side of the assignment must be a constant expression (§8.5).
+.NH 2
+Declarations with
+.CW import
+.PP
+These declarations take the form
+.s1
+ Iidentifier-listC : import Iidentifier C;I
+.s2
+Identifiers for entities
+declared within a module declaration are normally
+meaningful only in a context that
+identifies the module.
+The
+.CW import
+declaration lifts the names of specified members of a module
+directly into the current scope.
+The use of
+.CW import
+will be discussed more fully in §8.1.4 below, after the syntax
+for expressions involving modules has been presented.
+.NH 2
+Exception declarations
+.PP
+Exceptions represent run-time errors not data objects or values.
+Exception declarations have the form:
+.s1
+ identifier-listC : exceptionI tuple-typeO
+.s2
+Each identifier gives a compile-time name to a distinct user-defined run-time error,
+signaled at run-time by a
+.CW raise
+statement that quotes that identifier, as described below.
+An exception optionally includes a tuple of data values that qualifies the exception;
+the types of those values are provided by the tuple type in this declaration.
+.NH 2
+Declarations with
+.CW include
+.PP
+The string following the
+.CW include
+keyword names
+a file, which is inserted into the program's
+text at that point.
+The included
+text is treated like text literally present.
+Conventionally, included files declare
+module interfaces and are named with the suffix
+.CW .m .
+The directories to be searched for included files
+may be specified to the Limbo compiler command.
+Include files may be nested.
+.NH 1
+Function definitions
+.PP
+All executable code
+is supplied as part of a function definition.
+The syntax is
+.s1
+function-definition:
+ function-name-part function-arg-retC { IstatementsC }I
+
+function-name-part:
+ identifier
+ function-name-partC . Iidentifier
+.s2
+The syntax of the statements in a function will be discussed in §9 below.
+As a brief example,
+.P1
+ add_one(a: int): int
+ {
+ return a+1;
+ }
+.P2
+is a simple function
+that might be part of the top level of a module.
+.PP
+Functions that are declared within an
+.CW adt
+use the qualified form of definition:
+.P1
+ Point: adt {
+ x, y: int;
+ add: fn (p: Point, q: Point): Point;
+ eq: fn (p: Point, q: Point): int;
+ }
+ . . .
+ Point.add(p: Point, q: Point): Point
+ {
+ return Point(p.x+q.x, p.y+q.y);
+ }
+.P2
+Because an
+.CW adt
+may contain an
+.CW adt ,
+more than one qualification is possible.
+.NH 1
+Expressions
+.PP
+Expressions in Limbo resemble those of C, although some
+of the operators are different.
+The most salient difference between Limbo's expression
+semantics and those of C is that Limbo
+has no automatic coercions between types; in Limbo every
+type conversion is explicit.
+.NH 2
+Terms
+.PP
+The basic elements of expressions are terms:
+.s1
+term:
+ identifier
+ constant
+ real-constant
+ string-constant
+ CnilI
+ C( Iexpression-listC )I
+ termC . Iidentifier
+ termC -> Iterm
+ termC ( Iexpression-listOC )I
+ termC [ IexpressionC ]I
+ termC [ IexpressionC : IexpressionC ]I
+ termC [ IexpressionC : ]I
+ termC ++I
+ termC --I
+.s2
+The operators on terms all associate to the left,
+and their order of precedence, with tightest listed first, is as follows:
+.P1
+ .
+ ->
+ () [] ++ --
+.P2
+.NH 3
+Simple terms
+.PP
+The first five kinds of term are constants and identifiers.
+Constants have a type indicated by their syntax.
+An identifier used in an expression is often a previously declared
+data object with a particular data type; when used as a term
+in an expression
+it denotes the value stored in the object, and the term has
+the declared object's type.
+Sometimes, as discussed below, identifiers used in expressions
+are type names, function names, or module identifiers.
+.NH 3
+Parenthesized terms
+.PP
+A comma-separated list of expressions enclosed in parentheses
+is a term.
+If a single expression is present in the list,
+the type and value are those of the expression;
+the parentheses affect only the binding
+of operators in the expression of which the term
+is a part.
+If there is more than one expression in the list,
+the value is a tuple.
+The member types
+and values are taken from those of the expressions.
+.NH 3
+Selection
+.PP
+A term of the form
+.s1
+ termC . Iidentifier
+.s2
+denotes selection of a member of an
+.CW adt
+or one element from a tuple.
+.PP
+In the first case,
+the term must be a
+type name or yield an object;
+its type must be
+.CW adt
+or
+.CW ref
+.CW adt ;
+the identifier must be a member of the
+.CW adt .
+The result denotes the named member (either a data object
+or a function).
+.PP
+In the second case,
+the term must yield a value of a tuple type,
+and the identifier must have the form \f(CWt\fP\fIn\fP
+where
+.I n
+is a decimal number giving the index (starting from 0) of an element of the tuple.
+The result is the value of that element.
+.NH 3
+Module qualification
+.PP
+A term of the form
+.s1
+ termC -> Iterm
+.s2
+denotes module qualification.
+The first term identifies a module: either it is a module type name,
+or it is an expression of module type.
+The second term is a constant name, type, or function specified within
+that module's declaration.
+Either the module type name or
+an object of the module's type suffices to qualify constants and types;
+functions directly exported by the module or contained within its
+.CW adt
+must be qualified by an object of the module's type, initialized with
+.CW load .
+.PP
+An example using an abridged version of an example above: given
+.P1
+ Linear: module {
+ setflags: fn(flag: int);
+ TRUNCATE: con 1;
+ Vector: adt {
+ make: fn(v: array of real): Vector;
+ v: array of real;
+ };
+ };
+.P2
+one might say
+.P1
+ lin := load Linear "/dis/linear.dis";
+ a: array of real;
+
+ v1: lin->Vector;
+ v2: Linear->Vector;
+ lin->setflags(Linear->TRUNCATE);
+ v1 = lin->(Linear->Vector).make(a);
+ v1 = lin->v1.make(a);
+ v1 = lin->v1.add(v1);
+ v1.v = nil;
+.P2
+Here, the declarations for
+.CW v1
+and
+.CW v2
+are equivalent; either a module type name (here,
+.CW Linear )
+or a handle (here,
+.CW lin )
+suffices to identify the module.
+In the call to
+.CW setflags ,
+a handle
+is required for the call itself;
+the type name is sufficient for the constant.
+.PP
+When calling a function associated with an
+.CW adt
+of another module, it is necessary to identify
+both the module and the
+.CW adt
+as well as the function.
+The two calls to the
+.CW make
+function illustrate two ways of doing this.
+In the first,
+.P1
+ v1 = lin->(Linear->Vector).make(a);
+.P2
+the module handle
+.CW lin
+is specified first, then
+the type name of the
+.CW Vector
+.CW adt
+within it, and then the function.
+In the second call
+.P1
+ v1 = lin->v1.make(a);
+.P2
+instead of using a type name to specify the
+.CW adt ,
+an instance of an object of the appropriate type is
+used instead.
+In the first example, the parentheses are required because
+the qualification operators associate to the left.
+.P1
+ v1 = lin->Vector.make(a); # Wrong
+ v1 = lin->Linear->Vector.make(a); # Wrong
+.P2
+The first is wrong because the same
+.CW lin
+can't serve as a qualifier for both the type and the call;
+the second is wrong because
+.CW lin->Linear
+is meaningless.
+.PP
+Using
+.CW import
+makes the code less verbose:
+.P1
+ lin := load Linear "/usr/dmr/limbo/linear.dis";
+ Vector, TRUNCATE, setflags: import lin;
+ a: array of real;
+
+ v1: Vector;
+ v2: Vector;
+ setflags(TRUNCATE);
+ v1 = Vector.make(a);
+ v1 = v1.make(a);
+ v1 = v1.add(v1);
+ v1.v = nil;
+.P2
+.NH 3
+Function calls
+.PP
+The interpretation of an expression in the form
+.s1
+ termC ( Iexpression-listOC )
+.s2
+depends on the declaration of the term.
+If it is the (perhaps qualified) name of an
+.CW adt ,
+then the expression is a cast; this is discussed in §8.2.11 below.
+If the term is either the (perhaps qualified) name of a function
+or a value of a function reference type, and
+the expression means a function call; this is discussed here.
+.PP
+A plain identifier as the
+.I term
+can name a function defined
+in the current module or imported into it.
+A term qualified by using the selection operator
+.CW .
+specifies a function member of an
+.CW adt ;
+a term using
+.CW ->
+specifies a function defined in another module.
+.PP
+The
+.I term ,
+including a plain identifier denoting a variable of function reference type,
+can also yield a function reference value.
+The value specifies both a function and its module,
+established when the value was created,
+and cannot be qualified by the
+.B ->
+specifier.
+.PP
+Function calls in Limbo
+create a copy of each argument of value type,
+and the execution of a function cannot
+affect the value of the corresponding actual argument.
+For arguments of reference type,
+execution of the function may affect the value of the object
+to which the reference refers, although it cannot
+change the argument itself.
+The actual arguments to a function are evaluated
+in an unspecified order,
+although any side effects caused by argument evaluation
+occur before the function is called.
+.PP
+Function calls may be directly or indirectly recursive;
+objects declared within each function are distinct from
+those in their dynamic predecessors.
+.PP
+Functions (§4.3, §7) may either return a value
+of a specified type, or return no value.
+If a function returns a value, it has the specified type.
+A call to a function that returns no value may appear only as the
+sole expression in a statement (§9.1).
+.PP
+A function name is converted to a reference to that function when it appears
+in a context requiring a function reference type, including assignment to a variable,
+as an actual parameter, or the return value of a function.
+The resulting reference value includes the appropriate module value for the function name,
+following the rules given above for implicit and explicit qualifiers, and imports.
+For example, the following program fragment defines a table of commands:
+.P1
+ Cmd: adt {
+ c: int;
+ f: ref fn(a: array of string): int;
+ };
+
+ mkcmds(): array of Cmd
+ {
+ return array[] of {
+ ('.', editdot),
+ ('a', editadd),
+ ('d', editdel),
+ ('?', edithelp),
+ ('w', editwrite),
+ ('q', editquit),
+ };
+ }
+
+ editdot(a: array of string): int
+ {
+ ...
+ }
+ \&...
+ editquit(a: array of string): int
+ {
+ ...
+ }
+.P2
+which might be used as follows:
+.P1
+ cmd := mkcmds();
+ ...
+ for(i := 0; i < len cmd; i++)
+ if(cmd[i].c == c){
+ cmd[i].f(args);
+ return;
+ }
+ error("unknown command");
+.P2
+.NH 3
+Subscripting and slicing
+.PP
+In a term of the form
+.s1
+ termC [ IexpressionC ]I
+.s2
+the first term must be an array or a string, and the
+bracketed expression must have
+.CW int
+type.
+The whole term
+designates a member of the array or string, indexed by the bracketed expression;
+the index origin is 0.
+For an array, the type of the whole term is
+the type from which the array is constructed;
+for a string, the type is an
+.CW int
+whose value is the Unicode character at that position in the string.
+.PP
+It is erroneous to refer to a nonexisting
+part of an array or string.
+(A single exception to this rule, discussed in §8.4.1 below,
+allows extending a string by assigning a character at its end.)
+.PP
+In a term of the form
+.s1
+ termC [ IexpressionC : IexpressionC ]I
+.s2
+the first term must be an array or a string, and the whole term
+denotes a slice of it.
+The first expression is the lower bound, and the second
+is the upper.
+If
+.CW e1
+is the first expression and
+.CW e2
+is the second, then in
+.CW a[e1:e2]
+it must be the case that
+.CW "0<=e1, e1<=e2, e2<=len a" ,
+where
+.CW len
+gives the number of elements in the array or string.
+When the term is an array, the value is an
+array of the same type beginning at the indicated
+lower bound and extending to the element just before
+the upper bound.
+When the term is a string, the value is similarly the substring
+whose first character is indexed by the lower bound
+and whose last character lies just before the upper bound.
+.PP
+Thus, for both arrays and strings, the number of elements in
+.CW "a[e1:e2]
+is equal to
+.CW e2-e1 .
+.PP
+A slice of the form
+.CW a[e:]
+means
+.CW "a[e:len a].
+.PP
+When a string slice is assigned to another string or passed as an
+argument, a copy of its value is made.
+.PP
+A slice of an array produces a reference to the designated subarray;
+a change to an element of either the original array or
+the slice is reflected in the other.
+.PP
+In general, slice expressions cannot be the subject of
+assignments.
+However, as a special case, an array slice expression of the
+form
+.CW a[e1:]
+may be assigned to.
+This is discussed in §8.4.1.
+.PP
+The following example shows how slices
+can be used to accomplish what would
+need to be done with pointer arithmetic in C:
+.P1
+ fd := sys->open( ... );
+ want := 1024;
+ buf := array[want] of byte;
+ b := buf[0:];
+ while (want>0) {
+ got := sys->read(fd, b, want);
+ if (got<=0)
+ break;
+ b = b[got:];
+ want -= got;
+ }
+.P2
+Here the array
+.CW buf
+is filled by successive calls to
+.CW sys->read
+that may supply fewer bytes than requested; each call
+stores up to
+.CW want
+bytes
+starting at
+.CW b[0] ,
+and returns the number of bytes stored.
+The invariant is that the slice
+.CW b
+always refers to the part of the array still to be stored into.
+.NH 3
+Postfix increment and decrement
+.PP
+A term of the form
+.s1
+ termC ++I
+.s2
+is called a
+.I post-increment .
+The term must be an lvalue (see §8.4 below) and must have an
+arithmetic type.
+The type and value of the whole term is
+that of the incremented term.
+After the value is taken, 1 of the appropriate
+type is added to the lvalue.
+The result is undefined if the same object is changed
+more than once in the same expression.
+.PP
+The term
+.s1
+ termC --I
+.s2
+behaves analogously to the increment case except
+that 1 is subtracted from the lvalue.
+.PP
+.NH 2
+Monadic expressions
+.PP
+Monadic expressions are expressions with
+monadic operators, together with a few more
+specialized notations:
+.s1
+monadic-expression:
+ term
+ monadic-operator monadic-expression
+ Carray [ IexpressionC ] of Idata-type
+ Carray [ IexpressionOC ] of { Iinit-listC }I
+ Clist of { Iexpression-listC }I
+ Cchan of Idata-type
+ Cchan [ IexpressionC ] of Idata-type
+ data-type monadic-expression
+
+monadic-operator: one of
+ C+ - ! ~ ref * ++ -- <- hd tl lenI
+.s2
+.NH 3
+Monadic additive operators
+.PP
+The
+.CW -
+operator produces the negative of its operand, which
+must have an arithmetic type.
+The type of the result is the same as the type of
+its operand.
+.PP
+The
+.CW +
+operator has no effect; it is supplied only for
+symmetry.
+However, its argument must have an arithmetic type
+and the type of the result is the same.
+.NH 3
+Logical negation
+.PP
+The
+.CW !
+operator yields the
+.CW int
+value 1 if its operand
+has the value 0, and yields 0 otherwise.
+The operand must have type
+.CW int .
+.NH 3
+One's complement
+.PP
+The
+.CW ~
+operator yields the 1's complement of its
+operand, which must have type
+.CW int
+or
+.CW byte .
+The type of the result is the same as that of its operand.
+.NH 3
+Reference and indirection operators
+.PP
+If
+.I e
+is an expression of an
+.CW adt
+type, then
+.CW ref
+.I e
+is an expression of
+.CW ref
+.CW adt
+type whose value refers to (points to) an anonymous object with value
+.I e .
+The
+.CW ref
+operator differs from the unary
+.CW &
+operator of C; it makes a new object and returns a reference
+to it, rather than generating a reference to an existing object.
+.PP
+If
+.I e
+is an expression of type
+.CW ref
+.CW adt ,
+then
+.CW *
+.I e
+is the value
+of the
+.CW adt
+itself.
+The value of
+.I e
+must not be
+.CW nil .
+.PP
+For example, in
+.P1
+ Point: adt { ... };
+ p: Point;
+ pp: ref Point;
+ p = Point(1, 2);
+ pp = ref p; # pp is a new Point; *pp has value (1, 2)
+ p = Point(3, 4); # This makes *pp differ from p
+ *pp = Point(4, 5); # This does not affect p
+.P2
+the expression
+.CW *pp
+at first refers to a copy of the value stored in
+.CW p ,
+so
+.CW "*pp == p
+is true; however, when
+.CW p
+is changed later,
+.CW *pp
+does not change.
+.NH 3
+Prefix increment and decrement
+.PP
+A monadic expression of the form
+.s1
+ C++ Imonadic-expression
+.s2
+is called a
+.I pre-increment .
+The monadic expression must be an lvalue (see §8.4 below) and must have an
+arithmetic type.
+Before the value is taken, 1 of the appropriate type
+is added to the lvalue.
+The type and value of the whole expression is
+that of the now incremented term.
+The result is undefined if the same object is changed
+more than once in the same expression.
+.PP
+The term
+.s1
+ C-- Imonadic-expression
+.s2
+behaves analogously to the increment case except
+that 1 is subtracted from the lvalue.
+.NH 3
+Head and tail
+.PP
+The operand of the
+.CW hd
+operator must be a non-empty list.
+The value is the first member of the list
+and has that member's type.
+.PP
+The operand of the
+.CW tl
+operator must be a non-empty list.
+The value is the tail of the list,
+that is, the part of the list after its
+first member.
+The tail of a list with one member is
+.CW nil .
+.NH 3
+Length
+.PP
+The operand of the
+.CW len
+operator is a string, an array, or a list.
+The value is an
+.CW int
+giving the number of elements currently in the item.
+.NH 3
+Tagof
+.PP
+The operand of the
+.CW tagof
+operator is a monadic expression of type
+.CW ref
+.CW adt
+that refers to a
+.CW pick
+.CW adt .
+or the type name of a
+.CW pick
+.CW adt
+or one of its variants.
+The value is an
+.CW int
+giving a unique value for each of the variants and for the
+.CW pick
+.CW adt
+type itself.
+.NH 3
+Channel communication
+.PP
+The operand of the communication operator
+.CW <-
+has type
+.CW chan
+.CW of
+.I sometype .
+The value of the expression
+is the first unread object previously sent over that
+channel, and has the type associated with the channel.
+If the channel is empty, the program delays
+until something is sent.
+.PP
+As a special case, the operand of
+.CW <-
+may have type
+.CW array
+.CW of
+.CW chan
+.CW of
+.I sometype .
+In this case, all of the channels in the array are tested;
+one is fairly selected from those that have data.
+The expression yields a tuple of type
+.CW (int,
+.I sometype
+.CW ) ;
+its first member gives the index of the channel from
+which data was read, and its second member is the
+value read from the channel.
+If no member of the array has data ready, the expression delays.
+.PP
+Communication channels are treated more fully in §9.8 and
+§9.13 below with the discussion of the
+.CW alt
+and
+.CW spawn
+statements.
+.NH 3
+Creation of arrays
+.PP
+In the expressions
+.s1
+ Carray [ IexpressionC ] of Idata-type
+ Carray [ IexpressionOC ] of { Iinit-listC ,OC }I
+.s2
+the value is a new array of the specified type.
+In both forms, the
+.I expression
+must be of type
+.CW int ,
+and it supplies the size of the array.
+In the first form, the type is given,
+and the values in the array are initialized as
+appropriate to the underlying type.
+In the second form, a comma-separated list of values to initialize
+the array is given, optionally followed by a trailing comma.
+The type of the array is taken from the types of
+the initializers, which must all be the same.
+The list of initializers has the syntax
+.s1
+init-list:
+ element
+ init-listC , Ielement
+
+element:
+ expression
+ expressionC => Iexpression
+ C* => Iexpression
+.s2
+In an
+.I init-list
+of plain expressions (without
+.CW => ),
+the members of the array
+are successively initialized with the corresponding
+elements of the init-list.
+An element of the form
+.CW e1=>e2
+initializes the member of the array at subscript
+.CW e1
+with the expression
+.CW e2 .
+After such an element has been given, subsequent
+simple elements (without
+.CW => )
+begin initializing at position
+.CW e1+1
+and so on.
+Each of the first expressions must be of type
+.CW int
+and must evaluate to a constant (§8.5).
+.PP
+If an element of the form
+.CW *
+.CW =>e2
+is present, all members of the array not otherwise
+initialized are set to the value
+.CW e2 .
+The expression
+.CW e2
+is evaluated for each subscript position,
+but in an undefined order.
+For example,
+.P1
+ arr := array[3] of { * => array[3] of { * => 1 } };
+.P2
+yields a 2-dimensional array (actually an array of arrays) filled with
+.CW 1 's.
+.PP
+If the expression giving the size of the array is omitted, its size
+is taken from the largest subscript of
+a member explicitly initialized.
+It is erroneous to initialize a member twice.
+.NH 3
+Creation of lists
+.PP
+The value of an expression
+.s1
+ Clist of { Iexpression-listC }I
+.s2
+is a list consisting of the expressions given.
+The types of the expressions must be identical,
+and this type is the underlying type of the list.
+The first expression is the head of the list, and the
+remaining expressions are a list constituting its tail.
+Where a list is expected,
+.CW nil
+specifies an empty list.
+.NH 3
+Creation of channels
+.PP
+The value of
+.s1
+ Cchan of Idata-type
+.s2
+is an initialized channel of the specified type.
+Just a declaration of a channel leaves it initialized only to
+.CW nil ;
+before it can be used it must be created. For example,
+.P1
+ ch: chan of int; # just declares, sets ch to nil
+ . . .
+ ch = chan of int; # creates the channel and assigns it
+.P2
+Such a channel is unbuffered.
+The value of
+.s1
+ Cchan [ IexpressionC ] of Idata-type
+.s2
+is an initialized channel of the specified type.
+The
+.I expression
+must be of type
+.CW int ,
+and sets the size of the channel's buffer.
+If the size is zero, the channel is unbuffered, as for the first form.
+.NH 3
+Casts
+.PP
+An expression of the form
+.s1
+ data-type monadic-expression
+.s2
+in which a type name is followed by an expression
+is called a
+.I cast ,
+and converts the monadic expression to the named type.
+Only certain specialized forms are provided for.
+.NH 4
+Arithmetic casts
+.PP
+In arithmetic casts, the named type must be one of
+.CW byte ,
+.CW int ,
+.CW big ,
+or
+.CW real ,
+and the monadic-expression must have arithmetic type.
+For example,
+.P1
+ byte 10
+.P2
+is an expression of
+.CW byte
+type and value 10.
+When real values are converted to integral ones,
+they are rounded to the nearest integer, and away from 0
+if there is a tie.
+The effect of overflow during conversion is undefined.
+.NH 4
+Casts to strings
+.PP
+Here the named data type is
+.CW string .
+In a first form, the monadic expression has arithmetic type
+.CW byte , (
+.CW int ,
+.CW big ,
+or
+.CW real )
+and the value is a string containing the decimal representation
+of the value, which may be either positive or negative.
+A
+.CW real
+operand is converted as if by format
+.CW %g ,
+and if the result is converted back to
+.CW real ,
+the original value will be recovered exactly.
+.PP
+In a second form,
+the monadic expression has type
+.CW array
+.CW of
+.CW byte .
+The value is a new string containing the Unicode characters
+obtained by interpreting the bytes in the array as a UTF-8 representation
+of that string.
+(UTF-8 is a representation of 16-bit Unicode characters as one,
+two, or three bytes.)
+The result of the conversion is undefined if the byte array
+ends within a multi-byte UTF-8 sequence.
+.NH 4
+Casts from strings
+.PP
+In a first form, the monadic expression is a string,
+and the named type is an arithmetic type.
+The value is obtained by converting the string to
+that type. Initial white space is ignored; after a possible
+sign, conversion
+ceases at the first character not part of a number.
+.PP
+In a second form, the named type is
+.CW array
+.CW of
+.CW byte
+and the monadic-expression is a string.
+The value is a new array of bytes containing the UTF-8 representation
+of the Unicode characters in the string.
+For example,
+.P1
+ s := "Ångström";
+ a := array of byte s;
+ s = string a;
+.P2
+takes the string
+.CW s
+apart into bytes in the second line,
+and puts it back in the third.
+The length of
+.CW s
+is 8, because it contains that many characters;
+the length of
+.CW a
+is larger, because some of its characters require more than
+one byte in the UTF-8 representation.
+.NH 4
+Casts to
+.CW adt
+and
+.CW ref
+.CW adt
+.PP
+Here the named type is that of an
+.CW adt
+or
+.CW ref
+.CW adt ,
+and the monadic expression is a comma-separated list of expressions
+within parentheses.
+The value of the expression is an instance of an
+.CW adt
+of the named type whose data members are initialized with
+the members of the list, or whose single data member
+is initialized with the parenthesized expression.
+In case the type is
+.CW ref
+.CW adt ,
+the value is a reference to the new
+instance of the
+.CW adt .
+.PP
+The expressions in the list, read in order, correspond with the data
+members of the
+.CW adt
+read in order; their types and number must agree.
+Placement of any function members of the
+.CW adt
+is ignored.
+For example,
+.P1
+ Point: adt {
+ x: int;
+ eq: fn (p: Point): int;
+ y: int;
+ };
+ . . .
+ p: Point;
+ p = Point(1, 2);
+.P2
+puts in
+.CW p
+a
+.CW Point
+whose
+.CW x
+value is 1 and whose
+.CW y
+value is 2.
+The declaration and assignment could also be written
+.P1
+ p := Point(1, 2);
+.P2
+.NH 2
+Binary expressions
+.PP
+Binary expressions are either monadic expressions,
+or have two operands and an infix operator;
+the syntax is
+.s1
+binary-expression:
+ monadic-expression
+ binary-expression binary-operator binary-expression
+
+binary-operator: one of
+ C** * / % + - << >> < > <= >= == != & ^ | :: && ||I
+.s2
+All these binary operators are left-associative except for
+.CW **
+and
+.CW :: ,
+which associate to the right.
+Their precedence is as listed here, with tightest first:
+.P1
+ **
+ * / %
+ + -
+ << >>
+ < > <= >=
+ == !=
+ &
+ ^
+ |
+ ::
+ &&
+ ||
+.P2
+.NH 3
+Exponentiation
+.PP
+The
+.CW **
+operator accomplishes exponentiation.
+The type of the left operand must be
+.CW int ,
+.CW big
+or
+.CW real .
+The type of the right operand must be
+.CW int .
+The result has the type of the left operand.
+The operator is right associative, thus
+.P1
+ 3**4*2 = (3**4)*2 = 81*2 = 162
+ -3**4 = (-3)**4 = 81
+ 2**3**2 = 2**(3**2) = 2**9 = 512
+.P2
+.NH 3
+Multiplicative operators
+.PP
+The
+.CW * ,
+.CW / ,
+and
+.CW %
+operators respectively accomplish multiplication, division, and remainder.
+The operands must be of identical arithmetic type, and the result has that
+same type.
+The remainder operator does not apply to type
+.CW real .
+If overflow or division by 0 occurs, the result is undefined.
+The absolute value of
+.CW a%b
+is less than the absolute value of
+.CW b ;
+.CW "(a/b)*b + a%b
+is always equal to
+.CW a ;
+and
+.CW a%b
+is non-negative if
+.CW a
+and
+.CW b
+are.
+.NH 3
+Additive operators
+.PP
+The
+.CW +
+and
+.CW -
+operators respectively accomplish addition and subtraction
+of arithmetic operands of identical type;
+the result has the same type.
+The behavior on overflow or underflow is undefined.
+The
+.CW +
+operator may also be applied to strings;
+the result is a string that is the concatenation of the operands.
+.NH 3
+Shift operators
+.PP
+The shift operators are
+.CW <<
+and
+.CW >> .
+The left operand may be
+.CW big ,
+.CW int ,
+or
+.CW byte ;
+the right operand is
+.CW int .
+The type of the value is the same as its left operand.
+The value of the right operand must be non-negative
+and smaller than the number of bits in the left operand.
+For the left-shift operator
+.CW << ,
+the fill bits are 0;
+for the right-shift operator
+.CW >> ,
+the fill bits are a copy of the sign for the
+.CW int
+case, and 0 for the
+.CW byte
+case.
+.NH 3
+Relational operators
+.PP
+The relational operators are
+.CW <
+(less than),
+.CW >
+(greater than),
+.CW <=
+(less than or equal),
+.CW >=
+(greater than or equal),
+.CW ==
+(equal to),
+.CW !=
+(not equal to).
+The first four operators, which generate orderings,
+apply only to arithmetic types
+and to strings; the types of their operands
+must be identical, except that a string may be
+compared to
+.CW nil .
+Comparison on strings is lexicographic over the
+Unicode character set.
+.PP
+The equality operators
+.CW ==
+and
+.CW !=
+accept operands of arithmetic, string, and reference types.
+In general, the operands must have identical type,
+but reference types and strings may be compared for identity with
+.CW nil .
+Equality for reference types occurs when the operands
+refer to the same object, or when both are
+.CW nil .
+An uninitialized string, or one set to
+.CW nil ,
+is identical to the empty string denoted
+.CW \&""
+for all the relational operators.
+.PP
+The value of any comparison is the
+.CW int
+value 1 if the stated
+relation is true, 0 if it is false.
+.NH 3
+Bitwise logical operators
+.PP
+The logical operators
+.CW &
+(and),
+.CW ^
+(exclusive or) and
+.CW |
+(inclusive or)
+require operands of the same type,
+which must be
+.CW byte ,
+.CW int ,
+or
+.CW big .
+The result has the same type and its
+value is obtained by applying the operation
+bitwise.
+.NH 3
+List concatenation
+.PP
+The concatenation operator
+.CW ::
+takes a object of any data type
+as its left operand and a list as its right operand.
+The list's underlying type must be the same as
+the type of the left operand.
+The result is a new list with the left operand
+tacked onto the front:
+.P1
+ hd (a :: l)
+.P2
+is the same as
+.CW a .
+.NH 3
+Logical operators
+.PP
+The logical
+.I and
+operator
+.CW &&
+first evaluates its left operand.
+If the result is zero, then the value of the
+whole expression is the
+.CW int
+value 0.
+Otherwise the right operand is evaluated; if
+the result is zero, the value of the whole
+expression is again 0; otherwise it is 1.
+The operands must have the same arithmetic type.
+.PP
+The logical
+.I or
+operator
+.CW ||
+first evaluates its left operand.
+If the result is non-zero, then the value of the
+whole expression is the
+.CW int
+value 1.
+Otherwise the right operand is evaluated; if
+the result is non-zero, the value of the whole
+expression is again 1; otherwise it is 0.
+The operands must have the same arithmetic type.
+.NH 2
+General Expressions
+.PP
+The remaining syntax for expressions is
+.s1
+expression:
+ binary-expression
+ lvalue-expression assignment-operator expression
+ C( Ilvalue-expression-listC ) = Iexpression
+ send-expression
+ declare-expression
+ load-expression
+
+assignment-operator: one of
+ C= &= |= ^= <<= >>= += -= *= /= %=I
+.s2
+The left operand of an assignment can take only certain forms, called lvalues.
+.s1
+lvalue-expression:
+ identifier
+ CnilI
+ termC [ IexpressionC ]I
+ termC [ IexpressionC : ]I
+ termC . Iidentifier
+ C( Ilvalue-expression-listC )I
+ C* Imonadic-expression
+
+lvalue-expression-list:
+ lvalue
+ lvalue-expression-listC , Ilvalue
+.s2
+.NH 3
+Simple assignments with
+.CW =
+.PP
+In general, the types of the left and right operands
+must be the same; this type must be a data type.
+The value of an assignment is its new left operand.
+All the assignment operators associate right-to-left.
+.PP
+In the ordinary assignment with
+.CW = ,
+the value of the right side is assigned to the object
+on the left.
+For simple assignment only, the left operand may be a
+parenthesized list of lvalues and the right operand
+either a tuple or an
+.CW adt
+whose data members correspond
+in number and type to the lvalues in the list.
+The members of the tuple, or
+the data members of the
+.CW adt ,
+are assigned in sequence to
+lvalues in the list.
+For example,
+.P1
+ p: Point;
+ x, y: int;
+ (x, y) = p;
+.P2
+splits out the coordinates of the point into
+.CW x
+and
+.CW y .
+These rules apply recursively, so that if one of the
+components of the left side is a parenthesized list of lvalues,
+it is assigned from a corresponding
+.CW adt
+or tuple on the right.
+.PP
+If the left operand of a simple assignment is an
+.CW adt
+and the right side is a tuple, then the assignment
+assigns the members of the tuple to the
+.CW adt
+data members; these must correspond in number and type
+with the members of the tuple.
+.PP
+The constant
+.CW nil
+may be assigned to an lvalue of any reference type.
+This lvalue will compare equal to
+.CW nil
+until it is subsequently reassigned.
+Such an assignment also
+triggers the removal of the object referred to unless other references
+to it remain.
+.PP
+The left operand of an assignment may be the constant
+.CW nil
+to indicate that a value is discarded.
+This applies in particular to any of the lvalues in
+a tuple appearing on the left; to extend the examples above,
+.P1
+ (x, nil) = p;
+.P2
+assigns the
+.CW x
+member of the Point
+.CW p
+to the variable
+.CW x .
+.PP
+A special consideration applies to
+strings.
+If an
+.CW int
+containing a Unicode character is assigned to a subscripted
+string, the subscript
+is normally required to lie within the string.
+As a special case, the subscript's value may be equal to
+the length of the string (that is, just beyond its end);
+in this case, the character is appended to
+the string, and the string's length increases by 1.
+.PP
+A final special case applies to array slices in the form
+.CW e1[e2:] .
+Such expressions may lie on the left of
+.CW = .
+The right side must be an array of the same type as
+.CW e1 ,
+and its length must be less than or equal to
+.CW "(len e1)-e2.
+In this case, the
+elements in the array on the right replace the elements of
+.CW e1
+starting at position
+.CW e2 .
+The length of the array is unchanged.
+.NH 3
+Compound assignments
+.PP
+A compound assignment with
+.I op\f(CW=\fP
+is interpreted in terms of the plain assignment;
+.P1
+ e1 \fIop\f(CW= e2;
+.P2
+is equivalent to
+.P1
+ e1 \f(CW= (e1) \fIop \f(CW(e2);
+.P2
+except that
+.CW e1
+is evaluated only once.
+.NH 3
+Send expressions
+.PP
+A
+.I send-expression
+takes the form
+.s1
+send-expression:
+ lvalue-expressionC <- = Iexpression
+.s2
+In the expression
+.P1
+ e1 <- = e2
+.P2
+the lvalue
+.CW e1
+must have type
+.CW chan
+.CW of
+.I type ,
+and
+.CW e2
+must be of that type.
+The value of
+.CW e2
+is sent over the channel.
+If no task is executing a
+channel receive operation on the specified channel, and the channel is unbuffered or its buffer
+is full, the sender blocks.
+Task synchronization is discussed in §9.8 and §9.13 below.
+.NH 3
+Declare-expressions
+.PP
+A
+.I declare-expression
+is an assignment that also declares identifiers on its left:
+.s1
+declare-expression:
+ lvalue-expressionC := Iexpression
+.s2
+Each of the constituent terms in the
+.I lvalue-expression
+must be an identifier or
+.CW nil .
+A plain identifier on the left
+is declared as having the type of the expression,
+and it is initialized with the expression's value.
+When a parenthesized list of identifiers is given, the expression
+must be a tuple or an
+.CW adt ,
+and the individual identifiers in the list are declared and initialized
+with the members of the tuple, or the data members of the
+.CW adt .
+As with ordinary assignments, the keyword
+.CW nil
+may stand for an identifier whose declaration and assignment
+are skipped.
+.PP
+The value and type of a declare-expression are the same as those of the expression.
+.NH 3
+Load expressions
+.PP
+A
+.I load-expression
+has the form
+.s1
+load-expression:
+ Cload Iidentifier expression
+.s2
+The identifier is the identifier of a module, that is, the type
+name declared in a
+.CW module
+declaration.
+The expression following
+.CW load
+has type
+.CW string
+and names a file containing the
+compiled form of the module.
+The
+.CW load
+expression yields a handle for referring to the functions provided
+by a module and its
+.CW adt .
+.PP
+Execution of
+.CW load
+brings the file containing the module into local memory and dynamically type-checks
+its interface: the run-time system ascertains that
+the declarations exported by the module are compatible
+with the module declaration visible in the scope of the
+.CW load
+operator (see §11.2).
+In the scope of a module declaration, the types and constants
+exported by the module may be referred to without a handle, but
+the functions and data exported by the module
+(directly at its top level, or within its
+.CW adt )
+may be called only using a valid
+handle acquired by the
+.CW load
+operator.
+.PP
+The value of
+.CW load
+is
+.CW nil
+if the attempt to load fails, either because the file containing
+the module can not be found, or because the found module does not
+export the specified interface.
+.PP
+Each evaluation of
+.CW load
+creates a separate instance of the specified module;
+it does not share data with any other instance.
+.NH 2
+Constant expressions
+.PP
+In several places a constant expression is required.
+Such an expression contains operands that are
+identifiers previously declared with
+.CW con ,
+or
+.CW int ,
+.CW big ,
+.CW real ,
+or
+.CW string
+constants.
+These may be connected by any of the following operators:
+.P1
+.ta .5i 1i 1.5i 2i 2.5i 3i 3.5i 4i 4.5i 5i 5.5i
+ + - * / % & | ^
+ == < > <= >= != << >>
+ && ||
+ ~ !
+.P2
+together with arithmetic and string casts, and parentheses for
+grouping.
+.NH 2
+Expression evaluation
+.PP
+Expressions in Limbo are not reordered by the compiler;
+values are computed in accordance with the parse of the expression.
+However there is no guarantee of temporal evaluation order for expressions
+with side effects, except in the following circumstances:
+function arguments are fully evaluated before the function
+is called; the logical operators
+.CW &&
+and
+.CW ||
+have fully defined order of evaluation, as explained above.
+All side effects from an expression in one statement are
+completed before the next statement is begun.
+.PP
+In an expression containing a constant subexpression (in the
+sense of §8.5), the constant subexpression is evaluated at
+compile-time with all exceptions ignored.
+.PP
+Underflow, overflow, and zero-divide conditions during integer
+arithmetic produce undefined results.
+.PP
+The
+.CW real
+arithmetic of Limbo is all performed in IEEE double precision,
+although denormalized numbers may not be supported.
+By default,
+invalid operations, zero-divide, overflow, and underflow
+during real arithmetic are fatal; inexact-result is quiet.
+The default rounding mode is round-to-nearest-even.
+A set of routines in the
+.CW Math
+library module permits independent control of these modes within each thread.
+.NH 1
+Statements
+.PP
+The executable code within a function definition consists
+of a sequence of statements and declarations.
+As discussed in the Scope section §11 below,
+declarations become effective at the place they appear.
+Statements are executed in sequence except as discussed below.
+In particular, the optional labels on some of the statements are used with
+.CW break
+and
+.CW continue
+to exit from or re-execute the labeled statement.
+.s1
+statements:
+ (empty)
+ statements declaration
+ statements statement
+
+statement:
+ expressionC ;I
+ C;I
+ C{ IstatementsC }I
+ Cif ( IexpressionC ) Istatement
+ Cif ( IexpressionC ) IstatementC else Istatement
+ labelO Cwhile ( IexpressionOC ) Istatement
+ labelO Cdo IstatementC while ( IexpressionOC ) ;I
+ labelO Cfor ( IexpressionOC ; IexpressionOC ; IexpressionOC ) Istatement
+ labelO Ccase IexpressionC { Iqual-statement-sequenceC }I
+ labelO Calt { Iqual-statement-sequenceC }I
+ labelO Cpick IidentifierC := IexpressionC { Ipqual-statement-sequenceC }I
+ Cbreak IidentifierOC ;I
+ Ccontinue IidentifierOC ;I
+ Creturn IexpressionOC ;I
+ Cspawn ItermC ( Iexpression-listOC ) ;I
+ Cexit ;I
+ C{ IstatementsC } exceptionI identifierOC{ Iqual-statement-sequenceC }I
+ Craise IexpressionOC ;I
+.s2
+.s1
+label:
+ identifier C:I
+.s2
+.NH 2
+Expression statements
+.PP
+Expression statements consist of an expression followed by
+a semicolon:
+.s1
+ expressionC ;I
+.s2
+Most often expression statements are assignments, but other expressions
+that cause effects are often useful, for example calling a function
+or sending or receiving on a channel.
+.NH 2
+Null statement
+.PP
+The null statement consists of a lone semicolon.
+It is most useful for supplying an empty body
+to a looping statement with internal side effects.
+.NH 2
+Blocks
+.PP
+Blocks are
+.I statements
+enclosed in
+.CW {}
+characters.
+.s1
+ C{ IstatementsC }I
+.s2
+A block starts a new scope.
+The effect of any declarations within a block disappears
+at the end of the block.
+.NH 2
+Conditional statements
+.PP
+The conditional statement takes two forms:
+.s1
+ Cif ( IexpressionC ) Istatement
+ Cif ( IexpressionC ) IstatementC else Istatement
+.s2
+The
+.I expression
+is evaluated; it must have type
+.CW int .
+If it is non-zero, then the first
+.I statement
+is executed.
+In the second form, the second
+.I statement
+is executed if the
+.I expression
+is 0.
+The statement after
+.CW else
+is connected to the nearest
+.CW else -less
+.CW if .
+.NH 2
+Simple looping statements
+.PP
+The simple looping statements are
+.s1
+ labelO Cwhile ( IexpressionOC ) Istatement
+ labelO Cdo IstatementC while ( IexpressionOC ) ;I
+.s2
+In both cases the expression must be of type
+.CW int .
+In the first form, the
+.I expression
+is first tested against 0;
+while it is not equal, the
+.I statement
+is repeatedly executed.
+In the second form, the
+.I statement
+is executed, and then, while the
+.I expression
+is not 0, the statement is repeatedly executed.
+If the
+.I expression
+is missing, it is understood to be non-zero.
+.NH 2
+.CW for
+statement
+.PP
+The
+.CW for
+statement has the form
+.s1
+ labelO Cfor ( Iexpression-1OC ; Iexpression-2OC ; Iexpression-3OC ) Istatement
+.s2
+It is equivalent to
+.s1
+ expression-1C ;I
+ Cwhile ( Iexpression-2C ) {
+ Istatement
+ expression-3C ;
+ C}I
+.s2
+in the absence of
+.CW continue
+or
+.CW break
+statements.
+Thus (just as in C), the first expression is an initialization,
+the second a test for starting and continuing the loop, and the third
+a re-initialization for subsequent travels around the loop.
+.NH 2
+.CW case
+statement
+.PP
+The
+.CW case
+statement transfers control to one of several places
+depending on the value of an expression:
+.s1
+ labelO Ccase IexpressionC { Iqual-statement-sequenceC }I
+.s2
+The expression must have type
+.CW int ,
+.CW big
+or
+.CW string .
+The
+.CW case
+statement is followed by sequence of
+qualified statements, which are statements labeled by
+expressions or expression ranges:
+.s1
+qual-statement-sequence:
+ qual-listC =>I
+ qual-statement-sequence qual-listC =>I
+ qual-statement-sequence statement
+ qual-statement-sequence declaration
+
+qual-list:
+ qualifier
+ qual-listC or Iqualifier
+
+qualifier:
+ expression
+ expressionC to Iexpression
+ C*I
+.s2
+A
+.I qual-statement-sequence
+is a sequence of
+statements and declarations, each of which
+is preceded by one or more qualifiers.
+Syntactically, the qualifiers are
+expressions, expression ranges with
+.CW to ,
+or
+.CW * .
+If the expression mentioned after
+.CW case
+has
+.CW int
+or
+.CW big
+type,
+all the expressions appearing in the qualifiers
+must evaluate to integer constants of the same type (§8.5).
+If the expression has
+.CW string
+type, all the qualifiers must be
+string constants.
+.PP
+The
+.CW case
+statement is executed by comparing
+the expression at its head with the constants
+in the qualifiers.
+The test is for equality in the case
+of simple constant qualifiers;
+in range qualifiers, the test determines
+whether the expression is greater than or
+equal to the first constant and less than
+or equal to the second.
+.PP
+None of the ranges or constants may overlap.
+If no qualifier is selected and
+there is a
+.CW *
+qualifier,
+then that qualifier is selected.
+.PP
+Once a qualifier is selected, control passes
+to the set of statements headed by that
+qualifier.
+When control reaches the end of that set
+of statements, control passes to the end
+of the
+.CW case
+statement.
+If no qualifier is selected, the
+.CW case
+statement is skipped.
+.PP
+Each qualifier and the statements following it
+up to the next qualifier together form a separate
+scope, like a block; declarations within this scope
+disappear at the next qualifier (or at the end of
+the statement.)
+.PP
+As an example, this fragment separates small numbers
+by the initial letter of their spelling:
+.P1
+ case i {
+ 1 or 8 =>
+ sys->print("Begins with a vowel\en)";
+ 0 or 2 to 7 or 9 =>
+ sys->print("Begins with a consonant\en");
+ * =>
+ sys->print("Sorry, didn't understand\en");
+ }
+.P2
+.NH 2
+.CW alt
+statement
+.PP
+The
+.CW alt
+statement transfers control to one of several groups
+of statements depending on the readiness of communication
+channels.
+Its syntax resembles that of
+.CW case :
+.s1
+ labelO Calt { Iqual-statement-sequenceC }I
+.s2
+However, the qualifiers take a form different
+from those of
+.CW case .
+In
+.CW alt ,
+each qualifier must be a
+.CW * ,
+or an expression containing a communication
+operator
+.CW <-
+on a channel;
+the operator may specify either sending or receiving.
+For example,
+.P1
+ outchan := chan of string;
+ inchan := chan of int;
+ alt {
+ i := <-inchan =>
+ sys->print("Received %d\en", i);
+
+ outchan <- = "message" =>
+ sys->print("Sent the message\en");
+ }
+.P2
+The
+.CW alt
+statement is executed by testing each of
+the channels mentioned in the
+.I qual-list
+expressions for ability to send or receive,
+depending on the operator;
+if none is ready, the program blocks
+until at least one is ready.
+Then a random choice from the ready channels is selected
+and control passes to the associated set
+of statements.
+.PP
+If a qualifier of the form
+.CW *
+is present, then the statement does not block;
+if no channel is ready the statements associated with
+.CW *
+are executed.
+.PP
+If two communication operators are present
+in the same qualifier expression, only the leftmost one is
+tested by
+.CW alt .
+If two or more
+.CW alt
+statements referring to the same receive (or send)
+channel are executed in different
+threads, the requests are queued;
+when the channel becomes unblocked, the thread
+that executed
+.CW alt
+first is activated.
+.PP
+As with
+.CW case ,
+each qualifier and the statements following it
+up to the next qualifier together form a separate
+scope, like a block; declarations within this scope
+disappear at the next qualifier (or at the end of
+the statement.)
+Thus, in the example above, the scope of
+.CW i
+in the arm
+.P1
+ i := <-inchan =>
+ sys->print("Received %d\en", i);
+.P2
+is restricted to these two lines.
+.PP
+As mentioned in the specification
+of the channel receive operator
+.CW <-
+in §8.2.8, that operator can take an array of channels as an argument.
+This notation serves as a kind of simplified
+.CW alt
+in which all the channels have the same type
+and are treated similarly.
+In this variant,
+the value of the communication expression is a tuple
+containing the index of the
+channel over which a communication was received and
+the value received.
+For example, in
+.P1
+ a: array [2] of chan of string;
+ a[0] = chan of string;
+ a[1] = chan of string;
+ . . .
+ (i, s) := <- a;
+ # s has now has the string from channel a[i]
+.P2
+the
+.CW <-
+operator waits until at least one of the
+members of
+.CW a
+is ready, selects one of them at random,
+and returns the index and the transmitted string
+as a tuple.
+.PP
+During execution of an
+.CW alt ,
+the expressions in the qualifiers are evaluated in an undefined
+order, and in particular subexpressions may be evaluated before
+the channels are tested for readiness.
+Therefore qualifying expressions should not invoke side effects,
+and should avoid subparts that might delay execution.
+For example, in the qualifiers
+.P1
+ ch <- = getchar() => # Bad idea
+ ich <- = next++ => # Bad idea
+.P2
+.CW getchar()
+may be called early in the elaboration of the
+.CW alt
+statement; if it delays, the entire
+.CW alt
+may wait.
+Similarly, the
+.CW next++
+expression may be evaluated before testing the readiness of
+.CW ich .
+.NH 2
+.CW pick
+statement
+.PP
+The
+.CW pick
+statement transfers control to one of several groups of statements
+depending upon the resulting variant type of a
+.CW pick
+.CW adt
+expression. The syntax resembles that of
+.CW case :
+.s1
+ labelO Cpick IidentifierC := IexpressionC { Ipqual-statement-sequenceC }I
+.s2
+The expression must have type
+.CW ref
+.CW adt
+and the
+.CW adt
+must be a
+.CW pick
+.CW adt .
+The
+.CW pick
+statement is followed by a sequence of qualified statements, which are
+statements labeled by the
+.CW pick
+variant names:
+.s1
+pqual-statement-sequence:
+ pqual-listC =>I
+ pqual-statement-sequence pqual-listC =>I
+ pqual-statement-sequence statement
+ pqual-statement-sequence declaration
+
+pqual-list:
+ pqualifier
+ pqual-listC or Ipqualifier
+
+pqualifier:
+ identifier
+ C*I
+.s2
+A
+.I pqual-statement-sequence
+is a sequence of statements and declarations, each of which
+is preceded by one or more qualifiers.
+Syntactically, the qualifiers are identifiers, identifier lists (constructed with
+.CW or ),
+or
+.CW * .
+The identifiers must be names of the variant types of the
+.CW pick
+.CW adt .
+The
+.CW pick
+statement is executed by comparing the variant type of the
+.CW pick
+.CW adt
+referenced by the expression at its head with the variant type names in the qualifiers.
+The matching qualifier is selected.
+None of the variant type names may appear more than once.
+If no qualifier is selected and there is a
+.CW *
+qualifier, then that qualifier is selected.
+.PP
+Once a qualifier is selected, control passes
+to the set of statements headed by that qualifier.
+When control reaches the end of that set of statements,
+control passes to the end of the
+.CW pick
+statement.
+If no qualifier is selected, the
+.CW pick
+statement is skipped.
+.PP
+Each qualifier and the statements following it
+up to the next qualifier together form a separate
+scope, like a block; declarations within this scope
+disappear at the next qualifier (or at the end of
+the statement.)
+.PP
+The
+.I identifier
+and
+.I expression
+given in the
+.CW pick
+statement are used to bind a new variable to a
+.CW pick
+.CW adt
+reference expression, and within the statements associated with the
+selected qualifier the variable can be used as if it were of the corresponding
+variant type.
+.PP
+As an example, given a
+.CW pick
+.CW adt
+of the following form:
+.P1
+ Constant: adt {
+ name: string;
+ pick {
+ Str or Pstring =>
+ s: string;
+ Real =>
+ r: real;
+ }
+ };
+.P2
+the following function could be used to print out the value of
+an expression of type
+.CW "ref Constant" :
+.P1
+ printconst(c: ref Constant)
+ {
+ sys->print("%s: ", c.name);
+ pick x := c {
+ Str =>
+ sys->print("%s\en", x.s);
+ Pstring =>
+ sys->print("[%s]\en", x.s);
+ Real =>
+ sys->print("%f\en", x.r);
+ };
+ }
+.P2
+.NH 2
+.CW break
+statement
+.PP
+The
+.CW break
+statement
+.s1
+ Cbreak IidentifierO C;I
+.s2
+terminates execution of
+.CW while ,
+.CW do ,
+.CW for ,
+.CW case ,
+.CW alt ,
+and
+.CW pick
+statements.
+Execution of
+.CW break
+with no identifier
+transfers control to
+the statement after the innermost
+.CW while ,
+.CW do ,
+.CW for ,
+.CW case ,
+.CW alt ,
+or
+.CW pick
+statement in which it appears as a substatement.
+Execution of
+.CW break
+with an identifier
+transfers control to the next statement after the unique enclosing
+.CW while ,
+.CW do ,
+.CW for ,
+.CW case ,
+.CW alt ,
+or
+.CW pick
+labeled with that identifier.
+.NH 2
+.CW continue
+statement
+.PP
+The
+.CW continue
+statement
+.s1
+ Ccontinue IidentifierO C;I
+.s2
+restarts execution of
+.CW while ,
+.CW do ,
+and
+.CW for
+statements.
+Execution of
+.CW continue
+with no identifier
+transfers control to the end of
+the innermost
+.CW while ,
+.CW do ,
+or
+.CW for
+statement in which the
+.CW continue
+appears as a substatement.
+The expression that controls the loop is tested
+and if it succeeds, execution continues in the loop.
+The initialization portion of
+.CW for
+is not redone.
+.PP
+Similarly, execution of
+.CW continue
+with an identifier transfers control to the end of the enclosing
+.CW while ,
+.CW do ,
+or
+.CW for
+labeled with the same identifier.
+.NH 2
+.CW return
+statement
+.PP
+The
+.CW return
+statement,
+.s1
+ Creturn IexpressionOC ;I
+.s2
+returns control to the caller of a function.
+If the function returns a value (that is, if its definition
+and declaration mention a return type),
+the expression must be given and it must have the same type that the
+function returns.
+If the function returns no value, the expression
+must generally be omitted.
+However, if a function returns no value, and its
+last action before returning is to call
+another function with no value, then it may
+use a special form of
+.CW return
+that names the function being called.
+For example,
+.P1
+ f, g: fn(a: int);
+ f(a: int) {
+ . . .
+ return g(a+1);
+ }
+.P2
+is permitted.
+Its effect is the same as
+.P1
+ f(a: int) {
+ . . .
+ g(a+1);
+ return;
+ }
+.P2
+This
+.I "ad hoc
+syntax offers the compiler a cheap opportunity to recognize
+tail-recursion.
+.PP
+Running off the end of a function is equivalent to
+.CW return
+with no expression.
+.NH 2
+.CW spawn
+statement
+.PP
+The
+.CW spawn
+statement creates a new thread of control.
+It has the form
+.s1
+ Cspawn ItermC ( Iexpression-listOC ) ;I
+.s2
+The term and expression-list are taken to be
+a function call.
+Execution of
+.CW spawn
+creates an asynchronous, independent thread
+of control, which calls the function in the new thread context.
+This function may access the accessible objects
+in the spawning thread; the two threads share
+a common memory space.
+These accessible objects include the data global to
+the current module and reference data passed to the
+spawned function.
+Threads are preemptively scheduled, so that
+changes to objects used in common between
+threads may occur at any time.
+The Limbo language provides no explicit synchronization
+primitives; §12.3 shows examples of how to use channel
+communication to control concurrency.
+.NH 2
+.CW exit
+statement
+.PP
+The
+.CW exit
+statement
+.s1
+ Cexit ;I
+.s2
+terminates a thread and frees any resources
+belonging exclusively to it.
+.NH 2
+.CW raise
+statement
+.PP
+The
+.CW raise
+statement
+.s1
+ Craise IexpressionOC ;I
+.s2
+raises an exception in a thread.
+The
+.I expression
+is either a string describing the failure, or an exception name and its parameter values, if any.
+If an expression is not given, the
+.CW raise
+statement must appear in the body of an exception handler; it raises the currently active exception.
+.NH 2
+Exception handler
+.PP
+Various errors in a Limbo program can be detected only at run-time.
+These include programming errors such as an attempt to index outside the bounds of an array,
+system errors such as exhausting memory, and user-defined exceptions
+declared at compile-time by exception declarations and caused at run-time by the
+.CW raise
+statement.
+A group of statements can have an associated exception handler:
+.s1
+ C{ IstatementsC } exceptionI identifierOC{ Iqual-statement-sequenceC }I
+.s2
+The first run-time exception raised by any of the
+.I statements ,
+or functions they call,
+that is not handled by an exception handler enclosing the statement raising the exception
+will terminate execution of the
+.I statements
+at that point, and transfer control to the clause in the sequence of qualified statements
+that matches the exception.
+An exception represented by a string is matched by a qualifier that is either the same
+string value, or a prefix of it followed by
+.CW * .
+The optional identifier following
+.CW exception
+is set to the value of the exception string for the execution of the qualified statement.
+If execution of the qualified statement completes, control passes to the statement following
+the exception-handling statement.
+.PP
+A qualified statement labeled by a user-defined exception name matches that exception.
+If the exception has parameters, the identifier following
+.CW exception
+will be be declared and initialized as a tuple of the parameter values for the scope
+of the qualified statement, allowing the values to be recovered by tuple assigment.
+.PP
+The qualifier
+.CW *
+matches any string or user-defined exception.
+An exception that is raised and not successfully handled by a thread will terminate the thread.
+.NH
+Referring to modules;
+.CW import
+.PP
+As discussed above, modules present
+constants, functions, and types
+in their interface.
+Their names may be the same as names
+in other modules or of local objects or types within
+a module that uses another.
+Name clashes are avoided because references
+to the entities presented by a module are
+qualified by the module type name or an object
+of that module type.
+.PP
+For example,
+after the module and variable declarations
+.P1
+ M: module {
+ One: con 1;
+ Thing: adt {
+ t: int;
+ f: fn();
+ };
+ g: fn();
+ };
+ m: M;
+.P2
+the name
+.CW One
+refers to the constant defined in
+module
+.CW M
+only in the contexts
+.CW M->One
+or
+.CW m->One ;
+the name
+.CW Thing
+as the particular data type
+associated with the
+.CW M
+module can be referred to only in contexts
+like
+.P1
+ th1: M->Thing;
+ th2: m->Thing;
+.P2
+Finally, to call a function defined either as a top-level
+member of the module, or as a member of one of its
+.CW adt ,
+it is necessary to declare, and also dynamically initialize using
+.CW load ,
+a handle for the module.
+Then calls of the form
+.P1
+ m->g();
+ m->th1.f();
+.P2
+become appropriate.
+It is possible to use just the type name of a module to qualify
+its constants and types because constants and types can be understood
+without having the code and data present.
+Calling a function declared by a module or one of its
+.CW adt
+requires loading the module.
+.PP
+The
+.CW import
+declaration
+.s1
+ Iidentifier-listC : import Iidentifier C;I
+.s2
+lifts the identifiers in the
+.I identifier-list
+into the scope in which
+.CW import
+appears, so that they are usable without a qualifier.
+The identifier after the
+.CW import
+keyword is either
+a module identifier, or an identifier declared as having
+that type.
+The initial list of identifiers specifies those
+constants,
+types,
+and functions of the module whose names are promoted.
+In the case of constants and types,
+.CW import
+merely makes their names accessible without using a qualifier.
+In the example above, if the
+.CW module
+declaration above had been followed by
+.P1
+ One, Thing: import M;
+.P2
+then one could refer to just
+.CW One
+instead of
+.CW M->One ;
+similarly an object could be declared like
+.P1
+ th: Thing;
+.P2
+For functions, and also
+.CW adt
+with functions as members,
+.CW import
+must specify a module
+variable (as opposed to a module identifier).
+Each imported name is associated with the specified module
+variable, and the current value of this module variable
+controls which instance of the module will
+be called.
+For example, after
+.P1
+ g, Thing: import m;
+.P2
+then
+.P1
+ g();
+.P2
+is equivalent to
+.P1
+ m->g();
+.P2
+and
+.P1
+ th: Thing;
+ th.f();
+.P2
+is equivalent to
+.P1
+ th: M->Thing;
+ m->th.f();
+.P2
+When the module declaration for the module being
+implemented is encountered, an implicit
+.CW import
+of all the names of the module is executed.
+That is, given
+.P1
+ implement Mod;
+ . . .
+ Mod: module {
+ . . .
+ };
+.P2
+the constants and types of
+.CW Mod
+are accessed as if they had been imported;
+the functions declared in
+.CW Mod
+are imported as well, and refer dynamically to the
+current instance of the module being implemented.
+.NH
+Scope
+.PP
+The scope of an identifier is the lexical range of
+a program throughout which the identifier means a particular
+type of, or instance of, an object.
+The same identifier may be associated with several
+different objects in different parts of the same program.
+.PP
+The names of members of an
+.CW adt
+occupy a separate, nonconflicting space from other identifiers;
+they are declared in a syntactically distinct position,
+and are always used in a distinguishable way, namely
+after the
+.CW .
+selection operator.
+Although the same scope rules apply to
+.CW adt
+members as to other identifiers, their names may
+coincide with other entities in the same scope.
+.PP
+Similarly, the names of constants, functions, and
+.CW adt
+appearing
+within a
+.CW module
+declaration are ordinarily qualified either with
+the name of the module or with a module variable
+using the
+.CW ->
+notation.
+As discussed above, the
+.CW import
+declaration lifts these names into the current scope.
+.PP
+Identifiers declared in a top-declaration
+(§5) have scope that lasts from the
+declaration throughout the remainder of the
+file in which it occurs, unless it is overridden
+by a redeclaration of that name within an inner
+scope.
+Each function definition, and each block
+within a function,
+introduces a new scope.
+A name declared within the block or function
+(including a formal argument name of a function)
+has a scope that begins
+at the completion of its declaration and lasts until
+the end of the block or function.
+If an already-declared identifier is redeclared within
+such an inner scope, the declaration previously in
+force is used in any initialization expression
+that is part of the new declaration.
+.PP
+As discussed above, within
+.CW case
+.CW alt
+and
+.CW pick ,
+each qualifier
+and the statements following it form an inner
+scope just like a block.
+.PP
+The scope of a label is restricted to the
+labeled statement,
+and label names may coincide with those of other
+entities in the same scope.
+.NH 2
+Forward referencing
+.PP
+In general, names must be declared before they are used.
+.PP
+The first exception to this rule is that a
+function local to a module need not have a
+declaration at all; it is sufficient to give
+its definition, and that definition may appear anywhere
+in the module.
+.PP
+The general rule implies that no
+.CW adt
+may contain, as a member, an
+.CW adt
+not previously declared (including an instance of itself).
+A second exception to this rule applies to
+.CW ref
+.CW adt
+types.
+An
+.CW adt
+may contain a member whose type is a
+.CW ref
+to itself, or to another
+.CW adt
+even if the second
+.CW adt
+has not yet been declared.
+.PP
+For example, a tree structure where nodes contain references to children can be declared and created as follows:
+.P1
+ Tree: adt {
+ l: ref Tree;
+ r: ref Tree;
+ v: int;
+ };
+
+ t1a := ref Tree(nil, nil, 0);
+ t1b := ref Tree(nil, nil, 1);
+ t1c := ref Tree(nil, nil, 2);
+ t2 := Tree(t1a, t1b, 0);
+ t2.l = t1c; # replace reference to t1a by reference to t1c
+.P2
+The tree structure resulting above is non-circular, since no
+.CW adt
+value refers back to itself directly or indireclty.
+Circular data structures can also be created. For example,
+.P1
+ Graph: adt {
+ next: ref Graph;
+ v: int;
+ };
+
+ g1 := ref Graph(nil, 0);
+ g2 := ref Graph(g1, 1);
+ g1.next = g2;
+.P2
+creates a pair of nodes that refer to each other.
+.PP
+Limbo implementations guarantee to
+destroy all data objects not involved in circular data structures
+immediately after they become non-referenced by active
+tasks, whether because
+their names go out of scope or because they are assigned new values.
+This property has visible effect because certain system resources,
+like windows and file descriptors, can be seen outside the program.
+In particular, if a reference to such a resource is held only within an
+.CW adt ,
+then that resource too is destroyed when the
+.CW adt
+is.
+Circular data structures can also be created.
+When they become unreferenced except by themselves, they will
+be garbage-collected eventually, but not instantly.
+.PP
+An earlier version of the language required circular references to be annoted by the word
+.CW cyclic ,
+but that is no longer required.
+The notation can still be seen in some system source code, because the
+.CW cyclic
+qualifier is taken into account in type checking, as described below, and some instances remain to provide backward compatibility.
+.NH 2
+Type equality and compatibility
+.PP
+In an assignment and in passing an actual argument to a function,
+the types of the target and the expression being assigned or
+passed must be equal (with certain exceptions, e.g. assignment of
+.CW nil
+to a reference type).
+When a function is defined, its type must be equal to the type
+of a function with the same name if one is in scope.
+Type equality is determined as follows.
+.PP
+Two basic types are equal if and only if they are identical.
+.PP
+Two tuple types are equal if and only if they are composed
+of equal types in the same order.
+.PP
+Two array types are equal if and only if they are arrays
+of equal types.
+The size of an array is not part of its type.
+.PP
+Two list types are equal if and only if they are composed
+of equal types.
+.PP
+Two channel types are equal if and only if they transmit
+equal types.
+.PP
+Two
+.CW adt
+types are equal if and only if their data members
+have the same names and correspondingly
+equal types, including any
+.CW cyclic
+attribute.
+The order of member declaration is insignificant, and
+constant and function members of an
+.CW adt
+do not enter into the comparison,
+nor does the name of the
+.CW adt
+type itself.
+In particular, with the declarations
+.P1
+ A: adt { x: ref B; };
+ B: adt { x: ref A; };
+.P2
+the types
+.CW A
+and
+.CW B
+are equal.
+.PP
+Two
+.CW ref
+.CW adt
+types are equal if and only if they are references to equal
+.CW adt
+types.
+.PP
+Two module types are equal if and only if their data and function members
+have the same names and correspondingly equal types; the order
+of their mention is insignificant.
+Constant members and type members do not enter into the comparison.
+.PP
+Two function types are equal if and only if their return
+values have the same type
+and their argument lists have correspondingly equal types.
+Any
+.CW self
+attributes given to arguments must match.
+Names given to arguments do not enter into the comparison.
+.PP
+A type name has the same type as the type from
+which it was constructed.
+.PP
+When a module is loaded, the module stored
+in the file system must have a type that is
+.I compatible
+with the type mentioned in the
+.CW load
+expression.
+The type of the stored module
+type is compatible with the mentioned type if and only if
+all data members of the two types are equal in name and type,
+and all
+.CW adt
+or functions actually mentioned by the program executing
+.CW load
+have names and types equal to corresponding members of
+the stored module.
+.NH
+Examples
+.PP
+Because Limbo was designed for the Inferno environment, several
+of these examples consist of simplified versions of already simple
+Inferno applications in a prototype Inferno implementation.
+Some appreciation for the resources available in this environment
+should become evident, but its full description is available
+elsewhere;
+the discussion here will focus on language features.
+However, several of the programs use facilities
+from the module
+.CW Sys ,
+which provides an interface to a file system and its methods
+resembling those of Unix or Plan 9,
+as well as other useful library facilities.
+.PP
+Some of the programs are annotated with line numbers;
+they are there only for descriptive purposes.
+.NH 2
+A simple command interpreter module
+.PP
+This version of a shell program reads from a keyboard and
+executes `commands' typed by the user.
+Its own interface has the type of a
+.CW Command
+module, and that is the type of the things it executes.
+In particular, it can call modules like the
+.CW hello
+example at the beginning of the paper.
+.P1
+1 implement Command;
+
+2 include "sys.m";
+3 include "draw.m";
+
+4 sys: Sys;
+5 stdin: ref Sys->FD;
+
+6 Command: module
+7 {
+8 init: fn(nil: ref Draw->Context, nil: list of string);
+9 };
+.P2
+After the boilerplate on lines 1-3, the variables
+.CW sys
+and
+.CW stdin
+are declared on lines 4 and 5.
+The I/O operations of the
+.CW Sys
+module use the
+.CW ref
+.CW FD
+type to refer to open files.
+.P1
+10 init(ctx: ref Draw->Context, nil: list of string)
+11 {
+12
+13
+14 buf := array[256] of byte;
+
+15 sys = load Sys Sys->PATH;
+16 stdin = sys->fildes(0);
+
+17 for(;;) {
+18 sys->print("$ ");
+19 n := sys->read(stdin, buf, len buf);
+20 if(n <= 0)
+21 break;
+22 (nw, arg) :=
+ sys->tokenize(string buf[0:n], " \et\en");
+23 if(nw != 0)
+24 exec(ctx, arg);
+25 }
+26 }
+.P2
+Line 10: conventionally, stand-alone modules are started
+by calling their
+.CW init
+functions.
+The
+.CW Command
+module follows this convention.
+The arguments are presented as a list of strings.
+In this simple example, the command interpreter itself
+ignores its argument, so it need not be given a name.
+.PP
+Local variables are declared on lines 12-14; line 15
+loads the
+.CW Sys
+module and stores a handle for it in the variable
+.CW sys .
+Line 16 creates an
+.CW FD
+for the standard input by calling the
+.CW fildes
+function of the
+.CW Sys
+module using the
+.CW ->
+operator; the notation
+.CW modhandle->func(...)
+specifies a call to the function named
+.CW func
+in the module currently referred to by
+.CW modhandle .
+(In general there can be several modules of the same type and name
+active, and there can also be unrelated modules containing identically
+named functions.
+The
+.CW import
+declaration, described in §6.6 above, can be used to abbreviate
+the references when names do not clash.)
+.PP
+The loop on lines 17-25 prints a prompt (line 18), reads a line from
+the standard input (line 19), parses it into tokens (line 22), and
+executes the command.
+.PP
+The function call
+.CW sys->tokenize
+is worth discussing as an example of style.
+It takes two strings as arguments.
+The characters in the second string are interpreted as separators
+of tokens in the first string.
+It returns a tuple whose first member is the number of
+tokens found, and whose second is a list of strings
+containing the tokens found: its declaration is
+.P1
+ tokenize: fn (s: string, sep: string): (int, list of string);
+.P2
+In the example, the second argument is
+\f(CW" \et\en"\fP,
+so that the routine returns the number of, and a list of,
+`words' separated by blanks, tabs, and new-lines.
+The free use of strings, lists, and tuple-returning
+functions is common in Limbo.
+.PP
+The
+.CW sys->read
+routine gathers an array of bytes into
+.CW buf .
+Thus the expression for the first argument of
+.CW sys->tokenize
+converts this array to a string by slicing the
+array with
+.CW [0:n] ,
+using the actual number of bytes
+gathered by the
+.CW read ,
+and using a cast.
+.PP
+At lines 23-24, if there were any words found,
+.CW exec
+is called:
+.P1
+27 exec(ctx: ref Draw->Context, args: list of string)
+28 {
+29 c: Command;
+30 cmd, file: string;
+
+31 cmd = hd args;
+
+32 file = cmd + ".dis";
+33 c = load Command file;
+34 if(c == nil)
+35 c = load Command "/dis/"+file;
+
+36 if(c == nil) {
+37 sys->print("%s: not found\en", cmd);
+38 return;
+39 }
+40 c->init(ctx, args);
+41 }
+.P2
+On lines 31 and 32 of
+.CW exec ,
+.CW cmd
+is set to the first of the words in the argument list,
+and the string
+.CW .dis
+is concatenated to it (to account for the fact that Limbo
+object program files are conventionally named using this suffix).
+On line 33 an attempt is made to load the named module
+from the derived file name; it will fail if the file
+does not exist.
+The attempt will succeed,
+and a non-nil handle assigned to
+.CW c ,
+if the file is found, and if
+the module stored in that file does in fact implement the
+.CW Command
+module type.
+In case this fails, lines 34-35 make another attempt, after prefixing
+.CW /dis/
+to the file name.
+.PP
+If either attempt to get a handle to the named module
+succeeds,
+.CW c
+will contain a valid handle to it; line 40 calls its
+.CW init
+function, passing it the whole argument list.
+When it returns, the
+.CW exec
+function returns, and the main loop resumes.
+.NH 2
+Infrared remote control
+.PP
+This example shows two instances of a module
+for interfacing to a TV remote control; one
+is for the real remote, which in this case
+is connected to a serial port on a set-top
+box, and the other is simulated for testing
+programs running on a regular operating
+system.
+The techniques of special interest are the
+dynamic use of modules and the communication
+using a channel.
+.PP
+The module is used by creating a channel and passing
+it to the module's
+.CW init
+function,
+which returns a success/error indicator and starts an
+asynchronous process to read the remote control.
+The user of the module executes a receive
+on the channel whenever it wishes to accept
+a button-push.
+.PP
+The (abridged) module declaration is
+.P1
+Ir: module
+{
+ # Codes buttons on IR remote control
+ Zero: con 0;
+ One: con 1;
+ . . .
+ Mute: con 23;
+ Error: con 9999;
+
+ init: fn(chan of int): int;
+ PATH: con "/dis/ir.dis";
+ SIMPATH: con "/dis/irsim.h";
+};
+.P2
+The implementation for the `real' remote control is
+.P1
+implement Ir;
+
+include "ir.m";
+include "sys.m";
+FD, Dir: import Sys;
+
+sys: Sys;
+
+init(keys: chan of int): int
+{
+ cfd, dfd: ref FD;
+
+ sys = load Sys Sys->PATH;
+
+ cfd = sys->open("/dev/eia1ctl", sys->OWRITE);
+ if(cfd == nil)
+ return -1;
+ sys->fprint(cfd, "b9600");
+
+ dfd = sys->open("/dev/eia1", sys->OREAD);
+ cfd = nil;
+
+ spawn reader(keys, dfd);
+ return 0;
+}
+.P2
+The
+.CW init
+routine accepts a
+.CW chan
+argument; it will be used by the module to
+send codes for the buttons pressed by the user.
+In this routine, the calls to
+.CW sys->open
+and
+.CW sys->fprint
+open and set up the device data and control files
+.CW /dev/eia1
+and
+.CW /dev/eia1ctl
+used to communicate with the device itself.
+The important step is at the end: the
+.CW spawn
+statement creates a new,
+asynchronous task to read the device, using a routine
+that is passed the communications channel and the
+FD for the device:
+.P1
+reader(keys: chan of int, dfd: ref FD)
+{
+ n, ta, tb: int;
+ dir: Dir;
+ b1:= array[1] of byte;
+ b2:= array[1] of byte;
+
+ # find the number of bytes already
+ # queued and flush that many
+ (n, dir) = sys->fstat(dfd);
+ if(n >= 0 && dir.length > 0) {
+ while(dir.length) {
+ n = sys->read(dfd,
+ array[dir.length] of byte,
+ dir.length);
+ if(n < 0)
+ break;
+ dir.length -= n;
+ }
+ }
+.P2
+.P1
+loop: for(;;) {
+ n = sys->read(dfd, b1, len b1);
+ if(n <= 0)
+ break;
+ ta = sys->millisec();
+ # Button pushes are pairs of characters
+ # that arrive closer together than
+ # 200 ms. Longer than that is likely
+ # to be noise.
+ for(;;) {
+ n = sys->read(dfd, b2, 1);
+ if(n <= 0)
+ break loop;
+ tb = sys->millisec();
+ if(tb - ta <= 200)
+ break;
+ ta = tb;
+ b1[0] = b2[0];
+ }
+ # map the character pair; the significant
+ # bits are the lowest 5.
+ case ((int b1[0]&16r1f)<<5) | (int b2[0]&16r1f) {
+ 975 => n = Ir->Zero;
+ 479 => n = Ir->One;
+ . . .
+ 791 => n = Ir->Mute;
+ * => n = Ir->Error;
+ }
+ # found a button-push; send the value
+ keys <-= n;
+ }
+ keys <-= Ir->Error;
+}
+.P2
+The code in the middle is related to noise-filtering
+and is uninteresting in detail except as it illustrates
+some of the methods provided by the
+.CW Sys
+module; the crucial actions are found at the bottom,
+where the routine sends either
+a true button-push or an error code over the channel to
+the module's client.
+.PP
+Here is another implementation of the same interface.
+Its
+.CW init
+function performs the same kind of initialization
+as the other version, but using the operating system's
+keyboard files
+.CW /dev/cons
+and
+.CW /dev/consctl .
+In the Inferno environment, operations corresponding to the Unix
+`stty' primitive are accomplished by writing messages to
+a control file associated with the file that handles the data.
+.P1
+implement Ir;
+
+include "ir.m";
+include "sys.m";
+FD: import Sys;
+
+sys: Sys;
+cctlfd: ref FD;
+
+init(keys: chan of int): int
+{
+ dfd: ref FD;
+
+ sys = load Sys Sys->PATH;
+
+ cctlfd = sys->open("/dev/consctl", sys->OWRITE);
+ if(cctlfd == nil)
+ return -1;
+ sys->write(cctlfd, array of byte "rawon", 5);
+
+ dfd = sys->open("/dev/cons", sys->OREAD);
+ if(dfd == nil)
+ return -1;
+
+ spawn reader(keys, dfd);
+ return 0;
+}
+.P2
+A fine point: the variable
+.CW cctlfd
+that contains the FD for the control device is
+declared external to the
+init function, even though it appears to be used
+only inside it.
+Programming cleanliness suggests that
+its declaration be moved inside, but here that
+won't work;
+device control files
+in Inferno retain settings like `raw mode' only
+while they remain open.
+If
+.CW cctlfd
+were declared inside
+.CW init ,
+then returning from
+.CW init
+would destroy the last reference to the FD for the control file,
+and the device would be closed automatically.
+.PP
+The reader function for this module has the same structure as the first
+example, but doesn't have to worry about a noisy infrared detector:
+.P1
+reader(keys: chan of int, dfd: ref FD)
+{
+ n: int;
+ b:= array[1] of byte;
+
+ for(;;) {
+ n = sys->read(dfd, b, 1);
+ if(n != 1)
+ break;
+ case int b[0] {
+ '0' => n = Ir->Zero;
+ '1' => n = Ir->One;
+ . . .
+ 16r7f => n = Ir->Mute;
+ * => n = Ir->Error;
+ }
+ keys <-= n;
+ }
+ keys <-= Ir->Error;
+}
+.P2
+The following module can be used to test the above code.
+It simply prints the name of the button that was pressed.
+.P1
+implement Irtest;
+
+include "sys.m";
+include "draw.m";
+FD: import Sys;
+include "ir.m";
+
+Irtest: module
+{
+ init: fn(nil: ref Draw->Context, nil: list of string);
+};
+ir: Ir;
+sys: Sys;
+.P2
+.P1
+init(nil: ref Draw->Context, nil: list of string)
+{
+ c: int;
+ stderr: ref FD;
+ irchan := chan of int;
+
+ sys = load Sys Sys->PATH;
+ stderr = sys->fildes(2);
+
+ # If the real IR remote application can
+ # be found, use it, otherwise use the simulator:
+ ir = load Ir Ir->PATH;
+ if(ir == nil)
+ ir = load Ir Ir->SIMPATH;
+ if(ir == nil) {
+ # %r format code means the last system error string
+ sys->fprint(stderr, "load ir: %r\en");
+ return;
+ }
+ if(ir->init(irchan) != 0) {
+ sys->fprint(stderr, "Ir.init: %r\en");
+ return;
+ }
+ names := array[] of {
+ "Zero",
+ "One",
+ . . .
+ "Mute",
+ };
+ for(;;) {
+ c = <-irchan;
+ if(c == ir->Error)
+ sys->print("Error %d\en", c);
+ else
+ sys->print("%s\en", names[c]);
+ }
+}
+.P2
+Finally, here is a snippet from a movie application that
+uses the IR module; it demonstrates how
+.CW alt
+is useful for dealing with multiple events.
+This is only one of the functions of the
+movie module, so not everything is defined.
+It uses the
+.CW Mpeg
+module, which actually
+copies the MPEG data stream to the screen
+asynchronously.
+Its
+.CW play
+function takes, as one of its arguments,
+a channel;
+before starting to play it writes a
+string on the channel.
+An empty string indicates success at
+locating the movie; a non-empty
+string contains an error message.
+When it finishes, it writes another string.
+.P1
+movie(entry: ref Dbinfo, cc: chan of int)
+{
+ i: int;
+ m: Mpeg;
+ b: ref Image;
+
+ m = load Mpeg Mpeg->PATH;
+ if (m == nil)
+ return;
+ # make a place on the screen
+ w := screen.window(screen.image.r);
+
+ mr := chan of string;
+ s := m->play(w, 1, w.r, entry.movie, mr);
+ if(s != "")
+ return;
+ # wait for the end of the movie
+ # while watching for button pushes
+ for(;;) {
+ alt {
+ <-mr =>
+ return;
+ i = <-cc =>
+ case i {
+ Ir->Select =>
+ m->ctl("stop");
+ Ir->Up or Ir->Dn =>
+ m->ctl("pause");
+ }
+ }
+ }
+}
+.P2
+.NH 2
+Monitors
+.PP
+Statically allocated storage within a module is accessible to
+all the functions of that module,
+and there is no explicit mechanism in Limbo for synchronizing
+concurrent updates to this storage from several tasks.
+However, it is straightforward to build a variety of concurrency-control
+mechanisms by using channel communications.
+.PP
+An example is a module that implements a
+.CW Monitor
+abstract data type.
+Each instance of
+.CW Monitor
+has a
+.CW lock
+and an
+.CW unlock
+operation;
+calling
+.CW lock
+delays if another task holds the lock; calling
+.CW unlock
+releases the lock and enables any other task attempting
+to execute
+.CW lock .
+.P1
+implement Monitors;
+
+Monitors: module
+{
+ Monitor: adt {
+ create: fn(): Monitor;
+ lock: fn(m: self Monitor);
+ unlock: fn(m: self Monitor);
+ ch: chan of int;
+ };
+};
+.P2
+.P1
+Monitor.create(): Monitor
+{
+ m := Monitor(chan of int);
+ spawn lockproc(m.ch);
+ return m;
+}
+.P2
+.P1
+Monitor.lock(m: self Monitor)
+{
+ m.ch <- = 0;
+}
+.P2
+.P1
+Monitor.unlock(m: self Monitor)
+{
+ <- m.ch;
+}
+.P2
+.P1
+lockproc(ch: chan of int)
+{
+ for (;;) {
+ <- ch; # wait for someone to lock
+ ch <- = 0; # wait for someone to unlock
+ }
+}
+.P2
+It would be used like this:
+.P1
+mp: Mon;
+Monitor: import mp;
+mp = load Mon "...";
+l := Monitor.create();
+\. . .
+l.lock();
+# region of code to be protected;
+# only one thread can execute here at once.
+l.unlock();
+.P2
+The
+.CW create
+method of
+.CW Monitor
+allocates an instance of a
+.CW Monitor
+containing an initialized channel.
+It also creates a thread executed in the
+.CW lockproc
+routine, which repeatedly reads from the channel,
+then writes on it.
+The values transmitted over the channel are of no
+interest; it is the pure fact of communication that is put to use.
+The
+.CW lock
+routine sends a message; in the idle state, the
+.CW lockproc
+thread reads it and the sender proceeds.
+Meanwhile,
+.CW lockproc
+tries to send a message over the same channel.
+If another thread attempts to
+.CW lock ,
+there is no reader for the channel, and so its transmission will block.
+At some point, the thread that gained the lock
+calls
+.CW unlock ,
+which receives from the channel.
+Depending on timing, this reception enables execution of either
+.CW lockproc
+or one of the threads attempting to send via
+.CW lock .
+.PP
+There is a simpler implementation of
+.CW Monitor ,
+using a buffered channel.
+The
+.CW create
+operation simply allocates a channel with a one-element buffer:
+.P1
+Monitor.create(): Monitor
+{
+ return Monitor(chan[1] of int);
+}
+.P2
+The
+.CW lock
+and
+.CW unlock
+operations have the same implementation.
+Because of the buffer, when a process locks an unlocked
+.CW Monitor ,
+the send succeeds but fills the channel.
+Subsequent attempts to
+.CW lock
+will therefore block as long as the channel is full.
+.CW Unlock
+removes the value from the channel, making it empty,
+and allowing another
+.CW lock
+to proceed.
+The
+.CW lockproc
+is not needed.
+Note that a program using the module would not need to be recompiled to
+use the new implementation, because the module's signature and use
+remains the same.
+This is the implementation of the
+.CW Lock
+module in the Limbo library for Inferno.
+.PP
+Limbo channels are usually unbuffered:
+a sender blocks until there
+is a receiver, and processes synchronise at each communication.
+Buffered channels are used sparingly in Limbo programs, typically to improve throughput or,
+less often, in specialized ways as in the monitor example above.
+.NH 2
+Guarding sends and receives
+.PP
+In some applications, a process takes input from one channel,
+and sends it on to another channel, possibly having transformed it.
+In case the input and output processes run at different rates,
+the process itself acts as a buffer, holding a queue of values internally.
+If the input process were faster than the output process, the queue
+would accumulate values faster than they are consumed, exhausting memory.
+To prevent that, when the queue reaches a specified limit, the process should guard against
+receiving from the input channel, but continue sending to the output channel.
+Conversely, when the queue is empty, it should not attempt to send.
+The
+.CW alt
+statement allows a process to choose between sending and receiving based on
+which channels are ready, but the process must also account for the current state
+of the queue.
+This example shows a way to make a buffered
+channel of strings from an unbuffered channel.
+It is written as a module whose
+.CW bufchan
+function takes a
+.CW chan
+.CW of
+.CW string
+and a size as argument, and returns a new channel;
+it creates an asynchronous task that accepts input from the argument
+channel and saves up to
+.CW size
+strings, meanwhile trying to send them to its user.
+.P1
+implement Bufchan;
+Bufchan: module {
+ bufchan: fn(c: chan of string, size: int): chan of string;
+};
+
+xfer(oldchan, newchan: chan of string, size: int)
+{
+ temp := array[size] of string;
+ fp := 0; # first string in buffer
+ n := 0; # number of strings in buffer
+ dummy := chan of string;
+ sendch, recvch: chan of string;
+ s: string;
+
+ for (;;) {
+ sendch = recvch = dummy;
+ if (n > 0)
+ sendch = newchan;
+ if (n < size)
+ recvch = oldchan;
+ alt {
+ s = <-recvch =>
+ temp[(fp+n)%size] = s;
+ n++;
+
+ sendch <- = temp[fp] =>
+ temp[fp++] = nil;
+ n--;
+ if (fp>=size)
+ fp -= size;
+ }
+ }
+}
+.P2
+.P1
+bufchan(oldchan: chan of string, size: int): chan of string
+{
+ newchan := chan of string;
+ spawn xfer(oldchan, newchan, size);
+ return newchan;
+}
+.P2
+The module is somewhat specialized, but it illustrates
+useful programming techniques.
+The most interesting occurs in
+.CW xfer ,
+which does the work.
+The problem
+.CW xfer
+faces is that it doesn't want to receive input when its
+buffer is full, nor to try to send when it has nothing to
+transmit.
+The solution here is to use a dummy channel
+on which nothing is ever sent or received; in the
+.CW alt
+statement,
+that channel substitutes for the real input channel
+when the buffer is full, and for the output channel
+when the buffer is empty.
+.PP
+The module could be used in the following way:
+.P1
+Bufchan: module {
+ PATH: con "/dis/lib/bufchan.dis";
+ bufchan: fn(c: chan of string, size: int): chan of string;
+};
+\. . .
+bufc := load Bufchan Bufchan->PATH;
+sourcech := chan of string;
+
+# ... (here, hand off sourcech to a process that
+# reads strings from it and copies them to ch)
+ch: chan of string = bufc->bufchan(sourcech, 10);
+\. . .
+s := <- ch;
+\. . .
+.P2
+.NH 1
+Syntax summary
+.PP
+This section summarizes the grammar of Limbo
+above the lexical level; constants and identifiers
+are left undefined.
+.PP
binary files /dev/null b/doc/limbo/limbo.pdf differ
--- /dev/null
+++ b/doc/limbo/limbo.rc
@@ -1,0 +1,20 @@
+#!/bin/rc
+cat limbo.ms synsum | awk 'BEGIN { inside = 0 }
+
+ { if ($1==".s1") {
+ inside = 1;
+ }
+ if ($1==".s2") {
+ inside = 0;
+ }
+ if (inside) {
+ gsub(/C/, "\\f(CW")
+ gsub(/ID/, "@D")
+ gsub(/I/, "\\fI")
+ gsub(/@D/, "ID")
+ gsub(/O/, "\\fI\\s-3\\v''+2p''opt\\v''-2p''\\s+3")
+ }
+ print $0
+ }
+'
+
--- /dev/null
+++ b/doc/limbo/mkfile
@@ -1,0 +1,12 @@
+<../fonts
+
+all:V: limbo.pdf addendum.pdf
+
+limbo.ps:D: limbo.ms limbo.rc synsum mkfile
+ rc limbo.rc | troff -mpm | dpost >limbo.ps
+
+%.pdf: %.ps
+ ps2pdf <$stem.ps >$stem.pdf
+
+addendum.ps:D: addendum.ms mkfile
+ cat addendum.ms |troff -mpm | dpost >$target
--- /dev/null
+++ b/doc/limbo/synsum
@@ -1,0 +1,335 @@
+.s1
+program:
+ Cimplement Iidentifier-listC ; Itop-declaration-sequence
+.s2
+.s1
+top-declaration-sequence:
+ top-declaration
+ top-declaration-sequence top-declaration
+.s2
+.s1
+top-declaration:
+ declaration
+ identifier-listC := IexpressionC ;I
+ identifier-listC = IexpressionC ;I
+ C( Iidentifier-listC ) := IexpressionC ;I
+ module-declaration
+ function-definition
+ adt-declaration
+.s2
+.s1
+declaration:
+ identifier-listC : ItypeC ;I
+ identifier-listC : ItypeC = IexpressionC ;I
+ identifier-listC : con IexpressionC ;I
+ Iidentifier-listC : import Iidentifier C;I
+ identifier-listC : typeI typeC ;I
+ identifier-listC : exceptionI tuple-typeO
+ Cinclude Istring-constantC ;I
+.s2
+.s1
+identifier-list:
+ identifier
+ identifier-listC , Iidentifier
+.s2
+.s1
+expression-list:
+ expression
+ expression-listC , Iexpression
+.s2
+.s1
+type:
+ data-type
+ function-type
+.s2
+.s1
+data-type:
+ CbyteI
+ CintI
+ CbigI
+ CrealI
+ CstringI
+ tuple-type
+ Carray of Idata-type
+ Clist of Idata-type
+ Cchan of Idata-type
+ adt-type
+ Cref Iadt-type
+ Cref Ifunction-type
+ module-type
+ module-qualified-type
+ type-name
+.s2
+.s1
+tuple-type:
+ C( Idata-type-listC )I
+.s2
+.s1
+data-type-list:
+ data-type
+ data-type-list C,I data-type
+.s2
+.s1
+adt-type:
+ identifier
+ module-qualified-type
+.s2
+.s1
+module-type:
+ identifier
+.s2
+.s1
+module-qualified-type:
+ identifier C->I identifier
+.s2
+.s1
+type-name:
+ identifier
+.s2
+.s1
+function-type:
+ Cfn Ifunction-arg-ret
+.s2
+.s1
+function-arg-ret:
+ C( Iformal-arg-listOC ) IraisesO
+ C( Iformal-arg-listOC ) : Idata-type raisesO
+.s2
+.s1
+formal-arg-list:
+ formal-arg
+ formal-arg-listC , Iformal-arg
+.s2
+.s1
+formal-arg:
+ nil-or-ID-listC : Itype
+ nil-or-IDC : self refO Iidentifier
+ nil-or-IDC : self Iidentifier
+ C*I
+.s2
+.s1
+nil-or-ID-list:
+ nil-or-ID
+ nil-or-ID-list C, Inil-or-ID
+.s2
+.s1
+nil-or-ID:
+ identifier
+ CnilI
+.s2
+.s1
+raises:
+ Craises ( Inil-or-ID-listC )I
+ CraisesI nil-or-ID
+.s2
+.s1
+module-declaration:
+ IidentifierC : module { Imod-member-listOC } ;I
+.s2
+.s1
+mod-member-list:
+ mod-member
+ mod-member-list mod-member
+.s2
+.s1
+mod-member:
+ identifier-listC : Ifunction-typeC ;I
+ identifier-listC : Idata-typeC ;I
+ adt-declarationC I
+ identifier-listC : con Iexpression C;I
+ identifier-listC : type Itype C;I
+.s2
+.s1
+adt-declaration:
+ IidentifierC : adt { Iadt-member-listOC } ;I
+.s2
+.s1
+adt-member-list:
+ adt-member
+ adt-member-list adt-member
+.s2
+.s1
+adt-member:
+ identifier-listC : cyclicO Idata-typeC ;I
+ identifier-listC : con IexpressionC ;I
+ identifier-listC : Ifunction-typeC ;I
+ Cpick { Ipick-member-listC }I
+.s2
+.s1
+pick-member-list:
+ pick-tag-listC =>I
+ pick-member-list pick-tag-listC =>I
+ pick-member-list identifier-listC : cyclicO Idata-typeC ;I
+.s2
+.s1
+pick-tag-list:
+ identifier
+ pick-tag-listC or Iidentifier
+.s2
+.s1
+function-definition:
+ function-name-part function-arg-retC { IstatementsC }I
+.s2
+.s1
+function-name-part:
+ identifier
+ function-name-partC . Iidentifier
+.s2
+.s1
+statements:
+ (empty)
+ statements declaration
+ statements statement
+.s2
+.s1
+statement:
+ expressionC ;I
+ C;I
+ C{ IstatementsC }I
+ Cif ( IexpressionC ) Istatement
+ Cif ( IexpressionC ) IstatementC else Istatement
+ labelO Cwhile ( IexpressionOC ) Istatement
+ labelO Cdo IstatementC while ( IexpressionOC ) ;I
+ labelO Cfor ( IexpressionOC ; IexpressionOC ; IexpressionOC ) Istatement
+ labelO Ccase IexpressionC { Iqual-statement-sequenceC }I
+ labelO Calt { Iqual-statement-sequenceC }I
+ labelO Cpick IidentifierC := IexpressionC { Ipqual-statement-sequenceC }I
+ Cbreak IidentifierOC ;I
+ Ccontinue IidentifierOC ;I
+ Creturn IexpressionOC ;I
+ Cspawn ItermC ( Iexpression-listOC ) ;I
+ Cexit ;I
+ Craise IexpressionOC ;I
+ C{ IstatementsC } exceptionI identifierOC{ Iqual-statement-sequenceC }I
+.s2
+.s1
+label:
+ identifier C:I
+.s2
+.s1
+qual-statement-sequence:
+ qual-listC =>I
+ qual-statement-sequence qual-listC =>I
+ qual-statement-sequence statement
+ qual-statement-sequence declaration
+.s2
+.s1
+qual-list:
+ qualifier
+ qual-listC or Iqualifier
+.s2
+.s1
+qualifier:
+ expression
+ expressionC to Iexpression
+ C*I
+.s2
+.s1
+pqual-statement-sequence:
+ pqual-listC =>I
+ pqual-statement-sequence pqual-listC =>I
+ pqual-statement-sequence statement
+ pqual-statement-sequence declaration
+.s2
+.s1
+pqual-list:
+ pqualifier
+ pqual-listC or Ipqualifier
+.s2
+.s1
+pqualifier:
+ identifier
+ C*I
+.s2
+.s1
+expression:
+ binary-expression
+ lvalue-expression assignment-operator expression
+ C( Ilvalue-expression-listC ) = Iexpression
+ send-expression
+ declare-expression
+ load-expression
+.s2
+.s1
+binary-expression:
+ monadic-expression
+ binary-expression binary-operator binary-expression
+.s2
+.s1
+binary-operator: one of
+ C** * / % + - << >> < > <= >= == != & ^ | :: && ||I
+.s2
+.s1
+assignment-operator: one of
+ C= &= |= ^= <<= >>= += -= *= /= %=I
+.s2
+.s1
+lvalue-expression:
+ identifier
+ CnilI
+ termC [ IexpressionC ]I
+ termC [ IexpressionC : ]I
+ termC . Iidentifier
+ C( Ilvalue-expression-listC )I
+ C* Imonadic-expression
+.s2
+.s1
+lvalue-expression-list:
+ lvalue-expression
+ lvalue-expression-listC , Ilvalue-expression
+.s2
+.s1
+expression:
+ term
+ monadic-operator monadic-expression
+ Carray [ IexpressionC ] of Idata-type
+ Carray [ IexpressionOC ] of { Iinit-listC }I
+ Clist of { Iexpression-listC }I
+ Cchan of Idata-type
+ Cchan [ IexpressionOC ] of Idata-type
+ data-type monadic-expression
+.s2
+.s1
+term:
+ identifier
+ constant
+ real-constant
+ string-constant
+ CnilI
+ C( Iexpression-listC )I
+ termC . Iidentifier
+ termC -> Iterm
+ termC ( Iexpression-listOC )I
+ termC [ IexpressionC ]I
+ termC [ IexpressionC : IexpressionC ]I
+ termC [ IexpressionC : ]I
+ termC ++I
+ termC --I
+.s2
+.s1
+monadic-operator: one of
+ C+ - ! ~ ref * ++ -- <- hd tl len tagofI
+.s2
+.s1
+init-list:
+ element
+ init-listC , Ielement
+.s2
+.s1
+element:
+ expression
+ expressionC => Iexpression
+ C* => Iexpression
+.s2
+.s1
+send-expression:
+ lvalue-expressionC <- = Iexpression
+.s2
+.s1
+declare-expression:
+ lvalue-expressionC := Iexpression
+.s2
+.s1
+load-expression:
+ Cload Iidentifier expression
+.s2
binary files /dev/null b/doc/limbotk/f1.gif differ
--- /dev/null
+++ b/doc/limbotk/f1.ps
@@ -1,0 +1,234 @@
+%!
+%%BoundingBox: 0 0 2691 216
+/picstr 299 string def
+2691 216 scale
+299 24 8
+[ 299 0 0 -24 0 24 ]
+{ currentfile picstr readhexstring pop }
+false 3 colorimage
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffff808080ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080
+808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080
+808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080
+808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080
+808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080
+808080808080808080808080808080808080808080808080808080ffffffc0c0c0c0c0c0ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0ffffffc0c0c0c0c0c0ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080ffffffffffff
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0ffffff
+c0c0c0c0c0c0ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0ffffffc0c0c0c0c0c0ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0ffffffc0c0c0c0c0c0ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080ffffff
+ffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+ffffffc0c0c0c0c0c0ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000000000000000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000000000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000000000c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0ffffffc0c0c0c0c0c0ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0
+000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0000000000000000000c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0ffffffc0c0c0c0c0c0ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0000000000000c0c0c0000000000000000000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080
+ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000000000000000c0c0c0c0c0c0000000000000c0c0c0000000000000c0c0c0c0c0c0c0c0c0c0c0c0000000000000000000
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000000000000000c0c0c0c0c0c0000000c0c0c0000000000000000000000000c0c0c0c0c0c0000000000000000000c0c0c0000000c0c0c0c0c0c0
+c0c0c0c0c0c0000000000000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0ffffffc0c0c0c0c0c0ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000000000000000000000c0c0c0c0c0c0c0c0c0000000000000c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000000000000000c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0000000000000c0c0c0000000
+000000c0c0c0c0c0c0000000000000c0c0c0000000000000c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0000000c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0
+c0c0c0000000c0c0c0c0c0c0000000c0c0c0000000000000000000000000c0c0c0000000000000c0c0c0c0c0c0000000000000c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0ffffffc0c0c0c0c0c0ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000000000
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000
+000000c0c0c0c0c0c0c0c0c0000000000000000000000000000000c0c0c0000000000000c0c0c0c0c0c0000000000000c0c0c0000000000000c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0000000c0c0c0c0c0c0000000c0c0c0000000c0c0c0000000000000000000000000c0c0c0c0c0c0000000c0c0c0000000000000000000000000c0c0c0000000000000000000000000000000000000c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0ffffffc0c0c0c0c0c0ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+808080ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000000000c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000000000c0c0c0c0c0c0000000000000c0c0c0000000000000c0c0c0c0c0c0
+000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0000000c0c0c0000000000000000000c0c0c0c0c0c0000000c0c0c0c0c0c0000000c0c0c0000000000000000000000000
+c0c0c0000000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0ffffffc0c0c0c0c0c0ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0000000000000c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0000000000000c0c0c0c0c0c0000000c0c0c0
+000000000000c0c0c0c0c0c0000000000000c0c0c0c0c0c0000000c0c0c0000000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0000000000000000000000000000000
+c0c0c0000000000000c0c0c0c0c0c0000000c0c0c0000000000000000000000000c0c0c0c0c0c0000000000000c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0ffffffc0c0c0c0c0c0ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000000000000000000000c0c0c0c0c0c0c0c0c0000000c0c0c0
+c0c0c0000000000000c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000000000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000
+000000000000c0c0c0c0c0c0c0c0c0c0c0c0000000000000000000c0c0c0c0c0c0000000000000c0c0c0c0c0c0000000000000c0c0c0c0c0c0c0c0c0000000c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0000000000000c0c0c0000000000000c0c0c0000000000000c0c0c0000000c0c0c0000000000000000000000000c0c0c0c0c0c0c0c0c0000000000000000000c0c0c0c0c0c0c0c0c0c0c0c0
+000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0ffffffc0c0c0c0c0c0ffffffffffffc0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0808080ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0ffffffc0c0c0c0c0c0ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0ffffffc0c0c0c0c0c0ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0ffffffc0c0c0c0c0c0ffffffffffffc0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0808080ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0ffffffc0c0c0c0c0c0ffffffffffff808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080
+808080808080808080808080808080808080808080808080808080808080808080808080808080808080ffffffffffff808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080
+808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0c0c0c0c0c0ffffff808080808080808080808080808080808080808080808080808080808080808080808080808080
+808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080ffffff808080808080808080808080808080808080
+808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+showpage
binary files /dev/null b/doc/limbotk/f2.gif differ
--- /dev/null
+++ b/doc/limbotk/f2.ps
@@ -1,0 +1,2044 @@
+%!
+%%BoundingBox: 0 0 318 216
+/picstr 310 string def
+318 216 scale
+310 210 8
+[ 310 0 0 -210 0 210 ]
+{ currentfile picstr readhexstring pop }
+false 3 colorimage
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffff999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+9999990000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+999999ffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd9999999999990000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999ffffffffffffdddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd9999999999990000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bbffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999ffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddd9999999999990000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffdddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddd999999ffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd9999999999990000bb999999999999ffffffffffff0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffdddddddddddddddddddddddd000000000000000000000000000000000000000000000000000000000000000000dddddd
+dddddddddddd999999999999ffffffdddddddddddddddddd000000000000000000000000000000000000000000000000000000000000000000000000000000dddddddddddddddddd999999ffffffffffffdddddddddddddddddddddddd000000
+000000dddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddd9999999999990000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffffffffffffffffffffffffff
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffffffff
+ffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bbffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddd000000dddddddddddd000000dddddd000000dddddddddddddddddd999999999999ffffffdddddddddddddddddd000000dddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000dddddddddddddddddd999999ffffffffffffdddddddddddddddddddddddd000000000000000000dddddddddddddddddddddddd000000000000000000dddddd
+dddddddddddddddddd9999999999990000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffff0000bbffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffdddddddddddddddddddddddd
+dddddddddddddddddddddddddddddd000000dddddddddddd000000dddddd000000dddddddddddddddddd999999999999ffffffdddddddddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+000000dddddddddddddddddd999999ffffffffffffdddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddd9999999999990000bb999999999999ffffffffffff
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffff0000bb0000bb0000bb0000bb0000bbffffffffffffffffff0000bb0000bb0000bbffffff0000bb0000bbffffffffffff0000bb0000bb0000bbffffffffffff0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffff0000bbffffffffffff0000bb0000bb0000bbffffff0000bb0000bbffffffffffff0000bb0000bb0000bbffffffffffff0000bb0000bbffffffffffff0000bb
+0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffffffffffffff0000bb0000bb0000bbffffffffffffffffff0000bb0000bb0000bb0000bbffffff0000bb0000bbffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddd000000dddddddddddd000000dddddd
+000000dddddddddddddddddd999999999999ffffffdddddddddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000dddddddddddddddddd999999ffffffffffffdddddddddddddddddd
+dddddddddddddddddd000000000000dddddddddddd000000000000dddddddddddddddddddddddddddddddddddd9999999999990000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffff
+0000bb0000bb0000bb0000bbffffff0000bb0000bbffffffffffff0000bb0000bbffffffffffff0000bbffffff0000bb0000bb0000bb0000bbffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffff
+ffffffffffff0000bb0000bb0000bb0000bb0000bbffffffffffff0000bb0000bbffffff0000bbffffffffffff0000bb0000bbffffff0000bbffffffffffff0000bbffffff0000bb0000bb0000bb0000bbffffff0000bb0000bb0000bb0000bb
+0000bb0000bbffffff0000bb0000bb0000bbffffff0000bb0000bb0000bbffffffffffff0000bbffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddd000000dddddddddddd000000dddddd000000dddddddddddddddddd999999999999ffffffdddddddddddddddddd
+000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000dddddddddddddddddd999999ffffffffffffdddddddddddddddddddddddddddddddddddddddddd000000000000000000000000dddddddddddd
+dddddddddddddddddddddddddddddd9999999999990000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffff0000bb0000bb0000bb0000bbffffffffffffffffffffffffffffff0000bb
+0000bb0000bbffffffffffff0000bb0000bb0000bb0000bb0000bbffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffff0000bbffffff0000bb0000bb0000bb0000bbffffff0000bb0000bb
+0000bb0000bb0000bbffffffffffff0000bb0000bbffffff0000bbffffffffffff0000bbffffffffffff0000bb0000bb0000bbffffffffffffffffffffffff0000bb0000bb0000bbffffffffffffffffffffffffffffff0000bb0000bb0000bb
+ffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffdddddddddddd
+dddddddddddddddddddddddddddddddddddddddddd000000dddddddddddd000000dddddd000000dddddddddddddddddd999999999999ffffffdddddddddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddd000000dddddddddddddddddd999999ffffffffffffdddddddddddddddddddddddddddddddddddddddddd000000000000000000000000dddddddddddddddddddddddddddddddddddddddddd9999999999990000bb999999999999
+ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffff0000bb0000bb0000bb0000bbffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffff0000bb0000bb0000bb0000bb0000bbffffff
+ffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffff0000bbffffffffffff0000bb0000bb0000bbffffff0000bb0000bb0000bb0000bb0000bbffffffffffff0000bb0000bbffffff0000bbffffff
+ffffff0000bbffffffffffff0000bb0000bb0000bb0000bbffffffffffffffffffffffff0000bb0000bbffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffdddddddddddddddddddddddd000000000000000000000000000000000000dddddddddddd
+000000dddddd000000dddddddddddddddddd999999999999ffffffdddddddddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000dddddddddddddddddd999999ffffffffffffdddddd
+dddddddddddddddddddddddddddddddddddd000000000000000000000000dddddddddddddddddddddddddddddddddddddddddd9999999999990000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+ffffffffffff0000bb0000bb0000bb0000bbffffffffffff0000bb0000bbffffff0000bb0000bbffffff0000bb0000bbffffffffffff0000bb0000bb0000bbffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bbffffffffffff0000bbffffffffffff0000bb0000bb0000bbffffff0000bb0000bb0000bb0000bb0000bb0000bbffffff0000bbffffffffffff0000bb0000bbffffffffffff0000bbffffffffffff0000bb0000bbffffff0000bb0000bb
+0000bbffffff0000bb0000bb0000bbffffff0000bb0000bbffffff0000bb0000bb0000bbffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000dddddd000000dddddddddddddddddd999999999999ffffffdddddd
+dddddddddddd000000000000000000000000000000000000000000000000000000000000000000000000000000dddddddddddddddddd999999ffffffffffffdddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddd
+000000000000dddddddddddddddddddddddddddddd9999999999990000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffff0000bb0000bb0000bb0000bb0000bbffffffffffffffffff
+0000bb0000bb0000bbffffff0000bb0000bbffffffffffff0000bb0000bb0000bb0000bbffffffffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffffffffffffff0000bb0000bb0000bb0000bbffffff
+0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffff0000bb0000bb0000bbffffffffffff0000bbffffffffffff0000bb0000bb0000bbffffffffffffffffffffffff0000bb0000bb0000bbffffffffffffffffff0000bb0000bb
+0000bb0000bbffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffff
+dddddddddddddddddddddddd000000000000000000000000000000000000000000000000000000dddddd000000dddddddddddddddddd999999999999ffffffdddddddddddddddddd000000000000000000000000000000000000000000000000
+000000000000000000000000000000dddddddddddddddddd999999ffffffffffffdddddddddddddddddddddddd000000000000000000dddddddddddddddddddddddd000000000000000000dddddddddddddddddddddddd9999999999990000bb
+999999999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddd000000dddddddddddddddddd999999999999ffffffdddddddddddddddddd000000000000000000000000000000000000000000000000000000000000000000000000000000dddddddddddddddddd999999ffffff
+ffffffdddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddd9999999999990000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffdddddddddddddddddddddddd000000000000000000000000000000000000000000000000000000000000000000dddddddddddddddddd999999999999
+ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999ffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddd9999999999990000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+ffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999ffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999
+9999990000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+999999ffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd9999999999990000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999ffffffffffffdddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd9999999999990000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bbffffffffffff999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999ffffff999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999ffffffffffff999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+9999999999999999990000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffff999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999ffffff999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999ffffff9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999990000bb999999999999ffffffffffff0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb999999999999ffffffffffff999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999ffffffffffff999999ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffff
+999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999999999ffffffffffff999999dddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddd999999999999999999ffffffffffff999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999999999
+ffffffffffff999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999999999ffffffffffff999999dddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999999999ffffffffffff999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999
+999999999999ffffffffffff999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddd000000000000000000000000dddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000
+dddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddd000000000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999999999ffffffffffff999999dddddddddddddddddddddddddddddd
+dddddddddddd000000000000000000000000000000dddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000000000000000000000000000dddddddddddddddddddddddddddddddddddd000000dddddddddddddddddddddddd000000000000dddddddddddddddddddddddd
+000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000dddddddddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000dddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999999999ffffffffffff999999dddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddd000000
+000000000000000000dddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddd000000000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+000000000000dddddddddddddddddddddddddddddddddddddddddd000000000000000000dddddddddddd000000000000000000000000dddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+000000dddddddddddddddddd000000dddddddddddddddddd000000000000000000dddddddddddddddddddddddddddddd000000dddddddddddddddddd000000000000dddddd000000dddddddddddddddddddddddddddddddddddddddddddddddd
+dddddd999999999999999999ffffffffffff999999dddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddd000000000000
+dddddddddddddddddddddddd000000dddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddddddddd000000dddddd
+dddddd000000dddddddddddddddddddddddd000000000000dddddddddddddddddd000000000000000000000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000dddddddddddddddddd000000dddddddddddd000000000000dddddd
+000000000000dddddddddddddddddddddddd000000dddddddddddddddddd000000000000000000dddddd000000dddddddddddddddddddddddddddddddddddddddddddddddd999999999999999999ffffffffffff999999dddddddddddddddddd
+dddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddd000000000000dddddddddddddddddd000000000000dddddddddddd000000dddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000000000000000000000dddddddddddddddddd000000000000dddddddddddd000000dddddddddddddddddddddddd000000000000dddddddddddd
+dddddddddddd000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000000000000000000000000000dddddddddddd000000dddddddddddd000000000000dddddddddddddddddddddddd000000dddddddddddddddddd
+000000000000dddddddddddd000000000000dddddddddddddddddddddddddddddddddddddddddd999999999999999999ffffffffffff999999dddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddd
+dddddddddddddddddd000000000000dddddddddddddddddddddddddddddd000000000000dddddddddddddddddd000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddd000000000000dddddddddddddddddddddddddddddd000000000000dddddddddddd000000dddddddddddddddddddddddd000000000000dddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddd000000dddddddddddddddddd000000dddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddd000000dddddddddddddddddd000000000000dddddddddddd000000000000dddddddddddddddddddddddd
+dddddddddddddddddd999999999999999999ffffffffffff999999dddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddd
+000000000000dddddddddddddddddd000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddd000000
+000000dddddddddddd000000dddddddddddddddddddddddd000000000000dddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000dddddddddddddddddd000000dddddddddddd000000
+dddddddddddddddddddddddddddddddddddddddddddddddd000000dddddddddddddddddd000000000000dddddddddddd000000000000dddddddddddddddddddddddddddddddddddddddddd999999999999999999ffffffffffff999999dddddd
+dddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddd000000dddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddddddddd000000dddddd000000000000dddddddddddddddddddddddd000000000000
+dddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000dddddddddddddddddd000000dddddddddddd000000000000dddddddddddd000000dddddddddddddddddddddddd000000dddddd
+dddddddddddd000000000000dddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddd999999999999999999ffffffffffff999999dddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddd
+dddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddd000000000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddd000000000000000000000000000000dddddddddddddddddddddddd000000dddddd000000dddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddd000000000000000000dddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddd000000dddddddddddddddddd000000dddddddddddddddddd000000000000000000dddddddddddddddddddddddddddddd000000dddddddddddddddddd000000000000000000000000dddddddddddddddddddddddd
+dddddddddddddddddddddddddddddd999999999999999999ffffffffffff999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999999999ffffffffffff
+999999dddddddddddddddddddddddddddddddddddd000000000000000000000000000000000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000000000000000000000000000000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000000000000000000000000000000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999999999ffffffffffff999999dddddddddddddddddddddddddddddddddddd000000000000000000
+000000000000000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddd000000000000000000000000000000000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddd000000000000000000000000000000000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddd999999999999999999ffffffffffff999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999999999
+ffffffffffff999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999999999ffffffffffff999999dddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999999999ffffffffffff999999ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+999999999999ffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffffffffdddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999dddddd999999999999ffffffffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffffffffdddddd999999999999ffffffffffffffffffdddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffffffffdddddd999999999999ffffffffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffdddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+999999999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999dddddddddddddddddddddddd000000dddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddffffffffffffdddddd999999999999ffffffffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999dddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999dddddddddddddddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffffffffdddddd999999999999ffffffffffffffffffdddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddd999999dddddddddddddddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffffffffdddddd999999999999ffffffffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddd999999999999ffffffdddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddd999999999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999dddddddddddddddddddddddd000000dddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddffffffffffffdddddd999999999999ffffffffffffffffffdddddddddddddddddddddddddddddddddddd000000dddddddddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddd999999999999ffffffdddddddddddddddddddddddddddddddddddd000000dddddddddddd000000dddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999dddddddddddddddddddddddddddddd000000
+000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999dddddddddddddddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffffffffdddddd999999999999ffffffffffff
+ffffffdddddddddddddddddddddddddddddddddddd000000dddddddddddddddddddddddddddddddddddddddddd000000000000000000dddddddddddddddddd000000dddddd000000000000dddddddddddddddddddddddd000000000000000000
+000000dddddddddddddddddddddddddddddd999999999999ffffffdddddddddddddddddddddddddddddd000000dddddddddddddddddd000000000000dddddddddddd000000dddddd000000dddddddddddddddddddddddddddddd000000000000
+000000dddddddddddd000000000000dddddd000000000000dddddddddddddddddddddddddddddddddddd999999999999dddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddd000000000000000000000000
+dddddddddddd000000dddddd000000dddddd000000dddddddddddddddddddddddd000000000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddd999999dddddddddddddddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffffffffdddddd999999999999ffffffffffffffffffdddddddddddddddddddddddddddddddddddd000000000000dddddd
+dddddddddddddddddddddddd000000000000dddddd000000000000dddddddddddd000000000000dddddd000000000000dddddddddddd000000000000dddddd000000000000dddddddddddddddddddddddddddddd999999999999ffffffdddddd
+dddddddddddddddddddddddd000000dddddddddddddddddd000000000000dddddddddddd000000000000dddddd000000dddddddddddddddddd000000000000dddddd000000000000dddddd000000000000000000000000000000000000dddddd
+dddddddddddddddddddddddd999999999999dddddddddddddddddddddddddddddd000000dddddd000000dddddddddddddddddddddddddddddddddddddddddd000000000000dddddd000000000000000000000000dddddd000000dddddddddddd
+dddddd000000dddddddddddd000000dddddddddddddddddd000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999dddddddddddddddddddddddd000000
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddffffffffffffdddddd999999999999ffffffffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddd000000000000000000000000000000dddddd
+dddddd000000dddddddddddd000000000000dddddd000000000000dddddddddddd000000000000dddddddddddddddddddddddddddddd999999999999ffffffdddddddddddddddddddddddddddddd000000dddddddddddddddddd000000000000
+dddddddddddd000000dddddddddddd000000000000dddddd000000000000000000000000000000000000dddddd000000000000dddddddddddd000000000000dddddddddddddddddddddddddddddd999999999999dddddddddddddddddddddddd
+dddddd000000dddddd000000000000dddddddddddddddddd000000000000000000000000000000dddddd000000000000000000000000dddddd000000dddddddddddd000000000000000000000000000000dddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999dddddddddddddddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffffffffdddddd999999999999
+ffffffffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddd000000dddddddddddddddddddddddddddddddddddd000000dddddddddddd000000000000dddddd000000000000dddddd
+dddddd000000000000dddddddddddddddddddddddddddddd999999999999ffffffdddddddddddddddddddddddddddddd000000dddddddddddddddddd000000000000dddddddddddd000000dddddddddddd000000000000dddddd000000000000
+dddddddddddddddddddddddddddddd000000000000dddddddddddd000000000000dddddddddddddddddddddddddddddd999999999999dddddddddddddddddddddddddddddd000000dddddd000000000000dddddddddddd000000000000dddddd
+dddddd000000000000dddddd000000000000000000000000dddddd000000dddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddd999999dddddddddddddddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffffffffdddddd999999999999ffffffffffffffffffdddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddd000000dddddddddddd000000dddddddddddddddddddddddddddddddddddd000000dddddddddddd000000000000dddddd000000000000dddddddddddd000000000000dddddddddddddddddddddddddddddd999999999999
+ffffffdddddddddddddddddddddddddddddd000000dddddddddddddddddd000000000000dddddddddddd000000dddddddddddd000000000000dddddd000000000000dddddddddddddddddddddddddddddd000000000000dddddddddddd000000
+000000dddddddddddddddddddddddddddddd999999999999dddddddddddddddddddddddddddddd000000dddddddddddd000000000000dddddd000000000000dddddddddddd000000000000dddddd000000000000000000000000dddddd000000
+dddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999dddddddddddddddddd
+dddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddddddddddddddffffffffffffdddddd999999999999ffffffffffffffffffdddddddddddddddddddddddddddddddddddd000000dddddddddddddddddd000000dddddddddddd000000000000dddddddddddd
+000000dddddddddddd000000dddddddddddd000000000000dddddddddddd000000000000dddddd000000000000dddddddddddddddddddddddddddddd999999999999ffffffdddddddddddddddddddddddddddddddddddd000000dddddddddddd
+000000dddddddddddddddddd000000dddddddddddd000000dddddddddddddddddd000000000000dddddddddddd000000dddddd000000000000dddddddddddd000000000000dddddddddddddddddddddddddddddd999999999999dddddddddddd
+dddddddddddddddddd000000dddddddddddd000000000000dddddd000000000000dddddd000000000000000000dddddd000000000000000000000000dddddd000000dddddddddddddddddd000000dddddddddddd000000dddddddddddddddddd
+000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999dddddddddddddddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffffffffdddddd
+999999999999ffffffffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000dddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddd999999dddddddddddddddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffffffffdddddd999999999999ffffffffffffffffffdddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddd999999999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999dddddd
+dddddddddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffffffffdddddd999999999999ffffffffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999dddddddddddddddddddddddd000000dddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffff
+ffffffdddddd999999999999ffffffffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffffffffdddddd999999999999ffffffffffffffffffdddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffffffffdddddd999999999999ffffffffffffffffff999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999ffffff999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999ffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffdddddd999999999999ffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffffffffdddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddddddddddddddddddddbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb999999999999ffffffffffffddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb999999999999ffffffffffff
+dddddd999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999ffffffddddddddddddbbbbbb000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999dddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddddddddddddddffffffddddddddddddbbbbbb000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffdddddddddddd
+bbbbbb000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999
+ffffffffffffdddddd999999999999ddddddddddddddddddddddddddddddddddddffffffffffffddddddddddddddddddddddddddddddddddddffffffddddddddddddbbbbbb000000ffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999dddddddddddddddddddddddddddddd
+ffffffffffffffffff999999ddddddddddddddddddddddddddddddffffffddddddddddddbbbbbb000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ddddddddddddddddddddddddddddddffffffffffffffffff999999ddddddddddddddddddddddddddddddffffff
+ddddddddddddbbbbbb000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+999999999999ffffffffffffdddddd999999999999ddddddddddddddddddddddddffffffffffffffffffdddddd999999999999ddddddddddddddddddddddddffffffddddddddddddbbbbbb000000ffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999dddddddddddddddddd
+ddddddffffffffffffdddddddddddd999999999999999999ddddddddddddddddddffffffddddddddddddbbbbbb000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ddddddddddddddddddddddddffffffffffffdddddddddddd999999999999999999dddddddddddd
+ddddddffffffddddddddddddbbbbbb000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffff999999999999ffffffffffffdddddd999999999999ddddddddddddddddddffffffffffffdddddddddddddddddddddddd999999999999ddddddddddddddddddffffffddddddddddddbbbbbb000000ffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999dddddd
+ddddddffffffffffffdddddddddddddddddddddddddddddddddddd999999999999ddddddddddddffffffddddddddddddbbbbbb000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ddddddddddddffffffffffffdddddddddddddddddddddddddddddddddddd999999
+999999ddddddddddddffffffddddddddddddbbbbbb000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ddddddffffffffffffffffffdddddddddddddddddddddddddddddddddddddddddd999999999999ddddddffffffddddddddddddbbbbbb000000ffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999
+999999ddddddffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddd999999999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ddddddffffffffffffdddddddddddddddddddddddddddddddddddd
+dddddddddddd999999999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffff
+dddddd999999999999ffffff999999999999999999999999999999999999999999999999999999999999999999999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffdddddddddddd
+bbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999
+ffffffffffffdddddd999999999999ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffff999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffff
+ddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999
+999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffff
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999
+999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffff
+dddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffdddddddddddd
+bbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999
+ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffff
+ddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999
+999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffff
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999
+999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffff
+dddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffdddddddddddd
+bbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999
+ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffff
+ddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999
+999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffff
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999
+999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffff
+dddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffdddddddddddd
+bbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999
+ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffff
+ddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999
+999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffff
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999
+999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffff
+dddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffdddddddddddd
+bbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999
+ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffff
+ddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999
+999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffff
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999
+999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffff
+dddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffdddddddddddd
+bbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999
+ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffff
+ddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999
+999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffff
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999
+999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffff999999999999999999999999999999999999999999999999
+999999999999999999999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffff999999999999999999999999999999999999999999999999999999999999999999999999999999ffffffddddddddddddbbbbbbffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffff
+dddddd999999999999ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffff999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999ffffffdddddddddddd
+bbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999
+ffffffffffffdddddd999999999999ffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ddddddffffffffffffdddddddddddd
+dddddddddddddddddddddddddddddddddddd999999999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ddddddffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddd999999999999999999ffffff
+ddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+999999999999ffffffffffffdddddd999999999999ddddddffffffffffffffffffdddddddddddddddddddddddddddddddddddddddddd999999999999ddddddffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ddddddddddddffffff
+ffffffdddddddddddddddddddddddddddddddddddd999999999999ddddddddddddffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ddddddddddddffffffffffffdddddddddddddddddddddddddddddddddddd999999999999dddddd
+ddddddffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffff999999999999ffffffffffffdddddd999999999999ddddddddddddddddddffffffffffffdddddddddddddddddddddddd999999999999ddddddddddddddddddffffffddddddddddddbbbbbbffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999dddddd
+ddddddddddddddddddffffffffffffdddddddddddd999999999999999999ddddddddddddddddddffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ddddddddddddddddddddddddffffffffffffdddddddddddd999999999999999999
+ddddddddddddddddddffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ddddddddddddddddddddddddffffffffffffffffffdddddd999999999999ddddddddddddddddddddddddffffffddddddddddddbbbbbbffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999
+999999ddddddddddddddddddddddddffffffffffffffffffdddddd999999999999ddddddddddddddddddddddddffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ddddddddddddddddddddddddddddddffffffffffffffffff999999
+ddddddddddddddddddddddddddddddffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ddddddddddddddddddddddddddddddddddddffffffffffffddddddddddddddddddddddddddddddddddddffffffddddddddddddbbbbbbffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffff
+dddddd999999999999ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999ffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+bbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999
+ffffffffffffddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffff999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999
+showpage
--- /dev/null
+++ b/doc/limbotk/mkfile
@@ -1,0 +1,10 @@
+<../fonts.pal
+
+tk.ps:D: tk.ms f1.ps f2.ps mkfile
+ {echo $FONTS; cat tk.ms} | tbl | troff -mpm -mpictures | dpost >$target
+#%.ps: %.gif mkfile
+# fb/gif2pic $stem.gif | fb/pic2ps -c >$stem.ps
+#%.ps: %.gif mkfile
+# lp -d stdout <$stem.gif >$stem.ps
+%.pdf: %.ps
+ ps2pdf <$stem.ps >$stem.pdf
--- /dev/null
+++ b/doc/limbotk/tk.ms
@@ -1,0 +1,1248 @@
+.nr dT 4
+.nr P1 .2i
+.de EX
+.nr x \\$1v
+\\!h0c n \\nx 0
+..
+.nr Pd \n(PD
+.de FG \" start figure caption: .FG filename.ps verticalsize
+.KF
+.BP \\$1 \\$2
+.sp .5v
+.EX \\$2v
+.ps -1
+.vs -1
+..
+.de fg \" end figure caption (yes, it is clumsy)
+.ps
+.vs
+.br
+.KE
+..
+.de Tk \" Tk option name and option
+.CW \\$1
+.I \\$2 \\$3
+..
+.de Tc \" Tk command string
+.IP "\\f(CW\\$1\\fP \\$2" \w'\f(CWburble\fP'u
+.br
+..
+.de Kp \" Keypress
+.IP "\\f(CW\\$1\\fP" \w'\f(CWKeypress\fP'u
+.br
+..
+.de d0 \" no gap between paragraphs
+.nr PD 0
+..
+.de d1 \" restore gap
+.nr PD \n(Pd
+..
+.ds Op "\fR[\fP\fIoptions ...\fP\fR]\fP
+.TL
+An Overview of Limbo/Tk
+.AU
+.I "Lucent Technologies Inc."
+.br
+Revised June 2000 by Vita Nuova
+.SH
+Overview
+.LP
+Limbo/Tk is a concise and powerful way to construct graphical user interfaces without directly using the Draw module primitives.
+Standard interfaces can quickly be created from collections of menus, buttons, and other widgets that are part of Limbo/Tk's visual toolkit.
+It is modelled on Ousterhout's Tk 4.0 [1,2], commonly deployed
+with the scripting language Tcl as `Tcl/Tk'.
+Although inspired by Tk 4.0, Inferno's Tk implementation is new, and unrelated to Ousterhout's.
+It is intended to be used with the new programming language Limbo, not Tcl.
+Limbo/Tk applications make
+extensive use of Limbo's concurrent programming constructions and data structures,
+and that is reflected in the interface.
+Section 9 of Volume 1 of the
+.I "Inferno Programmer's Manual"
+provides a detailed reference for Limbo/Tk.
+This paper provides an overview of its use in some simple staged examples, and
+concludes with
+a summary of the differences between the Limbo/Tk implementation and Tk 4.0.
+In the rest of this paper, `Tk' refers to Limbo/Tk, and `Tk 4.0' refers to Ousterhout's
+original implementation.
+.NH 1
+The Limbo/Tk environment
+.LP
+Limbo applications access Tk by means of a built-in module,
+.CW "$Tk" .
+The standard distribution also includes the window manager
+.CW "wm"
+and the Limbo module
+.CW Wmlib .
+Unlike
+.CW Tk ,
+.CW Wmlib
+is not built-in but implemented in Limbo by
+.CW /appl/lib/wmlib.b .
+It simplifies and standardises the construction of windowed applications;
+it also contains some graphical devices such as tabbed notebooks not provided
+directly by Limbo/Tk.
+The essentials of both
+.CW Tk
+and
+.CW Wmlib
+are discussed here.
+.LP
+Programmers usually need only three functions from the
+.CW Tk
+module:
+.IP •
+.CW toplevel
+.br
+Creates a graphical window \- a Tk `top level' widget \-
+that can be used to build a Limbo/Tk application.
+The function returns a reference to an adt
+.CW "\%Tk->Toplevel"
+adt that represents the window in subsequent Tk operations.
+.IP •
+.CW cmd
+.br
+Creates and arranges graphic objects within the toplevel window by processing Limbo/Tk command strings.
+The interface to Tk is primarily the passing of strings between
+the application and Tk
+of the toolkit using
+.CW cmd .
+Each call to
+.CW cmd
+returns a string representing the result of the Tk command;
+a string starting with
+.CW ! ' `
+diagnoses an error.
+.IP •
+.CW namechan
+.br
+Gives a name within Tk (in the scope of a given window) to a Limbo
+.CW "chan of string"
+that Tk commands can use to send data to a Limbo program.
+.LP
+Other functions in the module have more specialised uses that will not be discussed here.
+For instance,
+.CW "mouse"
+and
+.CW "keyboard"
+are used by a window manager to send mouse and keyboard events
+to the Tk implementation for distribution to applications.
+.LP
+Even
+.CW toplevel
+is not commonly used in the window manager environment:
+a function
+.CW Wmlib->titlebar
+provides the usual interface to
+.CW toplevel .
+The low-level interface will be described first, for completeness,
+then the normal case using
+.CW titlebar .
+.NH 1
+Basic Limbo/Tk
+.LP
+This section shows a simple Tk application that uses only the fundamental Tk functions.
+.NH 2
+Preliminaries
+.LP
+The example assumes that the
+.CW "Tk"
+module is loaded as
+.CW "tk" :
+.P1
+include "tk.m";
+ tk: Tk;
+ ...
+init(ctxt: ref Draw->Context, nil: list of string)
+{
+ tk = load Tk Tk->PATH;
+ ...
+}
+.P2
+.NH 2
+Creating a toplevel
+.LP
+The following fragment makes the Limbo identifier
+.CW "top"
+refer to a new
+.CW "ref Tk->Toplevel"
+for use in later Tk commands:
+.P1
+ top := tk->toplevel(ctxt.screen, "-x 150 -y 150");
+.P2
+The upper left corner of this window will be at point (150, 150), where (0,0) is the upper left corner of the screen;
+.I x
+coordinates increase from left to right, and
+.I y
+coordinates increase from top to bottom.
+.LP
+In general,
+.CW "Tk->toplevel"
+takes a screen argument and a string containing further options, and it returns a reference to a top-level Limbo/Tk widget on the given screen.
+The options argument contains
+.Tk -option value
+pairs, such as
+.CW "-relief raised" .
+As well as the generic options,
+.CW "toplevel"
+accepts the options
+.Tk -x int
+and
+.Tk -y int
+to specify the upper left corner of the toplevel widget, where (0,0) is the top left corner of the screen,
+and
+.Tk -debug bool
+to cause a trace of all Tk commands to be printed,
+if the boolean value is true.
+.NH 2
+Creating a named channel to Tk
+.LP
+The following fragment creates a
+.CW "chan of string"
+called
+.CW "c" ,
+then associates the name
+.CW "cmdchan"
+within Tk with the Limbo channel
+.CW "c" :
+.P1
+ c := chan of string;
+ tk->namechan(top, c, "cmdchan");
+.P2
+The named channel
+.CW "cmdchan"
+can now be used in a special Tk
+.CW send
+command
+to send strings to be processed by a Limbo program, typically notifying it of an event.
+Note that the Limbo identifer name need not match the name given to Tk,
+although it is invariably easier to follow the code if the two are the same.
+.NH 2
+Defining and positioning widgets
+.LP
+The following fragment uses
+.CW "tk->cmd"
+to define four widgets: two buttons, a label, and an entry widget. The widgets are positioned in their parent window (in this case the toplevel window
+.CW "top" )
+using the Tk command
+.CW "pack" :
+.P1
+.ps -1
+.vs -1
+ \fI# define widgets\fP
+ tk->cmd(top, "button .b1 -text Exit -command {send cmdchan exit}");
+ tk->cmd(top, "button .b2 -text Send -command {send cmdchan send}");
+ tk->cmd(top, "label .l -text {Name: }");
+ tk->cmd(top, "entry .e");
+
+ \fI# bind newline character in entry widget to command\fP
+ tk->cmd(top, "bind .e <Key-\en> {send cmdchan send}");
+
+ \fI# pack widgets\fP
+ tk->cmd(top, "pack .b1 .b2 .l .e -side left; update");
+.ps +1
+.vs +1
+.P2
+This particular pack command packs the widgets named
+.CW ".b1" ,
+.CW ".b2" ,
+.CW ".l" ,
+and
+.CW ".e"
+into the
+.CW "top"
+window beginning at the left side. The
+.CW "update"
+command forces Tk to update the screen right away. The result is shown in Figure 1.
+.FG "f1.ps" 0.21i
+.ce
+.I "Figure 1. Two buttons, a label and an entry widget."
+.fg
+.LP
+Entering a newline (`return' or `enter' key)\-the character
+.CW \en ' `
+in Limbo\-
+in the entry box results in the execution of the Tk command
+.CW "{send cmdchan send}" ,
+because of the binding set by
+.CW "bind .e <Key-\en>"
+previously executed by
+.CW tk->cmd .
+The
+.CW "bind"
+command is often used to bind specific widget events (including key presses, mouse button presses, and mouse motion) to Tk
+.CW send
+commands.
+.NH 2
+Processing widget events
+.LP
+This next fragment defines what will happen when a user selects either the
+.CW "Exit"
+or the
+.CW "Send"
+buttons. The
+.CW "Exit"
+behaviour is simple: the program ends. If a user touches
+.CW Send ,
+the program executes
+.CW "tk->cmd"
+to get whatever text is in the entry widget
+.CW ".e"
+then prints it to standard output.
+.P1
+ for(;;) {
+ s := <- c;
+ case s {
+ "exit" =>
+ return;
+
+ "send" =>
+ sys->print("name was: %s\en", tk->cmd(top, ".e get"));
+ }
+ }
+.P2
+.NH 1
+Example - using Tk and Wmlib
+.LP
+This section uses both Tk and Wmlib to create a simple window manager application with a titlebar, including resize and exit buttons.
+This is the usual way to create new windows.
+.NH 1
+Preamble
+.LP
+The example assumes that the
+.CW "Tk"
+module is loaded as before, as module variable
+.CW "tk" ,
+but furthermore that the
+.CW "Wmlib"
+module is also loaded, as
+.CW "wmlib" :
+.P1
+include "tk.m";
+ tk: Tk;
+include "wmlib.m";
+ wmlib: Wmlib;
+ ...
+ tk = load Tk Tk->PATH;
+ wmlib = load Wmlib Wmlib->PATH;
+ wmlib->init();
+.P2
+Note that
+.CW wmlib->init
+is called once to initialise the
+.CW wmlib
+module just loaded, before any other functions are called.
+.LP
+In window manager applications the
+.CW Tk->toplevel
+function is not normally used directly.
+Instead, a window manager interface is used to create both
+the top level widget and a channel to receive events from the window manager.
+The
+.CW titlebar
+function has the signature:
+.ps -1
+.vs -1
+.P1
+ titlebar(scr: Draw->Screen, tkargs: string, title: string, buts: int):
+ (ref Tk->Toplevel, chan of string);
+.P2
+.vs +1
+.ps +1
+The
+.CW Screen
+is the one on which the window is to be created, normally the
+one passed in the
+.CW Context
+parameter to a program's
+.CW init
+function.
+The
+.I tkargs
+parameter can control the position and appearance of the window,
+but is best left nil (or the empty string) to use the window manager's
+defaults (see
+.I wmlib (2)
+for details otherwise),
+including automatic placement.
+The
+.I title
+string gives the title that appears in the title bar.
+Finally,
+.I buts
+is a bit set that selects the buttons to appear.
+The value
+.CW Wmlib->Appl
+gives the usual resize and hide buttons;
+the exit (delete) button always appears.
+The following is used in the example:
+.P1
+ (top, titlechan) := wmlib->titlebar(ctxt.screen, nil,
+ "Text Browser", Wmlib->Appl);
+.P2
+Note that
+.CW titlebar
+returns a tuple.
+The first element is a reference to the Tk top level widget
+for use in later Tk commands.
+The second element of the tuple
+is a Limbo channel of type
+.CW "chan of string"
+that passes window manager events to the application.
+.LP
+The channel
+.CW "titlechan"
+is used by
+.CW "wmlib"
+to send messages, but it is normally necessary
+to create a channel to Tk to receive events from widgets the application creates:
+.P1
+ cmdchan := chan of string;
+ tk->namechan(top, cmdchan, "cmdchan");
+.P2
+.NH 2
+Defining and positioning widgets
+.LP
+The function
+.CW "Wmlib->tkcmds"
+takes two arguments, a
+.CW "ref Tk->Toplevel"
+that identifies a top level window,
+and an
+.CW "array of string" .
+Each element of the array is a Tk command acceptable to
+.CW "Tk->cmd" ;
+.CW Wmlib->tkcmds
+simply applies it
+to each element of the array.
+.LP
+Most of the following fragment consists of Tk command strings that are members of the array of strings
+.CW "tk_config" .
+The comments describe the widgets being created. Not all widgets and menu items in this example are functional.
+The last line executes the array of commands using
+.CW "wmlib->tkcmds" :
+.nr dP +1
+.nr dV +1p
+.P1
+ tk_config := array[] of {
+
+ \fI# define menubar frame, widget frame, text frame\fP
+ "frame .mbar -relief groove -bd 2",
+ "frame .w",
+ "frame .text",
+
+ \fI# define and pack menus\fP
+ "menubutton .file -text File -menu .file.m",
+ "menubutton .edit -text Edit -menu .edit.m",
+ "menubutton .help -text Help -menu .help.m",
+
+ "menu .file.m",
+ ".file.m add command -label Send -command {send cmdchan send}",
+ ".file.m add command -label Exit -command {send cmdchan exit}",
+ "menu .edit.m",
+ ".edit.m add command -label Cut",
+
+ "menu .help.m",
+ ".help.m add command -label Index -underline 0",
+
+ "pack .file .edit -side left -in .mbar; update",
+ "pack .help -side right -in .mbar",
+.P3
+
+ \fI# define and pack buttons and text entry box (for file name)\fP
+ "button .b1 -text Send -command {send cmdchan send}",
+ "button .b2 -text Open -command {send cmdchan open}",
+ "label .l -text {Name: }",
+
+ "entry .e",
+ "bind .e <Key-\en> {send cmdchan open}",
+
+ "pack .b1 .b2 .l .e -side left -in .w",
+.P3
+
+ \fI# define and pack text panel and its scrollbar\fP
+ "text .t -yscrollcommand {.scroll set} -bg white",
+ "scrollbar .scroll -command {.t yview}",
+ "pack .scroll -side left -fill y -in .text",
+ "pack .t -side right -in .text -expand 1 -fill both",
+
+ \fI# pack frames\fP
+ "pack .text -side bottom -fill both -expand 1",
+ "pack .mbar .w -fill x; update",
+ "pack propagate . 0",
+ };
+
+ \fI# run the Tk commands\fP
+ wmlib->tkcmds(top, tk_config);
+.P2
+.nr dP -1
+.nr dV -1p
+The result of executing these Tk commands is shown in Figure 2.
+.LP
+The arrays defining Tk widgets are sometimes made global to a module
+when they can sensibly be used by several functions.
+It is also common to use small Limbo functions to replicate
+similar widgets by building Tk commands from the value of parameters,
+using Limbo string concatenation
+or
+.CW sys->sprint .
+.FG "f2.ps" 2.16i
+.ce
+.I "Figure 2. A Wm application with a menu bar, a tool bar, and a text window."
+.fg
+.LP
+.NH 2
+Processing widget events
+.LP
+This fragment uses an
+.CW "alt"
+block to wait for strings to arrive from either
+.CW "titlechan"
+or
+.CW "cmdchan" .
+.LP
+When a string is received on
+.CW "titlechan" ,
+the
+.CW "case"
+statement either handles it directly (as with
+.CW exit )
+or passes it to
+.CW "wmlib->titlectl"
+for normal handling by the window manager.
+.LP
+When a string is received on
+.CW cmdchan ,
+the program acts accordingly: it writes the text in the entry widget to standard output
+.CW send ); (
+calls
+.CW "do_open"
+to open the file name currently in the entry box
+.CW open ); (
+or returns from the processing loop
+.CW exit ). (
+.P1
+ for(;;) {
+ alt {
+ s := <-titlechan => \fI# message from title bar buttons\fP
+ case s {
+ "exit" =>
+ return;
+ * =>
+ wmlib->titlectl(top,s);
+ }
+
+ com := <-cmdchan => \fI# message from widgets created above\fP
+ case com {
+ "send" =>
+ sys->print("name was: %s\en", tk->cmd(top, ".e get"));
+ "open" =>
+ do_open(top, tk->cmd(top, ".e get"));
+ "exit" =>
+ return;
+ }
+ }
+ }
+.P2
+Although this example uses a Tk text entry widget,
+.CW Wmlib
+provides a function
+.CW filename
+that pops up a graphical device that allows a user to
+select a file by typing a name, browsing the file system, or a mixture of both.
+See
+.I wmlib (2)
+for details.
+.NH 2
+Putting text into the text widget
+.LP
+The
+.CW "do_open"
+function below uses
+the buffered I/O module
+.CW Bufio
+to read lines from the file named in the entry widget and add them to the text currently in the text widget
+.CW ".t" .
+.P1
+do_open(top: ref Tk->Toplevel, file: string)
+{
+ iofd := bufio->open(file, Bufio->OREAD);
+ if(iofd == nil){
+ wmlib->dialog(top, "error -fg red", "Open file",
+ sys->sprint("%s: %r", file), 0, "Ok"::nil);
+ return;
+ }
+
+ tk->cmd(top, ".t delete 1.0 end");
+ tk->cmd(top, "cursor -bitmap cursor.wait");
+
+ for(;;){
+ line := iofd.gets('\en');
+ if(line == nil)
+ break;
+ tk->cmd(top, ".t insert end '" + line);
+ }
+ tk->cmd(top, "cursor -default");
+}
+.P2
+If the file cannot be opened,
+.CW do_open
+calls
+.CW wmlib->dialog
+to pop up a diagnostic message panel, rather than (say) printing a message to standard
+error,
+and returns.
+If the file was opened,
+.CW do_open
+deletes the current
+contents of the frame, and reads the
+file into it, inserts one line at a time.
+Tk allows the data inserted to contain embedded newlines, and
+a more efficient implementation could read blocks
+of data from the file and insert them, but some care is required.
+A text file in Inferno contains Unicode characters in UTF-encoding, and the
+bytes of a single character might be split across separate reads.
+.CW Iobuf.gets
+by contrast is guaranteed to reassemble complete Unicode characters from
+the buffered input stream.
+A program using
+.CW Iobuf.read
+(or
+.CW Sys->read )
+to fetch blocks of data would typically use
+.CW Sys->utfbytes
+to find maximal sequences of UTF-encoded characters
+and insert large chunks of text at once.
+See the function
+.CW loadtfile
+in
+.CW /appl/wm/edit.b
+for example.
+.NH 1
+Limbo/Tk command syntax
+.LP
+Once a toplevel widget has been built, an application calls
+.CW "tk->cmd"
+to issue commands to Tk and receive results.
+This section describes in more detail the contents of the string argument
+that conveys the commands.
+.NH 2
+Command strings
+.LP
+The command string may contain one or more commands, separated by semicolons. A semicolon is not a command separator when it is nested in braces
+.CW "{}" ) (
+or brackets
+.CW "[]" ), (
+or it is escaped by a backslash (\e).
+.LP
+Each command is divided into
+.I "words" :
+sequences of characters separated by one or more blanks or tabs,
+subject to the following quoting rules:
+.IP
+.br
+A word beginning with an opening brace
+.CW { ) (
+continues until the balancing closing brace
+.CW } ) (
+is reached.
+The outer brace characters are stripped.
+A backslash
+.CW \e ) (
+can be used to escape a brace, preventing special interpretation.
+.IP
+.br
+A word beginning with an opening bracket
+.CW [ ) (
+continues until the balancing closing bracket
+.CW ] ) (
+is reached. The enclosed string is then evaluated as if it were a command string, and the resulting value is used as the contents of the word.
+.IP
+.br
+At any point in the command string a single quote (\f5'\fP) causes the rest of the string to be treated as one word.
+.LP
+Single commands are executed in order until they are all done or an error is encountered. By convention, an error is signalled by a return value starting with an exclamation mark. The return value from
+.CW "cmd"
+is the return value of the first error-producing command or else the return value of the final single command.
+.LP
+To execute a single command, the first word is examined. It can be one of the following:
+.IP \(bu
+One of the following widget creating commands:
+.RS
+.TS
+lf(CW) lf(CW) .
+button menu
+canvas menubutton
+checkbutton radiobutton
+entry scale
+frame scrollbar
+label text
+listbox
+.TE
+The second word of each of these commands is the name of the widget to be created. The remaining words are option/value pairs.
+.RE
+.IP \(bu
+A widget name (beginning with a dot
+.CW . ') `
+that corresponds to an existing widget. The second word gives the name of a particular widget subcommand and the remaining words are arguments for the subcommand.
+.IP \(bu
+A
+.CW "pack" ,
+.CW "bind" ,
+.CW "focus" ,
+.CW "grab" ,
+.CW "put" ,
+.CW "destroy" ,
+.CW "image" ,
+or
+.CW "update"
+command.
+These commands manipulate existing widgets or control Tk.
+Most are the same as documented for Tk 4.0.
+The
+.CW "bind"
+command is significantly different, and the
+.CW "image"
+command is more limited.
+.IP \(bu
+The
+.CW " send "
+command,
+which sends a string to a Limbo process.
+The second word is the Tk name of a Limbo channel (previously registered with
+.CW "namechan" ),
+and the rest of the command is sent as a single string along the channel.
+.IP \(bu
+The
+.CW "variable"
+command.
+Limbo/Tk generally does not provide the variables of Tcl/Tk; radio buttons are an exception. The
+.CW "variable"
+command takes the name of a variable defined in a radio button as the second word, and the value of the variable is the result of the command. Furthermore, there is one predefined variable whose value can be retrieved this way: the
+.CW "lasterror"
+variable is set every time a Tk command returns an error. The value is the offending command (possibly truncated) followed by the error return value. The
+.CW "lasterror"
+variable is cleared whenever it is retrieved using the variable command. This allows several
+Tk commands to be executed without checking error returns each time. A call to the
+.CW "variable"
+command with
+.CW "lasterror"
+at strategic points can make sure that an unexpected error has not occurred.
+.IP \(bu
+The
+.CW "cursor"
+command. This command takes a number of option/value pairs to control the appearance and placement of the cursor. Available options are:
+.Tk -x int
+and
+.Tk -y int ,
+to change the cursor position to align its hotpoint at the given point (in screen coordinates);
+.Tk -bitmap filename
+or
+.Tk -image imagename
+to change the appearance of the cursor; and
+.CW -default
+to change back to the default appearance of the cursor.
+.LP
+Because the language accepted by the
+.CW "cmd"
+function has no user-defined functions, no control flow and very few variables, almost all applications need to have some of their logic in Limbo programs.
+The modern concurrency constructions provided by Limbo \-
+processes, channels, send/receive operators and
+.CW alt \-
+replace unstructured interrupts (`call backs'), often used by
+other graphics systems, by structured control flow.
+(The Inferno shell does provide support, however, for rapid prototyping using Tk
+and a scripting language: see the manual pages for
+.I sh-tk (1)
+and
+.I wish (1)
+in Volume 1.)
+.NH 2
+Widget options
+.LP
+In Tk, all widget creation commands, and all
+.CW "cget"
+widget commands accept a common set of generic options in addition to widget-specific options.
+Except as noted otherwise, the meanings are the same as they are in Tk 4.0. The allowable forms of things like
+.I "color" ,
+.I "dist" ,
+and
+.I "font"
+are slightly different in Limbo/Tk.
+See
+.I types (9)
+in Volume 1
+for precise definitions.
+The generic options are as follows:
+.DS
+.fi
+.Tk -activebackground color
+.br
+.Tk -activeforeground color
+.br
+.Tk -actwidth dist
+.br
+.Tk -actheight dist
+.DE
+.QS
+Note:
+the
+.CW -actwidth
+and
+.CW -actheight
+variables are overridden by the
+packer, but are useful as arguments to
+.CW cget
+to retrieve the actual
+width and height (inside the border) of a widget after packing.
+.QE
+.DS
+.fi
+.Tk -background color
+(or
+.Tk -bg color )
+.br
+.Tk -borderwidth dist
+(or
+.Tk -bd dist )
+.br
+.Tk -font font
+.br
+.Tk -foreground color
+(or
+.Tk -fg color )
+.br
+.Tk -height dist
+.br
+.Tk -padx dist
+.br
+.Tk -pady dist
+.br
+.Tk -relief relief
+.br
+.Tk -state normal ,
+.Tk -state active ,
+or
+.Tk -state disabled
+.DE
+.QS
+Note:
+.CW -state
+is only relevant for some widgets (for example,
+entry widgets).
+.QE
+.DS
+.fi
+.Tk -selectbackground color
+.br
+.Tk -selectborderwidth dist
+.br
+.Tk -selectcolor color
+.DE
+.QS
+Note:
+.CW -selectcolor
+is the colour of the box in selection menu
+items.
+.QE
+.DS
+.fi
+.Tk -selectforeground colour
+.br
+.Tk -width dist
+.DE
+In general, the manual page for each widget in section 9 of Volume 1 tells which of the
+generic Tk options the widget accepts.
+.LP
+The
+.I "dist"
+parameters are lengths, expressed in the following form:
+an optional minus sign, then one or more decimal digits (with possible embedded decimal point), then an optional units specifier.
+The unit specifiers are the following:
+.IP
+.TS
+lf(CW) lf(R)w(3i) .
+c centimetres
+m millimetres
+i inches
+p points
+h height of widget's font (*)
+w T{
+width of `\f(CW0\fP' character in widget's font (*)
+T}
+.TE
+.LP
+The ones marked (*) are specific to Limbo/Tk.
+.LP
+Tcl/Tk 4.0 widgets do not uniformly take
+.CW "-width"
+and
+.CW "-height"
+options; instead, each widget may take either or both, and the interpretation
+of a number lacking a unit specifier varies from widget to widget. For example, in Tk 4.0
+.CW "-width 25"
+means 25 characters to an entry widget, but 25 pixels to a canvas widget. In Limbo/Tk, all widgets may specify width and height, and bare numbers always mean screen pixels.
+.LP
+A
+.I "colour"
+parameter can be a colour name or an RGB value.
+Only a few names are known:
+.IP
+.TS
+lf(CW) lf(CW) lf(CW) lf(CW) lf(CW) .
+aqua fuchsia maroon purple yellow
+black gray navy red
+blue green olive teal
+darkblue lime orange white
+.TE
+.LP
+For RGB values, either
+.CW "#" \fIrgb\fP
+or
+.CW "#" \fIrrggbb\fP
+can be used, where
+.I r ,
+.I rr ,
+etc.
+are hexadecimal values for the corresponding colour components.
+.LP
+A
+.I "font"
+parameter gives the full path name of an Inferno font file; for example,
+.CW "/fonts/pelm/unicode.9.font" .
+.LP
+A
+.I bitmap
+parameter is not used by any of the generic options, but is worth mentioning here.
+Unlike Tk 4.0, a
+.I bitmap
+in Limbo/Tk is not restricted to a 1-bit deep bitmap to be coloured with foreground and background.
+Instead, it can be a full-colour image (`pixmap' in X11 terminology),
+which is displayed as is. If
+.I "bitmap"
+begins with a
+.CW @ ', `
+the remaining characters should be the path name of an Inferno image file. If
+.I "bitmap"
+begins with the character
+.CW < ', `
+the remaining characters must be a decimal integer giving a file descriptor number of an open file from which the bitmap can be loaded. Otherwise,
+.I bitmap
+should be the name of a bitmap file in the directory
+.CW "/icons/tk" .
+.NE 1i
+.SH
+Options not supported in Limbo/Tk
+.LP
+The following options provided by Tk 4.0 are not supported by any Limbo/Tk widget:
+.P1
+-cursor -insertofftime -wraplength
+-disabledforeground -insertontime
+-exportselection -insertwidth
+-geometry -repeatdelay
+-highlightbackground -repeatinterval
+-highlightcolor -setgrid
+-highlightthickness -takefocus
+-insertbackground -textvariable
+-insertborderwidth -troughcolor
+.P2
+.NH 1
+Limbo/Tk commands
+.LP
+This section lists all the commands documented in the Tk 4.0 man pages, giving the differences between the behaviour specified in those man pages and the behaviour implemented in Limbo/Tk.
+Some common Tcl commands are listed as well.
+Bear in mind that some Tk 4.0 options are unsupported, as noted above.
+.Tc "bell" "[\f(CW-displayof \fP\fIwindow\fP]"
+Not implemented.
+.Tc "bind" "\fIwidget\fP <\fIevent-event-...-event\fP> \fIcommand\fP"
+.d0
+.Tc "bind" "\fIwidget\fP <\fIevent-event-...-event\fP> + \fIcommand\fP"
+.d1
+The bind command is perhaps the command that differs most from Tk 4.0.
+In general, only a subset of its functionality is implemented. One difference is that
+.I widget
+must be the name of an existing widget.
+The notion of a widget class is completely absent in Limbo/Tk.
+Event sequence specifications are also more restricted. A sequence is either a single character (rune), meaning a
+.CW "KeyPress"
+of that character, or a sequence of
+.I "events"
+in angle brackets.
+.I "Events"
+are separated by blanks or minus signs.
+See
+.I bind (9)
+for a complete discussion.
+.Tc "bindtags" "\fIwindow\fP [\fItaglist\fP]"
+Not implemented.
+.Tc button "\fIpathname\fP \*(Op"
+As in Tk 4.0 (but note difference in units for
+.CW "-height"
+and
+.CW "-width" ).
+.Tc canvas "\fIpathname\fP \*(Op"
+The Postscript subcommand is not implemented.
+.Tc checkbutton "\fIpathname\fP \*(Op"
+Unimplemented options:
+.CW "-indicatoron" ,
+.CW "-offvalue" ,
+.CW "-onvalue" ,
+and
+.CW "-selectimage" .
+The
+.CW flash
+subcommand is not implemented.
+.Tc clipboard \fIoperation\fP [\fIarg ...\fP]"
+Not implemented.
+.Tc "\fIpathname\fP configure [" "option ...\f5]\f1"
+Configure options for widget
+.I pathname .
+Widget-specific; see the manual entry for the widget in
+section 9 of Volume 1.
+.Tc destroy "[\fIwindow ...\fP]"
+As in Tk 4.0, but
+note that
+.CW "destroy ." ' `
+is rarely needed because top level windows are automatically
+destroyed by the Inferno garbage collector immediately when the last reference vanishes.
+.Tc entry "\fIpathname\fP \*(Op"
+The
+.CW scan
+subcommand is not implemented. Some key bindings are not implemented when there is currently no way to type those keys to Inferno (for example,
+.CW "Home" ).
+Note difference in units for
+.CW "-height"
+and
+.CW "-width" .
+.Tc "event" \fIoperation\fP [\fIarg ...\fP]"
+Not implemented: normally replaced by Tk
+.CW send
+or Limbo channel send operation within the application.
+.Tc focus \fIwindow\fP
+The focus model in Inferno is different. Only one widget has the keyboard focus at a given time. Limbo/Tk does not maintain a private keyboard focus for each toplevel tree and automatically move the focus there whenever the tree is entered. (Canvas and text widgets, however, do maintain a private keyboard focus.)
+The Limbo/Tk
+.CW "focus"
+command moves the keyboard focus to the given
+.I window .
+By default, the first press of the primary button in an
+.CW "entry" ,
+.CW "listbox"
+or
+.CW "text"
+widget causes the focus to be moved to that widget. Just entering a menu widget gives it the focus.
+The
+.CW "-displayof" ,
+.CW "-force"
+and
+.CW "-lastfor"
+options are not implemented.
+.Tc frame "\fIpathname\fP \*(Op"
+Unimplemented options:
+.CW "class" ,
+.CW "colormap" ,
+and
+.CW "visual" .
+.Tc grab "\fIwindow\fP"
+.d0
+.Tc grab "\fIoption\fP [\fIarg ...\fP]"
+.d1
+Limbo/Tk implements only global grabs, so the
+.CW "-global"
+option is not recognised. The
+.CW "grab current"
+command is not implemented. The
+.CW "grab"
+command is not recognised as a synonym for
+.CW "grab set" .
+.Tc "grid" "\fIoperation\fP [\fIarg ...\fP]"
+Not implemented.
+.Tc "image create bitmap" "[\fIname\fP] [\fIoptions\fP]"
+.d0
+.Tc image "\fIoption\fP [\fIarg arg ...\fP]"
+.d1
+Only bitmap image types are implemented, but, as documented under
+.CW "bitmap" ,
+Inferno `bitmaps' are not just 1-bit deep;
+they encompass both bitmaps and `photo' (colour) images
+as provided by Tk/4.0.
+Limbo/Tk does not, however, recognise the wide variety of graphics formats that Tk 4.0 does.
+Instead, only Inferno's own format is supported internally, and external programs
+are provided to convert between that and other formats such as JPEG.
+The file descriptor syntax for specifying bitmaps is useful when an external program writes the bitmap to a file descriptor.
+If a maskfile is given, it may also have a depth greater than 1 bit; the meaning is that if a pixel of the mask is non-zero then the corresponding pixel of the image should be drawn.
+(But see the handling of bitmaps used as stipples in
+.I canvas (9).)
+The
+.CW -data
+and
+.CW -maskdata
+options are not implemented.
+.Tc label "\fIpathname\fP \*(Op"
+Unimplemented options:
+.CW "-justify"
+and
+.CW "-wraplength" .
+Note difference in units for
+.CW "-height"
+and
+.CW "-width" .
+.Tc listbox "\fIpathname\fP \*(Op"
+The
+.CW "bbox"
+and
+.CW "scan"
+subcommands are not implemented. Note difference in units for
+.CW "-height"
+and
+.CW "-width" .
+.Tc lower \fIwindow\fP
+The
+.CW "belowThis"
+optional parameter is not recognised.
+.Tc menu "\fIpathname\fP \*(Op"
+Unimplemented options:
+.CW "-postcommand" ,
+.CW "-tearoff" ,
+.CW "-tearoff"
+command, and
+.CW "-transient" .
+In the
+.CW add
+subcommand, the
+.CW "-accelerator" ,
+.CW "-indicatoron" ,
+and
+.CW "-selectimage"
+options are not implemented. In the
+.CW "index"
+subcommand, the
+.CW "last"
+and
+.CW "pattern"
+index forms are not implemented. The
+.CW "configure"
+and
+.CW "entrycget"
+subcommands are not implemented.
+.Tc menubutton "\fIpathname\fP \*(Op"
+Unimplemented options:
+.CW "-indicatoron" ,
+.CW "-justify" ,
+and
+.CW "-wraplength" .
+.Tc "message" "\fIpathname\fP \*(Op"
+Not implemented (subsumed by
+.CW "label" ).
+.Tc "option" "\fIoperation\fP [\fIarg ...\fP]"
+Not implemented. There is no option database.
+.Tc pack "\fIoption arg ...\fP"
+.d0
+.Tc pack "\fIslave\fP ...\*(Op"
+.Tc "pack configure" "\fIslave\fP ... \*(Op"
+.Tc "pack forget" "\fIslave\fP ..."
+.Tc "pack propagate" "\fImaster\fP [0 | 1]"
+.Tc "pack slaves" "\fImaster\fP"
+.d1
+The
+.CW "info"
+subcommand is not implemented.
+.Tc place "\fIoperation\fP [\fIarg ...\fP]"
+Not implemented.
+.Tc radiobutton "\fIpathname\fP \*(Op"
+Unimplemented options:
+.CW "-indicatoron" ,
+.CW "-justify" ,
+.CW "-selectimage" ,
+and
+.CW -wraplength .
+The
+.CW "flash"
+subcommand is not implemented.
+.Tc raise \fIwindow\fP
+The
+.CW "aboveThis"
+optional parameter is not recognised.
+.Tc scale "\fIpathname\fP \*(Op"
+Unimplemented options:
+.CW "-digits "
+and
+.CW "-variable" .
+.Tc scrollbar "\fIpathname\fP \*(Op"
+The old syntax of
+.CW "set"
+and
+.CW "get"
+is not supported.
+.Tc "selection"
+Not implemented.
+.Tc send "\fIchanname string\fP"
+Rather than sending data to a different application, the
+.CW "send"
+command sends a given
+.I string
+down the Limbo channel associated with
+.I channame ,
+as set by
+.CW namechan .
+.Tc text "\fIpathname\fP \*(Op"
+The
+.CW "dump"
+subcommand is not implemented. The
+.CW "-regexp"
+mode of the
+.CW "search"
+subcommand is not implemented.
+.Tc tk "\fIoperation\fP [\fIarg ...\fP]"
+Not implemented.
+.Tc "tkerror"
+Not implemented.
+.Tc "tkwait" "\fIoperation name\fP"
+Not implemented.
+.Tc "toplevel" "\fIpathname\fP [\fIoption value\fP...]"
+There is no
+.CW "toplevel"
+Tk command implemented by the
+.CW "cmd"
+function; instead, the Tk module entry point
+.CW "toplevel"
+is used to make toplevel widgets (windows)
+as described above.
+.Tc update
+In Tcl/Tk,
+.CW update
+is a Tcl command that invokes the `event handler loop'.
+In Limbo/Tk,
+it flushes any pending updates to the screen.
+The optional
+.CW "idletasks"
+argument is not recognised.
+.Tc "winfo" "\fIoperation\fP [\fIarg ...\fP]"
+Not implemented. Much of the information that
+.CW "winfo"
+would return can be got by applying
+.CW "cget"
+to each widget.
+.Tc "wm" "\fIoperation window\fP [\fIarg ...\fP]"
+Not implemented.
+.NH 2
+References
+.IP 1.
+John K Ousterhout,
+.I "Tcl and the Tk Toolkit" ,
+Addison-Wesley Publishing Company, Reading, Massachusetts, 1994.
+.IP 2.
+Paul Raines and Jeff Trantor,
+.I "Tcl/Tk in a Nutshell" ,
+O'Reilly, Sebastopol, California, 1999.
+.IP 3.
+B W Kernighan,
+``Descent into Limbo'',
+elsewhere in this volume.
+.IP 4.
+See
+.I draw-intro (2),
+.I tk (2)
+and
+.I wmlib (2)
+in
+.I "The Inferno Programmer's Manual",
+Volume 1.
binary files /dev/null b/doc/limbotk/tk.pdf differ
--- /dev/null
+++ b/doc/limbotk/tk.ps
@@ -1,0 +1,7913 @@
+%!PS-Adobe-2.0
+%%Version: 0.1
+%%DocumentFonts: (atend)
+%%Pages: (atend)
+%%EndComments
+%
+% Version 3.3.2 prologue for troff files.
+%
+
+/#copies 1 store
+/aspectratio 1 def
+/formsperpage 1 def
+/landscape false def
+/linewidth .3 def
+/magnification 1 def
+/margin 0 def
+/orientation 0 def
+/resolution 720 def
+/rotation 1 def
+/xoffset 0 def
+/yoffset 0 def
+
+/roundpage true def
+/useclippath true def
+/pagebbox [0 0 612 792] def
+
+/R /Times-Roman def
+/I /Times-Italic def
+/B /Times-Bold def
+/BI /Times-BoldItalic def
+/H /Helvetica def
+/HI /Helvetica-Oblique def
+/HB /Helvetica-Bold def
+/HX /Helvetica-BoldOblique def
+/CW /Courier def
+/CO /Courier def
+/CI /Courier-Oblique def
+/CB /Courier-Bold def
+/CX /Courier-BoldOblique def
+/PA /Palatino-Roman def
+/PI /Palatino-Italic def
+/PB /Palatino-Bold def
+/PX /Palatino-BoldItalic def
+/Hr /Helvetica-Narrow def
+/Hi /Helvetica-Narrow-Oblique def
+/Hb /Helvetica-Narrow-Bold def
+/Hx /Helvetica-Narrow-BoldOblique def
+/KR /Bookman-Light def
+/KI /Bookman-LightItalic def
+/KB /Bookman-Demi def
+/KX /Bookman-DemiItalic def
+/AR /AvantGarde-Book def
+/AI /AvantGarde-BookOblique def
+/AB /AvantGarde-Demi def
+/AX /AvantGarde-DemiOblique def
+/NR /NewCenturySchlbk-Roman def
+/NI /NewCenturySchlbk-Italic def
+/NB /NewCenturySchlbk-Bold def
+/NX /NewCenturySchlbk-BoldItalic def
+/ZD /ZapfDingbats def
+/ZI /ZapfChancery-MediumItalic def
+/S /S def
+/S1 /S1 def
+/GR /Symbol def
+
+/inch {72 mul} bind def
+/min {2 copy gt {exch} if pop} bind def
+
+/setup {
+ counttomark 2 idiv {def} repeat pop
+
+ landscape {/orientation 90 orientation add def} if
+ /scaling 72 resolution div def
+ linewidth setlinewidth
+ 1 setlinecap
+
+ pagedimensions
+ xcenter ycenter translate
+ orientation rotation mul rotate
+ width 2 div neg height 2 div translate
+ xoffset inch yoffset inch neg translate
+ margin 2 div dup neg translate
+ magnification dup aspectratio mul scale
+ scaling scaling scale
+
+ addmetrics
+ 0 0 moveto
+} def
+
+/pagedimensions {
+ useclippath userdict /gotpagebbox known not and {
+ /pagebbox [clippath pathbbox newpath] def
+ roundpage currentdict /roundpagebbox known and {roundpagebbox} if
+ } if
+ pagebbox aload pop
+ 4 -1 roll exch 4 1 roll 4 copy
+ landscape {4 2 roll} if
+ sub /width exch def
+ sub /height exch def
+ add 2 div /xcenter exch def
+ add 2 div /ycenter exch def
+ userdict /gotpagebbox true put
+} def
+
+/addmetrics {
+ /Symbol /S null Sdefs cf
+ /Times-Roman /S1 StandardEncoding dup length array copy S1defs cf
+} def
+
+/pagesetup {
+ /page exch def
+ currentdict /pagedict known currentdict page known and {
+ page load pagedict exch get cvx exec
+ } if
+} def
+
+/decodingdefs [
+ {counttomark 2 idiv {y moveto show} repeat}
+ {neg /y exch def counttomark 2 idiv {y moveto show} repeat}
+ {neg moveto {2 index stringwidth pop sub exch div 0 32 4 -1 roll widthshow} repeat}
+ {neg moveto {spacewidth sub 0.0 32 4 -1 roll widthshow} repeat}
+ {counttomark 2 idiv {y moveto show} repeat}
+ {neg setfunnytext}
+] def
+
+/setdecoding {/t decodingdefs 3 -1 roll get bind def} bind def
+
+/w {neg moveto show} bind def
+/m {neg dup /y exch def moveto} bind def
+/done {/lastpage where {pop lastpage} if} def
+
+/f {
+ dup /font exch def findfont exch
+ dup /ptsize exch def scaling div dup /size exch def scalefont setfont
+ linewidth ptsize mul scaling 10 mul div setlinewidth
+ /spacewidth ( ) stringwidth pop def
+} bind def
+
+/changefont {
+ /fontheight exch def
+ /fontslant exch def
+ currentfont [
+ 1 0
+ fontheight ptsize div fontslant sin mul fontslant cos div
+ fontheight ptsize div
+ 0 0
+ ] makefont setfont
+} bind def
+
+/sf {f} bind def
+
+/cf {
+ dup length 2 idiv
+ /entries exch def
+ /chtab exch def
+ /newencoding exch def
+ /newfont exch def
+
+ findfont dup length 1 add dict
+ /newdict exch def
+ {1 index /FID ne {newdict 3 1 roll put}{pop pop} ifelse} forall
+
+ newencoding type /arraytype eq {newdict /Encoding newencoding put} if
+
+ newdict /Metrics entries dict put
+ newdict /Metrics get
+ begin
+ chtab aload pop
+ 1 1 entries {pop def} for
+ newfont newdict definefont pop
+ end
+} bind def
+
+%
+% A few arrays used to adjust reference points and character widths in some
+% of the printer resident fonts. If square roots are too high try changing
+% the lines describing /radical and /radicalex to,
+%
+% /radical [0 -75 550 0]
+% /radicalex [-50 -75 500 0]
+%
+% Move braceleftbt a bit - default PostScript character is off a bit.
+%
+
+/Sdefs [
+ /bracketlefttp [201 500]
+ /bracketleftbt [201 500]
+ /bracketrighttp [-81 380]
+ /bracketrightbt [-83 380]
+ /braceleftbt [203 490]
+ /bracketrightex [220 -125 500 0]
+ /radical [0 0 550 0]
+ /radicalex [-50 0 500 0]
+ /parenleftex [-20 -170 0 0]
+ /integral [100 -50 500 0]
+ /infinity [10 -75 730 0]
+] def
+
+/S1defs [
+ /underscore [0 80 500 0]
+ /endash [7 90 650 0]
+] def
+%
+% Tries to round clipping path dimensions, as stored in array pagebbox, so they
+% match one of the known sizes in the papersizes array. Lower left coordinates
+% are always set to 0.
+%
+
+/roundpagebbox {
+ 7 dict begin
+ /papersizes [8.5 inch 11 inch 14 inch 17 inch] def
+
+ /mappapersize {
+ /val exch def
+ /slop .5 inch def
+ /diff slop def
+ /j 0 def
+ 0 1 papersizes length 1 sub {
+ /i exch def
+ papersizes i get val sub abs
+ dup diff le {/diff exch def /j i def} {pop} ifelse
+ } for
+ diff slop lt {papersizes j get} {val} ifelse
+ } def
+
+ pagebbox 0 0 put
+ pagebbox 1 0 put
+ pagebbox dup 2 get mappapersize 2 exch put
+ pagebbox dup 3 get mappapersize 3 exch put
+ end
+} bind def
+
+%%EndProlog
+%%BeginSetup
+mark
+%
+% Encoding vector and redefinition of findfont for the ISO Latin1 standard.
+% The 18 characters missing from ROM based fonts on older printers are noted
+% below.
+%
+
+/ISOLatin1Encoding [
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /space
+ /exclam
+ /quotedbl
+ /numbersign
+ /dollar
+ /percent
+ /ampersand
+ /quoteright
+ /parenleft
+ /parenright
+ /asterisk
+ /plus
+ /comma
+ /minus
+ /period
+ /slash
+ /zero
+ /one
+ /two
+ /three
+ /four
+ /five
+ /six
+ /seven
+ /eight
+ /nine
+ /colon
+ /semicolon
+ /less
+ /equal
+ /greater
+ /question
+ /at
+ /A
+ /B
+ /C
+ /D
+ /E
+ /F
+ /G
+ /H
+ /I
+ /J
+ /K
+ /L
+ /M
+ /N
+ /O
+ /P
+ /Q
+ /R
+ /S
+ /T
+ /U
+ /V
+ /W
+ /X
+ /Y
+ /Z
+ /bracketleft
+ /backslash
+ /bracketright
+ /asciicircum
+ /underscore
+ /quoteleft
+ /a
+ /b
+ /c
+ /d
+ /e
+ /f
+ /g
+ /h
+ /i
+ /j
+ /k
+ /l
+ /m
+ /n
+ /o
+ /p
+ /q
+ /r
+ /s
+ /t
+ /u
+ /v
+ /w
+ /x
+ /y
+ /z
+ /braceleft
+ /bar
+ /braceright
+ /asciitilde
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /dotlessi
+ /grave
+ /acute
+ /circumflex
+ /tilde
+ /macron
+ /breve
+ /dotaccent
+ /dieresis
+ /.notdef
+ /ring
+ /cedilla
+ /.notdef
+ /hungarumlaut
+ /ogonek
+ /caron
+ /space
+ /exclamdown
+ /cent
+ /sterling
+ /currency
+ /yen
+ /brokenbar % missing
+ /section
+ /dieresis
+ /copyright
+ /ordfeminine
+ /guillemotleft
+ /logicalnot
+ /hyphen
+ /registered
+ /macron
+ /degree % missing
+ /plusminus % missing
+ /twosuperior % missing
+ /threesuperior % missing
+ /acute
+ /mu % missing
+ /paragraph
+ /periodcentered
+ /cedilla
+ /onesuperior % missing
+ /ordmasculine
+ /guillemotright
+ /onequarter % missing
+ /onehalf % missing
+ /threequarters % missing
+ /questiondown
+ /Agrave
+ /Aacute
+ /Acircumflex
+ /Atilde
+ /Adieresis
+ /Aring
+ /AE
+ /Ccedilla
+ /Egrave
+ /Eacute
+ /Ecircumflex
+ /Edieresis
+ /Igrave
+ /Iacute
+ /Icircumflex
+ /Idieresis
+ /Eth % missing
+ /Ntilde
+ /Ograve
+ /Oacute
+ /Ocircumflex
+ /Otilde
+ /Odieresis
+ /multiply % missing
+ /Oslash
+ /Ugrave
+ /Uacute
+ /Ucircumflex
+ /Udieresis
+ /Yacute % missing
+ /Thorn % missing
+ /germandbls
+ /agrave
+ /aacute
+ /acircumflex
+ /atilde
+ /adieresis
+ /aring
+ /ae
+ /ccedilla
+ /egrave
+ /eacute
+ /ecircumflex
+ /edieresis
+ /igrave
+ /iacute
+ /icircumflex
+ /idieresis
+ /eth % missing
+ /ntilde
+ /ograve
+ /oacute
+ /ocircumflex
+ /otilde
+ /odieresis
+ /divide % missing
+ /oslash
+ /ugrave
+ /uacute
+ /ucircumflex
+ /udieresis
+ /yacute % missing
+ /thorn % missing
+ /ydieresis
+] def
+
+/NewFontDirectory FontDirectory maxlength dict def
+
+%
+% Apparently no guarantee findfont is defined in systemdict so the obvious
+%
+% systemdict /findfont get exec
+%
+% can generate an error. So far the only exception is a VT600 (version 48.0).
+%
+
+userdict /@RealFindfont known not {
+ userdict begin
+ /@RealFindfont systemdict begin /findfont load end def
+ end
+} if
+
+/findfont {
+ dup NewFontDirectory exch known not {
+ dup
+ %dup systemdict /findfont get exec % not always in systemdict
+ dup userdict /@RealFindfont get exec
+ dup /Encoding get StandardEncoding eq {
+ dup length dict begin
+ {1 index /FID ne {def}{pop pop} ifelse} forall
+ /Encoding ISOLatin1Encoding def
+ currentdict
+ end
+ /DummyFontName exch definefont
+ } if
+ NewFontDirectory 3 1 roll put
+ } if
+ NewFontDirectory exch get
+} bind def
+
+%%Patch from lp
+%%EndPatch from lp
+
+setup
+%%EndSetup
+%%Page: 1 1
+/saveobj save def
+mark
+1 pagesetup
+12 /Palatino-Bold f
+(An Overview) 2149 1340 w
+(of) 2917 1340 w
+(Limbo/Tk) 3061 1340 w
+10 /Palatino-Italic f
+(Lucent Technologies Inc.) 2373 1556 w
+(Revised June 2000 by Vita Nuova) 2197 1676 w
+10 /Palatino-Bold f
+(Overview) 720 1988 w
+10 /Palatino-Roman f
+(Limbo/Tk) 720 2166 w
+(is) 1218 2166 w
+(a) 1322 2166 w
+(concise) 1405 2166 w
+(and) 1758 2166 w
+(powerful) 1960 2166 w
+(way) 2401 2166 w
+(to) 2623 2166 w
+(construct) 2744 2166 w
+(graphical) 3186 2166 w
+(user) 3635 2166 w
+(interfaces) 3858 2166 w
+(without) 4316 2166 w
+(directly) 4700 2166 w
+(using) 720 2286 w
+(the) 991 2286 w
+(Draw) 1156 2286 w
+(module) 1432 2286 w
+(primitives.) 1799 2286 w
+(Standard interfaces can quickly be created from collections of) 2330 2286 w
+(menus,) 720 2406 w
+(buttons,) 1073 2406 w
+(and) 1466 2406 w
+(other) 1667 2406 w
+(widgets) 1933 2406 w
+(that) 2317 2406 w
+(are) 2523 2406 w
+(part) 2693 2406 w
+(of) 2908 2406 w
+(Limbo/Tk's) 3029 2406 w
+(visual) 3598 2406 w
+(toolkit.) 3898 2406 w
+(It) 4271 2406 w
+(is) 4371 2406 w
+(modelled) 4475 2406 w
+(on) 4927 2406 w
+(Ousterhout's) 720 2526 w
+(Tk) 1351 2526 w
+(4.0) 1521 2526 w
+([1,2],) 1699 2526 w
+(commonly) 1968 2526 w
+(deployed) 2494 2526 w
+(with) 2965 2526 w
+(the) 3221 2526 w
+(scripting) 3413 2526 w
+(language) 3857 2526 w
+(Tcl) 4317 2526 w
+(as) 4503 2526 w
+(`Tcl/Tk'.) 4647 2526 w
+(Although) 720 2646 w
+(inspired) 1174 2646 w
+(by) 1568 2646 w
+(Tk) 1706 2646 w
+(4.0,) 1850 2646 w
+(Inferno's) 2027 2646 w
+(Tk) 2450 2646 w
+(implementation) 2594 2646 w
+(is) 3328 2646 w
+(new,) 3427 2646 w
+(and) 3669 2646 w
+(unrelated) 3866 2646 w
+(to) 4321 2646 w
+(Ousterhout's.) 4437 2646 w
+(It) 720 2766 w
+(is) 818 2766 w
+(intended) 920 2766 w
+(to) 1347 2766 w
+(be) 1466 2766 w
+(used) 1600 2766 w
+(with) 1842 2766 w
+(the) 2075 2766 w
+(new) 2244 2766 w
+(programming) 2463 2766 w
+(language) 3113 2766 w
+(Limbo,) 3550 2766 w
+(not) 3893 2766 w
+(Tcl.) 4069 2766 w
+(Limbo/Tk) 4283 2766 w
+(appli\255) 4779 2766 w
+(cations) 720 2886 w
+(make) 1071 2886 w
+(extensive) 1353 2886 w
+(use) 1808 2886 w
+(of) 1999 2886 w
+(Limbo's) 2128 2886 w
+(concurrent) 2527 2886 w
+(programming) 3048 2886 w
+(constructions) 3709 2886 w
+(and) 4343 2886 w
+(data) 4553 2886 w
+(struc\255) 4788 2886 w
+(tures,) 720 3006 w
+(and) 994 3006 w
+(that) 1189 3006 w
+(is reflected in the interface.) 1389 3006 w
+(Section 9 of Volume 1 of the) 2628 3006 w
+10 /Palatino-Italic f
+(Inferno Programmer's Man\255) 3890 3006 w
+(ual) 720 3126 w
+10 /Palatino-Roman f
+(provides) 891 3126 w
+(a) 1318 3126 w
+(detailed) 1404 3126 w
+(reference) 1799 3126 w
+(for) 2242 3126 w
+(Limbo/Tk.) 2406 3126 w
+(This) 2958 3126 w
+(paper) 3184 3126 w
+(provides) 3478 3126 w
+(an) 3906 3126 w
+(overview) 4050 3126 w
+(of) 4503 3126 w
+(its) 4627 3126 w
+(use) 4767 3126 w
+(in) 4953 3126 w
+(some) 720 3246 w
+(simple) 996 3246 w
+(staged) 1335 3246 w
+(examples,) 1668 3246 w
+(and) 2152 3246 w
+(concludes) 2363 3246 w
+(with) 2846 3246 w
+(a) 3091 3246 w
+(summary) 3183 3246 w
+(of) 3649 3246 w
+(the) 3779 3246 w
+(differences) 3960 3246 w
+(between) 4486 3246 w
+(the) 4901 3246 w
+(Limbo/Tk) 720 3366 w
+(implementation) 1213 3366 w
+(and) 1946 3366 w
+(Tk) 2142 3366 w
+(4.0.) 2286 3366 w
+(In) 2488 3366 w
+(the) 2608 3366 w
+(rest) 2775 3366 w
+(of) 2966 3366 w
+(this) 3082 3366 w
+(paper,) 3272 3366 w
+(`Tk') 3583 3366 w
+(refers) 3784 3366 w
+(to) 4063 3366 w
+(Limbo/Tk,) 4179 3366 w
+(and) 4698 3366 w
+(`Tk) 4895 3366 w
+(4.0' refers to Ousterhout's original implementation.) 720 3486 w
+10 /Palatino-Bold f
+(1.) 720 3798 w
+(The Limbo/Tk environment) 845 3798 w
+10 /Palatino-Roman f
+(Limbo) 720 3976 w
+(applications) 1035 3976 w
+(access) 1601 3976 w
+(Tk) 1898 3976 w
+(by) 2042 3976 w
+(means) 2180 3976 w
+(of) 2494 3976 w
+(a) 2610 3976 w
+(built\255in) 2688 3976 w
+(module,) 3042 3976 w
+10 /Courier f
+($Tk) 3436 3976 w
+10 /Palatino-Roman f
+(.) 3616 3976 w
+(The) 3694 3976 w
+(standard) 3889 3976 w
+(distribution) 4312 3976 w
+(also) 4864 3976 w
+(includes) 720 4096 w
+(the) 1121 4096 w
+(window) 1290 4096 w
+(manager) 1689 4096 w
+10 /Courier f
+(wm) 2109 4096 w
+10 /Palatino-Roman f
+(and) 2259 4096 w
+(the) 2458 4096 w
+(Limbo) 2627 4096 w
+(module) 2945 4096 w
+10 /Courier f
+(Wmlib) 3316 4096 w
+10 /Palatino-Roman f
+(.) 3616 4096 w
+(Unlike) 3696 4096 w
+10 /Courier f
+(Tk) 4023 4096 w
+10 /Palatino-Roman f
+(,) 4143 4096 w
+10 /Courier f
+(Wmlib) 4197 4096 w
+10 /Palatino-Roman f
+(is) 4526 4096 w
+(not) 4626 4096 w
+(built\255) 4801 4096 w
+(in) 720 4216 w
+(but) 839 4216 w
+(implemented) 1019 4216 w
+(in) 1641 4216 w
+(Limbo) 1760 4216 w
+(by) 2080 4216 w
+10 /Courier f
+(/appl/lib/wmlib.b) 2223 4216 w
+10 /Palatino-Roman f
+(.) 3243 4216 w
+(It) 3325 4216 w
+(simplifies) 3425 4216 w
+(and) 3887 4216 w
+(standardises) 4089 4216 w
+(the) 4678 4216 w
+(con\255) 4850 4216 w
+(struction) 720 4336 w
+(of) 1144 4336 w
+(windowed) 1262 4336 w
+(applications;) 1770 4336 w
+(it) 2364 4336 w
+(also) 2456 4336 w
+(contains) 2662 4336 w
+(some) 3061 4336 w
+(graphical) 3324 4336 w
+(devices) 3770 4336 w
+(such) 4128 4336 w
+(as) 4361 4336 w
+(tabbed) 4482 4336 w
+(note\255) 4813 4336 w
+(books) 720 4456 w
+(not) 1018 4456 w
+(provided) 1199 4456 w
+(directly) 1645 4456 w
+(by) 2020 4456 w
+(Limbo/Tk.) 2167 4456 w
+(The) 2719 4456 w
+(essentials) 2922 4456 w
+(of) 3379 4456 w
+(both) 3503 4456 w
+10 /Courier f
+(Tk) 3740 4456 w
+10 /Palatino-Roman f
+(and) 3896 4456 w
+10 /Courier f
+(Wmlib) 4101 4456 w
+10 /Palatino-Roman f
+(are) 4437 4456 w
+(discussed) 4611 4456 w
+(here.) 720 4576 w
+(Programmers usually need only three functions from the) 720 4754 w
+10 /Courier f
+(Tk) 3260 4754 w
+10 /Palatino-Roman f
+(module:) 3405 4754 w
+10 /LucidaSansUnicode20 f
+(") 720 4932 w
+10 /Courier f
+(toplevel) 970 4932 w
+10 /Palatino-Roman f
+(Creates) 970 5052 w
+(a) 1354 5052 w
+(graphical) 1456 5052 w
+(window) 1925 5052 w
+10 /LucidaSansUnicode20 f
+(\023) 2347 5052 w
+10 /Palatino-Roman f
+(a) 2450 5052 w
+(Tk) 2553 5052 w
+(`top) 2723 5052 w
+(level') 2952 5052 w
+(widget) 3244 5052 w
+10 /LucidaSansUnicode20 f
+(\023) 3607 5052 w
+10 /Palatino-Roman f
+(that) 3710 5052 w
+(can) 3937 5052 w
+(be) 4142 5052 w
+(used) 4298 5052 w
+(to) 4562 5052 w
+(build) 4703 5052 w
+(a) 4990 5052 w
+(Limbo/Tk) 970 5172 w
+(application.) 1467 5172 w
+(The) 2045 5172 w
+(function) 2243 5172 w
+(returns) 2644 5172 w
+(a) 2995 5172 w
+(reference) 3075 5172 w
+(to) 3512 5172 w
+(an) 3630 5172 w
+(adt) 3768 5172 w
+10 /Courier f
+(Tk\255>Toplevel) 3942 5172 w
+10 /Palatino-Roman f
+(adt) 4692 5172 w
+(that) 4866 5172 w
+(represents the window in subsequent Tk operations.) 970 5292 w
+10 /LucidaSansUnicode20 f
+(") 720 5470 w
+10 /Courier f
+(cmd) 970 5470 w
+10 /Palatino-Roman f
+(Creates) 970 5590 w
+(and) 1332 5590 w
+(arranges) 1532 5590 w
+(graphic) 1947 5590 w
+(objects) 2315 5590 w
+(within) 2646 5590 w
+(the) 2967 5590 w
+(toplevel) 3137 5590 w
+(window) 3527 5590 w
+(by) 3927 5590 w
+(processing) 4069 5590 w
+(Limbo/Tk) 4574 5590 w
+(command) 970 5710 w
+(strings.) 1442 5710 w
+(The) 1820 5710 w
+(interface) 2015 5710 w
+(to) 2426 5710 w
+(Tk) 2542 5710 w
+(is) 2687 5710 w
+(primarily) 2786 5710 w
+(the) 3235 5710 w
+(passing) 3402 5710 w
+(of) 3767 5710 w
+(strings) 3883 5710 w
+(between) 4211 5710 w
+(the) 4612 5710 w
+(appli\255) 4779 5710 w
+(cation) 970 5830 w
+(and) 1274 5830 w
+(Tk) 1478 5830 w
+(of) 1630 5830 w
+(the) 1753 5830 w
+(toolkit) 1927 5830 w
+(using) 2252 5830 w
+10 /Courier f
+(cmd) 2532 5830 w
+10 /Palatino-Roman f
+(.) 2712 5830 w
+(Each) 2797 5830 w
+(call) 3045 5830 w
+(to) 3232 5830 w
+10 /Courier f
+(cmd) 3355 5830 w
+10 /Palatino-Roman f
+(returns) 3570 5830 w
+(a) 3926 5830 w
+(string) 4011 5830 w
+(representing) 4305 5830 w
+(the) 4901 5830 w
+(result of the Tk command; a string starting with `) 970 5950 w
+10 /Courier f
+(!) 3140 5950 w
+10 /Palatino-Roman f
+(' diagnoses an error.) 3200 5950 w
+10 /LucidaSansUnicode20 f
+(") 720 6128 w
+10 /Courier f
+(namechan) 970 6128 w
+10 /Palatino-Roman f
+(Gives) 970 6248 w
+(a) 1257 6248 w
+(name) 1342 6248 w
+(within) 1621 6248 w
+(Tk) 1946 6248 w
+(\(in) 2098 6248 w
+(the) 2253 6248 w
+(scope) 2427 6248 w
+(of) 2712 6248 w
+(a) 2836 6248 w
+(given) 2922 6248 w
+(window\)) 3206 6248 w
+(to) 3644 6248 w
+(a) 3768 6248 w
+(Limbo) 3854 6248 w
+10 /Courier f
+(chan) 4178 6248 w
+(of) 4489 6248 w
+(string) 4680 6248 w
+10 /Palatino-Roman f
+(that Tk commands can use to send data to a Limbo program.) 970 6368 w
+(Other) 720 6546 w
+(functions) 1014 6546 w
+(in) 1462 6546 w
+(the) 1585 6546 w
+(module) 1760 6546 w
+(have) 2137 6546 w
+(more) 2386 6546 w
+(specialised) 2653 6546 w
+(uses) 3172 6546 w
+(that) 3401 6546 w
+(will) 3612 6546 w
+(not) 3819 6546 w
+(be) 4002 6546 w
+(discussed) 4142 6546 w
+(here.) 4608 6546 w
+(For) 4889 6546 w
+(instance,) 720 6666 w
+10 /Courier f
+(mouse) 1146 6666 w
+10 /Palatino-Roman f
+(and) 1485 6666 w
+10 /Courier f
+(keyboard) 1693 6666 w
+10 /Palatino-Roman f
+(are) 2211 6666 w
+(used) 2387 6666 w
+(by) 2636 6666 w
+(a) 2785 6666 w
+(window) 2873 6666 w
+(manager) 3280 6666 w
+(to) 3708 6666 w
+(send) 3834 6666 w
+(mouse) 4081 6666 w
+(and) 4412 6666 w
+(keyboard) 4619 6666 w
+(events to the Tk implementation for distribution to applications.) 720 6786 w
+(Even) 720 6964 w
+10 /Courier f
+(toplevel) 1003 6964 w
+10 /Palatino-Roman f
+(is) 1542 6964 w
+(not) 1672 6964 w
+(commonly) 1877 6964 w
+(used) 2409 6964 w
+(in) 2679 6964 w
+(the) 2825 6964 w
+(window) 3024 6964 w
+(manager) 3453 6964 w
+(environment:) 3903 6964 w
+(a) 4560 6964 w
+(function) 4670 6964 w
+10 /Courier f
+(Wmlib\255>titlebar) 720 7084 w
+10 /Palatino-Roman f
+(provides) 1658 7084 w
+(the) 2088 7084 w
+(usual) 2265 7084 w
+(interface) 2544 7084 w
+(to) 2965 7084 w
+10 /Courier f
+(toplevel) 3091 7084 w
+10 /Palatino-Roman f
+(.) 3571 7084 w
+(The) 3658 7084 w
+(low\255level) 3862 7084 w
+(interface) 4310 7084 w
+(will) 4730 7084 w
+(be) 4937 7084 w
+(described first, for completeness, then the normal case using) 720 7204 w
+10 /Courier f
+(titlebar) 3408 7204 w
+10 /Palatino-Roman f
+(.) 3888 7204 w
+cleartomark
+showpage
+saveobj restore
+%%EndPage: 1 1
+%%Page: 2 2
+/saveobj save def
+mark
+2 pagesetup
+10 /Palatino-Roman f
+(\255 2 \255) 2797 480 w
+10 /Palatino-Bold f
+(2.) 720 840 w
+(Basic Limbo/Tk) 845 840 w
+10 /Palatino-Roman f
+(This section shows a simple Tk application that uses only the fundamental Tk functions.) 720 999 w
+10 /Palatino-Bold f
+(2.1.) 720 1250 w
+(Preliminaries) 920 1250 w
+10 /Palatino-Roman f
+(The example assumes that the) 720 1409 w
+10 /Courier f
+(Tk) 2072 1409 w
+10 /Palatino-Roman f
+(module is loaded as) 2217 1409 w
+10 /Courier f
+(tk) 3125 1409 w
+10 /Palatino-Roman f
+(:) 3245 1409 w
+9 /Courier f
+(include "tk.m";) 864 1574 w
+(tk: Tk;) 1080 1674 w
+(...) 1080 1774 w
+(init\(ctxt: ref Draw\255>Context, nil: list of string\)) 864 1874 w
+({) 864 1974 w
+(tk =) 1080 2074 w
+(load Tk Tk\255>PATH;) 1404 2074 w
+(...) 1080 2174 w
+(}) 864 2274 w
+10 /Palatino-Bold f
+(2.2.) 720 2525 w
+(Creating a toplevel) 920 2525 w
+10 /Palatino-Roman f
+(The) 720 2684 w
+(following) 917 2684 w
+(fragment) 1374 2684 w
+(makes) 1810 2684 w
+(the) 2124 2684 w
+(Limbo) 2293 2684 w
+(identifier) 2611 2684 w
+10 /Courier f
+(top) 3049 2684 w
+10 /Palatino-Roman f
+(refer) 3259 2684 w
+(to) 3498 2684 w
+(a) 3616 2684 w
+(new) 3696 2684 w
+10 /Courier f
+(ref) 3915 2684 w
+(Tk\255>Toplevel) 4161 2684 w
+10 /Palatino-Roman f
+(for) 4912 2684 w
+(use in later Tk commands:) 720 2804 w
+9 /Courier f
+(top := tk\255>toplevel\(ctxt.screen, "\255x 150 \255y 150"\);) 1080 2969 w
+10 /Palatino-Roman f
+(The) 720 3154 w
+(upper) 917 3154 w
+(left) 1215 3154 w
+(corner) 1388 3154 w
+(of) 1703 3154 w
+(this) 1821 3154 w
+(window) 2013 3154 w
+(will) 2412 3154 w
+(be) 2612 3154 w
+(at) 2745 3154 w
+(point) 2858 3154 w
+(\(150,) 3123 3154 w
+(150\),) 3361 3154 w
+(where) 3599 3154 w
+(\(0,0\)) 3906 3154 w
+(is) 4127 3154 w
+(the) 4228 3154 w
+(upper) 4397 3154 w
+(left) 4695 3154 w
+(cor\255) 4868 3154 w
+(ner) 720 3274 w
+(of) 894 3274 w
+(the) 1010 3274 w
+(screen;) 1177 3274 w
+10 /Palatino-Italic f
+(x) 1510 3274 w
+10 /Palatino-Roman f
+(coordinates) 1596 3274 w
+(increase) 2139 3274 w
+(from) 2526 3274 w
+(left) 2770 3274 w
+(to) 2941 3274 w
+(right,) 3057 3274 w
+(and) 3325 3274 w
+10 /Palatino-Italic f
+(y) 3521 3274 w
+10 /Palatino-Roman f
+(coordinates) 3606 3274 w
+(increase) 4148 3274 w
+(from) 4534 3274 w
+(top) 4777 3274 w
+(to) 4952 3274 w
+(bottom.) 720 3394 w
+(In) 720 3553 w
+(general,) 841 3553 w
+10 /Courier f
+(Tk\255>toplevel) 1224 3553 w
+10 /Palatino-Roman f
+(takes) 1973 3553 w
+(a) 2231 3553 w
+(screen) 2310 3553 w
+(argument) 2619 3553 w
+(and) 3081 3553 w
+(a) 3279 3553 w
+(string) 3358 3553 w
+(containing) 3645 3553 w
+(further) 4144 3553 w
+(options,) 4485 3553 w
+(and) 4871 3553 w
+(it) 720 3673 w
+(returns) 810 3673 w
+(a) 1159 3673 w
+(reference) 1237 3673 w
+(to) 1672 3673 w
+(a) 1788 3673 w
+(top\255level) 1866 3673 w
+(Limbo/Tk) 2286 3673 w
+(widget) 2779 3673 w
+(on) 3116 3673 w
+(the) 3256 3673 w
+(given) 3422 3673 w
+(screen.) 3697 3673 w
+(The) 4054 3673 w
+(options) 4248 3673 w
+(argument) 4607 3673 w
+(contains) 720 3793 w
+10 /Courier f
+(\255option) 1141 3793 w
+10 /Palatino-Italic f
+(value) 1613 3793 w
+10 /Palatino-Roman f
+(pairs,) 1890 3793 w
+(such) 2188 3793 w
+(as) 2444 3793 w
+10 /Courier f
+(\255relief) 2588 3793 w
+(raised) 3095 3793 w
+10 /Palatino-Roman f
+(.) 3455 3793 w
+(As) 3557 3793 w
+(well) 3729 3793 w
+(as) 3970 3793 w
+(the) 4115 3793 w
+(generic) 4307 3793 w
+(options,) 4683 3793 w
+10 /Courier f
+(toplevel) 720 3913 w
+10 /Palatino-Roman f
+(accepts) 1234 3913 w
+(the) 1589 3913 w
+(options) 1762 3913 w
+10 /Courier f
+(\255x) 2128 3913 w
+10 /Palatino-Italic f
+(int) 2282 3913 w
+10 /Palatino-Roman f
+(and) 2441 3913 w
+10 /Courier f
+(\255y) 2644 3913 w
+10 /Palatino-Italic f
+(int) 2797 3913 w
+10 /Palatino-Roman f
+(to) 2955 3913 w
+(specify) 3076 3913 w
+(the) 3421 3913 w
+(upper) 3593 3913 w
+(left) 3894 3913 w
+(corner) 4070 3913 w
+(of) 4388 3913 w
+(the) 4509 3913 w
+(toplevel) 4681 3913 w
+(widget,) 720 4033 w
+(where) 1084 4033 w
+(\(0,0\)) 1390 4033 w
+(is) 1610 4033 w
+(the) 1710 4033 w
+(top) 1878 4033 w
+(left) 2055 4033 w
+(corner) 2227 4033 w
+(of) 2541 4033 w
+(the) 2658 4033 w
+(screen,) 2826 4033 w
+(and) 3161 4033 w
+10 /Courier f
+(\255debug) 3360 4033 w
+10 /Palatino-Italic f
+(bool) 3750 4033 w
+10 /Palatino-Roman f
+(to) 3950 4033 w
+(cause) 4068 4033 w
+(a) 4342 4033 w
+(trace) 4422 4033 w
+(of) 4667 4033 w
+(all) 4785 4033 w
+(Tk) 4923 4033 w
+(commands to be printed, if the boolean value is true.) 720 4153 w
+10 /Palatino-Bold f
+(2.3.) 720 4404 w
+(Creating a named channel to Tk) 920 4404 w
+10 /Palatino-Roman f
+(The) 720 4563 w
+(following) 915 4563 w
+(fragment) 1370 4563 w
+(creates) 1804 4563 w
+(a) 2137 4563 w
+10 /Courier f
+(chan) 2215 4563 w
+(of) 2518 4563 w
+(string) 2701 4563 w
+10 /Palatino-Roman f
+(called) 3089 4563 w
+10 /Courier f
+(c) 3378 4563 w
+10 /Palatino-Roman f
+(,) 3438 4563 w
+(then) 3491 4563 w
+(associates) 3716 4563 w
+(the) 4179 4563 w
+(name) 4347 4563 w
+10 /Courier f
+(cmdchan) 4620 4563 w
+10 /Palatino-Roman f
+(within Tk with the Limbo channel) 720 4683 w
+10 /Courier f
+(c) 2252 4683 w
+10 /Palatino-Roman f
+(:) 2312 4683 w
+9 /Courier f
+(c := chan of string;) 1080 4848 w
+(tk\255>namechan\(top, c, "cmdchan"\);) 1080 4948 w
+10 /Palatino-Roman f
+(The) 720 5133 w
+(named) 916 5133 w
+(channel) 1250 5133 w
+10 /Courier f
+(cmdchan) 1624 5133 w
+10 /Palatino-Roman f
+(can) 2073 5133 w
+(now) 2254 5133 w
+(be) 2479 5133 w
+(used) 2611 5133 w
+(in) 2851 5133 w
+(a) 2967 5133 w
+(special) 3046 5133 w
+(Tk) 3377 5133 w
+10 /Courier f
+(send) 3523 5133 w
+10 /Palatino-Roman f
+(command) 3792 5133 w
+(to) 4265 5133 w
+(send) 4383 5133 w
+(strings) 4622 5133 w
+(to) 4952 5133 w
+(be) 720 5253 w
+(processed) 852 5253 w
+(by) 1321 5253 w
+(a) 1461 5253 w
+(Limbo) 1540 5253 w
+(program,) 1857 5253 w
+(typically) 2300 5253 w
+(notifying) 2715 5253 w
+(it) 3151 5253 w
+(of) 3242 5253 w
+(an) 3359 5253 w
+(event.) 3495 5253 w
+(Note) 3817 5253 w
+(that) 4064 5253 w
+(the) 4266 5253 w
+(Limbo) 4433 5253 w
+(identi\255) 4749 5253 w
+(fer) 720 5373 w
+(name) 868 5373 w
+(need) 1139 5373 w
+(not) 1381 5373 w
+(match) 1554 5373 w
+(the) 1854 5373 w
+(name) 2021 5373 w
+(given) 2293 5373 w
+(to) 2569 5373 w
+(Tk,) 2685 5373 w
+(although) 2855 5373 w
+(it) 3282 5373 w
+(is) 3372 5373 w
+(invariably) 3471 5373 w
+(easier) 3952 5373 w
+(to) 4237 5373 w
+(follow) 4353 5373 w
+(the) 4665 5373 w
+(code) 4832 5373 w
+(if the two are the same.) 720 5493 w
+10 /Palatino-Bold f
+(2.4.) 720 5744 w
+(Defining and positioning widgets) 920 5744 w
+10 /Palatino-Roman f
+(The) 720 5903 w
+(following) 916 5903 w
+(fragment) 1372 5903 w
+(uses) 1808 5903 w
+10 /Courier f
+(tk\255>cmd) 2030 5903 w
+10 /Palatino-Roman f
+(to) 2480 5903 w
+(define) 2598 5903 w
+(four) 2905 5903 w
+(widgets:) 3123 5903 w
+(two) 3530 5903 w
+(buttons,) 3731 5903 w
+(a) 4122 5903 w
+(label,) 4202 5903 w
+(and) 4468 5903 w
+(an) 4667 5903 w
+(entry) 4805 5903 w
+(widget.) 720 6023 w
+(The) 1096 6023 w
+(widgets) 1304 6023 w
+(are) 1697 6023 w
+(positioned) 1876 6023 w
+(in) 2387 6023 w
+(their) 2515 6023 w
+(parent) 2764 6023 w
+(window) 3094 6023 w
+(\(in) 3504 6023 w
+(this) 3665 6023 w
+(case) 3868 6023 w
+(the) 4093 6023 w
+(toplevel) 4272 6023 w
+(window) 4671 6023 w
+10 /Courier f
+(top) 720 6143 w
+10 /Palatino-Roman f
+(\) using the Tk command) 900 6143 w
+10 /Courier f
+(pack) 2003 6143 w
+10 /Palatino-Roman f
+(:) 2243 6143 w
+8 /Palatino-Italic f
+(# define widgets) 1080 6298 w
+8 /Courier f
+(tk\255>cmd\(top, "button .b1 \255text Exit \255command {send cmdchan exit}"\);) 1080 6388 w
+(tk\255>cmd\(top, "button .b2 \255text Send \255command {send cmdchan send}"\);) 1080 6478 w
+(tk\255>cmd\(top, "label .l \255text {Name: }"\);) 1080 6568 w
+(tk\255>cmd\(top, "entry .e"\);) 1080 6658 w
+8 /Palatino-Italic f
+(# bind newline character in) 1080 6838 w
+(entry widget to command) 1980 6838 w
+8 /Courier f
+(tk\255>cmd\(top, "bind .e <Key\255\\n> {send cmdchan send}"\);) 1080 6928 w
+8 /Palatino-Italic f
+(# pack widgets) 1080 7108 w
+8 /Courier f
+(tk\255>cmd\(top, "pack .b1 .b2 .l .e \255side left; update"\);) 1080 7198 w
+cleartomark
+showpage
+saveobj restore
+%%EndPage: 2 2
+%%Page: 3 3
+/saveobj save def
+mark
+3 pagesetup
+10 /Palatino-Roman f
+(\255 3 \255) 2797 480 w
+cleartomark
+saveobj restore
+%ps_include: begin
+save
+/ed {exch def} def
+{} /showpage ed
+{} /copypage ed
+{} /erasepage ed
+{} /letter ed
+currentdict /findfont known systemdict /findfont known and {
+ /findfont systemdict /findfont get def
+} if
+36 dict dup /PS-include-dict-dw ed begin
+/context ed
+count array astore /o-stack ed
+%ps_include: variables begin
+/llx 0 def
+/lly 0 def
+/urx 2691 def
+/ury 216 def
+/w 0 def
+/o 0 def
+/s 0 def
+/cx 2880 def
+/cy -1035.5 def
+/sx 4320 def
+/sy 151 def
+/ax .5 def
+/ay .5 def
+/rot 0 def
+%ps_include: variables end
+{llx lly urx ury} /bbox ed
+{newpath 2 index exch 2 index exch dup 6 index exch
+ moveto 3 {lineto} repeat closepath} /boxpath ed
+{dup mul exch dup mul add sqrt} /len ed
+{2 copy gt {exch} if pop} /min ed
+{2 copy lt {exch} if pop} /max ed
+{transform round exch round exch A itransform} /nice ed
+{6 array} /n ed
+n defaultmatrix n currentmatrix n invertmatrix n concatmatrix /A ed
+urx llx sub 0 A dtransform len /Sx ed
+0 ury lly sub A dtransform len /Sy ed
+llx urx add 2 div lly ury add 2 div A transform /Cy ed /Cx ed
+rot dup sin abs /S ed cos abs /C ed
+Sx S mul Sy C mul add /H ed
+Sx C mul Sy S mul add /W ed
+sy H div /Scaley ed
+sx W div /Scalex ed
+s 0 eq {Scalex Scaley min dup /Scalex ed /Scaley ed} if
+sx Scalex W mul sub 0 max ax 0.5 sub mul cx add /cx ed
+sy Scaley H mul sub 0 max ay 0.5 sub mul cy add /cy ed
+urx llx sub 0 A dtransform exch atan rot exch sub /rot ed
+n currentmatrix initgraphics setmatrix
+cx cy translate
+Scalex Scaley scale
+rot rotate
+Cx neg Cy neg translate
+A concat
+bbox boxpath clip newpath
+w 0 ne {gsave bbox boxpath 1 setgray fill grestore} if
+end
+gsave
+%ps_include: inclusion begin
+ %!
+ %%BoundingBox: 0 0 2691 216
+/picstr 299 string def
+2691 216 scale
+299 24 8
+[ 299 0 0 -24 0 24 ]
+{ currentfile picstr readhexstring pop }
+false 3 colorimage
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffff808080ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080
+808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080
+808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080
+808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080
+808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080
+808080808080808080808080808080808080808080808080808080ffffffc0c0c0c0c0c0ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0ffffffc0c0c0c0c0c0ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080ffffffffffff
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0ffffff
+c0c0c0c0c0c0ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0ffffffc0c0c0c0c0c0ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0ffffffc0c0c0c0c0c0ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080ffffff
+ffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+ffffffc0c0c0c0c0c0ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000000000000000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000000000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000000000c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0ffffffc0c0c0c0c0c0ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0
+000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0000000000000000000c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0ffffffc0c0c0c0c0c0ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0000000000000c0c0c0000000000000000000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080
+ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000000000000000c0c0c0c0c0c0000000000000c0c0c0000000000000c0c0c0c0c0c0c0c0c0c0c0c0000000000000000000
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000000000000000c0c0c0c0c0c0000000c0c0c0000000000000000000000000c0c0c0c0c0c0000000000000000000c0c0c0000000c0c0c0c0c0c0
+c0c0c0c0c0c0000000000000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0ffffffc0c0c0c0c0c0ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000000000000000000000c0c0c0c0c0c0c0c0c0000000000000c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000000000000000c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0000000000000c0c0c0000000
+000000c0c0c0c0c0c0000000000000c0c0c0000000000000c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0000000c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0
+c0c0c0000000c0c0c0c0c0c0000000c0c0c0000000000000000000000000c0c0c0000000000000c0c0c0c0c0c0000000000000c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0ffffffc0c0c0c0c0c0ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000000000
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000
+000000c0c0c0c0c0c0c0c0c0000000000000000000000000000000c0c0c0000000000000c0c0c0c0c0c0000000000000c0c0c0000000000000c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0000000c0c0c0c0c0c0000000c0c0c0000000c0c0c0000000000000000000000000c0c0c0c0c0c0000000c0c0c0000000000000000000000000c0c0c0000000000000000000000000000000000000c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0ffffffc0c0c0c0c0c0ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+808080ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000000000c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000000000c0c0c0c0c0c0000000000000c0c0c0000000000000c0c0c0c0c0c0
+000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0000000c0c0c0000000000000000000c0c0c0c0c0c0000000c0c0c0c0c0c0000000c0c0c0000000000000000000000000
+c0c0c0000000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0ffffffc0c0c0c0c0c0ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0000000000000c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0000000000000c0c0c0c0c0c0000000c0c0c0
+000000000000c0c0c0c0c0c0000000000000c0c0c0c0c0c0000000c0c0c0000000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0000000000000000000000000000000
+c0c0c0000000000000c0c0c0c0c0c0000000c0c0c0000000000000000000000000c0c0c0c0c0c0000000000000c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0ffffffc0c0c0c0c0c0ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000000000000000000000c0c0c0c0c0c0c0c0c0000000c0c0c0
+c0c0c0000000000000c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000000000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000
+000000000000c0c0c0c0c0c0c0c0c0c0c0c0000000000000000000c0c0c0c0c0c0000000000000c0c0c0c0c0c0000000000000c0c0c0c0c0c0c0c0c0000000c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0000000000000c0c0c0000000000000c0c0c0000000000000c0c0c0000000c0c0c0000000000000000000000000c0c0c0c0c0c0c0c0c0000000000000000000c0c0c0c0c0c0c0c0c0c0c0c0
+000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0ffffffc0c0c0c0c0c0ffffffffffffc0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0808080ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0ffffffc0c0c0c0c0c0ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0ffffffc0c0c0c0c0c0ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0ffffffc0c0c0c0c0c0ffffffffffffc0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0808080ffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0ffffffc0c0c0c0c0c0ffffffffffff808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080
+808080808080808080808080808080808080808080808080808080808080808080808080808080808080ffffffffffff808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080
+808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0c0c0c0c0c0ffffff808080808080808080808080808080808080808080808080808080808080808080808080808080
+808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080ffffff808080808080808080808080808080808080
+808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0808080ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+showpage
+%ps_include: inclusion end
+grestore
+PS-include-dict-dw begin
+o 0 ne {gsave A defaultmatrix /A ed llx lly nice urx ury nice
+ initgraphics 0.1 setlinewidth boxpath stroke grestore} if
+clear o-stack aload pop
+context end restore
+%ps_include: end
+/saveobj save def
+mark
+10 /Palatino-Roman f
+9 /Palatino-Italic f
+(Figure) 1942 1281 w
+(1.) 2205 1281 w
+(Two) 2296 1281 w
+(buttons,) 2479 1281 w
+(a) 2801 1281 w
+(label) 2864 1281 w
+(and) 3053 1281 w
+(an) 3211 1281 w
+(entry) 3324 1281 w
+(widget.) 3542 1281 w
+10 /Palatino-Roman f
+(This) 720 1464 w
+(particular) 938 1464 w
+(pack) 1401 1464 w
+(command) 1639 1464 w
+(packs) 2111 1464 w
+(the) 2391 1464 w
+(widgets) 2558 1464 w
+(named) 2938 1464 w
+10 /Courier f
+(.b1) 3271 1464 w
+10 /Palatino-Roman f
+(,) 3451 1464 w
+10 /Courier f
+(.b2) 3504 1464 w
+10 /Palatino-Roman f
+(,) 3684 1464 w
+10 /Courier f
+(.l) 3737 1464 w
+10 /Palatino-Roman f
+(,) 3857 1464 w
+(and) 3910 1464 w
+10 /Courier f
+(.e) 4107 1464 w
+10 /Palatino-Roman f
+(into) 4256 1464 w
+(the) 4460 1464 w
+10 /Courier f
+(top) 4628 1464 w
+10 /Palatino-Roman f
+(win\255) 4837 1464 w
+(dow) 720 1584 w
+(beginning) 948 1584 w
+(at) 1424 1584 w
+(the) 1536 1584 w
+(left) 1704 1584 w
+(side.) 1876 1584 w
+(The) 2110 1584 w
+10 /Courier f
+(update) 2306 1584 w
+10 /Palatino-Roman f
+(command) 2694 1584 w
+(forces) 3166 1584 w
+(Tk) 3456 1584 w
+(to) 3601 1584 w
+(update) 3717 1584 w
+(the) 4057 1584 w
+(screen) 4224 1584 w
+(right) 4532 1584 w
+(away.) 4776 1584 w
+(The result is shown in Figure 1.) 720 1704 w
+(Entering) 720 1862 w
+(a) 1135 1862 w
+(newline) 1217 1862 w
+(\(`return') 1602 1862 w
+(or) 2002 1862 w
+(`enter') 2129 1862 w
+(key\)) 2444 1862 w
+10 /LucidaSansUnicode20 f
+(\023) 2637 1862 w
+10 /Palatino-Roman f
+(the) 2687 1862 w
+(character) 2858 1862 w
+(`) 3297 1862 w
+10 /Courier f
+(\\n) 3325 1862 w
+10 /Palatino-Roman f
+(') 3445 1862 w
+(in) 3505 1862 w
+(Limbo) 3624 1862 w
+10 /LucidaSansUnicode20 f
+(\023) 3912 1862 w
+10 /Palatino-Roman f
+(in) 3994 1862 w
+(the) 4113 1862 w
+(entry) 4284 1862 w
+(box) 4551 1862 w
+(results) 4746 1862 w
+(in) 720 1982 w
+(the) 848 1982 w
+(execution) 1028 1982 w
+(of) 1496 1982 w
+(the) 1625 1982 w
+(Tk) 1805 1982 w
+(command) 1963 1982 w
+10 /Courier f
+({send) 2448 1982 w
+(cmdchan) 2824 1982 w
+(send}) 3320 1982 w
+10 /Palatino-Roman f
+(,) 3620 1982 w
+(because) 3686 1982 w
+(of) 4073 1982 w
+(the) 4201 1982 w
+(binding) 4380 1982 w
+(set) 4766 1982 w
+(by) 4929 1982 w
+10 /Courier f
+(bind) 720 2102 w
+(.e) 1034 2102 w
+(<Key\255\\n>) 1228 2102 w
+10 /Palatino-Roman f
+(previously) 1747 2102 w
+(executed) 2262 2102 w
+(by) 2695 2102 w
+10 /Courier f
+(tk\255>cmd) 2845 2102 w
+10 /Palatino-Roman f
+(.) 3265 2102 w
+(The) 3354 2102 w
+10 /Courier f
+(bind) 3560 2102 w
+10 /Palatino-Roman f
+(command) 3839 2102 w
+(is) 4323 2102 w
+(often) 4434 2102 w
+(used) 4701 2102 w
+(to) 4952 2102 w
+(bind) 720 2222 w
+(specific) 954 2222 w
+(widget) 1314 2222 w
+(events) 1655 2222 w
+(\(including) 1971 2222 w
+(key) 2458 2222 w
+(presses,) 2648 2222 w
+(mouse) 3025 2222 w
+(button) 3348 2222 w
+(presses,) 3672 2222 w
+(and) 4049 2222 w
+(mouse) 4248 2222 w
+(motion\)) 4571 2222 w
+(to) 4952 2222 w
+(Tk) 720 2342 w
+10 /Courier f
+(send) 862 2342 w
+10 /Palatino-Roman f
+(commands.) 1127 2342 w
+10 /Palatino-Bold f
+(2.5.) 720 2589 w
+(Processing widget events) 920 2589 w
+10 /Palatino-Roman f
+(This) 720 2747 w
+(next) 947 2747 w
+(fragment) 1175 2747 w
+(defines) 1618 2747 w
+(what) 1974 2747 w
+(will) 2236 2747 w
+(happen) 2444 2747 w
+(when) 2816 2747 w
+(a) 3101 2747 w
+(user) 3189 2747 w
+(selects) 3417 2747 w
+(either) 3741 2747 w
+(the) 4035 2747 w
+10 /Courier f
+(Exit) 4212 2747 w
+10 /Palatino-Roman f
+(or) 4490 2747 w
+(the) 4623 2747 w
+10 /Courier f
+(Send) 4800 2747 w
+10 /Palatino-Roman f
+(buttons.) 720 2867 w
+(The) 1115 2867 w
+10 /Courier f
+(Exit) 1316 2867 w
+10 /Palatino-Roman f
+(behaviour) 1590 2867 w
+(is) 2076 2867 w
+(simple:) 2181 2867 w
+(the) 2536 2867 w
+(program) 2709 2867 w
+(ends.) 3132 2867 w
+(If) 3400 2867 w
+(a) 3501 2867 w
+(user) 3585 2867 w
+(touches) 3808 2867 w
+10 /Courier f
+(Send) 4181 2867 w
+10 /Palatino-Roman f
+(,) 4421 2867 w
+(the) 4479 2867 w
+(program) 4651 2867 w
+(executes) 720 2987 w
+10 /Courier f
+(tk\255>cmd) 1120 2987 w
+10 /Palatino-Roman f
+(to get whatever text is in the entry widget) 1565 2987 w
+10 /Courier f
+(.e) 3440 2987 w
+10 /Palatino-Roman f
+(then prints it to standard output.) 3585 2987 w
+9 /Courier f
+(for\(;;\) {) 1080 3150 w
+(s := <\255 c;) 1296 3250 w
+(case s {) 1296 3350 w
+("exit" =>) 1296 3450 w
+(return;) 1512 3550 w
+("send" =>) 1296 3750 w
+(sys\255>print\("name was: %s\\n", tk\255>cmd\(top, ".e get"\)\);) 1512 3850 w
+(}) 1296 3950 w
+(}) 1080 4050 w
+10 /Palatino-Bold f
+(3.) 720 4297 w
+(Example \255 using Tk and Wmlib) 845 4297 w
+10 /Palatino-Roman f
+(This) 720 4455 w
+(section) 936 4455 w
+(uses) 1271 4455 w
+(both) 1490 4455 w
+(Tk) 1718 4455 w
+(and) 1862 4455 w
+(Wmlib) 2058 4455 w
+(to) 2386 4455 w
+(create) 2501 4455 w
+(a) 2791 4455 w
+(simple) 2868 4455 w
+(window) 3191 4455 w
+(manager) 3587 4455 w
+(application) 4004 4455 w
+(with) 4528 4455 w
+(a) 4758 4455 w
+(title\255) 4835 4455 w
+(bar, including resize and exit buttons.) 720 4575 w
+(This is the usual way to create new windows.) 2438 4575 w
+10 /Palatino-Bold f
+(4.) 720 4822 w
+(Preamble) 845 4822 w
+10 /Palatino-Roman f
+(The) 720 4980 w
+(example) 914 4980 w
+(assumes) 1316 4980 w
+(that) 1715 4980 w
+(the) 1916 4980 w
+10 /Courier f
+(Tk) 2082 4980 w
+10 /Palatino-Roman f
+(module) 2229 4980 w
+(is) 2597 4980 w
+(loaded) 2695 4980 w
+(as) 3026 4980 w
+(before,) 3145 4980 w
+(as) 3476 4980 w
+(module) 3595 4980 w
+(variable) 3963 4980 w
+10 /Courier f
+(tk) 4348 4980 w
+10 /Palatino-Roman f
+(,) 4468 4980 w
+(but) 4520 4980 w
+(further\255) 4695 4980 w
+(more that the) 720 5100 w
+10 /Courier f
+(Wmlib) 1339 5100 w
+10 /Palatino-Roman f
+(module is also loaded, as) 1664 5100 w
+10 /Courier f
+(wmlib) 2798 5100 w
+10 /Palatino-Roman f
+(:) 3098 5100 w
+9 /Courier f
+(include "tk.m";) 864 5263 w
+(tk: Tk;) 1080 5363 w
+(include "wmlib.m";) 864 5463 w
+(wmlib: Wmlib;) 1080 5563 w
+(...) 1080 5663 w
+(tk =) 1080 5763 w
+(load Tk) 1404 5763 w
+(Tk\255>PATH;) 1890 5763 w
+(wmlib = load Wmlib Wmlib\255>PATH;) 1080 5863 w
+(wmlib\255>init\(\);) 1080 5963 w
+10 /Palatino-Roman f
+(Note) 720 6146 w
+(that) 978 6146 w
+10 /Courier f
+(wmlib\255>init) 1191 6146 w
+10 /Palatino-Roman f
+(is) 1890 6146 w
+(called) 2000 6146 w
+(once) 2301 6146 w
+(to) 2546 6146 w
+(initialise) 2674 6146 w
+(the) 3090 6146 w
+10 /Courier f
+(wmlib) 3269 6146 w
+10 /Palatino-Roman f
+(module) 3609 6146 w
+(just) 3990 6146 w
+(loaded,) 4188 6146 w
+(before) 4557 6146 w
+(any) 4876 6146 w
+(other functions are called.) 720 6266 w
+(In) 720 6424 w
+(window) 857 6424 w
+(manager) 1271 6424 w
+(applications) 1706 6424 w
+(the) 2291 6424 w
+10 /Courier f
+(Tk\255>toplevel) 2476 6424 w
+10 /Palatino-Roman f
+(function) 3242 6424 w
+(is) 3658 6424 w
+(not) 3775 6424 w
+(normally) 3967 6424 w
+(used) 4418 6424 w
+(directly.) 4675 6424 w
+(Instead,) 720 6544 w
+(a) 1100 6544 w
+(window) 1179 6544 w
+(manager) 1577 6544 w
+(interface) 1996 6544 w
+(is) 2408 6544 w
+(used) 2508 6544 w
+(to) 2748 6544 w
+(create) 2864 6544 w
+(both) 3155 6544 w
+(the) 3384 6544 w
+(top) 3551 6544 w
+(level) 3727 6544 w
+(widget) 3966 6544 w
+(and) 4304 6544 w
+(a) 4501 6544 w
+(channel) 4579 6544 w
+(to) 4952 6544 w
+(receive events from the window manager.) 720 6654 w
+(The) 2634 6654 w
+10 /Courier f
+(titlebar) 2826 6654 w
+10 /Palatino-Roman f
+(function has the signature:) 3331 6654 w
+8 /Courier f
+(titlebar\(scr: Draw\255>Screen, tkargs: string, title: string, buts: int\):) 1056 6807 w
+(\(ref Tk\255>Toplevel, chan of string\);) 1248 6897 w
+11 /Palatino-Roman f
+(The) 720 7080 w
+11 /Courier f
+(Screen) 939 7080 w
+11 /Palatino-Roman f
+(is) 1370 7080 w
+(the) 1483 7080 w
+(one) 1671 7080 w
+(on) 1884 7080 w
+(which) 2044 7080 w
+(the) 2378 7080 w
+(window) 2566 7080 w
+(is) 3007 7080 w
+(to) 3120 7080 w
+(be) 3252 7080 w
+(created,) 3401 7080 w
+(normally) 3821 7080 w
+(the) 4304 7080 w
+(one) 4493 7080 w
+(passed) 4707 7080 w
+(in) 720 7200 w
+(the) 845 7200 w
+11 /Courier f
+(Context) 1027 7200 w
+11 /Palatino-Roman f
+(parameter) 1518 7200 w
+(to) 2050 7200 w
+(a) 2176 7200 w
+(program's) 2260 7200 w
+11 /Courier f
+(init) 2795 7200 w
+11 /Palatino-Roman f
+(function.) 3088 7200 w
+(The) 3580 7200 w
+11 /Palatino-Italic f
+(tkargs) 3793 7200 w
+11 /Palatino-Roman f
+(parameter) 4104 7200 w
+(can) 4636 7200 w
+(con\255) 4831 7200 w
+cleartomark
+showpage
+saveobj restore
+%%EndPage: 3 3
+%%Page: 4 4
+/saveobj save def
+mark
+4 pagesetup
+10 /Palatino-Roman f
+(\255 4 \255) 2797 480 w
+11 /Palatino-Roman f
+(trol) 720 840 w
+(the) 925 840 w
+(position) 1110 840 w
+(and) 1540 840 w
+(appearance) 1758 840 w
+(of) 2349 840 w
+(the) 2478 840 w
+(window,) 2663 840 w
+(but) 3129 840 w
+(is) 3324 840 w
+(best) 3434 840 w
+(left) 3662 840 w
+(nil) 3852 840 w
+(\(or) 4013 840 w
+(the) 4187 840 w
+(empty) 4373 840 w
+(string\)) 4720 840 w
+(to) 720 960 w
+(use) 865 960 w
+(the) 1078 960 w
+(window) 1279 960 w
+(manager's) 1733 960 w
+(defaults) 2288 960 w
+(\(see) 2727 960 w
+11 /Palatino-Italic f
+(wmlib) 2963 960 w
+11 /Palatino-Roman f
+(\(2\)) 3250 960 w
+(for) 3425 960 w
+(details) 3614 960 w
+(otherwise\),) 3982 960 w
+(including) 4573 960 w
+(automatic) 720 1080 w
+(placement.) 1236 1080 w
+(The) 1826 1080 w
+11 /Palatino-Italic f
+(title) 2040 1080 w
+11 /Palatino-Roman f
+(string) 2256 1080 w
+(gives) 2570 1080 w
+(the) 2856 1080 w
+(title) 3039 1080 w
+(that) 3258 1080 w
+(appears) 3479 1080 w
+(in) 3895 1080 w
+(the) 4022 1080 w
+(title) 4206 1080 w
+(bar.) 4426 1080 w
+(Finally,) 4673 1080 w
+11 /Palatino-Italic f
+(buts) 720 1200 w
+11 /Palatino-Roman f
+(is) 962 1200 w
+(a) 1081 1200 w
+(bit) 1177 1200 w
+(set) 1347 1200 w
+(that) 1523 1200 w
+(selects) 1755 1200 w
+(the) 2110 1200 w
+(buttons) 2304 1200 w
+(to) 2715 1200 w
+(appear.) 2853 1200 w
+(The) 3289 1200 w
+(value) 3514 1200 w
+11 /Courier f
+(Wmlib\255>Appl) 3824 1200 w
+11 /Palatino-Roman f
+(gives) 4591 1200 w
+(the) 4887 1200 w
+(usual) 720 1320 w
+(resize) 1018 1320 w
+(and) 1334 1320 w
+(hide) 1553 1320 w
+(buttons;) 1802 1320 w
+(the) 2233 1320 w
+(exit) 2419 1320 w
+(\(delete\)) 2631 1320 w
+(button) 3031 1320 w
+(always) 3389 1320 w
+(appears.) 3764 1320 w
+(The) 4239 1320 w
+(following) 4457 1320 w
+(is) 4962 1320 w
+(used) 720 1440 w
+(in) 980 1440 w
+(the) 1104 1440 w
+(example:) 1285 1440 w
+10 /Courier f
+(\(top, titlechan\) := wmlib\255>titlebar\(ctxt.screen, nil,) 1104 1646 w
+("Text Browser", Wmlib\255>Appl\);) 2064 1746 w
+10 /Palatino-Roman f
+(Note) 720 1972 w
+(that) 971 1972 w
+10 /Courier f
+(titlebar) 1177 1972 w
+10 /Palatino-Roman f
+(returns) 1690 1972 w
+(a) 2044 1972 w
+(tuple.) 2127 1972 w
+(The) 2440 1972 w
+(first) 2640 1972 w
+(element) 2850 1972 w
+(is) 3235 1972 w
+(a) 3339 1972 w
+(reference) 3422 1972 w
+(to) 3862 1972 w
+(the) 3983 1972 w
+(Tk) 4155 1972 w
+(top) 4305 1972 w
+(level) 4486 1972 w
+(widget) 4730 1972 w
+(for) 720 2092 w
+(use) 878 2092 w
+(in) 1058 2092 w
+(later) 1175 2092 w
+(Tk) 1405 2092 w
+(commands.) 1552 2092 w
+(The) 2118 2092 w
+(second) 2315 2092 w
+(element) 2653 2092 w
+(of) 3035 2092 w
+(the) 3153 2092 w
+(tuple) 3322 2092 w
+(is) 3582 2092 w
+(a) 3683 2092 w
+(Limbo) 3763 2092 w
+(channel) 4081 2092 w
+(of) 4456 2092 w
+(type) 4574 2092 w
+10 /Courier f
+(chan) 4800 2092 w
+(of string) 720 2212 w
+10 /Palatino-Roman f
+(that passes window manager events to the application.) 1285 2212 w
+(The) 720 2396 w
+(channel) 916 2396 w
+10 /Courier f
+(titlechan) 1290 2396 w
+10 /Palatino-Roman f
+(is) 1859 2396 w
+(used) 1959 2396 w
+(by) 2199 2396 w
+10 /Courier f
+(wmlib) 2339 2396 w
+10 /Palatino-Roman f
+(to) 2668 2396 w
+(send) 2785 2396 w
+(messages,) 3023 2396 w
+(but) 3493 2396 w
+(it) 3671 2396 w
+(is) 3763 2396 w
+(normally) 3864 2396 w
+(necessary) 4299 2396 w
+(to) 4757 2396 w
+(cre\255) 4875 2396 w
+(ate a channel to Tk to receive events from widgets the application creates:) 720 2516 w
+9 /Courier f
+(cmdchan := chan of string;) 1080 2722 w
+(tk\255>namechan\(top, cmdchan, "cmdchan"\);) 1080 2822 w
+10 /Palatino-Bold f
+(4.1.) 720 3155 w
+(Defining and positioning widgets) 920 3155 w
+10 /Palatino-Roman f
+(The) 720 3339 w
+(function) 915 3339 w
+10 /Courier f
+(Wmlib\255>tkcmds) 1313 3339 w
+10 /Palatino-Roman f
+(takes) 2121 3339 w
+(two) 2378 3339 w
+(arguments,) 2577 3339 w
+(a) 3105 3339 w
+10 /Courier f
+(ref) 3183 3339 w
+(Tk\255>Toplevel) 3426 3339 w
+10 /Palatino-Roman f
+(that) 4174 3339 w
+(identifies) 4376 3339 w
+(a) 4814 3339 w
+(top) 4892 3339 w
+(level) 720 3459 w
+(window,) 964 3459 w
+(and) 1391 3459 w
+(an) 1593 3459 w
+10 /Courier f
+(array) 1734 3459 w
+(of) 2101 3459 w
+(string) 2288 3459 w
+10 /Palatino-Roman f
+(.) 2648 3459 w
+(Each) 2730 3459 w
+(element) 2975 3459 w
+(of) 3359 3459 w
+(the) 3479 3459 w
+(array) 3650 3459 w
+(is) 3918 3459 w
+(a) 4021 3459 w
+(Tk) 4103 3459 w
+(command) 4252 3459 w
+(accept\255) 4728 3459 w
+(able to) 720 3579 w
+10 /Courier f
+(Tk\255>cmd) 1040 3579 w
+10 /Palatino-Roman f
+(;) 1460 3579 w
+10 /Courier f
+(Wmlib\255>tkcmds) 1510 3579 w
+10 /Palatino-Roman f
+(simply applies it to each element of the array.) 2315 3579 w
+(Most) 720 3763 w
+(of) 974 3763 w
+(the) 1091 3763 w
+(following) 1259 3763 w
+(fragment) 1715 3763 w
+(consists) 2150 3763 w
+(of) 2524 3763 w
+(Tk) 2641 3763 w
+(command) 2787 3763 w
+(strings) 3260 3763 w
+(that) 3589 3763 w
+(are) 3792 3763 w
+(members) 3960 3763 w
+(of) 4399 3763 w
+(the) 4517 3763 w
+(array) 4686 3763 w
+(of) 4952 3763 w
+(strings) 720 3883 w
+10 /Courier f
+(tk_config) 1067 3883 w
+10 /Palatino-Roman f
+(.) 1607 3883 w
+(The) 1704 3883 w
+(comments) 1917 3883 w
+(describe) 2419 3883 w
+(the) 2832 3883 w
+(widgets) 3017 3883 w
+(being) 3415 3883 w
+(created.) 3707 3883 w
+(Not) 4102 3883 w
+(all) 4319 3883 w
+(widgets) 4473 3883 w
+(and) 4871 3883 w
+(menu) 720 4003 w
+(items) 1008 4003 w
+(in) 1282 4003 w
+(this) 1403 4003 w
+(example) 1599 4003 w
+(are) 2008 4003 w
+(functional.) 2180 4003 w
+(The) 2713 4003 w
+(last) 2914 4003 w
+(line) 3102 4003 w
+(executes) 3300 4003 w
+(the) 3709 4003 w
+(array) 3882 4003 w
+(of) 4152 4003 w
+(commands) 4274 4003 w
+(using) 4795 4003 w
+10 /Courier f
+(wmlib\255>tkcmds) 720 4123 w
+10 /Palatino-Roman f
+(:) 1500 4123 w
+8 /Courier f
+(tk_config := array[] of {) 1056 4319 w
+8 /Palatino-Italic f
+(# define menubar frame, widget frame, text frame) 1056 4499 w
+8 /Courier f
+("frame .mbar \255relief groove \255bd 2",) 1056 4589 w
+("frame .w",) 1056 4679 w
+("frame .text",) 1056 4769 w
+8 /Palatino-Italic f
+(# define and pack menus) 1056 4949 w
+8 /Courier f
+("menubutton .file \255text File \255menu .file.m",) 1056 5039 w
+("menubutton .edit \255text Edit \255menu .edit.m",) 1056 5129 w
+("menubutton .help \255text Help \255menu .help.m",) 1056 5219 w
+("menu .file.m",) 1056 5399 w
+(".file.m add command \255label Send \255command {send cmdchan send}",) 1056 5489 w
+(".file.m add command \255label Exit \255command {send cmdchan exit}",) 1056 5579 w
+("menu .edit.m",) 1056 5669 w
+(".edit.m add command \255label Cut",) 1056 5759 w
+("menu .help.m",) 1056 5939 w
+(".help.m add command \255label Index \255underline 0",) 1056 6029 w
+("pack .file .edit \255side left \255in .mbar; update",) 1056 6209 w
+("pack .help \255side right \255in .mbar",) 1056 6299 w
+8 /Palatino-Italic f
+(# define and pack buttons and text entry box \(for file name\)) 1056 6479 w
+8 /Courier f
+("button .b1 \255text Send \255command {send cmdchan send}",) 1056 6569 w
+("button .b2 \255text Open \255command {send cmdchan open}",) 1056 6659 w
+("label .l \255text {Name: }",) 1056 6749 w
+("entry .e",) 1056 6929 w
+("bind .e <Key\255\\n> {send cmdchan open}",) 1056 7019 w
+("pack .b1 .b2 .l .e \255side left \255in .w",) 1056 7199 w
+cleartomark
+showpage
+saveobj restore
+%%EndPage: 4 4
+%%Page: 5 5
+/saveobj save def
+mark
+5 pagesetup
+10 /Palatino-Roman f
+(\255 5 \255) 2797 480 w
+cleartomark
+saveobj restore
+%ps_include: begin
+save
+/ed {exch def} def
+{} /showpage ed
+{} /copypage ed
+{} /erasepage ed
+{} /letter ed
+currentdict /findfont known systemdict /findfont known and {
+ /findfont systemdict /findfont get def
+} if
+36 dict dup /PS-include-dict-dw ed begin
+/context ed
+count array astore /o-stack ed
+%ps_include: variables begin
+/llx 0 def
+/lly 0 def
+/urx 318 def
+/ury 216 def
+/w 0 def
+/o 0 def
+/s 0 def
+/cx 2880 def
+/cy -1737.5 def
+/sx 4320 def
+/sy 1555 def
+/ax .5 def
+/ay .5 def
+/rot 0 def
+%ps_include: variables end
+{llx lly urx ury} /bbox ed
+{newpath 2 index exch 2 index exch dup 6 index exch
+ moveto 3 {lineto} repeat closepath} /boxpath ed
+{dup mul exch dup mul add sqrt} /len ed
+{2 copy gt {exch} if pop} /min ed
+{2 copy lt {exch} if pop} /max ed
+{transform round exch round exch A itransform} /nice ed
+{6 array} /n ed
+n defaultmatrix n currentmatrix n invertmatrix n concatmatrix /A ed
+urx llx sub 0 A dtransform len /Sx ed
+0 ury lly sub A dtransform len /Sy ed
+llx urx add 2 div lly ury add 2 div A transform /Cy ed /Cx ed
+rot dup sin abs /S ed cos abs /C ed
+Sx S mul Sy C mul add /H ed
+Sx C mul Sy S mul add /W ed
+sy H div /Scaley ed
+sx W div /Scalex ed
+s 0 eq {Scalex Scaley min dup /Scalex ed /Scaley ed} if
+sx Scalex W mul sub 0 max ax 0.5 sub mul cx add /cx ed
+sy Scaley H mul sub 0 max ay 0.5 sub mul cy add /cy ed
+urx llx sub 0 A dtransform exch atan rot exch sub /rot ed
+n currentmatrix initgraphics setmatrix
+cx cy translate
+Scalex Scaley scale
+rot rotate
+Cx neg Cy neg translate
+A concat
+bbox boxpath clip newpath
+w 0 ne {gsave bbox boxpath 1 setgray fill grestore} if
+end
+gsave
+%ps_include: inclusion begin
+ %!
+ %%BoundingBox: 0 0 318 216
+/picstr 310 string def
+318 216 scale
+310 210 8
+[ 310 0 0 -210 0 210 ]
+{ currentfile picstr readhexstring pop }
+false 3 colorimage
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffff999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+9999990000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+999999ffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd9999999999990000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999ffffffffffffdddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd9999999999990000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bbffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999ffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddd9999999999990000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffdddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddd999999ffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd9999999999990000bb999999999999ffffffffffff0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffdddddddddddddddddddddddd000000000000000000000000000000000000000000000000000000000000000000dddddd
+dddddddddddd999999999999ffffffdddddddddddddddddd000000000000000000000000000000000000000000000000000000000000000000000000000000dddddddddddddddddd999999ffffffffffffdddddddddddddddddddddddd000000
+000000dddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddd9999999999990000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffffffffffffffffffffffffff
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffffffff
+ffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bbffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddd000000dddddddddddd000000dddddd000000dddddddddddddddddd999999999999ffffffdddddddddddddddddd000000dddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000dddddddddddddddddd999999ffffffffffffdddddddddddddddddddddddd000000000000000000dddddddddddddddddddddddd000000000000000000dddddd
+dddddddddddddddddd9999999999990000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffff0000bbffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffdddddddddddddddddddddddd
+dddddddddddddddddddddddddddddd000000dddddddddddd000000dddddd000000dddddddddddddddddd999999999999ffffffdddddddddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+000000dddddddddddddddddd999999ffffffffffffdddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddd9999999999990000bb999999999999ffffffffffff
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffff0000bb0000bb0000bb0000bb0000bbffffffffffffffffff0000bb0000bb0000bbffffff0000bb0000bbffffffffffff0000bb0000bb0000bbffffffffffff0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffff0000bbffffffffffff0000bb0000bb0000bbffffff0000bb0000bbffffffffffff0000bb0000bb0000bbffffffffffff0000bb0000bbffffffffffff0000bb
+0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffffffffffffff0000bb0000bb0000bbffffffffffffffffff0000bb0000bb0000bb0000bbffffff0000bb0000bbffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddd000000dddddddddddd000000dddddd
+000000dddddddddddddddddd999999999999ffffffdddddddddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000dddddddddddddddddd999999ffffffffffffdddddddddddddddddd
+dddddddddddddddddd000000000000dddddddddddd000000000000dddddddddddddddddddddddddddddddddddd9999999999990000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffff
+0000bb0000bb0000bb0000bbffffff0000bb0000bbffffffffffff0000bb0000bbffffffffffff0000bbffffff0000bb0000bb0000bb0000bbffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffff
+ffffffffffff0000bb0000bb0000bb0000bb0000bbffffffffffff0000bb0000bbffffff0000bbffffffffffff0000bb0000bbffffff0000bbffffffffffff0000bbffffff0000bb0000bb0000bb0000bbffffff0000bb0000bb0000bb0000bb
+0000bb0000bbffffff0000bb0000bb0000bbffffff0000bb0000bb0000bbffffffffffff0000bbffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddd000000dddddddddddd000000dddddd000000dddddddddddddddddd999999999999ffffffdddddddddddddddddd
+000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000dddddddddddddddddd999999ffffffffffffdddddddddddddddddddddddddddddddddddddddddd000000000000000000000000dddddddddddd
+dddddddddddddddddddddddddddddd9999999999990000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffff0000bb0000bb0000bb0000bbffffffffffffffffffffffffffffff0000bb
+0000bb0000bbffffffffffff0000bb0000bb0000bb0000bb0000bbffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffff0000bbffffff0000bb0000bb0000bb0000bbffffff0000bb0000bb
+0000bb0000bb0000bbffffffffffff0000bb0000bbffffff0000bbffffffffffff0000bbffffffffffff0000bb0000bb0000bbffffffffffffffffffffffff0000bb0000bb0000bbffffffffffffffffffffffffffffff0000bb0000bb0000bb
+ffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffdddddddddddd
+dddddddddddddddddddddddddddddddddddddddddd000000dddddddddddd000000dddddd000000dddddddddddddddddd999999999999ffffffdddddddddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddd000000dddddddddddddddddd999999ffffffffffffdddddddddddddddddddddddddddddddddddddddddd000000000000000000000000dddddddddddddddddddddddddddddddddddddddddd9999999999990000bb999999999999
+ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffff0000bb0000bb0000bb0000bbffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffff0000bb0000bb0000bb0000bb0000bbffffff
+ffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffff0000bbffffffffffff0000bb0000bb0000bbffffff0000bb0000bb0000bb0000bb0000bbffffffffffff0000bb0000bbffffff0000bbffffff
+ffffff0000bbffffffffffff0000bb0000bb0000bb0000bbffffffffffffffffffffffff0000bb0000bbffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffdddddddddddddddddddddddd000000000000000000000000000000000000dddddddddddd
+000000dddddd000000dddddddddddddddddd999999999999ffffffdddddddddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000dddddddddddddddddd999999ffffffffffffdddddd
+dddddddddddddddddddddddddddddddddddd000000000000000000000000dddddddddddddddddddddddddddddddddddddddddd9999999999990000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+ffffffffffff0000bb0000bb0000bb0000bbffffffffffff0000bb0000bbffffff0000bb0000bbffffff0000bb0000bbffffffffffff0000bb0000bb0000bbffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bbffffffffffff0000bbffffffffffff0000bb0000bb0000bbffffff0000bb0000bb0000bb0000bb0000bb0000bbffffff0000bbffffffffffff0000bb0000bbffffffffffff0000bbffffffffffff0000bb0000bbffffff0000bb0000bb
+0000bbffffff0000bb0000bb0000bbffffff0000bb0000bbffffff0000bb0000bb0000bbffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000dddddd000000dddddddddddddddddd999999999999ffffffdddddd
+dddddddddddd000000000000000000000000000000000000000000000000000000000000000000000000000000dddddddddddddddddd999999ffffffffffffdddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddd
+000000000000dddddddddddddddddddddddddddddd9999999999990000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffff0000bb0000bb0000bb0000bb0000bbffffffffffffffffff
+0000bb0000bb0000bbffffff0000bb0000bbffffffffffff0000bb0000bb0000bb0000bbffffffffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffffffffffffff0000bb0000bb0000bb0000bbffffff
+0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffff0000bb0000bb0000bbffffffffffff0000bbffffffffffff0000bb0000bb0000bbffffffffffffffffffffffff0000bb0000bb0000bbffffffffffffffffff0000bb0000bb
+0000bb0000bbffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffff
+dddddddddddddddddddddddd000000000000000000000000000000000000000000000000000000dddddd000000dddddddddddddddddd999999999999ffffffdddddddddddddddddd000000000000000000000000000000000000000000000000
+000000000000000000000000000000dddddddddddddddddd999999ffffffffffffdddddddddddddddddddddddd000000000000000000dddddddddddddddddddddddd000000000000000000dddddddddddddddddddddddd9999999999990000bb
+999999999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddd000000dddddddddddddddddd999999999999ffffffdddddddddddddddddd000000000000000000000000000000000000000000000000000000000000000000000000000000dddddddddddddddddd999999ffffff
+ffffffdddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddd9999999999990000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffdddddddddddddddddddddddd000000000000000000000000000000000000000000000000000000000000000000dddddddddddddddddd999999999999
+ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999ffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddd9999999999990000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+ffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999ffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999
+9999990000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+999999ffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd9999999999990000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999ffffffffffffdddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd9999999999990000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bbffffffffffff999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999ffffff999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999ffffffffffff999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+9999999999999999990000bb999999999999ffffffffffff0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bbffffff999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999ffffff999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999ffffff9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999990000bb999999999999ffffffffffff0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb
+0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb0000bb999999999999ffffffffffff999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999ffffffffffff999999ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffff
+999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999999999ffffffffffff999999dddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddd999999999999999999ffffffffffff999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999999999
+ffffffffffff999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999999999ffffffffffff999999dddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999999999ffffffffffff999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999
+999999999999ffffffffffff999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddd000000000000000000000000dddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000
+dddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddd000000000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999999999ffffffffffff999999dddddddddddddddddddddddddddddd
+dddddddddddd000000000000000000000000000000dddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000000000000000000000000000dddddddddddddddddddddddddddddddddddd000000dddddddddddddddddddddddd000000000000dddddddddddddddddddddddd
+000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000dddddddddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000dddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999999999ffffffffffff999999dddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddd000000
+000000000000000000dddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddd000000000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+000000000000dddddddddddddddddddddddddddddddddddddddddd000000000000000000dddddddddddd000000000000000000000000dddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+000000dddddddddddddddddd000000dddddddddddddddddd000000000000000000dddddddddddddddddddddddddddddd000000dddddddddddddddddd000000000000dddddd000000dddddddddddddddddddddddddddddddddddddddddddddddd
+dddddd999999999999999999ffffffffffff999999dddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddd000000000000
+dddddddddddddddddddddddd000000dddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddddddddd000000dddddd
+dddddd000000dddddddddddddddddddddddd000000000000dddddddddddddddddd000000000000000000000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000dddddddddddddddddd000000dddddddddddd000000000000dddddd
+000000000000dddddddddddddddddddddddd000000dddddddddddddddddd000000000000000000dddddd000000dddddddddddddddddddddddddddddddddddddddddddddddd999999999999999999ffffffffffff999999dddddddddddddddddd
+dddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddd000000000000dddddddddddddddddd000000000000dddddddddddd000000dddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000000000000000000000dddddddddddddddddd000000000000dddddddddddd000000dddddddddddddddddddddddd000000000000dddddddddddd
+dddddddddddd000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000000000000000000000000000dddddddddddd000000dddddddddddd000000000000dddddddddddddddddddddddd000000dddddddddddddddddd
+000000000000dddddddddddd000000000000dddddddddddddddddddddddddddddddddddddddddd999999999999999999ffffffffffff999999dddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddd
+dddddddddddddddddd000000000000dddddddddddddddddddddddddddddd000000000000dddddddddddddddddd000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddd000000000000dddddddddddddddddddddddddddddd000000000000dddddddddddd000000dddddddddddddddddddddddd000000000000dddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddd000000dddddddddddddddddd000000dddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddd000000dddddddddddddddddd000000000000dddddddddddd000000000000dddddddddddddddddddddddd
+dddddddddddddddddd999999999999999999ffffffffffff999999dddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddd
+000000000000dddddddddddddddddd000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddd000000
+000000dddddddddddd000000dddddddddddddddddddddddd000000000000dddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000dddddddddddddddddd000000dddddddddddd000000
+dddddddddddddddddddddddddddddddddddddddddddddddd000000dddddddddddddddddd000000000000dddddddddddd000000000000dddddddddddddddddddddddddddddddddddddddddd999999999999999999ffffffffffff999999dddddd
+dddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddd000000dddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddddddddd000000dddddd000000000000dddddddddddddddddddddddd000000000000
+dddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000dddddddddddddddddd000000dddddddddddd000000000000dddddddddddd000000dddddddddddddddddddddddd000000dddddd
+dddddddddddd000000000000dddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddd999999999999999999ffffffffffff999999dddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddd
+dddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddd000000000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddd000000000000000000000000000000dddddddddddddddddddddddd000000dddddd000000dddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddd000000000000000000dddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddd000000dddddddddddddddddd000000dddddddddddddddddd000000000000000000dddddddddddddddddddddddddddddd000000dddddddddddddddddd000000000000000000000000dddddddddddddddddddddddd
+dddddddddddddddddddddddddddddd999999999999999999ffffffffffff999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999999999ffffffffffff
+999999dddddddddddddddddddddddddddddddddddd000000000000000000000000000000000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000000000000000000000000000000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000000000000000000000000000000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999999999ffffffffffff999999dddddddddddddddddddddddddddddddddddd000000000000000000
+000000000000000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddd000000000000000000000000000000000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddd000000000000000000000000000000000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddd999999999999999999ffffffffffff999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999999999
+ffffffffffff999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999999999ffffffffffff999999dddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999999999ffffffffffff999999ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+999999999999ffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffffffffdddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999dddddd999999999999ffffffffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffffffffdddddd999999999999ffffffffffffffffffdddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffffffffdddddd999999999999ffffffffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffdddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+999999999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999dddddddddddddddddddddddd000000dddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddffffffffffffdddddd999999999999ffffffffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999dddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999dddddddddddddddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffffffffdddddd999999999999ffffffffffffffffffdddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddd999999dddddddddddddddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffffffffdddddd999999999999ffffffffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddd999999999999ffffffdddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddd999999999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999dddddddddddddddddddddddd000000dddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddffffffffffffdddddd999999999999ffffffffffffffffffdddddddddddddddddddddddddddddddddddd000000dddddddddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddd999999999999ffffffdddddddddddddddddddddddddddddddddddd000000dddddddddddd000000dddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999dddddddddddddddddddddddddddddd000000
+000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999dddddddddddddddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffffffffdddddd999999999999ffffffffffff
+ffffffdddddddddddddddddddddddddddddddddddd000000dddddddddddddddddddddddddddddddddddddddddd000000000000000000dddddddddddddddddd000000dddddd000000000000dddddddddddddddddddddddd000000000000000000
+000000dddddddddddddddddddddddddddddd999999999999ffffffdddddddddddddddddddddddddddddd000000dddddddddddddddddd000000000000dddddddddddd000000dddddd000000dddddddddddddddddddddddddddddd000000000000
+000000dddddddddddd000000000000dddddd000000000000dddddddddddddddddddddddddddddddddddd999999999999dddddddddddddddddddddddddddddd000000000000dddddddddddddddddddddddddddddd000000000000000000000000
+dddddddddddd000000dddddd000000dddddd000000dddddddddddddddddddddddd000000000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddd999999dddddddddddddddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffffffffdddddd999999999999ffffffffffffffffffdddddddddddddddddddddddddddddddddddd000000000000dddddd
+dddddddddddddddddddddddd000000000000dddddd000000000000dddddddddddd000000000000dddddd000000000000dddddddddddd000000000000dddddd000000000000dddddddddddddddddddddddddddddd999999999999ffffffdddddd
+dddddddddddddddddddddddd000000dddddddddddddddddd000000000000dddddddddddd000000000000dddddd000000dddddddddddddddddd000000000000dddddd000000000000dddddd000000000000000000000000000000000000dddddd
+dddddddddddddddddddddddd999999999999dddddddddddddddddddddddddddddd000000dddddd000000dddddddddddddddddddddddddddddddddddddddddd000000000000dddddd000000000000000000000000dddddd000000dddddddddddd
+dddddd000000dddddddddddd000000dddddddddddddddddd000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999dddddddddddddddddddddddd000000
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddffffffffffffdddddd999999999999ffffffffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddddddddd000000000000000000000000000000dddddd
+dddddd000000dddddddddddd000000000000dddddd000000000000dddddddddddd000000000000dddddddddddddddddddddddddddddd999999999999ffffffdddddddddddddddddddddddddddddd000000dddddddddddddddddd000000000000
+dddddddddddd000000dddddddddddd000000000000dddddd000000000000000000000000000000000000dddddd000000000000dddddddddddd000000000000dddddddddddddddddddddddddddddd999999999999dddddddddddddddddddddddd
+dddddd000000dddddd000000000000dddddddddddddddddd000000000000000000000000000000dddddd000000000000000000000000dddddd000000dddddddddddd000000000000000000000000000000dddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999dddddddddddddddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffffffffdddddd999999999999
+ffffffffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddd000000000000dddddddddddd000000dddddddddddddddddddddddddddddddddddd000000dddddddddddd000000000000dddddd000000000000dddddd
+dddddd000000000000dddddddddddddddddddddddddddddd999999999999ffffffdddddddddddddddddddddddddddddd000000dddddddddddddddddd000000000000dddddddddddd000000dddddddddddd000000000000dddddd000000000000
+dddddddddddddddddddddddddddddd000000000000dddddddddddd000000000000dddddddddddddddddddddddddddddd999999999999dddddddddddddddddddddddddddddd000000dddddd000000000000dddddddddddd000000000000dddddd
+dddddd000000000000dddddd000000000000000000000000dddddd000000dddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddd999999dddddddddddddddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffffffffdddddd999999999999ffffffffffffffffffdddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddd000000dddddddddddd000000dddddddddddddddddddddddddddddddddddd000000dddddddddddd000000000000dddddd000000000000dddddddddddd000000000000dddddddddddddddddddddddddddddd999999999999
+ffffffdddddddddddddddddddddddddddddd000000dddddddddddddddddd000000000000dddddddddddd000000dddddddddddd000000000000dddddd000000000000dddddddddddddddddddddddddddddd000000000000dddddddddddd000000
+000000dddddddddddddddddddddddddddddd999999999999dddddddddddddddddddddddddddddd000000dddddddddddd000000000000dddddd000000000000dddddddddddd000000000000dddddd000000000000000000000000dddddd000000
+dddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999dddddddddddddddddd
+dddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddddddddddddddffffffffffffdddddd999999999999ffffffffffffffffffdddddddddddddddddddddddddddddddddddd000000dddddddddddddddddd000000dddddddddddd000000000000dddddddddddd
+000000dddddddddddd000000dddddddddddd000000000000dddddddddddd000000000000dddddd000000000000dddddddddddddddddddddddddddddd999999999999ffffffdddddddddddddddddddddddddddddddddddd000000dddddddddddd
+000000dddddddddddddddddd000000dddddddddddd000000dddddddddddddddddd000000000000dddddddddddd000000dddddd000000000000dddddddddddd000000000000dddddddddddddddddddddddddddddd999999999999dddddddddddd
+dddddddddddddddddd000000dddddddddddd000000000000dddddd000000000000dddddd000000000000000000dddddd000000000000000000000000dddddd000000dddddddddddddddddd000000dddddddddddd000000dddddddddddddddddd
+000000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999dddddddddddddddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffffffffdddddd
+999999999999ffffffffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000dddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddd999999dddddddddddddddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffffffffdddddd999999999999ffffffffffffffffffdddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddd999999999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999dddddd
+dddddddddddddddddd000000dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffffffffdddddd999999999999ffffffffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999dddddddddddddddddddddddd000000dddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffff
+ffffffdddddd999999999999ffffffffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffffffffdddddd999999999999ffffffffffffffffffdddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffffffffdddddd999999999999ffffffffffffffffff999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999ffffff999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999ffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffdddddd999999999999ffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffffffffdddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddddddddddddddddddddbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb999999999999ffffffffffffddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb999999999999ffffffffffff
+dddddd999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999ffffffddddddddddddbbbbbb000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999dddddddddddddddddddddddddddddddddddddddddd
+ddddddddddddddddddddddddddddddddddddddddddffffffddddddddddddbbbbbb000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffdddddddddddd
+bbbbbb000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999
+ffffffffffffdddddd999999999999ddddddddddddddddddddddddddddddddddddffffffffffffddddddddddddddddddddddddddddddddddddffffffddddddddddddbbbbbb000000ffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999dddddddddddddddddddddddddddddd
+ffffffffffffffffff999999ddddddddddddddddddddddddddddddffffffddddddddddddbbbbbb000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ddddddddddddddddddddddddddddddffffffffffffffffff999999ddddddddddddddddddddddddddddddffffff
+ddddddddddddbbbbbb000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+999999999999ffffffffffffdddddd999999999999ddddddddddddddddddddddddffffffffffffffffffdddddd999999999999ddddddddddddddddddddddddffffffddddddddddddbbbbbb000000ffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999dddddddddddddddddd
+ddddddffffffffffffdddddddddddd999999999999999999ddddddddddddddddddffffffddddddddddddbbbbbb000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ddddddddddddddddddddddddffffffffffffdddddddddddd999999999999999999dddddddddddd
+ddddddffffffddddddddddddbbbbbb000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffff999999999999ffffffffffffdddddd999999999999ddddddddddddddddddffffffffffffdddddddddddddddddddddddd999999999999ddddddddddddddddddffffffddddddddddddbbbbbb000000ffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999dddddd
+ddddddffffffffffffdddddddddddddddddddddddddddddddddddd999999999999ddddddddddddffffffddddddddddddbbbbbb000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ddddddddddddffffffffffffdddddddddddddddddddddddddddddddddddd999999
+999999ddddddddddddffffffddddddddddddbbbbbb000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ddddddffffffffffffffffffdddddddddddddddddddddddddddddddddddddddddd999999999999ddddddffffffddddddddddddbbbbbb000000ffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999
+999999ddddddffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddd999999999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ddddddffffffffffffdddddddddddddddddddddddddddddddddddd
+dddddddddddd999999999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffff
+dddddd999999999999ffffff999999999999999999999999999999999999999999999999999999999999999999999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffdddddddddddd
+bbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999
+ffffffffffffdddddd999999999999ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffff999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffff
+ddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999
+999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffff
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999
+999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffff
+dddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffdddddddddddd
+bbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999
+ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffff
+ddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999
+999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffff
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999
+999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffff
+dddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffdddddddddddd
+bbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999
+ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffff
+ddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999
+999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffff
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999
+999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffff
+dddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffdddddddddddd
+bbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999
+ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffff
+ddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999
+999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffff
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999
+999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffff
+dddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffdddddddddddd
+bbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999
+ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffff
+ddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999
+999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffff
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999
+999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddd
+dddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffff
+dddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddd
+dddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffdddddddddddd
+bbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999
+ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddd
+dddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffff
+ddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddd
+dddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999
+999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffff
+dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+dddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999
+999999ffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffff999999999999999999999999999999999999999999999999
+999999999999999999999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffff999999999999999999999999999999999999999999999999999999999999999999999999999999ffffffddddddddddddbbbbbbffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffff
+dddddd999999999999ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffff999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999ffffffdddddddddddd
+bbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999
+ffffffffffffdddddd999999999999ffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ddddddffffffffffffdddddddddddd
+dddddddddddddddddddddddddddddddddddd999999999999999999ffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ddddddffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddd999999999999999999ffffff
+ddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+999999999999ffffffffffffdddddd999999999999ddddddffffffffffffffffffdddddddddddddddddddddddddddddddddddddddddd999999999999ddddddffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ddddddddddddffffff
+ffffffdddddddddddddddddddddddddddddddddddd999999999999ddddddddddddffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ddddddddddddffffffffffffdddddddddddddddddddddddddddddddddddd999999999999dddddd
+ddddddffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffff999999999999ffffffffffffdddddd999999999999ddddddddddddddddddffffffffffffdddddddddddddddddddddddd999999999999ddddddddddddddddddffffffddddddddddddbbbbbbffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999dddddd
+ddddddddddddddddddffffffffffffdddddddddddd999999999999999999ddddddddddddddddddffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ddddddddddddddddddddddddffffffffffffdddddddddddd999999999999999999
+ddddddddddddddddddffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ddddddddddddddddddddddddffffffffffffffffffdddddd999999999999ddddddddddddddddddddddddffffffddddddddddddbbbbbbffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999
+999999ddddddddddddddddddddddddffffffffffffffffffdddddd999999999999ddddddddddddddddddddddddffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ddddddddddddddddddddddddddddddffffffffffffffffff999999
+ddddddddddddddddddddddddddddddffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999999999ddddddddddddddddddddddddddddddddddddffffffffffffddddddddddddddddddddddddddddddddddddffffffddddddddddddbbbbbbffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffff
+dddddd999999999999ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddd999999ffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+bbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999
+ffffffffffffddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddbbbbbbffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff999999999999ffffff999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999
+showpage
+%ps_include: inclusion end
+grestore
+PS-include-dict-dw begin
+o 0 ne {gsave A defaultmatrix /A ed llx lly nice urx ury nice
+ initgraphics 0.1 setlinewidth boxpath stroke grestore} if
+clear o-stack aload pop
+context end restore
+%ps_include: end
+/saveobj save def
+mark
+10 /Palatino-Roman f
+9 /Palatino-Italic f
+(Figure) 1493 2685 w
+(2.) 1756 2685 w
+(A) 1847 2685 w
+(Wm) 1935 2685 w
+(application) 2113 2685 w
+(with) 2538 2685 w
+(a) 2726 2685 w
+(menu) 2789 2685 w
+(bar,) 3017 2685 w
+(a) 3179 2685 w
+(tool) 3242 2685 w
+(bar,) 3400 2685 w
+(and) 3562 2685 w
+(a) 3720 2685 w
+(text) 3783 2685 w
+(window.) 3946 2685 w
+8 /Palatino-Italic f
+(# define and pack text panel and its scrollbar) 1056 2925 w
+8 /Courier f
+("text .t \255yscrollcommand {.scroll set} \255bg white",) 1056 3015 w
+("scrollbar .scroll \255command {.t yview}",) 1056 3105 w
+("pack .scroll \255side left \255fill y \255in .text",) 1056 3195 w
+("pack .t \255side right \255in .text \255expand 1 \255fill both",) 1056 3285 w
+8 /Palatino-Italic f
+(# pack frames) 1056 3465 w
+8 /Courier f
+("pack .text \255side bottom \255fill both \255expand 1",) 1056 3555 w
+("pack .mbar .w \255fill x; update",) 1056 3645 w
+("pack propagate . 0",) 1056 3735 w
+(};) 1056 3825 w
+8 /Palatino-Italic f
+(# run) 1056 4005 w
+(the Tk commands) 1257 4005 w
+8 /Courier f
+(wmlib\255>tkcmds\(top, tk_config\);) 1056 4095 w
+10 /Palatino-Roman f
+(The result of executing these Tk commands is shown in Figure 2.) 720 4275 w
+(The) 720 4431 w
+(arrays) 918 4431 w
+(defining) 1227 4431 w
+(Tk) 1630 4431 w
+(widgets) 1778 4431 w
+(are) 2161 4431 w
+(sometimes) 2330 4431 w
+(made) 2834 4431 w
+(global) 3112 4431 w
+(to) 3417 4431 w
+(a) 3536 4431 w
+(module) 3618 4431 w
+(when) 3991 4431 w
+(they) 4270 4431 w
+(can) 4497 4431 w
+(sensibly) 4681 4431 w
+(be) 720 4551 w
+(used) 853 4551 w
+(by) 1093 4551 w
+(several) 1233 4551 w
+(functions.) 1576 4551 w
+(It) 2067 4551 w
+(is) 2163 4551 w
+(also) 2263 4551 w
+(common) 2468 4551 w
+(to) 2885 4551 w
+(use) 3002 4551 w
+(small) 3181 4551 w
+(Limbo) 3448 4551 w
+(functions) 3765 4551 w
+(to) 4206 4551 w
+(replicate) 4323 4551 w
+(similar) 4733 4551 w
+(widgets) 720 4671 w
+(by) 1102 4671 w
+(building) 1244 4671 w
+(Tk) 1652 4671 w
+(commands) 1800 4671 w
+(from) 2317 4671 w
+(the) 2564 4671 w
+(value) 2734 4671 w
+(of) 3009 4671 w
+(parameters,) 3128 4671 w
+(using) 3683 4671 w
+(Limbo) 3959 4671 w
+(string) 4278 4671 w
+(concatena\255) 4567 4671 w
+(tion or) 720 4791 w
+10 /Courier f
+(sys\255>sprint) 1040 4791 w
+10 /Palatino-Roman f
+(.) 1700 4791 w
+10 /Palatino-Bold f
+(4.2.) 720 5031 w
+(Processing widget events) 920 5031 w
+10 /Palatino-Roman f
+(This) 720 5187 w
+(fragment) 965 5187 w
+(uses) 1426 5187 w
+(an) 1673 5187 w
+10 /Courier f
+(alt) 1836 5187 w
+10 /Palatino-Roman f
+(block) 2071 5187 w
+(to) 2366 5187 w
+(wait) 2510 5187 w
+(for) 2761 5187 w
+(strings) 2945 5187 w
+(to) 3301 5187 w
+(arrive) 3445 5187 w
+(from) 3765 5187 w
+(either) 4037 5187 w
+10 /Courier f
+(titlechan) 4349 5187 w
+10 /Palatino-Roman f
+(or) 4945 5187 w
+10 /Courier f
+(cmdchan) 720 5307 w
+10 /Palatino-Roman f
+(.) 1140 5307 w
+(When) 720 5463 w
+(a) 1016 5463 w
+(string) 1098 5463 w
+(is) 1388 5463 w
+(received) 1491 5463 w
+(on) 1898 5463 w
+10 /Courier f
+(titlechan) 2043 5463 w
+10 /Palatino-Roman f
+(,) 2583 5463 w
+(the) 2640 5463 w
+10 /Courier f
+(case) 2811 5463 w
+10 /Palatino-Roman f
+(statement) 3083 5463 w
+(either) 3548 5463 w
+(handles) 3836 5463 w
+(it) 4214 5463 w
+(directly) 4308 5463 w
+(\(as) 4680 5463 w
+(with) 4837 5463 w
+10 /Courier f
+(exit) 720 5583 w
+10 /Palatino-Roman f
+(\) or passes it to) 960 5583 w
+10 /Courier f
+(wmlib\255>titlectl) 1647 5583 w
+10 /Palatino-Roman f
+(for normal handling by the window manager.) 2572 5583 w
+(When) 720 5739 w
+(a) 1023 5739 w
+(string) 1112 5739 w
+(is) 1409 5739 w
+(received) 1519 5739 w
+(on) 1933 5739 w
+10 /Courier f
+(cmdchan) 2085 5739 w
+10 /Palatino-Roman f
+(,) 2505 5739 w
+(the) 2569 5739 w
+(program) 2747 5739 w
+(acts) 3176 5739 w
+(accordingly:) 3385 5739 w
+(it) 3972 5739 w
+(writes) 4074 5739 w
+(the) 4389 5739 w
+(text) 4568 5739 w
+(in) 4774 5739 w
+(the) 4901 5739 w
+(entry) 720 5859 w
+(widget) 994 5859 w
+(to) 1343 5859 w
+(standard) 1470 5859 w
+(output) 1904 5859 w
+(\() 2244 5859 w
+10 /Courier f
+(send) 2277 5859 w
+10 /Palatino-Roman f
+(\);) 2517 5859 w
+(calls) 2614 5859 w
+10 /Courier f
+(do_open) 2847 5859 w
+10 /Palatino-Roman f
+(to) 3306 5859 w
+(open) 3433 5859 w
+(the) 3693 5859 w
+(file) 3871 5859 w
+(name) 4048 5859 w
+(currently) 4330 5859 w
+(in) 4776 5859 w
+(the) 4901 5859 w
+(entry box \() 720 5979 w
+10 /Courier f
+(open) 1200 5979 w
+10 /Palatino-Roman f
+(\); or returns from the processing loop \() 1440 5979 w
+10 /Courier f
+(exit) 3150 5979 w
+10 /Palatino-Roman f
+(\).) 3390 5979 w
+cleartomark
+showpage
+saveobj restore
+%%EndPage: 5 5
+%%Page: 6 6
+/saveobj save def
+mark
+6 pagesetup
+10 /Palatino-Roman f
+(\255 6 \255) 2797 480 w
+9 /Courier f
+(for\(;;\) {) 1080 820 w
+(alt {) 1296 920 w
+(s := <\255titlechan =>) 1296 1020 w
+9 /Palatino-Italic f
+(#) 2376 1020 w
+(message) 2444 1020 w
+(from) 2762 1020 w
+(title) 2955 1020 w
+(bar) 3123 1020 w
+(buttons) 3262 1020 w
+9 /Courier f
+(case s {) 1512 1120 w
+("exit" =>) 1512 1220 w
+(return;) 1728 1320 w
+(* =>) 1512 1420 w
+(wmlib\255>titlectl\(top,s\);) 1728 1520 w
+(}) 1512 1620 w
+(com := <\255cmdchan =>) 1296 1820 w
+9 /Palatino-Italic f
+(#) 2376 1820 w
+(message) 2444 1820 w
+(from) 2762 1820 w
+(widgets) 2955 1820 w
+(created) 3258 1820 w
+(above) 3538 1820 w
+9 /Courier f
+(case com {) 1512 1920 w
+("send" =>) 1512 2020 w
+(sys\255>print\("name was: %s\\n", tk\255>cmd\(top, ".e get"\)\);) 1728 2120 w
+("open" =>) 1512 2220 w
+(do_open\(top, tk\255>cmd\(top, ".e get"\)\);) 1728 2320 w
+("exit" =>) 1512 2420 w
+(return;) 1728 2520 w
+(}) 1512 2620 w
+(}) 1296 2720 w
+(}) 1080 2820 w
+10 /Palatino-Roman f
+(Although) 720 3001 w
+(this) 1182 3001 w
+(example) 1379 3001 w
+(uses) 1789 3001 w
+(a) 2016 3001 w
+(Tk) 2101 3001 w
+(text) 2253 3001 w
+(entry) 2454 3001 w
+(widget,) 2724 3001 w
+10 /Courier f
+(Wmlib) 3094 3001 w
+10 /Palatino-Roman f
+(provides) 3430 3001 w
+(a) 3858 3001 w
+(function) 3944 3001 w
+10 /Courier f
+(filename) 4350 3001 w
+10 /Palatino-Roman f
+(that) 4866 3001 w
+(pops) 720 3121 w
+(up) 968 3121 w
+(a) 1119 3121 w
+(graphical) 1200 3121 w
+(device) 1647 3121 w
+(that) 1965 3121 w
+(allows) 2170 3121 w
+(a) 2489 3121 w
+(user) 2570 3121 w
+(to) 2791 3121 w
+(select) 2910 3121 w
+(a) 3185 3121 w
+(file) 3266 3121 w
+(by) 3436 3121 w
+(typing) 3578 3121 w
+(a) 3901 3121 w
+(name,) 3982 3121 w
+(browsing) 4282 3121 w
+(the) 4731 3121 w
+(file) 4901 3121 w
+(system, or a mixture of both.) 720 3241 w
+(See) 2038 3241 w
+10 /Palatino-Italic f
+(wmlib) 2212 3241 w
+10 /Palatino-Roman f
+(\(2\) for details.) 2472 3241 w
+10 /Palatino-Bold f
+(4.3.) 720 3482 w
+(Putting text into the text widget) 920 3482 w
+10 /Palatino-Roman f
+(The) 720 3638 w
+10 /Courier f
+(do_open) 925 3638 w
+10 /Palatino-Roman f
+(function) 1383 3638 w
+(below) 1791 3638 w
+(uses) 2100 3638 w
+(the) 2331 3638 w
+(buffered) 2509 3638 w
+(I/O) 2926 3638 w
+(module) 3139 3638 w
+10 /Courier f
+(Bufio) 3519 3638 w
+10 /Palatino-Roman f
+(to) 3858 3638 w
+(read) 3985 3638 w
+(lines) 4223 3638 w
+(from) 4468 3638 w
+(the) 4723 3638 w
+(file) 4901 3638 w
+(named in the entry widget and add them to the text currently in the text widget) 720 3758 w
+10 /Courier f
+(.t) 4267 3758 w
+10 /Palatino-Roman f
+(.) 4387 3758 w
+9 /Courier f
+(do_open\(top: ref Tk\255>Toplevel, file: string\)) 864 3919 w
+({) 864 4019 w
+(iofd := bufio\255>open\(file, Bufio\255>OREAD\);) 1080 4119 w
+(if\(iofd == nil\){) 1080 4219 w
+(wmlib\255>dialog\(top, "error \255fg red", "Open file",) 1296 4319 w
+(sys\255>sprint\("%s: %r", file\), 0, "Ok"::nil\);) 1512 4419 w
+(return;) 1296 4519 w
+(}) 1080 4619 w
+(tk\255>cmd\(top, ".t delete 1.0 end"\);) 1080 4819 w
+(tk\255>cmd\(top, "cursor \255bitmap cursor.wait"\);) 1080 4919 w
+(for\(;;\){) 1080 5119 w
+(line := iofd.gets\('\\n'\);) 1296 5219 w
+(if\(line == nil\)) 1296 5319 w
+(break;) 1512 5419 w
+(tk\255>cmd\(top, ".t insert end '" + line\);) 1296 5519 w
+(}) 1080 5619 w
+(tk\255>cmd\(top, "cursor \255default"\);) 1080 5719 w
+(}) 864 5819 w
+10 /Palatino-Roman f
+(If) 720 6000 w
+(the) 827 6000 w
+(file) 1006 6000 w
+(cannot) 1185 6000 w
+(be) 1523 6000 w
+(opened,) 1666 6000 w
+10 /Courier f
+(do_open) 2061 6000 w
+10 /Palatino-Roman f
+(calls) 2521 6000 w
+10 /Courier f
+(wmlib\255>dialog) 2755 6000 w
+10 /Palatino-Roman f
+(to) 3575 6000 w
+(pop) 3703 6000 w
+(up) 3918 6000 w
+(a) 4078 6000 w
+(diagnostic) 4168 6000 w
+(message) 4666 6000 w
+(panel,) 720 6120 w
+(rather) 1018 6120 w
+(than) 1315 6120 w
+(\(say\)) 1542 6120 w
+(printing) 1783 6120 w
+(a) 2173 6120 w
+(message) 2250 6120 w
+(to) 2651 6120 w
+(standard) 2766 6120 w
+(error,) 3188 6120 w
+(and) 3463 6120 w
+(returns.) 3659 6120 w
+(If) 4057 6120 w
+(the) 4151 6120 w
+(file) 4317 6120 w
+(was) 4483 6120 w
+(opened,) 4685 6120 w
+10 /Courier f
+(do_open) 720 6240 w
+10 /Palatino-Roman f
+(deletes) 1170 6240 w
+(the) 1509 6240 w
+(current) 1678 6240 w
+(contents) 2031 6240 w
+(of) 2432 6240 w
+(the) 2550 6240 w
+(frame,) 2719 6240 w
+(and) 3033 6240 w
+(reads) 3232 6240 w
+(the) 3503 6240 w
+(file) 3672 6240 w
+(into) 3842 6240 w
+(it,) 4048 6240 w
+(inserts) 4166 6240 w
+(one) 4489 6240 w
+(line) 4681 6240 w
+(at) 4876 6240 w
+(a) 4990 6240 w
+(time.) 720 6360 w
+(Tk) 996 6360 w
+(allows) 1141 6360 w
+(the) 1457 6360 w
+(data) 1624 6360 w
+(inserted) 1846 6360 w
+(to) 2233 6360 w
+(contain) 2348 6360 w
+(embedded) 2702 6360 w
+(newlines,) 3199 6360 w
+(and) 3646 6360 w
+(a) 3842 6360 w
+(more) 3919 6360 w
+(efficient) 4177 6360 w
+(implemen\255) 4559 6360 w
+(tation) 720 6480 w
+(could) 1010 6480 w
+(read) 1291 6480 w
+(blocks) 1522 6480 w
+(of) 1835 6480 w
+(data) 1955 6480 w
+(from) 2181 6480 w
+(the) 2429 6480 w
+(file) 2600 6480 w
+(and) 2771 6480 w
+(insert) 2972 6480 w
+(them,) 3254 6480 w
+(but) 3538 6480 w
+(some) 3718 6480 w
+(care) 3983 6480 w
+(is) 4197 6480 w
+(required.) 4300 6480 w
+(A) 4764 6480 w
+(text) 4874 6480 w
+(file) 720 6600 w
+(in) 894 6600 w
+(Inferno) 1016 6600 w
+(contains) 1377 6600 w
+(Unicode) 1780 6600 w
+(characters) 2187 6600 w
+(in) 2670 6600 w
+(UTF\255encoding,) 2791 6600 w
+(and) 3487 6600 w
+(the) 3690 6600 w
+(bytes) 3863 6600 w
+(of) 4131 6600 w
+(a) 4253 6600 w
+(single) 4337 6600 w
+(character) 4633 6600 w
+(might) 720 6720 w
+(be) 1013 6720 w
+(split) 1145 6720 w
+(across) 1367 6720 w
+(separate) 1669 6720 w
+(reads.) 2070 6720 w
+10 /Courier f
+(Iobuf.gets) 2391 6720 w
+10 /Palatino-Roman f
+(by) 3021 6720 w
+(contrast) 3162 6720 w
+(is) 3547 6720 w
+(guaranteed) 3648 6720 w
+(to) 4182 6720 w
+(reassemble) 4300 6720 w
+(com\255) 4820 6720 w
+(plete) 720 6840 w
+(Unicode) 981 6840 w
+(characters) 1397 6840 w
+(from) 1889 6840 w
+(the) 2148 6840 w
+(buffered) 2330 6840 w
+(input) 2751 6840 w
+(stream.) 3034 6840 w
+(A) 3428 6840 w
+(program) 3549 6840 w
+(using) 3981 6840 w
+10 /Courier f
+(Iobuf.read) 4269 6840 w
+10 /Palatino-Roman f
+(\(or) 4912 6840 w
+10 /Courier f
+(Sys\255>read) 720 6960 w
+10 /Palatino-Roman f
+(\)) 1260 6960 w
+(to) 1344 6960 w
+(fetch) 1483 6960 w
+(blocks) 1750 6960 w
+(of) 2083 6960 w
+(data) 2223 6960 w
+(would) 2469 6960 w
+(typically) 2809 6960 w
+(use) 3247 6960 w
+10 /Courier f
+(Sys\255>utfbytes) 3449 6960 w
+10 /Palatino-Roman f
+(to) 4281 6960 w
+(find) 4421 6960 w
+(maximal) 4654 6960 w
+(sequences) 720 7080 w
+(of) 1204 7080 w
+(UTF\255encoded) 1330 7080 w
+(characters) 1971 7080 w
+(and) 2458 7080 w
+(insert) 2665 7080 w
+(large) 2953 7080 w
+(chunks) 3213 7080 w
+(of) 3568 7080 w
+(text) 3693 7080 w
+(at) 3896 7080 w
+(once.) 4016 7080 w
+(See) 4308 7080 w
+(the) 4494 7080 w
+(function) 4670 7080 w
+10 /Courier f
+(loadtfile) 720 7200 w
+10 /Palatino-Roman f
+(in) 1285 7200 w
+10 /Courier f
+(/appl/wm/edit.b) 1397 7200 w
+10 /Palatino-Roman f
+(for example.) 2322 7200 w
+cleartomark
+showpage
+saveobj restore
+%%EndPage: 6 6
+%%Page: 7 7
+/saveobj save def
+mark
+7 pagesetup
+10 /Palatino-Roman f
+(\255 7 \255) 2797 480 w
+10 /Palatino-Bold f
+(5.) 720 840 w
+(Limbo/Tk command syntax) 845 840 w
+10 /Palatino-Roman f
+(Once) 720 997 w
+(a) 986 997 w
+(toplevel) 1073 997 w
+(widget) 1469 997 w
+(has) 1816 997 w
+(been) 2003 997 w
+(built,) 2249 997 w
+(an) 2517 997 w
+(application) 2663 997 w
+(calls) 3198 997 w
+10 /Courier f
+(tk\255>cmd) 3430 997 w
+10 /Palatino-Roman f
+(to) 3888 997 w
+(issue) 4014 997 w
+(commands) 4273 997 w
+(to) 4797 997 w
+(Tk) 4923 997 w
+(and) 720 1117 w
+(receive) 917 1117 w
+(results.) 1259 1117 w
+(This) 1631 1117 w
+(section) 1849 1117 w
+(describes) 2186 1117 w
+(in) 2623 1117 w
+(more) 2738 1117 w
+(detail) 2997 1117 w
+(the) 3275 1117 w
+(contents) 3442 1117 w
+(of) 3840 1117 w
+(the) 3955 1117 w
+(string) 4121 1117 w
+(argument) 4406 1117 w
+(that) 4866 1117 w
+(conveys the commands.) 720 1237 w
+10 /Palatino-Bold f
+(5.1.) 720 1479 w
+(Command strings) 920 1479 w
+10 /Palatino-Roman f
+(The) 720 1636 w
+(command) 913 1636 w
+(string) 1383 1636 w
+(may) 1667 1636 w
+(contain) 1888 1636 w
+(one) 2242 1636 w
+(or) 2430 1636 w
+(more) 2552 1636 w
+(commands,) 2810 1636 w
+(separated) 3348 1636 w
+(by) 3807 1636 w
+(semicolons.) 3945 1636 w
+(A) 4487 1636 w
+(semicolon) 4592 1636 w
+(is) 720 1756 w
+(not) 819 1756 w
+(a) 993 1756 w
+(command) 1071 1756 w
+(separator) 1543 1756 w
+(when) 1989 1756 w
+(it) 2264 1756 w
+(is) 2354 1756 w
+(nested) 2453 1756 w
+(in) 2771 1756 w
+(braces) 2886 1756 w
+(\() 3193 1756 w
+10 /Courier f
+({}) 3226 1756 w
+10 /Palatino-Roman f
+(\)) 3346 1756 w
+(or) 3407 1756 w
+(brackets) 3530 1756 w
+(\() 3925 1756 w
+10 /Courier f
+([]) 3958 1756 w
+10 /Palatino-Roman f
+(\),) 4078 1756 w
+(or) 4163 1756 w
+(it) 4285 1756 w
+(is) 4374 1756 w
+(escaped) 4472 1756 w
+(by) 4852 1756 w
+(a) 4990 1756 w
+(backslash \(\\\).) 720 1876 w
+(Each) 720 2033 w
+(command) 959 2033 w
+(is) 1429 2033 w
+(divided) 1526 2033 w
+(into) 1898 2033 w
+10 /Palatino-Italic f
+(words) 2099 2033 w
+10 /Palatino-Roman f
+(:) 2351 2033 w
+(sequences) 2402 2033 w
+(of) 2874 2033 w
+(characters) 2988 2033 w
+(separated) 3463 2033 w
+(by) 3922 2033 w
+(one) 4060 2033 w
+(or) 4248 2033 w
+(more) 4370 2033 w
+(blanks) 4628 2033 w
+(or) 4945 2033 w
+(tabs, subject to the following quoting rules:) 720 2153 w
+(A) 970 2310 w
+(word) 1075 2310 w
+(beginning) 1341 2310 w
+(with) 1815 2310 w
+(an) 2045 2310 w
+(opening) 2181 2310 w
+(brace) 2573 2310 w
+(\() 2838 2310 w
+10 /Courier f
+({) 2871 2310 w
+10 /Palatino-Roman f
+(\)) 2931 2310 w
+(continues) 2992 2310 w
+(until) 3447 2310 w
+(the) 3684 2310 w
+(balancing) 3851 2310 w
+(closing) 4308 2310 w
+(brace) 4649 2310 w
+(\() 4914 2310 w
+10 /Courier f
+(}) 4947 2310 w
+10 /Palatino-Roman f
+(\)) 5007 2310 w
+(is) 970 2430 w
+(reached.) 1068 2430 w
+(The) 1494 2430 w
+(outer) 1688 2430 w
+(brace) 1951 2430 w
+(characters) 2215 2430 w
+(are) 2691 2430 w
+(stripped.) 2856 2430 w
+(A) 3306 2430 w
+(backslash) 3410 2430 w
+(\() 3862 2430 w
+10 /Courier f
+(\\) 3895 2430 w
+10 /Palatino-Roman f
+(\)) 3955 2430 w
+(can) 4014 2430 w
+(be) 4192 2430 w
+(used) 4321 2430 w
+(to) 4558 2430 w
+(escape) 4672 2430 w
+(a) 4990 2430 w
+(brace, preventing special interpretation.) 970 2550 w
+(A word beginning) 970 2707 w
+(with) 1810 2707 w
+(an) 2039 2707 w
+(opening) 2173 2707 w
+(bracket) 2563 2707 w
+(\() 2915 2707 w
+10 /Courier f
+([) 2948 2707 w
+10 /Palatino-Roman f
+(\)) 3008 2707 w
+(continues) 3067 2707 w
+(until) 3520 2707 w
+(the) 3755 2707 w
+(balancing) 3920 2707 w
+(closing) 4375 2707 w
+(bracket) 4714 2707 w
+(\() 970 2827 w
+10 /Courier f
+(]) 1003 2827 w
+10 /Palatino-Roman f
+(\)) 1063 2827 w
+(is) 1124 2827 w
+(reached.) 1223 2827 w
+(The) 1625 2827 w
+(enclosed) 1820 2827 w
+(string) 2233 2827 w
+(is) 2519 2827 w
+(then) 2617 2827 w
+(evaluated) 2841 2827 w
+(as) 3304 2827 w
+(if) 3423 2827 w
+(it) 3512 2827 w
+(were) 3601 2827 w
+(a) 3847 2827 w
+(command) 3924 2827 w
+(string,) 4395 2827 w
+(and) 4705 2827 w
+(the) 4901 2827 w
+(resulting value is used as the contents of the word.) 970 2947 w
+(At) 970 3104 w
+(any) 1118 3104 w
+(point) 1319 3104 w
+(in) 1591 3104 w
+(the) 1715 3104 w
+(command) 1891 3104 w
+(string) 2372 3104 w
+(a) 2668 3104 w
+(single) 2756 3104 w
+(quote) 3056 3104 w
+(\() 3346 3104 w
+10 /Courier f
+(') 3379 3104 w
+10 /Palatino-Roman f
+(\)) 3439 3104 w
+(causes) 3510 3104 w
+(the) 3834 3104 w
+(rest) 4011 3104 w
+(of) 4212 3104 w
+(the) 4338 3104 w
+(string) 4515 3104 w
+(to) 4811 3104 w
+(be) 4937 3104 w
+(treated as one word.) 970 3224 w
+(Single) 720 3381 w
+(commands) 1019 3381 w
+(are) 1531 3381 w
+(executed) 1695 3381 w
+(in) 2115 3381 w
+(order) 2228 3381 w
+(until) 2498 3381 w
+(they) 2733 3381 w
+(are) 2954 3381 w
+(all) 3118 3381 w
+(done) 3252 3381 w
+(or) 3500 3381 w
+(an) 3621 3381 w
+(error) 3755 3381 w
+(is) 4004 3381 w
+(encountered.) 4101 3381 w
+(By) 4706 3381 w
+(con\255) 4850 3381 w
+(vention,) 720 3501 w
+(an) 1122 3501 w
+(error) 1269 3501 w
+(is) 1531 3501 w
+(signalled) 1641 3501 w
+(by) 2082 3501 w
+(a) 2232 3501 w
+(return) 2320 3501 w
+(value) 2637 3501 w
+(starting) 2919 3501 w
+(with) 3298 3501 w
+(an) 3539 3501 w
+(exclamation) 3685 3501 w
+(mark.) 4259 3501 w
+(The) 4556 3501 w
+(return) 4761 3501 w
+(value) 720 3621 w
+(from) 992 3621 w
+10 /Courier f
+(cmd) 1236 3621 w
+10 /Palatino-Roman f
+(is) 1444 3621 w
+(the) 1543 3621 w
+(return) 1710 3621 w
+(value) 2017 3621 w
+(of) 2289 3621 w
+(the) 2405 3621 w
+(first) 2573 3621 w
+(error\255producing) 2779 3621 w
+(command) 3527 3621 w
+(or) 4000 3621 w
+(else) 4124 3621 w
+(the) 4320 3621 w
+(return) 4488 3621 w
+(value) 4796 3621 w
+(of the final single command.) 720 3741 w
+(To execute a single command, the first word is examined. It can be one of the following:) 720 3898 w
+10 /LucidaSansUnicode22 f
+(\031) 720 4055 w
+10 /Palatino-Roman f
+(One of the following widget creating commands:) 970 4055 w
+10 /Courier f
+(button) 970 4236 w
+(menu) 1780 4236 w
+(canvas) 970 4356 w
+(menubutton) 1780 4356 w
+(checkbutton) 970 4476 w
+(radiobutton) 1780 4476 w
+(entry) 970 4596 w
+(scale) 1780 4596 w
+(frame) 970 4716 w
+(scrollbar) 1780 4716 w
+(label) 970 4836 w
+(text) 1780 4836 w
+(listbox) 970 4956 w
+10 /Palatino-Roman f
+(The) 970 5137 w
+(second) 1170 5137 w
+(word) 1511 5137 w
+(of) 1783 5137 w
+(each) 1904 5137 w
+(of) 2137 5137 w
+(these) 2258 5137 w
+(commands) 2520 5137 w
+(is) 3039 5137 w
+(the) 3143 5137 w
+(name) 3315 5137 w
+(of) 3592 5137 w
+(the) 3714 5137 w
+(widget) 3887 5137 w
+(to) 4231 5137 w
+(be) 4353 5137 w
+(created.) 4490 5137 w
+(The) 4873 5137 w
+(remaining words are option/value pairs.) 970 5257 w
+10 /LucidaSansUnicode22 f
+(\031) 720 5414 w
+10 /Palatino-Roman f
+(A) 970 5414 w
+(widget) 1079 5414 w
+(name) 1420 5414 w
+(\(beginning) 1695 5414 w
+(with) 2206 5414 w
+(a) 2441 5414 w
+(dot) 2523 5414 w
+(`) 2704 5414 w
+10 /Courier f
+(.) 2732 5414 w
+10 /Palatino-Roman f
+('\)) 2792 5414 w
+(that) 2885 5414 w
+(corresponds) 3091 5414 w
+(to) 3668 5414 w
+(an) 3788 5414 w
+(existing) 3928 5414 w
+(widget.) 4307 5414 w
+(The) 4674 5414 w
+(sec\255) 4873 5414 w
+(ond) 970 5534 w
+(word) 1171 5534 w
+(gives) 1437 5534 w
+(the) 1696 5534 w
+(name) 1862 5534 w
+(of) 2133 5534 w
+(a) 2248 5534 w
+(particular) 2325 5534 w
+(widget) 2787 5534 w
+(subcommand) 3124 5534 w
+(and) 3752 5534 w
+(the) 3948 5534 w
+(remaining) 4113 5534 w
+(words) 4595 5534 w
+(are) 4902 5534 w
+(arguments for the subcommand.) 970 5654 w
+10 /LucidaSansUnicode22 f
+(\031) 720 5811 w
+10 /Palatino-Roman f
+(A) 970 5811 w
+10 /Courier f
+(pack) 1087 5811 w
+10 /Palatino-Roman f
+(,) 1327 5811 w
+10 /Courier f
+(bind) 1391 5811 w
+10 /Palatino-Roman f
+(,) 1631 5811 w
+10 /Courier f
+(focus) 1695 5811 w
+10 /Palatino-Roman f
+(,) 1995 5811 w
+10 /Courier f
+(grab) 2059 5811 w
+10 /Palatino-Roman f
+(,) 2299 5811 w
+10 /Courier f
+(put) 2363 5811 w
+10 /Palatino-Roman f
+(,) 2543 5811 w
+10 /Courier f
+(destroy) 2607 5811 w
+10 /Palatino-Roman f
+(,) 3027 5811 w
+10 /Courier f
+(image) 3091 5811 w
+10 /Palatino-Roman f
+(,) 3391 5811 w
+(or) 3455 5811 w
+10 /Courier f
+(update) 3589 5811 w
+10 /Palatino-Roman f
+(command.) 3989 5811 w
+(These) 4523 5811 w
+(com\255) 4820 5811 w
+(mands) 970 5931 w
+(manipulate) 1296 5931 w
+(existing) 1828 5931 w
+(widgets) 2202 5931 w
+(or) 2581 5931 w
+(control) 2702 5931 w
+(Tk.) 3042 5931 w
+(Most) 3235 5931 w
+(are) 3486 5931 w
+(the) 3650 5931 w
+(same) 3815 5931 w
+(as) 4069 5931 w
+(documented) 4187 5931 w
+(for) 4769 5931 w
+(Tk) 4923 5931 w
+(4.0.) 970 6051 w
+(The) 1182 6051 w
+10 /Courier f
+(bind) 1386 6051 w
+10 /Palatino-Roman f
+(command) 1663 6051 w
+(is) 2144 6051 w
+(significantly) 2252 6051 w
+(different,) 2835 6051 w
+(and) 3280 6051 w
+(the) 3486 6051 w
+10 /Courier f
+(image) 3663 6051 w
+10 /Palatino-Roman f
+(command) 4001 6051 w
+(is) 4483 6051 w
+(more) 4592 6051 w
+(lim\255) 4861 6051 w
+(ited.) 970 6171 w
+10 /LucidaSansUnicode22 f
+(\031) 720 6328 w
+10 /Palatino-Roman f
+(The) 970 6328 w
+10 /Courier f
+(send) 1238 6328 w
+10 /Palatino-Roman f
+(command,) 1579 6328 w
+(which) 2081 6328 w
+(sends) 2386 6328 w
+(a) 2670 6328 w
+(string) 2753 6328 w
+(to) 3044 6328 w
+(a) 3165 6328 w
+(Limbo) 3248 6328 w
+(process.) 3569 6328 w
+(The) 3983 6328 w
+(second) 4183 6328 w
+(word) 4524 6328 w
+(is) 4796 6328 w
+(the) 4901 6328 w
+(Tk) 970 6448 w
+(name) 1126 6448 w
+(of) 1409 6448 w
+(a) 1536 6448 w
+(Limbo) 1625 6448 w
+(channel) 1952 6448 w
+(\(previously) 2336 6448 w
+(registered) 2884 6448 w
+(with) 3368 6448 w
+10 /Courier f
+(namechan) 3610 6448 w
+10 /Palatino-Roman f
+(\),) 4090 6448 w
+(and) 4187 6448 w
+(the) 4395 6448 w
+(rest) 4573 6448 w
+(of) 4775 6448 w
+(the) 4901 6448 w
+(command is sent as a single string along the channel.) 970 6568 w
+10 /LucidaSansUnicode22 f
+(\031) 720 6725 w
+10 /Palatino-Roman f
+(The) 970 6725 w
+10 /Courier f
+(variable) 1171 6725 w
+10 /Palatino-Roman f
+(command.) 1685 6725 w
+(Limbo/Tk) 2214 6725 w
+(generally) 2715 6725 w
+(does) 3164 6725 w
+(not) 3405 6725 w
+(provide) 3586 6725 w
+(the) 3971 6725 w
+(variables) 4145 6725 w
+(of) 4580 6725 w
+(Tcl/Tk;) 4703 6725 w
+(radio) 970 6845 w
+(buttons) 1252 6845 w
+(are) 1635 6845 w
+(an) 1820 6845 w
+(exception.) 1975 6845 w
+(The) 2473 6845 w
+10 /Courier f
+(variable) 2686 6845 w
+10 /Palatino-Roman f
+(command) 3212 6845 w
+(takes) 3702 6845 w
+(the) 3977 6845 w
+(name) 4162 6845 w
+(of) 4452 6845 w
+(a) 4586 6845 w
+(variable) 4682 6845 w
+(defined) 970 6965 w
+(in) 1340 6965 w
+(a) 1459 6965 w
+(radio) 1541 6965 w
+(button) 1808 6965 w
+(as) 2134 6965 w
+(the) 2258 6965 w
+(second) 2429 6965 w
+(word,) 2769 6965 w
+(and) 3065 6965 w
+(the) 3266 6965 w
+(value) 3437 6965 w
+(of) 3713 6965 w
+(the) 3833 6965 w
+(variable) 4004 6965 w
+(is) 4394 6965 w
+(the) 4497 6965 w
+(result) 4668 6965 w
+(of) 4952 6965 w
+(the) 970 7085 w
+(command.) 1141 7085 w
+(Furthermore,) 1642 7085 w
+(there) 2265 7085 w
+(is) 2524 7085 w
+(one) 2627 7085 w
+(predefined) 2820 7085 w
+(variable) 3338 7085 w
+(whose) 3727 7085 w
+(value) 4044 7085 w
+(can) 4319 7085 w
+(be) 4502 7085 w
+(retrieved) 4636 7085 w
+(this) 970 7205 w
+(way:) 1169 7205 w
+(the) 1420 7205 w
+10 /Courier f
+(lasterror) 1596 7205 w
+10 /Palatino-Roman f
+(variable) 2173 7205 w
+(is) 2568 7205 w
+(set) 2676 7205 w
+(every) 2836 7205 w
+(time) 3122 7205 w
+(a) 3357 7205 w
+(Tk) 3445 7205 w
+(command) 3600 7205 w
+(returns) 4082 7205 w
+(an) 4441 7205 w
+(error.) 4587 7205 w
+(The) 4873 7205 w
+cleartomark
+showpage
+saveobj restore
+%%EndPage: 7 7
+%%Page: 8 8
+/saveobj save def
+mark
+8 pagesetup
+10 /Palatino-Roman f
+(\255 8 \255) 2797 480 w
+(value) 970 840 w
+(is) 1253 840 w
+(the) 1363 840 w
+(offending) 1541 840 w
+(command) 2011 840 w
+(\(possibly) 2494 840 w
+(truncated\)) 2934 840 w
+(followed) 3433 840 w
+(by) 3865 840 w
+(the) 4015 840 w
+(error) 4193 840 w
+(return) 4454 840 w
+(value.) 4771 840 w
+(The) 970 960 w
+10 /Courier f
+(lasterror) 1172 960 w
+10 /Palatino-Roman f
+(variable) 1747 960 w
+(is) 2140 960 w
+(cleared) 2246 960 w
+(whenever) 2601 960 w
+(it) 3076 960 w
+(is) 3174 960 w
+(retrieved) 3281 960 w
+(using) 3721 960 w
+(the) 4002 960 w
+(variable) 4177 960 w
+(command.) 4571 960 w
+(This) 970 1080 w
+(allows) 1190 1080 w
+(several) 1508 1080 w
+(Tk) 1851 1080 w
+(commands) 1997 1080 w
+(to) 2512 1080 w
+(be) 2629 1080 w
+(executed) 2761 1080 w
+(without) 3184 1080 w
+(checking) 3564 1080 w
+(error) 3986 1080 w
+(returns) 4238 1080 w
+(each) 4588 1080 w
+(time.) 4817 1080 w
+(A) 970 1200 w
+(call) 1080 1200 w
+(to) 1264 1200 w
+(the) 1384 1200 w
+10 /Courier f
+(variable) 1555 1200 w
+10 /Palatino-Roman f
+(command) 2067 1200 w
+(with) 2543 1200 w
+10 /Courier f
+(lasterror) 2778 1200 w
+10 /Palatino-Roman f
+(at) 3350 1200 w
+(strategic) 3465 1200 w
+(points) 3873 1200 w
+(can) 4183 1200 w
+(make) 4368 1200 w
+(sure) 4643 1200 w
+(that) 4866 1200 w
+(an unexpected error has not occurred.) 970 1320 w
+10 /LucidaSansUnicode22 f
+(\031) 720 1477 w
+10 /Palatino-Roman f
+(The) 970 1477 w
+10 /Courier f
+(cursor) 1165 1477 w
+10 /Palatino-Roman f
+(command.) 1553 1477 w
+(This) 2050 1477 w
+(command) 2268 1477 w
+(takes) 2740 1477 w
+(a) 2997 1477 w
+(number) 3075 1477 w
+(of) 3452 1477 w
+(option/value) 3568 1477 w
+(pairs) 4191 1477 w
+(to) 4441 1477 w
+(control) 4558 1477 w
+(the) 4901 1477 w
+(appearance) 970 1597 w
+(and) 1505 1597 w
+(placement) 1701 1597 w
+(of) 2186 1597 w
+(the) 2301 1597 w
+(cursor.) 2467 1597 w
+(Available) 2800 1597 w
+(options) 3251 1597 w
+(are:) 3609 1597 w
+10 /Courier f
+(\255x) 3798 1597 w
+10 /Palatino-Italic f
+(int) 3944 1597 w
+10 /Palatino-Roman f
+(and) 4095 1597 w
+10 /Courier f
+(\255y) 4290 1597 w
+10 /Palatino-Italic f
+(int) 4436 1597 w
+10 /Palatino-Roman f
+(,) 4561 1597 w
+(to) 4612 1597 w
+(change) 4726 1597 w
+(the) 970 1717 w
+(cursor) 1137 1717 w
+(position) 1446 1717 w
+(to) 1835 1717 w
+(align) 1951 1717 w
+(its) 2201 1717 w
+(hotpoint) 2333 1717 w
+(at) 2742 1717 w
+(the) 2853 1717 w
+(given) 3020 1717 w
+(point) 3296 1717 w
+(\(in) 3560 1717 w
+(screen) 3709 1717 w
+(coordinates\);) 4018 1717 w
+10 /Courier f
+(\255bitmap) 4620 1717 w
+10 /Palatino-Italic f
+(filename) 970 1837 w
+10 /Palatino-Roman f
+(or) 1356 1837 w
+10 /Courier f
+(\255image) 1489 1837 w
+10 /Palatino-Italic f
+(imagename) 1887 1837 w
+10 /Palatino-Roman f
+(to) 2388 1837 w
+(change) 2513 1837 w
+(the) 2864 1837 w
+(appearance) 3040 1837 w
+(of) 3585 1837 w
+(the) 3710 1837 w
+(cursor;) 3886 1837 w
+(and) 4229 1837 w
+10 /Courier f
+(\255default) 4435 1837 w
+10 /Palatino-Roman f
+(to) 4952 1837 w
+(change back to the default appearance of the cursor.) 970 1957 w
+(Because) 720 2114 w
+(the) 1114 2114 w
+(language) 1295 2114 w
+(accepted) 1744 2114 w
+(by) 2174 2114 w
+(the) 2327 2114 w
+10 /Courier f
+(cmd) 2508 2114 w
+10 /Palatino-Roman f
+(function) 2730 2114 w
+(has) 3142 2114 w
+(no) 3334 2114 w
+(user\255defined) 3489 2114 w
+(functions,) 4092 2114 w
+(no) 4571 2114 w
+(control) 4726 2114 w
+(flow) 720 2234 w
+(and) 957 2234 w
+(very) 1163 2234 w
+(few) 1401 2234 w
+(variables,) 1602 2234 w
+(almost) 2064 2234 w
+(all) 2398 2234 w
+(applications) 2543 2234 w
+(need) 3119 2234 w
+(to) 3370 2234 w
+(have) 3494 2234 w
+(some) 3743 2234 w
+(of) 4012 2234 w
+(their) 4136 2234 w
+(logic) 4380 2234 w
+(in) 4629 2234 w
+(Limbo) 4752 2234 w
+(programs.) 720 2354 w
+(The) 1247 2354 w
+(modern) 1460 2354 w
+(concurrency) 1856 2354 w
+(constructions) 2449 2354 w
+(provided) 3088 2354 w
+(by) 3545 2354 w
+(Limbo) 3703 2354 w
+10 /LucidaSansUnicode20 f
+(\023) 4038 2354 w
+10 /Palatino-Roman f
+(processes,) 4135 2354 w
+(channels,) 4628 2354 w
+(send/receive) 720 2474 w
+(operators) 1348 2474 w
+(and) 1815 2474 w
+10 /Courier f
+(alt) 2028 2474 w
+10 /LucidaSansUnicode20 f
+(\023) 2208 2474 w
+10 /Palatino-Roman f
+(replace) 2302 2474 w
+(unstructured) 2665 2474 w
+(interrupts) 3287 2474 w
+(\(`call) 3773 2474 w
+(backs'\),) 4029 2474 w
+(often) 4405 2474 w
+(used) 4675 2474 w
+(by) 4929 2474 w
+(other) 720 2594 w
+(graphics) 998 2594 w
+(systems,) 1421 2594 w
+(by) 1841 2594 w
+(structured) 1996 2594 w
+(control) 2501 2594 w
+(flow.) 2859 2594 w
+(\(The) 3153 2594 w
+(Inferno) 3397 2594 w
+(shell) 3768 2594 w
+(does) 4019 2594 w
+(provide) 4270 2594 w
+(support,) 4665 2594 w
+(however,) 720 2714 w
+(for) 1167 2714 w
+(rapid) 1327 2714 w
+(prototyping) 1599 2714 w
+(using) 2166 2714 w
+(Tk) 2443 2714 w
+(and) 2592 2714 w
+(a) 2793 2714 w
+(scripting) 2875 2714 w
+(language:) 3298 2714 w
+(see) 3762 2714 w
+(the) 3932 2714 w
+(manual) 4103 2714 w
+(pages) 4470 2714 w
+(for) 4758 2714 w
+10 /Palatino-Italic f
+(sh\255) 4918 2714 w
+(tk) 720 2834 w
+10 /Palatino-Roman f
+(\(1\) and) 805 2834 w
+10 /Palatino-Italic f
+(wish) 1140 2834 w
+10 /Palatino-Roman f
+(\(1\) in Volume 1.\)) 1337 2834 w
+10 /Palatino-Bold f
+(5.2.) 720 3076 w
+(Widget options) 920 3076 w
+10 /Palatino-Roman f
+(In) 720 3233 w
+(Tk,) 849 3233 w
+(all) 1028 3233 w
+(widget) 1173 3233 w
+(creation) 1520 3233 w
+(commands,) 1914 3233 w
+(and) 2462 3233 w
+(all) 2668 3233 w
+10 /Courier f
+(cget) 2813 3233 w
+10 /Palatino-Roman f
+(widget) 3090 3233 w
+(commands) 3437 3233 w
+(accept) 3960 3233 w
+(a) 4277 3233 w
+(common) 4365 3233 w
+(set) 4791 3233 w
+(of) 4952 3233 w
+(generic) 720 3353 w
+(options) 1076 3353 w
+(in) 1441 3353 w
+(addition) 1560 3353 w
+(to) 1968 3353 w
+(widget\255specific) 2088 3353 w
+(options.) 2792 3353 w
+(Except) 3206 3353 w
+(as) 3536 3353 w
+(noted) 3660 3353 w
+(otherwise,) 3947 3353 w
+(the) 4440 3353 w
+(meanings) 4611 3353 w
+(are) 720 3473 w
+(the) 898 3473 w
+(same) 1077 3473 w
+(as) 1345 3473 w
+(they) 1477 3473 w
+(are) 1712 3473 w
+(in) 1890 3473 w
+(Tk) 2017 3473 w
+(4.0.) 2174 3473 w
+(The) 2364 3473 w
+(allowable) 2571 3473 w
+(forms) 3040 3473 w
+(of) 3339 3473 w
+(things) 3468 3473 w
+(like) 3785 3473 w
+10 /Palatino-Italic f
+(color) 3988 3473 w
+10 /Palatino-Roman f
+(,) 4192 3473 w
+10 /Palatino-Italic f
+(dist) 4258 3473 w
+10 /Palatino-Roman f
+(,) 4416 3473 w
+(and) 4482 3473 w
+10 /Palatino-Italic f
+(font) 4692 3473 w
+10 /Palatino-Roman f
+(are) 4902 3473 w
+(slightly) 720 3593 w
+(different) 1097 3593 w
+(in) 1525 3593 w
+(Limbo/Tk.) 1657 3593 w
+(See) 2217 3593 w
+10 /Palatino-Italic f
+(types) 2410 3593 w
+10 /Palatino-Roman f
+(\(9\)) 2629 3593 w
+(in) 2789 3593 w
+(Volume) 2920 3593 w
+(1) 3316 3593 w
+(for) 3410 3593 w
+(precise) 3582 3593 w
+(definitions.) 3937 3593 w
+(The) 4506 3593 w
+(generic) 4717 3593 w
+(options are as follows:) 720 3713 w
+10 /Courier f
+(\255activebackground) 970 3894 w
+10 /Palatino-Italic f
+(color) 2015 3894 w
+10 /Courier f
+(\255activeforeground) 970 4014 w
+10 /Palatino-Italic f
+(color) 2015 4014 w
+10 /Courier f
+(\255actwidth) 970 4134 w
+10 /Palatino-Italic f
+(dist) 1535 4134 w
+10 /Courier f
+(\255actheight) 970 4254 w
+10 /Palatino-Italic f
+(dist) 1595 4254 w
+10 /Palatino-Roman f
+(Note:) 970 4435 w
+(the) 1247 4435 w
+10 /Courier f
+(\255actwidth) 1419 4435 w
+10 /Palatino-Roman f
+(and) 1993 4435 w
+10 /Courier f
+(\255actheight) 2196 4435 w
+10 /Palatino-Roman f
+(variables) 2830 4435 w
+(are) 3264 4435 w
+(overridden) 3436 4435 w
+(by) 3967 4435 w
+(the) 4112 4435 w
+(packer,) 4285 4435 w
+(but) 4642 4435 w
+(are) 970 4555 w
+(useful) 1146 4555 w
+(as) 1456 4555 w
+(arguments) 1586 4555 w
+(to) 2099 4555 w
+10 /Courier f
+(cget) 2225 4555 w
+10 /Palatino-Roman f
+(to) 2503 4555 w
+(retrieve) 2629 4555 w
+(the) 3009 4555 w
+(actual) 3185 4555 w
+(width) 3488 4555 w
+(and) 3789 4555 w
+(height) 3995 4555 w
+(\(inside) 4314 4555 w
+(the) 4651 4555 w
+(border\) of a widget after packing.) 970 4675 w
+10 /Courier f
+(\255background) 970 4856 w
+10 /Palatino-Italic f
+(color) 1655 4856 w
+10 /Palatino-Roman f
+(\(or) 1884 4856 w
+10 /Courier f
+(\255bg) 2037 4856 w
+10 /Palatino-Italic f
+(color) 2242 4856 w
+10 /Palatino-Roman f
+(\)) 2446 4856 w
+10 /Courier f
+(\255borderwidth) 970 4976 w
+10 /Palatino-Italic f
+(dist) 1715 4976 w
+10 /Palatino-Roman f
+(\(or) 1898 4976 w
+10 /Courier f
+(\255bd) 2051 4976 w
+10 /Palatino-Italic f
+(dist) 2256 4976 w
+10 /Palatino-Roman f
+(\)) 2414 4976 w
+10 /Courier f
+(\255font) 970 5096 w
+10 /Palatino-Italic f
+(font) 1295 5096 w
+10 /Courier f
+(\255foreground) 970 5216 w
+10 /Palatino-Italic f
+(color) 1655 5216 w
+10 /Palatino-Roman f
+(\(or) 1884 5216 w
+10 /Courier f
+(\255fg) 2037 5216 w
+10 /Palatino-Italic f
+(color) 2242 5216 w
+10 /Palatino-Roman f
+(\)) 2446 5216 w
+10 /Courier f
+(\255height) 970 5336 w
+10 /Palatino-Italic f
+(dist) 1415 5336 w
+10 /Courier f
+(\255padx) 970 5456 w
+10 /Palatino-Italic f
+(dist) 1295 5456 w
+10 /Courier f
+(\255pady) 970 5576 w
+10 /Palatino-Italic f
+(dist) 1295 5576 w
+10 /Courier f
+(\255relief) 970 5696 w
+10 /Palatino-Italic f
+(relief) 1415 5696 w
+10 /Courier f
+(\255state) 970 5816 w
+10 /Palatino-Italic f
+(normal) 1355 5816 w
+10 /Palatino-Roman f
+(,) 1652 5816 w
+10 /Courier f
+(\255state) 1702 5816 w
+10 /Palatino-Italic f
+(active) 2087 5816 w
+10 /Palatino-Roman f
+(, or) 2330 5816 w
+10 /Courier f
+(\255state) 2500 5816 w
+10 /Palatino-Italic f
+(disabled) 2885 5816 w
+10 /Palatino-Roman f
+(Note:) 970 5997 w
+10 /Courier f
+(\255state) 1239 5997 w
+10 /Palatino-Roman f
+(is only relevant for some widgets \(for example, entry widgets\).) 1624 5997 w
+10 /Courier f
+(\255selectbackground) 970 6178 w
+10 /Palatino-Italic f
+(color) 2015 6178 w
+10 /Courier f
+(\255selectborderwidth) 970 6298 w
+10 /Palatino-Italic f
+(dist) 2075 6298 w
+10 /Courier f
+(\255selectcolor) 970 6418 w
+10 /Palatino-Italic f
+(color) 1715 6418 w
+10 /Palatino-Roman f
+(Note:) 970 6599 w
+10 /Courier f
+(\255selectcolor) 1239 6599 w
+10 /Palatino-Roman f
+(is the colour of the box in selection menu items.) 1984 6599 w
+10 /Courier f
+(\255selectforeground) 970 6780 w
+10 /Palatino-Italic f
+(colour) 2015 6780 w
+10 /Courier f
+(\255width) 970 6900 w
+10 /Palatino-Italic f
+(dist) 1355 6900 w
+10 /Palatino-Roman f
+(In general, the) 720 7081 w
+(manual) 1381 7081 w
+(page) 1742 7081 w
+(for) 1982 7081 w
+(each) 2136 7081 w
+(widget) 2362 7081 w
+(in) 2698 7081 w
+(section) 2811 7081 w
+(9) 3146 7081 w
+(of) 3222 7081 w
+(Volume) 3336 7081 w
+(1) 3714 7081 w
+(tells) 3790 7081 w
+(which) 3997 7081 w
+(of) 4295 7081 w
+(the) 4409 7081 w
+(generic) 4574 7081 w
+(Tk) 4923 7081 w
+(options the widget accepts.) 720 7201 w
+cleartomark
+showpage
+saveobj restore
+%%EndPage: 8 8
+%%Page: 9 9
+/saveobj save def
+mark
+9 pagesetup
+10 /Palatino-Roman f
+(\255 9 \255) 2797 480 w
+(The) 720 840 w
+10 /Palatino-Italic f
+(dist) 923 840 w
+10 /Palatino-Roman f
+(parameters) 1117 840 w
+(are) 1652 840 w
+(lengths,) 1826 840 w
+(expressed) 2211 840 w
+(in) 2689 840 w
+(the) 2813 840 w
+(following) 2989 840 w
+(form:) 3453 840 w
+(an) 3731 840 w
+(optional) 3876 840 w
+(minus) 4282 840 w
+(sign,) 4596 840 w
+(then) 4843 840 w
+(one) 720 960 w
+(or) 908 960 w
+(more) 1030 960 w
+(decimal) 1288 960 w
+(digits) 1664 960 w
+(\(with) 1941 960 w
+(possible) 2204 960 w
+(embedded) 2591 960 w
+(decimal) 3088 960 w
+(point\),) 3464 960 w
+(then) 3784 960 w
+(an) 4007 960 w
+(optional) 4141 960 w
+(units) 4536 960 w
+(speci\255) 4784 960 w
+(fier.) 720 1080 w
+(The unit specifiers are the following:) 945 1080 w
+10 /Courier f
+(c) 970 1271 w
+10 /Palatino-Roman f
+(centimetres) 1180 1271 w
+10 /Courier f
+(m) 970 1391 w
+10 /Palatino-Roman f
+(millimetres) 1180 1391 w
+10 /Courier f
+(i) 970 1511 w
+10 /Palatino-Roman f
+(inches) 1180 1511 w
+10 /Courier f
+(p) 970 1631 w
+10 /Palatino-Roman f
+(points) 1180 1631 w
+10 /Courier f
+(h) 970 1751 w
+10 /Palatino-Roman f
+(height of widget's font \(*\)) 1180 1751 w
+10 /Courier f
+(w) 970 1871 w
+10 /Palatino-Roman f
+(width of `) 1180 1871 w
+10 /Courier f
+(0) 1610 1871 w
+10 /Palatino-Roman f
+(' character in widget's font \(*\)) 1670 1871 w
+(The ones marked \(*\) are specific to Limbo/Tk.) 720 2062 w
+(Tcl/Tk) 720 2225 w
+(4.0) 1068 2225 w
+(widgets) 1229 2225 w
+(do) 1617 2225 w
+(not) 1769 2225 w
+(uniformly) 1951 2225 w
+(take) 2435 2225 w
+10 /Courier f
+(\255width) 2658 2225 w
+10 /Palatino-Roman f
+(and) 3054 2225 w
+10 /Courier f
+(\255height) 3259 2225 w
+10 /Palatino-Roman f
+(options;) 3716 2225 w
+(instead,) 4110 2225 w
+(each) 4493 2225 w
+(widget) 4730 2225 w
+(may) 720 2345 w
+(take) 949 2345 w
+(either) 1171 2345 w
+(or) 1461 2345 w
+(both,) 1590 2345 w
+(and) 1850 2345 w
+(the) 2053 2345 w
+(interpretation) 2226 2345 w
+(of) 2874 2345 w
+(a) 2996 2345 w
+(number) 3080 2345 w
+(lacking) 3463 2345 w
+(a) 3819 2345 w
+(unit) 3903 2345 w
+(specifier) 4117 2345 w
+(varies) 4524 2345 w
+(from) 4824 2345 w
+(widget) 720 2465 w
+(to) 1056 2465 w
+(widget.) 1170 2465 w
+(For) 1531 2465 w
+(example,) 1708 2465 w
+(in) 2134 2465 w
+(Tk) 2247 2465 w
+(4.0) 2390 2465 w
+10 /Courier f
+(\255width) 2541 2465 w
+(25) 2962 2465 w
+10 /Palatino-Roman f
+(means) 3108 2465 w
+(25) 3420 2465 w
+(characters) 3546 2465 w
+(to) 4021 2465 w
+(an) 4135 2465 w
+(entry) 4269 2465 w
+(widget,) 4530 2465 w
+(but) 4892 2465 w
+(25) 720 2585 w
+(pixels) 854 2585 w
+(to) 1148 2585 w
+(a) 1270 2585 w
+(canvas) 1354 2585 w
+(widget.) 1689 2585 w
+(In) 2058 2585 w
+(Limbo/Tk,) 2184 2585 w
+(all) 2708 2585 w
+(widgets) 2849 2585 w
+(may) 3234 2585 w
+(specify) 3461 2585 w
+(width) 3806 2585 w
+(and) 4103 2585 w
+(height,) 4305 2585 w
+(and) 4645 2585 w
+(bare) 4847 2585 w
+(numbers always mean screen pixels.) 720 2705 w
+(A) 720 2868 w
+10 /Palatino-Italic f
+(colour) 823 2868 w
+10 /Palatino-Roman f
+(parameter can be a colour name or an RGB value.) 1108 2868 w
+(Only a few names are known:) 3348 2868 w
+10 /Courier f
+(aqua) 970 3059 w
+(fuchsia) 1600 3059 w
+(maroon) 2170 3059 w
+(purple) 2680 3059 w
+(yellow) 3190 3059 w
+(black) 970 3179 w
+(gray) 1600 3179 w
+(navy) 2170 3179 w
+(red) 2680 3179 w
+(blue) 970 3299 w
+(green) 1600 3299 w
+(olive) 2170 3299 w
+(teal) 2680 3299 w
+(darkblue) 970 3419 w
+(lime) 1600 3419 w
+(orange) 2170 3419 w
+(white) 2680 3419 w
+10 /Palatino-Roman f
+(For) 720 3610 w
+(RGB) 902 3610 w
+(values,) 1138 3610 w
+(either) 1481 3610 w
+10 /Courier f
+(#) 1769 3610 w
+10 /Palatino-Italic f
+(rgb) 1829 3610 w
+10 /Palatino-Roman f
+(or) 1996 3610 w
+10 /Courier f
+(#) 2123 3610 w
+10 /Palatino-Italic f
+(rrggbb) 2183 3610 w
+10 /Palatino-Roman f
+(can) 2485 3610 w
+(be) 2669 3610 w
+(used,) 2804 3610 w
+(where) 3072 3610 w
+10 /Palatino-Italic f
+(r) 3381 3610 w
+10 /Palatino-Roman f
+(,) 3428 3610 w
+10 /Palatino-Italic f
+(rr) 3485 3610 w
+10 /Palatino-Roman f
+(,) 3571 3610 w
+(etc.) 3628 3610 w
+(are) 3835 3610 w
+(hexadecimal) 4005 3610 w
+(values) 4594 3610 w
+(for) 4912 3610 w
+(the corresponding colour components.) 720 3730 w
+(A) 720 3893 w
+10 /Palatino-Italic f
+(font) 887 3893 w
+10 /Palatino-Roman f
+(parameter) 1145 3893 w
+(gives) 1691 3893 w
+(the) 2012 3893 w
+(full) 2241 3893 w
+(path) 2482 3893 w
+(name) 2773 3893 w
+(of) 3107 3893 w
+(an) 3285 3893 w
+(Inferno) 3483 3893 w
+(font) 3899 3893 w
+(file;) 4168 3893 w
+(for) 4422 3893 w
+(example,) 4640 3893 w
+10 /Courier f
+(/fonts/pelm/unicode.9.font) 720 4013 w
+10 /Palatino-Roman f
+(.) 2280 4013 w
+(A) 720 4176 w
+10 /Palatino-Italic f
+(bitmap) 839 4176 w
+10 /Palatino-Roman f
+(parameter) 1167 4176 w
+(is) 1665 4176 w
+(not) 1778 4176 w
+(used) 1966 4176 w
+(by) 2219 4176 w
+(any) 2372 4176 w
+(of) 2578 4176 w
+(the) 2708 4176 w
+(generic) 2889 4176 w
+(options,) 3254 4176 w
+(but) 3653 4176 w
+(is) 3843 4176 w
+(worth) 3956 4176 w
+(mentioning) 4267 4176 w
+(here.) 4821 4176 w
+(Unlike) 720 4296 w
+(Tk) 1050 4296 w
+(4.0,) 1199 4296 w
+(a) 1381 4296 w
+10 /Palatino-Italic f
+(bitmap) 1463 4296 w
+10 /Palatino-Roman f
+(in) 1782 4296 w
+(Limbo/Tk) 1901 4296 w
+(is) 2399 4296 w
+(not) 2502 4296 w
+(restricted) 2680 4296 w
+(to) 3130 4296 w
+(a) 3250 4296 w
+(1\255bit) 3332 4296 w
+(deep) 3564 4296 w
+(bitmap) 3813 4296 w
+(to) 4160 4296 w
+(be) 4280 4296 w
+(coloured) 4414 4296 w
+(with) 4837 4296 w
+(foreground) 720 4416 w
+(and) 1265 4416 w
+(background.) 1473 4416 w
+(Instead,) 2097 4416 w
+(it) 2487 4416 w
+(can) 2588 4416 w
+(be) 2779 4416 w
+(a) 2921 4416 w
+(full\255colour) 3010 4416 w
+(image) 3516 4416 w
+(\(`pixmap') 3826 4416 w
+(in) 4293 4416 w
+(X11) 4420 4416 w
+(terminol\255) 4627 4416 w
+(ogy\),) 720 4536 w
+(which) 975 4536 w
+(is) 1277 4536 w
+(displayed) 1378 4536 w
+(as) 1844 4536 w
+(is.) 1966 4536 w
+(If) 2092 4536 w
+10 /Palatino-Italic f
+(bitmap) 2189 4536 w
+10 /Palatino-Roman f
+(begins) 2506 4536 w
+(with) 2823 4536 w
+(a) 3055 4536 w
+(`) 3134 4536 w
+10 /Courier f
+(@) 3162 4536 w
+10 /Palatino-Roman f
+(',) 3222 4536 w
+(the) 3304 4536 w
+(remaining) 3472 4536 w
+(characters) 3957 4536 w
+(should) 4435 4536 w
+(be) 4769 4536 w
+(the) 4901 4536 w
+(path) 720 4656 w
+(name) 950 4656 w
+(of) 1223 4656 w
+(an) 1340 4656 w
+(Inferno) 1477 4656 w
+(image) 1832 4656 w
+(file.) 2132 4656 w
+(If) 2325 4656 w
+10 /Palatino-Italic f
+(bitmap) 2421 4656 w
+10 /Palatino-Roman f
+(begins) 2738 4656 w
+(with) 3056 4656 w
+(the) 3289 4656 w
+(character) 3458 4656 w
+(`) 3895 4656 w
+10 /Courier f
+(<) 3923 4656 w
+10 /Palatino-Roman f
+(',) 3983 4656 w
+(the) 4066 4656 w
+(remaining) 4235 4656 w
+(charac\255) 4721 4656 w
+(ters) 720 4776 w
+(must) 912 4776 w
+(be) 1164 4776 w
+(a) 1296 4776 w
+(decimal) 1375 4776 w
+(integer) 1753 4776 w
+(giving) 2094 4776 w
+(a) 2408 4776 w
+(file) 2487 4776 w
+(descriptor) 2654 4776 w
+(number) 3134 4776 w
+(of) 3511 4776 w
+(an) 3627 4776 w
+(open) 3763 4776 w
+(file) 4012 4776 w
+(from) 4179 4776 w
+(which) 4423 4776 w
+(the) 4723 4776 w
+(bit\255) 4890 4776 w
+(map) 720 4896 w
+(can) 964 4896 w
+(be) 1163 4896 w
+(loaded.) 1313 4896 w
+(Otherwise,) 1689 4896 w
+10 /Palatino-Italic f
+(bitmap) 2221 4896 w
+10 /Palatino-Roman f
+(should) 2555 4896 w
+(be) 2907 4896 w
+(the) 3057 4896 w
+(name) 3243 4896 w
+(of) 3534 4896 w
+(a) 3669 4896 w
+(bitmap) 3766 4896 w
+(file) 4128 4896 w
+(in) 4314 4896 w
+(the) 4448 4896 w
+(directory) 4634 4896 w
+10 /Courier f
+(/icons/tk) 720 5016 w
+10 /Palatino-Roman f
+(.) 1260 5016 w
+10 /Palatino-Bold f
+(Options not supported in Limbo/Tk) 720 5279 w
+10 /Palatino-Roman f
+(The following options provided by Tk 4.0 are not supported by any Limbo/Tk widget:) 720 5442 w
+9 /Courier f
+(\255cursor) 864 5613 w
+(\255insertofftime) 2214 5613 w
+(\255wraplength) 3348 5613 w
+(\255disabledforeground) 864 5713 w
+(\255insertontime) 2214 5713 w
+(\255exportselection) 864 5813 w
+(\255insertwidth) 2214 5813 w
+(\255geometry) 864 5913 w
+(\255repeatdelay) 2214 5913 w
+(\255highlightbackground) 864 6013 w
+(\255repeatinterval) 2214 6013 w
+(\255highlightcolor) 864 6113 w
+(\255setgrid) 2214 6113 w
+(\255highlightthickness) 864 6213 w
+(\255takefocus) 2214 6213 w
+(\255insertbackground) 864 6313 w
+(\255textvariable) 2214 6313 w
+(\255insertborderwidth) 864 6413 w
+(\255troughcolor) 2214 6413 w
+10 /Palatino-Bold f
+(6.) 720 6676 w
+(Limbo/Tk commands) 845 6676 w
+10 /Palatino-Roman f
+(This) 720 6839 w
+(section) 943 6839 w
+(lists) 1285 6839 w
+(all) 1493 6839 w
+(the) 1634 6839 w
+(commands) 1806 6839 w
+(documented) 2325 6839 w
+(in) 2915 6839 w
+(the) 3036 6839 w
+(Tk) 3209 6839 w
+(4.0) 3360 6839 w
+(man) 3519 6839 w
+(pages,) 3749 6839 w
+(giving) 4064 6839 w
+(the) 4383 6839 w
+(differences) 4556 6839 w
+(between) 720 6959 w
+(the) 1156 6959 w
+(behaviour) 1358 6959 w
+(specified) 1873 6959 w
+(in) 2330 6959 w
+(those) 2480 6959 w
+(man) 2779 6959 w
+(pages) 3037 6959 w
+(and) 3355 6959 w
+(the) 3586 6959 w
+(behaviour) 3787 6959 w
+(implemented) 4301 6959 w
+(in) 4953 6959 w
+(Limbo/Tk.) 720 7079 w
+(Some) 1280 7079 w
+(common) 1568 7079 w
+(Tcl) 2000 7079 w
+(commands) 2178 7079 w
+(are) 2708 7079 w
+(listed) 2891 7079 w
+(as) 3178 7079 w
+(well.) 3315 7079 w
+(Bear) 3599 7079 w
+(in) 3843 7079 w
+(mind) 3975 7079 w
+(that) 4256 7079 w
+(some) 4475 7079 w
+(Tk) 4753 7079 w
+(4.0) 4915 7079 w
+(options are unsupported, as noted above.) 720 7199 w
+cleartomark
+showpage
+saveobj restore
+%%EndPage: 9 9
+%%Page: 10 10
+/saveobj save def
+mark
+10 pagesetup
+10 /Palatino-Roman f
+(\255 10 \255) 2772 480 w
+10 /Courier f
+(bell) 720 840 w
+10 /Palatino-Roman f
+([) 985 840 w
+10 /Courier f
+(\255displayof) 1018 840 w
+10 /Palatino-Italic f
+(window) 1678 840 w
+10 /Palatino-Roman f
+(]) 2000 840 w
+(Not implemented.) 1080 960 w
+10 /Courier f
+(bind) 720 1117 w
+10 /Palatino-Italic f
+(widget) 985 1117 w
+10 /Palatino-Roman f
+10 /S f
+(<) 1282 1117 w
+10 /Palatino-Italic f
+(event\255event\255...\255event) 1337 1117 w
+10 /S f
+(>) 2162 1117 w
+10 /Palatino-Italic f
+(command) 2242 1117 w
+10 /Courier f
+(bind) 720 1237 w
+10 /Palatino-Italic f
+(widget) 985 1237 w
+10 /Palatino-Roman f
+10 /S f
+(<) 1282 1237 w
+10 /Palatino-Italic f
+(event\255event\255...\255event) 1337 1237 w
+10 /S f
+(>) 2162 1237 w
+10 /Palatino-Roman f
+(+) 2242 1237 w
+10 /Palatino-Italic f
+(command) 2328 1237 w
+10 /Palatino-Roman f
+(The) 1080 1357 w
+(bind) 1282 1357 w
+(command) 1520 1357 w
+(is) 2000 1357 w
+(perhaps) 2107 1357 w
+(the) 2501 1357 w
+(command) 2676 1357 w
+(that) 3156 1357 w
+(differs) 3366 1357 w
+(most) 3688 1357 w
+(from) 3942 1357 w
+(Tk) 4194 1357 w
+(4.0.) 4347 1357 w
+(In) 4558 1357 w
+(general,) 4686 1357 w
+(only) 1080 1477 w
+(a) 1315 1477 w
+(subset) 1402 1477 w
+(of) 1719 1477 w
+(its) 1844 1477 w
+(functionality) 1985 1477 w
+(is) 2588 1477 w
+(implemented.) 2695 1477 w
+(One) 3346 1477 w
+(difference) 3567 1477 w
+(is) 4045 1477 w
+(that) 4152 1477 w
+10 /Palatino-Italic f
+(widget) 4362 1477 w
+10 /Palatino-Roman f
+(must) 4678 1477 w
+(be) 4937 1477 w
+(the) 1080 1597 w
+(name) 1261 1597 w
+(of) 1547 1597 w
+(an) 1677 1597 w
+(existing) 1827 1597 w
+(widget.) 2216 1597 w
+(The) 2618 1597 w
+(notion) 2827 1597 w
+(of) 3157 1597 w
+(a) 3287 1597 w
+(widget) 3379 1597 w
+(class) 3731 1597 w
+(is) 3980 1597 w
+(completely) 4093 1597 w
+(absent) 4625 1597 w
+(in) 4953 1597 w
+(Limbo/Tk.) 1080 1717 w
+(Event) 1625 1717 w
+(sequence) 1911 1717 w
+(specifications) 2344 1717 w
+(are) 2969 1717 w
+(also) 3135 1717 w
+(more) 3339 1717 w
+(restricted.) 3598 1717 w
+(A) 4069 1717 w
+(sequence) 4175 1717 w
+(is) 4607 1717 w
+(either) 4706 1717 w
+(a) 4990 1717 w
+(single) 1080 1837 w
+(character) 1370 1837 w
+(\(rune\),) 1805 1837 w
+(meaning) 2130 1837 w
+(a) 2545 1837 w
+10 /Courier f
+(KeyPress) 2623 1837 w
+10 /Palatino-Roman f
+(of) 3131 1837 w
+(that) 3247 1837 w
+(character,) 3449 1837 w
+(or) 3909 1837 w
+(a) 4032 1837 w
+(sequence) 4110 1837 w
+(of) 4543 1837 w
+10 /Palatino-Italic f
+(events) 4660 1837 w
+10 /Palatino-Roman f
+(in) 4953 1837 w
+(angle) 1080 1957 w
+(brackets.) 1347 1957 w
+10 /Palatino-Italic f
+(Events) 1791 1957 w
+10 /Palatino-Roman f
+(are) 2103 1957 w
+(separated) 2267 1957 w
+(by) 2725 1957 w
+(blanks) 2862 1957 w
+(or) 3178 1957 w
+(minus) 3299 1957 w
+(signs.) 3602 1957 w
+(See) 3904 1957 w
+10 /Palatino-Italic f
+(bind) 4078 1957 w
+10 /Palatino-Roman f
+(\(9\) for a complete) 4266 1957 w
+(discussion.) 1080 2077 w
+10 /Courier f
+(bindtags) 720 2234 w
+10 /Palatino-Italic f
+(window) 1225 2234 w
+10 /Palatino-Roman f
+([) 1572 2234 w
+10 /Palatino-Italic f
+(taglist) 1605 2234 w
+10 /Palatino-Roman f
+(]) 1860 2234 w
+(Not implemented.) 1080 2354 w
+10 /Courier f
+(button) 720 2511 w
+10 /Palatino-Italic f
+(pathname) 1105 2511 w
+10 /Palatino-Roman f
+([) 1524 2511 w
+10 /Palatino-Italic f
+(options ...) 1557 2511 w
+10 /Palatino-Roman f
+(]) 1951 2511 w
+(As in Tk 4.0 \(but note difference in units for) 1080 2631 w
+10 /Courier f
+(\255height) 3033 2631 w
+10 /Palatino-Roman f
+(and) 3478 2631 w
+10 /Courier f
+(\255width) 3672 2631 w
+10 /Palatino-Roman f
+(\).) 4032 2631 w
+10 /Courier f
+(canvas) 720 2788 w
+10 /Palatino-Italic f
+(pathname) 1105 2788 w
+10 /Palatino-Roman f
+([) 1524 2788 w
+10 /Palatino-Italic f
+(options ...) 1557 2788 w
+10 /Palatino-Roman f
+(]) 1951 2788 w
+(The Postscript subcommand is not implemented.) 1080 2908 w
+10 /Courier f
+(checkbutton) 720 3065 w
+10 /Palatino-Italic f
+(pathname) 1405 3065 w
+10 /Palatino-Roman f
+([) 1824 3065 w
+10 /Palatino-Italic f
+(options ...) 1857 3065 w
+10 /Palatino-Roman f
+(]) 2251 3065 w
+(Unimplemented) 1080 3185 w
+(options:) 1984 3185 w
+10 /Courier f
+(\255indicatoron) 2519 3185 w
+10 /Palatino-Roman f
+(,) 3239 3185 w
+10 /Courier f
+(\255offvalue) 3443 3185 w
+10 /Palatino-Roman f
+(,) 3983 3185 w
+10 /Courier f
+(\255onvalue) 4187 3185 w
+10 /Palatino-Roman f
+(,) 4667 3185 w
+(and) 4871 3185 w
+10 /Courier f
+(\255selectimage) 1080 3305 w
+10 /Palatino-Roman f
+(.) 1800 3305 w
+(The) 1875 3305 w
+10 /Courier f
+(flash) 2067 3305 w
+10 /Palatino-Roman f
+(subcommand is not implemented.) 2392 3305 w
+10 /Courier f
+(clipboard) 720 3462 w
+10 /Palatino-Italic f
+(operation) 1285 3462 w
+10 /Palatino-Roman f
+(Not implemented.) 1080 3582 w
+10 /Palatino-Italic f
+(pathname) 720 3739 w
+10 /Courier f
+(configure [) 1174 3739 w
+10 /Palatino-Italic f
+(option ...) 1859 3739 w
+10 /Courier f
+(]) 2214 3739 w
+10 /Palatino-Roman f
+(Configure) 1080 3859 w
+(options) 1571 3859 w
+(for) 1944 3859 w
+(widget) 2114 3859 w
+10 /Palatino-Italic f
+(pathname) 2466 3859 w
+10 /Palatino-Roman f
+(.) 2868 3859 w
+(Widget\255specific;) 2960 3859 w
+(see) 3716 3859 w
+(the) 3896 3859 w
+(manual) 4077 3859 w
+(entry) 4454 3859 w
+(for) 4731 3859 w
+(the) 4901 3859 w
+(widget in section 9 of Volume 1.) 1080 3979 w
+10 /Courier f
+(destroy) 720 4136 w
+10 /Palatino-Roman f
+([) 1165 4136 w
+10 /Palatino-Italic f
+(window ...) 1198 4136 w
+10 /Palatino-Roman f
+(]) 1620 4136 w
+(As) 1080 4256 w
+(in) 1230 4256 w
+(Tk) 1347 4256 w
+(4.0,) 1494 4256 w
+(but) 1674 4256 w
+(note) 1852 4256 w
+(that) 2076 4256 w
+(`) 2280 4256 w
+10 /Courier f
+(destroy) 2308 4256 w
+(.) 2793 4256 w
+10 /Palatino-Roman f
+(') 2853 4256 w
+(is) 2911 4256 w
+(rarely) 3012 4256 w
+(needed) 3306 4256 w
+(because) 3661 4256 w
+(top) 4039 4256 w
+(level) 4218 4256 w
+(windows) 4460 4256 w
+(are) 4902 4256 w
+(automatically) 1080 4376 w
+(destroyed) 1718 4376 w
+(by) 2194 4376 w
+(the) 2337 4376 w
+(Inferno) 2508 4376 w
+(garbage) 2866 4376 w
+(collector) 3253 4376 w
+(immediately) 3662 4376 w
+(when) 4253 4376 w
+(the) 4531 4376 w
+(last) 4701 4376 w
+(ref\255) 4886 4376 w
+(erence vanishes.) 1080 4496 w
+10 /Courier f
+(entry) 720 4653 w
+10 /Palatino-Italic f
+(pathname) 1045 4653 w
+10 /Palatino-Roman f
+([) 1464 4653 w
+10 /Palatino-Italic f
+(options ...) 1497 4653 w
+10 /Palatino-Roman f
+(]) 1891 4653 w
+(The) 1080 4773 w
+10 /Courier f
+(scan) 1288 4773 w
+10 /Palatino-Roman f
+(subcommand) 1569 4773 w
+(is) 2211 4773 w
+(not) 2323 4773 w
+(implemented.) 2510 4773 w
+(Some) 3166 4773 w
+(key) 3451 4773 w
+(bindings) 3652 4773 w
+(are) 4082 4773 w
+(not) 4262 4773 w
+(implemented) 4450 4773 w
+(when) 1080 4893 w
+(there) 1358 4893 w
+(is) 1616 4893 w
+(currently) 1718 4893 w
+(no) 2157 4893 w
+(way) 2301 4893 w
+(to) 2521 4893 w
+(type) 2640 4893 w
+(those) 2868 4893 w
+(keys) 3135 4893 w
+(to) 3368 4893 w
+(Inferno) 3487 4893 w
+(\(for) 3844 4893 w
+(example,) 4036 4893 w
+10 /Courier f
+(Home) 4467 4893 w
+10 /Palatino-Roman f
+(\).) 4707 4893 w
+(Note) 4821 4893 w
+(difference in units for) 1080 5013 w
+10 /Courier f
+(\255height) 2059 5013 w
+10 /Palatino-Roman f
+(and) 2504 5013 w
+10 /Courier f
+(\255width) 2698 5013 w
+10 /Palatino-Roman f
+(.) 3058 5013 w
+10 /Courier f
+(event) 720 5170 w
+10 /Palatino-Italic f
+(operation) 1045 5170 w
+10 /Palatino-Roman f
+(Not) 1080 5290 w
+(implemented:) 1301 5290 w
+(normally) 1966 5290 w
+(replaced) 2421 5290 w
+(by) 2851 5290 w
+(Tk) 3012 5290 w
+10 /Courier f
+(send) 3180 5290 w
+10 /Palatino-Roman f
+(or) 3471 5290 w
+(Limbo) 3617 5290 w
+(channel) 3956 5290 w
+(send) 4352 5290 w
+(operation) 4612 5290 w
+(within the application.) 1080 5410 w
+10 /Courier f
+(focus) 720 5567 w
+10 /Palatino-Italic f
+(window) 1045 5567 w
+10 /Palatino-Roman f
+(The) 1080 5687 w
+(focus) 1288 5687 w
+(model) 1563 5687 w
+(in) 1885 5687 w
+(Inferno) 2013 5687 w
+(is) 2380 5687 w
+(different.) 2492 5687 w
+(Only) 2941 5687 w
+(one) 3204 5687 w
+(widget) 3406 5687 w
+(has) 3757 5687 w
+(the) 3948 5687 w
+(keyboard) 4128 5687 w
+(focus) 4590 5687 w
+(at) 4865 5687 w
+(a) 4990 5687 w
+(given) 1080 5807 w
+(time.) 1359 5807 w
+(Limbo/Tk) 1613 5807 w
+(does) 2110 5807 w
+(not) 2347 5807 w
+(maintain) 2524 5807 w
+(a) 2950 5807 w
+(private) 3031 5807 w
+(keyboard) 3379 5807 w
+(focus) 3830 5807 w
+(for) 4094 5807 w
+(each) 4252 5807 w
+(toplevel) 4482 5807 w
+(tree) 4871 5807 w
+(and) 1080 5927 w
+(automatically) 1284 5927 w
+(move) 1925 5927 w
+(the) 2208 5927 w
+(focus) 2382 5927 w
+(there) 2651 5927 w
+(whenever) 2913 5927 w
+(the) 3388 5927 w
+(tree) 3563 5927 w
+(is) 3768 5927 w
+(entered.) 3875 5927 w
+(\(Canvas) 4272 5927 w
+(and) 4669 5927 w
+(text) 4874 5927 w
+(widgets,) 1080 6047 w
+(however,) 1494 6047 w
+(do) 1945 6047 w
+(maintain) 2098 6047 w
+(a) 2530 6047 w
+(private) 2616 6047 w
+(keyboard) 2969 6047 w
+(focus.\)) 3426 6047 w
+(The) 3779 6047 w
+(Limbo/Tk) 3982 6047 w
+10 /Courier f
+(focus) 4484 6047 w
+10 /Palatino-Roman f
+(com\255) 4820 6047 w
+(mand) 1080 6167 w
+(moves) 1372 6167 w
+(the) 1697 6167 w
+(keyboard) 1871 6167 w
+(focus) 2327 6167 w
+(to) 2596 6167 w
+(the) 2719 6167 w
+(given) 2893 6167 w
+10 /Palatino-Italic f
+(window) 3177 6167 w
+10 /Palatino-Roman f
+(.) 3507 6167 w
+(By) 3593 6167 w
+(default,) 3746 6167 w
+(the) 4121 6167 w
+(first) 4296 6167 w
+(press) 4509 6167 w
+(of) 4777 6167 w
+(the) 4901 6167 w
+(primary) 1080 6287 w
+(button) 1475 6287 w
+(in) 1801 6287 w
+(an) 1920 6287 w
+10 /Courier f
+(entry) 2060 6287 w
+10 /Palatino-Roman f
+(,) 2360 6287 w
+10 /Courier f
+(listbox) 2417 6287 w
+10 /Palatino-Roman f
+(or) 2869 6287 w
+10 /Courier f
+(text) 2995 6287 w
+10 /Palatino-Roman f
+(widget) 3266 6287 w
+(causes) 3607 6287 w
+(the) 3924 6287 w
+(focus) 4094 6287 w
+(to) 4359 6287 w
+(be) 4478 6287 w
+(moved) 4612 6287 w
+(to) 4952 6287 w
+(that) 1080 6407 w
+(widget.) 1287 6407 w
+(Just) 1655 6407 w
+(entering) 1856 6407 w
+(a) 2259 6407 w
+(menu) 2342 6407 w
+(widget) 2629 6407 w
+(gives) 2972 6407 w
+(it) 3237 6407 w
+(the) 3332 6407 w
+(focus.) 3504 6407 w
+(The) 3821 6407 w
+10 /Courier f
+(\255displayof) 4021 6407 w
+10 /Palatino-Roman f
+(,) 4621 6407 w
+10 /Courier f
+(\255force) 4680 6407 w
+10 /Palatino-Roman f
+(and) 1080 6527 w
+10 /Courier f
+(\255lastfor) 1274 6527 w
+10 /Palatino-Roman f
+(options are not implemented.) 1779 6527 w
+10 /Courier f
+(frame) 720 6684 w
+10 /Palatino-Italic f
+(pathname) 1045 6684 w
+10 /Palatino-Roman f
+([) 1464 6684 w
+10 /Palatino-Italic f
+(options ...) 1497 6684 w
+10 /Palatino-Roman f
+(]) 1891 6684 w
+(Unimplemented options:) 1080 6804 w
+10 /Courier f
+(class) 2213 6804 w
+10 /Palatino-Roman f
+(,) 2513 6804 w
+10 /Courier f
+(colormap) 2563 6804 w
+10 /Palatino-Roman f
+(, and) 3043 6804 w
+10 /Courier f
+(visual) 3287 6804 w
+10 /Palatino-Roman f
+(.) 3647 6804 w
+10 /Courier f
+(grab) 720 6961 w
+10 /Palatino-Italic f
+(window) 985 6961 w
+10 /Courier f
+(grab) 720 7081 w
+10 /Palatino-Italic f
+(option) 985 7081 w
+10 /Palatino-Roman f
+([) 1265 7081 w
+10 /Palatino-Italic f
+(arg ...) 1298 7081 w
+10 /Palatino-Roman f
+(]) 1531 7081 w
+(Limbo/Tk) 1080 7201 w
+(implements) 1578 7201 w
+(only) 2134 7201 w
+(global) 2365 7201 w
+(grabs,) 2672 7201 w
+(so) 2973 7201 w
+(the) 3103 7201 w
+10 /Courier f
+(\255global) 3275 7201 w
+10 /Palatino-Roman f
+(option) 3728 7201 w
+(is) 4051 7201 w
+(not) 4155 7201 w
+(recognised.) 4334 7201 w
+(The) 4873 7201 w
+cleartomark
+showpage
+saveobj restore
+%%EndPage: 10 10
+%%Page: 11 11
+/saveobj save def
+mark
+11 pagesetup
+10 /Palatino-Roman f
+(\255 11 \255) 2772 480 w
+10 /Courier f
+(grab) 1080 840 w
+(current) 1384 840 w
+10 /Palatino-Roman f
+(command) 1833 840 w
+(is) 2306 840 w
+(not) 2406 840 w
+(implemented.) 2581 840 w
+(The) 3225 840 w
+10 /Courier f
+(grab) 3421 840 w
+10 /Palatino-Roman f
+(command) 3690 840 w
+(is) 4163 840 w
+(not) 4263 840 w
+(recognised) 4438 840 w
+(as) 4948 840 w
+(a synonym for) 1080 960 w
+10 /Courier f
+(grab set) 1746 960 w
+10 /Palatino-Roman f
+(.) 2226 960 w
+10 /Courier f
+(grid) 720 1117 w
+10 /Palatino-Italic f
+(operation) 985 1117 w
+10 /Palatino-Roman f
+([) 1387 1117 w
+10 /Palatino-Italic f
+(arg ...) 1420 1117 w
+10 /Palatino-Roman f
+(]) 1653 1117 w
+(Not implemented.) 1080 1237 w
+10 /Courier f
+(image create bitmap) 720 1394 w
+10 /Palatino-Roman f
+([) 1885 1394 w
+10 /Palatino-Italic f
+(name) 1918 1394 w
+10 /Palatino-Roman f
+(] [) 2135 1394 w
+10 /Palatino-Italic f
+(options) 2226 1394 w
+10 /Palatino-Roman f
+(]) 2520 1394 w
+10 /Courier f
+(image) 720 1514 w
+10 /Palatino-Italic f
+(option) 1045 1514 w
+10 /Palatino-Roman f
+([) 1325 1514 w
+10 /Palatino-Italic f
+(arg arg ...) 1358 1514 w
+10 /Palatino-Roman f
+(]) 1749 1514 w
+(Only) 1080 1634 w
+(bitmap) 1334 1634 w
+(image) 1681 1634 w
+(types) 1985 1634 w
+(are) 2257 1634 w
+(implemented,) 2428 1634 w
+(but,) 3076 1634 w
+(as) 3282 1634 w
+(documented) 3407 1634 w
+(under) 3996 1634 w
+10 /Courier f
+(bitmap) 4296 1634 w
+10 /Palatino-Roman f
+(,) 4656 1634 w
+(Inferno) 4714 1634 w
+(`bitmaps') 1080 1754 w
+(are) 1542 1754 w
+(not) 1729 1754 w
+(just) 1924 1754 w
+(1\255bit) 2131 1754 w
+(deep;) 2380 1754 w
+(they) 2671 1754 w
+(encompass) 2915 1754 w
+(both) 3451 1754 w
+(bitmaps) 3701 1754 w
+(and) 4107 1754 w
+(`photo') 4325 1754 w
+(\(colour\)) 4691 1754 w
+(images) 1080 1874 w
+(as) 1420 1874 w
+(provided) 1539 1874 w
+(by) 1977 1874 w
+(Tk/4.0.) 2115 1874 w
+(Limbo/Tk) 2495 1874 w
+(does) 2988 1874 w
+(not,) 3222 1874 w
+(however,) 3421 1874 w
+(recognise) 3863 1874 w
+(the) 4311 1874 w
+(wide) 4478 1874 w
+(variety) 4727 1874 w
+(of) 1080 1994 w
+(graphics) 1208 1994 w
+(formats) 1627 1994 w
+(that) 2008 1994 w
+(Tk) 2221 1994 w
+(4.0) 2377 1994 w
+(does.) 2541 1994 w
+(Instead,) 2836 1994 w
+(only) 3226 1994 w
+(Inferno's) 3463 1994 w
+(own) 3898 1994 w
+(format) 4133 1994 w
+(is) 4471 1994 w
+(supported) 4581 1994 w
+(internally,) 1080 2114 w
+(and) 1573 2114 w
+(external) 1780 2114 w
+(programs) 2176 2114 w
+(are) 2645 2114 w
+(provided) 2822 2114 w
+(to) 3272 2114 w
+(convert) 3399 2114 w
+(between) 3773 2114 w
+(that) 4185 2114 w
+(and) 4398 2114 w
+(other) 4606 2114 w
+(for\255) 4879 2114 w
+(mats) 1080 2234 w
+(such) 1328 2234 w
+(as) 1567 2234 w
+(JPEG.) 1694 2234 w
+(The) 2009 2234 w
+(file) 2211 2234 w
+(descriptor) 2385 2234 w
+(syntax) 2872 2234 w
+(for) 3198 2234 w
+(specifying) 3360 2234 w
+(bitmaps) 3849 2234 w
+(is) 4240 2234 w
+(useful) 4345 2234 w
+(when) 4651 2234 w
+(an) 4932 2234 w
+(external) 1080 2354 w
+(program) 1465 2354 w
+(writes) 1881 2354 w
+(the) 2183 2354 w
+(bitmap) 2349 2354 w
+(to) 2691 2354 w
+(a) 2806 2354 w
+(file) 2883 2354 w
+(descriptor.) 3049 2354 w
+(If) 3578 2354 w
+(a) 3672 2354 w
+(maskfile) 3749 2354 w
+(is) 4152 2354 w
+(given,) 4251 2354 w
+(it) 4552 2354 w
+(may) 4642 2354 w
+(also) 4864 2354 w
+(have) 1080 2474 w
+(a) 1320 2474 w
+(depth) 1397 2474 w
+(greater) 1684 2474 w
+(than) 2026 2474 w
+(1) 2252 2474 w
+(bit;) 2329 2474 w
+(the) 2498 2474 w
+(meaning) 2664 2474 w
+(is) 3077 2474 w
+(that) 3174 2474 w
+(if) 3374 2474 w
+(a) 3462 2474 w
+(pixel) 3538 2474 w
+(of) 3782 2474 w
+(the) 3896 2474 w
+(mask) 4061 2474 w
+(is) 4323 2474 w
+(non\255zero) 4420 2474 w
+(then) 4843 2474 w
+(the) 1080 2594 w
+(corresponding) 1247 2594 w
+(pixel) 1921 2594 w
+(of) 2167 2594 w
+(the) 2283 2594 w
+(image) 2450 2594 w
+(should) 2750 2594 w
+(be) 3084 2594 w
+(drawn.) 3216 2594 w
+(\(But) 3587 2594 w
+(see) 3803 2594 w
+(the) 3970 2594 w
+(handling) 4138 2594 w
+(of) 4566 2594 w
+(bitmaps) 4683 2594 w
+(used as stipples in) 1080 2714 w
+10 /Palatino-Italic f
+(canvas) 1913 2714 w
+10 /Palatino-Roman f
+(\(9\).\)) 2195 2714 w
+(The) 2419 2714 w
+10 /Courier f
+(\255data) 2611 2714 w
+10 /Palatino-Roman f
+(and) 2936 2714 w
+10 /Courier f
+(\255maskdata) 3130 2714 w
+10 /Palatino-Roman f
+(options are not implemented.) 3695 2714 w
+10 /Courier f
+(label) 720 2871 w
+10 /Palatino-Italic f
+(pathname) 1045 2871 w
+10 /Palatino-Roman f
+([) 1464 2871 w
+10 /Palatino-Italic f
+(options ...) 1497 2871 w
+10 /Palatino-Roman f
+(]) 1891 2871 w
+(Unimplemented) 1080 2991 w
+(options:) 1852 2991 w
+10 /Courier f
+(\255justify) 2255 2991 w
+10 /Palatino-Roman f
+(and) 2781 2991 w
+10 /Courier f
+(\255wraplength) 2997 2991 w
+10 /Palatino-Roman f
+(.) 3657 2991 w
+(Note) 3754 2991 w
+(difference) 4020 2991 w
+(in) 4509 2991 w
+(units) 4643 2991 w
+(for) 4912 2991 w
+10 /Courier f
+(\255height) 1080 3111 w
+10 /Palatino-Roman f
+(and) 1525 3111 w
+10 /Courier f
+(\255width) 1719 3111 w
+10 /Palatino-Roman f
+(.) 2079 3111 w
+10 /Courier f
+(listbox) 720 3268 w
+10 /Palatino-Italic f
+(pathname) 1165 3268 w
+10 /Palatino-Roman f
+([) 1584 3268 w
+10 /Palatino-Italic f
+(options ...) 1617 3268 w
+10 /Palatino-Roman f
+(]) 2011 3268 w
+(The) 1080 3388 w
+10 /Courier f
+(bbox) 1289 3388 w
+10 /Palatino-Roman f
+(and) 1571 3388 w
+10 /Courier f
+(scan) 1782 3388 w
+10 /Palatino-Roman f
+(subcommands) 2064 3388 w
+(are) 2749 3388 w
+(not) 2929 3388 w
+(implemented.) 3117 3388 w
+(Note) 3774 3388 w
+(difference) 4035 3388 w
+(in) 4519 3388 w
+(units) 4648 3388 w
+(for) 4912 3388 w
+10 /Courier f
+(\255height) 1080 3508 w
+10 /Palatino-Roman f
+(and) 1525 3508 w
+10 /Courier f
+(\255width) 1719 3508 w
+10 /Palatino-Roman f
+(.) 2079 3508 w
+10 /Courier f
+(lower) 720 3665 w
+10 /Palatino-Italic f
+(window) 1045 3665 w
+10 /Palatino-Roman f
+(The) 1080 3785 w
+10 /Courier f
+(belowThis) 1272 3785 w
+10 /Palatino-Roman f
+(optional parameter is not recognised.) 1837 3785 w
+10 /Courier f
+(menu) 720 3942 w
+10 /Palatino-Italic f
+(pathname) 985 3942 w
+10 /Palatino-Roman f
+([) 1404 3942 w
+10 /Palatino-Italic f
+(options ...) 1437 3942 w
+10 /Palatino-Roman f
+(]) 1831 3942 w
+(Unimplemented) 1080 4062 w
+(options:) 1890 4062 w
+10 /Courier f
+(\255postcommand) 2332 4062 w
+10 /Palatino-Roman f
+(,) 3052 4062 w
+10 /Courier f
+(\255tearoff) 3162 4062 w
+10 /Palatino-Roman f
+(,) 3642 4062 w
+10 /Courier f
+(\255tearoff) 3752 4062 w
+10 /Palatino-Roman f
+(command,) 4317 4062 w
+(and) 4871 4062 w
+10 /Courier f
+(\255transient) 1080 4182 w
+10 /Palatino-Roman f
+(.) 1680 4182 w
+(In) 1790 4182 w
+(the) 1942 4182 w
+10 /Courier f
+(add) 2141 4182 w
+10 /Palatino-Roman f
+(subcommand,) 2380 4182 w
+(the) 3065 4182 w
+10 /Courier f
+(\255accelerator) 3263 4182 w
+10 /Palatino-Roman f
+(,) 3983 4182 w
+10 /Courier f
+(\255indicatoron) 4067 4182 w
+10 /Palatino-Roman f
+(,) 4787 4182 w
+(and) 4871 4182 w
+10 /Courier f
+(\255selectimage) 1080 4302 w
+10 /Palatino-Roman f
+(options) 1827 4302 w
+(are) 2186 4302 w
+(not) 2351 4302 w
+(implemented.) 2524 4302 w
+(In) 3167 4302 w
+(the) 3287 4302 w
+10 /Courier f
+(index) 3454 4302 w
+10 /Palatino-Roman f
+(subcommand,) 3782 4302 w
+(the) 4436 4302 w
+10 /Courier f
+(last) 4603 4302 w
+10 /Palatino-Roman f
+(and) 4871 4302 w
+10 /Courier f
+(pattern) 1080 4422 w
+10 /Palatino-Roman f
+(index) 1535 4422 w
+(forms) 1818 4422 w
+(are) 2110 4422 w
+(not) 2282 4422 w
+(implemented.) 2462 4422 w
+(The) 3111 4422 w
+10 /Courier f
+(configure) 3312 4422 w
+10 /Palatino-Roman f
+(and) 3886 4422 w
+10 /Courier f
+(entrycget) 4089 4422 w
+10 /Palatino-Roman f
+(subcom\255) 4663 4422 w
+(mands are not implemented.) 1080 4542 w
+10 /Courier f
+(menubutton) 720 4699 w
+10 /Palatino-Italic f
+(pathname) 1345 4699 w
+10 /Palatino-Roman f
+([) 1764 4699 w
+10 /Palatino-Italic f
+(options ...) 1797 4699 w
+10 /Palatino-Roman f
+(]) 2191 4699 w
+(Unimplemented options:) 1080 4819 w
+10 /Courier f
+(\255indicatoron) 2213 4819 w
+10 /Palatino-Roman f
+(,) 2933 4819 w
+10 /Courier f
+(\255justify) 2983 4819 w
+10 /Palatino-Roman f
+(, and) 3463 4819 w
+10 /Courier f
+(\255wraplength) 3707 4819 w
+10 /Palatino-Roman f
+(.) 4367 4819 w
+10 /Courier f
+(message) 720 4976 w
+10 /Palatino-Italic f
+(pathname) 1165 4976 w
+10 /Palatino-Roman f
+([) 1584 4976 w
+10 /Palatino-Italic f
+(options ...) 1617 4976 w
+10 /Palatino-Roman f
+(]) 2011 4976 w
+(Not implemented \(subsumed by) 1080 5096 w
+10 /Courier f
+(label) 2541 5096 w
+10 /Palatino-Roman f
+(\).) 2841 5096 w
+10 /Courier f
+(option) 720 5253 w
+10 /Palatino-Italic f
+(operation) 1105 5253 w
+10 /Palatino-Roman f
+([) 1507 5253 w
+10 /Palatino-Italic f
+(arg ...) 1540 5253 w
+10 /Palatino-Roman f
+(]) 1773 5253 w
+(Not implemented. There is no option database.) 1080 5373 w
+10 /Courier f
+(pack) 720 5530 w
+10 /Palatino-Italic f
+(option arg ...) 985 5530 w
+10 /Courier f
+(pack) 720 5650 w
+10 /Palatino-Italic f
+(slave) 985 5650 w
+10 /Palatino-Roman f
+(...[) 1210 5650 w
+10 /Palatino-Italic f
+(options ...) 1318 5650 w
+10 /Palatino-Roman f
+(]) 1712 5650 w
+10 /Courier f
+(pack configure) 720 5770 w
+10 /Palatino-Italic f
+(slave) 1585 5770 w
+10 /Palatino-Roman f
+(... [) 1810 5770 w
+10 /Palatino-Italic f
+(options ...) 1943 5770 w
+10 /Palatino-Roman f
+(]) 2337 5770 w
+10 /Courier f
+(pack forget) 720 5890 w
+10 /Palatino-Italic f
+(slave) 1405 5890 w
+10 /Palatino-Roman f
+(...) 1630 5890 w
+10 /Courier f
+(pack propagate) 720 6010 w
+10 /Palatino-Italic f
+(master) 1585 6010 w
+10 /Palatino-Roman f
+([0 ) 1882 6010 w
+10 /S f
+(\357) 1990 6010 w
+10 /Palatino-Roman f
+(1]) 2064 6010 w
+10 /Courier f
+(pack slaves) 720 6130 w
+10 /Palatino-Italic f
+(master) 1405 6130 w
+10 /Palatino-Roman f
+(The) 1080 6250 w
+10 /Courier f
+(info) 1272 6250 w
+10 /Palatino-Roman f
+(subcommand is not implemented.) 1537 6250 w
+10 /Courier f
+(place) 720 6407 w
+10 /Palatino-Italic f
+(operation) 1045 6407 w
+10 /Palatino-Roman f
+([) 1447 6407 w
+10 /Palatino-Italic f
+(arg ...) 1480 6407 w
+10 /Palatino-Roman f
+(]) 1713 6407 w
+(Not implemented.) 1080 6527 w
+10 /Courier f
+(radiobutton) 720 6684 w
+10 /Palatino-Italic f
+(pathname) 1405 6684 w
+10 /Palatino-Roman f
+([) 1824 6684 w
+10 /Palatino-Italic f
+(options ...) 1857 6684 w
+10 /Palatino-Roman f
+(]) 2251 6684 w
+(Unimplemented) 1080 6804 w
+(options:) 1948 6804 w
+10 /Courier f
+(\255indicatoron) 2447 6804 w
+10 /Palatino-Roman f
+(,) 3167 6804 w
+10 /Courier f
+(\255justify) 3335 6804 w
+10 /Palatino-Roman f
+(,) 3815 6804 w
+10 /Courier f
+(\255selectimage) 3983 6804 w
+10 /Palatino-Roman f
+(,) 4703 6804 w
+(and) 4871 6804 w
+10 /Courier f
+(\255wraplength) 1080 6924 w
+10 /Palatino-Roman f
+(.) 1740 6924 w
+(The) 1815 6924 w
+10 /Courier f
+(flash) 2007 6924 w
+10 /Palatino-Roman f
+(subcommand is not implemented.) 2332 6924 w
+10 /Courier f
+(raise) 720 7081 w
+10 /Palatino-Italic f
+(window) 1045 7081 w
+10 /Palatino-Roman f
+(The) 1080 7201 w
+10 /Courier f
+(aboveThis) 1272 7201 w
+10 /Palatino-Roman f
+(optional parameter is not recognised.) 1837 7201 w
+cleartomark
+showpage
+saveobj restore
+%%EndPage: 11 11
+%%Page: 12 12
+/saveobj save def
+mark
+12 pagesetup
+10 /Palatino-Roman f
+(\255 12 \255) 2772 480 w
+10 /Courier f
+(scale) 720 840 w
+10 /Palatino-Italic f
+(pathname) 1045 840 w
+10 /Palatino-Roman f
+([) 1464 840 w
+10 /Palatino-Italic f
+(options ...) 1497 840 w
+10 /Palatino-Roman f
+(]) 1891 840 w
+(Unimplemented options:) 1080 960 w
+10 /Courier f
+(\255digits) 2213 960 w
+10 /Palatino-Roman f
+(and) 2718 960 w
+10 /Courier f
+(\255variable) 2912 960 w
+10 /Palatino-Roman f
+(.) 3452 960 w
+10 /Courier f
+(scrollbar) 720 1116 w
+10 /Palatino-Italic f
+(pathname) 1285 1116 w
+10 /Palatino-Roman f
+([) 1704 1116 w
+10 /Palatino-Italic f
+(options ...) 1737 1116 w
+10 /Palatino-Roman f
+(]) 2131 1116 w
+(The old syntax of) 1080 1236 w
+10 /Courier f
+(set) 1871 1236 w
+10 /Palatino-Roman f
+(and) 2076 1236 w
+10 /Courier f
+(get) 2270 1236 w
+10 /Palatino-Roman f
+(is not supported.) 2475 1236 w
+10 /Courier f
+(selection) 720 1392 w
+10 /Palatino-Roman f
+(Not implemented.) 1080 1512 w
+10 /Courier f
+(send) 720 1668 w
+10 /Palatino-Italic f
+(channame string) 985 1668 w
+10 /Palatino-Roman f
+(Rather) 1080 1788 w
+(than) 1414 1788 w
+(sending) 1651 1788 w
+(data) 2041 1788 w
+(to) 2274 1788 w
+(a) 2401 1788 w
+(different) 2490 1788 w
+(application,) 2912 1788 w
+(the) 3473 1788 w
+10 /Courier f
+(send) 3651 1788 w
+10 /Palatino-Roman f
+(command) 3930 1788 w
+(sends) 4413 1788 w
+(a) 4703 1788 w
+(given) 4792 1788 w
+10 /Palatino-Italic f
+(string) 1080 1908 w
+10 /Palatino-Roman f
+(down the Limbo channel associated with) 1358 1908 w
+10 /Palatino-Italic f
+(channame) 3194 1908 w
+10 /Palatino-Roman f
+(, as set by) 3610 1908 w
+10 /Courier f
+(namechan) 4061 1908 w
+10 /Palatino-Roman f
+(.) 4541 1908 w
+10 /Courier f
+(text) 720 2064 w
+10 /Palatino-Italic f
+(pathname) 985 2064 w
+10 /Palatino-Roman f
+([) 1404 2064 w
+10 /Palatino-Italic f
+(options ...) 1437 2064 w
+10 /Palatino-Roman f
+(]) 1831 2064 w
+(The) 1080 2184 w
+10 /Courier f
+(dump) 1273 2184 w
+10 /Palatino-Roman f
+(subcommand) 1539 2184 w
+(is) 2166 2184 w
+(not) 2263 2184 w
+(implemented.) 2435 2184 w
+(The) 3076 2184 w
+10 /Courier f
+(\255regexp) 3269 2184 w
+10 /Palatino-Roman f
+(mode) 3716 2184 w
+(of) 3995 2184 w
+(the) 4110 2184 w
+10 /Courier f
+(search) 4276 2184 w
+10 /Palatino-Roman f
+(subcom\255) 4663 2184 w
+(mand is not implemented.) 1080 2304 w
+10 /Courier f
+(tk) 720 2460 w
+10 /Palatino-Italic f
+(operation) 865 2460 w
+10 /Palatino-Roman f
+([) 1267 2460 w
+10 /Palatino-Italic f
+(arg ...) 1300 2460 w
+10 /Palatino-Roman f
+(]) 1533 2460 w
+(Not implemented.) 1080 2580 w
+10 /Courier f
+(tkerror) 720 2736 w
+10 /Palatino-Roman f
+(Not implemented.) 1080 2856 w
+10 /Courier f
+(tkwait) 720 3012 w
+10 /Palatino-Italic f
+(operation name) 1105 3012 w
+10 /Palatino-Roman f
+(Not implemented.) 1080 3132 w
+10 /Courier f
+(toplevel) 720 3288 w
+10 /Palatino-Italic f
+(pathname) 1225 3288 w
+10 /Palatino-Roman f
+([) 1644 3288 w
+10 /Palatino-Italic f
+(option value) 1677 3288 w
+10 /Palatino-Roman f
+(...]) 2174 3288 w
+(There) 1080 3408 w
+(is) 1370 3408 w
+(no) 1476 3408 w
+10 /Courier f
+(toplevel) 1624 3408 w
+10 /Palatino-Roman f
+(Tk) 2139 3408 w
+(command) 2291 3408 w
+(implemented) 2771 3408 w
+(by) 3397 3408 w
+(the) 3544 3408 w
+10 /Courier f
+(cmd) 3719 3408 w
+10 /Palatino-Roman f
+(function;) 3935 3408 w
+(instead,) 4366 3408 w
+(the) 4748 3408 w
+(Tk) 4923 3408 w
+(module) 1080 3528 w
+(entry) 1451 3528 w
+(point) 1715 3528 w
+10 /Courier f
+(toplevel) 1979 3528 w
+10 /Palatino-Roman f
+(is) 2488 3528 w
+(used) 2588 3528 w
+(to) 2828 3528 w
+(make) 2945 3528 w
+(toplevel) 3216 3528 w
+(widgets) 3604 3528 w
+(\(windows\)) 3985 3528 w
+(as) 4491 3528 w
+(described) 4612 3528 w
+(above.) 1080 3648 w
+10 /Courier f
+(update) 720 3804 w
+10 /Palatino-Roman f
+(In) 1080 3924 w
+(Tcl/Tk,) 1235 3924 w
+10 /Courier f
+(update) 1635 3924 w
+10 /Palatino-Roman f
+(is) 2058 3924 w
+(a) 2193 3924 w
+(Tcl) 2307 3924 w
+(command) 2505 3924 w
+(that) 3013 3924 w
+(invokes) 3251 3924 w
+(the) 3660 3924 w
+(`event) 3863 3924 w
+(handler) 4199 3924 w
+(loop'.) 4607 3924 w
+(In) 4948 3924 w
+(Limbo/Tk,) 1080 4044 w
+(it) 1599 4044 w
+(flushes) 1689 4044 w
+(any) 2029 4044 w
+(pending) 2221 4044 w
+(updates) 2619 4044 w
+(to) 3001 4044 w
+(the) 3117 4044 w
+(screen.) 3284 4044 w
+(The) 3642 4044 w
+(optional) 3837 4044 w
+10 /Courier f
+(idletasks) 4234 4044 w
+10 /Palatino-Roman f
+(argu\255) 4801 4044 w
+(ment is not recognised.) 1080 4164 w
+10 /Courier f
+(winfo) 720 4320 w
+10 /Palatino-Italic f
+(operation) 1045 4320 w
+10 /Palatino-Roman f
+([) 1447 4320 w
+10 /Palatino-Italic f
+(arg ...) 1480 4320 w
+10 /Palatino-Roman f
+(]) 1713 4320 w
+(Not) 1080 4440 w
+(implemented.) 1298 4440 w
+(Much) 1960 4440 w
+(of) 2264 4440 w
+(the) 2399 4440 w
+(information) 2585 4440 w
+(that) 3160 4440 w
+10 /Courier f
+(winfo) 3381 4440 w
+10 /Palatino-Roman f
+(would) 3728 4440 w
+(return) 4063 4440 w
+(can) 4389 4440 w
+(be) 4588 4440 w
+(got) 4738 4440 w
+(by) 4929 4440 w
+(applying) 1080 4560 w
+10 /Courier f
+(cget) 1503 4560 w
+10 /Palatino-Roman f
+(to each widget.) 1768 4560 w
+10 /Courier f
+(wm) 720 4716 w
+10 /Palatino-Italic f
+(operation window) 865 4716 w
+10 /Palatino-Roman f
+([) 1614 4716 w
+10 /Palatino-Italic f
+(arg ...) 1647 4716 w
+10 /Palatino-Roman f
+(]) 1880 4716 w
+(Not implemented.) 1080 4836 w
+10 /Palatino-Bold f
+(6.1.) 720 5076 w
+(References) 920 5076 w
+10 /Palatino-Roman f
+(1.) 720 5232 w
+(John) 970 5232 w
+(K) 1207 5232 w
+(Ousterhout,) 1313 5232 w
+10 /Palatino-Italic f
+(Tcl) 1879 5232 w
+(and) 2042 5232 w
+(the) 2225 5232 w
+(Tk) 2380 5232 w
+(Toolkit) 2518 5232 w
+10 /Palatino-Roman f
+(,) 2808 5232 w
+(Addison\255Wesley) 2866 5232 w
+(Publishing) 3639 5232 w
+(Company,) 4149 5232 w
+(Reading,) 4646 5232 w
+(Massachusetts, 1994.) 970 5352 w
+(2.) 720 5508 w
+(Paul Raines and Jeff Trantor,) 970 5508 w
+10 /Palatino-Italic f
+(Tcl/Tk in a Nutshell) 2266 5508 w
+10 /Palatino-Roman f
+(, O'Reilly, Sebastopol, California, 1999.) 3093 5508 w
+(3.) 720 5664 w
+(B W Kernighan, ``Descent into Limbo'', elsewhere in this volume.) 970 5664 w
+(4.) 720 5820 w
+(See) 970 5820 w
+10 /Palatino-Italic f
+(draw\255intro) 1144 5820 w
+10 /Palatino-Roman f
+(\(2\),) 1590 5820 w
+10 /Palatino-Italic f
+(tk) 1756 5820 w
+10 /Palatino-Roman f
+(\(2\) and) 1841 5820 w
+10 /Palatino-Italic f
+(wmlib) 2176 5820 w
+10 /Palatino-Roman f
+(\(2\) in) 2436 5820 w
+10 /Palatino-Italic f
+(The Inferno Programmer's Manual) 2689 5820 w
+10 /Palatino-Roman f
+(, Volume 1.) 4117 5820 w
+cleartomark
+showpage
+saveobj restore
+%%EndPage: 12 12
+%%Trailer
+done
+%%DocumentFonts: LucidaSansUnicode20 LucidaSansUnicode22 Courier S Palatino-Roman Palatino-Bold Palatino-Italic
+%%Pages: 12
--- /dev/null
+++ b/doc/lprof.ms
@@ -1,0 +1,514 @@
+.TL
+Limbo profilers in Inferno
+.AU
+J R Firth
+.AI
+Vita Nuova
+.br
+13 June 2002
+.SP 4
+.NH 1
+Introduction
+.LP
+Currently there are three application level profiling tools in the
+Inferno package.
+.I Prof
+is a time profiler which, by sampling, can provide statistics
+on the percentage of time spent on each line of limbo source.
+.I Cprof
+is a
+coverage profiler which provides the execution profile for limbo source
+code. It can accumulate results over a series of runs to allow full
+coverage testing. Finally,
+.I mprof
+is a memory profiler which provides
+statistics on the amount of memory used by each line
+of limbo source.
+.LP
+Two gui versions of these tools currently exist.
+.I Wm/cprof
+shows the
+coverage per module and highlights those lines which have not been
+executed or have been only partially executed.
+.I Wm/mprof
+shows the memory
+usage per module and highlights lines with high memory allocation in
+darker shades of red.
+.I Prof
+itself does not have a gui equivalent as it
+was originally written to determine why acme was so slow when using it's
+global editing command. A gui for it was not a requirement at that stage.
+.LP
+All these tools use a common library module
+.CW /module/profile.m
+and
+.CW /appl/lib/profile.b
+that acts as the direct interface with the kernel profiling device.
+.LP
+Note that none of these tools give kernel profile statistics. For that, the devmem driver should be used.
+.LP
+Although the use of these tools is very similar, there are a few differences
+when it comes to interactive testing as the profilers were written to
+answer different questions. Thus
+.I prof
+tries to determine 'why is blah so
+slow ?',
+.I cprof
+tries to accumulate coverage records over time and
+.I mprof
+tries to
+give a series of memory statistics at intervals during the execution of
+a program or series of programs.
+.NH 1
+Prof
+.LP
+The time profiler works by sampling. A kernel procedure sleeps for the
+given sample time and then notes the particular dis instruction currently
+being executed before repeating the process. After many such samples, an accurate profile can be obtained.
+.LP
+At it's simplest we can profile a particular command by giving the command
+to execute followed by any arguments to the command eg
+.sp
+.RS
+ prof wm/polyhedra
+.RE
+.sp
+profiles the polyhedra displayer. After letting the latter run for a reasonable
+amount of time, we exit and then get the following statistics.
+.br
+.DS
+Module: Wmlib(/dis/lib/wmlib.dis)
+
+34 0.06 str = load String String->PATH;
+
+**** module sampling points 1 ****
+
+.DE
+.DS
+Module: Bufio(/dis/lib/bufio.dis)
+
+340 0.06 n := 0;
+341 0.12 while(b.index < b.size){
+342 0.99 (ch, i, nil) = sys->byte2char(b.buffer[0:b.size], b.index);
+
+**** module sampling points 19 ****
+
+Module: Polyfill(/dis/math/polyfill.dis)
+
+37 10.80 for(i := 0; i < n; i++)
+38 19.86 b0[i] = b1[i] = ∞;
+57 0.06 p.y += y;
+58 1.18 dst.line((left, y), (right, y), Endsquare, Endsquare, 0, src, p);
+63 0.12 prevx := ∞;
+64 9.93 for(x := left; x <= right; x++){
+65 20.61 if(z+e < zbuf0[k] || (z-e <= zbuf1[k] && x != right && prevx != ∞)){
+66 6.46 zbuf0[k] = z-e;
+67 5.71 zbuf1[k] = z+e;
+68 0.74 if(prevx == ∞)
+69 0.74 prevx = x;
+71 0.12 else if(prevx != ∞){
+72 0.25 fillline(dst, prevx, x-1, y, src, p);
+73 2.61 prevx = ∞;
+75 4.35 z += dx;
+76 3.17 k++;
+78 0.06 if(prevx != ∞)
+79 0.87 fillline(dst, prevx, right, y, src, p);
+80 0.06 }
+152 0.06 return (vx/z, mod);
+186 0.06 sp.dzrem = mod(sp.num, sp.den) << fixshift;
+187 0.06 sp.dz += sdiv(sp.dzrem, sp.den);
+217 0.62 for(q = p = 0; p < ep; p++) {
+218 0.37 sp = seg[p];
+220 0.12 continue;
+221 0.12 sp.z += sp.dz;
+222 0.19 sp.zerr += sp.dzrem;
+223 0.12 if(sp.zerr >= sp.den) {
+224 0.19 sp.z++;
+225 0.25 sp.zerr -= sp.den;
+226 0.25 if(sp.zerr < 0 || sp.zerr >= sp.den)
+227 0.25 sys->print("bad ratzerr1: %d den %d dzrem %d\n", sp.zerr, sp.den, sp.dzrem);
+229 0.31 seg[q] = sp;
+230 0.31 q++;
+233 0.25 for(p = next; seg[p] != nil; p++) {
+234 0.06 sp = seg[p];
+247 0.12 ep = q;
+248 0.06 next = p;
+257 0.06 continue;
+260 0.62 zsort(seg, ep);
+262 0.25 for(p = 0; p < ep; p++) {
+263 0.19 sp = seg[p];
+264 0.06 cnt = 0;
+265 0.06 x = sp.z;
+266 0.25 ix = (x + onehalf) >> fixshift;
+267 0.06 if(ix >= maxx)
+271 0.06 cnt += sp.d;
+272 0.12 p++;
+273 0.25 sp = seg[p];
+275 0.06 if(p == ep) {
+277 0.06 return;
+279 0.06 cnt += sp.d;
+280 0.12 if((cnt&wind) == 0)
+283 0.19 sp = seg[p];
+286 0.25 ix2 = (x2 + onehalf) >> fixshift;
+291 1.92 filllinez(dst, ix, ix2, iy, zv+ix*dx, er, dx, k+ix-zr.min.x, zbuf0, zbuf1, src, spt);
+293 0.06 y += (1<<fixshift);
+294 0.31 iy++;
+295 0.06 k += xlen;
+296 0.06 zv += dy;
+298 0.06 }
+310 0.06 done = 1;
+311 0.12 q--;
+312 0.25 for(p = 0; p < q; p++) {
+313 0.87 if(seg[p].z > seg[p+1].z) {
+367 0.06 t = a[0]; a[0] = a[i]; a[i] = t;
+373 0.06 while(i < n && ycompare(a[i], a[0]) < 0);
+379 0.12 t = a[i]; a[i] = a[j]; a[j] = t;
+384 0.06 qsortycompare(a, j);
+
+**** module sampling points 1584 ****
+
+Module: Polyhedra(/dis/wm/polyhedra.dis)
+
+327 0.12 return (int (geo.sx*v.x)+geo.tx, int (geo.sy*v.y)+geo.ty);
+471 0.06 if(allf || dot(geo.view, newn[j]) < 0.0)
+472 0.06 polyfilla(fv[j], new, newn[j], dot(geo.light, newn[j]), geo, concave, inc);
+496 0.06 ap[j] = map(vtx, geo);
+512 0.06 if(a <= -LIMIT || a >= LIMIT)
+531 0.06 fillpoly(RDisp, ap, ~0, face, (0, 0), geo.zstate, dc, dx, dy);
+
+**** module sampling points 7 ****
+
+
+**** total sampling points 1611 ****
+.DE
+.br
+The output lists all lines in all modules with a sampling point. Each line
+shows the line number in the corresponding source file, the percentage of
+time spent on that line and the source code. We can see that about 60% of
+the sampling points occur on lines 37, 38, 64 and 65 of the Polyfill module.
+With this information we might then try to speed up this part of the code
+by altering the algorithm or making the limbo code more efficient (for
+instance by moving constant calculations or addressing out of loops).
+.LP
+The number of sampling points is also shown. The sampling rate can be
+increased with the -s option to give better granularity.
+This will cause a decrease in apparent performance but increases the
+accuracy of the results. The above example showed the results for all
+modules sampled. We might have restricted attention to the two main
+polyhedra modules instead by executing
+.sp
+.RS
+ prof -m Polyhedra -m Polyfill wm/polyhedra
+.RE
+.sp
+See the manual page for other options to
+.I prof
+and further examples.
+.NH1
+Cprof
+.LP
+Coverage of instructions is achieved by running a special dis instruction execute routine in place of the usual one (just as the debugger does).
+This routine notes down each
+instruction as it is executed. The profile device then passes this information
+to
+.I cprof
+via the io system.
+.LP
+The coverage profiler is used in a similar way to the time profiler.
+.sp
+.RS
+ cprof -m Zeros zeros 1024 2880
+.RE
+.sp
+gives
+.br
+.DS
+Module: Zeros(zeros.dis) 56% coverage
+
+1 implement Zeros;
+2
+3 include "sys.m";
+4 sys: Sys;
+5 include "arg.m";
+6 arg: Arg;
+7 include "string.m";
+8 str: String;
+9 include "keyring.m";
+10 include "security.m";
+11 random: Random;
+12
+13 include "draw.m";
+14
+15 Zeros: module
+16 {
+17 init: fn(nil: ref Draw->Context, argv: list of string);
+18 };
+19
+20 init(nil: ref Draw->Context, argv: list of string)
+21 {
+22 z: array of byte;
+23 i: int;
+24 + sys = load Sys Sys->PATH;
+25 + arg = load Arg Arg->PATH;
+26 + str = load String String->PATH;
+27
+28 + if(sys == nil || arg == nil)
+29 - return;
+30
+31 + bs := 0;
+32 + n := 0;
+33 + val := 0;
+34 + rflag := 0;
+35 + arg->init(argv);
+36 + while ((c := arg->opt()) != 0)
+37 - case c {
+38 - 'r' => rflag = 1;
+39 - 'v' => (val, nil) = str->toint(arg->arg(), 16);
+40 - * => sys->raise(sys->sprint("fail: unknown option (%c)\n", c));
+41 }
+.DE
+.DS
+42 + argv = arg->argv();
+43 + if(len argv >= 1)
+44 + bs = int hd argv;
+45 else
+46 - bs = 1;
+47 + if (len argv >= 2)
+48 + n = int hd tl argv;
+49 else
+50 - n = 1;
+51 + if(bs == 0 || n == 0) {
+52 - sys->fprint(sys->fildes(2), "usage: zeros [-r] [-v value] blocksize [number]\n");
+53 - sys->raise("fail: usage");
+54 }
+55 + if (rflag) {
+56 - random = load Random Random->PATH;
+57 - if (random == nil)
+58 - sys->raise("fail: no security module\n");
+59 - z = random->randombuf(random->NotQuiteRandom, bs);
+60 }
+61 else {
+62 + z = array[bs] of byte;
+63 + for(i=0;i<bs;i++)
+64 + z[i] = byte val;
+65 }
+66 + for(i=0;i<n;i++)
+67 + sys->write(sys->fildes(1), z, bs);
+68 + }
+
+**** module dis instructions 39725 ****
+.DE
+.br
+Here the -m option has restricted attention to the Zeros module itself.
+The output shows the source line number, an indicator of coverage and
+the source. The indicator is + if the line has been executed, - if
+it hasn't and ? if only part of it has (for instance a loop statement that has
+never had it's iteration part executed). Lines with no indicator have no
+corresponding dis instructions associated with them. Another option (-f)
+shows coverage frequencies instead.
+.LP
+An alternative to
+.I cprof
+is
+.I wm/cprof
+which shows the statistics graphically.
+It's options are pretty much the same as those to
+.I cprof .
+Unexecuted and
+partially executed lines of code are shown in colour. See the man page
+for exact details of the colouring convention
+.LP
+Results may be accumulated with the -r option so that multiple runs of
+code can be made. The resulting statistics go into a file <xxx>.prf when
+<xxx>.dis is the corresponding dis file. See the manual page for further
+details on how to use this option and then review the accumulated
+results.
+.NH 1
+Mprof
+.LP
+When memory profiling, the kernel profile device associates each heap allocation with a line of limbo source and each heap deallocation with the line of
+limbo source that allocated it. In this way, current memory usage and
+high-water usage can be determined on a line by line basis.
+.LP
+Here it seems that memory usage at a particular point in the execution of
+a program is more appropriate than the post-mortem approach of
+.I prof
+and
+.I cprof
+, so an interactive example is described (though
+.I mprof
+can be
+used non-interactively and
+.I prof
+interactively if so desired). See the manual
+pages for complete details and further examples.
+.LP
+To do this we execute
+.sp
+.RS
+ mprof -b -m Polyhedra
+.RE
+.sp
+which kicks off profiling and restricts attention to the Polyhedra module
+whenever it runs. The -b simply says begin profiling. Note that no command
+to execute is given to
+.I mprof
+at this stage. Then run the command
+.sp
+.RS
+ wm/polyhedra &
+.RE
+.sp
+and interact with it. Now show memory statistics
+.sp
+.RS
+ mprof
+.RE
+.sp
+This gives
+.br
+.DS
+Module: Polyhedra(/dis/wm/polyhedra.dis)
+
+44 100 100 sys = load Sys Sys->PATH;
+45 132 132 draw = load Draw Draw->PATH;
+46 68 68 tk = load Tk Tk->PATH;
+47 1788 1788 wmlib = load Wmlib Wmlib->PATH;
+48 232 232 bufio = load Bufio Bufio->PATH;
+49 68 68 math = load Math Math->PATH;
+50 204 204 rand = load Rand Rand->PATH;
+51 0 3504 daytime = load Daytime Daytime->PATH;
+52 544 544 polyfill = load Polyfill Polyfill->PATH;
+53 1824 1824 smenu = load Smenu Smenu->PATH;
+86 36 36 cmdch := chan of string;
+95 36 36 sync := chan of int;
+96 36 36 chanθ := chan of real;
+103 68 68 shade = array[NSHADES] of ref Image;
+116 36 36 yieldc := chan of int;
+120 36 36 sm := array[2] of ref Scrollmenu;
+378 68 176 s += " (" + string p.indx + ")";
+403 36 36 vec := array[2] of array of Vector;
+404 740 740 vec[0] = array[V] of Vector;
+405 740 740 vec[1] = array[V] of Vector;
+407 36 36 norm = array[2] of array of Vector;
+408 612 612 norm[0] = array[F] of Vector;
+409 612 612 norm[1] = array[F] of Vector;
+492 68 68 ap := array[n+1] of Point;
+609 164 164 geo := ref Geom;
+610 36 36 TM := array[4] of array of real;
+612 272 272 TM[i] = array[4] of real;
+663 8000 8000 p := ref Polyhedron;
+707 740 740 p.v = array[p.V] of Vector;
+710 612 612 p.f = array[p.F] of Vector;
+713 132 132 p.fv = array[p.F] of array of int;
+716 164 164 p.vf = array[p.V] of array of int;
+729 9504 9640 return s[0: len s - 1];
+750 3672 3672 a := array[n+2] of int;
+768 0 136 return (n, s[i+1:]);
+779 0 104 return (r, s[i+1:]);
+802 0 68 s = s[1:];
+806 0 72 s = s[0: ln-1];
+.DE
+.DS
+866 0 200 cmd(mainwin, ".f1.txt configure -text {" + s + "}");
+874 0 356 labs := array[n] of string;
+881 0 5128 labs[i++] = string q.indx + " " + name;
+884 0 68 cmd(top, mname + " configure -borderwidth 3");
+920 0 104 cmd(win, ". configure -height " + string (scrsize.y - bd * 2));
+934 0 244 cmd(win, ". configure -x " + string actr.min.x + " -y " + string actr.min.y);
+
+Module totals 31416 33984
+.DE
+.br
+We get the source line number, the amount of memory in bytes
+currently allocated on that line, the high-water mark in bytes and then the source. Thus
+loading the Sys module on line 44 used 100 bytes and this memory is
+still allocated. Loading Daytime on line 51 used 3504 bytes but this is now
+released (because the module pointer is set to nil in the source and the
+memory has been reclaimed). The string concatenation on line 378 currently uses 68 bytes
+but at it's worst it was 176 bytes.
+.LP
+Further interaction with wm/polyhedra can now be done and memory
+statistics reviewed before the
+profiling session is ended, throwing away the accumulated memory
+statistics inside the kernel with
+.sp
+.RS
+ mprof -c
+.RE
+.sp
+The -c option simply says cease profiling.
+.LP
+An alternative to
+.I mprof
+is
+.I wm/mprof
+which shows the statistics graphically.
+It's options are pretty much the same as those to
+.I mprof .
+Lines of code
+which have allocated more of the memory are shown in darker shades of red.
+.NH 1
+Manual pages
+.LP
+Further information and other examples are given in the following
+manual pages :-
+.sp
+.RS
+.I cprof(1)
+.br
+.I mprof(1)
+.br
+.I prof(1)
+.br
+.I wm-cprof(1)
+.br
+.I wm-mprof(1)
+.RE
+.sp
+For the lower level library module interface to these profilers
+.sp
+.RS
+.I prof(2)
+.RE
+.sp
+For the kernel profile device which gathers timing, coverage and memory
+statistics
+.sp
+.RS
+.I prof(3)
+.RE
+.br
+.NH 1
+Sources
+.LP
+The relevant sources are
+.sp
+.RS
+.CW /module/profile.m
+.br
+.CW /appl/lib/profile.b
+.br
+.CW /appl/cmd/cprof.b
+.br
+.CW /appl/cmd/mprof.b
+.br
+.CW /appl/cmd/prof.b
+.br
+.CW /appl/wm/cprof.b
+.br
+.CW /appl/wm/mprof.b
+.br
+.CW /emu/devprof.c
+.br
+.CW /os/port/devprof.c
+.RE
+.NH 1
+Addendum
+.LP
+A gui version of
+.I prof
+has been added for completeness. See the manual page
+.I wm-prof(1)
+and the source
+.CW /appl/wm/prof.b .
binary files /dev/null b/doc/lprof.pdf differ
--- /dev/null
+++ b/doc/mk.ms
@@ -1,0 +1,1539 @@
+.TL
+Maintaining Files on Plan 9 with Mk
+.AU
+Andrew G. Hume
+andrew@research.att.com
+Bob Flandrena
+bobf@plan9.bell-labs.com
+.AB
+.PP
+.CW Mk
+is a tool
+for describing and maintaining dependencies between
+files.
+It is similar to the
+UNIX program
+.CW make ,
+but provides several new capabilities.
+.CW Mk\fR'\fPs
+flexible rule specifications, implied
+dependency derivation, and parallel
+execution of maintenance actions are
+well-suited to the Plan 9 environment.
+Almost all Plan 9 maintenance procedures
+are automated using
+.CW mk .
+.AE
+.NH 1
+Introduction
+.PP
+.CW Mk
+performs the same task as
+.CW make
+[Feld79] but is different in many ways.
+This document describes
+.CW mk\fR'\fPs
+capabilities and discusses how they are
+used in Plan 9. There are occasional references
+to differences between
+.CW mk
+and
+.CW make ,
+but
+an appendix summarizes the details.
+.PP
+.CW Mk
+works well in the Plan 9 environment.
+It supports program construction
+in a heterogeneous environment and
+exploits the power of multiprocessors by executing
+maintenance actions in parallel.
+It interacts seamlessly with the Plan 9 command
+interpreter
+.CW rc
+and accepts pattern-based dependency specifications
+that are not limited to describing
+rules for program construction.
+The result is a tool that is flexible enough to
+perform many maintenance tasks including
+database maintenance,
+hardware design, and document production.
+.PP
+This document begins by discussing
+the syntax of the input file,
+the pattern matching capabilities, and
+the special rules for maintaining archives.
+A brief description of
+.CW mk\fR'\fPs
+algorithm for deriving dependencies
+is followed by a discussion
+of the conventions used to resolve ambiguous
+specifications. The final sections
+describe parallel execution
+and special features.
+.PP
+An earlier paper [Hume87]
+provides a detailed discussion of
+.CW mk\fR'\fPs
+design.
+.NH 1
+The \f(CWMkfile\fP
+.PP
+.CW Mk
+reads a file describing relationships among files
+and executes commands to bring the files up to date.
+The specification file, called a
+.CW mkfile ,
+contains three types of statements:
+assignments, includes, and rules.
+Assignment and include statements are similar
+to those in C.
+Rules specify dependencies between a
+.I target
+and its
+.I prerequisites .
+When the target and prerequisites are files, their
+modification times determine if they
+are out of date. Rules often contain a
+.I recipe ,
+an
+.I rc (1)
+script that produces the target from
+the prerequisites.
+.PP
+This simple
+.CW mkfile
+produces an executable
+from a C source file:
+.P1
+CC=pcc
+f1: f1.c
+ $CC -o f1 f1.c
+.P2
+The first line assigns the name of the portable ANSI/POSIX compiler
+to the
+.CW mk
+variable
+.CW CC ;
+subsequent references of the form
+.CW $CC
+select this compiler.
+The only rule specifies a dependence between the target file
+.CW f1
+and the prerequisite file
+.CW f1.c .
+If the target does not exist or if the
+prerequisite has been modified more recently than
+the target,
+.CW mk
+passes the recipe to
+.CW rc
+for execution. Here,
+.CW f1.c
+is compiled and loaded to produce
+.CW f1 .
+.PP
+The native Plan 9 environment
+requires executables for
+all architectures, not only the current one.
+The Plan 9 version of the same
+.CW mkfile
+looks like:
+.P1
+</$objtype/mkfile
+CFLAGS=-w
+
+f1: f1.$O
+ $LD $LDFLAGS -o f1 f1.$O
+f1.$O: f1.c
+ $CC $CFLAGS f1.c
+.P2
+The first line is an include statement
+that replaces itself with the contents of the file
+.CW /$objtype/mkfile .
+The variable
+.CW $objtype
+is inherited from the environment and
+contains the name of the target architecture.
+The prototype
+.CW mkfile
+for that architecture defines architecture-specific variables:
+.CW CC
+and
+.CW LD
+are the names of the compiler and loader,
+.CW O
+is the code character of the architecture.
+The rules compile the source file into an object
+file and invoke the loader to produce
+.CW f1 .
+Invoking
+.CW mk
+from the command line as follows
+.P1
+% objtype=sparc mk
+kc -w f1.c
+kl $LDFLAGS -o f1 f1.k
+%
+.P2
+produces the
+.CW sparc
+executable of program
+.CW f1
+regardless of the current architecture type.
+.PP
+We can extend the
+.CW mkfile
+to build two programs:
+.P1
+</$objtype/mkfile
+CFLAGS=-w
+ALL=f1 f2
+
+all:V: $ALL
+
+f1: f1.$O
+ $LD $LDFLAGS -o f1 f1.$O
+f1.$O: f1.c
+ $CC $CFLAGS f1.c
+f2: f2.$O
+ $LD $LDFLAGS -o f2 f2.$O
+f2.$O: f2.c
+ $CC $CFLAGS f2.c
+.P2
+The target
+.CW all ,
+modified by the
+.I attribute
+.CW V ,
+builds both programs.
+The attribute identifies
+.CW all
+as a dummy target that is
+not related to a file of the same name;
+its precise effect is explained later.
+This example describes cascading dependencies:
+the first target depends on another which depends on a third and
+so on.
+Here, individual rules build each
+program; later we'll see how to do this with a
+general rule.
+.NH 1
+Variables and the environment
+.PP
+.CW Mk
+does not distinguish between its
+variables and
+.CW rc
+variables in the environment.
+When
+.CW mk
+starts, it imports each environment variable into a
+.CW mk
+variable of the same name. Before executing a recipe,
+.CW mk
+exports all variables, including those
+inherited from the environment,
+to the environment in which
+.CW rc
+executes the recipe.
+.PP
+There are several ways for a
+variable to take a value.
+It can be set with an assignment statement,
+inherited from the environment, or specified
+on the command line.
+.CW Mk
+also maintains several internal variables;
+these variables are described in
+.I mk (1).
+Assignments have the following decreasing order of precedence:
+.LP
+.in .7i
+1) Command line assignment
+.br
+2) Assignment statement
+.br
+3) Imported from the environment
+.br
+4) Implicitly set by \f(CWmk\fP
+.in 0
+.LP
+For example, a command line assignment overrides
+a value imported from the environment.
+.PP
+All variable values are strings. They can be
+used for pattern matching and
+comparison but not for arithmetic.
+A
+.I list
+is a string containing several values separated by
+white space. Each member is
+handled individually during pattern matching,
+target selection, and prerequisite evaluation.
+.PP
+A
+.I namelist
+is a list produced by
+transforming the members of an existing list.
+The transform applies a pattern to each member,
+replacing each matched string with a new string,
+much as in the substitute command in
+.I sam (1)
+or
+.I ed (1).
+The syntax is
+.P1
+${\fIvar\fP:A%B=C%D}
+.P2
+where
+.I var
+is a variable.
+The pattern
+.CW A%B
+matches a member beginning with the string
+.I A
+and ending with the string
+.I B
+with any string in between;
+it behaves like the regular expression
+.CW A.*B .
+When a member of the
+.I var
+list
+matches this pattern,
+the string
+.I C
+replaces
+.I A ,
+.I D
+replaces
+.I B ,
+and the matched string replaces itself.
+Any of
+.I A ,
+.I B ,
+.I C ,
+or
+.I D
+may be the empty string. In effect, a namelist is
+generated by applying the
+.I ed (1)
+substitute command
+.P1
+ s/\fIA\fP(.*)\fIB\fP/\fIC\fP\e1\fID\fP/
+.P2
+to each member of a variable.
+.PP
+Namelists are useful for generating
+a list based on a predictable transformation.
+For example,
+.P1
+ SRC=a.c b.c c.c
+ OBJ=${SRC:%.c=%.v}
+.P2
+assigns the list \f(CW(a.v b.v c.v)\fP to
+.CW OBJ .
+A namelist may be used anywhere a variable is allowed
+except in a recipe.
+.PP
+Command output is assigned to a variable
+using the normal
+.CW rc
+syntax:
+.P1
+ var=`{rc command}
+.P2
+The command executes in an environment populated
+with previously assigned variables, including those
+inherited from
+.CW mk\fR'\fPs
+execution environment.
+The command may
+be arbitrarily complex; for example,
+.P1
+ TARG=`{ls -d *.[cyl] | sed 's/..$//'}
+.P2
+assigns a list of the C, yacc, and Alef source files in the current
+directory, stripped of their suffix, to the variable
+.CW TARG .
+.NH 1
+The include statement
+.PP
+The include statement
+replaces itself with the contents of a file.
+It is functionally similar to the C
+.CW #include
+statement but uses a different syntax:
+.P1
+ <\fIfilename\fP
+.P2
+The contents of the file are evaluated
+as they are read.
+An include statement may be used anywhere except
+in a recipe.
+.PP
+Unlike
+.CW make ,
+.CW mk
+has no built-in rules. Instead,
+the include statement allows generic rules
+to be imported from a prototype
+.CW mkfile ;
+most Plan 9
+.CW mkfiles
+use this approach [Flan95].
+.NH 1
+Rules
+.PP
+A rule has four elements: targets,
+prerequisites, attributes, and a recipe.
+It has the form:
+.P1
+\fItargets\fP:\fIattributes\fP:\fIprerequisites\fP
+ \fIrecipe\fP
+.P2
+The first line, containing the
+targets, attributes, and prerequisites is
+the
+.I "rule header" ;
+it
+must begin at the left margin.
+The recipe contains zero or more lines,
+each of which begins with white space.
+One or more targets must be specified but the
+attributes, prerequisites, and recipe are optional.
+A rule specifies
+a dependency between the targets and the prerequisites;
+the recipe brings the targets
+up to date with the prerequisites.
+Attributes modify
+.CW mk\fR'\fPs
+evaluation of a rule.
+.PP
+Normally the target is a file that depends
+on one or more prerequisite files.
+.CW Mk
+compares the modification times of each target
+and each prerequisite; a target is considered out of date
+when it does not exist or when a prerequisite has been modified
+more recently.
+When a target is out of date,
+.CW mk
+executes the
+recipe to bring it up to date.
+When the recipe completes,
+the modification time of the target is checked and
+used in later dependency evaluations.
+If the recipe does not update the target,
+evaluation continues with the out of date target.
+.PP
+A prerequisite of one rule
+may be the target of another. When
+this happens, the rules cascade
+to define a multi-step procedure.
+For example,
+an executable target depends on prerequisite
+object files, each of which is a target
+in a rule with a C source file as the prerequisite.
+.CW Mk
+follows a chain of dependencies until it encounters
+a prerequisite that is not a target of another rule
+or it finds a target that
+is up to date. It then
+executes the recipes in reverse order to produce
+the desired target.
+.PP
+The rule header is evaluated when the rule is read.
+Variables are replaced by their values, namelists are
+generated, and
+commands are replaced by their
+output at this time.
+.PP
+Most attributes modify
+.CW mk\fR'\fPs
+evaluation of a rule.
+An attribute is usually a single letter but some
+are more complicated.
+This paper only discusses commonly used attributes;
+see
+.I mk (1)
+for a complete list.
+.PP
+The
+.CW V
+attribute identifies a
+.I virtual
+target;
+that is, a target that is not a file.
+For example,
+.P1
+clean:V:
+ rm *.$O $O.out
+.P2
+removes executables and compiler intermediate files.
+The target is virtual because it does not refer to a file named
+.CW clean .
+Without the attribute, the recipe would not be
+executed if a file named
+.CW clean
+existed.
+The
+.CW Q
+silences the default printing of a recipe before
+it is executed.
+It is useful when the output of a recipe is
+similar to the recipe:
+.P1
+default:QV:
+ echo 'No default target; use mk all or mk install'
+.P2
+.PP
+A recipe is an
+.CW rc
+script. The recipe is optional; when it is
+missing, the rule is handled specially, as described later.
+Unlike
+.CW make ,
+.CW mk
+executes recipes without interpretation.
+After
+stripping the first white space character from each line
+it passes the entire recipe to
+.CW rc
+on standard input.
+Since
+.CW mk
+does not interpret a recipe,
+escape conventions are exactly those of
+.CW rc .
+Scripts for
+.CW awk
+and
+.CW sed
+commands can be embedded just as they would
+be specified from the command line.
+.CW Mk
+invokes
+.CW rc
+with the
+.CW -e
+flag, which causes
+.CW rc
+to stop if any command
+in the recipe exits with a non-zero status; the
+.CW E
+attribute overrides this behavior and allows
+.CW rc
+to continue executing in the face of errors.
+Before a recipe is executed, variables are exported
+to the environment where
+.CW rc
+can see them.
+Recipe commands may not read from
+standard input because
+.CW mk
+uses it internally.
+.PP
+References to a variable can yield different
+values depending on the location of the
+reference in the
+.CW mkfile .
+.CW Mk
+resolves variable references
+in assignment statements and rule headers
+when the statement is read. Variable references
+in recipes are evaluated by
+.CW rc
+when the recipe is executed; this
+happens after the entire
+.CW mkfile
+has been read. The value of a variable in a recipe
+is the last value assigned in the file. For example,
+.P1
+STRING=all
+
+all:VQ:
+ echo $STRING
+STRING=none
+.P2
+produces the message
+.CW none .
+A variable assignment in a recipe
+does not affect the value of the variable in the
+.CW mkfile
+for two reasons.
+First,
+.CW mk
+does not import values from
+the environment when a recipe completes;
+one recipe cannot pass a value through
+the environment to another recipe.
+Second, no recipe is executed until
+.CW mk
+has completed its evaluation, so even if a variable
+were changed,
+it would not affect the dependency evaluation.
+.NH 1
+Metarules
+.PP
+A
+.I metarule
+is a rule based on a pattern.
+The pattern selects a class of target and
+identifies related prerequisites.
+.CW Mk
+metarules may select targets and prerequisites
+based on any criterion that can be described by a pattern, not just
+the suffix transformations associated with program
+construction.
+.PP
+.CW Mk
+has two types of patterns:
+.I intrinsic
+patterns or regular expressions conforming to the
+syntax of
+.I regexp (6).
+The intrinsic patterns are shorthand
+for common regular expressions.
+The intrinsic pattern
+.CW %
+matches one or more of anything; it is equivalent to
+the regular expression
+.CW `.+' .
+The other intrinsic pattern,
+.CW & ,
+matches one or more of any characters except \f(CW`/'\fP
+and \f(CW`.'\fP.
+It matches a portion of a path and is
+equivalent to the regular expression
+.CW `[^./]+' .
+An intrinsic pattern in a prerequisite references
+the string matched by the same intrinsic pattern in the target.
+For example, the rule
+.P1
+ %.v: %.c
+.P2
+says that a file ending in
+.CW .v
+depends on a file of the same name with a
+.CW .c
+suffix:
+.CW foo.v
+depends on
+.CW foo.c ,
+.CW bar.v
+depends on
+.CW bar.c ,
+and so on.
+The string matched by an intrinsic pattern in the target
+is supplied to the recipe in the variable
+.CW $stem .
+Thus the rule
+.P1
+%.$O: %.c
+ $CC $CFLAGS $stem.c
+.P2
+creates an object file for the target architecture from
+a similarly named C source file. If several object
+files are out of date, the rule is applied repeatedly and
+.CW $stem
+refers to each file in turn.
+Since there is only one
+.CW stem
+variable, there can only be one
+.CW %
+or
+.CW &
+pattern in a target;
+the pattern
+.CW %-%.c
+is illegal.
+.PP
+Metarules simplify the
+.CW mkfile
+for building programs
+.CW f1
+and
+.CW f2 :
+.P1
+</$objtype/mkfile
+CFLAGS=-w
+ALL=f1 f2
+
+all:V: $ALL
+
+%: %.$O
+ $LD -o $target $prereq
+%.$O: %.c
+ $CC $CFLAGS $stem.c
+clean:V:
+ rm -f $ALL *.[$OS]
+.P2
+(The variable
+.CW $OS
+is a list of code characters for all architectures.)
+Here, metarules specify
+compile and load steps for all files.
+The loader rule relies on two internal variables
+set by
+.CW mk
+during evaluation of the rule:
+.CW $target
+is the name of the target and
+.CW $prereq
+the name of all prerequisites.
+Metarules allow this
+.CW mkfile
+to be easily extended; a new program
+is supported by adding its name to the third line.
+.PP
+A regular expression metarule must have an
+.CW R
+attribute.
+Prerequisites may reference matching substrings in
+the target using the form
+.CW \e\fIn\fP
+where
+.I n
+is a digit from 1 to 9 specifying the
+.I n th
+parenthesized sub-expression. In a recipe,
+.CW $stem\fIn\fP
+is the equivalent reference.
+For example, a compile rule could be
+specified using regular expressions:
+.P1
+(.+)\e.$O:R: \e1.c
+ $CC $CFLAGS $stem1.c
+.P2
+Here,
+.CW \e1
+and
+.CW $stem1
+refer to the name of the target object file without the
+suffix. The variable
+.CW $stem
+associated with an intrinsic pattern is undefined
+in a regular expression metarule.
+.NH 1
+Archives
+.PP
+.CW Mk
+provides a special mechanism for maintaining an archive.
+An archive member is referenced using the form
+.CW \fIlib\fP(\fIfile\fP)
+where
+.I lib
+is the name of the archive and
+.I file
+is the name of the member. Two rules define the
+dependency between an object file and its membership
+in an archive:
+.P1
+$LIB(foo.v):N: foo.v
+$LIB: $LIB(foo.v)
+ ar rv $LIB foo.v
+.P2
+The first rule establishes a dependency between the
+archive member and the object file.
+Normally,
+.CW mk
+detects an error when a target does not exist and the rule
+contains no recipe; the
+.CW N
+attribute overrides this behavior because the subsequent rule
+updates the member.
+The second
+rule establishes the dependency between the member and
+the archive; its recipe inserts the member
+into the archive.
+This two-step specification allows the archive
+to represent the state of its members. Other rules
+can then specify the archive as a prerequisite instead of
+listing each member.
+.PP
+A metarule generalizes library maintenance:
+.P1
+LIB=lib.a
+OBJS=etoa.$O atoe.$O ebcdic.$O
+
+$LIB(%):N: %
+$LIB: ${OBJS:%=$LIB(%)}
+ ar rv $LIB $OBJS
+.P2
+The namelist prerequisite of the
+.CW $LIB
+target generates archive member names for each object file name;
+for example,
+.CW etoa.$O
+becomes
+.CW lib.a(etoa.$O) .
+This formulation always updates all members.
+This is acceptable for a small archive, but may
+be slow for a big one.
+The rule
+.P1
+$LIB: ${OBJS:%=$LIB(%)}
+ ar rv $LIB `{membername $newprereq}
+.P2
+only updates out of date object files.
+The internal variable
+.CW $newprereq
+contains the names of the out of
+date prerequisites. The
+.CW rc
+script
+.CW membername
+transforms an archive member specification into a file name:
+it translates
+.CW lib.a(etoa.$O)
+into
+.CW etoa.$O .
+.PP
+The
+.CW mkfile
+.P1
+</$objtype/mkfile
+LIB=lib.a
+OBJS=etoa.$O atoe.$O ebcdic.$O
+
+prog: main.$O $LIB
+ $LD -o $target $prereq
+
+$LIB(%):N: %
+$LIB: ${OBJS:%=$LIB(%)}
+ ar rv $LIB $OBJS
+.P2
+builds a program by loading it with a library.
+.NH 1
+Evaluation algorithm
+.PP
+For each target of interest,
+.CW mk
+uses the rules in a
+.CW mkfile
+to build a data
+structure called a dependency graph. The nodes of
+the graph represent targets and prerequisites;
+a directed arc
+from one node to another indicates that
+the file associated with the first node depends
+on the file associated with the second.
+When the
+.CW mkfile
+has been completely read, the graph is analyzed.
+In the first step, implied dependencies are resolved by
+computing the
+.I "transitive closure"
+of the graph.
+This calculation extends the graph to include all
+targets that are potentially
+derivable from the rules in the
+.CW mkfile .
+Next the graph is checked for cycles;
+.CW make
+accepts cyclic dependencies, but
+.CW mk
+does not allow them.
+Subsequent steps
+prune subgraphs that are irrelevant for producing the
+desired target and verify that there is only one way
+to build it.
+The recipes associated with the
+nodes on the longest path between the
+target and an out of date prerequisite
+are then executed in reverse order.
+.PP
+The transitive closure calculation is sensitive to
+metarules; the patterns often select many potential targets
+and cause the graph to grow rapidly.
+Fortunately,
+dependencies associated with the desired target
+usually form a small part of the graph, so, after
+pruning, analysis is tractable.
+For example, the rules
+.P1
+%: x.%
+ recipe1
+x.%: %.k
+ recipe2
+%.k: %.f
+ recipe3
+.P2
+produce a graph with four nodes for each file in the
+current directory.
+If the desired target is
+.CW foo ,
+.CW mk
+detects the dependency between it
+and the original file
+.CW foo.f
+through intermediate dependencies on
+.CW foo.k
+and
+.CW x.foo .
+Nodes associated with other files are deleted during pruning because
+they are irrelevant to the production of
+.CW foo .
+.PP
+.CW Mk
+avoids infinite cycles by evaluating
+each metarule once.
+Thus, the rule
+.P1
+%: %.z
+ cp $prereq $prereq.z
+.P2
+copies the prerequisite file once.
+.NH 1
+Conventions for evaluating rules
+.PP
+There must be only one
+way to build each target. However, during evaluation
+metarule patterns often select potential targets that
+conflict with the
+targets of other rules.
+.CW Mk
+uses several conventions to resolve ambiguities
+and to select the proper dependencies.
+.PP
+When a target selects more than one rule,
+.CW mk
+chooses a regular rule
+over a metarule.
+For example, the
+.CW mkfile
+.P1
+</$objtype/mkfile
+CFLAGS=-w
+FILES=f1.$O f2.$O f3.$O
+
+prog: $FILES
+ $LD -o $target $prereq
+
+%.$O: %.c
+ $CC $CFLAGS $stem.c
+
+f2.$O: f2.c
+ $CC f2.c
+.P2
+contains two rules that could build
+.CW f2.$O .
+.CW Mk
+selects the last rule because its target,
+.CW f2.$O ,
+is explicitly specified, while the
+.CW %.$O
+rule is a metarule. In effect,
+the explicit rule for
+.CW f2.$O
+overrides the general rule for building object files from
+C source files.
+.PP
+When a rule has a target and prerequisites but no recipe,
+those prerequisites are added to all other rules with
+recipes that have the same target.
+All prerequisites, regardless of where they were specified, are
+available in the recipe in variable
+.CW $prereq .
+For example, in
+.P1
+</$objtype/mkfile
+CFLAGS=-w
+FILES=f1.$O f2.$O f3.$O
+
+prog: $FILES
+ $LD -o $target $prereq
+
+%.$O: hdr.h
+
+%.$O: %.c
+ $CC $CFLAGS $stem.c
+.P2
+the second rule adds
+.CW hdr.h
+as a prerequisite of the compile metarule;
+an object file produced from a C source file
+depends on
+.CW hdr.h
+as well as the source file. Notice that the recipe of
+the compile rule uses
+.CW $stem.c
+instead of
+.CW $prereq
+because the latter specification would attempt to compile
+.CW hdr.h .
+.PP
+When a target is virtual and there is no other rule with
+the same target,
+.CW mk
+evaluates each prerequisite.
+For example, adding the rule
+.P1
+all:V: prog
+.P2
+to the preceding example builds the executable
+when either
+.CW prog
+or
+.CW all
+is the specified target. In effect, the
+.CW all
+target is an alias for
+.CW prog .
+.PP
+When two rules have identical rule headers and both have
+recipes, the later rule replaces the former one.
+For example,
+if a file named
+.CW mkrules
+contains
+.P1
+$O.out: $OFILES
+ $LD $LFLAGS $OFILES
+%.$O: %.c
+ $CC $CFLAGS $stem.c
+.P2
+the
+.CW mkfile
+.P1
+OFILES=f1.$O f2.$O f3.$O
+
+<mkrules
+
+$O.out: $OFILES
+ $LD $LFLAGS -l $OFILES -lbio -lc
+.P2
+overrides the general loader rule with a special
+rule using a non-standard library search sequence.
+A rule is neutralized by overriding it with a rule
+with a null recipe:
+.P1
+<mkrules
+
+$O.out:Q: $OFILES
+ ;
+.P2
+The
+.CW Q
+attribute suppresses the printing of the semicolon.
+.PP
+When a rule has no prerequisites, the recipe is executed
+only when the target does not exist. For example,
+.P1
+marker:
+ touch $target
+.P2
+defines a rule to manage a marker file.
+If the file exists, it is considered up to date
+regardless of its modification time.
+When a virtual target has no prerequisites the
+recipe is always executed.
+The
+.CW clean
+rule is of this type:
+.P1
+clean:V:
+ rm -f [$OS].out *.[$OS]
+.P2
+When a rule without prerequisites has multiple targets, the
+extra targets are aliases for the rule.
+For example, in
+.P1
+clean tidy nuke:V:
+ rm -f [$OS].out *.[$OS]
+.P2
+the
+rule can be invoked by any of three names.
+The first rule in a
+.CW mkfile
+is handled specially:
+when
+.CW mk
+is invoked without a command line target
+all targets of the first non-metarule are built.
+When that rule has multiple targets, the recipe
+is executed once for each target; normally, the recipe
+of a rule with multiple targets is only executed once.
+.PP
+A rule applies to a target only when its prerequisites
+exist or can be derived. More than one rule may have the
+same target as long as only one rule with a recipe
+remains applicable after the dependency evaluation completes.
+For example, consider a program built from C
+and assembler source files. Two rules produce
+object files:
+.P1
+%.$O: %.c
+ $CC $CFLAGS $stem.c
+%.$O: %.s
+ $AS $AFLAGS $stem.s
+.P2
+As long as there are not two source files with names like
+.CW \fIfoo\fP.c
+and
+.CW \fIfoo\fP.s ,
+.CW mk
+can unambiguously select the proper rule.
+If both files exist,
+there are ambiguous rules to produce
+.CW \fIfoo\fP.$O ,
+and
+.CW mk
+exits with an error message.
+.PP
+In Plan 9, many programs consist of portable code stored
+in one directory and architecture-specific source stored in
+another.
+For example, the
+.CW mkfile
+.P1
+</$objtype/mkfile
+CFLAGS=-w
+FILES=f1.$O f2.$O f3.$O f3.$O
+
+prog: $FILES
+ $LD -o $target $prereq
+
+%.$O: %.$c
+ $CC $CFLAGS $stem.c
+
+%.$O: ../port/%.c
+ $CC $CFLAGS ../port/$stem.c
+.P2
+builds the program named
+.CW prog
+using portable code in directory
+.CW ../port
+and architecture-specific code in the current directory.
+As long as the
+names of the C source files in
+.CW ../port
+do not conflict with the names of files in the current directory,
+.CW mk
+selects the appropriate rule.
+If like-named files exist in both directories, the
+specification is ambiguous and results in an error.
+An explicit target resolves the ambiguity.
+For example,
+adding the rule
+.P1
+f2.$O: f2.c
+ $CC $CFLAGS $f2.c
+.P2
+to the previous
+.CW mkfile
+uses the architecture-specific version of
+.CW f2.c
+instead of the portable one.
+Here, the explicit rule
+documents which of the
+like-named source files is used to build the program.
+.PP
+.CW Mk\fR'\fP s
+heuristics can produce unintended results
+when rules are not carefully specified.
+For example, the rules that build
+object files from C or assembler source files
+.P1
+%.$O: %.c
+ $CC $CFLAGS $stem.c
+%.$O: %.s
+ $AS $AFLAGS $stem.s
+.P2
+illustrate a subtle pratfall.
+Adding a header file dependency to the compile rule
+.P1
+%.$O: %.c hdr.h
+ $CC $CFLAGS $stem.c
+.P2
+produces the error message
+.P1
+.CW "don't know how to make '\fIfile\fP.c'"
+.P2
+when \fIfile\fP.s is an assembler
+source file.
+This occurs because
+.CW \fIfile\fP.s
+satisfies the assemble rule and
+.CW hdr.h
+satisfies the compile rule, so
+either rule can potentially produce the target.
+When a prerequisite exists or can be
+derived,
+all other prerequisites in that
+rule header must exist or be derivable; here,
+the existence of
+.CW hdr.h
+forces the evaluation of a C source file.
+Specifying the dependencies in different
+rules avoids this interpretation:
+.P1
+%.$O: hdr.h
+%.$O: %.c
+ $CC $CFLAGS $stem.c
+.P2
+Although
+.CW hdr.h
+is an additional prerequisite of the compile rule,
+the two rules are evaluated independently and
+the existence of the C source file is not linked
+to the existence of the header file.
+However, this specification describes a different
+dependency. Originally, only object
+files derived from C files depended on
+.CW hdr.h ;
+now all object files, including those built
+from assembler source, depend on the header file.
+.PP
+Metarule patterns should be as restrictive as possible to
+prevent conflicts with other rules.
+Consider the
+.CW mkfile
+.P1
+</$objtype/mkfile
+BIN=/$objtype/bin
+PROG=foo
+
+install:V: $BIN/$PROG
+
+%: %.c
+ $CC $stem.c
+ $LD -o $target $stem.$O
+
+$BIN/%: %
+ mv $stem $target
+.P2
+The first target builds an executable
+in the local directory; the second
+installs it in the directory
+of executables for the architecture.
+Invoking
+.CW mk
+with the
+.CW install
+target produces:
+.P1 0
+mk: ambiguous recipes for /mips/bin/foo:
+/mips/bin/foo <-(mkfile:8)- /mips/bin/foo.c <-(mkfile:12)- foo.c
+/mips/bin/foo <-(mkfile:12)- foo <-(mkfile:8)- foo.c
+.P2
+The prerequisite of the
+.CW install
+rule,
+.CW $BIN/$PROG ,
+matches both metarules because the
+.CW %
+pattern matches everything.
+The
+.CW &
+pattern restricts the compile rule to files in the
+current directory and avoids the conflict:
+.P1
+&: &.c
+ $CC $stem.c
+ $LD -o $target $stem.$O
+.P2
+.NH 1
+Missing intermediates
+.PP
+.CW Mk
+does not build a missing intermediate file if a target
+is up to date with the prerequisites of the intermediate.
+For example,
+when an executable is up to date with its source file,
+.CW mk
+does not compile the source to create a missing object file.
+The evaluation only applies
+when a target is considered up to date by pretending that the
+intermediate exists. Thus, it does not apply
+when the intermediate is a command line target
+or when it has no prerequisites.
+.PP
+This capability is useful for
+maintaining archives. We can modify the archive
+update recipe to remove object files after
+they are archived:
+.P1
+$LIB(%):N: %
+$LIB: ${OBJS:%=$LIB(%)}
+ names=`{membername $newprereq}
+ ar rv $LIB $names
+ rm -f $names
+.P2
+A subsequent
+.CW mk
+does not remake the object files as long as the members
+of the archive remain up to date with the source files.
+The
+.CW -i
+command line option overrides this behavior
+and causes all intermediates to be built.
+.NH 1
+Alternative out-of-date determination
+.PP
+Sometimes the modification time is not useful
+for deciding when a target and prerequisite are out of date.
+The
+.CW P
+attribute replaces the default mechanism with the result of
+a command. The command immediately follows the attribute
+and is repeatedly executed with each
+target and each prerequisite as its arguments;
+if its exit status is non-zero, they are considered out of date
+and the recipe is executed. Consider the
+.CW mkfile
+.P1
+foo.ref:Pcmp -s: foo
+ cp $prereq $target
+.P2
+The command
+.P1
+cmp -s foo.ref foo
+.P2
+is executed and if
+.CW foo.ref
+differs from
+.CW foo ,
+the latter file is copied to the former.
+.NH 1
+Parallel processing
+.PP
+When possible,
+.CW mk
+executes recipes in parallel.
+The variable
+.CW $NPROC
+specifies the maximum number of simultaneously executing
+recipes.
+Normally it is imported from the environment,
+where the system has set it to the number of available processors.
+It can be decreased by assigning a new
+value and can be set to 1 to force single-threaded recipe execution.
+This is necessary when several targets access
+a common resource such as
+a status file or data base.
+When there is no dependency between targets,
+.CW mk
+assumes the
+recipes can be
+executed concurrently.
+Normally, this allows
+multiple prerequisites to be built simultaneously;
+for example, the object file prerequisites of
+a load rule can be produced by compiling the source files in parallel.
+.CW Mk
+does not define the order of execution of independent recipes.
+When the prerequisites of a rule are not independent,
+the dependencies between them should be specified in a rule or the
+.CW mkfile
+should be single-threaded.
+For example, the archive update rules
+.P1
+$LIB(%):N: %
+$LIB: ${OBJS:%=$LIB(%)}
+ ar rv $LIB `{membername $newprereq}
+.P2
+compile source files in parallel but update
+all members of the archive at once.
+It is a mistake to merge the two rules
+.P1
+$LIB(%): %
+ ar rv $LIB $stem
+.P2
+because an
+.CW ar
+command is executed for every
+member of the library. Not only is this
+inefficient, but the archive is updated
+in parallel, making interference likely.
+.PP
+The
+.CW $nproc
+environment variable contains a number associated
+with the processor executing a recipe.
+It can be used to create unique
+names when the
+recipe may be executing simultaneously on several processors.
+Other maintenance tools provide mechanisms to control recipe
+scheduling explicitly [Cmel86], but
+.CW mk\fR'\fPs
+general rules are sufficient for all but the most unusual cases.
+.NH 1
+Deleting target files on errors
+.PP
+The
+.CW D
+attribute
+causes
+.CW mk
+to remove the target file when a
+recipe terminates prematurely.
+The error message describing the
+termination condition warns
+of the deletion.
+A partially built file is doubly dangerous:
+it is not only wrong, but is also
+considered to be up to date so
+a subsequent
+.CW mk
+will not rebuild it. For example,
+.P1
+pic.out:D: mk.ms
+ pic $prereq | tbl | troff -ms > $target
+.P2
+produces the message
+.P1
+.CW "mk: pic mk.ms | ... : exit status=rc 685: deleting 'pic.out'"
+.P2
+if any program in the recipe exits with an error status.
+.NH 1
+Unspecified dependencies
+.PP
+The
+.CW -w
+command line flag forces the
+files following the flag to be treated
+as if they were just modified.
+We can use this flag with a command that selects files
+to force a build based on the selection criterion.
+For example, if the declaration of
+a global variable named
+.I var
+is changed in a header file,
+all source files that reference
+it can be rebuilt with the command
+.P1
+$ mk -w`{grep -l \fIvar\fP *.[cyl]}
+.P2
+.NH 1
+Conclusion
+.PP
+There are many programs related to
+.CW make ,
+each choosing a different balance between
+specialization and generality.
+.CW Mk
+emphasizes generality but allows
+customization through its pattern specifications and
+include facilities.
+.PP
+Plan 9 presents a difficult problem, particularly
+because of its heterogeneous collection of
+architectures and languages.
+.CW Mk\fR'\fPs
+flexible specification language and simple
+interaction with
+.CW rc
+work well in this environment.
+.PP
+As a result,
+Plan 9 relies on
+.CW mk
+to automate almost all maintenance.
+Tasks as diverse as updating the
+network data base, producing the manual,
+or building a release are expressed as
+.CW mk
+procedures.
+.NH 1
+References
+.LP
+[Cmel86] R. F. Cmelik,
+``Concurrent Make: A Distributed Program in Concurrent C'',
+AT&T Bell Laboratories Technical Report, 1986.
+.LP
+[Feld79] S. I. Feldman,
+``Make \(em a program for maintaining computer programs'',
+.I
+Software Practice & Experience ,
+.R
+1979
+Vol 9 #4,
+pp. 255-266.
+.LP
+[Flan95] Bob Flandrena,
+``Plan 9 Mkfiles'',
+this volume.
+.LP
+[Hume87] A. G. Hume,
+``Mk: A Successor to Make'',
+.I
+USENIX Summer Conf. Proc.,
+.R
+Phoenix, Az.
+.NH 1
+Appendix: Differences between
+.CW make
+and
+.CW mk
+.PP
+The differences between
+.CW mk
+and
+.CW make
+are:
+.IP \(bu 3n
+.CW Make
+builds targets when it needs them, allowing systematic use of side effects.
+.CW Mk
+constructs the entire dependency graph before building any target.
+.IP \(bu
+.CW Make
+supports suffix rules and
+.CW %
+metarules.
+.CW Mk
+supports
+.CW %
+and regular expression metarules.
+(Older versions of
+.CW make
+support only suffix rules.)
+.IP \(bu
+.CW Mk
+performs transitive closure on metarules,
+.CW make
+does not.
+.IP \(bu
+.CW Make
+supports cyclic dependencies,
+.CW mk
+does not.
+.IP \(bu
+.CW Make
+evaluates recipes one line at a time, replacing variables by their values and
+executing some commands internally.
+.CW Mk
+passes the entire recipe to the shell without
+interpretation or internal execution.
+.IP \(bu
+.CW Make
+supports parallel execution of single-line recipes when building
+the prerequisites for specified targets.
+.CW Mk
+supports parallel execution of all recipes.
+(Older versions of
+.CW make
+did not support parallel execution.)
+.IP \(bu
+.CW Make
+uses special targets (beginning with a period)
+to indicate special processing.
+.CW Mk
+uses attributes to modify rule evaluation.
+.IP \(bu
+.CW Mk
+supports virtual
+targets that are independent of the file system.
+.IP \(bu
+.CW Mk
+allows non-standard out-of-date determination,
+.CW make
+does not.
+.PP
+It is usually easy to convert a
+.CW makefile
+to or from an equivalent
+.CW mkfile .
binary files /dev/null b/doc/mk.pdf differ
--- /dev/null
+++ b/doc/mkfile
@@ -1,0 +1,67 @@
+<fonts.pal
+NPROC = 1
+FILES = \
+ title.ps \
+ bltj.ps \
+ styx.ps \
+ asm.ps \
+ changes.ps \
+ gridinstall.ps \
+ ebookimp.ps \
+ styx.ps \
+ mk.ps \
+ asm.ps \
+ compiler.ps \
+ sh.ps \
+ dis.ps \
+ acid.ps \
+ acidpaper.ps \
+ acidtut.ps \
+ mk.ps \
+ asm.ps \
+ compiler.ps \
+ port.ps \
+ hotchips.ps \
+ install.ps \
+
+DIRS = \
+ limbo \
+ perform \
+# limbotk \
+
+PRE=$FONTS'.ps 9
+.nr PS 9
+.vs 11
+.nr VS 11
+.nr dP 1
+.nr dV 1p
+.nr dT 4
+.nr XT 4
+'
+
+all:V: dirs
+
+print:V: \
+ title.ps \
+
+dirs:V: $FILES $DIRS mkfile fonts
+ for(i in $DIRS) @{
+ cd $i
+ mk
+ }
+
+%.ps:D: %.ms
+ { echo $PRE; cat $stem.ms } | tbl | troff -mpm | lp -dstdout > $target
+
+gridinstall.ps:D: gridinstall.ms
+ PRE=''
+ { echo $PRE; cat gridinstall.ms } | tbl | troff -ms | lp -dstdout > $target
+
+title.ps:D: title
+ troff $prereq | lp -dstdout > $target
+
+changes.ps:D: changes.ms
+ tbl changes.ms | troff -ms | dpost >$target
+
+%.pdf: %.ps
+ ps2pdf <$stem.ps >$stem.pdf
--- /dev/null
+++ b/doc/perform/mkfile
@@ -1,0 +1,15 @@
+<../fonts.pal
+
+%.ps:D: %.ms
+ { echo $FONTS; cat $stem.ms } | grap | pic | tbl | troff -mpm | lp -dstdout > $target
+
+FILES = \
+ perform.ps \
+
+all:V: $FILES
+
+perform.ps:D: perform.ms x0base.gr x0baseo.gr \
+ x0baseh.gr x0baseho.gr \
+ x9gc.gr x9gc200.gr \
+ x31.gr x27base.gr x27base200.gr \
+ x28base.gr x28basehd.gr x29basehd.gr
--- /dev/null
+++ b/doc/perform/perform.ms
@@ -1,0 +1,982 @@
+.TL
+Reliable Benchmarking with Limbo on Inferno
+.AU
+John Bates
+Vita Nuova Limited
+.SP
+3rd March 1999
+.br
+Revised 20th February 2000
+.AB
+Our goal was to identify a mechanism for performing
+accurate, reliable and realistic benchmarking measurements
+with Limbo on Inferno.
+The measurements would need to be \fIaccurate\fR in the sense that
+we could be confident that they were sufficiently close to the real time
+taken to perform the measured operation.
+We would consider a measurement to be \fIreliable\fR if it could be obtained
+repeatedly when carried out under the same conditions at a later date.
+Additionally, a measurement is only useful if it can be claimed
+to be related to the expected performance of a real applicable operation,
+we would call such a measurement \fIrealistic\fR.
+The emphasis in this document is on achieving a reliable measurement.
+.AE
+.SH
+Expectation
+.LP
+We would like to be able to make measurements with code like:
+.P1
+s := Sample.new(NREP);
+for(i:=0; i<NREP; i++) {
+ t = tstamp();
+ sys->sleep(0);
+ t = tstamp() - t;
+ s.add(t-base);
+}
+.P2
+Where
+.CW s
+is an object that can be used to record up to
+.CW NREP
+measurements and
+.CW base
+is our predetermined estimate of the cost of actually making the
+measurement. The Limbo function
+.CW tstamp()
+uses \fIdevbench\fR to obtain a microsecond timestamp.
+Such a measurement would give us an idea of the cost of making a
+.CW sys->sleep(0)
+call and by examining a sample of such measurements we could reason about
+the true cost of the call. In particular, we would get a feel for
+just how reliable our estimate of the true cost was.
+.LP
+The first task was to determine a suitable value to use for
+.CW base
+by measuring how long it took to do \fInothing\fR\(dg.
+.FS
+.vs 9
+.FA
+\(dg This benchmark is called
+.CW BASE
+in the \fIdevbench\fR benchmark suite.
+.FE
+.P1
+s := Sample.new(NREP);
+for(i:=0; i<NREP; i++) {
+ t = tstamp();
+ t = tstamp() - t;
+ s.add(t-base);
+}
+(n, mean, min, max, std) := s.stat();
+base = min;
+.P2
+By repeating the measurement a large number of times and then by
+choosing the minimum measurement we could hope to choose a
+sensible value for
+.CW base.
+Our confidence in the chosen value
+and in the results of subsequent benchmarking
+would be greatest if the
+distribution of measurements was \fInarrow\fR with most
+of the values close to the minimum.
+.SH
+Initial Results
+.LP
+We ran the initial tests on a 150MHz Pentium PC with a standard
+Inferno 2.0 native kernel and later with an Inferno 2.3 native kernel.
+The commands
+.P1
+bench -o >x
+bgrep BASE x | plot
+.P2
+run the benchmark suite leaving the observations in a file called
+.CW x
+and then extract the line containing the results for the test called
+.CW BASE
+and plot them to a Wm window under Inferno\(dg.
+.FS
+.vs 9
+.FA
+\(dg Actually, to generate the graphs in this document I used plot -g which
+produces grap(1) output.
+.br
+.vs
+.FE
+The command
+.CW bgrep
+is used in place of
+.CW grep
+because the Inferno
+.CW grep
+uses
+.CW sys->print
+to output lines and so inherits a very small upper bound on line length.
+The
+.CW -o
+option to
+.CW bench
+delivers the individual observations rather than summary statistics.
+The
+.CW BASE
+test repeats the above empty loop 1000 times.
+Plotting the observations in the order in which they were observed
+gives the surprising result shown in Figure 1.
+.KF
+.G1
+copy "x0base.gr"
+.G2
+.I "Figure 1. Showing the unexpected variation in the BASE results."
+.KE
+The majority of values appear to be small, but the graph is dominated
+by the relatively small number of very large irregular observations which
+lie at around 6 milliseconds to 8 milliseconds
+and a clearly discernible second set of values
+which look to form a more regular pattern at about
+the 1 millisecond level.
+The smaller set of values can be seen more clearly by removing the
+large values and rescaling the graph.
+The
+.CW -o
+option to
+.CW Plot
+invokes a crude scheme to remove a layer of outliers.
+It does this by calculating the sample mean and standard deviation and removing values which lie more than two standard deviations away from the mean. The process is repeated for each occurrence of the
+.CW -o
+option to
+.CW plot.
+Thus
+.P1
+plot -ooo
+.P2
+will remove three layers of outliers and then plot the remaining values.
+.KS
+Running
+.P1
+bgrep BASE x | plot -o
+.P2
+gives the output shown in figure 2.
+.KE
+.KF
+.G1
+copy "x0baseo.gr"
+.G2
+.I "Figure 2. Great variability in the BASE results, \
+even with the large outliers removed."
+.KE
+Again, a large number of small values (less than 500 microseconds)
+and a smaller number of larger values lying at around about the 1 millisecond
+level.
+Running the commands
+.P1
+bgrep BASE x | plot -p 1h
+bgrep BASE x | plot -p 1h -o -z
+.P2
+gives a histogram showing the distribution of the results.
+Firstly, with all the values
+and then with one level of outliers removed \(dg.
+.FS
+.vs 9
+.FA
+\(dg The
+.CW -z
+option to \fIplot\fR forces a zero origin to be part of the plot.
+.FE
+.KF
+.G1
+copy "x0baseh.gr"
+.G2
+.I "Figure 3. Histogram showing the distribution of results \
+from the BASE benchmark."
+.KE
+In Figure 3 we can see a small set of values up above the 7 millisecond
+level and then a slightly more focused set at around about 1 millisecond but
+together these groups make up much less than 10% of the total values.
+.KF
+.G1
+copy "x0baseho.gr"
+.G2
+.I "Figure 4. Histogram showing the distribution of results \
+from the BASE benchmark with the large outliers removed."
+.KE
+By removing a level of outliers we can see the distribution of the
+lower values more clearly, as shown in Figure 4.
+Even this lower cluster ranges from about 220 microseconds up to
+about 500 microseconds.
+.LP
+We can conclude from these initial results
+that it is not going to be possible to use this mechanism to
+perform accurate or reliable benchmarking unless its performance
+can be improved.
+.SH
+The Measurement Process
+.LP
+At this stage we're not actually measuring anything real, but looking
+to obtain some confidence in our measurements.
+We have started by observing times to complete the measurement of
+\fInothing\fR. We do this by writing a Limbo program (\fIbench.b\fR)
+which contains the following code:
+.P1
+t0, t1, base: big;
+NREP: con 1000;
+
+s := Sample.new(NREP);
+treset();
+for(i:=0; i<NREP; i++) {
+ t0 = tstamp();
+ t1 = tstamp();
+ s.add(t1-t0);
+}
+(nil, nil, base, nil, nil) = s.stat();
+
+iob.puts("BASE:1l:Observation::Time:us ");
+s.obs(iob);
+iob.puts("\\n");
+iob.flush();
+.P2
+The middle section of code performs the benchmark by taking
+two consecutive timestamps and noting the difference between them.
+This is repeated 1000 times and the observations accumulated
+in the sample variable
+.CW s.
+The function
+.CW s.stat()
+returns a tuple containing count, mean, minimum, maximum
+and standard deviation for the accumulated values.
+We assign the minimum value to our variable
+.CW base.
+The function
+.CW treset()
+arranges for the timestamp code to start returning
+small values and so reduces the likelihood of overflow
+or signing related issues.
+.LP
+The last section of code outputs one line containing the individual
+observations separated by spaces and with a suitably formatted
+initial \fIword\fR which labels the line so that
+.CW plot
+can make a useful interpretation of the results.
+.KS
+.LP
+The functions
+.CW treset()
+and
+.CW tstamp()
+make use of files served by \fIdevbench\fR and look like this:
+.P1
+tsfd: ref Sys->FD;
+treset()
+{
+ tsfd = sys->open("/dev/busec", sys->OWRITE);
+ if(tsfd == nil)
+ return;
+ buf := array[1] of byte;
+ n := sys->write(tsfd, buf, len buf);
+ tsfd = sys->open("/dev/busec", sys->OREAD);
+}
+.P3
+tstamp(): big
+{
+ buf := array[128] of byte;
+ n := sys->read(tsfd, buf, len buf);
+ if(n < 0)
+ return big 0;
+
+ return big string buf[0:n];
+}
+.P2
+.KE
+\fIDevbench\fR must have been previously bound into the
+namespace
+.P1
+bind -b '#x' /dev
+.P2
+so that the files
+.P1
+/dev/bctl
+/dev/bdata
+/dev/busec
+.P2
+are available.
+A microsecond timestamp is provided by reading from
+.CW /dev/busec
+and is reset to zero
+each time anthing is written to it.
+The function
+.CW treset()
+resets the timestamp by writing to the file and then opens it for reading.
+The function
+.CW tstamp()
+reads the timestamp from the file and converts it into a
+.CW big
+value for use in the program.
+The device driver ignores the offset when reading from the file so that it
+is not necessary to
+.CW seek
+to the beginning of the file before each read.
+The important part of the benchmark consists of two consecutive calls to
+.CW tstamp().
+We need to identify where time is being spent; either in the calls to
+.CW tstamp()
+or else inside the function itself.
+.SH
+Costing
+.LP
+The \fIdevbench\fR suite of programs includes one for timing
+individual lines of Limbo code and breaking down the time
+spent on each line into times for each of the Dis operations
+invoked by that line; the program is called \fIcost\fR.
+To find out how long each part of the benchmark timing loop
+takes we can invoke
+.P1
+cost -f bench.b -s bench
+.P2
+Which results in the following output - edited to just
+show the timing loop and the function
+.CW tstamp()
+\&.
+The first line is the output from \fIbench\fR giving the
+mean, minimum, maximum and standard deviation of microsecond times for
+1000 repetitions of the loop. We see a minimum of 402 microseconds
+and a maximum of just over 9 milliseconds.
+The remaining lines are the output of \fIcost\fR; those beginning
+with a dash are Dis operation times for the preceding Limbo
+source code line. Dis operation lines contain an operation name,
+an execution count and the mean, minimum, maximum and
+standard deviation of execution times.
+.P1
+BASE:summary:Sample:n:Time:us 1000 486 402 9053 499
+
+-- bench.b
+\&...
+ treset();
+- frame 1 2.13 us 2.13 us 2.13 us 0 ns
+- call 1 807 ns 807 ns 807 ns 0 ns
+ s := Sample.new(NREP*10);
+- mframe 1 4.85 us 4.85 us 4.85 us 0 ns
+- movw 1 2.27 us 2.27 us 2.27 us 0 ns
+- lea 1 1.57 us 1.57 us 1.57 us 0 ns
+- mcall 1 2.71 us 2.71 us 2.71 us 0 ns
+ for(i:=0; i<NREP*10; i++) {
+- movw 1 1.99 us 1.99 us 1.99 us 0 ns
+- blew 1001 1.60 us 1.51 us 34.04 us 1.03 us
+ t0 = tstamp();
+- frame 1000 2.43 us 2.29 us 3.40 us 133 ns
+- lea 1000 1.00 us 953 ns 27.74 us 847 ns
+- call 1000 1.45 us 1.29 us 2.24 us 153 ns
+ t1 = tstamp();
+- frame 1000 3.45 us 3.01 us 5.57 us 293 ns
+- lea 1000 1.22 us 1.02 us 1.61 us 173 ns
+- call 1000 1.44 us 1.29 us 1.75 us 140 ns
+ s.add(t1-t0);
+- mframe 1000 3.65 us 3.37 us 24.73 us 700 ns
+- movp 1000 1.99 us 1.48 us 2.96 us 267 ns
+- subl 1000 2.43 us 2.23 us 4.80 us 173 ns
+- mcall 1000 2.11 us 1.95 us 2.51 us 120 ns
+- addw 1000 1.62 us 1.48 us 2.50 us 127 ns
+- jmp 1000 1.50 us 1.37 us 1.81 us 120 ns
+ }
+ (nil, nil, base, nil, nil) = s.stat();
+- mframe 1 2.66 us 2.66 us 2.66 us 0 ns
+- movp 1 1.39 us 1.39 us 1.39 us 0 ns
+- lea 1 1.41 us 1.41 us 1.41 us 0 ns
+- mcall 1 1.37 us 1.37 us 1.37 us 0 ns
+- movl 1 1.56 us 1.56 us 1.56 us 0 ns
+ if(sflag)
+- beqw 1 2.14 us 2.14 us 2.14 us 0 ns
+ iob.puts("BASE:summary:Sample:n:Time:us "
+ + s.str() + "\\n");
+- mframe 1 4.01 us 4.01 us 4.01 us 0 ns
+- movp 1 2.87 us 2.87 us 2.87 us 0 ns
+- mframe 1 1.75 us 1.75 us 1.75 us 0 ns
+- movp 1 1.69 us 1.69 us 1.69 us 0 ns
+- lea 1 1.15 us 1.15 us 1.15 us 0 ns
+- mcall 1 2.35 us 2.35 us 2.35 us 0 ns
+- addc 1 19.57 us 19.57 us 19.57 us 0 ns
+- addc 1 8.55 us 8.55 us 8.55 us 0 ns
+- lea 1 1.49 us 1.49 us 1.49 us 0 ns
+- mcall 1 3.65 us 3.65 us 3.65 us 0 ns
+ iob.flush();
+- mframe 1 4.50 us 4.50 us 4.50 us 0 ns
+- movp 1 2.13 us 2.13 us 2.13 us 0 ns
+- lea 1 967 ns 967 ns 967 ns 0 ns
+- mcall 1 1.89 us 1.89 us 1.89 us 0 ns
+ }
+\&...
+.P3
+
+# return timestamp in microseconds
+tstamp(): big
+{
+ buf := array[128] of byte;
+- newa 2000 6.98 us 5.37 us 80.91 us 2.43 us
+ n := sys->read(tsfd, buf, len buf);
+- mframe 2000 3.05 us 2.59 us 4.05 us 227 ns
+- movp 2000 2.33 us 2.14 us 3.21 us 120 ns
+- movp 2000 1.19 us 1.14 us 2.93 us 73 ns
+- lena 2000 1.07 us 907 ns 34.48 us 760 ns
+- lea 2000 893 ns 860 ns 33.00 us 907 ns
+- mcall 2000 133.81 us 89.88 us 8.61 ms 514.44 us
+ if(n < 0)
+- blew 2000 2.27 us 1.76 us 3.43 us 313 ns
+ return big 0;
+
+ return big string buf[0:n];
+- movp 2000 2.21 us 1.67 us 3.38 us 253 ns
+- slicea 2000 10.06 us 8.35 us 39.31 us 1.40 us
+- cvtac 2000 12.02 us 11.13 us 16.63 us 553 ns
+- cvtcl 2000 16.39 us 15.78 us 45.16 us 787 ns
+- ret 2000 10.52 us 9.79 us 13.97 us 333 ns
+}
+.P2
+We can see from these figures that times for both calls
+to
+.CW tstamp()
+are reasonably low. But looking at the call to
+.CW "sys->read()"
+in
+.CW tstamp()
+we can see a maximum of just over 8½ milliseconds for the \fImcall\fR
+operation. We see too that this operation also has a high standard deviation
+of 514 microseconds across 2000 calls and so it looks like it may be
+the cause of the large observed delays.
+.LP
+In order to get a second view of what was happening we surrounded the
+timing code with calls to enable kernel profiling.
+.P1
+profon();
+for(i:=0; i<NREP*10; i++) {
+ t0 = tstamp();
+ t1 = tstamp();
+ s.add(t1-t0);
+}
+profoff();
+\&...
+profon()
+{
+ if(sys->write(kpctl, array of byte "startclr", 8) < 8)
+ error("kprof start");
+}
+
+profoff()
+{
+ if(sys->write(kpctl, array of byte "stop", 4) < 4)
+ error("kprof stop");
+}
+.P2
+Having previously bound in \fIdevkprof\fR
+.P1
+bind -b '#T' /dev
+.P2
+and opened \fI/dev/kpctl\fR for writing.
+By examining the contents of \fI/dev/kpdata\fR with \fIkprof\fR
+we see that the garbage collection functions \fImarkheap\fR
+and \fIrungc\fR are taking up a surprisingly large amount
+of kernel time for this operation.
+.P1
+total: 1460 in kernel text: 1460 outside kernel text: 0
+KTZERO 80100000
+ms % sym
+130 8.9 markheap
+110 7.5 iunlock
+100 6.8 xec
+90 6.1 rungc
+80 5.4 chartorune
+70 4.7 c2string
+60 4.1 numbconv
+50 3.4 string2c
+40 2.7 sched
+40 2.7 wakeup
+30 2.0 splhi
+30 2.0 freeptrs
+30 2.0 memset
+30 2.0 dodiv
+30 2.0 _divvu
+30 2.0 strtoll
+20 1.3 _mulv
+20 1.3 vmachine
+20 1.3 unlock
+20 1.3 runproc
+20 1.3 DEA
+10 0.6 kwrite
+.P2
+.SH
+Interpreting the Results
+.LP
+In order to progress we need to look more closely at what is
+happening inside the call to
+.CW "sys->read".
+As far as the kernel is concerned, there are two kinds of \fImcall\fR
+operations; those which result in a call to a builtin function and those
+which result in a call to a non-builtin function in another module.
+.CW "Sys->read"
+is of the former kind, it is a system builtin whose definition lies in the
+function \fISys_read\fR.
+When executing \fImcall\fR for a normal function the virtual machine
+primes the register set so that on the next iteration the operations
+will be fetched from the code associated with the new function.
+When executing \fImcall\fR for a builtin the virtual machine actually executes
+the associated function before returning to the next operation.
+The code for \fISys_read\fR looks like this:
+.P1
+void
+Sys_read(void *fp)
+{
+ int n;
+ F_Sys_read *f;
+
+ f = fp;
+ n = f->n;
+ if(f->buf == (Array*)H) {
+ *f->ret = 0;
+ return;
+ }
+ if(n > f->buf->len)
+ n = f->buf->len;
+
+ release();
+ *f->ret = kread(fdchk(f->fd), f->buf->data, n);
+ acquire();
+}
+.P2
+The important thing to note is that in common with all builtin
+functions which must perform some kernel function
+\fISys_read\fR releases the interpreter before carrying out
+its task and then acquires it again before returning to
+the body of the \fImcall\fR operation.
+Releasing the interpreter means removing this Dis thread
+from the list of threads to be run and making ready
+another virtual machine from the list of kernel processes
+waiting to use the interpreter, if necessary by first creating a new
+one.
+Once the interpreter has been released the process carries
+out its operation, in this case a call to \fIkread\fR,
+and then attempts to reacquire the interpreter.
+If no other process is using the interpreter it will get it back
+immediately, otherwise the process sets its state to \fIQueueing\fR
+and calls
+.CW sched()
+to wait for its turn.
+How long it has to wait depends on how many other threads are running and
+whether they are compiled or interpreted.
+If another process wants to use the interpreter then it may run
+for a short period of time before making a call to \fIrungc()\fR
+to perform
+a small amount of garbage collection
+and then yielding control to our process.
+If the other process is running an interpreted thread then it may execute
+for up to 2048 Dis instructions or for a more variable time if
+it is a compiled thread.
+We can see the likely effect of this by timing calls to \fIrungc\fR.
+The following code does this inside \fIdevbench\fR\(dg:
+.FS
+.vs 9
+.FA
+\(dg This benchmark is called
+.CW GCSCHED
+in the \fIdevbench\fR benchmark suite.
+.FE
+.P1
+log("GCSCHED:1d:Observation:n:Time:us");
+for(i=0; i<1000; i++) {
+ (*ts)(&t0);
+ rungc(head);
+ (*ts)(&t1);
+ log(" %.2f", ts2us(t1-t0));
+ release();
+ acquire();
+}
+log("\\n");
+.P2
+The calls to
+.CW release()
+and
+.CW acquire()
+allow other Dis threads to run and so exercise the memory allocation
+code in much the same way that the same calls in
+.CW tstamp()
+do.
+On each call to
+.CW rungc()
+the garbage collector visits 50 blocks in the heap.
+The times for 1000 calls to rungc are shown in Figure 5.
+.KF
+.G1
+copy "x9gc.gr"
+.G2
+.I "Figure 5. Times for 1000 calls to rungc()."
+.KE
+Running
+.P1
+cat results | bcut 1-201 | plot
+.P2
+will give us just the first 200 data points in a little more detail,
+these are shown in Figure 6.
+.KF
+.G1
+copy "x9gc200.gr"
+.G2
+.I "Figure 6. Times for the first 200 calls to rungc()."
+.KE
+We can see that the time for calls to rungc has a very repeatable pattern,
+but there is no sign of the large 6 millisecond delay.
+.LP
+Garbage collection is also done during idle virtual machine cycles.
+If no thread is ready to run the interpreter calls
+.CW execatidle()
+and then sleeps until there is something to do.
+.CW Execatidle()
+attempts to complete 3 epochs of garbage collection, checking
+after each call to
+.CW rungc()
+to see if any thread is ready to run; if a thread is ready, normal interpretation
+is resumed immediately.
+.KS
+The following code in \fIdevbench\fR is used to determine
+how long it might take the garbage collector to run 3 epochs\(dg:
+.P1
+int
+idlegc(void *p)
+{
+ int done;
+ Prog *head;
+ vlong t0, t1, tot;
+ USED(p);
+
+ head = progn(0); /* isched.head */
+ done = gccolor + 3;
+ tot = 0;
+ while(gccolor < done && gcruns()) {
+ if(tready(nil))
+ break;
+ (*ts)(&t0);
+ rungc(head);
+ (*ts)(&t1);
+ tot += t1-t0;
+ }
+ log(" %.2f", ts2us(tot));
+ nidle--;
+ if(nidle == 0) {
+ log("\n");
+ return 1;
+ }
+ return 0;
+}
+.P2
+.KE
+.FS
+.vs 9
+.FA
+\(dg This benchmark is called
+.CW GCIDLE
+in the \fIdevbench\fR benchmark suite.
+.FE
+The code is invoked by assigning 100 to
+.CW nidle
+and then calling
+.P1
+atidle(idlegc, 0);
+.P2
+so that the interpreter will call this code when idle
+in the same way that it calls the normal garbage collection code.
+.KS
+The function
+.CW tready()
+is defined as
+.P1
+tready(void *a)
+{
+ return isched.runhd != nil || isched.yield != 0;
+}
+.P2
+.KE
+returning \fItrue\fR whenever there is a thread in the run queue
+or when another interpreter kernel process has called \fIacquire()\fR
+to request that control of the interpreter be \fIyielded\fR to it.
+In fact, the code mirrors the garbage collection code in the interpreter,
+breaking when another thread is ready to be run.
+.KF
+.G1
+copy "x31.gr"
+.G2
+.I "Figure 7. Times for performing three epochs of garbage collection."
+.KE
+.LP
+Figure 7 shows the times for performing three epochs of garbage collection.
+It is clear from these results that idle garbage collection can take
+some considerable time even when the system is relatively quiet.
+The times for completing 3 epochs of garbage collection
+were of the same order of magnitude as the large delays we were
+noticing with the timestamping earlier.
+However, the system is clearly designed to relinquish control
+whenever another thread needs to run.
+It was not, therefore, clear that this could be the cause of these delays.
+.SH
+An Explanation
+.LP
+Clock interrupts happen on this system at regular intervals
+of 10 milliseconds.
+At each such interrupt the handler checks to see if any
+kernel processes are ready to run, and if so it calls \fIsched\fR.
+This gives the system its preemptive scheduling.
+Suppose we are executing a call to
+.CW sys->read().
+If after calling \fIrelease\fR but before returning
+from the call to \fIkread\fR and calling \fIacquire\fR a clock interrupt goes off
+then another process may grab the interpreter and complete a scheduler
+quantum.
+If no other threads are ready to run
+because, like us, they are still in the kernel then
+.CW tready()
+will return \fIfalse\fR
+and so it will choose to perform idle garbage collection.
+There is an upper bound on how long this may go on for;
+it is the minimum of the time it takes to perform three epochs
+of garbage collection and the time to the next clock interrupt
+which may be as much as 10 milliseconds.
+This would give rise to the periodic high values we have seen
+and would likely result in delays of the same order of magnitude
+as those that we have seen.
+.LP
+One way to check this hypothesis would be to modify the condition
+upon which the idle garbage collection is halted to include a test
+for kernel processes that are ready to run.
+.KS
+The existing code in the function \fIport/dis.c:execatidle()\fR breaks
+from the process of garbage collection only when another interpreter
+requests control or when another thread is ready to run.
+.P1
+done = gccolor+3;
+while(gccolor < done && gcruns()) {
+ if(isched.yield != 0 || isched.runhd != isched.runtl)
+ break;
+
+ rungc(isched.head);
+}
+.P2
+.KE
+The result of this is that when a thread makes a call that takes
+it into the kernel it is effectively given a lower priority than the idle time
+garbage collection. This effect can only be seen if a clock interrupt happens
+which results in control being switched to an interpreter thread which completes
+its execution quantum and enters idle time garbage collection. Ordinarily,
+a thread in the kernel will either run to completion or will, itself, call
+.CW sched()
+while waiting for an event to occur.
+.LP
+This effect will be visible in any Inferno thread that makes a call to a system
+function which then results in a \fIrelease\fR of the interpreter - not
+just this benchmarking application.
+.SH
+Improving the Results
+.LP
+We have changed the code in \fIexecatidle\fR to call \fIsched\fR
+on detection of
+ready kernel processes.
+.KS
+It now looks like this:\(dg
+.P1
+done = gccolor+3;
+while(gccolor < done && gcruns()) {
+ if(isched.yield != 0 || isched.runhd != isched.runtl)
+ break;
+ rungc(isched.head);
+ sched();
+}
+.P2
+.KE
+.FS
+.vs 9
+.FA
+\(dg A first attempt checked the number of processes ready
+to run, making the call to
+.I sched
+conditional, but that did not correctly account for their priorities
+relative to the process running the collector.
+.FE
+Processes in the kernel running at the
+same priority as the collector are interleaved with the collector.
+If such a process returns from a
+kernel operation and attempts to \fIacquire\fR the interpreter then
+this loop will exit the next time around because
+.CW isched.yield
+will be set.
+Kernel processes which do not require the interpreter,
+such as the network timers, will get to run without interrupting
+the garbage collection.
+The effect of this change can be, readily, seen in much smaller delays
+shown in Figure 8.
+.KF
+.G1
+copy "x27base.gr"
+.G2
+.I "Figure 8. Improved results from idle garbage collection change"
+.KE
+The large 6 millisecond delays have disappeared but regular 1 millisecond
+delays still remain. Looking more closely at the first 200
+times, in Figure 9, we can see that the pattern looks very similar to the pattern
+we know that we get from repeatedly calling \fIrungc()\fR.
+.KF
+.G1
+copy "x27base200.gr"
+.G2
+.I "Figure 9. Improved results from idle garbage collection change - \
+the first 200 values"
+.KE
+Indeed, this is most likely the cause of the regular pattern.
+The call to \fIrungc\fR after completing each quantum of scheduler
+activity results in quite a variable delay which means that the real
+time taken in executing
+.CW tstamp()
+will be difficult to predict.
+This will be true for any Limbo function that calls a system builtin
+which in turn releases the interpreter.
+.LP
+I suspect that the single large delay will occur when the garbage
+collector completes an epoch and runs through marking each
+root as a propagator.
+There may be ways to improve the situation by smoothing this operation,
+perhaps by making it incremental or by temporarily disabling garbage
+collection or by optimising the conditions under which garbage collection
+is done.
+However, garbage collection has to be done sometime, and it is not
+clear that, in general, deferring it is always the best thing to do - we may get good
+results when the system is quiet but very bad results when garbage
+collection is required.
+It would seem likely that there may have been some work done on this aspect
+of the virtual machine in later incarnations of the Inferno system.
+.LP
+There are two ways forward. We could accept that garbage collection
+is an integral part of the system and not try to measure small units
+of time - instead, we could measure the time for a lot of operations
+and average them out and then subtract the known garbage collection
+background count from the overall time to get a feel for how much time
+taken performing our operation of interest.
+There are several problems with this approach.
+Firstly, it seems unreasonable not to be able to
+measure something small with Inferno; frustrating too, when the problem
+is caused by a visually regular disturbance.
+Secondly, measuring something over a long period of time gives
+ample opportunity for other factors to interfere with the operation
+of interest (for example, interrupts from external interfaces).
+.LP
+The second way forward is to modify our measurement process so that
+its interaction with the virtual machine is minimised in such a way that
+it can be used more predictably and, hence, is more reliable.
+We did this by providing a builtin function
+.CW bench->microsec()
+and by providing an interface which allowed garbage collection to be
+disabled for a period of time.
+.KS
+The Limbo module prototype looks like this:
+.P1
+{
+ PATH: con "$Bench";
+
+ microsec: fn(): big;
+ disablegc: fn();
+ enablegc: fn();
+};
+.P2
+.KE
+.KS
+and the Limbo function to return a timestamp just calls the builtin.
+.P1
+xstamp(): big
+{
+ return bench->microsec();
+}
+.P2
+.KE
+Using \fIxstamp()\fR in place of \fItstamp()\fR
+without disabling garbage collection results in a significant
+improvement to the times returned by the
+.CW BASE
+benchmark\(dg.
+These results are shown in Figure 10.
+.FS
+.vs 9
+.FA
+\(dg The kernel used to make this recording (and all subsequent in this document)
+has had the modifications made to the idle garbage collection code
+described earlier. We found that switching to using a builtin with the
+old kernel did result in much better times but could still occasionally
+fall foul of a clock interrupt.
+.FE
+.KF
+.G1
+copy "x28base.gr"
+.G2
+.I "Figure 10. Further improvement by using a builtin timestamp."
+.KE
+I suspect that the few large values are as a result of external interrupts
+or scheduler quantum garbage collection.
+The distribution of these values is shown in Figure 11.
+.KF
+.G1
+copy "x28basehd.gr"
+.G2
+.I "Figure 11. The distribution of the results shown in Figure 10"
+.KE
+Out of the 1000 measurements all but 6 of them were
+recorded at 6 microseconds.
+.KS
+.LP
+By wrapping the entire benchmark with calls to
+.P1
+bench->disablegc()
+.P2
+and
+.P1
+bench->enablegc()
+.P2
+which disable and then reenable all garbage collection
+the figures can be improved even further.
+.KE
+.KF
+.G1
+copy "x29basehd.gr"
+.G2
+.I "Figure 12. The distribution of results obtained when garbage collection \
+is completely disabled."
+.KE
+The histogram of timestamps obtained when garbage collection
+is completely disabled is shown in Figure 12.
+It is clear that the values we are now getting
+from \fIxstamp()\fR are much more acceptable.
+Out of the 1000 measurements, five were recorded at 12 microseconds,
+one at 8 microseconds and the remainder at either 6 or 7 microseconds.
+.BP
+.SH
+Conclusion
+.LP
+Comparing the histogram for the original measurements
+with the one obtained by making a simple change to
+the interpreter and by using a builtin instead of using
+.CW sys->read()
+it is clear that considerable improvements have been made.
+This behaviour will be visible in any Inferno thread that makes a
+call to a system function which, in turn, causes the interpreter
+to be released. These effects will be present in any Inferno application
+that uses, for example,
+.CW "sys->read(), sys->write(), sys->mount()"
+and
+.CW "sys->bind()"
+or any other such builtin system functions.
+.LP
+The decision to enable or disable garbage collection whilst benchmarking
+is a difficult one.
+Disabling it results in slightly better measurement, but is somewhat less realistic.
+The improvement gained by disabling it doesn't seem good enough to
+justify the likely criticism which might be levelled at the subsequent results.
+.LP
+It would appear that to enable reliable benchmarking
+of Limbo programs under Inferno two changes should be applied.
+Firstly, a simple change should be made to the interpreter to prevent idle
+garbage collection from grabbing a large time slot when scheduling
+occurs at a clock interrupt
+and one or more interpreter threads are in kernel operations.
+Secondly, making the timestamp function a builtin
+results in a simpler interface to the kernel and results in
+a measurement process whose execution time is reliable.
+Applied together, these changes make it possible to perform
+reliable benchmarking of Limbo programs under Inferno.
binary files /dev/null b/doc/perform/perform.pdf differ
--- /dev/null
+++ b/doc/port.ms
@@ -1,0 +1,590 @@
+.TL
+Inferno Ports: Hosted and Native
+.AU
+Vita Nuova
+27 April 2005
+Revised 22 January 2007
+.PP
+Inferno is a portable environment, encompassing operating system,
+languages, virtual machine and the tools required to build it.
+This section briefly summarises the state of the ports and compilers
+included in this release.
+Directory names are relative to the root of the Inferno release tree,
+unless otherwise specified by the context.
+.PP
+All components are built using the program
+.CW mk ,
+based on `make'-like recipes found in the
+.CW mkfile
+in each source directory throughout the Inferno tree.
+.CW Mk
+is described by the manual page
+.I mk (10.1)
+in Volume 1; a more tutorial discussion, including
+a summary of differences with Unix
+.I make ,
+can be found in
+.I "Maintaining Files on Plan 9 with Mk"
+by Hume and Flandrena,
+reprinted in this volume.
+The source for
+.CW mk
+itself is included in
+.CW utils/mk .
+It is included ready-made in the full and source-only distributions, to make life easier.
+It must be compiled manually only on the initial port to a new host environment;
+instructions for that are given below.
+.PP
+.NH 1
+The C compilers
+.PP
+An unusual property of the compiler suites used to compile native
+Inferno is that there is no difference in configuration or content
+between a `compiler' (compiling on the same system and processor type as the target)
+and a `cross compiler' (compiling on a host that differs from the target),
+even when the host operating systems are quite different.
+Indeed, in their ancestral home, Plan 9, it is the default action to compile
+instances of all compilers for all possible target architectures,
+as a matter of course.
+.PP
+The main difference between this suite and the original Plan 9 suite is
+that all Plan 9 C extensions have been eliminated from the compiler's own source,
+allowing it to be compiled on environments that accurately support
+ANSI C and a few necessary Posix functions.
+.PP
+The source for the compilers is found in subdirectories of
+.CW utils .
+The compilers are named as follows:
+.RS
+.IP \f50c\fP 8
+MIPS compiler for 64-bit little-endian R4000 MIPS (or `\f5spim\fP')
+.IP \f51c\fP
+68000 compiler, usable with the Motorola Dragonball
+.IP \f52c\fP
+680x0 compiler for x >= 2
+.IP \f55c\fP
+ARM compiler
+.IP \f56c\fP
+AMD64
+.IP \f58c\fP
+Intel x86 compiler, for x>2
+.IP \f5kc\fP
+Sun SPARC compiler
+.IP \f5qc\fP
+PowerPC compiler
+.IP \f5vc\fP
+MIPS R[234]000 in 32-bit big-endian mode
+.RE
+.LP
+The compilers share components, compiled into a library from
+source in the directory
+.CW utils/cc .
+The corresponding assemblers and linkers are found in similarly
+named directories:
+.CW 2a
+and
+.CW 2l
+are the assembler and linker for use with
+.CW 2c
+for instance.
+Note that this suite is unusual in that the compilers and assemblers produce
+a binary assembly language that is finally converted to machine code
+by the linker.
+The assembler is used only to write machine-language assist for the operating
+system, or a run-time routines using instructions not accessible from C,
+and is not used by the compiler.
+See the paper ``Plan 9 C compilers'' by Ken Thompson,
+reprinted in this volume.
+.PP
+With the exception of the 68000 compiler, all the compilers have been
+used extensively to compile Inferno, and most have been used
+to compile Plan 9 and all its applications; and we have found them solid.
+The 68000 compiler was used to attempt a port of Inferno to the Motorola
+Dragonball (in the Palm Pilot).
+It is included here in case someone wishes to have another go.
+We have no experience with it.
+.PP
+The ARM compiler
+.CW 5c
+supports the ARM (Strongarm, PXA) architecture;
+the related compiler
+.CW tc
+generates ARM's Thumb instructions instead.
+The output of both can be linked together by the ARM loader
+.CW 5l
+to achieve ARM-Thumb interworking.
+.CW 5c
+has been used to generate code for the StrongARM SA110 and SA1100
+processors (the primary
+targets for native Inferno for many years).
+The code generated was greatly improved by Richard Miller.
+The floating-point support is adequate for C programs: the compiler
+generates ARM floating-point instructions, as implemented on the ARM7500 but
+not on the Strongarm, where they must be emulated.
+.PP
+The PowerPC compiler supports the 32-bit PowerPC architecture only;
+it does not support either the 64-bit extensions or the POWER compatibility instructions.
+It has been used for production operating system work on the 405EP, 603, 70x, 821, 823, and 860.
+On the embedded processors such as 405 and 8xx floating-point instructions must be emulated.
+Instruction scheduling is not implemented; otherwise the code generated
+is similar to that for the other load-store architectures.
+The compiler makes little or no use of unusual PowerPC features such as the
+counter register, several condition code registers, and multiply-accumulate
+instructions, but they are sometimes
+used by assembly language routines in the libraries.
+The compiler does replace explicit comparisons by condition-setting instructions.
+Its run-time conventions are more efficient than those of the PowerPC ABI.
+.NH 1
+Applications
+.PP
+Dis object files are portable across all variants of Inferno, hosted and native.
+There need be only one copy of the Dis files to serve many different
+versions of Inferno; they need not be rebuilt for each platform
+and can be shared by different types of host.
+Limbo insulates the programmer from all details of
+the particular processor, including byte-ordering,
+and consequently the applications themselves are portable.
+.PP
+The source for the applications is found in subdirectories of
+.CW appl :
+.CW appl/cmd
+holds the source for most command line applications (that use no graphics);
+.CW appl/wm
+contains the source for most applications that run under
+.I wm (1);
+.CW appl/svc
+contains the source for various system services and file servers;
+.CW appl/mux ,
+the source for the interactive television demo
+.I mux (1);
+.CW appl/charon ,
+the source for the Charon web browser; and
+.CW appl/acme
+the source for Acme written in Limbo.
+.PP
+The
+.CW mkfile
+in each directory can currently only be used by an instance of
+.CW mk
+running
+.I outside
+the Inferno environment, under the host operating system.
+This complicates its use with
+.I acme (1),
+normally requiring the use of the
+.I os (1)
+command.
+In a few cases, there is a
+.CW mashfile
+that can be used by
+.I mash-make (1)
+to build a Limbo application from within Inferno (native or hosted).
+A consistent approach to building applications both inside and outside
+Inferno is being developed.
+In any case, the resulting Dis files are portable once produced.
+.NH 1
+Hosted Inferno (emu)
+.PP
+There are currently four main variants of hosted Inferno: Plan 9, Unix (and clones), MacOS X and Windows.
+The source is held in directory
+.CW emu ,
+with a subdirectory for each hosted platform:
+.CW FreeBSD ,
+.CW Irix ,
+.CW Linux ,
+.CW MacOSX ,
+.CW NetBSD ,
+.CW Nt
+(for all Windows platforms, including the Internet Explorer plug-in),
+.CW Plan9 ,
+.CW Solaris ,
+and so on.
+Each platform directory has a
+.CW mkfile
+and one or more configuration files of the form described by
+.I config (6).
+An executable for a particular host type is built on that host type,
+using the host's own command interpreter, not under Inferno.
+Move to the
+.CW emu
+subdirectory appropriate to that host,
+ensure the command interpreter's path variable includes
+the directory containing the Inferno
+.CW bin
+directory for that host
+(eg,
+.CW /home/inferno/Solaris/sparc/bin ),
+and run
+.CW mk .
+.PP
+Like the native kernels
+.CW emu
+relies on several auxiliary libraries (the source of which
+it often shares with the native kernels).
+Emu itself is built by the
+.CW mkfile
+in the
+.CW emu
+subdirectory containing the platform-specific source for the host platform.
+Each library has its own
+.CW mkfile ;
+the various components are made in the right order by the
+.CW mkfile
+at the root of the Inferno tree.
+The
+.CW mkfile
+for each platform will also invoke
+.CW mk
+recursively to make the appropriate libraries
+for a given configuration.
+.PP
+The Unix emu variant generally is covered by `POSIX' (with common extensions)
+but each Unix port has one file that differs considerably for each port,
+namely \f5emu/\fP\fIplatform\fP\f5/os.c\fP, the differences
+corresponding to the different ways under Unix of implementing kernel-scheduled
+threads efficiently.
+.PP
+There are working emu versions
+for
+FreeBSD/386,
+Irix/mips,
+Linux/386,
+NetBSD/386,
+MacOSX/386,
+MacOSX/power,
+Plan 9,
+Solaris/sparc,
+and Windows (NT, 2000 and Explorer plug-in).
+Each platform typically uses mechanisms specific to the host operating
+system to implement Inferno's internal thread/process structure.
+POSIX threads have often been found to be insufficient (poorly implemented)
+on some platforms, and if so are avoided.
+See
+.CW kproc
+in
+.CW emu/*/os.c .
+.PP
+Source is included for ports to HP/UX (S800 architecture),
+Solaris/386, and Unixware, in case someone wishes to take them up now,
+but we have not determined their fitness.
+.PP
+The Plan 9 hosted implementation is unusual in that it supports
+several processor types:
+.CW 386 ,
+.CW mips ,
+.CW power
+(Power PC)
+and
+.CW sparc .
+Furthermore, all versions of
+.CW emu
+can be built on any processor type, in the usual way for Plan 9.
+.PP
+Otherwise, as distributed,
+.CW emu
+for a platform can only be built when running on that platform.
+.PP
+One unusual variant makes the whole of Inferno a plug-in for Microsoft's
+Internet Explorer, giving the same environment for Inferno applications
+running in an HTML page as is provided by hosted or native Inferno.
+That is, there is not a distinct `applet' environment with special programming interfaces.
+The source for the various plug-in components is found in
+.CW /tools/plugin
+and
+.CW /usr/internet
+within the Inferno tree; they use the version of
+.I emu
+defined by the configuration file
+.CW /emu/Nt/ie .
+.PP
+All the libraries and executables can be built in a tree containing only the source code.
+To do that for a supported variant of hosted Inferno, on Unix or Plan 9, do the following
+in the root of the Inferno tree:
+.nr Ci 0 +1
+.de Xx
+.IP \\n+(Ci
+..
+.Xx
+Edit
+.CW mkconfig
+to reflect your host environment,
+specifically ROOT (which must be an absolute path name), SYSHOST and OBJTYPE.
+The comments in the file should help you choose.
+.Xx
+Run
+.CW makemk.sh
+to rebuild the
+.CW mk
+command, which is used to build everything else.
+.Xx
+Set
+.CW PATH
+(or
+.CW path
+on Plan 9)
+to include the
+.CW bin
+directory for the platform, which will now contain the
+.CW mk
+binary just built.
+On Unix, export
+.CW PATH .
+.Xx
+Then
+.CW "mk nuke"
+to remove any extraneous object files.
+.Xx
+Finally,
+.CW "mk install"
+to create and install the libraries,
+.CW limbo
+compiler,
+.CW emu
+for hosted Inferno, and auxiliary commands.
+The rules do that in an order that ensures that the commands or libraries
+needed by a later stage are built and installed first.
+(Note that a plain
+.CW mk
+will not suffice, because it does not put the results in the search path.)
+.LP
+Doing something similar on Windows or Plan 9 currently requires the executable for
+.CW mk
+to be available in the search path,
+since there is no equivalent of
+.CW makemk.sh .
+Otherwise the procedure is the same.
+On Plan 9, of course, the host system's normal version of
+.CW mk
+should be adequate.
+.NH 1
+Native Inferno
+.PP
+As with the different versions of emu, once the native kernel is running, all applications
+work straight away;
+the same applications are used in native and emulated mode, subject to
+suitable devices being available.
+Because the portable compiler suite is used to compile native kernels,
+and those compilers are automatically cross-compilers, all native Inferno
+implementations can be built on any host platform.
+Furthermore, the build procedures and resulting object files are the same.
+.PP
+Early ports in 1996 were made by Bell Labs to an internal device based on
+the AMD 29000, an early ARM-based `network computer', and Intel-based PCs.
+Between 1997 and 1999, Lucent concentrated mainly on the Strongarm platform
+(SA1100), for various Digital/Intel development boards,
+and especially several `web phones', including the Sword Webphone Reference Design.
+It also undertook ports to other devices for experiment, or under contract.
+.PP
+Vita Nuova Limited also ported the system, both for its own purposes
+and under contract to Lucent.
+Targets included a small 386-based Internet device,
+a set top Internet box using the PowerPC 603e,
+a digital television set top box with a Strongarm SA110 and a Teralogic TL750 graphics chip,
+the USR/3Com Edgeserver (in a chassis containing various types of line card),
+various boards based on the PowerPC 823/821/860,
+many different configurations of IBM PC,
+and a Ziatech Pentium-based VME crate.
+.PP
+Distribution of most previous and existing ports is restricted by
+the terms on which they were undertaken,
+or because they were ports of older Inferno releases and not kept up to date.
+We have included the following as examples in this distribution.
+.SH
+The StrongARM kernel
+.PP
+The source for the StrongARM kernels is split across several directories.
+The directory
+.CW os/sa1110
+contains all code that is generally architecture-specific but platform-independent.
+Other directories contain platform-specific code:
+.CW os/cerf1110
+for the Intrinsyc Cerfcube1110,
+and
+.CW os/ipaq1110
+for the Compaq (as it then was) IPAQ H3650.
+Earlier Webphone ports are tied to hardware that is not generally obtainable
+and the ports to those
+platforms included some software (notably modem software)
+that cannot generally be distributed.
+.PP
+There is also a preliminary port to the ARM-based Intel XScale.
+The code common to PXA implementations is in
+.CW os/pxa .
+The initial platform was the Intrinsyc Cerfboard 250; its code is in
+.CW os/cerf250 .
+A port to the Gumstix (see
+.CW www.gumstix.com )
+is in progress.
+.PP
+The platform's own bootstrap is used in all cases.
+On the IPAQ, the Linux bootloader from Compaq (HP) Research must
+be loaded onto the device first, following instructions given at
+.CW www.handhelds.org .
+See the
+.CW README
+file in each
+.CW os
+source directory for details.
+.PP
+Other ARM-based processors to which Inferno has been ported include
+the ARM-7 evaluator kit (see
+.CW os/ks32 ),
+although its memory is tight,
+and the TI925 including the TI OMAP.
+The latter two ports were to proprietary TI925 implementations, and have not
+been included, but there is a body of code common to all such platforms that
+could be made available if that were useful.
+.SH
+The PowerPC kernel
+.PP
+The directory
+.CW os/fads
+contains the port of Inferno to the MPC8xx FADS development board.
+It has been used with the MPC821, MPC823 and MPC860 processors.
+It uses code common to MPC8xx processors, found in
+.CW os/mpc .
+The interface to the CPM is provided by
+.CW cpm.c .
+There are drivers for the real time clock,
+flash devices (including a Flash Translation Layer driver),
+and communications controllers in Ethernet,
+UART, and IrDA mode
+(see
+.CW etherscc.c
+and
+.CW devuart.c ).
+The IrDA has been used for 9P transport between a FADS board
+and an IBM Thinkpad 560.
+The file
+.CW screen.c
+drives an 8-bit per pixel LCD (TFT) display panel.
+A sample interface to the on-chip video device of the MPC823 (only)
+as wired on the FADS board using auxiliary chips can be found in
+.CW devvid.c .
+The York Electronics Centre developed a touch panel for us,
+connected using SPI;
+the driver is
+.CW devtouch.c ,
+and could be adapted for similar devices.
+.PP
+The bootstrap program for the FADS board is in
+.CW os/boot/mpc ,
+loosely derived from an older version of
+.CW os/boot/pc .
+It is initially converted to S records that are loaded into flash by MPC8BUG
+from a PC, and thereafter the images of the boot and kernel images can
+be updated using the flash devices provided by the system itself,
+and the utility programs
+.CW qconfig.b
+and
+.CW qflash.b
+in
+.CW appl/cmd/mpc .
+.PP
+Another port is to the Brightstar Engineering ip-Engine containing an MPC823
+and an Altera FPGA.
+See
+.CW os/ipengine .
+It uses common code from
+.CW os/mpc .
+The device driver that loads the FPGA is in
+.CW devfpga.c ;
+see
+.I fpga (3)
+for the interface and
+.I fpgaload (8)
+for a command to do it.
+See the
+.CW README
+file for information on loading the kernel into the flash.
+.PP
+The most recent PowerPC port is to the IBM 405EP, and more specifically
+to the Intrinsyc Cerfcube 405EP.
+The source for that port is in
+.CW os/cerf405 ;
+lacking another 405EP platform for reference, the source code has not yet
+been split into that common to all 405EP implementations and that specific
+to the Cerfcube, although that would be easy to do.
+.SH
+The x86 kernel
+.PP
+The
+.CW os/pc
+directory contains the components for ports to 386, 486 and Pentium class machines.
+The main difficulty is device support: in particular
+only a limited set of Ethernet and graphics cards is supported.
+We have used mainly the 3Com and Intel 82557 drivers.
+A `generic' PC port is included that has a graphics driver that
+should run on systems that provide a VESA BIOS mode.
+.PP
+We have a (slow) floating-point emulator for the 386 found in
+.CW os/pc/fpi387.c ;
+code to invoke it in trap can be provided on request.
+.PP
+The source for the PC bootstrap program
+.CW 9load
+is in
+.CW os/boot/pc .
+It is simply a copy of the current Plan 9 PC bootstrap program, with slight modifications
+to allow it to be compiled on many host systems.
+.SH
+The Javastation 1 kernel
+.PP
+The directory
+.CW os/js
+has the first port
+to the Sun Javastation 1.
+It was done by Tad Hunt and Eric Van Hensbergen
+in a matter of days to demonstrate Inferno at Java One in 1997.
+It boots over the net using TFTP.
+Javastations being a bit thin on the ground now,
+it is unlikely to be directly usable unless you can find one second hand
+(you might find a Javastation 2 coffee pot, but that is slightly different again).
+That is a pity, because the machine was quite usable running Inferno and
+Limbo applications, often surprising those used to the Java-based
+offering on the same platform.
+It is included as an example of a micro-SPARC port.
+Beware that
+.CW screen.c
+has not yet been converted for Fourth Edition graphics
+(partly because we no longer have a suitable device for testing).
+.NH 1
+Supporting tools
+.PP
+The
+.CW utils
+directory also contains ANSI C versions of other components of the
+Plan 9 development suite,
+such as
+.CW nm ,
+.CW ksize ,
+.CW ar ,
+and of course
+the
+.CW acid
+debugger.
+Most rely on
+.CW libmach ,
+a suite of functions forming a
+library to handle the various object and executable files in one place.
+.PP
+Some other utilities give a portable
+way to express some of the kernel build scripts:
+.CW sed ,
+.CW test ,
+.CW rm ,
+and
+.CW mkdir .
+On Plan 9,
+.CW mk
+and kernel build scripts use Plan 9's own shell,
+.I rc .
+On Unix systems, they use
+.I sh .
+On Windows, a version of Plan 9's
+.I rc
+has been ported to reduce the number of variants
+to two, and keep the system self-contained; its source is in
+.CW utils/rcsh
+and installs as
+.CW rcsh.exe .
binary files /dev/null b/doc/port.pdf differ
--- /dev/null
+++ b/doc/realinferno/mkfile
@@ -1,0 +1,12 @@
+<../fonts.pal
+
+real.ps:D: real.ms real.ref
+ {echo $FONTS; eqn real.ms} | troff -mpm | dpost >$target
+
+real.ref:D: real.ms
+ {echo $FONTS; eqn real.ms} | troff -rZ1 -mpm >/dev/null >[2]real.tmp
+ {echo .rm ]C; echo .de ]C; sed 's/(.*) (.*)/.if "\\\\$1"\1" .nr ]R \2/'; echo '[\\n(]R]'; echo ..} <real.tmp >real.ref
+ rm -f real.tmp
+
+clean:N:
+ rm -f real.ref
--- /dev/null
+++ b/doc/realinferno/real.ms
@@ -1,0 +1,611 @@
+.FP palatino
+.de ]C
+\&[\\$1]\\$2
+..
+.if \nZ=0 .so real.ref
+.EQ
+delim $$
+.EN
+.TL
+Real Inferno
+.AU
+.I "Eric Grosse"
+.AI
+.I "Lucent Technologies, Bell Labs"
+.I "Murray Hill NJ 07974 USA"
+.I "ehg@bell-labs.com"
+.\"date{19 Aug 1996, minor revisions 7 Jan 1998}
+.FS
+Previously appeared in R.F. Boisvert (editor),
+.ft I
+The Quality of Numerical Software: Assessment and
+Enhancement: Proceedings of the IFIP TC2/WG2.5
+Working Conference on the Quality of Numerical
+Software, Oxford,
+United Kingdom, 8-12 July 1996,
+.ft R
+Chapman Hall,
+London,
+1997 (pp. 270-279).
+.FE
+.AB
+Inferno is an operating system well suited to applications that need to be
+portable, graphical, and networked. This paper describes the fundamental
+floating point facilities of the system, including: tight rules on
+expression evaluation, binary/decimal conversion, exceptions and rounding,
+and the elementary function library.
+.AE
+.PP
+Although the focus of Inferno is interactive media, its portability across
+hardware and operating platforms, its relative simplicity, and its strength
+in distributed computing make it attractive for advanced scientific
+computing as well. Since the appearance of a new operating system is a
+relatively uncommon event, this is a special opportunity for numerical
+analysts to voice their opinion about what fundamental facilities they need.
+The purpose of this short paper is to describe numerical aspects of the
+initial release of Inferno, and to invite comment before the tyranny of
+backward compatibility makes changes impossible.
+.PP
+An overview of Inferno is given by Dorward et. al.
+.]C "Inferno" ,
+but for our immediate purposes it may suffice to say that Inferno plays the
+role of a traditional operating system (with compilers, process control,
+networking, graphics, and so on) but can run either on bare hardware or on
+top of another operating system like Windows95 or Unix. Programs for
+.I "Inferno"
+are written in the language
+.I "Limbo"
+and compiled to
+machine-independent object files for the
+.I "Dis"
+virtual
+machine, which is then implemented with runtime compilation for best
+performance. Files are accessible over networks using the
+.I "Styx"
+protocol; together with the presentation of most system resources as files
+and the manipulation of file namespaces, this permits integration of a
+collection of machines into a team. Limbo looks somewhat like a mixture of C
+and Pascal, augmented by modules (to cope with the namespace and dynamic
+loading needs of large programs) and by a channel facility for convenient
+(coarse-grain) parallel programing. Array references are bounds-checked and
+memory is garbage collected.
+.PP
+The rest of this paper covers the fundamental floating point environment
+provided by the Limbo compiler and
+.I "math"
+module, the ``elementary
+functions,'' and finally some comments on why particular definitions were
+chosen or why certain facilities were included or excluded. This discussion
+assumes the reader is familiar with scientific computing in general and the
+IEEE floating point standard in particular.
+.NH 1
+Floating point
+.PP
+In Limbo, arithmetic on literal and named constants is evaluated at compile
+time with all exceptions ignored. Arithmetic on variables is left by the
+compiler to runtime, even if data path analysis shows the value to be a
+compile time constant. This implies that tools generating Limbo source must
+do their own simplification, and not expect the compiler to change $x/x$
+into $1$, or $-(y-x)$ into $x-y$, or even $x-0$ into $x$. Negation $-x$
+changes the sign of $x$; note that this not the same as $0-x$ if $x=0$.
+.PP
+The compiler may perform subexpression elimination and other forms of code
+motion, but not across calls to the mode and status functions. It respects
+parentheses. The evaluation order of $a+b+c$ follows the parse tree and is
+therefore the same as for $(a+b)+c$. These are the same rules as for Fortran
+and C.
+.PP
+Contracted multiply-add instructions (with a single rounding) are not
+generated by the compiler, though they may be used in the native
+.SM BLAS
+libraries. All arithmetic follows the IEEE floating point standard
+.]C "IEEEfp" ,
+except that denormalized numbers may not be supported; see the
+discussion in section 3.
+.PP
+The most important numerical development at the language level recently has
+been accurate binary/decimal conversion
+.]C "Clinger"
+.]C "Gay"
+.]C "SteeleWhite" .
+Thus printing a real using
+.CW "\%g"
+and reading
+it on a different machine guarantees recovering identical bits. (Limbo uses
+the familiar
+.I "printf"
+syntax of C, but checks argument types against
+the format string at compile time, in keeping with its attempt to help the
+programmer by stringent type checking.) A good
+.I "strtod/dtoa"
+is,
+unfortunately, 1700 lines of source (15kbytes compiled), though with modest
+average runtime penalty. This code must be used in the compiler so that
+coefficients are accurately transferred to bytecodes. Smaller, faster, but
+sloppier, runtimes will also be provided when mandated by limited memory and
+specialized use. However, programmers may assume the features described in
+this paper are present in all Inferno systems intended for general computing.
+.PP
+Each thread has a floating point control word (governing rounding mode and
+whether a particular floating point exception causes a trap) and a floating
+point status word (storing accumulated exception flags). Functions
+.I "FPcontrol"
+and
+.I "FPstatus"
+copy bits to the control or status word, in
+positions specified by a mask, returning previous values of the bits.
+.I "getFPcontrol"
+and
+.I "getFPstatus"
+return the words unchanged.
+.PP
+The constants
+.I "INVAL, ZDIV, OVFL, UNFL, INEX"
+are non-overlapping
+single-bit masks used to compose arguments or return values. They stand for
+the five IEEE exceptions:
+.IP •
+``invalid operation'' ($0/0$,$0 * infinity $,$ infinity - infinity $,$sqrt{-1}$)
+.IP •
+``division by zero'' ($1/0$),
+.IP •
+``overflow'' ($1.8e308$)
+.IP •
+``underflow'' ($1.1e-308$)
+.IP •
+``inexact'' ($.3*.3$).
+.PP
+The constants
+.I "RND_NR, RND_NINF, RND_PINF, RND_Z"
+are distinct
+bit patterns for ``round to nearest even'', ``round toward $-{infinity} $'',
+``round toward $+{infinity} $'', ``round toward $0$'', any of which can be set
+or extracted from the floating point control word using
+.I "RND_MASK" .
+For example,
+.IP •
+to arrange for the program to tolerate underflow,
+.I "FPcontrol(0,UNFL)."
+.IP •
+to check and clear the inexact flag,
+.I "FPstatus(0,INEX)."
+.IP •
+to set directed rounding,
+.I "FPcontrol(RND_PINF,RND_MASK)."
+.PP
+By default,
+.I "INEX"
+is quiet and
+.I "OVFL, UNFL, ZDIV,"
+and
+.I "INVAL"
+are fatal. By default, rounding is to nearest even, and library
+functions are entitled to assume this. Functions that wish to use quiet
+overflow, underflow, or zero-divide should either set and restore the
+control register themselves or clearly document that the caller must do so.
+The ``default'' mentioned here is what a Limbo program gets if started in a
+fresh environment. Threads inherit floating point control and status from
+their parent at the time of spawning and therefore one can spawn a ``round
+toward 0'' shell and re-run a program to effortlessly look for rounding
+instabilities in a program.
+.NH 1
+Elementary functions
+.PP
+The constants
+.I "Infinity, NaN, MachEps, Pi, Degree"
+are defined. Since
+Inferno has thorough support of Unicode, it was tempting to name these $infinity $, $ε $, $π $, and °, but people (or rather, their
+favorite text editing tools) may not be ready yet for non-\s-2ASCII\s0
+source text.
+.I "Infinity"
+and
+.I "NaN"
+are the positive infinity
+and quiet not-a-number of the IEEE standard, double precision.
+.I MachEps
+is $2 sup {-52}$, the unit in the last place of the mantissa $1.0$.
+The value of
+.I "Pi"
+is the nearest machine number to the
+mathematical value $π $.
+.I "Degree"
+is
+$"Pi" / 180$.
+.PP
+Three useful functions
+.I "fdim, fmax, fmin"
+are adopted from the
+Numerical C extensions
+.]C "NumerC" .
+The unusual one of these, often
+denoted $(x-y) sub {+}$, is defined by $roman "fdim" ( x , y )=x-y$ if $x > y$, else $0$. The compiler may turn these into efficient machine instruction sequences,
+possibly even branch-free, rather than function calls. There are two almost
+redundant mod functions:
+.I "remainder(x,y)"
+is as defined by the IEEE
+standard (with result $roman "|" r roman "|" <= y/2$);
+.I "fmod(x,y)"
+is $x roman "mod" y$,
+computed in exact arithmetic with $0<= r<y$. Limbo has a ``tuple'' type,
+which is the natural return value in the call $(i,f)= roman "modf" ( x )$ to
+break $x$ into integer and fractional parts. The function
+.I "rint"
+rounds to an integer, following the rounding mode specified in the floating
+point control word.
+.PP
+For a good-quality, freely-available elementary function library,
+.I "math"
+uses the IEEE subset of
+.I "fdlibm"
+.]C "fdlibm" .
+Of course, a
+conforming implementation may use entirely different source, but must take
+care with accuracy and with special arguments. There are the customary
+power, trigonometric, Bessel, and erf functions, and specialized versions $roman "expm1"( x )=e sup x - 1$, $roman "log1p" ( x )=log ( 1 + x )$. An additional function
+$roman "pow10"( n ) = 10 sup n$ is defined; in the default implementation this is
+just fdlibm's $roman "pow" ( 10. , n )$ but it is provided so that separate
+trade-offs of accuracy and simplicity can be made
+.]C "MacIlroy" .
+.I "fdlibm"
+uses extra precise argument reduction, so the computed $sin (n*Pi)$
+is small but nonzero. If demands warrant, degree versions of the
+trigonometric functions will be added, but for now the style $sin (45*Degree)$ is used.
+The library also provides IEEE functions
+.I "ilogb, scalbn, copysign, finite, isnan,"
+and
+.I "nextafter" .
+.PP
+The functions
+.I "dot, norm1, norm2, iamax, gemm"
+are adopted from the
+.SM BLAS
+.]C "blas"
+to get tuned linear algebra kernels for
+each architecture, possibly using extra-precise accumulators. These are
+defined by $sum {{x sub i}{y sub i}}$, $sum roman | {x sub i} roman | $, $ sqrt{sum { x sub {i sup 2}}} $, $i$ such
+that $roman | {x sub i} roman | = roman max $, and $C= alpha AB + beta C$ with optional transposes on $A$
+and $B$. Since Limbo has only one floating-point type, there is no need here
+for a precision prefix. Limbo array slices permit the calling sequences to
+be more readable than in Fortran77 or C, though restricted to unit stride.
+This encourages better cache performance anyway. The matrix multiply
+function
+.I "gemm"
+remains general stride (and is the foundation for
+other operations
+.]C "Kagstrom" ).
+.PP
+Limbo is like C in providing singly-subscripted arrays with indexing
+starting at 0. Although Limbo offers arrays of arrays, as in C, for
+scientific work a better choice is to adopt the style of linearizing
+subscripts using Fortran storage order. This promotes easier exchange of
+data with other applications and reuses effort in organizing loops to
+achieve good locality. In previous language work
+.]C "pine" ,
+we implemented
+a C preprocessor that allowed the programmer to choose a convenient origin
+(such as 1) and have it compiled into 0 for the base language; because we
+passed arrays as dope vectors, we were even able to allow different origins
+for the same array in calling and called functions. The main lesson we
+learned from that experience, however, was that permutations become a
+nightmare when there is anything but dogmatic adherence to a single origin.
+So for an $m$ by $n$ matrix $A$, the programmer should use loops with $0<=
+i<m$ and $0<= j<n$ and access $A[i+m*j]$.
+.PP
+For interoperability with foreign file formats and for saving main memory in
+selected applications, functions are provided for copying bits between and
+reals and 32-bit or 64-bit IEEE-format values.
+.PP
+Finally,
+.I "math"
+provides a tuned quicksort function
+.I "sort(x,p)"
+where
+.I "x"
+is a real array and
+.I "p"
+is an int array representing
+a 0-origin permutation. This function leaves the contents of
+.I "x"
+untouched and rearranges
+.I "p"
+so that $x[{p sub i}]<= x[p sub {i+1}]$. This is
+usually what one wants to do: sort an array of abstract data types based on
+some key, but without the need to actually swap large chunks of memory.
+.NH 1
+Rationale
+.PP
+This section discusses why certain numerical features were included or not.
+.NH 2
+Rounding modes and accumulated exceptions
+.PP
+Directed rounding is only needed in a very few places in scientific
+computing, but in those places it is indispensable. Accumulated floating
+point exceptions are even more useful. User trap handling is a harder
+problem, and may be worth leaving for later, possibly with a default
+``retrospective diagnostics'' log
+.]C "Kahan" .
+.PP
+Note that the exception masks must be architecture independent, since they
+reside in the Limbo bytecodes, and therefore the implementation involves a
+small amount of bit fiddling. Still, it is efficient enough to encourage
+use. It would be difficult to port to a processor that only had static
+rounding modes in instruction opcodes rather than the dynamic model
+specified in section 2 of the IEEE standard. Fortunately, the Alpha
+does provide both models.
+.NH 2
+Sudden underflow
+.PP
+Some processor vendors make supporting gradual underflow just too hard. (One
+must struggle upon the system trap to reconstruct exactly which instruction
+was executing and what the state of the registers was. On the MIPS, it is
+said to be 30 pages of assembler.) So Inferno supports denormalized numbers
+only if the hardware makes this easy. Providing underflow that is correct
+but very slow, as some systems do, is not necessarily doing the user a favor.
+.PP
+To determine portably if a particular system offers gradual underflow, mask
+off UNFL and do trial arithmetic.
+.NH 2
+Speed
+.PP
+Computers with slow (software) gradual underflow usually provide a fast
+flush-to-0 alternative. This often suffices, though there are important
+examples where it forces an uglier and slower coding style. A worse
+situation is if the hardware uses system traps for Infinity and NaN
+arithmetic. The resulting slowdown will make otherwise excellent and natural
+algorithms run slowly
+.]C "Demmel" .
+Sadly, even some x86 implementations
+that do non-finite arithmetic in hardware, do it relatively slowly.
+.PP
+We considered providing syntax to declare a certain program scope within
+which precise IEEE behavior was required, and relaxing the rules outside
+such scopes.
+(The numerical C extensions
+.]C "NumerC"
+use pragma
+for this purpose.)
+These scope declarations would need to be in the
+bytecodes, since significant optimization may be attempted by the runtime
+compiler. After some discussion, and with some trepidation, it was agreed
+that instead all compilers would be required to preserve the same result and
+status as for an unoptimized version.
+.NH 2
+Comparison
+.PP
+The standard C operators
+.CW ==
+.CW !=
+.CW "<"
+.CW "<="
+.CW ">"
+.CW ">="
+are the only comparisons provided, and they behave exactly
+like the ``math'' part of Table 4 of the IEEE standard. Programs interested
+in handling NaN data should test explicitly. This seems to be the way most
+people program and leads to code more understandable to nonexperts. It is
+true that with more operators one can correctly write code that propagates
+NaNs to a successful conclusion\-but that support has been left for later.
+NaN(''tag'') should be added at that same time.
+.NH 2
+Precision
+.PP
+All implementations run exclusively in IEEE double precision. If the
+hardware has extra-precise accumulators, the round-to-double mode is set
+automatically and not changeable, in keeping with Limbo's design to have
+only one floating point type. Extended precision hardware, if available, may
+be used by the built-in elementary function and
+.SM BLAS
+libraries.
+Also, we contemplate adding a dotsharp function that would use a very long
+accumulator for very precise inner products, independent of the order of
+vector elements
+.]C "kulisch" .
+But reference implementations that use only
+double precision, avoid contracted multiply-add, and evaluate in the order 1
+up to n will always be available for strict portability.
+.PP
+At the time the decision was made to restrict the system to 64-bit floating
+point, Limbo integers were almost exclusively 32-bit and the consistency
+argument to have a single real type was compelling. Now that Limbo has more
+integer types the decision might be reconsidered. But so many engineers
+needlessly struggle with programs run in short precision, that offering it
+may do as much harm as good. On most modern computers used for general
+purpose scientific computing, 64-bit floating point arithmetic is as fast as
+32-bit, except for the memory traffic. In cases where the shorter precision
+would suffice and memory is a crucial concern, the programmer should
+consider carefully scaled fixed point or specialized compression. To
+efficiently interoperate with data files that use the short format,
+programmers may use the provided realbits32 function. While there are surely
+appropriate uses for a first-class 32-bit real type, for now we follow
+Kahan's sarcastic motto ``why use lead when gold will do?''
+.NH 2
+BLAS
+.PP
+The few
+.SM BLAS
+in the core library were chosen for readability and,
+in case of gemm, for optimization beyond what a reasonable compiler would
+attempt. We expect that compilers will (soon) be good enough that the
+difference between compiling $y+=a*x$ and calling daxpy is small. Also, as
+mentioned above, dot and gemm might reasonably use combined multiply-add or
+a long accumulator in some optional implementations.
+.NH 2
+$GAMMA ( x )$
+.PP
+To avoid confusion with the C math library, which defined
+.I "gamma"
+as $ln GAMMA $, we offer only
+.I "lgamma"
+for now. This function and
+.I "modf"
+return an (int,real) tuple rather than assigning through an
+integer pointer, in keeping with Limbo's design. The opportunity has been
+taken to drop some obsolete functions like
+.I "frexp" .
+Other functions
+are unchanged from the C math library.
+.NH 2
+Future
+.PP
+A prototype preprocessor has been written to allow the scientific programmer
+to write $A[i,j]$ for an $A$ that was created as a $Matrix(m,n)$ and to have
+the subscript linearization done automatically. Here $Matrix$ is an Limbo
+abstract data type containing a real array and integers $m$, $n$, and column
+stride $lda$ used as in typical Fortran calling sequences.
+.PP
+The Limbo compiler is soon expected to implement the type
+.I "complex" .
+.PP
+Higher level numerical libraries will also be provided, and although that
+topic is beyond the scope of this paper, opinions about what should come
+first would be welcome.
+.PP
+Distributed computing has not been mentioned here because it involves
+relatively few considerations specific to floating point computation.
+However, it may be worth noting that in the default environment (with
+underflow trapped, so that presence or absence of denormalized numbers is
+not significant) programs run independently on heterogeneous machines
+nevertheless get precisely identical results, even with respect to thread
+scheduling. This implies that certain communication steps can be avoided,
+and that regression testing is considerably simplified.
+.PP
+Please direct comments on these numerical aspects of Inferno to Eric Grosse.
+More general technical comments can be directed to Vita Nuova
+.CW comments@vitanuova.com ). (
+I am grateful to Joe Darcy, Berkeley,
+to David Gay, Bell Labs, to David Hook, University of Melbourne,
+and to participants of the IFIP WG2.5 Working
+Conference on Quality of Numerical Software for insightful comments on a
+first draft of this paper.
+.\"the principal developers of Inferno: Sean Dorward, Rob Pike, Dave Presotto, Howard Trickey, and Phil Winterbottom.
+.SH
+Trademarks
+.LP
+Inferno, Limbo, and Dis are trademarks of Vita Nuova Holdings Limited.
+Unix is a trademark of Unix Systems Laboratories.
+Windows95 is a trademark of Microsoft.
+.EQ
+delim off
+.EN
+.SH
+References
+.nr PS -1
+.nr VS -1
+.LP
+.nr [N 0 1
+.de ]N
+.IP \\n+([N.
+.if \nZ>0 .tm \\$1 \\n([N
+..
+....
+....
+.]N "Inferno"
+S. Dorward,
+R. Pike,
+D.\ L. Presotto,
+D.\ M. Ritchie,
+H. Trickey,
+P. Winterbottom,
+``The Inferno Operating System'',
+.I "Bell Labs Technical Journal" ,
+Vol. 2,
+No. 1,
+Winter 1997, pp. 5-18.
+Reprinted in this volume.
+.]N "Clinger"
+W.\ D. Clinger.
+``How to read floating point numbers accurately.
+In \fIProceedings of the ACM SIGPLAN'90 Conference on Programming
+Language Design and Implementation\fP, pages 92-101, 1990.
+....
+....
+.]N "Demmel"
+James\ W. Demmel and Xiaoye Li.
+Faster numerical algorithms via exception handling.
+In Jr. Earl\ Swartzlander, Mary\ Jane Irwin, and Graham Jullien,
+editors, \fIProceedings: 11th Symposium on Computer Arithmetic\fP. IEEE
+Computer Society Press, 1993.
+....
+....
+.]N "blas"
+Jack\ J. Dongarra, Jeremy\ Du Croz, Sven Hammarling, and Richard\ J. Hanson.
+Algorithm 656: An extended set of Basic Linear Algebra Subprograms.
+\fIACM Trans. on Mathematical Software\fP, 14(1):18-32, March 1988.
+....
+....
+.]N "Gay"
+D.\ M. Gay.
+Correctly rounded binary-decimal and decimal-binary conversions.
+Numerical Analysis Manuscript No. 90-10, AT&T Bell Laboratories,
+Murray Hill, NJ, 1990.
+freely redistributable, available at
+.CW http://netlib.bell-labs.com/netlib/fp/ .
+....
+....
+.]N "pine"
+E.\ H. Grosse and W.\ M. Coughran, Jr.
+The pine programming language.
+Numerical Analysis Manuscript 83-4, AT&T Bell Laboratories, 1983.
+.br
+.CW ftp://cm.bell-labs.com/cm/cs/doc/92/pine.ps.Z .
+....
+....
+.]N "IEEEfp"
+IEEE.
+Standard for binary floating-point arithmetic.
+Technical Report Std 754-1985, ANSI, 1985.
+....
+....
+.]N "Kagstrom"
+Bo\ Kagstrom, Per Ling, and Charles Van\ Loan.
+Portable high performance GEMM-based Level 3 BLAS.
+In R.\ F.\ Sincovec et\ al., editor, \fIParallel Processing for
+Scientific Computing\fP, pages 339-346. SIAM Publications, 1993.
+.CW /netlib/blas/ .
+....
+....
+.]N "Kahan"
+W.\ Kahan.
+Lecture notes on the status of IEEE Standard 754 for binary
+floating-point arithmetic.
+Technical report, Univ. Calif. Berkeley, May 23 1995.
+Work in Progress.
+....
+....
+.]N "kulisch"
+U.\ Kulisch and W.L. Miranker.
+\fIComputer arithmetic in theory and practice.\fP
+Academic Press, 1980.
+....
+....
+.]N "MacIlroy"
+M.\ D. McIlroy.
+Mass produced software components.
+In Peter Naur and Brian Randell, editors, \fISoftware Engineering\fP,
+pages 138-155, 1969.
+Garmisch, Germany, October 1968.
+....
+....
+.]N "fdlibm"
+Kwok\ C. Ng.
+.CW fdlibm :
+C math library for machines that support ieee 754
+floating-point.
+freely redistributable; available at
+.CW http://netlib.bell-labs.com/netlib/fdlibm/ ,
+March 1995.
+....
+....
+.]N "SteeleWhite"
+G.\ L. Steele and J.\ L. White.
+How to print floating point numbers accurately.
+In \fIProceedings of the ACM SIGPLAN'90 Conference on Programming
+Language Design and Implementation\fP, pages 112-126, 1990.
+....
+....
+.]N "NumerC"
+X3J11.1.
+Chapter 5, floating-point C extensions.
+Technical report, ANSI, March 29 1995.
+.nr PS +1
+.nr VS +1
binary files /dev/null b/doc/realinferno/real.pdf differ
--- /dev/null
+++ b/doc/sh.ms
@@ -1,0 +1,2067 @@
+.TL
+The Inferno Shell
+.AU
+Roger Peppé
+rog@vitanuova.com
+.AB
+The Inferno shell
+.I sh
+is a reasonably small shell that brings together aspects of
+several other shells along with Inferno's dynamically loaded
+modules, which it uses for much of the functionality
+traditionally built in to the shell. This paper focuses principally
+on the features that make it unusual, and presents
+an example ``network chat'' application written entirely
+in
+.I sh
+script.
+.AE
+.SH
+Introduction
+.LP
+Shells come in many shapes and sizes. The Inferno
+shell
+.I sh
+(actually one of three shells supplied with Inferno)
+is an attempt to combine the strengths of a Unix-like
+shell, notably Tom Duff's
+.I rc ,
+with some of the features peculiar to Inferno.
+It owes its largest debt to
+.I rc ,
+which provides almost all of the syntax
+and most of the semantics too; when in doubt,
+I copied
+.I rc 's
+behaviour.
+In fact, I borrowed as many good ideas as I could
+from elsewhere, inventing new concepts and syntax
+only when unbearably tempted. See Credits
+for a list of those I could remember.
+.LP
+This paper does not attempt to give more than
+a brief overview of the aspects of
+.I sh
+which it holds in common with Plan 9's
+.I rc .
+The reader is referred
+to
+.I sh (1)
+(the definitive reference)
+and Tom Duff's paper ``Rc - The Plan 9 Shell''.
+I have occasionally pinched examples from the latter,
+so the differences are easily contrasted.
+.SH
+Overview
+.LP
+.I Sh
+is, at its simplest level, a command interpreter that will
+be familiar to all those who have used the Bourne-shell,
+C shell, or any of the numerous variants thereof (e.g.
+.I bash ,
+.I ksh ,
+.I tcsh ).
+All of the following commands behave as expected:
+.P1
+date
+cat /lib/keyboard
+ls -l > file.names
+ls -l /dis >> file.names
+wc <file
+echo [a-f]*.b
+ls | wc
+ls; date
+limbo *.b &
+.P2
+An
+.I rc
+concept that will be less familiar to users
+of more conventional shells is the rôle of
+.I lists
+in the shell.
+Each simple
+.I sh
+command, and the value of any
+.I sh
+environment variable, consists of a list of words.
+.I Sh
+lists are flat, a simple ordered list of words,
+where a word is a sequence of characters that
+may include white-space or characters special
+to the shell. The Bourne-shell and its kin
+have no such concept, which means that every
+time the value of any environment variable is
+used, it is split into blank separated words.
+For instance, the command:
+.P1
+x='-l /lib/keyboard'
+ls $x
+.P2
+would in many shells pass the two arguments
+.CW -l '' ``
+and
+.CW /lib/keyboard '' ``
+to the
+.CW ls
+command.
+In
+.I sh ,
+it will pass the single argument
+.CW "-l /lib/keyboard" ''. ``
+.LP
+The following aspects of
+.I sh 's
+syntax will be familiar to users of
+.I rc .
+.LP
+File descriptor manipulation:
+.P1
+echo hello, world > /dev/null >[1=2]
+.P2
+Environment variable values:
+.P1
+echo $var
+.P2
+Count number of elements in a variable:
+.P1
+echo $#var
+.P2
+Run a command and substitute its output:
+.P1
+rm `{grep -li microsoft *}
+.P2
+Lists:
+.P1
+echo (((a b) c) d)
+.P2
+List concatenation:
+.P1
+cat /appl/cmd/sh/^(std regex expr)^.b
+.P2
+To the above,
+.I sh
+adds a variant of the
+.CW `{}
+operator:
+\f5"{}\fP,
+which is the same except that it does not
+split the input into tokens,
+for example:
+.P1
+for i in "{echo one two three} {
+ echo loop
+}
+.P2
+will only print
+.CW loop
+once.
+.LP
+.I Sh
+also adds a new redirection operator
+.CW <> ,
+which opens the standard input (by default) for
+reading
+.I and
+writing.
+.SH
+Command blocks
+.LP
+Possibly
+.I sh 's
+most significant departure from the
+norm is its use of command blocks as values.
+In a conventional shell, a command block
+groups commands together into a single
+syntactic unit that can then be used wherever
+a simple command might appear.
+For example:
+.P1
+{
+ echo hello
+ echo goodbye
+} > /dev/null
+.P2
+.I Sh
+allows this, but it also allows a command block to appear
+wherever a normal word would appear. In this
+case, the command block is not executed immediately,
+but is bundled up as if it was a single quoted word.
+For example:
+.P1
+cmd = {
+ echo hello
+ echo goodbye
+}
+.P2
+will store the contents of the braced block inside
+the environment variable
+.CW $cmd .
+Printing the value of
+.CW $cmd
+gets the block back again, for example:
+.P1
+echo $cmd
+.P2
+gives
+.P1
+{echo hello;echo goodbye}
+.P2
+Note that when the shell parsed the block,
+it ignored everything that was not
+syntactically relevant to the execution
+of the block; for instance, the white space
+has been reduced to the minimum necessary,
+and the newline has been changed to
+the functionally identical semi-colon.
+.LP
+It is also worth pointing out that
+.CW echo
+is an external module, implementing only the
+standard
+.I Command (2)
+interface; it has no knowledge of shell command
+blocks. When the shell invokes an external command,
+and one of the arguments is a command block,
+it simply passes the equivalent string. Internally, built in commands
+are slightly different for efficiency's sake, as we will see,
+but for almost all purposes you can treat command blocks
+as if they were strings holding functionally equivalent shell commands.
+.LP
+This equivalence also applies to the execution of commands.
+When the
+shell comes to execute a simple command (a sequence of
+words), it examines the first word to decide what to execute.
+In most shells, this word can be either the file name of
+an external command, or the name of a command built in
+to the shell (e.g.
+.CW exit ).
+.LP
+.I Sh
+follows these conventional rules, but first, it examines
+the first character of the first word, and if it is an open
+brace
+.CW { ) (
+character, it treats it as a command block,
+parses it, and executes it according to the normal syntax
+rules of the shell. For the duration of this execution, it
+sets the environment variable
+.CW $*
+to the list of arguments passed to the block. For example:
+.P1
+{echo $*} hello world
+.P2
+is exactly the same as
+.P1
+echo hello world
+.P2
+Execution of command blocks is the same whether
+the command block is just a string or has already been
+parsed by the shell.
+For example:
+.P1
+{echo hello}
+.P2
+is exactly the same as
+.P1
+\&'{echo hello}'
+.P2
+The only difference is that the former case has its syntax
+checked for correctness as soon as the shell sees the script;
+whereas if the latter contained a malformed command block,
+a syntax error will be raised only when it
+comes to actually execute the command.
+.LP
+The shell's treatment of braces can be used to provide functionality
+similar to the
+.CW eval
+command that is built in to most other shells.
+.P1
+cmd = 'echo hello; echo goodbye'
+\&'{'^$cmd^'}'
+.P2
+In other words, simply by surrounding a string
+by braces and executing it, the string
+will be executed as if it had been typed to the
+shell. Note the use of the caret
+.CW ^ ) (
+string concatenatation operator.
+.I Sh
+does provide `free carets' in the same way as
+.I rc ,
+so in the previous example
+.P1
+\&'{'$cmd'}'
+.P2
+would work exactly the same, but generally,
+and in particular when writing scripts, it is
+good style to make the carets explicit.
+.SH
+Assignment and scope
+.LP
+The assignment operator in
+.I sh ,
+in common with most other shells
+is
+.CW = .
+.P1
+x=a b c d
+.P2
+assigns the four element list
+.CW "(a b c d)"
+to the environment variable named
+.CW x .
+The value can later be extracted
+with the
+.CW $
+operator, for example:
+.P1
+echo $x
+.P2
+will print
+.P1
+a b c d
+.P2
+.I Sh
+also implements a form of local variable.
+An execution of a braced block command
+creates a new scope for the duration of that block;
+the value of a variable assigned with
+.CW :=
+in that block will be lost when the
+block exits. For example:
+.P1
+x = hello
+{x := goodbye }
+echo $x
+.P2
+will print ``hello''.
+Note that the scoping rules are
+.I dynamic
+\- variable references are interpreted
+relative to their containing scope at execution time.
+For example:
+.P1
+x := hello
+cmd := {echo $x}
+{
+ x := goodbye
+ $cmd
+}
+.P2
+wil print ``goodbye'', not ``hello''. For one
+way of avoiding this problem, see ``Lexical
+binding'' below.
+.LP
+One late, but useful, addition to the shell's assignment
+syntax is tuple assignment. This partially
+makes up for the lack of list indexing primitives in the shell.
+If the left hand side of the assignment operator is
+a list of variable names, each element of the list on the
+right hand side is assigned in turn to its respective variable.
+The last variable mentioned gets assigned all the
+remaining elements.
+For example, after:
+.P1
+(a b c) := (one two three four five)
+.P2
+.CW a
+is
+.CW one ,
+.CW b
+is
+.CW two ,
+and
+.CW c
+contains the three element list
+.CW "(three four five)".
+For example:
+.P1
+(first var) = $var
+.P2
+knocks the first element off
+.CW $var
+and puts it in
+.CW $first .
+.LP
+One important difference between
+.I sh 's
+variables and variables in shells under
+Unix-like operating systems derives from
+the fact that Inferno's underlying process
+creation primitive is
+.I spawn ,
+not
+.I fork .
+This means that, even though the shell
+might create a new process to accomplish
+an I/O redirection, variables changed by
+the sub-process are still visible in the parent
+process. This applies anywhere a new process
+is created that runs synchronously with respect
+to the rest of the shell script - i.e. there is no
+chance of parallel access to the environment.
+For example, it is possible to get
+access to the status value of a command executed
+by the
+.CW `{}
+operator:
+.P1
+files=`{du -a; dustatus = $status}
+if {! ~ $dustatus ''} {
+ echo du failed
+}
+.P2
+When the shell does spawn an asynchronous
+process (background processes and pipelines
+are the two occasions that it does so), the
+environment is copied so changes in one
+process do not affect another.
+.SH
+Loadable modules
+.LP
+The ability to pass command blocks as values is
+all very well, but does not in itself provide the
+programmability that is central to the power of shell scripts
+and is built in to most shells, the conditional
+execution of commands, for instance.
+The Inferno shell is different;
+it provides no programmability within the shell itself,
+but instead relies on external modules to provide this.
+It has a built in command
+.CW load
+that loads a new module into the shell. The module
+that supports standard control flow functionality
+and a number of other useful tidbits is called
+.CW std .
+.P1
+load std
+.P2
+loads this module into the shell.
+.CW Std
+is a Dis module that
+implements the
+.CW Shellbuiltin
+interface; the shell looks in the directory
+.CW /dis/sh
+for the module file, in this case
+.CW /dis/sh/std.dis .
+.LP
+When a module is loaded, it is given the opportunity
+to define as many new commands as it wants.
+Perhaps slightly confusingly, these are known as
+``built-in'' commands (or just ``builtins''), to distinguish
+them from commands executed in a separate process
+with no access to shell internals. Built-in
+commands run in the same process as the shell, and
+have direct access to all its internal state (environment variables,
+command line options, and state stored within the implementing
+module itself). It is possible to find out
+what built-in commands are currently defined with
+the command
+.CW loaded .
+Before any modules have been loaded, typing
+.P1
+loaded
+.P2
+produces:
+.P1
+builtin builtin
+exit builtin
+load builtin
+loaded builtin
+run builtin
+unload builtin
+whatis builtin
+${builtin} builtin
+${loaded} builtin
+${quote} builtin
+${unquote} builtin
+.P2
+These are all the commands that are built in to the
+shell proper; I'll explain the
+.CW ${}
+commands later.
+After loading
+.CW std ,
+executing
+.CW loaded
+produces:
+.P1
+! std
+and std
+apply std
+builtin builtin
+exit builtin
+flag std
+fn std
+for std
+getlines std
+if std
+load builtin
+loaded builtin
+.P3
+or std
+pctl std
+raise std
+rescue std
+run builtin
+status std
+subfn std
+unload builtin
+whatis builtin
+while std
+~ std
+.P3
+${builtin} builtin
+${env} std
+${hd} std
+${index} std
+${join} std
+${loaded} builtin
+${parse} std
+${pid} std
+${pipe} std
+${quote} builtin
+${split} std
+${tl} std
+${unquote} builtin
+.P2
+The name of each command defined
+by a loaded module is followed by the name of
+the module, so you can see that in this case
+.CW std
+has defined commands such as
+.CW if
+and
+.CW while .
+These commands are reminiscent of the
+commands built in to the syntax of
+other shells, but have no special syntax
+associated with them: they obey the normal
+argument gathering and execution semantics.
+.LP
+As an example, consider the
+.CW for
+command.
+.P1
+for i in a b c d {
+ echo $i
+}
+.P2
+This command traverses the list
+.CW "(a b c d)"
+executing
+.CW "{echo $i}"
+with
+.CW $i
+set to each element in turn. In
+.I rc ,
+this might be written
+.P1
+for (i in a b c d) {
+ echo $i
+}
+.P2
+and in fact, in
+.I sh ,
+this is exactly equivalent. The round brackets
+denote a list and, like
+.I rc ,
+all lists are flattened before passing to an
+executed command.
+Unlike the
+.CW for
+command in
+.I rc ,
+the braces around the command are
+not optional; as with the arguments to
+a normal command, gathering of arguments
+stops at a newline. The exception to this rule
+is that newlines within brackets are treated as white space.
+This last rule also
+applies to round brackets, for example:
+.P1
+(for i in
+ a
+ b
+ c
+ d
+ {echo $i}
+)
+.P2
+does the same thing.
+This is very useful for commands that take multiple
+command block arguments, and is actually the only
+line continuation mechanism that
+.I sh
+provides (the usual backslash
+.CW \e ) (
+character is not in any way special to
+.I sh ).
+.SH
+Control structures
+.LP
+Inferno commands, like shell commands in Unix
+or Plan 9, return a status when they finish.
+A command's status in Inferno is a short string
+describing any error that has occurred;
+it can be found in the environment variable
+.CW $status .
+This is the value that commands defined by
+.CW std
+use to determine conditional
+execution - if it is empty, it is true; otherwise
+false.
+.CW Std
+defines, for instance, a command
+.CW ~
+that provides a simple pattern matching capability.
+Its first argument is the string to test the patterns
+against, and subsequent arguments give the patterns,
+in normal shell wildcard syntax; its status is true
+if there is a match.
+.P1
+~ sh.y '*.y'
+~ std.b '*.y'
+.P2
+give true and false statuses respectively.
+A couple of pitfalls lurk here for the unwary:
+unlike its
+.I rc
+namesake, the patterns
+.I are
+expanded by the shell if left unquoted, so
+one has to be careful to quote wildcard characters,
+or escape them with a backslash if they are to
+be used literally.
+Like any other command,
+.CW ~
+receives a simple list of arguments, so it has to
+assume that the string tested has exactly one element;
+if you provide a null variable, or one with more
+than one element, then you will get unexpected results.
+If in doubt, use the
+\f5$"\fP
+operator to make sure of that.
+.LP
+Used in conjunction with the
+.CW $#
+operator,
+.CW ~
+provides a way to check the
+number of elements in a list:
+.P1
+~ $#var 0
+.P2
+will be true if
+.CW $var
+is empty.
+.LP
+This can be tested by the
+.CW if
+command, which
+accepts command blocks for
+its arguments, executing its second argument if
+the status of the first is empty (true).
+For example:
+.P1
+if {~ $#var 0} {
+ echo '$var has no elements'
+}
+.P2
+Note that the start of one argument must
+come on the same line as the end of of the previous,
+otherwise it will be treated as a new command,
+and always executed. For example:
+.P1
+if {~ $#var 0}
+ {echo '$var has no elements'} # this will always be executed
+.P2
+The way to get around this is to use list bracketing,
+for example:
+.P1
+(if {~ $#var 0}
+ {echo '$var has no elements'}
+)
+.P2
+will have the desired effect.
+The
+.CW if
+command is more general than
+.I rc 's
+.CW if ,
+in that it accepts an arbitrary number
+of condition/action pairs, and executes each condition
+in turn until one is true, whereupon it executes the associated
+action. If the last condition has no action, then it
+acts as the ``else'' clause in the
+.CW if .
+For example:
+.P1
+(if {~ $#var 0} {
+ echo zero elements
+ }
+ {~ $#var 1} {
+ echo one element
+ }
+ {echo more than one element}
+)
+.P2
+.LP
+.CW Std
+provides various other control structures.
+.CW And
+and
+.CW or
+provide the equivalent of
+.I rc 's
+.CW &&
+and
+.CW ||
+operators. They each take any number of command
+block arguments and conditionally execute each
+in turn.
+.CW And
+stops executing when a block's status is false,
+.CW or
+when a block's status is true:
+.P1
+and {~ $#var 1} {~ $var '*.sbl'} {echo variable ends in .sbl}
+(or {mount /dev/eia0 /n/remote}
+ {echo mount has failed with $status}
+)
+.P2
+An extremely easy trap to fall into is to use
+.CW $*
+inside a block assuming that its value is the
+same as that outside the block. For instance:
+.P1
+# this will not work
+if {~ $#* 2} {echo two arguments}
+.P2
+It will not work because
+.CW $*
+is set locally for every block, whether it
+is given arguments or not. A solution is to
+assign
+.CW $*
+to a variable at the start of the block:
+.P1
+args = $*
+if {~ $#args 2} {echo two arguments}
+.P2
+.LP
+.CW While
+provides looping, executing its second argument
+as long as the status of the first remains true.
+As the status of an empty block is always true,
+.P1
+while {} {echo yes}
+.P2
+will loop forever printing ``yes''.
+Another looping command is
+.CW getlines ,
+which loops reading lines from its standard
+input, and executing its command argument,
+setting the environment variable
+.CW $line
+to each line in turn.
+For example:
+.P1
+getlines {
+ echo '#' $line
+} < x.b
+.P2
+will print each line of the file
+.CW x.b
+preceded by a
+.CW #
+character.
+.SH
+Exceptions
+.LP
+When the shell encounters some error conditions, such
+as a parsing error, or a redirection failure,
+it prints a message to standard error and raises
+an
+.I exception .
+In an interactive shell this is caught by the interactive
+command loop; in a script it will cause an exit with
+a false status, unless handled.
+.LP
+Exceptions can be handled and raised with the
+.CW rescue
+and
+.CW raise
+commands provided by
+.CW std .
+An exception has a short string associated with it.
+.P1
+raise error
+.P2
+will raise an exception named ``error''.
+.P1
+rescue error {echo an error has occurred} {
+ command
+}
+.P2
+will execute
+.CW command
+and will, in the event that it raises an
+.CW error
+exception, print a diagnostic message.
+The name of the exception given to
+.CW rescue
+can end in an asterisk
+.CW * ), (
+which will match any exception starting with
+the preceding characters. The
+.CW *
+needs quoting to avoid being expanded as a wildcard
+by the shell.
+.P1
+rescue '*' {echo caught an exception $exception} {
+ command
+}
+.P2
+will catch all exceptions raised by
+.CW command ,
+regardless of name.
+Within the handler block,
+.CW rescue
+sets the environment variable
+.CW $exception
+to the actual name of the exception caught.
+.LP
+Exceptions can be caught only within a single
+process \- if an exception is not caught, then
+the name of the exception becomes the
+exit status of the process.
+As
+.I sh
+starts a new process for commands with redirected
+I/O, this means that
+.P1
+raise error
+echo got here
+.P2
+behaves differently to:
+.P1
+raise error > /dev/null
+echo got here
+.P2
+The former prints nothing, while the latter
+prints ``got here''.
+.LP
+The exceptions
+.CW break
+and
+.CW continue
+are recognised by
+.CW std 's
+looping commands
+.CW for ,
+.CW while ,
+and
+.CW getlines .
+A
+.CW break
+exception causes the loop to terminate;
+a
+.CW continue
+exception causes the loop to continue
+as before. For example:
+.P1
+for i in * {
+ if {~ $i 'r*'} {
+ echo found $i
+ raise break
+ }
+}
+.P2
+will print the name of the first
+file beginning with ``r'' in the
+current directory.
+.SH
+Substitution builtins
+.LP
+In addition to normal commands, a loaded module
+can also define
+.I "substitution builtin"
+commands. These are different from normal commands
+in that they are executed as part of the argument
+gathering process of a command, and instead of
+returning an exit status, they yield a list of values
+to be used as arguments to a command. They
+can be thought of as a kind of `active environment variable',
+whose value is created every time it is referenced.
+For example, the
+.CW split
+substitution builtin defined by
+.CW std
+splits up a single argument into strings separated
+by characters in its first argument:
+.P1
+echo ${split e 'hello there'}
+.P2
+will print
+.P1
+h llo th r
+.P2
+Note that, unlike the conventional shell
+backquote operator, the result of the
+.CW $
+command is not re-interpreted, for example:
+.P1
+for i in ${split e 'hello there'} {
+ echo arg $i
+}
+.P2
+will print
+.P1
+arg h
+arg llo th
+arg r
+.P2
+Substitution builtins can only be named
+as the initial command inside a dollar-referenced
+command block - they live in a different namespace
+from that of normal commands.
+For instance,
+.CW loaded
+and
+.CW ${loaded}
+are quite distinct: the former prints a list
+of all builtin names and their defining modules, whereas
+the former yields a list of all the currently loaded
+modules.
+.LP
+.CW Std
+provides a number of useful commands
+in the form of substitution builtins.
+.CW ${join}
+is the complement of
+.CW ${split} :
+it joins together any elements in its argument list
+using its first argument as the separator, for example:
+.P1
+echo ${join . file tar gz}
+.P2
+will print:
+.P1
+file.tar.gz
+.P2
+The in-built shell operator
+\f5$"\fP
+is exactly equivalent to
+.CW ${join}
+with a space as its first argument.
+.LP
+List indexing is provided with
+.CW ${index} ,
+which given a numeric index and a list
+yields the
+.I index 'th
+item in the list (origin 1). For example:
+.P1
+echo ${index 4 one two three four five}
+.P2
+will print
+.P1
+four
+.P2
+A pair of substitution builtins with some of
+the most interesting uses are defined by
+the shell itself:
+.CW ${quote}
+packages its argument list into a single
+string in such a way that it can be later
+parsed by the shell and turned back into the same list.
+This entails quoting any items in the list
+that contain shell metacharacters, such as
+.CW ; ` '
+or
+.CW & '. `
+For example:
+.P1
+x='a;' 'b' 'c d' ''
+echo $x
+echo ${quote $x}
+.P2
+will print
+.P1
+a; b c d
+\&'a;' b 'c d' ''
+.P2
+Travel in the reverse direction is possible
+using
+.CW ${unquote} ,
+which takes a single string, as produced by
+.CW ${quote} ,
+and produces the original list again.
+There are situations in
+.I sh
+where only a single string can be used, but
+it is useful to be able to pass around the values
+of arbitrary
+.I sh
+variables in this form;
+.CW ${quote}
+and
+.CW ${unquote}
+between them make this possible. For instance
+the value of a
+.I sh
+list can be stored in a file and later retrieved
+without loss. They are also useful to implement
+various types of behaviour involving automatically
+constructed shell scripts; see ``Lexical binding'', below,
+for an example.
+.LP
+Two more list manipulation commands provided
+by
+.CW std
+are
+.CW ${hd}
+and
+.CW ${tl} ,
+which mirror their Limbo namesakes:
+.CW ${hd}
+returns the first element of a list,
+.CW ${tl}
+returns all but the first element of a list.
+For example:
+.P1
+x=one two three four
+echo ${hd $x}
+echo ${tl $x}
+.P2
+will print:
+.P1
+one
+two three four
+.P2
+Unlike their Limbo counterparts, they
+do not complain if their argument list
+is not long enough; they just yield a null list.
+.LP
+.CW Std
+provides three other substitution builtins of
+note.
+.CW ${pid}
+yields the process id of the current
+process.
+.CW ${pipe}
+provides a somewhat more cumbersome equivalent of the
+.CW >{}
+and
+.CW <{}
+commands found in
+.I rc ,
+i.e. branching pipelines.
+For example:
+.P1
+cmp ${pipe from {old}} ${pipe from {new}}
+.P2
+will regression-test a new version of a command.
+Using
+.CW ${pipe}
+yields the name of a file in the namespace
+which is a pipe to its argument command.
+.LP
+The substitution builtin
+.CW ${parse}
+is used to check shell syntax without actually
+executing a command. The command:
+.P1
+x=${parse '{echo hello, world}'}
+.P2
+will return a parsed version of the string
+.CW "echo hello, world" ''; ``
+if an error occurs, then a
+.CW "parse error"
+exception will be raised.
+.SH
+Functions
+.LP
+Shell functions are a facility provided
+by the
+.CW std
+shell module; they associate a command
+name with some code to execute when
+that command is named.
+.P1
+fn hello {
+ echo hello, world
+}
+.P2
+defines a new command,
+.CW hello ,
+that prints a message when executed.
+The command is passed arguments in the
+usual way, for example:
+.P1
+fn removems {
+ for i in $* {
+ if {grep -s Microsoft $i} {
+ rm $i
+ }
+ }
+}
+removems *
+.P2
+will remove all files in the current directory
+that contain the string ``Microsoft''.
+.LP
+The
+.CW status
+command provides a way to return an
+arbitrary status from a function. It takes
+a single argument \- its exit status
+is the value of that argument. For instance:
+.P1
+fn false {
+ status false
+}
+fn true {
+ status ''
+}
+.P2
+It is also possible to define new substitution builtins
+with the command
+.CW subfn :
+the value of
+.CW $result
+at the end of the execution of the
+command gives the value yielded.
+For example:
+.P1
+subfn backwards {
+ for i in $* {
+ result=$i $result
+ }
+}
+echo ${backwards a b c 'd e'}
+.P2
+will reverse a list, producing:
+.P1
+d e c b a
+.P2
+.LP
+The commands associated with shell functions
+are stored as normal environment variables, and
+so are exported to external commands in the usual
+way.
+.CW Fn
+definitions are stored in environment variables
+starting
+.CW fn- ;
+.CW subfn
+definitions use environment variables starting
+.CW sfn- .
+It is useful to know this, as the shell core knows
+nothing of these functions - they look just like
+builtin commands defined by
+.CW std ;
+looking at the current definition of
+.CW $fn-\fIname\fP
+is the only way of finding out the body of code
+associated with function
+.I name .
+.SH
+Other loadable
+.I sh
+modules
+.LP
+In addition to
+.CW std ,
+and
+.CW tk ,
+which is mentioned later, there are
+several loadable
+.I sh
+modules that extend
+.I sh's
+functionality.
+.LP
+.CW Expr
+provides a very simple stack-based calculator,
+giving simple arithmetic capability to the shell.
+For example:
+.P1
+load expr
+echo ${expr 3 2 1 + x}
+.P2
+will print
+.CW 9 .
+.LP
+.CW String
+provides shell level access to the Limbo
+string library routines. For example:
+.P1
+load string
+echo ${tolower 'Hello, WORLD'}
+.P2
+will print
+.P1
+hello, world
+.P2
+.CW Regex
+provides regular expression matching and
+substitution operations. For instance:
+.P1
+load regex
+if {! match '^[a-z0-9_]+$' $line} {
+ echo line contains invalid characters
+}
+.P2
+.CW File2chan
+provides a way for a shell script to create a
+file in the namespace with properties
+under its control. For instance:
+.P1
+load file2chan
+(file2chan /chan/myfile
+ {echo read request from /chan/myfile}
+ {echo write request to /chan/myfile}
+)
+.P2
+.CW Arg
+provides support for the parsing of standard
+Unix-style options.
+.SH
+.I Sh
+and Inferno devices
+.LP
+Devices under Inferno are implemented as files,
+and usually device interaction consists of simple
+strings written or read from the device files.
+This is a happy coincidence, as the two things
+that
+.I sh
+does best are file manipulation and string manipulation.
+This means that
+.I sh
+scripts can exploit the power of direct access to
+devices without the need to write more long winded
+Limbo programs. You do not get the type checking
+that Limbo gives you, and it is not quick, but for
+knocking up quick prototypes, or ``wrapper scripts'',
+it can be very useful.
+.LP
+Consider the way that Inferno implements network
+access, for example. A file called
+.CW /net/cs
+implements DNS address translation. A string such as
+.CW tcp!www.vitanuova.com!telnet
+is written to
+.CW /net/cs ;
+the translated form of the address is then read
+back, in the form of a (\fIfile\fP, \fItext\fP)
+pair, where
+.I file
+is the name of a
+.I clone
+file in the
+.CW /net
+directory
+(e.g.
+.CW /net/tcp/clone ),
+and
+.I text
+is a translated address as understood by the relevant
+network (e.g.
+.CW 194.217.172.25!23 ).
+We can write a shell function that performs this
+translation, returning a triple
+(\fIdirectory\fP \fIclonefile\fP \fItext\fP):
+.P1
+subfn cs {
+ addr := $1
+ or {
+ <> /net/cs {
+ (if {echo -n $addr >[1=0]} {
+ (clone addr) := `{read 8192 0}
+ netdir := ${dirname $clone}
+ result=$netdir $clone $addr
+ } {
+ echo 'cs: cannot translate "' ^
+ $addr ^
+ '":' $status >[1=2]
+ status failed
+ }
+ )
+ }
+ } {raise 'cs failed'}
+}
+.P2
+The code
+.P1
+<> /net/cs { \fR....\fP }
+.P2
+opens
+.CW /net/cs
+for reading and writing, on the standard input;
+the code inside the braces can then read and
+write it.
+If the address translation fails, an error will
+be generated on the write, so the
+.CW echo
+will fail - this is detected, and an appropriate exit status
+set.
+Being a substitution function, the only way that
+.CW cs
+can indicate an error is by raising an exception, but
+exceptions do not propagate across processes
+(a new process is created as a result of the redirection),
+hence the need for the status check and the raised exception
+on failure.
+.LP
+The external program
+.CW read
+is invoked to make a single read of the
+result from
+.CW /lib/cs .
+It takes a block size, and a read offset - it
+is important to set this, as the initial write of the
+address to
+.CW /lib/cs
+will have advanced the file offset, and we will miss
+a chunk of the returned address if we're not careful.
+.LP
+.CW Dirname
+is a little shell function that uses one of the
+.I string
+builtin functions to get the directory name from
+the pathname of the
+.I clone
+file. It looks like:
+.P1
+load string
+subfn dirname {
+ result = ${hd ${splitr $1 /}}
+}
+.P2
+Now we have an address translation function, we can
+access the network interface directly. There are
+three main operations possible with Inferno network
+devices: connecting to a remote address, announcing
+the availability of a local dial-in address, and listening
+for an incoming connection on a previously announced
+address. They are accessed in similar ways (see
+.I ip (3)
+for details):
+.LP
+The dial and announce operations require a new
+.CW net
+directory, which is created by reading the
+clone file - this actually opens the
+.CW ctl
+file in a newly created net directory, representing
+one end of a network connection. Reading a
+.CW ctl
+file yields the name of the new directory;
+this enables an application to find the associated
+.CW data
+file; reads and writes to this file go to the
+other end of the network connection.
+The listen operation is similar, but the new
+net directory is created by reading from an existing
+directory's
+.CW listen
+file.
+.LP
+Here is a
+.I sh
+function that implements some behaviour common
+to all three operations:
+.P1
+fn newnetcon {
+ (netdir constr datacmd) := $*
+ id := "{read 20 0}
+ or {~ $constr ''} {echo -n $constr >[1=0]} {
+ echo cannot $constr >[1=2]
+ raise failed
+ }
+ net := $netdir/^$id
+ $datacmd <> $net^/data
+}
+.P2
+It takes the name of a network protocol directory
+(e.g.
+.CW /net/tcp ),
+a possibly empty string to write into the control
+file when the new directory id has been read,
+and a command to be executed connected to
+the newly opened
+.CW data
+file. The code is fairly straightforward: read
+the name of a new directory from standard input
+(we are assuming that the caller of
+.CW newnetcon
+sets up the standard input correctly); then
+write the configuration string (if it is not empty),
+raising an error if the write failed; then run the
+command, attached to the
+.CW data
+file.
+.LP
+We set up the
+.CW $net
+environment variable so that
+the running command knows its network
+context, and can access other files in the
+directory (the
+.CW local
+and
+.CW remote
+files, for example).
+Given
+.CW newnetcon ,
+the implementation of
+.CW dial ,
+.CW announce ,
+and
+.CW listen
+is quite easy:
+.P1
+fn announce {
+ (addr cmd) := $*
+ (netdir clone addr) := ${cs $addr}
+ newnetcon $netdir 'announce '^$addr $cmd <> $clone
+}
+
+fn dial {
+ (addr cmd) := $*
+ (netdir clone addr) := ${cs $addr}
+ newnetcon $netdir 'connect '^$addr $cmd <> $clone
+}
+
+fn listen {
+ newnetcon ${dirname $net} '' $1 <> $net/listen
+}
+.P2
+.CW Dial
+and
+.CW announce
+differ only in the string that is written to the control
+file;
+.CW listen
+assumes it is being called in the context of
+an
+.CW announce
+command, so can use the value
+of
+.CW $net
+to open the
+.CW listen
+file to wait for incoming connections.
+.LP
+The upshot of these function definitions is that we
+can make connections to, and announce, services
+on the network. The code for a simple client might look like:
+.P1
+dial tcp!somewhere.com!5432 {
+ echo connected to `{cat $net/remote}
+ echo hello somewhere >[1=0]
+}
+.P2
+A server might look like:
+.P1
+announce tcp!somewhere.com!5432 {
+ listen {
+ echo got connection from `{cat $net/remote}
+ cat
+ }
+}
+.P2
+.SH
+.I Sh
+and the windowing environment
+.LP
+The main interface to the Inferno graphics and windowing
+system is a textual one, based on Osterhaut's Tk,
+where commands to manipulate the graphics inside
+windows are strings using a uniform syntax not
+a million miles away from the syntax of
+.I sh .
+(See section 9 of Volume 1 for details).
+The
+.CW tk
+.I sh
+module provides an interface to the Tk graphics
+subsystem, providing not only graphics capabilities,
+but also the channel communication on which
+Inferno's Tk event mechanism is based.
+.LP
+The Tk module gives each window a unique
+numeric id which is used to control that window.
+.P1
+load tk
+wid := ${tk window 'My window'}
+.P2
+loads the tk module, creates a new window titled ``My window''
+and assigns its unique identifier to the variable
+.CW $wid .
+Commands of the form
+.CW "tk $wid"
+.I tkcommand
+can then be used to control graphics in the window.
+When writing tk applets, it is helpful to get feedback
+on errors that occur as tk commands are executed, so
+here's a function that checks for errors, and minimises
+the syntactic overhead of sending a Tk command:
+.P1
+fn x {
+ args := $*
+ or {tk $wid $args} {
+ echo error on tk cmd $"args':' $status
+ }
+}
+.P2
+It assumes that
+.CW $wid
+has already been set.
+Using
+.CW x ,
+we could create a button in our new window:
+.P1
+x button .b -text {A button}
+x pack .b -side top
+x update
+.P2
+Note that the nice coincidence of the quoting rules
+of
+.I sh
+and tk mean that the unquoted
+.I sh
+command block argument to the
+.CW button
+command gets through to tk unchanged,
+there to become quoted text.
+.LP
+Once we've got a button, we want to know when
+it has been pressed. Inferno Tk sends events
+through Limbo channels, so the Tk module provides
+access to simple string channels. A channel is
+created with the
+.CW chan
+command.
+.P1
+chan event
+.P2
+creates a channel named
+.CW event .
+A
+.CW send
+command takes a string to send down the channel,
+and the
+.CW ${recv}
+builtin yields a received value. Both operations
+block until the transfer of data can proceed \- as with
+Limbo channels, the operation is synchronous. For example:
+.P1
+send event 'hello, world' &
+echo ${recv event}
+.P2
+will print ``hello, world''. Note that the send
+and receive operations must execute in different
+processes, hence the use of the
+.CW &
+backgrounding operator.
+Although for implementation reasons they are
+part of the Tk module, these channel operations
+are potentially useful in non-graphical scripts \-
+they will still work fine if there's no graphics context.
+.LP
+The
+.CW "tk namechan"
+command makes a channel known to Tk.
+.P1
+tk namechan $wid event
+.P2
+Then we can get events from Tk:
+.P1
+x .b configure -command {send event buttonpressed}
+while {} {echo ${recv event}} &
+.P2
+This starts a background process that prints a message
+each time the button is pressed.
+Interaction with the window manager is handled in
+a similar way. When a window is created, it is automatically
+associated with a channel of the same name as the window id.
+Strings arriving on this are window manager events, such as
+.CW resize
+and
+.CW move .
+These can be interpreted if desired, or forwarded back
+to the window manager for default handling with
+.CW "tk winctl" .
+The following is a useful idiom that does all the usual
+event handling on a window:
+.P1
+while {} {tk winctl $wid ${recv $wid}} &
+.P2
+One thing worth knowing is that the default
+.CW exit
+action (i.e. when the user closes the window) is
+to kill all processes in the current process group, so
+in a script that creates windows,
+it is usual to fork the process group with
+.CW "pctl newgrp"
+early on, otherwise
+it can end up killing the shell window that spawned it.
+.SH
+An example
+.LP
+By way of an example. I'll present a function that implements
+a simple network chat facility, allowing two people on the
+network to send text messages to one another, making use
+of the network functions described earlier.
+.LP
+The core is a function called
+.CW chat
+which assumes that its standard input has
+been directed to an active network connection; it creates a
+window containing an entry widget and a text widget. Any text
+entered into the entry widget is sent to the other end
+of the connection; lines of text arriving from
+the network are appended to the text widget.
+.LP
+The first part of the function creates the window,
+forks the process group, runs the window controller
+and creates the widgets inside the window:
+.P1
+fn chat {
+ load tk
+ pctl newpgrp
+ wid := ${tk window 'Chat'}
+ nl := '
+\&' # newline
+ while {} {tk winctl $wid ${recv $wid}} &
+ x entry .e
+ x frame .f
+ x scrollbar .f.s -orient vertical -command {.f.t yview}
+ x text .f.t -yscrollcommand {.f.s set}
+ x pack .f.s -side left -fill y
+ x pack .f.t -side top -fill both -expand 1
+ x pack .f -side top -fill both -expand 1
+ x pack .e -side top -fill x
+ x pack propagate . 0
+ x bind .e '<Key-'^$nl^'>' {send event enter}
+ x update
+ chan event
+ tk namechan $wid event event
+.P2
+The middle part of
+.CW chat
+loops in the background getting text entered
+by the user and sending it across the network
+(also putting a copy in the local text widget
+so that you can see what you have sent.
+.P1
+ while {} {
+ {} ${recv event}
+ txt := ${tk $wid .e get}
+ echo $txt >[1=0]
+ x .f.t insert end '''me: '^$txt^$nl
+ x .e delete 0 end
+ x .f.t see end
+ x update
+ } &
+.P2
+Note the null command on the second line,
+used to wait for the receive event without
+having to deal with the value (there's only
+one event that can arrive on the channel, and
+we know what it is).
+.LP
+The final piece of
+.CW chat
+gets lines from the network and puts them
+in the text widget. The loop will terminate when
+the connection is dropped by the other party, whereupon
+the window closes and the chat finished:
+.P1
+ getlines {
+ x .f.t insert end '''you: '^$line^$nl
+ x .f.t see end
+ x update
+ }
+ tk winctl $wid exit
+}
+.P2
+Now we can wrap up the network functions and the
+chat function in a shell script, to finish off the little demo:
+.P1
+#!/dis/sh
+.I "Include the earlier function definitions here."
+fn usage {
+ echo 'usage: chat [-s] address' >[1=2]
+ raise usage
+}
+
+args=$*
+or {~ $#args 1 2} {usage}
+(addr args) := $*
+if {~ $addr -s} {
+ # server
+ or {~ $#args 1} {usage}
+ (addr nil) := $args
+ announce $addr {
+ echo announced on `{cat $net/local}
+ while {} {
+ net := $net
+ listen {
+ echo got connection from `{cat $net/remote}
+ chat &
+ }
+ }
+ }
+} {
+ or {~ $#args 0} {usage}
+ # client
+ dial $addr {
+ echo made connection
+ chat
+ }
+}
+.P2
+If this is placed in an executable script file
+named
+.CW chat ,
+then
+.P1
+chat -s tcp!mymachine.com!5432
+.P2
+would announce a chat server using tcp
+on
+.CW mymachine.com
+(the local machine)
+on port 5432.
+.P1
+chat tcp!mymachine.com!5432
+.P2
+would make a connection to
+the previous server; they would both pop
+up windows and allow text to be typed in from
+either end.
+.SH
+Lexical binding
+.LP
+One potential problem with all this passing around
+of fragments of shell script is the scope of names.
+This piece of code:
+.P1
+fn runit {x := Two; $*}
+x := One
+runit {echo $x}
+.P2
+will print ``Two'', which is quite likely to confound the
+expectations of the person writing the script if they
+did not know that
+.CW runit
+set the value of
+.CW $x
+before calling its argument script.
+Some functional languages (and the
+.I es
+shell) implement
+.I "lexical binding"
+to get around this problem. The idea
+is to derive a new script from the old
+one with all the necessary variables bound to
+their current values, regardless of the context in which
+the script is later called.
+.LP
+.I Sh
+does not provide any explicit support for
+this operation; however it is possible to fake
+up a reasonably passable job.
+Recall that blocks can be treated as strings if necessary,
+and that
+.CW ${quote}
+allows the bundling of lists in such a way that they
+can later be extracted again without loss. These two
+features allow the writing of the following
+.CW let
+function (I have omitted argument checking code here and
+in later code for the sake of brevity):
+.P1
+subfn let {
+ # usage: let cmd var...
+ (let_cmd let_vars) := $*
+ if {~ $#let_cmd 0} {
+ echo 'usage: let {cmd} var...' >[1=2]
+ raise usage
+ }
+ let_prefix := ''
+ for let_i in $let_vars {
+ let_prefix = $let_prefix ^
+ ${quote $let_i}^':='^${quote $$let_i}^';'
+ }
+ result=${parse '{'^$let_prefix^$let_cmd^' $*}'}
+}
+.P2
+.CW Let
+takes a block of code, and the names of environment variables
+to bind onto it; it returns the resulting new block of code.
+For example:
+.P1
+fn runit {x := hello, world; $*}
+x := a 'b c d' 'e'
+runit ${let {echo $x} x}
+.P2
+will print:
+.P1
+a b c d e
+.P2
+Looking at the code it produces is perhaps more
+enlightening than examining the function definition:
+.P1
+x=a 'b c d' 'e'
+echo ${let {echo $x} x}
+.P2
+produces
+.P1
+{x:=a 'b c d' e;{echo $x} $*}
+.P2
+.CW Let
+has bundled up the values of the two bound variables,
+stuck them onto the beginning of the code block
+and surrounded the whole thing in braces.
+It makes sure that it has valid syntax by using
+.CW ${parse} ,
+and it ensures that the correct arguments are
+passed to the script by passing it
+.CW $* .
+.LP
+Note that all the variable names used inside the
+body of
+.CW let
+are prefixed with
+.CW let_ .
+This is to try to reduce the likelihood that someone
+will want to lexically bind to a variable of a name used
+inside
+.CW let .
+.SH
+The module interface
+.PP
+It is not within the scope of this paper to discuss in
+detail the public module interface to the shell, but
+it is probably worth mentioning some of the other
+benefits that
+.I sh
+derives from living within Inferno.
+.PP
+Unlike shells in conventional systems, where
+the shell is a standalone program, accessible
+only through
+.CW exec() ,
+in Inferno,
+.I sh
+presents a module interface that allows programs
+to gain lower level access to the primitives provided
+by the shell. For example, Inferno programs can make use of
+the shell syntax parsing directly, so
+a shell command in a configuration script might be
+checked for correctness before running it,
+or parsed to avoid parsing overhead when running
+a shell command within a loop.
+.PP
+More importantly, as long as it implements a superset
+of the
+.CW Shellbuiltin
+interface, an application can
+load
+.I itself
+into the shell as a module, and define builtin commands
+that directly access functionality that it can provide.
+.PP
+This can, with minimum effort, provide an application
+with a programmable interface to its primitives.
+I have modified the Inferno window manager
+.CW wm ,
+for example, so that instead of using a custom, fairly limited
+format file, its configuration file is just
+a shell script.
+.CW Wm
+loads itself into the shell,
+defines a new builtin command
+.CW menu
+to create items in
+its main menu, and runs a shell script.
+The shell script has the freedom to customise
+menu entries dynamically, to run arbitrary programs,
+and even to publicise this interface to
+.CW wm
+by creating a file with
+.CW file2chan
+and interpreting writes to the file as calls
+to the
+.CW menu
+command:
+.P1
+file2chan /chan/wmmenu {} {menu ${unquote ${rget data}}}
+.P2
+A corresponding
+.CW wmmenu
+shell function might be written to provide access to
+the functionality:
+.P1
+fn wmmenu {
+ echo ${quote $*} > /chan/wmmenu
+}
+.P2
+Inferno has blurred the boundaries between
+application and library and
+.I sh
+exploits this \- the possibilities have only just begun
+to be explored.
+.SH
+Discussion
+.LP
+Although it is a newly written shell, the use of tried
+and tested semantics means that most of the
+normal shell functionality works quite smoothly.
+The separation between normal commands and
+substitution builtins is arguable, but I think justifiable.
+The distinction between the two classes of command
+means that there is less awkwardness in the transition between
+ordinary commands and internally implemented commands:
+both return the same kind of thing. A normal command's
+return value remains essentially a simple true/false status,
+whereas the new substitution builtins are returning a list
+with no real distinction between true and false.
+.LP
+I believe that the decision to keep as much functionality as
+possible out
+of the core shell has paid off. Allowing command blocks
+as values enables external modules to define new
+control-flow primitives, which in turn means that
+the core shell can be kept reasonably static,
+while the design of the shell modules evolves
+independently. There is a syntactic price
+to pay for this generality, but I think it is worth it!
+.LP
+There are some aspects to the design that I do not
+find entirely satisfactory. It is strange, given the
+throwaway and non-explicit use of subprocesses
+in the shell, that exceptions do not propagate
+between processes. The model is Limbo's, but
+I am not sure it works perfectly for
+.I sh .
+I feel there should probably be some difference
+between:
+.P1
+raise error > /dev/null
+.P2
+and
+.P1
+status error > /dev/null
+.P2
+The shared nature of loaded modules can cause
+problems; unlike environment variables, which
+are copied for asynchronously running processes,
+the module instances for an asynchronously running
+process remain the same. This means that a
+module such as
+.CW tk
+must maintain mutual exclusion locks to
+protect access to its data structures. This
+could be solved if Limbo had some kind of polymorphic
+type that enabled the shell to hold some data on
+a module's behalf \- it could ask the module
+to copy it when necessary.
+.LP
+One thing that is lost going from Limbo to
+.I sh
+when using the
+.CW tk
+module is the usual reference-counted garbage collection
+of windows. Because a shell-script holds not
+a direct handle on the window, but only a string
+that indirectly refers to a handle held inside
+the
+.CW tk
+module, there is no way for the system to
+know when the window is no longer referred to,
+so, as long as a
+.CW tk
+module is loaded, its windows must be
+explicitly deleted.
+.LP
+The names defined by loaded modules will
+become an issue if
+loaded modules proliferate. It is not easy
+to ensure that a command that you are executing
+is defined by the module you think it is, given name clashes
+between modules.I have been considering some
+kind of scheme that would allow discrimination
+between modules, but for the moment, the point
+is moot \- there are no module name clashes, and
+I hope that that will remain the case.
+.SH
+Credits
+.LP
+.I Sh
+is almost entirely an amalgam of other people's
+ideas that I have been fortunate enough to
+encounter over the years. I hope they will forgive
+me for the corruption I've applied...
+.LP
+I have been a happy user of a version of Tom Duff's
+.I rc
+for ten years or so; without
+.I rc ,
+this shell would not exist in anything like its present form.
+Thanks, Tom.
+.LP
+It was Byron Rakitzis's UNIX version of
+.I rc
+that I was using for most of those ten years; it was his
+version of the grammar that eventually became
+.I sh 's
+grammar, and the name of my
+.CW glom()
+function came straight from his
+.I rc
+source.
+.LP
+From Paul Haahr's
+.I es ,
+a descendent of Byron's
+.I rc ,
+and the shell that probably holds the most in common
+with
+.I sh ,
+I stole the ``blocks as values'' idea;
+the way that blocks transform into strings
+and vice versa is completely
+.I es 's.
+The syntax of the
+.CW if
+command also comes directly from
+.I es .
+.LP
+From Bruce Ellis's
+.I mash ,
+the other programmable shell for Inferno,
+I took the
+.CW load
+command, the
+\f5"{}\fP
+syntax and the
+.CW <>
+redirection operator.
+.LP
+Last, but by no means least, S. R. Bourne,
+the author of the original
+.I sh ,
+the granddaddy of this
+.I sh ,
+is indirectly responsible for all these shells.
+That so much has remained unchanged from
+then is a testament to the power of his original
+vision.
binary files /dev/null b/doc/sh.pdf differ
--- /dev/null
+++ b/doc/styx.ms
@@ -1,0 +1,737 @@
+.ds TM \u\s-2TM\s+2\d
+.nr dT 6
+.nr XT 6
+.TL
+The Styx Architecture for Distributed Systems
+.AU
+Rob Pike
+Dennis M. Ritchie
+.AI
+Computing Science Research Center
+Lucent Technologies, Bell Labs
+Murray Hill, New Jersey
+USA
+.FS
+.FA
+Originally appeared in
+.I "Bell Labs Technical Journal" ,
+Vol. 4,
+No. 2,
+April-June 1999,
+pp. 146-152.
+.br
+Copyright © 1999 Lucent Technologies Inc. All rights reserved.
+.FE
+.AB
+A distributed system is constructed from a set of relatively
+independent components that form a unified, but geographically and
+functionally diverse entity. Examples include networked operating
+systems, Internet services, the national telephone
+switching system, and in general
+all the technology using today's diverse digital
+networks. Nevertheless, distributed systems remain difficult
+to design, build, and maintain, primarily because of the lack
+of a clean, perspicuous interconnection model for the
+components.
+.LP
+Our experience with two distributed operating systems,
+Plan 9 and Inferno, encourages us to propose such a model.
+These systems depend on, advocate, and generally push to the
+limit a fruitful idea: to present their
+resources as files in a hierarchical name space.
+The objects appearing as files may represent stored data, but may
+also be devices, dynamic information sources, interfaces to services,
+and control points. The approach unifies and provides basic naming,
+structuring, and access control mechanisms for all system resources.
+A simple underlying network protocol, Styx, forms
+the core of the architecture by presenting a common
+language for communication within the system.
+.LP
+Even within non-distributed systems, the presentation of services
+as files advantageously extends a familiar scheme for naming, classifying,
+and connecting to system resources.
+More important, the approach provides a natural way to build
+distributed systems, by using well-known technology for attaching
+remote file systems.
+If resources are represented as files,
+and there are remote file systems, one has
+a distributed system: resources available in one place
+are usable from another.
+.AE
+.SH
+Introduction
+.LP
+The Styx protocol is a variant of a protocol called
+.I 9P
+that
+was developed for the Plan 9 operating system[9man].
+For simplicity, we will use the name
+Styx throughout this paper; the difference concerns only the initialization of
+a connection.
+.LP
+The original idea behind Styx was to encode file operations between
+client programs and the file system,
+to be translated into messages for transmission on a computer network.
+Using this technology,
+Plan 9 separates the file server\(ema central repository for
+permanent file storage\(emboth from the CPU server\(ema large
+shared-memory multiprocessor\(emand from the user terminals.
+This physical separation of function was central to the original
+design of the system;
+what was unexpected was how well the model could be used to
+solve a wide variety of problems not usually thought of as
+file system issues.
+.LP
+The breakthrough was to realize that by representing
+a computing resource as a form of file system,
+many of the difficulties of making that resource available
+across the network would disappear naturally, because
+Styx could export the resource transparently.
+For example,
+the Plan 9 window system,
+.CW 8½
+[Pike91],
+is implemented as a dynamic file server that publishes
+files with names like
+.CW /dev/mouse
+and
+.CW /dev/screen
+to provide access to the local hardware.
+The
+.CW /dev/mouse
+file, for instance,
+may be opened and read like a regular file, in the manner of UNIX\*(TM device
+files, but under
+.CW 8½
+it is multiplexed: each client program has a private
+.CW /dev/mouse
+file that returns mouse events only when the client's window
+is the active one on the display.
+This design provides a clean, simple mechanism for controlling
+access to the mouse.
+Its real strength, though, is that the representation of the window system's
+resources as files allows Styx to make those resources available across the
+network.
+For example, an interactive graphics program may be run on a CPU server
+simply by having
+.CW 8½
+serve the appropriate files to that machine.
+.LP
+Note that although the resources published by Styx behave like files\(emthey
+have file names, file permissions, and file access methods\(emthey do not
+need to exist as standard files on disk.
+The
+.CW /dev/mouse
+file is accessed by standard file I/O mechanisms but is nonetheless a
+transient object fabricated dynamically by a running program;
+it has no permanent existence.
+.LP
+By following this approach throughout the system, Plan 9 achieves
+a remarkable degree of transparency in the distribution of resources[PPTTW93].
+Besides interactive graphics, services such as debugging, maintenance,
+file backup, and even access to the underlying network hardware
+can be made available across the network using Styx, permitting
+the construction of distributed applications and services
+using nothing more sophisticated than file I/O.
+.SH
+The Styx protocol
+.LP
+Styx's place in the world is analogous to
+Sun NFS[RFC][NFS] or Microsoft CIFS[CIFS], although it is simpler and easier to implement
+[Welc94].
+Furthermore, NFS and CIFS are designed for sharing regular disk files; NFS in particular
+is intimately tied to the implementation and caching strategy
+of the underlying UNIX file system.
+Unlike Styx, NFS and CIFS are clumsier at exporting dynamic device-like
+files such as
+.CW /dev/mouse .
+.LP
+Styx provides a view of a hierarchical, tree-shaped
+file system name space[Nee89], together with access information about
+the files (permissions, sizes, dates) and the means to read and write
+the files.
+Its users (that is, the people who write application programs),
+don't see the protocol itself; instead they see files that they
+read and write, and that provide information or change information.
+.LP
+In use, a Styx
+.I client
+is an entity on one machine that establishes communication with
+another entity, the
+.I server ,
+on the same or another machine.
+The client mechanisms may be built into the operating system, as they
+are in Plan 9 or Inferno[INF1][INF2], or into application libraries;
+a server may be part of the operating system, or just as often
+may be application code on a separate server machine. In any case, the
+client and server entities
+communicate by exchanging messages, and the effect is that the client
+sees a hierarchical file system that exists on the server.
+The Styx protocol is the specification of the messages that are exchanged.
+.LP
+At one level, Styx consists of messages of 13 types for
+.RS
+.IP \(bu
+Starting communication (attaching to a file system);
+.IP \(bu
+Navigating the file system (that is, specifying and
+gaining a handle for a named file);
+.IP \(bu
+Reading and writing a file; and
+.IP \(bu
+Performing file status inquiries and changes
+.RE
+.LP
+However, application writers simply code requests to open, read, or write
+files; a library or the operating system translates the requests
+into the necessary byte sequences transmitted over a communication
+channel. The Styx protocol proper specifies the interpretation of these
+byte sequences. It fits, approximately, at the OSI Session Layer level
+of the ISO standard classification.
+Its specification is independent of most details of machine architecture
+and it has been successfully used among machines of varying instruction
+sets and data layout.
+The protocol is summarized in Table 1.
+.KF
+.TS
+center box;
+l l
+--
+lfCW l.
+Name Description
+attach Authenticate user of connection; return FID
+clone Duplicate FID
+walk Advance FID one level of name hierarchy
+open Check permissions for file I/O
+create Create new file
+read Read contents of file
+write Write contents of file
+close Discard FID
+remove Remove file
+stat Report file state: permissions, etc.
+wstat Modify file state
+error Return error condition for failed operation
+flush Disregard outstanding I/O requests
+.TE
+.ce 100
+.ps -1
+Table 1. Summary of Styx messages.
+.ps
+.ce 0
+.KE
+.LP
+In use, an operation such as
+.P1
+open("/usr/rob/.profile", O_READ);
+.P2
+is translated by the underlying system into a sequence of Styx messages.
+After establishing the initial connection to the
+file server, an
+.CW attach
+message authenticates the user (the person or agent accessing the files) and
+returns an object called a
+.CW FID
+(file ID) that represents the root of the hierarchy on the server.
+When the
+.CW open()
+operation is executed, it proceeds as follows.
+.RS
+.IP \(bu
+A
+.CW clone
+message duplicates the root
+.CW FID ,
+returning a new
+.CW FID
+that can navigate the hierarchy without losing the connection to the root.
+.IP \(bu
+The new
+.CW FID
+is then moved to the file
+.CW /usr/rob/.profile
+by a sequence of
+.CW walk
+messages that step along, one path component at a time
+.CW usr , (
+.CW rob ,
+.CW .profile ).
+.IP \(bu
+Finally, an
+.CW open
+message checks that the user has permission to read the file,
+permitting subsequent
+.CW read
+and
+.CW write
+operations (messages) on the
+.CW FID .
+.IP \(bu
+Once I/O is completed, the
+.CW close
+message will release the
+.CW FID .
+.RE
+.LP
+At a lower level, implementations of Styx depend only on a reliable,
+byte-stream Transport communications layer. For example, it runs over either
+TCP/IP, the standard transmission control protocol
+and Internet protocol,
+or Internet link (IL), which is a sequenced, reliable datagram protocol
+using IP packets.
+It is worth emphasizing, though, that the model does not require the
+existence of a network to join the components; Styx runs fine
+over a Unix pipe or even using shared memory.
+The strength of the approach is not so much how it works over a network
+as that its behavior over a network is identical to its behavior locally.
+.SH
+Architectural approach
+.LP
+Styx, as a file system protocol, is merely a component in a
+more encompassing approach
+to system design: the presentation of resources as files.
+This approach will be discussed using a sequence of examples.
+.SH
+.I "Example: networking
+.LP
+As an example, access to a TCP/IP network in Inferno and Plan 9 systems
+appears as a piece of a file system, with (abbreviated) structure
+as follows[PrWi93]:
+.P1
+/net/
+ dns/
+ tcp/
+ clone
+ stats
+ 0/
+ ctl
+ status
+ data
+ listen
+ 1/
+ ...
+ ...
+ ether0/
+ 0/
+ ctl
+ status
+ ...
+ 1/
+ ...
+ ...
+.P2
+This represents a file system structure in which one can name, read, and write `files' with
+names like
+.CW /net/dns ,
+.CW /net/tcp/clone ,
+.CW /net/tcp/0/ctl
+and so on;
+there are directories of files
+.CW /net/tcp
+and
+.CW /net/ether0 .
+On the machine that actually has the network interface, all of these
+things that look like files are constructed by the kernel drivers that maintain
+the TCP/IP stack; they are not real files on a disk.
+Operations on the `files' turn into operations sent to the device drivers.
+.LP
+Suppose an application wishes to establish a connection over TCP/IP to
+.CW www.bell-labs.com .
+The first task is to translate the domain name
+.CW www.bell-labs.com
+to a numerical internet address; this is a complicated process, generally
+involving communicating with local and remote Domain Name Servers.
+In the Styx model, this is done by opening the file
+.CW /dev/dns
+and writing the literal string
+.CW www.bell-labs.com
+on the file; then the same file is read.
+It will return the string
+.CW 204.178.16.5
+as a sequence of 12 characters.
+.LP
+Once the numerical Internet address is acquired, the connection must be established;
+this is done by opening
+.CW /net/tcp/clone
+and reading from it a string that specifies a directory like
+.CW /net/tcp/43 ,
+which represents a new, unique TCP/IP channel.
+To establish the connection,
+write a message like
+.CW "connect 204.178.16.5
+on the control file for that connection,
+.CW /net/tcp/43/ctl .
+Subsequently, communication with
+.CW www.bell-labs.com
+is done by reading and
+writing on the file
+.CW /net/tcp/43/data .
+.LP
+There are several things to note about this approach.
+.RS
+.IP \(bu
+All the interface points look like files, and are
+accessed by the same I/O mechanisms already available in
+programming languages like C, C++, or Java. However, they do not
+correspond to ordinary data files on disk, but instead are creations
+of a middleware code layer.
+.IP \(bu
+Communication across the interface, by convention, uses printable character strings where
+feasible instead of binary information. This means that the syntax
+of communication does not depend on CPU architecture or language details.
+.IP \(bu
+Because the interface, as in this example with
+.CW /net
+as the interface with networking facilities, looks like a piece of a
+hierarchical file system, it can easily and nearly automatically
+be exported to a remote machine and used from afar.
+.RE
+.LP
+In particular, the Styx implementation encourages a natural way of providing
+controlled access to networks.
+Lucent, like many organizations, has an internal network not
+accessible to the international Internet, and has a few
+gateways between the inside and outside networks.
+Only the gateway machines are connected to both, and they implement
+the administrative controls for safety and security.
+The advantage of the Styx model is the ease with which
+the outside Internet can be used from inside.
+If the
+.CW /net
+file tree described above is provided on a gateway machine,
+it can be used as a remote file system from machines on the
+inside. This is safe, because this connection is one-way:
+inside machines can see the external network interfaces,
+but outside machines cannot see the inside.
+.SH
+.I "Example: debugging
+.LP
+A similar approach, borrowed and generalized from the UNIX
+system [Kill], is useful for controlling and discovering the status
+of the running processes in the operating system.
+Here a directory
+.CW /proc
+contains a subdirectory for each process running on the
+system; the names of the subdirectories correspond to
+process IDs:
+.P1
+/proc/
+ 1/
+ status
+ ctl
+ fd
+ text
+ mem
+ ...
+ 2/
+ status
+ ctl
+ ...
+ ...
+.P2
+The file names in the process directories refer to various aspects
+of the corresponding process:
+.CW status
+contains information about the state of the process;
+.CW ctl ,
+when written, performs operations like pausing, restarting,
+or killing the process;
+.CW fd
+names and describes the files open in the process;
+.CW text
+and
+.CW mem
+represent the program code and the data respectively.
+.LP
+Where possible, the information and control are again
+represented as text strings. For example, one line
+from the
+.CW status
+file of a typical process might be
+.DS
+.CW "samterm dmr Read 0 20 2478910 0 0 ...
+.DE
+which shows the name of the program, the owner, its state, and several numbers
+representing CPU time in various categories.
+.LP
+Once again, the approach provides several payoffs.
+Because process information is represented in file form,
+remote debugging (debugging programs on another machine)
+is possible immediately by remote-mounting the
+.CW /proc
+tree on another machine.
+The machine-independent representation of information means
+that most operations work properly even if the remote machine
+uses a different CPU architecture from the one doing the
+debugging.
+Most of the programs that deal
+with status and control contain no machine-dependent parts
+and are completely portable.
+(A few are not, however: no attempt is made to render the
+memory data or instructions in machine-independent form.)
+.SH
+.I "Example: PathStar\*(TM Access Server
+.LP
+The data shelf of Lucent's PathStar Access Server[PATH] uses Styx to connect
+the line cards and other devices on the shelf to the control computer.
+In fact, Styx is the protocol for high-level communication on the backplane.
+.LP
+The file system hierarchy served by the control computer includes a structure
+like this:
+.P1
+/trip/
+ config
+ admin/
+ ospfctl
+ ...
+ boot/
+ 0/
+ ctl
+ eeprom
+ memory
+ msg
+ pack
+ alarm
+ ...
+ 1/
+ ...
+/net/
+ ...
+.P2
+The directories under
+.CW /net
+are similar to those in Plan 9 or Inferno; they form the interface to the
+external IP network.
+The
+.CW /trip
+hierarchy represents the control structure of the shelf.
+.LP
+The subdirectories under
+.CW /trip/boot
+each provide access to one of the line cards or other devices in the shelf.
+For example, to initialize a card one writes the text string
+.CW reset
+to the
+.CW ctl
+file of the card, while bootstrapping is done by copying the control
+software for the card into the
+.CW memory
+file and writing a
+.CW reset
+message to
+.CW ctl .
+Once the line card is running,
+the other files present an interface to the higher-level structure of the device:
+.CW pack
+is the port through which IP packets are transferred to and from the card,
+.CW alarm
+may be read to discover outstanding conditions on the card, and so on.
+.LP
+All this structure is exported from the shelf using Styx.
+The external element management software (EMS) controls and monitors the
+shelf using Styx operations.
+For example, the EMS may read
+.CW /trip/boot/7/alarm
+and discover a diagnostic condition.
+By reading and writing the other files under
+.CW /trip/boot/7/ ,
+the card may be taken off line, diagnosed, and perhaps reset or substituted,
+all from the system running the EMS, which may be elsewhere in the network.
+.LP
+Another example is the implementation of SNMP in the PathStar Access Server.
+The functionality of SNMP is usually distributed through the various components
+of a network, but here it is a straightforward adaption process,
+running anywhere in the network, that translates SNMP requests to Styx
+operations in the network element.
+Besides dramatically simplifying the implementation, the natural
+ability for aggregation permits
+a single process to provide SNMP access to an arbitrarily complex network subsystem.
+Yet the structure is secure: the file-oriented nature of the operations make it
+easy to establish standard authentication and security controls to guarantee
+that only trusted parties have access to the SNMP operations.
+.LP
+There are local benefits to this architecture, as well.
+Styx provides a single point in the design where control can be separated
+from the details of the underlying fabric, isolating both from changes in the
+other. Components become more adaptable: software can be upgraded
+without worrying about hidden dependencies on the hardware,
+and new hardware may be installed without updating the control
+software above.
+.SH
+Security issues
+.LP
+Styx provides several security mechanisms for
+discouraging hostile or accidental actions that injure the integrity
+of a system.
+.LP
+The underlying file-communication protocol includes
+user and group identifiers that a server may check against
+other authentication.
+For example, a server may check, on a request to open a file,
+that the user ID associated with the request is permitted to
+perform the operation.
+This mechanism is familiar from general-purpose operating
+systems, and its use is well-known.
+It depends on passwords or stronger mechanisms for authenticating
+the identity of clients.
+.LP
+The Styx approach of providing remote resources
+as file systems over a network encourages genuinely secure access
+to the resources in a way transparent to applications, so that
+authentication transactions need not be provided as part of each.
+For example, in Inferno, the negotiation of an initial connection
+between client and server may include installation of any of
+several encrypting or message-digesting protocols that
+supervise the channel.
+All application use of the resources provided by the server
+is then protected against interference, and the server
+has strong assurance that its facilities are being used in
+an authorized way.
+This is relevant both for general-purpose file servers,
+and, in the telephony field, is especially useful for safe
+remote administration.
+.SH
+Summary
+.LP
+Presentation of resources as a piece of a possibly remote file system
+is an attractive way of creating distributed systems that treads a
+path between two extremes:
+.IP 1
+All communication with other parts of the system is by
+explicit messages sent between components.
+This communication differs in style from applications' use
+of local resources.
+.IP 2
+All communication is by means of
+closely shared resources: the CPU-addressable memory in
+various parts is made directly available across a big network;
+applications can read and write far-away objects exactly as
+they do those on the same motherboard as their own CPU.
+.LP
+Something like the first of these extremes is usually more evident
+in today's systems, although either the operating system or software
+layered upon it usually paper over some of the rough spots.
+The second remains more difficult to approach, because
+networks (especially big ones like the Internet) are not very
+reliable, and because
+the machines on them are diverse in processor architecture
+and in installed software.
+.LP
+The design plan described and advocated in this paper
+lies between the two extremes.
+It has these advantages:
+.IP \(bu
+.I "A simple, familiar programming model for reading and writing named files" .
+File systems have well-defined naming, access, and permissions structures.
+.IP \(bu
+.I "Platform and language independence" .
+Underlying access to resources is
+at the file level, which is provided nearly everywhere, instead
+of depending on facilities available only with particular languages
+or operating systems.
+C++ or Java classes, and C libraries can be constructed
+to access the facilities.
+.IP \(bu
+.I "A hierarchical naming and access control structure" .
+This encourages clean
+and well-structured design of resource naming and access.
+.IP \(bu
+.I "Easy testing and debugging" .
+By using well-specified, narrow interfaces
+at the file level, it is straightforward to observe the communication
+between distributed entities.
+.IP \(bu
+.I "Low cost" .
+Support software, at both client and server,
+can be written in a few thousand lines
+of code, and will occupy only small space in products.
+.LP
+This approach to building systems is successful in the general-purpose
+systems Plan 9 and Inferno;
+it has also been used to construct systems specialized for telephony, such
+as Mantra[MAN] and the PathStar Access Server.
+It supplies a coherent, extensible structure both to the internal communications
+within a single system and external communication between heterogeneous
+components of a large digital network.
+.LP
+.SH
+References
+.nr PS -1
+.nr VS -1
+.IP [NFS] 11
+R. Sandberg, D. Goldberg, S. Kleiman, D. Walsh, and
+B. Lyon,
+``Design and Implementation of the Sun Network File System'',
+.I "Proc. Summer 1985 USENIX Conf." ,
+Portland, Oregon, June 1985,
+pp. 119-130.
+.IP [RFC] 11
+Internet RFC 1094.
+.IP [9man] 11
+.I "Plan 9 Programmer's Manual" ,
+Second Edition,
+Vol. 1 and 2,
+Bell Laboratories,
+Murray Hill, N.J.,
+1995.
+.IP [Kill84] 11
+T. J. Killian,
+``Processes as Files'',
+.I "Proc. Summer 1984 USENIX Conf." ,
+June 1984, Salt Lake City, Utah, June 1984, pp. 203-207.
+.IP [Pike91] 11
+R. Pike,
+``8½, the Plan 9 Window System'',
+.I "Proc. Summer 1991 USENIX Conf." ,
+Nashville TN, June 1991, pp. 257-265.
+.IP "[PPTTW93] " 11
+R. Pike, D.L. Presotto, K. Thompson, H. Trickey, and P. Winterbottom, ``The Use of Name Spaces in Plan 9'',
+.I "Op. Sys. Rev." ,
+Vol. 27, No. 2, April 1993, pp. 72-76.
+.IP [PrWi93] 11
+D. L. Presotto and P. Winterbottom,
+``The Organization of Networks in Plan 9'',
+.I "Proc. Winter 1993 USENIX Conf." ,
+San Diego, Calif., Jan. 1993, pp. 43-50.
+.IP [Nee89] 11
+R. Needham, ``Names'', in
+.I "Distributed systems" ,
+edited by S. Mullender,
+Addison-Wesley,
+Reading, Mass., 1989, pp. 89-101.
+.IP [CIFS]
+Paul Leach and Dan Perry, ``CIFS: A Common Internet File System'', Nov. 1996,
+.I "http://www.microsoft.com/mind/1196/cifs.htm" .
+.IP [INF1]
+.I "Inferno Programmer's Manual",
+Third Edition,
+Vol. 1 and 2, Vita Nuova Holdings Limited, York, England, 2000.
+.IP [INF2]
+S.M. Dorward, R. Pike, D. L. Presotto, D. M. Ritchie, H. Trickey,
+and P. Winterbottom, ``The Inferno Operating System'',
+.I "Bell Labs Technical Journal"
+Vol. 2,
+No. 1,
+Winter 1997.
+.IP [MAN]
+R. A. Lakshmi-Ratan,
+``The Lucent Technologies Softswitch\-Realizing the Promise of Convergence'',
+.I "Bell Labs Technical Journal" ,
+Vol. 4,
+No. 2,
+April-June 1999,
+pp. 174-196.
+.IP [PATH]
+J. M. Fossaceca, J. D. Sandoz, and P. Winterbottom,
+``The PathStar Access Server: Facilitating Carrier-Scale Packet Telephony'',
+.I "Bell Labs Technical Journal" ,
+Vol. 3,
+No. 4,
+October-December 1998,
+pp. 86-102.
+.IP [Welc94]
+B. Welch,
+``A Comparison of Three Distributed File System Architectures: Vnode, Sprite, and Plan 9'',
+.I "Computing Systems" ,
+Vol. 7, No. 2, pp. 175-199 (1994).
+.nr PS +1
+.nr VS +1
binary files /dev/null b/doc/styx.pdf differ