camlspotter avatar camlspotter committed fb1f10e

added

Comments (0)

Files changed (48)

+command.cmi :
+locident.cmi :
+name.cmi :
+pathreparse.cmi : spot.cmi
+spot.cmi :
+spotconfig.cmi : spotconfig_intf.cmo
+spoteval.cmi : utils.cmi spot.cmi
+spotfile.cmi : spoteval.cmi spotconfig_intf.cmo spot.cmi
+treeset.cmi : xset.cmi
+typeFix.cmi :
+typeexpand.cmi :
+utils.cmi :
+xident.cmi : name.cmi
+xlongident.cmi :
+xmain.cmi :
+xpath.cmi : name.cmi
+xprinttyp.cmi :
+xset.cmi :
+command.cmo : command.cmi
+command.cmx : command.cmi
+dotfile.cmo :
+dotfile.cmx :
+ext.cmo : xprinttyp.cmi xpath.cmi xlongident.cmi xident.cmi
+ext.cmx : xprinttyp.cmx xpath.cmx xlongident.cmx xident.cmx
+locident.cmo : locident.cmi
+locident.cmx : locident.cmi
+name.cmo : name.cmi
+name.cmx : name.cmi
+ocamlspot.cmo : utils.cmi spoteval.cmi spotconfig.cmi spot.cmi ext.cmo
+ocamlspot.cmx : utils.cmx spoteval.cmx spotconfig.cmx spot.cmx ext.cmx
+pathreparse.cmo : utils.cmi spot.cmi locident.cmi ext.cmo pathreparse.cmi
+pathreparse.cmx : utils.cmx spot.cmx locident.cmx ext.cmx pathreparse.cmi
+spot.cmo : utils.cmi treeset.cmi ext.cmo spot.cmi
+spot.cmx : utils.cmx treeset.cmx ext.cmx spot.cmi
+spotconfig.cmo : utils.cmi spot.cmi ext.cmo spotconfig.cmi
+spotconfig.cmx : utils.cmx spot.cmx ext.cmx spotconfig.cmi
+spotconfig_intf.cmo : spot.cmi ext.cmo
+spotconfig_intf.cmx : spot.cmx ext.cmx
+spoteval.cmo : utils.cmi spot.cmi spoteval.cmi
+spoteval.cmx : utils.cmx spot.cmx spoteval.cmi
+spotfile.cmo : utils.cmi spoteval.cmi spotconfig_intf.cmo spot.cmi \
+    dotfile.cmo spotfile.cmi
+spotfile.cmx : utils.cmx spoteval.cmx spotconfig_intf.cmx spot.cmx \
+    dotfile.cmx spotfile.cmi
+treeset.cmo : xset.cmi treeset.cmi
+treeset.cmx : xset.cmx treeset.cmi
+typeFix.cmo : utils.cmi name.cmi typeFix.cmi
+typeFix.cmx : utils.cmx name.cmx typeFix.cmi
+typeexpand.cmo : utils.cmi typeexpand.cmi
+typeexpand.cmx : utils.cmx typeexpand.cmi
+utils.cmo : utils.cmi
+utils.cmx : utils.cmi
+xident.cmo : name.cmi xident.cmi
+xident.cmx : name.cmx xident.cmi
+xlongident.cmo : xlongident.cmi
+xlongident.cmx : xlongident.cmi
+xmain.cmo : spot.cmi xmain.cmi
+xmain.cmx : spot.cmx xmain.cmi
+xpath.cmo : xident.cmi name.cmi xpath.cmi
+xpath.cmx : xident.cmx name.cmx xpath.cmi
+xprinttyp.cmo : typeFix.cmi xprinttyp.cmi
+xprinttyp.cmx : typeFix.cmx xprinttyp.cmi
+xset.cmo : xset.cmi
+xset.cmx : xset.cmi
+- this will be filled with bugs YOU find and report to jun.furuse@gmail.com.
+1.4.0
+--------------
+
+For OCaml 3.12.1.
+
+ocamlspot:
+- -i and --info options are now obsolete. Use ``ocamlspot info <filename>'' instead.
+- --type-expand option is added for type-directed expansion of expressions and patterns. 
+  Experimental.
+
+ocamlspot.el:
+- ocamlspot-path is removed. Use ocamlspot-command custom variable.
+- ocamlspot-expand for type-directed expansion of expressions and patterns. Experimental.
+
+Compiler modifications:
+- If OCAML_ANNOT environment variable exists, ocamlc/ocamlopt create .annot, .spot 
+  and .spit files even without -annot option.
+- Lazy thunks in Env.t are replaced by non-functional values.
+
+1.3.1
+--------------
+
+ocamlspot.el:
+- ocamlspot-pop-jump-stack for going back to the latest query position. Experimental.
+
+1.3.0
+--------------
+
+- For OCaml 3.12.1 and rcs
+- Refactoring
+- Use query (ocamlspot use)
+- Standalone type checks (ocamlspot typecheck and ocamlspot recheck)
+- elisp function ocamlspot-xtype for querying types of values
+- elisp function ocamlspot-use for use query
+- bug fixes and more spot support
+
+1.2.0
+--------------
+
+- For OCaml 3.12.0
+- Code cleanups
+
+1.1
+-----
+
+Bug fix
+
+- if x.spot file was obsolete, ocamlspot searched x.spit file instead, 
+  which was not a correct behavior.
+- exceptions in pattern were not browsable.
+- ocamldoc recorded top structures.
+- fix for predefined exception
+
+New feature
+
+- added -n option which does not analyze definition position.
+- ocamlspot-type function is added for type query in ocamlspot.el
+- ocamlspot-use function is added for use query in ocamlspot.el
+- supports a new position format l<line>c<column in bytes> 
+- supports a new query file:kind:path
+- more spots are saved
+- Work around for ocamlbuild. If .ocamlspot file with the text build_dir=dirname
+  is placed in a directory $DIR, then spot files of source files under $DIR 
+  ex. $DIR/subdir/source.ml is searched in $DIR/dirname/subdir/. See an example
+  at camlp4/.ocamlspot
+
+
+ocamlspot.el
+* ocamlspot-path is now ocamlspot-command. Please fix your .emacs.
+- defcustom'ed and code clean-ups (thanks to Sam Steingold) 
+- various elisp bug fixes
+- multi-byte character support in emacs
+
+1.0
+---
+
+Complete rewrite.
+
+beta3
+-----
+
+Clean-ups:
+- Annotation data type simplification
+
+Features:
+- Spot file version number is introduced
+- New browsables:
+    - Data type names to their type defs
+    - Module names to their defs (preliminary support)
+
+beta2p1
+-------
+
+Features:
+- New browsables: variants and record labels to their type defs
+
+beta2:
+------
+
+Complete rewrite.
+
+Features:
+- Enhanced spot file search: if ocamlspot finds no .spot in the load paths 
+  but the corresponding symlinked .cmi, it also searches the .spot file 
+  in the linked directory. 
+
+beta1:
+------
+
+Clean-up and announce.
+
+alpha3:
+-------
+
+Features:
+- File time stamp check
+- .spot file versioning
+
+alpha2:
+-------
+
+Features:
+- Support spotting externals.
+- Enhanced elisp display
+- ocamlopt creates .annot and .spot too
+
+Performance:
+- Things are evaluated more lazily.
+
+Clean-up:
+- Less verbose messages.
+- Removed unnecessary files
+
+Bug-fixes:
+- Location order was mis-defined.
+
+alpha1:
+-------
+
+The first release
+
+In the following, "the Library" refers to all files marked "Copyright
+Jun FURUSE" in this directory.
+
+and "the Patch" refers to the file named "ocamldpot.diff" in this directory.
+
+The Patch is distributed under the terms of the Q Public License
+version 1.0 with a change to choice of law (included below), following
+the license of the patch target, OCaml compiler, copyrighted INRIA.
+
+The Library is distributed under the terms of the GNU Library General
+Public License version 2 (included below).
+
+As a special exception to the Q Public Licence, you may develop
+application programs, reusable components and other software items
+that link with the original or modified versions of the Compiler
+and are not made available to the general public, without any of the
+additional requirements listed in clause 6c of the Q Public licence.
+
+As a special exception to the GNU Library General Public License, you
+may link, statically or dynamically, a "work that uses the Library"
+with a publicly distributed version of the Library to produce an
+executable file containing portions of the Library, and distribute
+that executable file under terms of your choice, without any of the
+additional requirements listed in clause 6 of the GNU Library General
+Public License.  By "a publicly distributed version of the Library",
+we mean either the unmodified Library as distributed by INRIA, or a
+modified version of the Library that is distributed under the
+conditions defined in clause 2 of the GNU Library General Public
+License.  This exception does not however invalidate any other reasons
+why the executable file might be covered by the GNU Library General
+Public License.
+
+----------------------------------------------------------------------
+
+                   THE Q PUBLIC LICENSE version 1.0
+
+              Copyright (C) 1999 Troll Tech AS, Norway.
+                  Everyone is permitted to copy and
+                  distribute this license document.
+
+The intent of this license is to establish freedom to share and change
+the software regulated by this license under the open source model.
+
+This license applies to any software containing a notice placed by the
+copyright holder saying that it may be distributed under the terms of
+the Q Public License version 1.0. Such software is herein referred to
+as the Software. This license covers modification and distribution of
+the Software, use of third-party application programs based on the
+Software, and development of free software which uses the Software.
+
+                            Granted Rights
+
+1. You are granted the non-exclusive rights set forth in this license
+provided you agree to and comply with any and all conditions in this
+license. Whole or partial distribution of the Software, or software
+items that link with the Software, in any form signifies acceptance of
+this license.
+
+2. You may copy and distribute the Software in unmodified form
+provided that the entire package, including - but not restricted to -
+copyright, trademark notices and disclaimers, as released by the
+initial developer of the Software, is distributed.
+
+3. You may make modifications to the Software and distribute your
+modifications, in a form that is separate from the Software, such as
+patches. The following restrictions apply to modifications:
+
+      a. Modifications must not alter or remove any copyright notices
+      in the Software.
+
+      b. When modifications to the Software are released under this
+      license, a non-exclusive royalty-free right is granted to the
+      initial developer of the Software to distribute your
+      modification in future versions of the Software provided such
+      versions remain available under these terms in addition to any
+      other license(s) of the initial developer.
+
+4. You may distribute machine-executable forms of the Software or
+machine-executable forms of modified versions of the Software,
+provided that you meet these restrictions:
+
+      a. You must include this license document in the distribution.
+
+      b. You must ensure that all recipients of the machine-executable
+      forms are also able to receive the complete machine-readable
+      source code to the distributed Software, including all
+      modifications, without any charge beyond the costs of data
+      transfer, and place prominent notices in the distribution
+      explaining this.
+
+      c. You must ensure that all modifications included in the
+      machine-executable forms are available under the terms of this
+      license.
+
+5. You may use the original or modified versions of the Software to
+compile, link and run application programs legally developed by you or
+by others.
+
+6. You may develop application programs, reusable components and other
+software items that link with the original or modified versions of the
+Software. These items, when distributed, are subject to the following
+requirements:
+
+      a. You must ensure that all recipients of machine-executable
+      forms of these items are also able to receive and use the
+      complete machine-readable source code to the items without any
+      charge beyond the costs of data transfer.
+
+      b. You must explicitly license all recipients of your items to
+      use and re-distribute original and modified versions of the
+      items in both machine-executable and source code forms. The
+      recipients must be able to do so without any charges whatsoever,
+      and they must be able to re-distribute to anyone they choose.
+
+      c. If the items are not available to the general public, and the
+      initial developer of the Software requests a copy of the items,
+      then you must supply one.
+
+                       Limitations of Liability
+
+In no event shall the initial developers or copyright holders be
+liable for any damages whatsoever, including - but not restricted to -
+lost revenue or profits or other direct, indirect, special, incidental
+or consequential damages, even if they have been advised of the
+possibility of such damages, except to the extent invariable law, if
+any, provides otherwise.
+
+                             No Warranty
+
+The Software and this license document are provided AS IS with NO
+WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN,
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+                            Choice of Law
+
+This license is governed by the Laws of France.
+
+----------------------------------------------------------------------
+
+                  GNU LIBRARY GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL.  It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it.  You can use it for
+your libraries, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library.  If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software.  To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+  Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs.  This
+license, the GNU Library General Public License, applies to certain
+designated libraries.  This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+  The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it.  Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program.  However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+  Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries.  We
+concluded that weaker conditions might promote sharing better.
+
+  However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves.  This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them.  (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.)  The hope is that this
+will lead to faster development of free libraries.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+  Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+                  GNU LIBRARY GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License").  Each licensee is
+addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    c) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    d) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                            NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+     Appendix: How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+    MA 02111-1307, USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+#########################################################################
+#                                                                       #
+#                             OCamlSpotter                              #
+#                                                                       #
+#                              Jun FURUSE                               #
+#                                                                       #
+#     Copyright 2008 Jun Furuse. All rights reserved.                   #
+#     This file is distributed under the terms of the GNU Library       #
+#     General Public License, with the special exception on linking     #
+#     described in file LICENSE.                                        #
+#                                                                       #
+#########################################################################
+
+OCAMLDIR=$(PREFIX)/lib/ocaml/
+include $(OCAMLDIR)/Makefile.config
+
+# Various commands and dir
+##########################
+CAMLRUN= ocamlrun
+OCAMLC   = ocamlc -annot -bin-annot -w Ae -warn-error Ae-32
+OCAMLOPT = ocamlopt -annot -bin-annot -w Ae -warn-error Ae-32
+OCAMLDEP = ocamldep
+OCAMLLEX = ocamllex
+OCAMLYACC= ocamlyacc
+OCAMLLIB = $(LIBDIR)
+OCAMLBIN = $(BINDIR)
+
+# Compilation
+#############
+OCAMLSRCDIR=..
+INCLUDES_DEP=-I $(OCAMLDIR)/compiler-libs
+
+# Requires unix!
+COMPFLAGS= $(INCLUDES_DEP) -I $(OTHERS)/unix
+
+MODULES= utils dotfile xset treeset command typeexpand \
+	xlongident name xident xpath locident typeFix xprinttyp ext spot spoteval spotconfig_intf spotconfig pathreparse ocamlspot
+
+OBJS=		$(addsuffix .cmo, $(MODULES))
+
+XOBJS=		$(addsuffix .cmx, $(MODULES))
+
+all: ocamlspot 
+
+.PHONY: test
+
+tests:
+	(cd tests; $(MAKE))
+
+ocamlspot: $(COMPOBJS) $(OBJS)
+	$(OCAMLC) -o $@ $(COMPFLAGS) $(COMPOBJS) unix.cma ocamlcommon.cma $(OBJS)
+
+opt.opt: ocamlspot.opt
+
+ocamlspot.opt: $(COMPXOBJS) $(XOBJS)
+	(cd ../asmrun; $(MAKE) meta.o dynlink.o)
+	$(OCAMLOPT) -o $@ $(COMPFLAGS) $(COMPXOBJS) unix.cmxa $(XOBJS) \
+	  ../asmrun/meta.o ../asmrun/dynlink.o -cclib "$(BYTECCLIBS)"
+
+#	$(CAMLOPT) $(LINKFLAGS) -ccopt "$(BYTECCLINKOPTS)" -o ocamlc.opt \
+#	  $(COMPOBJS:.cmo=.cmx) \
+#	  asmrun/meta.o asmrun/dynlink.o -cclib "$(BYTECCLIBS)"
+#	@sed -e 's|@compiler@|$$topdir/ocamlc.opt|' \
+#	  driver/ocamlcomp.sh.in > ocamlcomp.sh
+#	@chmod +x ocamlcomp.sh
+
+
+opt: ocamlspot.opt
+
+.PHONY: opt opt.opt
+
+clean:
+	rm -f ocamlspot ocamlspot.opt *.cm* *.o *.annot *.sp*t 
+	(cd tests; $(MAKE) clean)
+
+# generic rules :
+#################
+
+.SUFFIXES: .mll .mly .ml .mli .cmo .cmi .cmx
+
+.ml.cmo:
+	$(OCAMLC) $(OCAMLPP) $(COMPFLAGS) -c $<
+
+.mli.cmi:
+	$(OCAMLC) $(OCAMLPP) $(COMPFLAGS) -c $<
+
+.ml.cmx:
+	$(OCAMLOPT) $(OCAMLPP) $(COMPFLAGS) -c $<
+
+.mll.ml:
+	$(OCAMLLEX) $<
+
+.mly.ml:
+	$(OCAMLYACC) -v $<
+
+.mly.mli:
+	$(OCAMLYACC) -v $<
+
+beforedepend::
+
+depend: beforedepend
+	ocamldep $(INCLUDES) *.mli *.ml > .depend
+
+.PHONY: clean install installopt beforedepend depend test
+
+# elisp
+
+EMACS=emacs
+
+ELISPS=ocamlspot.el
+
+COMPILECMD=(progn \
+		(setq load-path (cons "." load-path)) \
+		(byte-compile-file "ocamlspot.el"))
+
+install-elisp:
+	@if test "$(EMACSDIR)" = ""; then \
+          set xxx `($(EMACS) --batch --eval "(mapcar 'print load-path)") \
+                   2>/dev/null | \
+                   sed -n -e '/\/site-lisp/s/"//gp'`; \
+          if test "$$2" = ""; then \
+            echo "Cannot determine Emacs site-lisp directory"; \
+            exit 2; \
+          else \
+            $(MAKE) EMACSDIR="$$2" simple-install; \
+	  fi; \
+        else \
+          $(MAKE) simple-install; \
+        fi
+
+# install the .el files, but do not compile them.
+install-el:
+	$(MAKE) NOCOMPILE=true install
+
+simple-install:
+	@echo "Installing in $(EMACSDIR)..."
+	if test -d $(EMACSDIR); then : ; else mkdir -p $(EMACSDIR); fi
+	cp $(ELISPS) $(EMACSDIR)
+	if [ -z "$(NOCOMPILE)" ]; then \
+	  cd $(EMACSDIR); $(EMACS) --batch --eval '$(COMPILECMD)'; \
+	fi
+
+install installopt::
+	cp ocamlspot $(BINDIR)/ocamlspot$(EXE)
+	if test -f ocamlspot.opt; \
+	  then cp ocamlspot.opt $(BINDIR)/ocamlspot.opt$(EXE); else :; fi
+	# The following is optional
+	# $(MAKE) install-emacs-lisp
+
+test: ocamlspot ocamlspot.cmo
+	tests/auto-test.pl ocamlspot.ml treeset.ml xset.ml 
+
+include .depend
+(***********************************************************************)
+(*                                                                     *)
+(*                            OCamlSpotter                             *)
+(*                                                                     *)
+(*                             Jun FURUSE                              *)
+(*                                                                     *)
+(*   Copyright 2008, 2009, 2010 Jun Furuse. All rights reserved.       *)
+(*   This file is distributed under the terms of the GNU Library       *)
+(*   General Public License, with the special exception on linking     *)
+(*   described in file LICENSE.                                        *)
+(*                                                                     *)
+(***********************************************************************)
+
+(* escape metacharacters for /bin/sh 
+
+   Backslash quoting the following characters
+
+   According to the manual of /bin/sh:
+
+   metacharacters: |  & ; ( ) < > space tab
+   history expansion character: !
+   quote characters: \\ \' "" 
+*)
+
+(* general escape *)
+let escaped pred s =
+  let b = Buffer.create (String.length s) in
+  String.iter (fun c ->
+    if pred c then Buffer.add_char b '\\';
+    Buffer.add_char b c) s;
+  Buffer.contents b
+;;
+
+let escaped_for_shell =
+  escaped (function
+    | '|' | '&' | ';' | '(' | ')' | '<' | '>' | ' ' | '\t'
+    | '!'
+    | '\\' | '\'' | '"' -> true
+    | _ -> false)
+;;
+
+let shell args = 
+  Sys.command (String.concat " " (List.map escaped_for_shell args))
+;;
+
+   
+   
+   
+   
+(***********************************************************************)
+(*                                                                     *)
+(*                            OCamlSpotter                             *)
+(*                                                                     *)
+(*                             Jun FURUSE                              *)
+(*                                                                     *)
+(*   Copyright 2008, 2009, 2010 Jun Furuse. All rights reserved.       *)
+(*   This file is distributed under the terms of the GNU Library       *)
+(*   General Public License, with the special exception on linking     *)
+(*   described in file LICENSE.                                        *)
+(*                                                                     *)
+(***********************************************************************)
+
+val escaped : (char -> bool) -> string -> string
+val escaped_for_shell : string -> string
+val shell : string list -> int
+(***********************************************************************)
+(*                                                                     *)
+(*                            OCamlSpotter                             *)
+(*                                                                     *)
+(*                             Jun FURUSE                              *)
+(*                                                                     *)
+(*   Copyright 2008-2011 Jun Furuse. All rights reserved.              *)
+(*   This file is distributed under the terms of the GNU Library       *)
+(*   General Public License, with the special exception on linking     *)
+(*   described in file LICENSE.                                        *)
+(*                                                                     *)
+(***********************************************************************)
+
+(***********************************************************************)
+(*                                                                     *)
+(*                            ocamlspotter                             *)
+(*                                                                     *)
+(*                             Jun FURUSE                              *)
+(*                                                                     *)
+(*   Copyright 2008, 2009 Jun Furuse. All rights reserved.             *)
+(*   This file is distributed under the terms of the GNU Library       *)
+(*   General Public License, with the special exception on linking     *)
+(*   described in file LICENSE.                                        *)
+(*                                                                     *)
+(***********************************************************************)
+
+(* module for .ocamlspot file 
+
+   build_dir: dirname
+
+      Work around for ocamlbuild. If .ocamlspot is placed in a directory $DIR,
+      then spot files of source files under $DIR ex. $DIR/subdir/source.ml
+      is searched in $DIR/dirname/subdir/.
+*)
+
+let name = ".ocamlspot"
+
+let rec find absdir =
+  let path = Filename.concat absdir name in
+  if Sys.file_exists path then Some (absdir, path)
+  else if absdir = "/" then None
+  else find (Filename.dirname absdir)
+;;
+
+type t = {
+  build_dir : string option;
+}
+
+(* very strict .ini file style format *)
+let split_by_equal s =
+  try
+    let pos = String.index s '=' in
+    let key = String.sub s 0 pos in
+    let value = String.sub s (pos+1) (String.length s - pos - 1) in
+    key, Some value
+  with
+  | Not_found -> s, None
+;;
+
+let load s =
+  let build_dir = ref None in
+  let set name ref v =
+    match !ref with
+    | Some _ -> failwith (Printf.sprintf "key %s is defined twice" name)
+    | None -> ref := Some v
+  in
+  let ic = open_in s in
+  let rec load () =
+    let line = input_line ic in
+    let key, value = split_by_equal line in
+    match key, value with
+    | "build_dir", Some s -> 
+        set "build_dir" build_dir s;
+        load ()
+    | "build_dir", None -> failwith (Printf.sprintf "key %S must have a value" key)
+    | key, _ -> failwith (Printf.sprintf "unknown key %S" key)
+  in
+  try load () with End_of_file ->
+    close_in ic;
+    { build_dir = !build_dir }
+;;
+
+let find_and_load absdir =
+  match find absdir with
+  | None -> None
+  | Some (dir, path) -> Some (dir, load path)
+;;
+module Longident = struct
+  include Longident
+  include Xlongident
+end
+
+module Ident0 = Ident
+
+module Ident = struct
+  include Ident
+  include Xident
+end
+
+module Path0 = Path
+
+module Path = struct
+  include Path
+  include Xpath
+end
+
+module Printtyp = struct
+  include Printtyp
+  include Xprinttyp
+end
+
+module Parser = struct
+  include Parser
+  let locident _ _ = assert false
+end
+
+(***********************************************************************)
+(*                                                                     *)
+(*                            OCamlSpotter                             *)
+(*                                                                     *)
+(*                             Jun FURUSE                              *)
+(*                                                                     *)
+(*   Copyright 2008, 2009, 2010 Jun Furuse. All rights reserved.       *)
+(*   This file is distributed under the terms of the GNU Library       *)
+(*   General Public License, with the special exception on linking     *)
+(*   described in file LICENSE.                                        *)
+(*                                                                     *)
+(***********************************************************************)
+
+(* Long identifiers with locations *)
+
+type desc =
+    LLident of string
+  | LLdot of t * string
+  | LLapply of t * t
+
+and t = {
+  lident_desc : desc;
+  lident_loc : Location.t
+}
+
+let rec format ppf t = match t.lident_desc with
+  | LLident s -> Format.pp_print_string ppf s
+  | LLdot (t, s) -> Format.fprintf ppf "%a.%s" format t s
+  | LLapply (t1, t2) -> Format.fprintf ppf "%a(%a)" format t1 format t2
+(***********************************************************************)
+(*                                                                     *)
+(*                            OCamlSpotter                             *)
+(*                                                                     *)
+(*                             Jun FURUSE                              *)
+(*                                                                     *)
+(*   Copyright 2008, 2009, 2010 Jun Furuse. All rights reserved.       *)
+(*   This file is distributed under the terms of the GNU Library       *)
+(*   General Public License, with the special exception on linking     *)
+(*   described in file LICENSE.                                        *)
+(*                                                                     *)
+(***********************************************************************)
+
+(* Long identifiers with locations *)
+
+type desc =
+    LLident of string
+  | LLdot of t * string
+  | LLapply of t * t
+
+and t = {
+  lident_desc : desc;
+  lident_loc : Location.t
+}
+
+val format : Format.formatter -> t -> unit
+(***********************************************************************)
+(*                                                                     *)
+(*                            OCamlSpotter                             *)
+(*                                                                     *)
+(*                             Jun FURUSE                              *)
+(*                                                                     *)
+(*   Copyright 2008, 2009, 2010 Jun Furuse. All rights reserved.       *)
+(*   This file is distributed under the terms of the GNU Library       *)
+(*   General Public License, with the special exception on linking     *)
+(*   described in file LICENSE.                                        *)
+(*                                                                     *)
+(***********************************************************************)
+
+type t = string
+
+let create name = function
+  | -1 -> Printf.sprintf "%s__G" name
+  | n -> Printf.sprintf "%s__%d" name n
+;;
+
+let parse s =
+  try
+    let pos = String.rindex s '_' in
+    if pos = 0 then raise Not_found;
+    if s.[pos-1] <> '_' then raise Not_found;
+    let n = String.sub s 0 (pos-1) in
+    let id =
+      match String.sub s (pos+1) (String.length s - pos - 1) with
+      | "G" -> -1
+      | s -> int_of_string s
+    in
+    n, id
+  with
+  | _ -> raise Not_found
+(* Name is an identifier name with its stamp number. For example, 
+   an ident of name "string" with a stamp 3 has the name "string__3".
+
+   With these names, OCamlSpotter distinguishes textual
+   representations of idents with the same name but with different
+   stamps.
+*)
+type t = string (* CR jfuruse: should be abstracted? *)
+val create : string -> int -> t
+val parse : t -> string * int
+
+; (***********************************************************************)
+; (*                                                                     *)
+; (*                            OCamlSpotter                             *)
+; (*                                                                     *)
+; (*                             Jun FURUSE                              *)
+; (*                                                                     *)
+; (*   Copyright 2008, 2009 Jun Furuse. All rights reserved.             *)
+; (*   This file is distributed under the terms of the GNU Library       *)
+; (*   General Public License, with the special exception on linking     *)
+; (*   described in file LICENSE.                                        *)
+; (*                                                                     *)
+; (***********************************************************************)
+
+; How-to-use
+;
+; Write the following to your .emacs
+
+
+
+;; load-path
+; (setq load-path (cons "WHERE-YOU-HAVE-INSTALLED-THE-ELISP" load-path))
+;
+;; set the path of the ocamlspot binary
+;; this can be a shell command, e.g., "ocamlfind ocamlspot"
+; (setq ocamlspot-command "WHERE-YOU-HAVE-INSTALLED-THE-BINARIES/ocamlspot")
+;
+; (require 'ocamlspot)
+;
+;; tuareg mode hook (use caml-mode-hook instead if you use caml-mode)
+;   (add-hook 'tuareg-mode-hook
+;         '(lambda ()
+;            (local-set-key "\C-c;" 'ocamlspot-query)
+; 	     (local-set-key "\C-c:" 'ocamlspot-query-interface)
+;            (local-set-key "\C-c'" 'ocamlspot-query-uses)
+;            (local-set-key "\C-c\C-t" 'ocamlspot-type)
+;            (local-set-key "\C-c\C-i" 'ocamlspot-xtype)
+;            (local-set-key "\C-c\C-y" 'ocamlspot-type-and-copy)
+;            (local-set-key "\C-cx" 'ocamlspot-expand)
+;            (local-set-key "\C-c\C-u" 'ocamlspot-use)
+;            (local-set-key "\C-ct" 'caml-types-show-type)
+;            (local-set-key "\C-cp" 'ocamlspot-pop-jump-stack)))
+;
+;; You can also change overlay colors as follows:
+; (set-face-background 'ocamlspot-spot-face "#660000")
+; (set-face-background 'ocamlspot-tree-face "#006600")
+
+
+
+; ocamlspot-query
+;   Show the type of the inner-most subexpression under the cursor.
+;   If there is an identifier under the cursor, browse and show its definition
+;
+; ocamlspot-query-interface
+;   Same as ocamlspot-query but browse identifier's interface rather than its defintion
+;   This is currently under construction and does not work properly.
+;
+; ocamlspot-type
+;   Show the type of the inner-most subexpression under the cursor.
+;
+; ocamlspot-type-and-copy
+;   Same as ocamlspot-type but it also copies the type expression to the kill buffer.
+;
+; ocamlspot-use
+;   Show the use information of the identifier under the cursor.
+;
+; ocamlspot-xtype
+;   Same as ocamlspot-type but it shows you more detailed information: 
+;   path id numbers. You can browse path names in this result using C-c;
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Configurable variables
+
+(eval-when-compile (require 'cl)) ; for `destructuring-bind'
+
+(defgroup ocamlspot ()
+  "OCamlSpotter: find the definition and type of variables."
+  :group 'languages)
+
+(defcustom ocamlspot-command "OCAML-SOURCE-TREE/ocamlspot/ocamlspot"
+  "*The command which invokes ocamlspot."
+  :type 'string :group 'ocamlspot)
+
+(defcustom ocamlspot-debug nil
+  "*Turn on ocamlspot debug output."
+  :type 'boolean :group 'ocamlspot)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Constants
+
+;; Buffer names
+
+(defconst ocamlspot-process-buffer "*ocamlspot-process*"
+  "The name of ocamlspot communication buffer")
+
+(defconst ocamlspot-debug-buffer "*ocamlspot-debug*"
+  "The name of ocamlspot debugging buffer")
+
+(defconst ocamlspot-message-buffer "*ocamlspot-message*"
+  "The name of ocamlspot message buffer")
+
+(defconst ocamlspot-type-buffer "*ocamlspot-type*"
+  "The name of ocamlspot type buffer")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; column chars => column bytes
+
+;; This looks complicated, but we need this conversion for multi-byte characters
+;; OCaml's colmuns are in bytes, but Emacs's columns are in chars.
+
+;; returns string from the beginning of the line at the point to the point.
+(defun ocamlspot-string-of-line-to-point ()
+  (buffer-substring-no-properties
+   (line-beginning-position) (point)))
+
+;; returns byte length from the beginning of the line at the point to the point.
+(defun ocamlspot-bytes-of-line-to-point ()
+  (length
+   (encode-coding-string
+    (ocamlspot-string-of-line-to-point) buffer-file-coding-system)))
+
+;; It count one line less when the cursor is at (point-max) 
+;; and it is at the top of the line.
+(defun ocamlspot-lines-of-point ()
+  (count-lines (point-min) (min (1+ (point)) (point-max))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; column bytes => column chars
+
+;; This looks complicated, but we need this conversion for multi-byte characters
+
+;; Same as (goto-line), but without unwanted side-effects.
+(defun ocamlspot-goto-line (line)
+  (goto-char (point-min))
+  (forward-line (1- line)))
+
+;; returns the string at line
+(defun ocamlspot-buffer-substring-at-line (line)
+  ; no need of save-excursion
+  (ocamlspot-goto-line line)
+  (buffer-substring-no-properties (line-beginning-position)
+                                  (line-end-position)))
+
+;; returns the first [bytes] of [str] as chars, not as bytes
+(defun ocamlspot-chars-of-bytes-of-string (str bytes)
+  (length
+   (decode-coding-string
+    (substring (encode-coding-string str buffer-file-coding-system)
+               0 bytes)
+    buffer-file-coding-system)))
+
+;; returns the buffer position of [bytes] at [line]
+(defun ocamlspot-pos-of-bytes-at-line (line bytes)
+  ; no need of save-excursion
+  (ocamlspot-goto-line line)
+  (let ((pos-at-beginning-of-line (line-beginning-position))
+        (chars-from-beginning-of-line
+         (ocamlspot-chars-of-bytes-of-string
+          (ocamlspot-buffer-substring-at-line line) bytes)))
+    (+ pos-at-beginning-of-line chars-from-beginning-of-line)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; location parser
+
+; parses lxxxcxxxbxxx and returns the triplet
+(defun ocamlspot-parse-location (s)
+  (if (string-match "^l\\([\-0-9]+\\)c\\([\-0-9]+\\)b\\([\-0-9]+\\)$" s)
+      (let ((line (string-to-number (match-string 1 s)))
+            (colbytes (string-to-number (match-string 2 s)))
+            (bytes (string-to-number (match-string 3 s))))
+        (list line colbytes bytes))))
+
+;; convert lxxxxcxxxxbxxxx to its buffer position
+(defun ocamlspot-pos-of-location (buffer s)
+  (destructuring-bind (line colbytes bytes) (ocamlspot-parse-location s)
+    (if (= line -1) bytes
+      (with-current-buffer buffer
+        (ocamlspot-pos-of-bytes-at-line line colbytes)))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Messaging
+
+(setq ocamlspot-message-file-name nil) ;; only used for xtype
+
+;; Clean the message buffer, and set the context file name
+(defun ocamlspot-message-init (context-file-name)
+  (setq ocamlspot-message-file-name context-file-name)
+  (with-current-buffer (get-buffer-create ocamlspot-message-buffer)
+    (erase-buffer)))
+
+;; Add a message to the message buffer
+(defun ocamlspot-message-add (mes)
+  (with-current-buffer (get-buffer-create ocamlspot-message-buffer)
+    (if (/= 0 (current-column))
+        (insert "\n"))
+    (insert mes)))
+
+;; Display message in the echo area if it is enough short, then return the string.
+;; If too large, pop a buffer of the message if may-pop is t and return the buffer.
+;; Otherwise, returns nil
+(defun ocamlspot-message-display (&optional may-pop)
+  (with-current-buffer (get-buffer-create ocamlspot-message-buffer)
+    (let ((lines ; how many lines in minibuffer-window ? 
+           (count-screen-lines nil nil nil (minibuffer-window)))
+          (max-echo-height 
+           (if resize-mini-windows
+               (cond ((floatp max-mini-window-height)
+                      (* (frame-height) max-mini-window-height))
+                     ((integerp max-mini-window-height)
+                      max-mini-window-height)
+                     (t 1)))))
+
+      (if (or (<= lines  1)
+              (<= lines max-echo-height))
+          (progn
+            (let ((mes (buffer-string)))
+              (message mes)
+              mes))
+        (if may-pop ; buffer layout may change... no way to recover ?
+            (progn
+              (display-buffer ocamlspot-message-buffer)
+              ocamlspot-message-buffer)
+          ;; display the first max-echo-height lines
+          (let ((lines (max 1 (1- max-echo-height))))
+            (goto-char (point-min))
+            (forward-visible-line (max 1 (- max-echo-height 2)))
+            (message (concat (buffer-substring (point-min) (point)) "... Result is too long. Truncated."))
+            nil))))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; type buffer
+
+;; Clean the type buffer
+(defun ocamlspot-type-init ()
+  (with-current-buffer (get-buffer-create ocamlspot-type-buffer)
+    (erase-buffer)
+    (ocamlspot-xtype-mode t)))
+
+;; Add message to the type buffer
+(defun ocamlspot-type-add (mes)
+  (with-current-buffer (get-buffer-create ocamlspot-type-buffer)
+    (if (/= 0 (current-column))
+        (insert "\n"))
+    (insert mes)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Overlays
+
+;; the spot overlay
+(defvar ocamlspot-spot-overlay (make-overlay 1 1))
+(defface ocamlspot-spot-face
+    '((t (:foreground "#88FF44")))
+  "Face for ocamlspot spot highlight"
+  :group 'ocamlspot)
+(overlay-put ocamlspot-spot-overlay 'face 'ocamlspot-spot-face)
+
+;; the tree overlay
+(defvar ocamlspot-tree-overlay (make-overlay 1 1))
+(defface ocamlspot-tree-face
+    '((t (:foreground "#FF88FF")))
+  "Face for ocamlspot tree highlight"
+  :group 'ocamlspot)
+(overlay-put ocamlspot-tree-overlay 'face 'ocamlspot-tree-face)
+
+;; Clear the overlay 
+(defun ocamlspot-delete-overlays-now ()
+  (interactive)
+  (delete-overlay ocamlspot-tree-overlay)
+  (delete-overlay ocamlspot-spot-overlay))
+
+;; Clear the overlay, waiting 10 secs maximum
+(defun ocamlspot-delete-overlays ()
+  (unwind-protect
+      (sit-for 10)
+    (ocamlspot-delete-overlays-now)))
+
+;; Parse ocamlspot region string
+;; Acceptable forms: all | lxxxcxxxbxxx:lyyycyyybyyy | xxx:yyy
+(defun ocamlspot-convert-region (buffer position)
+  (if (not buffer) (error "ocamlspot-convert-region: buffer is nill")
+    (save-current-buffer
+      (set-buffer buffer)
+      (if (or (string-equal "all" position) (string-equal "-1:-1" position))
+	  (list (point-min) (point-max))
+	(if (string-match "^\\(l[\-0-9]+c[\-0-9]+b[\-0-9]+\\|[0-9]+\\):\\(l[\-0-9]+c[\-0-9]+b[\-0-9]+\\|[0-9]+\\)$" position)
+	    (let ((start (match-string 1 position))
+		  (end   (match-string 2 position)))
+	      (let ((start (ocamlspot-pos-of-location buffer start))
+		    (end   (ocamlspot-pos-of-location buffer end)))
+		(list start end)))
+	  nil)))))
+
+(defun ocamlspot-display-overlay (buffer emacs-start-end overlay)
+  (if emacs-start-end
+      (progn
+	(destructuring-bind (start end) emacs-start-end
+	  ;; display the result
+	  (set-buffer buffer)
+	  (goto-char start)
+	  (move-overlay overlay start end buffer)))
+    (message "ocamlspot-display-overlay: strange region")))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Warnings
+
+;; Search a warning from the current point
+(defun ocamlspot-warning ()
+  (and (re-search-forward "^\\(Warning: .*\\)$" nil t)
+       (match-string 1)))
+
+;; Search the warnings from the current point, and returns them in reversed order
+(defun ocamlspot-warnings-rev (lst)
+  (let ((warning (ocamlspot-warning)))
+    (if warning (ocamlspot-warnings-rev (concat lst warning "\n"))
+      lst)))
+
+;; Search the warnings from the current point
+(defun ocamlspot-warnings ()
+  (goto-char (point-min))
+  (ocamlspot-warnings-rev ""))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; File access
+
+;; Open the file, if exists
+(defun ocamlspot-find-file-existing (path)
+  (if (file-exists-p path)
+      (find-file-other-window path)
+    (ocamlspot-message-add (format "ERROR: source file %s was not found" path))
+    nil))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Queries
+
+;; Run ocamlspot command with args, possibly in the given directory.
+(defun ocamlspot-run-query (args &optional chdir)
+  (with-current-buffer (get-buffer-create ocamlspot-process-buffer)
+    (ocamlspot-process-mode t)
+    (erase-buffer)
+    (let ((command (concat ocamlspot-command " " args)))
+      (insert command)
+      (insert "\n")
+      ;; chdir is required
+      (if chdir (cd chdir))
+      (let ((args (if ocamlspot-debug (concat "-debug " args) args)))
+	(call-process shell-file-name nil t nil shell-command-switch
+		      command)))))
+
+;; Creates the query location string of the point
+(defun ocamlspot-query-string-at-cursor ()
+  (format "%s:l%dc%d"
+	  (buffer-file-name)
+	  (ocamlspot-lines-of-point)
+	  (ocamlspot-bytes-of-line-to-point)))
+
+;; launch ocamlspot, using the position of the cursor
+;; result is stored in the buffer "ocamlspot-process-buffer"
+;; the current buffer is stored in source-buffer
+(defun ocamlspot-query-at-cursor (pre_extra_args &optional post_extra_args)
+  ;; arguments
+  (let ((file-name (buffer-file-name))
+	(arg (ocamlspot-query-string-at-cursor))
+	(post_sep (if post_extra_args " " "")))
+    (ocamlspot-run-query (concat pre_extra_args " " arg post_sep post_extra_args) 
+			 (file-name-directory file-name))))
+
+;; Search ocamlspot-process-buffer from the top and return the first line which matches with ^<pattern>: "
+;; If [to-kill], the output is copied to the kill-buffer.
+(defun ocamlspot-find-query-result (pattern &optional to-kill)
+  (save-current-buffer
+    (set-buffer (get-buffer-create ocamlspot-process-buffer))
+    (goto-char (point-min))
+    (if (re-search-forward (concat "^" pattern ": \\(.*\\(\n +.*\\)*\\)") nil t)
+	(let ((the-match (match-string 1)))
+	  (if to-kill (kill-new the-match))
+	  the-match))))
+
+;; Scan the ocamlspot process output and search a Tree tag.
+;; If there is a Tree result, highlight it and returns the position string
+;; Otherwise returns nil.
+(defun ocamlspot-find-tree ()
+  (save-excursion
+    (let ((source-buffer (current-buffer)))
+      (with-current-buffer (get-buffer-create ocamlspot-process-buffer)
+	;; search the found tree element
+	(let ((tree (ocamlspot-find-query-result "Tree")))
+	  (if tree 
+	      (progn
+		(let ((start-end (ocamlspot-convert-region source-buffer tree)))
+		  (if start-end
+		      (save-current-buffer
+			(ocamlspot-display-overlay source-buffer start-end ocamlspot-tree-overlay)))
+		  (let ((err (ocamlspot-find-query-result "Error")))
+		    (if err
+			(ocamlspot-message-add (concat "Error: " err))))
+		  start-end))
+
+	    (let ((err (ocamlspot-find-query-result "Error")))
+	      (if err
+		  (ocamlspot-message-add (concat "Error: " err))
+		(ocamlspot-message-add "Error: no tree node found there")))
+	    nil))))))
+
+;; Jump to [position] of [filename], with highlighting the spot overlay
+(defun ocamlspot-jump-to-spot (filename position)
+  (if (string-match "\.cm[ioxa]$" filename)
+      ;; It is not an .ml or .mli. Packed module.
+      ;; CR jfuruse: opening a binary file is not good
+      (ocamlspot-message-add "Packed module: %s" filename)
+    (let* ((buffer (ocamlspot-find-file-existing filename))
+	   (start-end (ocamlspot-convert-region buffer position)))
+      (if start-end
+	  (ocamlspot-display-overlay buffer start-end ocamlspot-spot-overlay)
+	  (ocamlspot-message-add (concat "Error: strange position: " position))))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Jump history
+
+;; Experimental. Jump back to the latest query position.
+
+(setq ocamlspot-jump-stack nil)
+
+(defun ocamlspot-pop-jump-stack ()
+  (interactive)
+  (if ocamlspot-jump-stack
+      (progn
+	(destructuring-bind (buffer pos) (car ocamlspot-jump-stack)
+	  (setq ocamlspot-jump-stack (cdr ocamlspot-jump-stack))
+	  (if (buffer-live-p buffer)
+	      (progn
+		(display-buffer buffer)
+		(switch-to-buffer buffer)
+		(goto-char pos))
+	    (ocamlspot-pop-jump-stack))))
+    (message "OCamlSpot jump stack is empty")))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Find-and-do-somethings. Query must be already done.
+
+;; Jump to given path-range.
+(defun ocamlspot-jump-to-path-range (path-range)
+  (if (string-match "^<?\\(.*\\):\\(all\\|[\-0-9lcb]+:[\-0-9lcb]+[^>]*\\)>?$" path-range)
+      (let ((filename (match-string 1 path-range))
+	    (position (match-string 2 path-range)))
+	;; preserve current buffer and pos ;; CR jfuruse: history preserving should take occur only when the jump is successful.
+	(setq ocamlspot-jump-stack (cons (list (current-buffer)
+					       (point))
+					 ocamlspot-jump-stack))
+
+	;; display the result
+	(ocamlspot-jump-to-spot filename position)
+	(let ((type (ocamlspot-find-val-or-type)))
+	  ;; (if type (ocamlspot-message-add (format "Type: %s" type)))
+	  ))
+    ;; failed to get the normal result
+    ;; CR jfuruse: this is an error message. Should be decolated?
+    (ocamlspot-message-add path-range)))
+
+;; Show the type information
+;; If [to-kill], the output is copied to the kill-buffer.
+(defun ocamlspot-find-type (&optional to-kill)
+  (let ((type (ocamlspot-find-query-result "Type" to-kill)))
+    (if type 
+	(progn
+	  (ocamlspot-message-add (format "Type: %s" type))
+	  (ocamlspot-type-add (format "Type: %s" type))
+	  type)
+      (ocamlspot-message-add "no type found here")
+      nil)))
+
+;; same as type-in-buffer but for XType
+(defun ocamlspot-find-xtype ()
+  (let ((type (ocamlspot-find-query-result "XType")))
+    (if type
+	(progn
+	  (ocamlspot-message-add (format "(* %s *)\n" ocamlspot-message-file-name))
+	  (ocamlspot-message-add (format "%s" type))
+	  (ocamlspot-type-add (format "(* %s *)\n" ocamlspot-message-file-name))
+	  (ocamlspot-type-add (format "%s" type))
+	  type)
+      (ocamlspot-message-add "no type found here")
+      nil)))
+
+;; If [to-kill], the output is copied to the kill-buffer.
+(defun ocamlspot-find-val-or-type (&optional to-kill)
+  (let ((type (ocamlspot-find-query-result "Val" to-kill)))
+    (if type
+	(progn 
+	  (ocamlspot-message-add (format "Val: %s" type))
+	  (ocamlspot-type-add (format "Val: %s" type))
+	  type)
+      (ocamlspot-find-type to-kill))))
+
+;; Show use info
+(defun ocamlspot-find-use ()
+  (let ((use (ocamlspot-find-query-result "Use")))
+    (if use
+	(progn 
+	  (ocamlspot-message-add (format "Use: %s" use))
+	  use)
+      (ocamlspot-message-add "no use information found here")
+      nil)))
+
+;; Jump to the position found at the Spot tag
+(defun ocamlspot-find-spot ()
+  (let ((spot (ocamlspot-find-query-result "Spot")))
+    (if spot (ocamlspot-jump-to-path-range spot)
+      ;; no Spot:
+      (let ((err (ocamlspot-find-query-result "Error")))
+	(if err
+	    (ocamlspot-message-add (concat "Error: " err))
+	  ;; display debug info
+	  (ocamlspot-message-add "No definition info found")
+	  (ocamlspot-find-val-or-type)
+	)))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Interactives
+
+;; Show the message, and wait at most 10secs, then clear the overlay highlights
+(defun ocamlspot-wait (&optional may-pop)
+  (ocamlspot-message-display may-pop)
+  (ocamlspot-delete-overlays))
+
+(defun ocamlspot-query (&optional args)
+  (interactive)
+  (let ((sel-window (selected-window)))
+  (save-selected-window
+    (ocamlspot-message-init (buffer-file-name))
+    (ocamlspot-type-init)
+    (ocamlspot-delete-overlays-now)
+    (ocamlspot-query-at-cursor args)
+    (when (ocamlspot-find-tree)
+      ;; search the result
+      (ocamlspot-find-spot))
+    (ocamlspot-wait))
+  ;; I dunno why but we need the following line to list-buffers work nicely
+  (select-window sel-window)))
+
+(defun ocamlspot-query-interface ()
+  (interactive)
+  (ocamlspot-query "--interface"))
+
+;; Query the type at the point and show it. 
+;; If [to-kill] is t, the type string is copied to the kill buffer.
+(defun ocamlspot-type (&optional to-kill)
+  (interactive)
+  (ocamlspot-message-init (buffer-file-name))
+  (ocamlspot-type-init)
+  (ocamlspot-delete-overlays-now)
+  (ocamlspot-query-at-cursor "-n")  
+  (if (ocamlspot-find-tree)
+      (save-current-buffer
+        (ocamlspot-find-val-or-type to-kill)))
+  (ocamlspot-wait t))
+
+(defun ocamlspot-type-and-copy ()
+  (interactive)
+  (ocamlspot-type t))
+
+(defun ocamlspot-xtype (&optional to-kill)
+  (interactive)
+  (ocamlspot-message-init (buffer-file-name))
+  (ocamlspot-type-init)
+  (ocamlspot-delete-overlays-now)
+  (ocamlspot-query-at-cursor "-n")
+  (if (ocamlspot-find-tree)
+      (save-current-buffer
+        (ocamlspot-find-xtype)))
+  (display-buffer ocamlspot-type-buffer))
+
+; CR can be shared with ocamlspot-type
+(defun ocamlspot-use ()
+  (interactive)
+  (ocamlspot-message-init (buffer-file-name))
+  (ocamlspot-type-init)
+  (ocamlspot-delete-overlays-now)
+  (ocamlspot-query-at-cursor "-n")
+  (if (ocamlspot-find-tree)
+      (save-current-buffer
+        (ocamlspot-find-use)))
+  (ocamlspot-wait t))
+
+; CR can be shared with ocamlspot-type
+(defun ocamlspot-query-uses ()
+  (interactive)
+  (let ((dir (read-directory-name "Search directory: "
+				  (file-name-directory (buffer-file-name)))))
+    (ocamlspot-message-init (buffer-file-name))
+    (ocamlspot-type-init)
+    (ocamlspot-delete-overlays-now)
+    (ocamlspot-query-at-cursor "use" dir)
+    (if (ocamlspot-find-tree)
+	(progn
+	 (ocamlspot-find-spot)
+	 (display-buffer ocamlspot-process-buffer)
+	 (ocamlspot-find-use)))
+    (ocamlspot-wait t)))
+
+; ;; expand expr/pattern by type
+(defun ocamlspot-expand ()
+  (interactive)
+  (ocamlspot-message-init (buffer-file-name))
+  (ocamlspot-type-init)
+  (ocamlspot-query-at-cursor "-n --type-expand")
+  (let ((expansion (ocamlspot-find-query-result "Expand")))
+    (if expansion
+	(let ((start-end (ocamlspot-find-tree)))
+	  (if start-end
+	      (destructuring-bind (start end) start-end
+                (ocamlspot-delete-overlays-now)
+		(delete-region start end) ; or kill-region ?
+		(goto-char start)
+		(insert expansion)
+		(let ((new-end (point)))
+		  (ocamlspot-display-overlay (current-buffer) (list start new-end) ocamlspot-tree-overlay))
+		(ocamlspot-delete-overlays)
+		)
+	    (ocamlspot-message-add "OCamlSpot -expand: no tree information found")))
+      (ocamlspot-message-add "OCamlSpot -expand: no expand information found"))))
+	
+;; Browsing of path-range <file:lxcxbx:lxcxbx>
+(defun ocamlspot-beginning-of-path-range ()
+  (search-backward "<"
+		   (save-excursion (beginning-of-line) (point))))
+(defun ocamlspot-end-of-path-range ()
+  (search-forward ">"
+		  (save-excursion (end-of-line) (point))))
+(put 'ocamlspot-path-range 'beginning-op 'ocamlspot-beginning-of-path-range)
+(put 'ocamlspot-path-range 'end-op 'ocamlspot-end-of-path-range)
+
+(defun ocamlspot-path-range-at-point ()
+  (interactive)
+  (let ((bounds (bounds-of-thing-at-point 'ocamlspot-path-range)))
+      (if bounds
+	  (progn
+	    (move-overlay ocamlspot-tree-overlay (car bounds) (cdr bounds))
+	    (buffer-substring (car bounds) (cdr bounds))))))
+
+(defun ocamlspot-browse-path-range-at-point ()
+  (interactive)
+  (let ((path-range (ocamlspot-path-range-at-point)))
+    (if path-range
+	(ocamlspot-jump-to-path-range path-range)
+	(message "no path-range at point")
+	)))
+
+;; build query string for the cursor point
+(defun ocamlspot-xtype-build-query-at-cursor ()
+  (let ((path-name 
+	 (save-excursion
+	   (let ((end
+;; Preferable, but not working correctly yet for A.B<cursor>.t
+;;		  (if (skip-chars-forward "A-z0-9_)")
+;;		      (point)
+;;		    nil))
+		  (if (skip-chars-forward "A-z0-9_().") ;; less powerful
+		      (point)
+		    nil))
+		 (start
+		  (if (skip-chars-backward "A-z0-9_().")
+		      (point)
+		    nil)))
+	     (if (and start end) 
+		 (progn
+		   (move-overlay ocamlspot-tree-overlay start end)
+		   (buffer-substring-no-properties start end)))))))
+    (message (concat "path-name " path-name))
+    (let ((file-name 
+	   (save-excursion
+	     (goto-char (point-min))
+	     (if (re-search-forward "^(\\* \\(.*\\) \\*)$" nil t)
+		 (match-string 1)))))
+      (if (and 
+	   file-name 
+	   path-name 
+	   (not (string= file-name "")) 
+	   (not (string= path-name "")))
+	  (concat file-name ":t:" path-name)))))
+
+(defun ocamlspot-xtype-query ()
+  (interactive)
+  (let ((sel-window (selected-window)))
+    (save-selected-window
+      (ocamlspot-message-init (buffer-file-name))
+      ;; (ocamlspot-type-init) ; We must keep xtype buffer
+      (ocamlspot-delete-overlays-now)
+      (let ((query (ocamlspot-xtype-build-query-at-cursor)))
+	(if query
+	    (progn
+	      (message query)
+	      (ocamlspot-run-query query)
+	      (ocamlspot-find-spot)
+	      (ocamlspot-wait))
+	  (message "query empty"))))
+    ;; I dunno why but we need the following line to list-buffers work nicely
+    (select-window sel-window)))
+
+(defun ocamlspot-xtype-mode-map ()
+  (let ((keymap (make-sparse-keymap)))
+    (define-key keymap "\C-c;" 'ocamlspot-xtype-query)
+    keymap))
+
+(defun ocamlspot-process-mode-map ()
+  (let ((keymap (make-sparse-keymap)))
+    (define-key keymap "\C-c;" 'ocamlspot-browse-path-range-at-point)
+    keymap))
+
+(define-minor-mode ocamlspot-xtype-mode
+  "OCamlSpot XType mode."
+  :lighter " OCamlSpot-XType"
+  :keymap (ocamlspot-xtype-mode-map))
+
+(define-minor-mode ocamlspot-process-mode
+  "OCamlSpot Process mode."
+  :lighter " OCamlSpot-Process"
+  :keymap (ocamlspot-process-mode-map))
+
+(provide 'ocamlspot)
+(***********************************************************************)
+(*                                                                     *)
+(*                            ocamlspotter                             *)
+(*                                                                     *)
+(*                             Jun FURUSE                              *)
+(*                                                                     *)
+(*   Copyright 2008, 2009 Jun Furuse. All rights reserved.             *)
+(*   This file is distributed under the terms of the GNU Library       *)
+(*   General Public License, with the special exception on linking     *)
+(*   described in file LICENSE.                                        *)
+(*                                                                     *)
+(***********************************************************************)
+
+(* module names may corride in different source/spot files *)
+
+(*
+open Format
+open Utils
+
+open Ext
+
+open Spot
+open Spoteval
+
+*)
+module C = Spotconfig
+
+open Cmt_format
+
+let _ =
+  match C.mode with
+  | `Dump p ->
+      begin match Cmt_format.read p with
+    | _, None -> Format.eprintf "%s : oops@." p
+    | _, Some cmti ->
+        let v = 
+          match cmti.cmt_annots with
+          | Implementation str -> 
+              Spot.Abstraction.structure str
+          | Interface sg ->
+              Spot.Abstraction.signature sg
+          | _ -> assert false
+        in
+        Format.eprintf "%a@."
+          Spot.Abstraction.format_module_expr v
+      end
+  | _ -> assert false
+    
+
+(*
+type binary_annots =
+  | Packed of Types.signature * string list
+  | Implementation of structure
+  | Interface of signature
+  | Partial_implementation of binary_part array
+  | Partial_interface of binary_part array
+
+and binary_part =
+  | Partial_structure of structure
+  | Partial_structure_item of structure_item
+  | Partial_expression of expression
+  | Partial_pattern of pattern
+  | Partial_class_expr of class_expr
+  | Partial_signature of signature
+  | Partial_signature_item of signature_item
+  | Partial_module_type of module_type
+*)
+
+(* module File = Spotfile.Make(C) *)
+    
+(*
+module Dump = struct
+  (* mainly debugging purpose *)
+  let tree file = Tree.dump !!(file.File.tree)
+  ;;
+
+  let top file = 
+    eprintf "@[<2>top =@ @[%a@]@]@." 
+      Abstraction.format_structure file.File.top;
+    let str = 
+      Eval.structure (File.empty_env file) file.File.top
+    in
+    if C.eager_dump then begin
+      let module Enforcer = Value.Enforcer(struct end) in
+      Enforcer.structure str;
+    end;
+    eprintf "==>@.@[%a@]@." Value.Format.structure str
+  ;;
+
+  let flat file = 
+    eprintf "@[<2>flat =@ @[%a@]@]@." 
+      Abstraction.format_structure file.File.flat;
+    let str = 
+      let env = File.invalid_env file in
+      let str = Eval.structure env file.File.flat in
+      Binding.set env.Env.binding str; (* dirty hack (dup code) *)
+      str
+    in
+    if C.eager_dump then begin
+      let module Enforcer = Value.Enforcer(struct end) in
+      Enforcer.structure str;
+    end;
+    eprintf "==>@.@[%a@]@." Value.Format.structure str;
+  ;;
+end
+
+module Main = struct
+
+  let bye return =
+    printf "BYE!@.";
+    exit return
+
+  let load path =
+
+    let file = File.load ~load_paths: ["."] path in
+    
+    if C.dump_file then Dump.file file;
+    if C.dump_rannots = `Full then Dump.rannots_full file;
+    if C.dump_rannots = `Summary then Dump.rannots_summary file;
+    if C.dump_tree then Dump.tree file;
+    if C.dump_top then Dump.top file;
+    if C.dump_flat then Dump.flat file;
+
+    file
+  ;;
+
+  let info path =
+    let file = load (File.spot_of_file path) in
+    printf "Compile: %s@."
+      (String.concat " " 
+         (List.map Command.escaped_for_shell 
+            (Array.to_list file.File.argv)));
+    printf "@[<v2>Included_dirs:@ %a@]@."
+      (Format.list "" pp_print_string)
+      file.File.load_paths
+
+  let query_by_kind_path file kind path = 
+    try Some (File.find_path_in_flat file (kind, path)) with Not_found -> None
+  ;;
+
+  let print_query_result kind = function
+    | None -> printf "Spot: no spot@."
+    | Some (pident, res) -> match res with
+	| File.File_itself ->
+            printf "Spot: <%s:all>@." pident.PIdent.path
+	| File.Found_at region ->
+            printf "Spot: <%s:%s>@."
+              pident.PIdent.path
+              (Region.to_string region)
+	| File.Predefined ->
+            printf "Spot: %a: predefined %s@."
+              PIdent.format pident
+              (Kind.name kind);
+  ;;
+    
+  let query_by_pos file pos = 
+    let probe = Region.point pos in
+    let treepath = 
+      (* subtree is not used *)
+      List.map fst (Tree.find_path_contains probe !!(file.File.tree))
+    in
+    match treepath with
+    | [] -> 
+	failwith (Printf.sprintf "nothing at %s" (Position.to_string pos))
+    | { Regioned.region = r; _ } :: _ ->
+	
+	(* find annots bound to the region *)
+        let annots = 
+	  List.filter_map (fun rannot ->
+	    if Region.compare r rannot.Regioned.region = `Same then 
+	      Some rannot.Regioned.value
+	    else None)
+	    treepath
+        in
+
+	(* annots and region improvement by path *)
+	let annots, r = 
+	  match 
+	    (* only the first Use *)
+	    List.find_map_opt (function
+	      | Annot.Use (_, path) -> 
+		  (* Find subpath *)
+		  begin match Pathreparse.get file.File.path r pos path with    
+		  | None -> None
+		  | Some (path', r) -> 
+		      if path = path' then None (* as original *)
+		      else Some ([Annot.Use (Kind.Module, path')], r)
+		  end
+	      | _ -> None) annots
+	  with
+	  | None -> annots, r
+	  | Some (annots, r) -> annots, r
+	in
+	  
+        List.iter (printf "@[<v>%a@]@." Annot.format) annots;
+
+	(* Tree is an older format. XTree is a newer which is the same as one for Spot *)
+        printf "Tree: %s@." (Region.to_string r);
+        printf "XTree: <%s:%s>@." file.File.path (Region.to_string r);
+
+	(* Find the innermost module *)
+        let rec find_module_path = function
+          | [] -> []
+          | { Regioned.value = Annot.Str (Abstraction.Str_module (id, _)); _ } :: ls
+          | { Regioned.value = Annot.Str (Abstraction.Str_modtype (id, _)); _ } :: ls ->
+              id :: find_module_path ls
+          | _ :: ls -> find_module_path ls
+        in
+        printf "In_module: %s@."
+          (String.concat "." (List.map Ident0.name (List.rev (find_module_path treepath))));
+
+        (* print "Val: val name : type" if it is a Str: val *)
+        let print_sig_entry annots =
+          let rec find_type = function
+            | Annot.Type (typ, _, _) :: _ -> Some typ
+            | _::xs -> find_type xs
+            | [] -> None
+          in
+          let rec find_str_value = function
+            | Annot.Str (Abstraction.Str_value id) :: _ -> Some id
+            | _::xs -> find_str_value xs
+            | [] -> None
+          in
+          match find_type annots, find_str_value annots with
+          | Some typ, Some id ->
+              printf "Val: val %s : @[%a@]@."
+                (Ident0.name id)
+                (Printtyp.type_scheme ~with_pos:false) typ
+          | _ -> ()
+        in
+        print_sig_entry annots;
+
+        (* print_type_decl: if one Type is found *)
+        if C.type_expand then begin
+          match List.filter (function Annot.Type _ -> true | _ -> false) annots with
+          (* CR jfuruse: Sometimes more than one Annot.Type are found at the same place... *)
+          | Annot.Type (typ, env, `Expr) :: _ -> 
+              printf "Expand: @[%a@]@." Typeexpand.format_as_expr (Typeexpand.expand file.File.load_paths env typ)
+          | Annot.Type (typ, env, `Pattern) :: _ -> 
+              printf "Expand: @[%a@]@." Typeexpand.format_as_pattern (Typeexpand.expand file.File.load_paths env typ)
+          | Annot.Type (_typ, _env, `Val) :: _ -> ()
+          | _ -> ()
+        end;
+
+	annots
+  ;;
+
+  let query path spec = 
+    (* CR jfuruse: dup *)
+    Debug.format "ocamlspot %s%s@." path (C.SearchSpec.to_string spec);
+    Debug.format "cwd: %s@." (Sys.getcwd ());
+    let path = File.spot_of_file path in
+    let file = load path in
+
+    let query_kind_path k path = print_query_result k (query_by_kind_path file k path) in
+
+    begin match spec with
+    | C.SearchSpec.Kind (k,path) -> query_kind_path k path
+    | C.SearchSpec.Pos pos -> 
+	let annots = query_by_pos file pos in
+        if not C.no_definition_analysis then begin
+          List.iter (function
+            | Annot.Use (k, path) -> query_kind_path k path
+            | _ -> ()) annots
+        end
+    end;
+
+    bye 0
+
+  let query file spec =
+    try query file spec with
+    | Failure s ->
+        eprintf "Error: %s@." s;
+        bye 1
+    | File.Old_spot (_spot, source) ->
+        eprintf "Error: source %s is newer than the spot@." source;
+        bye 1
+    | e ->
+        eprintf "uncaught exception: %s@." (Printexc.to_string e);
+        bye 1
+
+  let use path spec targets =
+    let targets = if targets = [] then ["."] else targets in
+    (* CR jfuruse: dup *)
+    Debug.format "ocamlspot %s%s@." path (C.SearchSpec.to_string spec);
+    Debug.format "cwd: %s@." (Sys.getcwd ());
+    let path = File.spot_of_file path in
+    let file = load path in
+
+    let find_by_kind_path k path found =
+      Unix.find targets ~f:(fun pathname ->
+	match Filename.split_extension pathname.Unix.base with
+	| _body, (".spit" | ".spot") ->
+	  let file = load pathname.Unix.path in
+	  Debug.format "Searching %s@." pathname.Unix.path;
+	  let base_ident = function
+	    | Path.Pident id -> Ident0.name id
+	    | Path.Pdot (_, name, _) -> name
+	    | Path.Papply _ -> assert false
+	  in
+	  let base = base_ident path in
+	  List.iter (function
+	    | { Regioned.region= region; value= Annot.Use (k', path'); } when k = k' && base = base_ident path' ->
+	      begin match query_by_kind_path file k' path' with
+	      | Some found' when found = found' ->
+		  printf "<%s:%s>: %s@." 
+		    file.File.path
+		    (Region.to_string region)
+		    (Path.name path)
+	      | None | Some _ -> ()
+	      end
+	    | _ -> ()) file.File.rannots