|
About this page
This page is for developers and people learning about guile, who want
ideas to persue. If you've done any of these things, or want advice
about them then please feel free to do so on the guile mailing list!
What's this page is about
People occasionally ask if there's anything they can work on in
Guile. In the past, I've just been dumb and written up a separate
list of ideas in response to each message; so I forget things, I waste
a lot of time retyping, and ideas that occur to me when nobody's
asking me disappear into the ether. So I've decided to write them
down.
Also, these are just the things that have come to my head over the
past few months. Each idea kind of argues for its own worldview, but
I don't actually claim that they're well-developed, or that the
functional boundaries are right, or anything. As a friend of mine
used to say, in a similar spirit: ``Why not take two --- they're
small!''
This is only meant as a source of ideas, not as a statement
of what I think is important, where I think Guile should go, or what
I'm willing to incorporate into some ``official'' distribution of
something. People should hack on what pleases them. These are
basically the things I wish I had time to do.
I hope this is helpful!
--- Jim Blandy
I've added a little here, mostly pointing to some additional
information on various bits, and removing some of the bits that've
been finished and added to guile, like guardians
--- Greg Harvey
If you've got your own list of Guile modules or features you'd
like to see, we'll put a link to it here.
Here are some things I'd like to see people write and distribute as
separate Guile modules.
Items are in most-recently-added-or-modified order.
- Clean SLIB integration
-
This may need to wait for the new module system, but it would be
nice to have a solid integration of SLIB into Guile, so that SLIB
files appear as first-class Guile modules.
- Server-side scripting
-
I'm thinking of something like a translator that reads a mix
of HTML-like tags and Scheme code --- basically, something like
quasiquote, except that it builds HTML structure, instead of list
structure. The translator would compile HTML-like things into
expressions that construct a tree which we can finally spit out as
HTML.
PHP has become really popular, but there's really no such thing as
a little language. I bet we'll see the same pattern with that
that we've seen with Perl and Tcl --- the interpreter will start
out small and fast, but then as people use it for more serious
work, it'll start acquiring real control structures, real
functions, more datatypes, ... until it'll just be another
poorly-implemented lisp with studly libraries. That's basically
what Tcl 8.0 is.
I don't know for sure, but I suspect that MHTML invented their
own language too. If so, the same rules apply.
We should do it right, by taking the features of PHP and MHTML
and giving them to Guile. Someone who does web application
development should do this, so it'll get done right. I don't do
that much web hacking myself, so I'd get the details all wrong.
Note that it's really easy to hack something up that works
here and there. This project will only have a significant impact
if it's an industrial-strength job.
See Olin Shivers'
``net.tar.gz''.
- IEEE 754 recommended functions and predicates
-
Guile should provide the functions described in the appendix to
IEEE 754. They're handy.
- Resurrect the Mesa interface
-
Long ago, Guile had an interface to the Mesa 3-D graphics library,
which is compatible with OpenGL. (See freshmeat for details.)
This code could probably be resurrected pretty easily.
Ideally, of course, this would be combined with a Mesa widget
for GTK+. :)
This is kind of stupid, but one thing you could use this for
is an origami program. I'd like to be able to see the
relationship between the folded and unfolded sheets. This is one
of those things that's not worth coding in C, but would be fun to
whip up in an interpreted language.
- Simple Network Management Protocol interface
-
There's a library called UCD-SNMP (search freshmeat for it) which
might be fun to hook up to Guile. I'd love to be able to combine
UCD-SNMP with the GTK+ canvas widget and get network utilization
graphs from my router.
- Bug-tracking system
-
I'd like something akin to Gnats, but written in Guile. I'm sure
we could do better than Gnats, and this would give us a chance to
focus on the needs of open source development --- for example, the
bug list should be open, and viewable from the web.
- Value history
-
When you're using Guile interactively, it's really common to want
to operate on a value returned by one of the previous
instructions. Mathematica and GDB automatically stash the result
of each expression in a variable (or something like a variable),
so you can refer to it later.
I have in mind something like this:
guile> (list 1 2 3)
$1 => (1 2 3)
guile> (cons 0 $1)
$2 => (0 1 2 3)
guile> (set-car! (cdr $2) 'yowza)
$3 => yowza
guile> $1
$4 => (yowza 2 3)
(Bengt Kleberg recommended the ``$1 => mumble'' syntax, on the
grounds that it resembles the notation RnRS uses to show what an
expression evaluates to. And indeed, $1 will evaluate to mumble.)
The current repl doesn't print the vale of expressions returning
#<unspecified>, and it shouldn't assign such values to value
history variables either.
- Directory walker with list of predicates
-
People have posted a bunch of functions for walking directory
trees, modeled more or less after the Unix `find' command.
They're essentially of the form (find DIRECTORY PROC), and apply
PROC to each file they find in the directory tree DIRECTORY.
It occurs to me that it might be convenient to actually have
`find' accept a list of procedures: (find DIRECTORY PROC ...), and
for each file found, apply each PROC successively, until one
returns a false value. That way, you could do things like this:
(find "." (glob ".deps") directory?
(lambda (d)
... now do something with the .deps directory d ...))
I'm imagining `glob' to be a function that accepts a filename
wildcard pattern and returns a predicate that likes filenames that
match the wildcard.
Maciej Stachowiak and others have suggested, as a convention,
that any function which accepts a predicate as an argument, and
applies that predicate to filenames, should also accept a string
as that argument, and treat that string as a wildcard pattern.
Thus, the code above would become:
(find "." ".deps" directory?
(lambda (d) ...))
Now we're starting to get friendly.
- smart dumping
-
This is kind of a dumb idea; I have no idea whether it's even
worth thinking about.
Would it be possible to write a function which walked data
structures in the Scheme heap, and wrote out, directly from
Scheme, a valid ELF shared library? Then you could load a module
and spit it back out as a shared library. While walking the heap,
we have all the information we need to emit the right relocs.
The code is certainly machine- and ABI-dependent.
Does this have any advantage over the freezer? The freezer
writes out initialized C data structures, which you can then
compile into shared libraries; what's wrong with that? I guess
the C compiler isn't involved, which is one more variable
eliminated. But freezing is much more portable.
- Sound/sample processing library
-
I'd love to use Guile to munge sound samples, try out various
effects, etc. The perfect complement to a sound-processing
library would be a nice interface to the audio hardware. Look
into the Enlightened Sound Daemon (esd), and audiofile, a library
that understands how to load a variety of different audio file
formats. (Tom Tromey pointed me at esd and audiofile.)
Bill Schottstaedt writes:
I've written a C library of basic audio functions (support for
hardware, headers, data types, etc) called sndlib
which is already tied into Guile in my sound
editor. And a ton of sound-processing functions can be found
in clm
(a Common Lisp and C based Music V implementation).
If there's interest, I could package all this up in some
pretty way; or perhaps help anyone else who wants to do something
along these lines. As I understand the copyright issue (I'm no
lawyer), Stanford owns the copyright since I'm doing this work as
their employee; they, however, have said the software author can
decide distribution policy (or whatever the word is), so I placed
the sound editor under the GPL, and have always made all the code
freeware available via anonymous ftp.
- Database engine interfaces
-
This is pretty important for web scripting, but also just a
generally handy thing.
Perl has DBI, which I think we should use a model; here's the
description from CPAN:
The Database Interface. The Perl DBI initiative has
standardized the interface to a number of commercial database
engines, so that you can move from, say, Oracle to Sybase with a
minimum of effort. You'll find DBD::DB2, DBD::Informix,
DBD::Oracle, DBD::QBase, DBD::Sybase, DBD::MySQL, and DBD:mSQL
inside the DBD module set.
The job here is to discern the important ideas in DBI's
design, figure out the nicest way to transpose those into Scheme,
write that up, and provide at least one implementation, so that
people can write database drivers that meet the spec, and use the
implementation as a reference.
- Database manager interfaces
-
These would be interfaces to Berkeley DB, GDBM, NDBM, DBM, etc.
I think the difference between a ``database engine'' and a
``database manager'' is that the former usually supports SQL, and
handles multiple readers and writers, whereas the latter just
implements the data structure on disk, and leaves questions of
synchronization and how to actually arrange data usefully in the
hands of the caller.
Just as discussed in the ``Database engine interface'' entry
elsewhere in this list, we want a common interface to these
libraries, so people can write code that will operate with any
file format.
- Query languages
-
Logic programming languages make great database query languages
--- much nicer and more consistent than SQL. It would be really
cool if someone could look into the work Richard Salter and Chris
Haynes did on embedding backtracking and unification in Scheme, or
Per Bothner's similar work, and then use that to produce the best
database front end ever.
Of course, this should ride on the
- GIMP interface
-
Peter Mattis did do a Guile/GIMP interface at one point, but we're
not the standard there; they're still using SIOD. Someone who
uses both Guile and the GIMP needs to pick this up, turn it into a
package people can use, and do whatever's needed to get the GIMP
people to accept it as their standard. If there are critical
Guile changes necessary (Make it smaller? Can do!), I want to
help with that.
Basically, I think all we need here is a module that exports
the GIMP's functions. Should be real easy.
- C parser
-
It would be cool to hook up a full parser for ANSI C to Guile.
Then we could use it to parse header files and generate Guile
interfaces, scan Guile code for missing argument typechecks, cases
where we need to call scm_return_first or scm_remember, unbalanced
calls to SCM_DEFER_INTS. We could even switch Guile to an
explicit-marking GC, and then use the checker to catch errors in
the explicit marking.
Tom Lord did this for Systas; perhaps
his work could be ported back to Guile.
For way extra points, implement a C++ parser. Ouch.
- A FastCGI interface
-
It would be nice to have Guile implement the FastCGI interface,
turning each HTTP request into a function call, with arguments and
environment broken out.
- ABI-conformant packed data structure interface
-
It would be nice if Guile could manipulate arbitrary C data
structures. Basically, you'd take the C declaration for a
structure, figure out its layout at the bit/byte offset level
(given a particular ABI), and generate a bunch of accessors, and a
new opaque type for pointers to that structure.
We're not going for type safety here --- there should be an
operation to turn these opaque values into integers and back, or
to treat the data in a string as one of them. But it would be
nice to provide some error checking.
If the ABI were something you could choose at run-time, that
could make Guile a powerful system for doing cross-platform
munging. "Sure, I know exactly how a 6-bit field would be laid
out on the i960!". Well, okay --- maybe that's not thrilling.
But I still think it would be cool.
- Henry Spencer's regexp matcher
-
I'd like to see someone package up Henry Spencer's latest regexp
engine (which supports Unicode's UTF-8 encoding!) as a dynamically
linked module for Guile. Actually, I'd like to incorporate this
into the Guile core. Our present code just uses whatever regexp
engine is in the system's C library, which is sometimes pretty
pathetic.
- HTTP routines
-
It would be cool if people could use Guile to implement web robots
and the like. Tim Pierce started to work on this, but it's not
finished.
- General URL functions
-
This would be a set of functions for just retriving any URL. I
think the WWW Consortium has a library which implements
everything.
- SGML and DSSSL
-
As long as we're supporting multiple languages, why not DSSSL?
Craig Brozefsky <craig@red-bean.com> has already attached an
SGML language parser to Guile.
- Mailbox support
-
Guile should have routines for doing full RFC 822 parsing, MIME
encoding, etc., to help people writing mailbots.
- Emacs-like buffers, for file handling.
-
Everyone is used to the sed/awk/perl model of file processing ---
you munge a line at a time, and maintain state to handle
multi-line things. That's just the way it's done.
But actually, there's a totally different system which works a
lot better for some applications, exemplified by Emacs. Emacs
lisp gives you buffers with very fast search, insert, and delete
operations. You don't have to process the data in any order;
there are no line boundaries to obscure the semantic structure of
the content, if the file isn't really line-structured; and so on.
So basically, this idea is, "implement Emacs buffers for Guile,
with all the searching, editing, and I/O facilities, but none of
the redisplay support."
(Greg) Initial code implementing these is available here
It's not complete, but could be used to build something bigger and
better (I intend to go back and reimplement these with goops
classes, to allow for more flexible usage).
- Cool I/O ports
-
Guile should be able to talk to compression libraries. You should
be able to hand an ordinary output port to a function, and have it
give you a new port, where data written to the new port gets
written compressed to the original port. And the reverse for
uncompression and input ports.
The same principle applies to any kind of stream transformation:
- encryption
- uu/base64 encoding, or error correcting codes
- Unicode/JIS/ISO-8859 conversion
- CR/LF vs. LF conversion
- telnet (for implement FTP)
- line and column number counting (the port just passes data
through unchanged, but counts the number of characters and
newlines, and has extra functions that let you read and set the
counters).
Guile's port implementation already has the infrastructure
needed to implement ports that do arbitrary things with their
streams (see the scm_ptobfuns structure). It's just
waiting to be used.
- SSLeay
-
The quintessential example of the above. SSLeay is a library that
implements the Secure Socket Layer protocol, the foundation of
secure http. It's basically a generic authentication and privacy
layer for network connections. I think PRMS uses it too.
- Adobe Document Structuring Conventions parser
-
Make it trivial to write psnup, and such. Make it trivial to
produce output that conforms to the DSC.
- Functional PostScript
-
Imagine taking the primitives of PostScript and providing them in
a more functional-language kind of way. That's what Olin
Shivers' group has done.
FPS
is a portable system for doing device-independent, resolution-
independent graphics from Scheme programs. It is PostScript, with
the Forth computational engine replaced with Scheme. At present,
it runs on SCSH.
- Occam-like thread control structures
-
The Occam language, designed for the INMOS transputer, made
parallalism as concise to use as `let'. It was a much nicer way
of thinking about threads, I think. It would be cool if someone
implemented the interesting Occam features in Guile:
- channels
- These are one-deep message queues, with the right blocking
behavior; Guile's channels would carry objects.
- SEQ
- Well, this is just begin.
- PAR
- Like begin, but execute all the subexpressions in
parallel.
And so on.
- RenderMan interface
-
It would be nice to be able to generate RenderMan scene
description files using Guile code.
Here are some languages I'd love to see translated into Guile.
Items are in most-recently-added-or-modified order.
- Tcl 8.0
- Tcl's syntax is remarkably simple for a language its age; I
quite like it. Especially with the semantic cleanups made for
Tcl 8.0, we should be able to do a good integration here.
Ian Bicking <bickiia@earlham.edu> has
done some work on a translator.
The first cut was an interpreter, partially evaluated using Similix
to produce a compiler; the latest version has been rewritten by hand.
- PHP
- The simple server-side scripting language.
- MetaHTML
- A more complex server-side scripting system, but a new
language, so still probably clean enough to tackle.
- Python
- Quite a pretty language, clean in both syntax and semantics.
("Pure in body and mind.") Datatypes seem very friendly with
Scheme's, so it should be possible to do a very satisfying
integration here.
- Emacs Lisp
- An interesting challenge. I've got a decent solution for
reconciling the nil/()/#f issue, which this translator should
use. Mikael Djurfeldt has some ideas about this too.
- Perl
- This is a herculean task, because Perl's syntax and semantics
are so complicated. Hats off to whoever even tries this.
Here are some improvements I'd like to see made to the core Guile
interpreter.
- Internationalization/Multilingualization
-
Torbjörn Gannholm has kindly offered to work on this.
I just got back from a conference in Japan about multilingual
information processing in free software, organized by the MULE
folks. While there I put together a pretty clear idea of how
I want Guile to work:
- Guile should have a separate "byte array" and "string"
types. Probably the byvect stuff in unif.c is a decent
"byte array" type already, but we may need to beef up
support for it.
- All characters should be Unicode characters, and all strings
are strings of Unicode characters. (We'll need a read
syntax for Unicode characters; I think Marc Feely has a
proposal for this.)
- I/O ports should know what encoding they're reading or
writing (ISO Latin-1 by default), and do the appropriate
translations. Some structure that allows us to layer
translators on top of raw ports might be nice, to decouple
the character set support from the I/O source support.
- Internally, strings should be represented as UTF-8 encoded strings;
this is the representation that C code linked with Guile
will see, and operate on. Guile should provide convenient
functions to ease the complexity of handling these.
- However, Scheme code will still index strings by character,
not byte. The expression
(string-ref s 1)
will always return the second character of s, even
if the first character is several bytes long. The fact that
the elements of the string are of varying width will be
concealed from Scheme code.
This means that string-ref and
string-set! will no longer be constant time
operations. Oh well; people usually manipulate strings using
searching, substring extraction, and concatenation anyway;
the complexity of those operations is unaffected.
- Each string object should record the byte position of the
first non-single-byte character, so we can still index
strings containing only fixed-width characters (ASCII) in
constant time.
This isn't perfect, but here's my rationale:
My driving concern is what I'll call the "pass-through"
problem. In the process of carrying out a user's request, each
piece of data will pass through many different modules. For
example, data might be read from an I/O port, stored in a
database, and then retrieved from that database and displayed by a
GUI toolkit. If any module fails to handle multilingual data
correctly, the user will experience the overall system as
non-multilingual.
This means that it's not enough to merely have most modules
handle multilingual text correctly. They must all do it, if we
are to earn the user's trust. We will need to police Guile
modules carefully, put pressure on the authors of non-multilingual
modules, support them with plenty of helpful routines and
documentation, mark entries in the public module archive as
"multilingual-safe", and so on.
But if we're to impose this burden on developers, it must be a
reasonable burden. We don't actually have any authority; we rely
on their good will. If we require them to become experts on every
character set and encoding on the planet, that's too much; they
simply won't bother. If we require developers to do too much,
they will do very little.
The proposal above presents the developer with a single
character set, whose semantics are clearly documented. Developers
working in C must also cope with a variable-width encoding, which
does complicate code, but it has some nice properties that
ameliorate the complexity somewhat.
It has been suggested that Guile simply use Unicode encoded in
sixteen-bit characters throughout, as Java does. However, this
isn't viable; the 16-bit space for Unicode is almost full, and the
Taiwanese have a ton of characters they want code points for. If
you represent them using the Unicode ``surrogate characters'',
then you've got a variable-width encoding again; you might as well
use UTF-8 and save memory, since you're not saving any complexity.
It has also been suggested that Guile use two or three
different string representations, with eight, sixteen, or
thirty-two bits per character. Guile could automatically select
the most dense representation capable of holding the data at hand.
However, this would require everyone working in C to write out
three copies of their string-processing code. Each copy would be
simpler than the code for handling UTF-8, because it would be
working with a fixed-width encoding, but it's my sense that a
single UTF-8 loop is less hair than three fixed-width loops.
So, I'd love to have routines to convert text between Unicode
and all the various local encodings --- the JIS standards, BIG5,
ISO 8859, and so on. Guile should try to use the gconv
interface in the GNU C library, then iconv, and then
whatever else is available.
Henry Spencer's latest regexp engine handles UTF-8, but as of
this writing, it hadn't been optimized yet.
Guile also needs some kind of gettext interface. We could add
a new syntax for translatable strings like
#"This is a translatable string."
- Use GMP for bignum arithmetic
-
At the moment, Guile uses a homebrew bignum implementation. GMP,
Torbjorn Granlund's multi-precision arithmetic package, is faster.
Guile should be changed to use GMP if it is installed, and omit
bignum support if GMP is absent.
It would be nice to implement rational numbers as part of
this.
- R5RS support
-
Right now Guile only supports R4RS. We should be able to use the
module system to let the user choose which dialect they want to
use on a module-by-module basis. I think this should be tied in
with Chris Hanson's work on a byte compiler.
- Custom buffered I/O
-
Guile has several different kinds of I/O ports. Those that
talk to the outside world are implemented on top of the ubiquitous
C standard I/O FILE buffered streams. This leads to a
few problems:
- We have to use fgets for speed, but it's difficult
to handle lines containing null characters, given
fgets's interface. So we use ftell to find
out how much we've read with fgets. But that doesn't
work on sockets. So on sockets we fall back to our old, slow
routine based on getc.
- We have to use unbuffered input sockets, because standard
I/O streams only promise you one buffer, so you can't mix read
and write operations, to implement a network protocol, say. You
have to do an fflush between a write and a read, and an
fseek or something equivalent between a read and a
write. This is stupid.
- There's no way to tell whether there's input immediately
available on a buffered stream. You can get the underlying file
descriptor and do fcntl magic on that, but that won't
tell you whether there are characters waiting in the buffer.
You get the idea. The thing is, every Unix system has
read, write, and seek, and I don't know
of any system that doesn't have select. So we could
actually implement our own buffering port implementation, and
address all these problems.
We'd actually do better, because people have had some good
ideas since standard I/O was implemented. For example, we could
follow the lead of the libio library, and expose the buffer
directly to the consumer, thus avoiding some copies. We could run
regexp matches directly in the buffer. We could implement our own
definition of line boundaries with little penalty. Each port
could have a magic writable shared substring object that gave
Scheme code direct access to the "current line", with no copies.
(Well, maybe that's not such a hot idea. But that's what Perl
does.)
Having our own buffered stream implementation would also allow
us to start acquiring cool optimizations strictly below the
interface. The presence of the interface would protect Guile from
whatever weird system-specific stuff we wanted to do for speed.
(Greg) Gary Houston has been working on this; patches against
cvs guile (for the brave) are available at Gary's web
page.
- Fast string implementations
-
Guile should implement the substring operation by sharing memory
with the original string, and using copy-on-write (COW) to
preserve the right semantics in case something gets side-effected.
The garbage collector would need to have some policy for throwing
away large substrings referenced only by small substrings, perhaps
by copying strings if they are small enough.
Once we had the copy-on-write system in place, people wouldn't
need to use explicitly shared substrings for efficiency any more,
and we'd be able to make explicitly shared substrings writable.
Which is a useful thing if you're doing a lot of string munging.
This could be easily combined with a hack for a fast
string-append. Have strings carry a bit that says, "I was
constructed by string-append." If string-append notices that its
first argument has this bit set, then the user is probably in a
loop building up a long string by appending a bunch of strings, in
a pattern like (string-append (string-append (string-append ...)
...) ...). In this case, it could allocate extra space beyond the
end of the string in anticipation of the next string-append. The
next append would notice this extra space, copy the tail into it.
The original string becomes a COW-shared substring of the result.
Combined with buffer-doubling, this makes building up strings
linear in time and consumed storage, instead of quadratic.
The same trick should be applied in reverse: if string-append
notices that its last argument has this bit set, then the user is
doing (string-append ... (string-append ... (string-append ...))),
and it should allocate extra space before the beginning of the
string.
- Generational garbage collection
-
(Greg Harvey has
started taking a shot at this; ((Greg) check out my personal
Guile page,
for news, notes, and code).
At the moment, anyone who profiles the Guile interpreter
notices that it's spending a lot of its time in gc_mark.
This is not too surprising. I'd like Guile to have a conservative
generational collector. The hard parts here are the write
barrier, and managing conservatism. I've put some of my ideas for
dealing with conservatism here.
The usual way to keep track of an object's generation is to
keep each generation in a separate region of memory, and then
check the object's address to see which generation it's in. To
age an object, you copy it from from a younger generation to an
older generation, and update all pointers to that object. There's
nothing magic about this; you could just as well have a field in
each object saying what generation it's in. However, using
address ranges saves space; you don't need that extra field per
object.
Unfortunately, when you're using a conservative collector like
Guile's, you can't move an object that's pointed to by the stack.
You have no idea whether any given word on the stack is actually a
pointer, or just some integer, or a piece of a string, so you
can't fix up the pointer after you've moved the object. Which
complicates the collector a bit, if you want to copy objects.
One approach would be to assume that the stack doesn't contain
pointers to too many objects, so you could just leave those there.
After all, aging just affects performance; it's not necessary for
correctness. I think this is a variant of Joel Bartlett's
``Mostly-copying Collector'' idea. Guile uses a free list to
manage its storage, so having a few old objects sticking around
(is there some nice concise derogatory term for people who have
failed a grade in school and are sticking around for another
year?) doesn't affect the allocation strategy at all.
(Greg) This assumption is a pretty safe one; the number of
cells traced conservatively is generally a very small fraction of
the actual number of cells traced. However, it's worth mentioning
that Bartlett's method is patented
(don't get me started), so we have to be a little careful about
the gc we end up with.
Anyway, anyone considering this project should check out Paul
Wilson's survey papers on garbage collection.
Here are projects that don't fall into the above categories.
- GDB support for debugging Guile-using C code
-
GDB actually has some Scheme support in there; we should teach it
how to print Scheme values, how to print interpreter frames, and
so on.
This has been done in the past with a mixed GDB/Guile
solution, but I think it would be more robust to actually put
everything in GDB.
Negotiate design with the GDB group, so it can be merged into
Cygnus's sources.
- New Guile logo
-
I'd like to have a Guile logo which is the word ``Guile''
outfitted with some eyebrows and pupils looking schemeing (ahem)
and crafty.
2 Aug 2000 spacey
|
Copyright (C) 2000,2001,2002,2005 Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111, USA
Verbatim copying and distribution of this entire web page is
permitted in any medium, provided this notice is preserved.