diff options
Diffstat (limited to 'libxsd-frontend')
164 files changed, 20271 insertions, 0 deletions
diff --git a/libxsd-frontend/GPLv2 b/libxsd-frontend/GPLv2 new file mode 100644 index 0000000..3912109 --- /dev/null +++ b/libxsd-frontend/GPLv2 @@ -0,0 +1,340 @@ +		    GNU GENERAL PUBLIC LICENSE +		       Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. +                       51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +			    Preamble + +  The licenses for most software are designed to take away your +freedom to share and change it.  By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users.  This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it.  (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.)  You can apply it to +your programs, 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 software, or if you modify it. + +  For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have.  You must make sure that they, too, receive or can get the +source code.  And you must show them these terms so they know their +rights. + +  We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + +  Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software.  If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, 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 redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary.  To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + +  The precise terms and conditions for copying, distribution and +modification follow. + +		    GNU GENERAL PUBLIC LICENSE +   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +  0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License.  The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language.  (Hereinafter, translation is included without limitation in +the term "modification".)  Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope.  The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + +  1. You may copy and distribute verbatim copies of the Program's +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 give any other recipients of the Program a copy of this License +along with the Program. + +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 Program or any portion +of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices +    stating that you changed the files and the date of any change. + +    b) You must cause any work that you distribute or publish, that in +    whole or in part contains or is derived from the Program or any +    part thereof, to be licensed as a whole at no charge to all third +    parties under the terms of this License. + +    c) If the modified program normally reads commands interactively +    when run, you must cause it, when started running for such +    interactive use in the most ordinary way, to print or display an +    announcement including an appropriate copyright notice and a +    notice that there is no warranty (or else, saying that you provide +    a warranty) and that users may redistribute the program under +    these conditions, and telling the user how to view a copy of this +    License.  (Exception: if the Program itself is interactive but +    does not normally print such an announcement, your work based on +    the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole.  If +identifiable sections of that work are not derived from the Program, +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 Program, 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 Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + +  3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + +    a) 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; or, + +    b) Accompany it with a written offer, valid for at least three +    years, to give any third party, for a charge no more than your +    cost of physically performing source distribution, a complete +    machine-readable copy of the corresponding source code, to be +    distributed under the terms of Sections 1 and 2 above on a medium +    customarily used for software interchange; or, + +    c) Accompany it with the information you received as to the offer +    to distribute corresponding source code.  (This alternative is +    allowed only for noncommercial distribution and only if you +    received the program in object code or executable form with such +    an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it.  For an executable work, 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 executable.  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. + +If distribution of executable or 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 counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + +  4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License.  Any attempt +otherwise to copy, modify, sublicense or distribute the Program 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. + +  5. 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 Program or its derivative works.  These actions are +prohibited by law if you do not accept this License.  Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + +  6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program 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. + +  7. 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 Program at all.  For example, if a patent +license would not permit royalty-free redistribution of the Program 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 Program. + +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. + +  8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program 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. + +  9. The Free Software Foundation may publish revised and/or new versions +of the 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 Program +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 Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + +  10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, 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 + +  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU.  SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + +  12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +		     END OF TERMS AND CONDITIONS + +	    How to Apply These Terms to Your New Programs + +  If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + +  To do so, attach the following notices to the program.  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 program's name and a brief idea of what it does.> +    Copyright (C) <year>  <name of author> + +    This program is free software; you can redistribute it and/or modify +    it under the terms of the GNU General Public License as published by +    the Free Software Foundation; either version 2 of the License, or +    (at your option) any later version. + +    This program 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 General Public License for more details. + +    You should have received a copy of the GNU General Public License +    along with this program; if not, write to the Free Software +    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + +    Gnomovision version 69, Copyright (C) year name of author +    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. +    This is free software, and you are welcome to redistribute it +    under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License.  Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary.  Here is a sample; alter the names: + +  Yoyodyne, Inc., hereby disclaims all copyright interest in the program +  `Gnomovision' (which makes passes at compilers) written by James Hacker. + +  <signature of Ty Coon>, 1 April 1989 +  Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs.  If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library.  If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/libxsd-frontend/INSTALL b/libxsd-frontend/INSTALL new file mode 100644 index 0000000..756b7e4 --- /dev/null +++ b/libxsd-frontend/INSTALL @@ -0,0 +1,28 @@ +Prerequisites + +  build-time: + +    - build                >= 0.3.7  http://www.codesynthesis.com/projects/build/ +    - g++                  >= 3.4.3  http://gcc.gnu.org + +  run-time: + +    - libfrontend-elements >= 1.1.4  http://kolpackov.net/projects/libfrontend-elements/ +    - libcult              >= 1.4.6  http://kolpackov.net/projects/libcult/ +    - libxerces-c          >= 2.6.0  http://xerces.apache.org/xerces-c/ +    - libboost_filesystem  >= 1.33.1 http://boost.org + + +Building libxsd-frontend + +  To build in the source directory simply run 'make'. You can also +  build in a separate directory, e.g., + +  $ mkdir libxsd-frontend-i686-pc-linux-gnu +  $ cd libxsd-frontend-i686-pc-linux-gnu +  $ make -f ../libxsd-frontend-x.y.z/makefile + + +Installing libxsd-frontend + +  Not supported in this version. diff --git a/libxsd-frontend/LICENSE b/libxsd-frontend/LICENSE new file mode 100644 index 0000000..33b4cbc --- /dev/null +++ b/libxsd-frontend/LICENSE @@ -0,0 +1,22 @@ +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License version 2 as +published by the Free Software Foundation. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +In addition, as a special exception, Code Synthesis Tools CC gives +permission to link this program with the Xerces-C++ library (or with +modified versions of Xerces-C++ that use the same license as Xerces-C++), +and distribute linked combinations including the two. You must obey +the GNU General Public License version 2 in all respects for all of +the code used other than Xerces-C++. If you modify this copy of the +program, you may extend this exception to your version of the program, +but you are not obligated to do so. If you do not wish to do so, delete +this exception statement from your version. diff --git a/libxsd-frontend/NEWS b/libxsd-frontend/NEWS new file mode 100644 index 0000000..aca46a7 --- /dev/null +++ b/libxsd-frontend/NEWS @@ -0,0 +1,281 @@ +Version 1.17.0 + +  * Add support for resolving default/fixed values of QName type. Now  +    the qualified value is represented in the <namespace>#<qname> form. + +  * Anonymous transformation now passes the actual file path instead of +    the empty string to the AnonymousNameTranslator::translate() function +    for the translation unit. + +  * Anonymous transformation now names anonymous union member types. + +  * Do not copy ref'ed default values for non-optional attributes. + +  * Change predicate names in the semantic graph to consistently end  +    with _p. + +  * New transformation: enum synthesis. + +  * Add union information to the semantics graph. + +  * Add support for translating schema file paths. + +Version 1.16.0 +   +  * New transformation: simplifier. It simplifies the schema graph +    by, for example, removing empty compositors where it would not +    change the semantics of the schema. + +  * Added min() and max() accessors to the Particle and Compositor  +    semantic graph nodes. + +  * Added optional strong include key to the schema-per-type +    transformation. + +Version 1.15.0 + +  * Support for the simple type/simple content restriction facets. + +  * Support for suppressing frontend warnings. +   +  * Support for suppressing full schema checking. + +  * Support for the interface changes introduced in Xerces-C++ 3.0.0.b2. + +Version 1.14.0 + +  * Support for referencing names in including schema in chameleon inclusion. + +  * Support for native paths in include/import directives. + +  * Support for UTF-32 and UTF-16 in wchar_t. + +  * Fixed a bug in import stubs. +   +  * Got rid of warnings reported by g++-4.3. + +Version 1.13.0 + +  * Support for anonymous list item and simple type restriction base +    in both parser and anonymous transformation. + +Version 1.12.0 + +  * New transformations: anonymous and schema-per-type. + +  * Optional location translator can now be passed to parser's +    c-tor to translate included and imported schema locations. + +  * Support for the upcoming Xerces-C++ 3.0.0 release. + +  * Upgraded to the new boost import stub. + +  * Upgraded to the new xerces-c import stub. + +Version 1.11.0 + +  * New transformation, xsd-frontend/transformations/restriction.hxx, +    copies omitted attributes and establishes associations between +    attributes, elements, and wildcards in complex type inheritance +    by restriction. + +  * Upgraded to the new boost import stub. + +Version 1.10.1 + +  * Add XML Schema error detection that is missing in Xerces-C++. + +  * Update Xerces-C++ import stub to use the include directory +    instead of src for header inclusion. + +Version 1.10.0 + +  * New semantic graph node Annotation and edge Annotates. The parser +    now handles XML Schema annotations and builds the corresponding +    representation in the semantic graph. + +  * The library no longer depends on the internal Xerces-C++ headers +    and can be built against an installed version of Xerces-C++. + +Version 1.9.1 + +  * Element wildcard (SemanticGraph::Any) is now present in the complex +    type scope with an auto-generated name. + +  * Additional regression tests for wildcard parsing. + +Version 1.9.0 + +  * Upgraded to build-0.3.0. + +Version 1.8.3 + +  * Fix for a bug in the edge case of empty prefix namespace resolution. + +Version 1.8.2 + +  * Fix for a bug in element ordering. + + +Version 1.8.1 + +  * Fix for a bug in element group forward reference resolution. + +  * Set of regression tests. + + +Version 1.8.0 + +  * Support for the anyAttribute wildcard. + +  * Substitution edge is now propagated to referenced elements. + +  * Special parsing method which returns a graph that virtually +    corresponds to the XML Schema namespace definition with all +    the built-in type. + +  * Mixed content flag in SemanticGraph::Complex. + +  * Optional proper handling of inheritance by restriction. + + +Version 1.7.0 + +  * Added Restricts and Extends edges that model XML Schema inheritance +    by restriction and inheritance by extension, respectively. The parser +    was adjusted to use these edges instead of the generic Inherits edge. + +  * Implemented handling of the complex content inheritance by restriction. + +  * Fixed the chameleon inclusion code to create one Schema node per each +    unique namespace. + +  * Removed support for multiple inheritance in Complex. + +  * Added a constructor that takes one node traverser to all edge traversers. + + +Version 1.6.1 + +  * Bug fixes in the parser. + + +Version 1.6.0 + +  * Support for traversing inheritance graph of enumerations. + +  * Support for removal of Names edges. + + +Version 1.5.0 + +  * Semantic graph now captures containment relations for elements. New +    semantic graph nodes: particle, compositor, all, choice, sequence. + +  * Element and attribute groups are not first-class semantic graph +    nodes: element-group and attribute-group. References to groups +    are still fully resolved (i.e., their content is copied into +    referencing constructs). + + +Version 1.4.1 + +  * Upgraded to the version-aware libboost import stub. + + +Version 1.4.0 + +  * Moved to the build 0.2 series. + +  * Support for the default and fixed values in attribute and element +    definitions. + + +Version 1.3.0 + +  * Several bug fixes in the parser. + +  * Basic support for union. Union member types are not yet tracked. + + +Version 1.2.0 + +  * Bug fixes in the parser. + +  * Support for the 'substitutes' relation. + +  * A flag that indicates whether an element is global. + + +Version 1.1.0 + +  * Basic support for inheritance-by-restriction of complex types. + +  * Support for mixed content model by simply ignoring the attribute. + +  * Support for xsd:anyAttribute by simply ignoring the declaration. + +  * Support for xsd:any. + +  * Support for the element/attribute-belongs-to-a-namespace relation +    for qualified elements and attributes. + + +Version 1.0.6 + +  * Bug fixes in the parser. + +  * Support for xsd:list. + +  * Support for the 'refType' extension attribute which allows to specify +    referenced type for IDREF/IDREFS data types. + + +Version 1.0.5 + +  * Bug fixes in the parser. + +  * SemanticGraph::Scope::NamesList uses List container instead of Vector. +    This allows changing the semantic graph while traversing it. + +  * SemanticGraph::Schema graph node supports multiple incoming Contains +    edges. + +  * Traversal::Scope has been extended to support traversal of changing +    semantic graphs. + + +Version 1.0.4 + +  * Diagnostics improvements. + +  * Bug fixes in the filesystem path handling logic. + + +Version 1.0.3 + +  * Bug fixes in the filesystem path handling logic. + + +Version 1.0.2 + +  * Parser now handles subsequent inclusion/importing of the same +    schema by creating an appropriate edge in the semantic graph. +    Note that this may result in the semantic graph having cycles +    of Includes/Imports/Sources edges. + +  * Support for iteration over Belongs edges in SemanticGraph::Type. + + +Version 1.0.1 + +  * Diagnostics improvements. + +  * Build system improvements. + +  * Code cleanups. + + +Version 1.0.0 + +  * First public release. diff --git a/libxsd-frontend/README b/libxsd-frontend/README new file mode 100644 index 0000000..afc6e58 --- /dev/null +++ b/libxsd-frontend/README @@ -0,0 +1,13 @@ +libxsd-frontend is a compiler frontend for the W3C XML Schema definition +language. It includes parser, semantic graph types and traversal mechanism. + +See the NEWS file for the user-visible changes from the previous release. + +See the LICENSE file for distribution conditions. + +See the INSTALL file for prerequisites and installation instructions. + +The project page is at http://codesynthesis.com/projects/libxsd-frontend/. + +Send bug reports or any other feedback to the +libxsd-frontend-users@codesynthesis.com mailing list. diff --git a/libxsd-frontend/build/bootstrap.make b/libxsd-frontend/build/bootstrap.make new file mode 100644 index 0000000..4db3c99 --- /dev/null +++ b/libxsd-frontend/build/bootstrap.make @@ -0,0 +1,46 @@ +# file      : build/bootstrap.make +# author    : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +# license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +project_name := libxsd-frontend + +# First try to include the bundled bootstrap.make if it exist. If that +# fails, let make search for the external bootstrap.make. +# +build := build-0.3 + +-include $(dir $(lastword $(MAKEFILE_LIST)))../../$(build)/bootstrap.make + +ifeq ($(patsubst %build/bootstrap.make,,$(lastword $(MAKEFILE_LIST))),) +include $(build)/bootstrap.make +endif + +# Aliases +# +.PHONY: $(out_base)/       \ +        $(out_base)/.test  \ +        $(out_base)/.clean + +ifdef %interactive% + +.PHONY: test clean + +test: $(out_base)/.test +clean: $(out_base)/.clean + +ifneq ($(filter $(.DEFAULT_GOAL),test clean),) +.DEFAULT_GOAL := +endif + +endif + +# Don't include dependency info for certain targets. +# +define include-dep +$(call -include,$1) +endef + +ifneq ($(filter $(MAKECMDGOALS),clean cleandoc disfigure),) +include-dep = +endif diff --git a/libxsd-frontend/build/cxx/configuration-dynamic.make b/libxsd-frontend/build/cxx/configuration-dynamic.make new file mode 100644 index 0000000..568ab40 --- /dev/null +++ b/libxsd-frontend/build/cxx/configuration-dynamic.make @@ -0,0 +1,14 @@ +cxx_id       := gnu +cxx_optimize := n +cxx_debug    := n +cxx_rpath    := n +cxx_pp_extra_options := $(CPPFLAGS) +cxx_extra_options    := $(CXXFLAGS) +cxx_ld_extra_options := $(LDFLAGS) +cxx_extra_libs       := $(LIBS) + +r := $(shell echo $(LDFLAGS) | sed -e 's/-L *\([^ ]*\)/-L\1/g') +r := $(patsubst -L%,%,$(filter -L%,$(r))) +r := $(shell echo $(r) | sed -e 's/ /:/g') + +cxx_extra_lib_paths  := $(r) diff --git a/libxsd-frontend/build/cxx/gnu/configuration-dynamic.make b/libxsd-frontend/build/cxx/gnu/configuration-dynamic.make new file mode 100644 index 0000000..f3fe64d --- /dev/null +++ b/libxsd-frontend/build/cxx/gnu/configuration-dynamic.make @@ -0,0 +1,8 @@ +ifneq ($(CXX),) +cxx_gnu := $(CXX) +else +cxx_gnu := g++ +endif + +cxx_gnu_libraries :=  +cxx_gnu_optimization_options := diff --git a/libxsd-frontend/build/export/libxsd-frontend/stub.make b/libxsd-frontend/build/export/libxsd-frontend/stub.make new file mode 100644 index 0000000..adae4b7 --- /dev/null +++ b/libxsd-frontend/build/export/libxsd-frontend/stub.make @@ -0,0 +1,10 @@ +# file      : build/import/libxsd-frontend/stub.make +# author    : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +# license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +$(call include-once,$(src_root)/xsd-frontend/makefile,$(out_root)) + +$(call export,\ +  l: $(out_root)/xsd-frontend/xsd-frontend.l,\ +  cpp-options: $(out_root)/xsd-frontend/xsd-frontend.l.cpp-options) diff --git a/libxsd-frontend/build/import/libboost/LICENSE b/libxsd-frontend/build/import/libboost/LICENSE new file mode 100644 index 0000000..3912109 --- /dev/null +++ b/libxsd-frontend/build/import/libboost/LICENSE @@ -0,0 +1,340 @@ +		    GNU GENERAL PUBLIC LICENSE +		       Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. +                       51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +			    Preamble + +  The licenses for most software are designed to take away your +freedom to share and change it.  By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users.  This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it.  (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.)  You can apply it to +your programs, 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 software, or if you modify it. + +  For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have.  You must make sure that they, too, receive or can get the +source code.  And you must show them these terms so they know their +rights. + +  We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + +  Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software.  If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, 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 redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary.  To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + +  The precise terms and conditions for copying, distribution and +modification follow. + +		    GNU GENERAL PUBLIC LICENSE +   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +  0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License.  The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language.  (Hereinafter, translation is included without limitation in +the term "modification".)  Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope.  The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + +  1. You may copy and distribute verbatim copies of the Program's +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 give any other recipients of the Program a copy of this License +along with the Program. + +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 Program or any portion +of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices +    stating that you changed the files and the date of any change. + +    b) You must cause any work that you distribute or publish, that in +    whole or in part contains or is derived from the Program or any +    part thereof, to be licensed as a whole at no charge to all third +    parties under the terms of this License. + +    c) If the modified program normally reads commands interactively +    when run, you must cause it, when started running for such +    interactive use in the most ordinary way, to print or display an +    announcement including an appropriate copyright notice and a +    notice that there is no warranty (or else, saying that you provide +    a warranty) and that users may redistribute the program under +    these conditions, and telling the user how to view a copy of this +    License.  (Exception: if the Program itself is interactive but +    does not normally print such an announcement, your work based on +    the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole.  If +identifiable sections of that work are not derived from the Program, +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 Program, 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 Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + +  3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + +    a) 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; or, + +    b) Accompany it with a written offer, valid for at least three +    years, to give any third party, for a charge no more than your +    cost of physically performing source distribution, a complete +    machine-readable copy of the corresponding source code, to be +    distributed under the terms of Sections 1 and 2 above on a medium +    customarily used for software interchange; or, + +    c) Accompany it with the information you received as to the offer +    to distribute corresponding source code.  (This alternative is +    allowed only for noncommercial distribution and only if you +    received the program in object code or executable form with such +    an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it.  For an executable work, 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 executable.  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. + +If distribution of executable or 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 counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + +  4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License.  Any attempt +otherwise to copy, modify, sublicense or distribute the Program 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. + +  5. 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 Program or its derivative works.  These actions are +prohibited by law if you do not accept this License.  Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + +  6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program 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. + +  7. 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 Program at all.  For example, if a patent +license would not permit royalty-free redistribution of the Program 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 Program. + +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. + +  8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program 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. + +  9. The Free Software Foundation may publish revised and/or new versions +of the 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 Program +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 Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + +  10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, 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 + +  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU.  SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + +  12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +		     END OF TERMS AND CONDITIONS + +	    How to Apply These Terms to Your New Programs + +  If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + +  To do so, attach the following notices to the program.  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 program's name and a brief idea of what it does.> +    Copyright (C) <year>  <name of author> + +    This program is free software; you can redistribute it and/or modify +    it under the terms of the GNU General Public License as published by +    the Free Software Foundation; either version 2 of the License, or +    (at your option) any later version. + +    This program 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 General Public License for more details. + +    You should have received a copy of the GNU General Public License +    along with this program; if not, write to the Free Software +    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + +    Gnomovision version 69, Copyright (C) year name of author +    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. +    This is free software, and you are welcome to redistribute it +    under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License.  Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary.  Here is a sample; alter the names: + +  Yoyodyne, Inc., hereby disclaims all copyright interest in the program +  `Gnomovision' (which makes passes at compilers) written by James Hacker. + +  <signature of Ty Coon>, 1 April 1989 +  Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs.  If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library.  If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/libxsd-frontend/build/import/libboost/configuration-dynamic.make b/libxsd-frontend/build/import/libboost/configuration-dynamic.make new file mode 100644 index 0000000..ab55882 --- /dev/null +++ b/libxsd-frontend/build/import/libboost/configuration-dynamic.make @@ -0,0 +1,8 @@ +libboost_installed := y +libboost_suffix := $(BOOST_LIB_SUFFIX) + +ifeq ($(BOOST_LINK_SYSTEM),n) +libboost_system := n +else +libboost_system := y +endif diff --git a/libxsd-frontend/build/import/libboost/configuration-rules.make b/libxsd-frontend/build/import/libboost/configuration-rules.make new file mode 100644 index 0000000..40fff9f --- /dev/null +++ b/libxsd-frontend/build/import/libboost/configuration-rules.make @@ -0,0 +1,15 @@ +# file      : build/import/libboost/configuration-rules.make +# author    : Boris Kolpackov <boris@kolpackov.net> +# copyright : Copyright (c) 2005-2010 Boris Kolpackov +# license   : GNU GPL v2; see accompanying LICENSE file + +$(dcf_root)/import/libboost/configuration-dynamic.make: | $(dcf_root)/import/libboost/. +	$(call message,,$(scf_root)/import/libboost/configure $@) + +ifndef %foreign% + +disfigure:: +	$(call message,rm $(dcf_root)/import/libboost/configuration-dynamic.make,\ +rm -f $(dcf_root)/import/libboost/configuration-dynamic.make) + +endif diff --git a/libxsd-frontend/build/import/libboost/configure b/libxsd-frontend/build/import/libboost/configure new file mode 100755 index 0000000..c924a30 --- /dev/null +++ b/libxsd-frontend/build/import/libboost/configure @@ -0,0 +1,74 @@ +#! /usr/bin/env bash + +# file      : build/import/libboost/configure +# author    : Boris Kolpackov <boris@kolpackov.net> +# copyright : Copyright (c) 2005-2010 Boris Kolpackov +# license   : GNU GPL v2; see accompanying LICENSE file + + +# $1           - out config file +# +# bld_root     - build root +# project_name - project name +# + +source $bld_root/dialog.bash + + +$echo +$echo "Configuring external dependency on 'boost libraries' for '$project_name'." +$echo + +$echo +$echo "Would you like to configure dependency on the installed version" +$echo "of 'boost libraries' as opposed to the development build?" +$echo + +installed=`read_y_n y` + +if [ "$installed" = "n" ]; then + +  $echo +  $echo "Please enter the 'boost' root directory." +  $echo + +  root=`read_path --directory --exist` + +  $echo +  $echo "Please select the library type you would like to use:" +  $echo +  $echo "(1) archive" +  $echo "(2) shared object" +  $echo + +  type=`read_option "archive shared" "shared"` +fi + +$echo +$echo "Link explicitly to the boost system library? This library" +$echo "is available since boost 1.35.0 and linking to it explicitly" +$echo "may be required by newer linkers." +$echo + +link_system=`read_y_n y` + +$echo +$echo "Please enter optional suffix that may be embedded into the" +$echo "boost library names. For example, if your library names are in" +$echo "the libboost_regex-gcc41-mt-d.so form, then enter -gcc41-mt-d" +$echo "Otherwise leave this field blank." +$echo + +suffix= +read -e -p "[]: " suffix + +echo libboost_installed := $installed   >$1 +echo libboost_suffix    := $suffix      >>$1 +echo libboost_system    := $link_system >>$1 + +if [ "$installed" = "n" ]; then + +  echo libboost_root    := $root    >>$1 +  echo libboost_type    := $type    >>$1 + +fi diff --git a/libxsd-frontend/build/import/libboost/filesystem/rules.make b/libxsd-frontend/build/import/libboost/filesystem/rules.make new file mode 100644 index 0000000..b5febd3 --- /dev/null +++ b/libxsd-frontend/build/import/libboost/filesystem/rules.make @@ -0,0 +1,53 @@ +# file      : build/import/libboost/filesystem/rules.make +# author    : Boris Kolpackov <boris@kolpackov.net> +# copyright : Copyright (c) 2005-2010 Boris Kolpackov +# license   : GNU GPL v2; see accompanying LICENSE file + +#@@ Should use message everywhere. +# + +$(dcf_root)/import/libboost/%: root := $(libboost_root) + +$(dcf_root)/import/libboost/filesystem/filesystem.l: \ +  | $(dcf_root)/import/libboost/filesystem/. + +ifeq ($(libboost_type),archive) + +ifeq ($(libboost_system),y) +$(dcf_root)/import/libboost/filesystem/filesystem.l: \ +  $(libboost_root)/stage/lib/libboost_filesystem$(libboost_suffix).a \ +  $(libboost_root)/stage/lib/libboost_system$(libboost_suffix).a +else +$(dcf_root)/import/libboost/filesystem/filesystem.l: \ +  $(libboost_root)/stage/lib/libboost_filesystem$(libboost_suffix).a +endif +	@echo $^ >$@ + +else + +ifeq ($(libboost_system),y) +$(dcf_root)/import/libboost/filesystem/filesystem.l: \ +  $(libboost_root)/stage/lib/libboost_filesystem$(libboost_suffix).so \ +  $(libboost_root)/stage/lib/libboost_system$(libboost_suffix).so +else +$(dcf_root)/import/libboost/filesystem/filesystem.l: \ +  $(libboost_root)/stage/lib/libboost_filesystem$(libboost_suffix).so +endif +	@echo $^ >$@ +	@echo rpath:$(root)/stage/lib >>$@ + +endif + + +$(dcf_root)/import/libboost/filesystem/filesystem.l.cpp-options: \ +  | $(dcf_root)/import/libboost/filesystem/. +	@echo include: -I$(root) >$@ + +ifndef %foreign% + +disfigure:: +	$(call message,rm $(dcf_root)/import/libboost/filesystem/filesystem.l,\ +rm -f $(dcf_root)/import/libboost/filesystem/filesystem.l) +	$(call message,,rm -f $(dcf_root)/import/libboost/filesystem/filesystem.l.cpp-options) + +endif diff --git a/libxsd-frontend/build/import/libboost/filesystem/stub.make b/libxsd-frontend/build/import/libboost/filesystem/stub.make new file mode 100644 index 0000000..fb7398d --- /dev/null +++ b/libxsd-frontend/build/import/libboost/filesystem/stub.make @@ -0,0 +1,36 @@ +# file      : build/import/libboost/filesystem/stub.make +# author    : Boris Kolpackov <boris@kolpackov.net> +# copyright : Copyright (c) 2005-2010 Boris Kolpackov +# license   : GNU GPL v2; see accompanying LICENSE file + +$(call include-once,$(scf_root)/import/libboost/configuration-rules.make,$(dcf_root)) + +libboost_installed := + +$(call -include,$(dcf_root)/import/libboost/configuration-dynamic.make) + +ifdef libboost_installed + +ifeq ($(libboost_installed),y) + +ifeq ($(libboost_system),y) +$(call export,l: -lboost_filesystem$(libboost_suffix) -lboost_system$(libboost_suffix),cpp_options: ) +else +$(call export,l: -lboost_filesystem$(libboost_suffix),cpp_options: ) +endif + +else + +$(call include-once,$(scf_root)/import/libboost/filesystem/rules.make,$(dcf_root)) + +$(call export,\ +  l: $(dcf_root)/import/libboost/filesystem/filesystem.l,\ +  cpp-options: $(dcf_root)/import/libboost/filesystem/filesystem.l.cpp-options) + +endif + +else + +.NOTPARALLEL: + +endif diff --git a/libxsd-frontend/build/import/libboost/version b/libxsd-frontend/build/import/libboost/version new file mode 100644 index 0000000..faef31a --- /dev/null +++ b/libxsd-frontend/build/import/libboost/version @@ -0,0 +1 @@ +0.7.0 diff --git a/libxsd-frontend/build/import/libcult/LICENSE b/libxsd-frontend/build/import/libcult/LICENSE new file mode 100644 index 0000000..3912109 --- /dev/null +++ b/libxsd-frontend/build/import/libcult/LICENSE @@ -0,0 +1,340 @@ +		    GNU GENERAL PUBLIC LICENSE +		       Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. +                       51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +			    Preamble + +  The licenses for most software are designed to take away your +freedom to share and change it.  By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users.  This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it.  (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.)  You can apply it to +your programs, 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 software, or if you modify it. + +  For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have.  You must make sure that they, too, receive or can get the +source code.  And you must show them these terms so they know their +rights. + +  We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + +  Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software.  If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, 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 redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary.  To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + +  The precise terms and conditions for copying, distribution and +modification follow. + +		    GNU GENERAL PUBLIC LICENSE +   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +  0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License.  The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language.  (Hereinafter, translation is included without limitation in +the term "modification".)  Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope.  The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + +  1. You may copy and distribute verbatim copies of the Program's +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 give any other recipients of the Program a copy of this License +along with the Program. + +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 Program or any portion +of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices +    stating that you changed the files and the date of any change. + +    b) You must cause any work that you distribute or publish, that in +    whole or in part contains or is derived from the Program or any +    part thereof, to be licensed as a whole at no charge to all third +    parties under the terms of this License. + +    c) If the modified program normally reads commands interactively +    when run, you must cause it, when started running for such +    interactive use in the most ordinary way, to print or display an +    announcement including an appropriate copyright notice and a +    notice that there is no warranty (or else, saying that you provide +    a warranty) and that users may redistribute the program under +    these conditions, and telling the user how to view a copy of this +    License.  (Exception: if the Program itself is interactive but +    does not normally print such an announcement, your work based on +    the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole.  If +identifiable sections of that work are not derived from the Program, +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 Program, 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 Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + +  3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + +    a) 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; or, + +    b) Accompany it with a written offer, valid for at least three +    years, to give any third party, for a charge no more than your +    cost of physically performing source distribution, a complete +    machine-readable copy of the corresponding source code, to be +    distributed under the terms of Sections 1 and 2 above on a medium +    customarily used for software interchange; or, + +    c) Accompany it with the information you received as to the offer +    to distribute corresponding source code.  (This alternative is +    allowed only for noncommercial distribution and only if you +    received the program in object code or executable form with such +    an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it.  For an executable work, 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 executable.  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. + +If distribution of executable or 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 counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + +  4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License.  Any attempt +otherwise to copy, modify, sublicense or distribute the Program 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. + +  5. 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 Program or its derivative works.  These actions are +prohibited by law if you do not accept this License.  Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + +  6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program 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. + +  7. 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 Program at all.  For example, if a patent +license would not permit royalty-free redistribution of the Program 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 Program. + +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. + +  8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program 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. + +  9. The Free Software Foundation may publish revised and/or new versions +of the 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 Program +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 Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + +  10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, 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 + +  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU.  SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + +  12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +		     END OF TERMS AND CONDITIONS + +	    How to Apply These Terms to Your New Programs + +  If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + +  To do so, attach the following notices to the program.  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 program's name and a brief idea of what it does.> +    Copyright (C) <year>  <name of author> + +    This program is free software; you can redistribute it and/or modify +    it under the terms of the GNU General Public License as published by +    the Free Software Foundation; either version 2 of the License, or +    (at your option) any later version. + +    This program 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 General Public License for more details. + +    You should have received a copy of the GNU General Public License +    along with this program; if not, write to the Free Software +    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + +    Gnomovision version 69, Copyright (C) year name of author +    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. +    This is free software, and you are welcome to redistribute it +    under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License.  Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary.  Here is a sample; alter the names: + +  Yoyodyne, Inc., hereby disclaims all copyright interest in the program +  `Gnomovision' (which makes passes at compilers) written by James Hacker. + +  <signature of Ty Coon>, 1 April 1989 +  Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs.  If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library.  If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/libxsd-frontend/build/import/libcult/configuration-dynamic.make b/libxsd-frontend/build/import/libcult/configuration-dynamic.make new file mode 100644 index 0000000..73c92bb --- /dev/null +++ b/libxsd-frontend/build/import/libcult/configuration-dynamic.make @@ -0,0 +1,4 @@ +libcult_installed := n +src_root := $(abspath $(src_root)/../libcult) +scf_root := $(src_root)/build +out_root := $(src_root) diff --git a/libxsd-frontend/build/import/libcult/configuration-rules.make b/libxsd-frontend/build/import/libcult/configuration-rules.make new file mode 100644 index 0000000..dc19df4 --- /dev/null +++ b/libxsd-frontend/build/import/libcult/configuration-rules.make @@ -0,0 +1,15 @@ +# file      : build/import/libcult/configuration-rules.make +# author    : Boris Kolpackov <boris@kolpackov.net> +# copyright : Copyright (c) 2005-2009 Boris Kolpackov +# license   : GNU GPL v2; see accompanying LICENSE file + +$(dcf_root)/import/libcult/configuration-dynamic.make: | $(dcf_root)/import/libcult/. +	$(call message,,$(scf_root)/import/libcult/configure $@) + +ifndef %foreign% + +disfigure:: +	$(call message,rm $(dcf_root)/import/libcult/configuration-dynamic.make,\ +rm -f $(dcf_root)/import/libcult/configuration-dynamic.make) + +endif diff --git a/libxsd-frontend/build/import/libcult/configure b/libxsd-frontend/build/import/libcult/configure new file mode 100755 index 0000000..afa4c9c --- /dev/null +++ b/libxsd-frontend/build/import/libcult/configure @@ -0,0 +1,55 @@ +#! /usr/bin/env bash + +# file      : build/import/libcult/configure +# author    : Boris Kolpackov <boris@kolpackov.net> +# copyright : Copyright (c) 2005-2009 Boris Kolpackov +# license   : GNU GPL v2; see accompanying LICENSE file + + +# $1           - out file +# +# bld_root     - build root +# project_name - project name +# + +source $bld_root/dialog.bash + + +$echo +$echo "Configuring external dependency on 'libcult' for '$project_name'." +$echo + +$echo +$echo "Would you like to configure dependency on the installed " +$echo "version of 'libcult' as opposed to the development build?" +$echo + +installed=`read_y_n y` + +path= + +if [ "$installed" = "n" ]; then + +$echo +$echo "Please enter the src_root for 'libcult'." +$echo + +src_root=`read_path --directory --exist` + +$echo +$echo "Please enter the out_root for 'libcult'." +$echo + +out_root=`read_path --directory $src_root` + +fi + +echo libcult_installed := $installed   >$1 + +if [ "$installed" = "n" ]; then + +echo src_root := $src_root            >>$1 +echo scf_root := \$\(src_root\)/build >>$1 +echo out_root := $out_root            >>$1 + +fi diff --git a/libxsd-frontend/build/import/libcult/stub.make b/libxsd-frontend/build/import/libcult/stub.make new file mode 100644 index 0000000..f5f7691 --- /dev/null +++ b/libxsd-frontend/build/import/libcult/stub.make @@ -0,0 +1,30 @@ +# file      : build/import/libcult/stub.make +# author    : Boris Kolpackov <boris@kolpackov.net> +# copyright : Copyright (c) 2005-2009 Boris Kolpackov +# license   : GNU GPL v2; see accompanying LICENSE file + +$(call include-once,$(scf_root)/import/libcult/configuration-rules.make,$(dcf_root)) + +libcult_installed := + +$(call -include,$(dcf_root)/import/libcult/configuration-dynamic.make) + +ifdef libcult_installed + +ifeq ($(libcult_installed),y) + +$(call export,l: -lcult,cpp-options: ) + +else + +# Include export stub. +# +$(call include,$(scf_root)/export/libcult/stub.make) + +endif + +else + +.NOTPARALLEL: + +endif diff --git a/libxsd-frontend/build/import/libfrontend-elements/LICENSE b/libxsd-frontend/build/import/libfrontend-elements/LICENSE new file mode 100644 index 0000000..3912109 --- /dev/null +++ b/libxsd-frontend/build/import/libfrontend-elements/LICENSE @@ -0,0 +1,340 @@ +		    GNU GENERAL PUBLIC LICENSE +		       Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. +                       51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +			    Preamble + +  The licenses for most software are designed to take away your +freedom to share and change it.  By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users.  This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it.  (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.)  You can apply it to +your programs, 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 software, or if you modify it. + +  For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have.  You must make sure that they, too, receive or can get the +source code.  And you must show them these terms so they know their +rights. + +  We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + +  Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software.  If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, 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 redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary.  To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + +  The precise terms and conditions for copying, distribution and +modification follow. + +		    GNU GENERAL PUBLIC LICENSE +   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +  0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License.  The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language.  (Hereinafter, translation is included without limitation in +the term "modification".)  Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope.  The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + +  1. You may copy and distribute verbatim copies of the Program's +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 give any other recipients of the Program a copy of this License +along with the Program. + +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 Program or any portion +of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices +    stating that you changed the files and the date of any change. + +    b) You must cause any work that you distribute or publish, that in +    whole or in part contains or is derived from the Program or any +    part thereof, to be licensed as a whole at no charge to all third +    parties under the terms of this License. + +    c) If the modified program normally reads commands interactively +    when run, you must cause it, when started running for such +    interactive use in the most ordinary way, to print or display an +    announcement including an appropriate copyright notice and a +    notice that there is no warranty (or else, saying that you provide +    a warranty) and that users may redistribute the program under +    these conditions, and telling the user how to view a copy of this +    License.  (Exception: if the Program itself is interactive but +    does not normally print such an announcement, your work based on +    the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole.  If +identifiable sections of that work are not derived from the Program, +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 Program, 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 Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + +  3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + +    a) 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; or, + +    b) Accompany it with a written offer, valid for at least three +    years, to give any third party, for a charge no more than your +    cost of physically performing source distribution, a complete +    machine-readable copy of the corresponding source code, to be +    distributed under the terms of Sections 1 and 2 above on a medium +    customarily used for software interchange; or, + +    c) Accompany it with the information you received as to the offer +    to distribute corresponding source code.  (This alternative is +    allowed only for noncommercial distribution and only if you +    received the program in object code or executable form with such +    an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it.  For an executable work, 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 executable.  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. + +If distribution of executable or 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 counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + +  4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License.  Any attempt +otherwise to copy, modify, sublicense or distribute the Program 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. + +  5. 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 Program or its derivative works.  These actions are +prohibited by law if you do not accept this License.  Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + +  6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program 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. + +  7. 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 Program at all.  For example, if a patent +license would not permit royalty-free redistribution of the Program 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 Program. + +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. + +  8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program 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. + +  9. The Free Software Foundation may publish revised and/or new versions +of the 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 Program +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 Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + +  10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, 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 + +  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU.  SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + +  12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +		     END OF TERMS AND CONDITIONS + +	    How to Apply These Terms to Your New Programs + +  If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + +  To do so, attach the following notices to the program.  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 program's name and a brief idea of what it does.> +    Copyright (C) <year>  <name of author> + +    This program is free software; you can redistribute it and/or modify +    it under the terms of the GNU General Public License as published by +    the Free Software Foundation; either version 2 of the License, or +    (at your option) any later version. + +    This program 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 General Public License for more details. + +    You should have received a copy of the GNU General Public License +    along with this program; if not, write to the Free Software +    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + +    Gnomovision version 69, Copyright (C) year name of author +    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. +    This is free software, and you are welcome to redistribute it +    under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License.  Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary.  Here is a sample; alter the names: + +  Yoyodyne, Inc., hereby disclaims all copyright interest in the program +  `Gnomovision' (which makes passes at compilers) written by James Hacker. + +  <signature of Ty Coon>, 1 April 1989 +  Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs.  If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library.  If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/libxsd-frontend/build/import/libfrontend-elements/configuration-dynamic.make b/libxsd-frontend/build/import/libfrontend-elements/configuration-dynamic.make new file mode 100644 index 0000000..70d0da6 --- /dev/null +++ b/libxsd-frontend/build/import/libfrontend-elements/configuration-dynamic.make @@ -0,0 +1,4 @@ +libfrontend_elements_installed := n +src_root := $(abspath $(src_root)/../libfrontend-elements) +scf_root := $(src_root)/build +out_root := $(src_root) diff --git a/libxsd-frontend/build/import/libfrontend-elements/configuration-rules.make b/libxsd-frontend/build/import/libfrontend-elements/configuration-rules.make new file mode 100644 index 0000000..a7db697 --- /dev/null +++ b/libxsd-frontend/build/import/libfrontend-elements/configuration-rules.make @@ -0,0 +1,15 @@ +# file      : build/import/libfrontend-elements/configuration-rules.make +# author    : Boris Kolpackov <boris@kolpackov.net> +# copyright : Copyright (c) 2005-2009 Boris Kolpackov +# license   : GNU GPL v2; see accompanying LICENSE file + +$(dcf_root)/import/libfrontend-elements/configuration-dynamic.make: | $(dcf_root)/import/libfrontend-elements/. +	$(call message,,$(scf_root)/import/libfrontend-elements/configure $@) + +ifndef %foreign% + +disfigure:: +	$(call message,rm $(dcf_root)/import/libfrontend-elements/configuration-dynamic.make,\ +rm -f $(dcf_root)/import/libfrontend-elements/configuration-dynamic.make) + +endif diff --git a/libxsd-frontend/build/import/libfrontend-elements/configure b/libxsd-frontend/build/import/libfrontend-elements/configure new file mode 100755 index 0000000..d02b4f7 --- /dev/null +++ b/libxsd-frontend/build/import/libfrontend-elements/configure @@ -0,0 +1,55 @@ +#! /usr/bin/env bash + +# file      : build/import/libfrontend-elements/configure +# author    : Boris Kolpackov <boris@kolpackov.net> +# copyright : Copyright (c) 2005-2009 Boris Kolpackov +# license   : GNU GPL v2; see accompanying LICENSE file + + +# $1           - out file +# +# bld_root     - build root +# project_name - project name +# + +source $bld_root/dialog.bash + + +$echo +$echo "Configuring external dependency on 'libfrontend-elements' for '$project_name'." +$echo + +$echo +$echo "Would you like to configure dependency on the installed version" +$echo "of 'libfrontend-elements' as opposed to the development build?" +$echo + +installed=`read_y_n y` + +path= + +if [ "$installed" = "n" ]; then + +$echo +$echo "Please enter the src_root for 'libfrontend-elements'." +$echo + +src_root=`read_path --directory --exist` + +$echo +$echo "Please enter the out_root for 'libfrontend-elements'." +$echo + +out_root=`read_path --directory $src_root` + +fi + +echo libfrontend_elements_installed := $installed   >$1 + +if [ "$installed" = "n" ]; then + +echo src_root := $src_root            >>$1 +echo scf_root := \$\(src_root\)/build >>$1 +echo out_root := $out_root            >>$1 + +fi diff --git a/libxsd-frontend/build/import/libfrontend-elements/stub.make b/libxsd-frontend/build/import/libfrontend-elements/stub.make new file mode 100644 index 0000000..d701305 --- /dev/null +++ b/libxsd-frontend/build/import/libfrontend-elements/stub.make @@ -0,0 +1,30 @@ +# file      : build/import/libfrontend-elements/stub.make +# author    : Boris Kolpackov <boris@kolpackov.net> +# copyright : Copyright (c) 2005-2009 Boris Kolpackov +# license   : GNU GPL v2; see accompanying LICENSE file + +$(call include-once,$(scf_root)/import/libfrontend-elements/configuration-rules.make,$(dcf_root)) + +libfrontend_elements_installed := + +$(call -include,$(dcf_root)/import/libfrontend-elements/configuration-dynamic.make) + +ifdef libfrontend_elements_installed + +ifeq ($(libfrontend_elements_installed),y) + +$(call export,l: -lfrontend-elements -lcult,cpp_options: ) + +else + +# Include export stub. +# +$(call include,$(scf_root)/export/libfrontend-elements/stub.make) + +endif + +else + +.NOTPARALLEL: + +endif diff --git a/libxsd-frontend/build/import/libxerces-c/LICENSE b/libxsd-frontend/build/import/libxerces-c/LICENSE new file mode 100644 index 0000000..3912109 --- /dev/null +++ b/libxsd-frontend/build/import/libxerces-c/LICENSE @@ -0,0 +1,340 @@ +		    GNU GENERAL PUBLIC LICENSE +		       Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. +                       51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +			    Preamble + +  The licenses for most software are designed to take away your +freedom to share and change it.  By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users.  This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it.  (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.)  You can apply it to +your programs, 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 software, or if you modify it. + +  For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have.  You must make sure that they, too, receive or can get the +source code.  And you must show them these terms so they know their +rights. + +  We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + +  Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software.  If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, 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 redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary.  To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + +  The precise terms and conditions for copying, distribution and +modification follow. + +		    GNU GENERAL PUBLIC LICENSE +   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +  0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License.  The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language.  (Hereinafter, translation is included without limitation in +the term "modification".)  Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope.  The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + +  1. You may copy and distribute verbatim copies of the Program's +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 give any other recipients of the Program a copy of this License +along with the Program. + +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 Program or any portion +of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices +    stating that you changed the files and the date of any change. + +    b) You must cause any work that you distribute or publish, that in +    whole or in part contains or is derived from the Program or any +    part thereof, to be licensed as a whole at no charge to all third +    parties under the terms of this License. + +    c) If the modified program normally reads commands interactively +    when run, you must cause it, when started running for such +    interactive use in the most ordinary way, to print or display an +    announcement including an appropriate copyright notice and a +    notice that there is no warranty (or else, saying that you provide +    a warranty) and that users may redistribute the program under +    these conditions, and telling the user how to view a copy of this +    License.  (Exception: if the Program itself is interactive but +    does not normally print such an announcement, your work based on +    the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole.  If +identifiable sections of that work are not derived from the Program, +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 Program, 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 Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + +  3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + +    a) 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; or, + +    b) Accompany it with a written offer, valid for at least three +    years, to give any third party, for a charge no more than your +    cost of physically performing source distribution, a complete +    machine-readable copy of the corresponding source code, to be +    distributed under the terms of Sections 1 and 2 above on a medium +    customarily used for software interchange; or, + +    c) Accompany it with the information you received as to the offer +    to distribute corresponding source code.  (This alternative is +    allowed only for noncommercial distribution and only if you +    received the program in object code or executable form with such +    an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it.  For an executable work, 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 executable.  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. + +If distribution of executable or 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 counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + +  4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License.  Any attempt +otherwise to copy, modify, sublicense or distribute the Program 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. + +  5. 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 Program or its derivative works.  These actions are +prohibited by law if you do not accept this License.  Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + +  6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program 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. + +  7. 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 Program at all.  For example, if a patent +license would not permit royalty-free redistribution of the Program 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 Program. + +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. + +  8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program 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. + +  9. The Free Software Foundation may publish revised and/or new versions +of the 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 Program +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 Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + +  10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, 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 + +  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU.  SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + +  12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +		     END OF TERMS AND CONDITIONS + +	    How to Apply These Terms to Your New Programs + +  If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + +  To do so, attach the following notices to the program.  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 program's name and a brief idea of what it does.> +    Copyright (C) <year>  <name of author> + +    This program is free software; you can redistribute it and/or modify +    it under the terms of the GNU General Public License as published by +    the Free Software Foundation; either version 2 of the License, or +    (at your option) any later version. + +    This program 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 General Public License for more details. + +    You should have received a copy of the GNU General Public License +    along with this program; if not, write to the Free Software +    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + +    Gnomovision version 69, Copyright (C) year name of author +    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. +    This is free software, and you are welcome to redistribute it +    under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License.  Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary.  Here is a sample; alter the names: + +  Yoyodyne, Inc., hereby disclaims all copyright interest in the program +  `Gnomovision' (which makes passes at compilers) written by James Hacker. + +  <signature of Ty Coon>, 1 April 1989 +  Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs.  If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library.  If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/libxsd-frontend/build/import/libxerces-c/configuration-dynamic.make b/libxsd-frontend/build/import/libxerces-c/configuration-dynamic.make new file mode 100644 index 0000000..91f61b2 --- /dev/null +++ b/libxsd-frontend/build/import/libxerces-c/configuration-dynamic.make @@ -0,0 +1 @@ +libxerces_c_installed := y diff --git a/libxsd-frontend/build/import/libxerces-c/configuration-rules.make b/libxsd-frontend/build/import/libxerces-c/configuration-rules.make new file mode 100644 index 0000000..fdb2263 --- /dev/null +++ b/libxsd-frontend/build/import/libxerces-c/configuration-rules.make @@ -0,0 +1,15 @@ +# file      : build/import/libxerces-c/configuration-rules.make +# author    : Boris Kolpackov <boris@kolpackov.net> +# copyright : Copyright (c) 2005-2009 Boris Kolpackov +# license   : GNU GPL v2; see accompanying LICENSE file + +$(dcf_root)/import/libxerces-c/configuration-dynamic.make: | $(dcf_root)/import/libxerces-c/. +	$(call message,,$(scf_root)/import/libxerces-c/configure $@) + +ifndef %foreign% + +disfigure:: +	$(call message,rm $(dcf_root)/import/libxerces-c/configuration-dynamic.make,\ +rm -f $(dcf_root)/import/libxerces-c/configuration-dynamic.make) + +endif diff --git a/libxsd-frontend/build/import/libxerces-c/configure b/libxsd-frontend/build/import/libxerces-c/configure new file mode 100755 index 0000000..26e56a7 --- /dev/null +++ b/libxsd-frontend/build/import/libxerces-c/configure @@ -0,0 +1,73 @@ +#! /usr/bin/env bash + +# file      : build/import/libxerces-c/configure +# author    : Boris Kolpackov <boris@kolpackov.net> +# copyright : Copyright (c) 2005-2009 Boris Kolpackov +# license   : GNU GPL v2; see accompanying LICENSE file + + +# $1           - out config file +# +# bld_root     - build root +# project_name - project name +# + +source $bld_root/dialog.bash + + +$echo +$echo "Configuring external dependency on 'libxerces-c' for '$project_name'." +$echo + +$echo +$echo "Would you like to configure dependency on the installed version" +$echo "of 'libxerces-c' as opposed to the development build?" +$echo + +installed=`read_y_n y` + +path= +type= + +if [ "$installed" = "n" ]; then + +  version= + +  while [ -z "$version" ]; do + +    $echo +    $echo "Please enter the 'libxerces-c' root directory." +    $echo + +    root=`read_path --directory --exist` + +    version=`sed -e 's/^VER=\([^_]*\)_\([^_]*\)_\([^_]*\)[ ]*$/\1.\2.\3/' \ +-e t -e d $root/version.incl 2>/dev/null` + +    if [ $? != 0 -o -z "$version" ]; then + +      version= +      echo "Unable to read version information from $root/version.incl" +    fi +  done + +  $echo +  $echo "Please select the library type you would like to use:" +  $echo +  $echo "(1) archive" +  $echo "(2) shared object" +  $echo + +  type=`read_option "archive shared" "shared"` + +fi + +echo libxerces_c_installed := $installed   >$1 + +if [ "$installed" = "n" ]; then + +  echo libxerces_c_root    := $root    >>$1 +  echo libxerces_c_type    := $type    >>$1 +  echo libxerces_c_version := $version >>$1 + +fi diff --git a/libxsd-frontend/build/import/libxerces-c/rules.make b/libxsd-frontend/build/import/libxerces-c/rules.make new file mode 100644 index 0000000..7cdca8c --- /dev/null +++ b/libxsd-frontend/build/import/libxerces-c/rules.make @@ -0,0 +1,52 @@ +# file      : build/import/libxerces-c/rules.make +# author    : Boris Kolpackov <boris@kolpackov.net> +# copyright : Copyright (c) 2005-2009 Boris Kolpackov +# license   : GNU GPL v2; see accompanying LICENSE file + +$(dcf_root)/import/libxerces-c/%: root := $(libxerces_c_root) + +ifneq ($(filter 3.%,$(libxerces_c_version)),) + +# 3.x.y +# +ifeq ($(libxerces_c_type),archive) + +$(dcf_root)/import/libxerces-c/xerces-c.l: $(libxerces_c_root)/src/.libs/libxerces-c.a +	@echo $< >$@ +else + +$(dcf_root)/import/libxerces-c/xerces-c.l: $(libxerces_c_root)/src/.libs/libxerces-c.so +	@echo $< >$@ +	@echo rpath:$(root)/src/.libs >>$@ +endif + +$(dcf_root)/import/libxerces-c/xerces-c.l.cpp-options: +	@echo include: -I$(root)/src >$@ +else + +#  2.x.y +# +ifeq ($(libxerces_c_type),archive) + +$(dcf_root)/import/libxerces-c/xerces-c.l: $(libxerces_c_root)/lib/libxerces-c.a +	@echo $< >$@ +else + +$(dcf_root)/import/libxerces-c/xerces-c.l: $(libxerces_c_root)/lib/libxerces-c.so +	@echo $< >$@ +	@echo rpath:$(root)/lib >>$@ +endif + +$(dcf_root)/import/libxerces-c/xerces-c.l.cpp-options: +	@echo include: -I$(root)/include >$@ +endif + + +ifndef %foreign% + +disfigure:: +	$(call message,rm $(dcf_root)/import/libxerces-c/xerces-c.l,\ +rm -f $(dcf_root)/import/libxerces-c/xerces-c.l) +	$(call message,,rm -f $(dcf_root)/import/libxerces-c/xerces-c.l.cpp-options) + +endif diff --git a/libxsd-frontend/build/import/libxerces-c/stub.make b/libxsd-frontend/build/import/libxerces-c/stub.make new file mode 100644 index 0000000..d4de5ec --- /dev/null +++ b/libxsd-frontend/build/import/libxerces-c/stub.make @@ -0,0 +1,32 @@ +# file      : build/import/libxerces-c/stub.make +# author    : Boris Kolpackov <boris@kolpackov.net> +# copyright : Copyright (c) 2005-2009 Boris Kolpackov +# license   : GNU GPL v2; see accompanying LICENSE file + +$(call include-once,$(scf_root)/import/libxerces-c/configuration-rules.make,$(dcf_root)) + +libxerces_c_installed := + +$(call -include,$(dcf_root)/import/libxerces-c/configuration-dynamic.make) + +ifdef libxerces_c_installed + +ifeq ($(libxerces_c_installed),y) + +$(call export,l: -lxerces-c,cpp-options: ) + +else + +$(call include-once,$(scf_root)/import/libxerces-c/rules.make,$(dcf_root)) + +$(call export,\ +  l: $(dcf_root)/import/libxerces-c/xerces-c.l,\ +  cpp-options: $(dcf_root)/import/libxerces-c/xerces-c.l.cpp-options) + +endif + +else + +.NOTPARALLEL: + +endif diff --git a/libxsd-frontend/build/import/libxerces-c/version b/libxsd-frontend/build/import/libxerces-c/version new file mode 100644 index 0000000..a918a2a --- /dev/null +++ b/libxsd-frontend/build/import/libxerces-c/version @@ -0,0 +1 @@ +0.6.0 diff --git a/libxsd-frontend/build/import/libxsd-frontend/LICENSE b/libxsd-frontend/build/import/libxsd-frontend/LICENSE new file mode 120000 index 0000000..5853aae --- /dev/null +++ b/libxsd-frontend/build/import/libxsd-frontend/LICENSE @@ -0,0 +1 @@ +../../../LICENSE
\ No newline at end of file diff --git a/libxsd-frontend/build/import/libxsd-frontend/configuration-rules.make b/libxsd-frontend/build/import/libxsd-frontend/configuration-rules.make new file mode 100644 index 0000000..29e8083 --- /dev/null +++ b/libxsd-frontend/build/import/libxsd-frontend/configuration-rules.make @@ -0,0 +1,15 @@ +# file      : build/import/libxsd-frontend/configuration-rules.make +# author    : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +# license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +$(dcf_root)/import/libxsd-frontend/configuration-dynamic.make: | $(dcf_root)/import/libxsd-frontend/. +	$(call message,,$(scf_root)/import/libxsd-frontend/configure $@) + +ifndef %foreign% + +disfigure:: +	$(call message,rm $(dcf_root)/import/libxsd-frontend/configuration-dynamic.make,\ +rm -f $(dcf_root)/import/libxsd-frontend/configuration-dynamic.make) + +endif diff --git a/libxsd-frontend/build/import/libxsd-frontend/configure b/libxsd-frontend/build/import/libxsd-frontend/configure new file mode 100755 index 0000000..cc6881c --- /dev/null +++ b/libxsd-frontend/build/import/libxsd-frontend/configure @@ -0,0 +1,55 @@ +#! /usr/bin/env bash + +# file      : build/import/libxsd-frontend/configure +# author    : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +# license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + + +# $1           - out file +# +# bld_root     - build root +# project_name - project name +# + +source $bld_root/dialog.bash + + +$echo +$echo "Configuring external dependency on 'libxsd-frontend' for '$project_name'." +$echo + +$echo +$echo "Would you like to configure dependency on the installed " +$echo "version of 'libxsd-frontend' as opposed to the development build?" +$echo + +installed=`read_y_n y` + +path= + +if [ "$installed" = "n" ]; then + +$echo +$echo "Please enter the src_root for 'libxsd-frontend'." +$echo + +src_root=`read_path --directory --exist` + +$echo +$echo "Please enter the out_root for 'libxsd-frontend'." +$echo + +out_root=`read_path --directory $src_root` + +fi + +echo libxsd_frontend_installed := $installed   >$1 + +if [ "$installed" = "n" ]; then + +echo src_root := $src_root            >>$1 +echo scf_root := \$\(src_root\)/build >>$1 +echo out_root := $out_root            >>$1 + +fi diff --git a/libxsd-frontend/build/import/libxsd-frontend/stub.make b/libxsd-frontend/build/import/libxsd-frontend/stub.make new file mode 100644 index 0000000..3721928 --- /dev/null +++ b/libxsd-frontend/build/import/libxsd-frontend/stub.make @@ -0,0 +1,30 @@ +# file      : build/import/libxsd-frontend/stub.make +# author    : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +# license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +$(call include-once,$(scf_root)/import/libxsd-frontend/configuration-rules.make,$(dcf_root)) + +libxsd_frontend_installed := + +$(call -include,$(dcf_root)/import/libxsd-frontend/configuration-dynamic.make) + +ifdef libxsd_frontend_installed + +ifeq ($(libxsd_frontend_installed),y) + +$(call export,l: -lxsd-frontend -lfrontend-elements -lcult -lboost_filesystem -lxerces-c,cpp_options: ) + +else + +# Include export stub. +# +$(call include,$(scf_root)/export/libxsd-frontend/stub.make) + +endif + +else + +.NOTPARALLEL: + +endif diff --git a/libxsd-frontend/build/ld/configuration-lib-dynamic.make b/libxsd-frontend/build/ld/configuration-lib-dynamic.make new file mode 100644 index 0000000..74c8885 --- /dev/null +++ b/libxsd-frontend/build/ld/configuration-lib-dynamic.make @@ -0,0 +1,13 @@ +ld_lib_type   := archive + +ifneq ($(AR),) +ld_lib_ar     := $(AR) +else +ld_lib_ar     := ar +endif + +ifneq ($(RANLIB),) +ld_lib_ranlib := $(RANLIB) +else +ld_lib_ranlib := ranlib +endif diff --git a/libxsd-frontend/makefile b/libxsd-frontend/makefile new file mode 100644 index 0000000..de97507 --- /dev/null +++ b/libxsd-frontend/makefile @@ -0,0 +1,17 @@ +# file      : makefile +# author    : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +# license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))build/bootstrap.make + +default := $(out_base)/ +test    := $(out_base)/.test +clean   := $(out_base)/.clean + +$(default): $(out_base)/xsd-frontend/ $(out_base)/tests/ +$(test): $(out_base)/tests/.test +$(clean): $(out_base)/xsd-frontend/.clean $(out_base)/tests/.clean + +$(call import,$(src_base)/xsd-frontend/makefile) +$(call import,$(src_base)/tests/makefile) diff --git a/libxsd-frontend/tests/dump/driver.cxx b/libxsd-frontend/tests/dump/driver.cxx new file mode 100644 index 0000000..5217ebf --- /dev/null +++ b/libxsd-frontend/tests/dump/driver.cxx @@ -0,0 +1,734 @@ +// file      : tests/dump/driver.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/types.hxx> + +#include <xsd-frontend/parser.hxx> +#include <xsd-frontend/transformations/anonymous.hxx> +#include <xsd-frontend/transformations/enum-synthesis.hxx> + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +#include <iostream> + +using namespace Cult::Types; +using namespace XSDFrontend; + +using std::wcerr; +using std::wcout; +using std::endl; + +UnsignedLong indent = 0; + +std::wostream& +ind (std::wostream& os) +{ +  for (UnsignedLong n (0); n < indent; ++n) +    os << L"  "; + +  return os; +} + +namespace +{ +  typedef Cult::Types::WideString String; + +  // Nameable which is named in the namespace scope. +  // +  String +  ref_name (SemanticGraph::Nameable& n) +  { +    String const& scope (n.scope ().name ()); + +    return scope + (scope.empty () ? L"" : L"#") + n.name (); +  } + +  struct List: Traversal::List +  { +    virtual Void +    traverse (Type& l) +    { +      if (l.annotated_p ()) +        wcout << ind << "<" << l.annotation ().documentation () << ">" +              << endl; + +      wcout << ind << "list " << +        (l.named_p () ? l.name () : String ("<anonymous>")); + +      SemanticGraph::Type& t (l.argumented ().type ()); + +      if (t.named_p ()) +        wcout << " " << ref_name (t) << endl; +      else +      { +        wcout << endl +              << ind << "{" << endl; +        indent++; + +        edge_traverser ().dispatch (l.argumented ()); + +        indent--; +        wcout << ind << "}" << endl; +      } +    } +  }; + +  struct Union: Traversal::Union +  { +    virtual Void +    traverse (Type& u) +    { +      if (u.annotated_p ()) +        wcout << ind << "<" << u.annotation ().documentation () << ">" +              << endl; + +      wcout << ind << "union " << +        (u.named_p () ? u.name () : String ("<anonymous>")) << " "; + +      for (Type::ArgumentedIterator i (u.argumented_begin ()); +           i != u.argumented_end (); ++i) +      { +        SemanticGraph::Type& t (i->type ()); + +        if (t.named_p ()) +          wcout << ref_name (t) << " "; +        else +        { +          wcout << endl +                << ind << "{" << endl; +          indent++; + +          edge_traverser ().dispatch (*i); + +          indent--; +          wcout << ind << "}" << endl; +        } +      } + +      wcout << endl; +    } +  }; + +  struct Enumerator: Traversal::Enumerator +  { +    virtual Void +    traverse (Type& e) +    { +      if (e.annotated_p ()) +        wcout << ind << "<" << e.annotation ().documentation () << ">" +              << endl; + +      wcout << ind << "enumerator " << e.name () << endl; +    } +  }; + +  struct Enumeration: Traversal::Enumeration +  { +    virtual Void +    traverse (Type& e) +    { +      if (e.annotated_p ()) +        wcout << ind << "<" << e.annotation ().documentation () << ">" +              << endl; + +      wcout << ind << "enumeration " << +        (e.named_p () ? e.name () : String ("<anonymous>")) << ": " << +        ref_name (e.inherits ().base ()) << endl +            << ind << "{" << endl; + +      indent++; +      Traversal::Enumeration::traverse (e); +      indent--; + +      wcout << ind << "}" << endl; +    } +  }; + +  struct ContainsParticle: Traversal::ContainsParticle +  { +    virtual Void +    traverse (Type& cp) +    { +      wcout << ind << "[" << cp.min () << ", "; + +      if (cp.max () == 0) +        wcout << "unbounded] "; +      else +        wcout << cp.max () << "] "; + +      Traversal::ContainsParticle::traverse (cp); +    } +  }; + +  struct ContainsCompositor: Traversal::ContainsCompositor +  { +    virtual Void +    traverse (Type& cc) +    { +      wcout << ind << "[" << cc.min () << ", "; + +      if (cc.max () == 0) +        wcout << "unbounded] "; +      else +        wcout << cc.max () << "] "; + +      Traversal::ContainsCompositor::traverse (cc); +    } +  }; + +  struct Compositor: Traversal::All, +                     Traversal::Choice, +                     Traversal::Sequence +  { +    virtual Void +    traverse (SemanticGraph::All& a) +    { +      wcout << "all" << endl +            << ind << "{" << endl; + +      indent++; + +      Traversal::All::traverse (a); + +      indent--; + +      wcout << ind << "}" << endl; +    } + +    virtual Void +    traverse (SemanticGraph::Choice& c) +    { +      wcout << "choice" << endl +            << ind << "{" << endl; + +      indent++; + +      Traversal::Choice::traverse (c); + +      indent--; + +      wcout << ind << "}" << endl; +    } + +    virtual Void +    traverse (SemanticGraph::Sequence& s) +    { +      wcout << "sequence" << endl +            << ind << "{" << endl; + +      indent++; + +      Traversal::Sequence::traverse (s); + +      indent--; + +      wcout << ind << "}" << endl; +    } +  }; + +  struct Attribute: Traversal::Attribute +  { +    virtual Void +    traverse (Type& a) +    { +      if (a.annotated_p ()) +        wcout << ind << "<" << a.annotation ().documentation () << ">" +              << endl; + +      wcout << ind << (a.optional_p () ? "optional" : "required") +            << " attribute " << a.name (); + +      if (a.fixed_p ()) +        wcout << "==" << a.value (); +      else if (a.default_p ()) +        wcout << "=" << a.value (); + +      SemanticGraph::Type& t (a.type ()); + +      if (t.named_p ()) +        wcout << " " << ref_name (t) << endl; +      else +      { +        wcout << endl +              << ind << "{" << endl; +        indent++; + +        belongs (a); + +        indent--; +        wcout << ind << "}" << endl; +      } +    } +  }; + +  struct AnyAttribute: Traversal::AnyAttribute +  { +    virtual Void +    traverse (Type& a) +    { +      if (a.annotated_p ()) +        wcout << ind << "<" << a.annotation ().documentation () << ">" +              << endl; + +      wcout << ind << "any-attribute '" << a.name () << "'" << endl; +    } +  }; + +  struct Element: Traversal::Element +  { +    virtual Void +    traverse (Type& e) +    { +      wcout << "element " << e.name (); + +      if (e.fixed_p ()) +        wcout << "==" << e.value (); +      else if (e.default_p ()) +        wcout << "=" << e.value (); + +      SemanticGraph::Type& t (e.type ()); + +      if (t.named_p ()) +        wcout << " " << ref_name (t) << endl; +      else +      { +        wcout << endl +              << ind << "{" << endl; +        indent++; + +        belongs (e); + +        indent--; +        wcout << ind << "}" << endl; +      } +    } +  }; + +  struct ElementFlat: Traversal::Element +  { +    virtual Void +    traverse (Type& e) +    { +      if (e.annotated_p ()) +        wcout << ind << "<" << e.annotation ().documentation () << ">" +              << endl; + +      wcout << ind << "element " << e.name (); + +      if (e.fixed_p ()) +        wcout << "==" << e.value (); +      else if (e.default_p ()) +        wcout << "=" << e.value (); + +      wcout << endl; +    } +  }; + +  struct Any: Traversal::Any +  { +    virtual Void +    traverse (Type& a) +    { +      wcout << "any '" << a.name () << "'" << endl; +    } +  }; + +  struct AnyFlat: Traversal::Any +  { +    virtual Void +    traverse (Type& a) +    { +      if (a.annotated_p ()) +        wcout << ind << "<" << a.annotation ().documentation () << ">" +              << endl; + +      wcout << ind << "any '" << a.name () << "'" << endl; +    } +  }; + +  struct Complex: Traversal::Complex +  { +    virtual Void +    traverse (Type& c) +    { +      // Anonymous type definition can recursively refer to itself. +      // +      if (c.context ().count ("seen")) +      { +        wcout << ind << "complex <recursive-anonymous>" << endl; +        return; +      } + +      c.context ().set ("seen", true); + +      if (c.annotated_p ()) +        wcout << ind << "<" << c.annotation ().documentation () << ">" +              << endl; + +      wcout << ind << "complex " << +        (c.named_p () ? c.name () : String ("<anonymous>")); + +      if (c.inherits_p ()) +        wcout << ": " << ref_name (c.inherits ().base ()); + +      wcout << endl +            << ind << "{" << endl; +      indent++; + +      Traversal::Complex::traverse (c); + +      indent--; +      wcout << ind << "}" << endl; + +      c.context ().remove ("seen"); +    } +  }; + +  struct GlobalAttribute: Traversal::Attribute +  { +    virtual Void +    traverse (Type& a) +    { +      if (a.annotated_p ()) +        wcout << ind << "<" << a.annotation ().documentation () << ">" +              << endl; + +      wcout << ind << "attribute " << a.name (); + +      if (a.fixed_p ()) +        wcout << "==" << a.value (); +      else if (a.default_p ()) +        wcout << "=" << a.value (); + +      SemanticGraph::Type& t (a.type ()); + +      if (t.named_p ()) +        wcout << " " << ref_name (t) << endl; +      else +      { +        wcout << endl +              << ind << "{" << endl; +        indent++; + +        belongs (a); + +        indent--; +        wcout << ind << "}" << endl; +      } +    } +  }; + +  struct GlobalElement: Traversal::Element +  { +    virtual Void +    traverse (Type& e) +    { +      if (e.annotated_p ()) +        wcout << ind << "<" << e.annotation ().documentation () << ">" +              << endl; + +      wcout << ind << "element " << e.name (); + +      if (e.fixed_p ()) +        wcout << "==" << e.value (); +      else if (e.default_p ()) +        wcout << "=" << e.value (); + +      SemanticGraph::Type& t (e.type ()); + +      if (t.named_p ()) +        wcout << " " << ref_name (t) << endl; +      else +      { +        wcout << endl +              << ind << "{" << endl; +        indent++; + +        belongs (e); + +        indent--; +        wcout << ind << "}" << endl; +      } +    } +  }; + +  struct Namespace: Traversal::Namespace +  { +    virtual Void +    traverse (Type& n) +    { +      wcout << ind << "namespace " << n.name () << endl +            << ind << "{" << endl; +      indent++; +      Traversal::Namespace::traverse (n); +      indent--; +      wcout << ind << "}" << endl; +    } +  }; + +  // Go into implied/included/imported schemas while making sure +  // we don't recurse forever. +  // +  struct Uses: Traversal::Imports, +               Traversal::Includes, +               Traversal::Sources +               //Traversal::Implies @@ Need a --with-implies option +  { +    virtual Void +    traverse (SemanticGraph::Imports& i) +    { +      if (traverse_uses (i, "imports")) +        Traversal::Imports::traverse (i); +    } + +    virtual Void +    traverse (SemanticGraph::Includes& i) +    { +      if (traverse_uses (i, "includes")) +        Traversal::Includes::traverse (i); +    } + +    virtual Void +    traverse (SemanticGraph::Sources& s) +    { +      if (traverse_uses (s, "sources")) +        Traversal::Sources::traverse (s); +    } + +    /* +    virtual Void +    traverse (SemanticGraph::Implies& i) +    { +      if (traverse_uses (i, "implies")) +        Traversal::Implies::traverse (i); +    } +    */ + +    Boolean +    traverse_uses (SemanticGraph::Uses& u, String const& type) +    { +      SemanticGraph::Schema& s (u.schema ()); + +      if (s.context ().count ("seen")) +      { +        wcout << ind << "recursively " << type << " " << u.path () << endl; +        return false; +      } + +      s.context ().set ("seen", true); + +      if (s.annotated_p ()) +        wcout << ind << "<" << s.annotation ().documentation () << ">" << endl; + +      wcout << ind << type << " " << u.path () << endl; + +      return true; +    } +  }; + +  struct Schema: Traversal::Schema +  { +    virtual Void +    traverse (Type& s) +    { +      wcout << ind << "{" << endl; +      indent++; +      Traversal::Schema::traverse (s); +      indent--; +      wcout << ind << "}" << endl; +    } +  }; +} + +struct AnonymousNameTranslator: Transformations::AnonymousNameTranslator +{ +  virtual WideString +  translate (WideString const& /*file*/, +             WideString const& ns, +             WideString const& name, +             WideString const& xpath) +  { +    wcout << "anonymous: " << ns << " " << name << " " << xpath << endl; +    return name; +  } +}; + + +Int +main (Int argc, Char* argv[]) +{ +  try +  { +    if (argc < 2) +    { +      wcerr << argv[0] << ": error: no input file." << endl; +      return 1; +    } + +    // Parse options. +    // +    Int i (1); +    Boolean anon (false); +    Boolean enum_synth (false); + +    for (; i < argc; ++i) +    { +      if (argv[i] == NarrowString ("--anonymous")) +        anon = true; +      else if (argv[i] == NarrowString ("--enum-synthesis")) +        enum_synth = true; +      else +        break; +    } + +    // Parse schema. +    // +    SemanticGraph::Path path (argv[i], boost::filesystem::native); + +    Parser parser (true, false, true); +    Evptr<SemanticGraph::Schema> tu (parser.parse (path)); + +    // +    // +    if (anon) +    { +      try +      { +        AnonymousNameTranslator transl; +        Transformations::Anonymous transf (transl); +        transf.transform (*tu, path, true); +      } +      catch (Transformations::Anonymous::Failed const&) +      { +        // Diagnostics has already been issued. +        // +        return 1; +      } +    } + +    // +    // +    if (enum_synth) +    { +      Transformations::EnumSynthesis transf; +      transf.transform (*tu, path); +    } + +    // +    // +    Schema schema; +    Uses uses; + +    schema >> uses >> schema; + +    Traversal::Names schema_names; +    Namespace ns; +    Traversal::Names ns_names; + +    schema >> schema_names >> ns >> ns_names; + +    // +    // +    List list; +    Union union_; +    Complex complex; +    Enumeration enumeration; +    GlobalElement global_element; +    GlobalAttribute global_attribute; + +    Traversal::Names complex_names; +    Traversal::Names enumeration_names; +    ContainsCompositor contains_compositor; + +    ns_names >> list; +    ns_names >> union_; +    ns_names >> complex; +    ns_names >> enumeration; +    ns_names >> global_attribute; +    ns_names >> global_element; + +    complex >> complex_names; +    complex >> contains_compositor; + +    enumeration >> enumeration_names; + +    // +    // +    Compositor compositor; +    ContainsParticle contains_particle; + +    contains_compositor >> compositor; +    compositor >> contains_particle >> compositor; + +    // +    // +    Any any; +    AnyFlat any_flat; +    Element element; +    ElementFlat element_flat; +    Attribute attribute; +    AnyAttribute any_attribute; +    Traversal::Belongs belongs; + +    element >> belongs; +    attribute >> belongs; + +    global_element >> belongs; +    global_attribute >> belongs; + +    complex_names >> attribute; +    complex_names >> any_attribute; +    complex_names >> any_flat; +    complex_names >> element_flat; + +    contains_particle >> any; +    contains_particle >> element; + +    belongs >> list; +    belongs >> union_; +    belongs >> complex; +    belongs >> enumeration; + +    // +    // +    Traversal::Argumented argumented; +    list >> argumented; +    union_ >> argumented; + +    argumented >> list; +    argumented >> union_; +    argumented >> complex; +    argumented >> enumeration; + +    // +    // +    Enumerator enumerator; +    enumeration_names >> enumerator; + +    // +    // +    if (tu->annotated_p ()) +      wcout << ind << "<" << tu->annotation ().documentation () << ">" +            << endl; + +    wcout << ind << "primary" << endl; +    tu->context ().set ("seen", true); +    schema.dispatch (*tu); + +    return 0; +  } +  catch (InvalidSchema const&) +  { +    // Diagnostic has already been issued. +  } +  catch (SemanticGraph::InvalidPath const&) +  { +    wcerr << argv[0] << ": error: '" << argv[1] << "' is not a valid " +      << "filesystem path" << endl; +  } + +  return 1; +} diff --git a/libxsd-frontend/tests/dump/makefile b/libxsd-frontend/tests/dump/makefile new file mode 100644 index 0000000..c51e72e --- /dev/null +++ b/libxsd-frontend/tests/dump/makefile @@ -0,0 +1,56 @@ +# file      : tests/dump/makefile +# author    : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +# license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../build/bootstrap.make + +cxx_tun := driver.cxx +cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o)) +cxx_od  := $(cxx_obj:.o=.o.d) + +xsd-fe.l             := $(out_root)/xsd-frontend/xsd-frontend.l +xsd-fe.l.cpp-options := $(out_root)/xsd-frontend/xsd-frontend.l.cpp-options + +driver  := $(out_base)/driver +clean   := $(out_base)/.clean + +# Build. +# +$(driver): $(cxx_obj) $(xsd-fe.l) + +$(cxx_obj) $(cxx_od): $(xsd-fe.l.cpp-options) + +$(call include-dep,$(cxx_od)) + +# Convenience alias for default target. +# +$(out_base)/: $(driver) + +# Clean. +# +$(clean): $(driver).o.clean          \ +  $(addsuffix .cxx.clean,$(cxx_obj)) \ +  $(addsuffix .cxx.clean,$(cxx_od)) + +# Generated .gitignore. +# +ifeq ($(out_base),$(src_base)) +$(driver): | $(out_base)/.gitignore + +$(out_base)/.gitignore: files := driver +$(clean): $(out_base)/.gitignore.clean + +$(call include,$(bld_root)/git/gitignore.make) +endif + +# How to. +# +$(call include,$(bld_root)/cxx/o-e.make) +$(call include,$(bld_root)/cxx/cxx-o.make) +$(call include,$(bld_root)/cxx/cxx-d.make) + + +# Dependencies. +# +$(call import,$(src_root)/xsd-frontend/makefile) diff --git a/libxsd-frontend/tests/makefile b/libxsd-frontend/tests/makefile new file mode 100644 index 0000000..6b794d6 --- /dev/null +++ b/libxsd-frontend/tests/makefile @@ -0,0 +1,17 @@ +# file      : tests/makefile +# author    : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +# license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../build/bootstrap.make + +default   := $(out_base)/ +test      := $(out_base)/.test +clean     := $(out_base)/.clean + +$(default): $(out_base)/dump/ $(out_base)/schema/ +$(test): $(out_base)/schema/.test +$(clean): $(out_base)/dump/.clean $(out_base)/schema/.clean + +$(call import,$(src_base)/dump/makefile) +$(call import,$(src_base)/schema/makefile) diff --git a/libxsd-frontend/tests/schema/annotation/makefile b/libxsd-frontend/tests/schema/annotation/makefile new file mode 100644 index 0000000..97f578b --- /dev/null +++ b/libxsd-frontend/tests/schema/annotation/makefile @@ -0,0 +1,35 @@ +# file      : tests/schema/annotation/makefile +# author    : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +# license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../../build/bootstrap.make + +tests := 000 001 + +driver := $(out_root)/tests/dump/driver +test   := $(out_base)/.test +clean  := $(out_base)/.clean + +# Convenience alias for default target. +# +$(out_base)/: $(driver) + +# Test. +# +test_targets := $(addprefix $(out_base)/.test-,$(tests)) + +$(test): $(test_targets) +$(test_targets): driver := $(driver) + +.PHONY: $(out_base)/.test-% +$(out_base)/.test-%: $(driver) $(src_base)/test-%.xsd $(src_base)/test-%.std +	$(call message,test $(out_base)/$*,$(driver) $(src_base)/test-$*.xsd | diff -u $(src_base)/test-$*.std -) + +# Clean. +# +$(clean): + +# Dependencies. +# +$(call import,$(src_root)/tests/dump/makefile) diff --git a/libxsd-frontend/tests/schema/annotation/test-000.std b/libxsd-frontend/tests/schema/annotation/test-000.std new file mode 100644 index 0000000..15f3e89 --- /dev/null +++ b/libxsd-frontend/tests/schema/annotation/test-000.std @@ -0,0 +1,67 @@ +<schema documentation> +primary +{ +  namespace test +  { +    <list type documentation> +    list list http://www.w3.org/2001/XMLSchema#string +    <union type documentation> +    union union http://www.w3.org/2001/XMLSchema#int http://www.w3.org/2001/XMLSchema#string  +    <enumeration type documentation> +    enumeration enum: http://www.w3.org/2001/XMLSchema#string +    { +      <enumerator documentation (male)> +      enumerator male +      <enumerator documentation (female)> +      enumerator female +    } +    <complex type documentation> +    complex type +    { +      <local element efoo documentation> +      element efoo +      <local element ebar documentation> +      element ebar +      <local element ebaz documentation> +      element ebaz +      <any documentation> +      any 'any #0' +      <local attribute afoo documentation> +      optional attribute afoo http://www.w3.org/2001/XMLSchema#string +      <local attribute abar documentation> +      optional attribute abar +      { +        <list type documentation> +        list <anonymous> http://www.w3.org/2001/XMLSchema#string +      } +      <local attribute abaz documentation> +      optional attribute abaz http://www.w3.org/2001/XMLSchema#string +      <anyAttribute documentation> +      any-attribute 'any-attribute #0' +      [1, 1] sequence +      { +        [1, 1] element efoo http://www.w3.org/2001/XMLSchema#string +        [1, 1] element ebar +        { +          complex <anonymous> +          { +            <nested local element efoo documentation> +            element efoo +            <nested local attribute afoo documentation> +            optional attribute afoo http://www.w3.org/2001/XMLSchema#string +            [1, 1] sequence +            { +              [1, 1] element efoo http://www.w3.org/2001/XMLSchema#string +            } +          } +        } +        [1, 1] element ebaz http://www.w3.org/2001/XMLSchema#string +        [1, 1] any 'any #0' +      } +    } +    <global element documentation> +    element ebaz http://www.w3.org/2001/XMLSchema#string +    <global attribute documentation> +    attribute abaz http://www.w3.org/2001/XMLSchema#string +  } +} diff --git a/libxsd-frontend/tests/schema/annotation/test-000.xsd b/libxsd-frontend/tests/schema/annotation/test-000.xsd new file mode 100644 index 0000000..f768b45 --- /dev/null +++ b/libxsd-frontend/tests/schema/annotation/test-000.xsd @@ -0,0 +1,120 @@ +<?xml version="1.0"?> +<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test"> + +  <annotation> +    <documentation>schema documentation</documentation> +  </annotation> + +  <simpleType name="list"> +    <annotation> +      <documentation>list type documentation</documentation> +    </annotation> +    <list itemType="string"/> +  </simpleType> + +  <simpleType name="union"> +    <annotation> +      <documentation>union type documentation</documentation> +    </annotation> +    <union memberTypes="int string"/> +  </simpleType> + +  <simpleType name="enum"> +    <annotation> +      <documentation>enumeration type documentation</documentation> +    </annotation> +    <restriction base="string"> +      <enumeration value="male"> +        <annotation> +          <documentation>enumerator documentation (male)</documentation> +        </annotation> +      </enumeration> +      <enumeration value="female"> +        <annotation> +          <documentation>enumerator documentation (female)</documentation> +        </annotation> +      </enumeration> +    </restriction> +  </simpleType> + +  <complexType name="type"> +    <annotation> +      <documentation>complex type documentation</documentation> +    </annotation> +    <sequence> +      <element name="efoo" type="string"> +        <annotation> +          <documentation>local element efoo documentation</documentation> +        </annotation> +      </element> +      <element name="ebar"> +        <annotation> +          <documentation>local element ebar documentation</documentation> +        </annotation> +        <complexType> +          <sequence> +            <element name="efoo" type="string"> +              <annotation> +                <documentation>nested local element efoo documentation</documentation> +              </annotation> +            </element> +          </sequence> +          <attribute name="afoo" type="string"> +            <annotation> +              <documentation>nested local attribute afoo documentation</documentation> +            </annotation> +          </attribute> +        </complexType> +      </element> +      <element ref="t:ebaz"> +        <annotation> +          <documentation>local element ebaz documentation</documentation> +        </annotation> +      </element> +      <any namespace="##other"> +        <annotation> +          <documentation>any documentation</documentation> +        </annotation> +      </any> +    </sequence> +    <attribute name="afoo" type="string"> +      <annotation> +        <documentation>local attribute afoo documentation</documentation> +      </annotation> +    </attribute> +    <attribute name="abar"> +      <annotation> +        <documentation>local attribute abar documentation</documentation> +      </annotation> +      <simpleType> +        <annotation> +          <documentation>list type documentation</documentation> +        </annotation> +        <list itemType="string"/> +      </simpleType> +    </attribute> +    <attribute ref="t:abaz"> +      <annotation> +        <documentation>local attribute abaz documentation</documentation> +      </annotation> +    </attribute> +    <anyAttribute namespace="##other"> +      <annotation> +        <documentation>anyAttribute documentation</documentation> +      </annotation> +    </anyAttribute> +  </complexType> + +  <element name="ebaz" type="string"> +    <annotation> +      <documentation>global element documentation</documentation> +    </annotation> +  </element> + +  <attribute name="abaz" type="string"> +    <annotation> +      <documentation>global attribute documentation</documentation> +    </annotation> +  </attribute> + +</schema> diff --git a/libxsd-frontend/tests/schema/annotation/test-001.std b/libxsd-frontend/tests/schema/annotation/test-001.std new file mode 100644 index 0000000..9e2c99a --- /dev/null +++ b/libxsd-frontend/tests/schema/annotation/test-001.std @@ -0,0 +1,36 @@ +primary +{ +  namespace test +  { +    complex type +    { +      <global element ebar documentation> +      element ebar +      <group element efoo documentation> +      element efoo +      <global element ebar documentation> +      element ebar +      <global attribute abar documentation> +      optional attribute abar http://www.w3.org/2001/XMLSchema#string +      <group attribute afoo documentation> +      optional attribute afoo http://www.w3.org/2001/XMLSchema#string +      <global attribute abaz documentation> +      optional attribute abaz http://www.w3.org/2001/XMLSchema#string +      [1, 1] sequence +      { +        [1, 1] element ebar http://www.w3.org/2001/XMLSchema#string +        [1, 1] choice +        { +          [1, 1] element efoo http://www.w3.org/2001/XMLSchema#string +          [1, 1] element ebar http://www.w3.org/2001/XMLSchema#string +        } +      } +    } +    <global element ebar documentation> +    element ebar http://www.w3.org/2001/XMLSchema#string +    <global attribute abar documentation> +    attribute abar http://www.w3.org/2001/XMLSchema#string +    <global attribute abaz documentation> +    attribute abaz http://www.w3.org/2001/XMLSchema#string +  } +} diff --git a/libxsd-frontend/tests/schema/annotation/test-001.xsd b/libxsd-frontend/tests/schema/annotation/test-001.xsd new file mode 100644 index 0000000..286f63a --- /dev/null +++ b/libxsd-frontend/tests/schema/annotation/test-001.xsd @@ -0,0 +1,53 @@ +<?xml version="1.0"?> +<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test"> + +  <!-- Test various ref constructs. --> + +  <complexType name="type"> +    <sequence> +      <element ref="t:ebar"/> +      <group ref="t:eg"/> +    </sequence> +    <attribute ref="t:abar"/> +    <attributeGroup ref="t:ag"/> +  </complexType> + +  <group name="eg"> +    <choice> +      <element name="efoo" type="string"> +        <annotation> +          <documentation>group element efoo documentation</documentation> +        </annotation> +      </element> +      <element ref="t:ebar"/> +    </choice> +  </group> + +  <element name="ebar" type="string"> +    <annotation> +      <documentation>global element ebar documentation</documentation> +    </annotation> +  </element> + +  <attributeGroup name="ag"> +    <attribute name="afoo" type="string"> +      <annotation> +        <documentation>group attribute afoo documentation</documentation> +      </annotation> +    </attribute> +    <attribute ref="t:abaz"/> +  </attributeGroup> + +  <attribute name="abar" type="string"> +    <annotation> +      <documentation>global attribute abar documentation</documentation> +    </annotation> +  </attribute> + +  <attribute name="abaz" type="string"> +    <annotation> +      <documentation>global attribute abaz documentation</documentation> +    </annotation> +  </attribute> + +</schema> diff --git a/libxsd-frontend/tests/schema/anonymous/makefile b/libxsd-frontend/tests/schema/anonymous/makefile new file mode 100644 index 0000000..950e34b --- /dev/null +++ b/libxsd-frontend/tests/schema/anonymous/makefile @@ -0,0 +1,35 @@ +# file      : tests/schema/annotation/makefile +# author    : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +# license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../../build/bootstrap.make + +tests := 000 001 + +driver := $(out_root)/tests/dump/driver +test   := $(out_base)/.test +clean  := $(out_base)/.clean + +# Convenience alias for default target. +# +$(out_base)/: $(driver) + +# Test. +# +test_targets := $(addprefix $(out_base)/.test-,$(tests)) + +$(test): $(test_targets) +$(test_targets): driver := $(driver) + +.PHONY: $(out_base)/.test-% +$(out_base)/.test-%: $(driver) $(src_base)/test-%.xsd $(src_base)/test-%.std +	$(call message,test $(out_base)/$*,$(driver) --anonymous $(src_base)/test-$*.xsd | diff -u $(src_base)/test-$*.std -) + +# Clean. +# +$(clean): + +# Dependencies. +# +$(call import,$(src_root)/tests/dump/makefile) diff --git a/libxsd-frontend/tests/schema/anonymous/test-000.std b/libxsd-frontend/tests/schema/anonymous/test-000.std new file mode 100644 index 0000000..1f33cb0 --- /dev/null +++ b/libxsd-frontend/tests/schema/anonymous/test-000.std @@ -0,0 +1,30 @@ +anonymous: test anon_item anon +anonymous: test anon_nested_item anon_nested +anonymous: test anon_nested_item_base anon_nested_item +primary +{ +  namespace test +  { +    list named http://www.w3.org/2001/XMLSchema#string +    enumeration anon_item: http://www.w3.org/2001/XMLSchema#string +    { +      enumerator male +      enumerator female +    } +    list anon test#anon_item1 +    list anon_nested test#anon_nested_item +    enumeration anon_item1: http://www.w3.org/2001/XMLSchema#string +    { +      enumerator male +      enumerator female +    } +    enumeration anon_nested_item: test#anon_nested_item_base +    { +      enumerator male +      enumerator female +    } +    complex anon_nested_item_base: http://www.w3.org/2001/XMLSchema#string +    { +    } +  } +} diff --git a/libxsd-frontend/tests/schema/anonymous/test-000.xsd b/libxsd-frontend/tests/schema/anonymous/test-000.xsd new file mode 100644 index 0000000..ece8f4a --- /dev/null +++ b/libxsd-frontend/tests/schema/anonymous/test-000.xsd @@ -0,0 +1,42 @@ +<?xml version="1.0"?> +<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test"> + +  <simpleType name="named"> +    <list itemType="string"/> +  </simpleType> + +  <simpleType name="anon_item"> +    <restriction base="string"> +      <enumeration value="male"/> +      <enumeration value="female"/> +    </restriction> +  </simpleType> + +  <simpleType name="anon"> +    <list> +      <simpleType> +        <restriction base="string"> +          <enumeration value="male"/> +	  <enumeration value="female"/> +        </restriction> +      </simpleType> +    </list> +  </simpleType> + +  <simpleType name="anon_nested"> +    <list> +      <simpleType> +        <restriction> +          <simpleType> +            <restriction base="string"> +              <maxLength value="20"/> +            </restriction> +          </simpleType> +          <enumeration value="male"/> +	  <enumeration value="female"/> +        </restriction> +      </simpleType> +    </list> +  </simpleType> + +</schema> diff --git a/libxsd-frontend/tests/schema/anonymous/test-001.std b/libxsd-frontend/tests/schema/anonymous/test-001.std new file mode 100644 index 0000000..cc3f2d1 --- /dev/null +++ b/libxsd-frontend/tests/schema/anonymous/test-001.std @@ -0,0 +1,38 @@ +anonymous: test anon_base anon +anonymous: test anon_nested_base anon_nested +anonymous: test anon_nested_base_base anon_nested_base +primary +{ +  namespace test +  { +    enumeration named: http://www.w3.org/2001/XMLSchema#string +    { +      enumerator male +      enumerator female +    } +    enumeration anon_base: http://www.w3.org/2001/XMLSchema#string +    { +      enumerator male +      enumerator female +    } +    enumeration anon: test#anon_base1 +    { +      enumerator male +      enumerator female +    } +    enumeration anon_nested: test#anon_nested_base +    { +      enumerator male +      enumerator female +    } +    complex anon_base1: http://www.w3.org/2001/XMLSchema#string +    { +    } +    complex anon_nested_base: test#anon_nested_base_base +    { +    } +    complex anon_nested_base_base: http://www.w3.org/2001/XMLSchema#string +    { +    } +  } +} diff --git a/libxsd-frontend/tests/schema/anonymous/test-001.xsd b/libxsd-frontend/tests/schema/anonymous/test-001.xsd new file mode 100644 index 0000000..4a8414f --- /dev/null +++ b/libxsd-frontend/tests/schema/anonymous/test-001.xsd @@ -0,0 +1,47 @@ +<?xml version="1.0"?> +<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test"> + +  <simpleType name="named"> +    <restriction base="string"> +      <enumeration value="male"/> +      <enumeration value="female"/> +    </restriction> +  </simpleType> + +  <simpleType name="anon_base"> +    <restriction base="string"> +      <enumeration value="male"/> +      <enumeration value="female"/> +    </restriction> +  </simpleType> + +  <simpleType name="anon"> +    <restriction> +      <simpleType> +        <restriction base="string"> +          <maxLength value="20"/> +        </restriction> +      </simpleType> +      <enumeration value="male"/> +      <enumeration value="female"/> +    </restriction> +  </simpleType> + +  <simpleType name="anon_nested"> +    <restriction> +      <simpleType> +        <restriction> +          <simpleType> +            <restriction base="string"> +              <maxLength value="40"/> +            </restriction> +          </simpleType> +          <maxLength value="20"/> +        </restriction> +      </simpleType> +      <enumeration value="male"/> +      <enumeration value="female"/> +    </restriction> +  </simpleType> + +</schema> diff --git a/libxsd-frontend/tests/schema/attribute-group/makefile b/libxsd-frontend/tests/schema/attribute-group/makefile new file mode 100644 index 0000000..e96c0c7 --- /dev/null +++ b/libxsd-frontend/tests/schema/attribute-group/makefile @@ -0,0 +1,35 @@ +# file      : tests/schema/attribute-group/makefile +# author    : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +# license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../../build/bootstrap.make + +tests := 000 001 + +driver := $(out_root)/tests/dump/driver +test   := $(out_base)/.test +clean  := $(out_base)/.clean + +# Convenience alias for default target. +# +$(out_base)/: $(driver) + +# Test. +# +test_targets := $(addprefix $(out_base)/.test-,$(tests)) + +$(test): $(test_targets) +$(test_targets): driver := $(driver) + +.PHONY: $(out_base)/.test-% +$(out_base)/.test-%: $(driver) $(src_base)/test-%.xsd $(src_base)/test-%.std +	$(call message,test $(out_base)/$*,$(driver) $(src_base)/test-$*.xsd | diff -u $(src_base)/test-$*.std -) + +# Clean. +# +$(clean): + +# Dependencies. +# +$(call import,$(src_root)/tests/dump/makefile) diff --git a/libxsd-frontend/tests/schema/attribute-group/test-000.std b/libxsd-frontend/tests/schema/attribute-group/test-000.std new file mode 100644 index 0000000..61ad802 --- /dev/null +++ b/libxsd-frontend/tests/schema/attribute-group/test-000.std @@ -0,0 +1,17 @@ +primary +{ +  namespace test +  { +    complex type +    { +      optional attribute foo2 http://www.w3.org/2001/XMLSchema#string +      required attribute bar2 http://www.w3.org/2001/XMLSchema#string +      optional attribute foo3 http://www.w3.org/2001/XMLSchema#string +      required attribute bar3 http://www.w3.org/2001/XMLSchema#string +    } +    attribute foo2 http://www.w3.org/2001/XMLSchema#string +    attribute bar2 http://www.w3.org/2001/XMLSchema#string +    attribute foo3 http://www.w3.org/2001/XMLSchema#string +    attribute bar3 http://www.w3.org/2001/XMLSchema#string +  } +} diff --git a/libxsd-frontend/tests/schema/attribute-group/test-000.xsd b/libxsd-frontend/tests/schema/attribute-group/test-000.xsd new file mode 100644 index 0000000..9087a2b --- /dev/null +++ b/libxsd-frontend/tests/schema/attribute-group/test-000.xsd @@ -0,0 +1,31 @@ +<?xml version="1.0"?> +<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test"> + +  <!-- Multiple levels of forward reference. --> + +  <complexType name="type"> +    <attributeGroup ref="t:g1"/> +  </complexType> + +  <attributeGroup name="g1"> +    <attributeGroup ref="t:g2"/> +    <attributeGroup ref="t:g3"/> +  </attributeGroup> + +  <attributeGroup name="g2"> +    <attribute ref="t:foo2"/> +    <attribute ref="t:bar2" use="required"/> +  </attributeGroup> + +  <attributeGroup name="g3"> +    <attribute ref="t:foo3"/> +    <attribute ref="t:bar3" use="required"/> +  </attributeGroup> + +  <attribute name="foo2" type="string"/> +  <attribute name="bar2" type="string"/> + +  <attribute name="foo3" type="string"/> +  <attribute name="bar3" type="string"/> + +</schema> diff --git a/libxsd-frontend/tests/schema/attribute-group/test-001.std b/libxsd-frontend/tests/schema/attribute-group/test-001.std new file mode 100644 index 0000000..54a1e96 --- /dev/null +++ b/libxsd-frontend/tests/schema/attribute-group/test-001.std @@ -0,0 +1,12 @@ +primary +{ +  namespace test +  { +    complex type +    { +      any-attribute 'any-attribute #1' +      optional attribute foo http://www.w3.org/2001/XMLSchema#string +      any-attribute 'any-attribute #0' +    } +  } +} diff --git a/libxsd-frontend/tests/schema/attribute-group/test-001.xsd b/libxsd-frontend/tests/schema/attribute-group/test-001.xsd new file mode 100644 index 0000000..dc44a70 --- /dev/null +++ b/libxsd-frontend/tests/schema/attribute-group/test-001.xsd @@ -0,0 +1,20 @@ +<?xml version="1.0"?> +<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test"> + +  <!-- AnyAttribute in attribute groups. --> + +  <complexType name="type"> +    <attributeGroup ref="t:g1"/> +    <attributeGroup ref="t:g2"/> +  </complexType> + +  <attributeGroup name="g1"> +    <anyAttribute namespace="http://www.foo.com"/> +  </attributeGroup> + +  <attributeGroup name="g2"> +    <attribute name="foo" type="string"/> +    <anyAttribute namespace="http://www.bar.com"/> +  </attributeGroup> + +</schema> diff --git a/libxsd-frontend/tests/schema/default/makefile b/libxsd-frontend/tests/schema/default/makefile new file mode 100644 index 0000000..dbb5fa9 --- /dev/null +++ b/libxsd-frontend/tests/schema/default/makefile @@ -0,0 +1,35 @@ +# file      : tests/schema/default/makefile +# author    : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +# license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../../build/bootstrap.make + +tests := 000 001 + +driver := $(out_root)/tests/dump/driver +test   := $(out_base)/.test +clean  := $(out_base)/.clean + +# Convenience alias for default target. +# +$(out_base)/: $(driver) + +# Test. +# +test_targets := $(addprefix $(out_base)/.test-,$(tests)) + +$(test): $(test_targets) +$(test_targets): driver := $(driver) + +.PHONY: $(out_base)/.test-% +$(out_base)/.test-%: $(driver) $(src_base)/test-%.xsd $(src_base)/test-%.std +	$(call message,test $(out_base)/$*,$(driver) --anonymous $(src_base)/test-$*.xsd | diff -u $(src_base)/test-$*.std -) + +# Clean. +# +$(clean): + +# Dependencies. +# +$(call import,$(src_root)/tests/dump/makefile) diff --git a/libxsd-frontend/tests/schema/default/test-000.std b/libxsd-frontend/tests/schema/default/test-000.std new file mode 100644 index 0000000..efa1140 --- /dev/null +++ b/libxsd-frontend/tests/schema/default/test-000.std @@ -0,0 +1,28 @@ +primary +{ +  namespace test +  { +    complex type +    { +      element e1=123 +      element e2==456 +      element e3=unqual +      element e4==test#t:foo +      element e5=foo#x:bar +      optional attribute a1=123 http://www.w3.org/2001/XMLSchema#int +      optional attribute a2==456 http://www.w3.org/2001/XMLSchema#int +      optional attribute a3=foo#x:bar test#qname +      [1, 1] sequence +      { +        [1, 1] element e1=123 http://www.w3.org/2001/XMLSchema#int +        [1, 1] element e2==456 http://www.w3.org/2001/XMLSchema#int +        [1, 1] element e3=unqual http://www.w3.org/2001/XMLSchema#QName +        [1, 1] element e4==test#t:foo http://www.w3.org/2001/XMLSchema#QName +        [1, 1] element e5=foo#x:bar http://www.w3.org/2001/XMLSchema#QName +      } +    } +    complex qname: http://www.w3.org/2001/XMLSchema#QName +    { +    } +  } +} diff --git a/libxsd-frontend/tests/schema/default/test-000.xsd b/libxsd-frontend/tests/schema/default/test-000.xsd new file mode 100644 index 0000000..bfaedc5 --- /dev/null +++ b/libxsd-frontend/tests/schema/default/test-000.xsd @@ -0,0 +1,23 @@ +<?xml version="1.0"?> +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="test" xmlns:x="foo" targetNamespace="test"> + +  <xs:complexType name="type"> +    <xs:sequence> +      <xs:element name="e1" type="xs:int" default="123"/> +      <xs:element name="e2" type="xs:int" fixed="456"/> + +      <xs:element name="e3" type="xs:QName" default="unqual"/> +      <xs:element name="e4" type="xs:QName" fixed="t:foo"/> +      <xs:element name="e5" type="xs:QName" default="x:bar"/> +    </xs:sequence> +    <xs:attribute name="a1" type="xs:int" default="123"/> +    <xs:attribute name="a2" type="xs:int" fixed="456"/> + +    <xs:attribute name="a3" type="t:qname" default="x:bar"/> +  </xs:complexType> + +  <xs:simpleType name="qname"> +    <xs:restriction base="xs:QName"/> +  </xs:simpleType> + +</xs:schema> diff --git a/libxsd-frontend/tests/schema/default/test-001.std b/libxsd-frontend/tests/schema/default/test-001.std new file mode 100644 index 0000000..1b84a07 --- /dev/null +++ b/libxsd-frontend/tests/schema/default/test-001.std @@ -0,0 +1,15 @@ +primary +{ +  namespace test +  { +    complex type +    { +      element e=foo#unqual +      optional attribute a=foo#unqual http://www.w3.org/2001/XMLSchema#QName +      [1, 1] sequence +      { +        [1, 1] element e=foo#unqual http://www.w3.org/2001/XMLSchema#QName +      } +    } +  } +} diff --git a/libxsd-frontend/tests/schema/default/test-001.xsd b/libxsd-frontend/tests/schema/default/test-001.xsd new file mode 100644 index 0000000..5ee0507 --- /dev/null +++ b/libxsd-frontend/tests/schema/default/test-001.xsd @@ -0,0 +1,11 @@ +<?xml version="1.0"?> +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="test" xmlns="foo" targetNamespace="test"> + +  <xs:complexType name="type"> +    <xs:sequence> +      <xs:element name="e" type="xs:QName" default="unqual"/> +    </xs:sequence> +    <xs:attribute name="a" type="xs:QName" default="unqual"/> +  </xs:complexType> + +</xs:schema> diff --git a/libxsd-frontend/tests/schema/element-group/makefile b/libxsd-frontend/tests/schema/element-group/makefile new file mode 100644 index 0000000..8a4ad89 --- /dev/null +++ b/libxsd-frontend/tests/schema/element-group/makefile @@ -0,0 +1,35 @@ +# file      : tests/schema/element-group/makefile +# author    : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +# license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../../build/bootstrap.make + +tests := 000 001 002 + +driver := $(out_root)/tests/dump/driver +test   := $(out_base)/.test +clean  := $(out_base)/.clean + +# Convenience alias for default target. +# +$(out_base)/: $(driver) + +# Test. +# +test_targets := $(addprefix $(out_base)/.test-,$(tests)) + +$(test): $(test_targets) +$(test_targets): driver := $(driver) + +.PHONY: $(out_base)/.test-% +$(out_base)/.test-%: $(driver) $(src_base)/test-%.xsd $(src_base)/test-%.std +	$(call message,test $(out_base)/$*,$(driver) $(src_base)/test-$*.xsd | diff -u $(src_base)/test-$*.std -) + +# Clean. +# +$(clean): + +# Dependencies. +# +$(call import,$(src_root)/tests/dump/makefile) diff --git a/libxsd-frontend/tests/schema/element-group/test-000.std b/libxsd-frontend/tests/schema/element-group/test-000.std new file mode 100644 index 0000000..1652b68 --- /dev/null +++ b/libxsd-frontend/tests/schema/element-group/test-000.std @@ -0,0 +1,33 @@ +primary +{ +  namespace test +  { +    complex type +    { +      element foo2 +      element bar2 +      element foo3 +      element bar3 +      [1, 1] sequence +      { +        [0, unbounded] choice +        { +          [0, 1] choice +          { +            [1, 1] element foo2 http://www.w3.org/2001/XMLSchema#string +            [0, 1] element bar2 http://www.w3.org/2001/XMLSchema#string +          } +          [1, unbounded] choice +          { +            [1, unbounded] element foo3 http://www.w3.org/2001/XMLSchema#string +            [0, unbounded] element bar3 http://www.w3.org/2001/XMLSchema#string +          } +        } +      } +    } +    element foo2 http://www.w3.org/2001/XMLSchema#string +    element bar2 http://www.w3.org/2001/XMLSchema#string +    element foo3 http://www.w3.org/2001/XMLSchema#string +    element bar3 http://www.w3.org/2001/XMLSchema#string +  } +} diff --git a/libxsd-frontend/tests/schema/element-group/test-000.xsd b/libxsd-frontend/tests/schema/element-group/test-000.xsd new file mode 100644 index 0000000..1864b28 --- /dev/null +++ b/libxsd-frontend/tests/schema/element-group/test-000.xsd @@ -0,0 +1,39 @@ +<?xml version="1.0"?> +<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test"> + +  <!-- Multiple levels of forward reference. --> + +  <complexType name="type"> +    <sequence> +      <group ref="t:g1" minOccurs="0" maxOccurs="unbounded"/> +    </sequence> +  </complexType> + +  <group name="g1"> +    <choice> +      <group ref="t:g2" minOccurs="0"/> +      <group ref="t:g3" maxOccurs="unbounded"/> +    </choice> +  </group> + +  <group name="g2"> +    <choice> +      <element ref="t:foo2"/> +      <element ref="t:bar2" minOccurs="0"/> +    </choice> +  </group> + +  <group name="g3"> +    <choice> +      <element ref="t:foo3" maxOccurs="unbounded"/> +      <element ref="t:bar3" minOccurs="0" maxOccurs="unbounded"/> +    </choice> +  </group> + +  <element name="foo2" type="string"/> +  <element name="bar2" type="string"/> + +  <element name="foo3" type="string"/> +  <element name="bar3" type="string"/> + +</schema> diff --git a/libxsd-frontend/tests/schema/element-group/test-001.std b/libxsd-frontend/tests/schema/element-group/test-001.std new file mode 100644 index 0000000..ae8c1fc --- /dev/null +++ b/libxsd-frontend/tests/schema/element-group/test-001.std @@ -0,0 +1,137 @@ +primary +{ +  namespace test +  { +    complex type +    { +      element foo +      element bar +      [1, 1] sequence +      { +        [1, 1] choice +        { +          [1, 1] element foo +          { +            complex <anonymous> +            { +              element foo +              element bar +              [1, 1] sequence +              { +                [1, 1] choice +                { +                  [1, 1] element foo +                  { +                    complex <recursive-anonymous> +                  } +                  [1, 1] element bar +                  { +                    complex <anonymous> +                    { +                      element foo +                      element bar +                      [1, 1] sequence +                      { +                        [1, 1] choice +                        { +                          [1, 1] element foo +                          { +                            complex <recursive-anonymous> +                          } +                          [1, 1] element bar +                          { +                            complex <recursive-anonymous> +                          } +                        } +                      } +                    } +                  } +                } +              } +            } +          } +          [1, 1] element bar +          { +            complex <anonymous> +            { +              element foo +              element bar +              [1, 1] sequence +              { +                [1, 1] choice +                { +                  [1, 1] element foo +                  { +                    complex <anonymous> +                    { +                      element foo +                      element bar +                      [1, 1] sequence +                      { +                        [1, 1] choice +                        { +                          [1, 1] element foo +                          { +                            complex <recursive-anonymous> +                          } +                          [1, 1] element bar +                          { +                            complex <recursive-anonymous> +                          } +                        } +                      } +                    } +                  } +                  [1, 1] element bar +                  { +                    complex <recursive-anonymous> +                  } +                } +              } +            } +          } +        } +      } +    } +    element bar +    { +      complex <anonymous> +      { +        element foo +        element bar +        [1, 1] sequence +        { +          [1, 1] choice +          { +            [1, 1] element foo +            { +              complex <anonymous> +              { +                element foo +                element bar +                [1, 1] sequence +                { +                  [1, 1] choice +                  { +                    [1, 1] element foo +                    { +                      complex <recursive-anonymous> +                    } +                    [1, 1] element bar +                    { +                      complex <recursive-anonymous> +                    } +                  } +                } +              } +            } +            [1, 1] element bar +            { +              complex <recursive-anonymous> +            } +          } +        } +      } +    } +  } +} diff --git a/libxsd-frontend/tests/schema/element-group/test-001.xsd b/libxsd-frontend/tests/schema/element-group/test-001.xsd new file mode 100644 index 0000000..c6059af --- /dev/null +++ b/libxsd-frontend/tests/schema/element-group/test-001.xsd @@ -0,0 +1,33 @@ +<?xml version="1.0"?> +<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test"> + +  <!-- Recursive reference: g1->element->type->g1 --> + +  <complexType name="type"> +    <sequence> +      <group ref="t:g1"/> +    </sequence> +  </complexType> + +  <group name="g1"> +    <choice> +      <element name="foo"> +        <complexType> +          <sequence> +            <group ref="t:g1"/> +          </sequence> +        </complexType> +      </element> +      <element ref="t:bar"/> +    </choice> +  </group> + +  <element name="bar"> +    <complexType> +      <sequence> +	<group ref="t:g1"/> +      </sequence> +    </complexType> +  </element> + +</schema> diff --git a/libxsd-frontend/tests/schema/element-group/test-002.std b/libxsd-frontend/tests/schema/element-group/test-002.std new file mode 100644 index 0000000..d2c60fe --- /dev/null +++ b/libxsd-frontend/tests/schema/element-group/test-002.std @@ -0,0 +1,24 @@ +primary +{ +  namespace test +  { +    complex type +    { +      any 'any #1' +      element foo +      any 'any #0' +      [1, 1] sequence +      { +        [0, unbounded] sequence +        { +          [1, 1] any 'any #1' +        } +        [0, unbounded] sequence +        { +          [1, 1] element foo http://www.w3.org/2001/XMLSchema#int +          [1, 1] any 'any #0' +        } +      } +    } +  } +} diff --git a/libxsd-frontend/tests/schema/element-group/test-002.xsd b/libxsd-frontend/tests/schema/element-group/test-002.xsd new file mode 100644 index 0000000..bc1bd70 --- /dev/null +++ b/libxsd-frontend/tests/schema/element-group/test-002.xsd @@ -0,0 +1,26 @@ +<?xml version="1.0"?> +<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test"> + +  <!-- Any in groups. --> + +  <complexType name="type"> +    <sequence> +      <group ref="t:g1" minOccurs="0" maxOccurs="unbounded"/> +      <group ref="t:g2" minOccurs="0" maxOccurs="unbounded"/> +    </sequence> +  </complexType> + +  <group name="g1"> +    <sequence> +      <any namespace="http://www.foo.com"/> +    </sequence> +  </group> + +  <group name="g2"> +    <sequence> +      <element name="foo" type="int"/> +      <any namespace="http://www.bar.com"/> +    </sequence> +  </group> + +</schema> diff --git a/libxsd-frontend/tests/schema/enumeration/makefile b/libxsd-frontend/tests/schema/enumeration/makefile new file mode 100644 index 0000000..d958178 --- /dev/null +++ b/libxsd-frontend/tests/schema/enumeration/makefile @@ -0,0 +1,35 @@ +# file      : tests/schema/enumeration/makefile +# author    : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +# license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../../build/bootstrap.make + +tests := 000 + +driver := $(out_root)/tests/dump/driver +test   := $(out_base)/.test +clean  := $(out_base)/.clean + +# Convenience alias for default target. +# +$(out_base)/: $(driver) + +# Test. +# +test_targets := $(addprefix $(out_base)/.test-,$(tests)) + +$(test): $(test_targets) +$(test_targets): driver := $(driver) + +.PHONY: $(out_base)/.test-% +$(out_base)/.test-%: $(driver) $(src_base)/test-%.xsd $(src_base)/test-%.std +	$(call message,test $(out_base)/$*,$(driver) --enum-synthesis $(src_base)/test-$*.xsd | diff -u $(src_base)/test-$*.std -) + +# Clean. +# +$(clean): + +# Dependencies. +# +$(call import,$(src_root)/tests/dump/makefile) diff --git a/libxsd-frontend/tests/schema/enumeration/test-000.std b/libxsd-frontend/tests/schema/enumeration/test-000.std new file mode 100644 index 0000000..64e3065 --- /dev/null +++ b/libxsd-frontend/tests/schema/enumeration/test-000.std @@ -0,0 +1,62 @@ +primary +{ +  namespace test +  { +    complex common-base: http://www.w3.org/2001/XMLSchema#string +    { +    } +    complex base: test#common-base +    { +    } +    enumeration one: test#base +    { +      <romance documentation> +      enumerator romance +      enumerator fiction +      enumerator horror +    } +    enumeration two: test#common-base +    { +      enumerator horror +      enumerator history +      enumerator philosophy +    } +    enumeration three: http://www.w3.org/2001/XMLSchema#anyURI +    { +      enumerator foo +      enumerator bar +    } +    enumeration union0: test#common-base +    { +      <romance documentation> +      enumerator romance +      enumerator fiction +      enumerator horror +      enumerator history +      enumerator philosophy +    } +    <union1 documentation> +    enumeration union1: test#common-base +    { +      <romance documentation> +      enumerator romance +      enumerator fiction +      enumerator horror +      enumerator history +      enumerator philosophy +    } +    union union2 test#one test#union1 test#common-base  +    union union3 test#one test#three  +    complex complex1 +    { +      element a +      [1, 1] sequence +      { +        [1, 1] element a test#union1 +      } +    } +    complex complex2: test#union1 +    { +    } +  } +} diff --git a/libxsd-frontend/tests/schema/enumeration/test-000.xsd b/libxsd-frontend/tests/schema/enumeration/test-000.xsd new file mode 100644 index 0000000..08539bf --- /dev/null +++ b/libxsd-frontend/tests/schema/enumeration/test-000.xsd @@ -0,0 +1,72 @@ +<?xml version="1.0"?> +<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test"> + +  <!-- Enumeration synthesis --> + +  <simpleType name="common-base"> +    <restriction base="string"/> +  </simpleType> + +  <simpleType name="base"> +    <restriction base="t:common-base"/> +  </simpleType> + +  <simpleType name="one"> +    <restriction base="t:base"> +      <enumeration value="romance"> +        <annotation> +          <documentation>romance documentation</documentation> +        </annotation> +      </enumeration> +      <enumeration value="fiction"/> +      <enumeration value="horror"/> +    </restriction> +  </simpleType> + +  <simpleType name="two"> +    <restriction base="t:common-base"> +      <enumeration value="horror"/> +      <enumeration value="history"/> +      <enumeration value="philosophy"/> +    </restriction> +  </simpleType> + +  <simpleType name="three"> +    <restriction base="anyURI"> +      <enumeration value="foo"/> +      <enumeration value="bar"/> +    </restriction> +  </simpleType> + +  <simpleType name="union0"> +    <union memberTypes="t:one t:two t:union1"/> +  </simpleType> + +  <simpleType name="union1"> +    <annotation> +      <documentation>union1 documentation</documentation> +    </annotation> +    <union memberTypes="t:one t:two"/> +  </simpleType> + +  <simpleType name="union2"> +    <union memberTypes="t:one t:union1 t:common-base"/> +  </simpleType> + +  <simpleType name="union3"> +    <union memberTypes="t:one t:three"/> +  </simpleType> + +  <complexType name="complex1"> +    <sequence> +      <element name="a" type="t:union1"/> +    </sequence> +  </complexType> + +  <complexType name="complex2"> +    <simpleContent> +      <extension base="t:union1"/> +    </simpleContent> +  </complexType> + +</schema> diff --git a/libxsd-frontend/tests/schema/makefile b/libxsd-frontend/tests/schema/makefile new file mode 100644 index 0000000..fde5482 --- /dev/null +++ b/libxsd-frontend/tests/schema/makefile @@ -0,0 +1,25 @@ +# file      : tests/schema +# author    : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +# license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../build/bootstrap.make + +tests :=        \ +annotation      \ +anonymous       \ +attribute-group \ +default         \ +element-group   \ +enumeration     \ +union + +default   := $(out_base)/ +test      := $(out_base)/.test +clean     := $(out_base)/.clean + +$(default): $(addprefix $(out_base)/,$(addsuffix /,$(tests))) +$(test): $(addprefix $(out_base)/,$(addsuffix /.test,$(tests))) +$(clean): $(addprefix $(out_base)/,$(addsuffix /.clean,$(tests))) + +$(foreach t,$(tests),$(call import,$(src_base)/$t/makefile)) diff --git a/libxsd-frontend/tests/schema/union/makefile b/libxsd-frontend/tests/schema/union/makefile new file mode 100644 index 0000000..7f01070 --- /dev/null +++ b/libxsd-frontend/tests/schema/union/makefile @@ -0,0 +1,35 @@ +# file      : tests/schema/union/makefile +# author    : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +# license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../../build/bootstrap.make + +tests := 000 001 + +driver := $(out_root)/tests/dump/driver +test   := $(out_base)/.test +clean  := $(out_base)/.clean + +# Convenience alias for default target. +# +$(out_base)/: $(driver) + +# Test. +# +test_targets := $(addprefix $(out_base)/.test-,$(tests)) + +$(test): $(test_targets) +$(test_targets): driver := $(driver) + +.PHONY: $(out_base)/.test-% +$(out_base)/.test-%: $(driver) $(src_base)/test-%.xsd $(src_base)/test-%.std +	$(call message,test $(out_base)/$*,$(driver) $(src_base)/test-$*.xsd | diff -u $(src_base)/test-$*.std -) + +# Clean. +# +$(clean): + +# Dependencies. +# +$(call import,$(src_root)/tests/dump/makefile) diff --git a/libxsd-frontend/tests/schema/union/test-000.std b/libxsd-frontend/tests/schema/union/test-000.std new file mode 100644 index 0000000..6f95b0c --- /dev/null +++ b/libxsd-frontend/tests/schema/union/test-000.std @@ -0,0 +1,37 @@ +primary +{ +  namespace test +  { +    union u1 http://www.w3.org/2001/XMLSchema#int http://www.w3.org/2001/XMLSchema#string  +    union u2  +    { +      enumeration <anonymous>: http://www.w3.org/2001/XMLSchema#token +      { +        enumerator one +      } +    } + +    { +      enumeration <anonymous>: http://www.w3.org/2001/XMLSchema#string +      { +        enumerator two +      } +    } + +    union u3 http://www.w3.org/2001/XMLSchema#int test#u1  +    { +      enumeration <anonymous>: http://www.w3.org/2001/XMLSchema#token +      { +        enumerator one +      } +    } + +    { +      enumeration <anonymous>: http://www.w3.org/2001/XMLSchema#string +      { +        enumerator two +      } +    } + +  } +} diff --git a/libxsd-frontend/tests/schema/union/test-000.xsd b/libxsd-frontend/tests/schema/union/test-000.xsd new file mode 100644 index 0000000..99535de --- /dev/null +++ b/libxsd-frontend/tests/schema/union/test-000.xsd @@ -0,0 +1,40 @@ +<?xml version="1.0"?> +<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test"> + +  <simpleType name="u1"> +    <union memberTypes="int string"/> +  </simpleType> + +  <simpleType name="u2"> +    <union> +      <simpleType> +        <restriction base="token"> +          <enumeration value="one"/> +        </restriction> +      </simpleType> +      <simpleType> +        <restriction base="string"> +          <enumeration value="two"/> +        </restriction> +      </simpleType> +    </union> +  </simpleType> + +  <simpleType name="u3"> +    <union memberTypes="  int + +t:u1 "> +      <simpleType> +        <restriction base="token"> +          <enumeration value="one"/> +        </restriction> +      </simpleType> +      <simpleType> +        <restriction base="string"> +          <enumeration value="two"/> +        </restriction> +      </simpleType> +    </union> +  </simpleType> + +</schema> diff --git a/libxsd-frontend/tests/schema/union/test-001.std b/libxsd-frontend/tests/schema/union/test-001.std new file mode 100644 index 0000000..f407b30 --- /dev/null +++ b/libxsd-frontend/tests/schema/union/test-001.std @@ -0,0 +1,15 @@ +primary +{ +  namespace test +  { +    list list +    { +      union <anonymous> http://www.w3.org/2001/XMLSchema#int test#enum  +    } +    enumeration enum: http://www.w3.org/2001/XMLSchema#string +    { +      enumerator male +      enumerator female +    } +  } +} diff --git a/libxsd-frontend/tests/schema/union/test-001.xsd b/libxsd-frontend/tests/schema/union/test-001.xsd new file mode 100644 index 0000000..00fd8ce --- /dev/null +++ b/libxsd-frontend/tests/schema/union/test-001.xsd @@ -0,0 +1,21 @@ +<?xml version="1.0"?> +<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test"> + +  <!-- Test resolution of anonymous argument types. --> + +  <simpleType name="list"> +    <list> +      <simpleType> +        <union memberTypes="int t:enum"/> +      </simpleType> +    </list> +  </simpleType> + +  <simpleType name="enum"> +    <restriction base="string"> +      <enumeration value="male"/> +      <enumeration value="female"/> +    </restriction> +  </simpleType> + +</schema> diff --git a/libxsd-frontend/version b/libxsd-frontend/version new file mode 100644 index 0000000..092afa1 --- /dev/null +++ b/libxsd-frontend/version @@ -0,0 +1 @@ +1.17.0 diff --git a/libxsd-frontend/xsd-frontend/makefile b/libxsd-frontend/xsd-frontend/makefile new file mode 100644 index 0000000..abf6565 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/makefile @@ -0,0 +1,126 @@ +# file      : xsd-frontend/makefile +# author    : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +# license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../build/bootstrap.make + +cxx_tun := semantic-graph/annotation.cxx      \ +           semantic-graph/any.cxx             \ +           semantic-graph/any-attribute.cxx   \ +           semantic-graph/attribute.cxx       \ +           semantic-graph/attribute-group.cxx \ +           semantic-graph/complex.cxx         \ +           semantic-graph/compositors.cxx     \ +           semantic-graph/element.cxx         \ +           semantic-graph/element-group.cxx   \ +           semantic-graph/elements.cxx        \ +           semantic-graph/enumeration.cxx     \ +           semantic-graph/fundamental.cxx     \ +           semantic-graph/list.cxx            \ +           semantic-graph/namespace.cxx       \ +           semantic-graph/particle.cxx        \ +           semantic-graph/schema.cxx          \ +           semantic-graph/union.cxx + +cxx_tun += traversal/attribute.cxx       \ +           traversal/attribute-group.cxx \ +           traversal/complex.cxx         \ +           traversal/compositors.cxx     \ +           traversal/element.cxx         \ +           traversal/element-group.cxx   \ +           traversal/elements.cxx        \ +           traversal/enumeration.cxx     \ +           traversal/fundamental.cxx     \ +           traversal/list.cxx            \ +           traversal/namespace.cxx       \ +           traversal/particle.cxx        \ +           traversal/schema.cxx          \ +           traversal/union.cxx + +cxx_tun += transformations/anonymous.cxx       \ +           transformations/enum-synthesis.cxx  \ +           transformations/restriction.cxx     \ +           transformations/schema-per-type.cxx \ +           transformations/simplifier.cxx + +cxx_tun += parser.cxx schema-dom-parser.cxx + + +cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o)) +cxx_od  := $(cxx_obj:.o=.o.d) +m4_cxx  := $(out_base)/semantic-graph/fundamental.hxx \ +  $(out_base)/semantic-graph/fundamental.cxx + +xsd_frontend.l             := $(out_base)/xsd-frontend.l +xsd_frontend.l.cpp-options := $(out_base)/xsd-frontend.l.cpp-options + +clean   := $(out_base)/.clean + +# Import. +# +$(call import,\ +  $(scf_root)/import/libboost/filesystem/stub.make,\ +  l: fs.l,cpp-options: fs.l.cpp-options) + +$(call import,\ +  $(scf_root)/import/libxerces-c/stub.make,\ +  l: xerces_c.l,cpp-options: xerces_c.l.cpp-options) + +$(call import,\ +  $(scf_root)/import/libcult/stub.make,\ +  l: cult.l,cpp-options: cult.l.cpp-options) + +$(call import,\ +  $(scf_root)/import/libfrontend-elements/stub.make,\ +  l: fe.l,cpp-options: fe.l.cpp-options) + +# what to build +# +$(xsd_frontend.l): $(cxx_obj) $(fe.l) $(cult.l) $(xerces_c.l) $(fs.l) + +$(xsd_frontend.l.cpp-options): prefix := xsd-frontend/ $(out_root)/ +$(xsd_frontend.l.cpp-options): value := -I$(src_root) -I$(out_root) +$(xsd_frontend.l.cpp-options):  \ +  $(fs.l.cpp-options)           \ +  $(fe.l.cpp-options)           \ +  $(cult.l.cpp-options) + +#@@ This can be further optimized since only parser depends on xerces. +# +$(cxx_obj) $(cxx_od): $(xsd_frontend.l.cpp-options) $(xerces_c.l.cpp-options) + +$(m4_cxx): $(src_base)/semantic-graph/fundamental.m4 +$(m4_cxx): m4_options := -I $(src_base)/semantic-graph + +$(call include-dep,$(cxx_od)) + +# Alias for default target. +# +$(out_base)/: $(xsd_frontend.l) + +# Clean +# +$(clean): $(xsd_frontend.l).o.clean     \ +  $(xsd_frontend.l.cpp-options).clean   \ +  $(addsuffix .cxx.clean,$(cxx_obj))    \ +  $(addsuffix .cxx.clean,$(cxx_od))     \ +  $(addsuffix .m4.clean,$(m4_cxx)) + +# Generated .gitignore. +# +ifeq ($(out_base),$(src_base)) +$(xsd_frontend.l): | $(out_base)/.gitignore + +$(out_base)/.gitignore: files := semantic-graph/fundamental.hxx semantic-graph/fundamental.cxx +$(clean): $(out_base)/.gitignore.clean + +$(call include,$(bld_root)/git/gitignore.make) +endif + +# How to. +# +$(call include,$(bld_root)/cxx/o-l.make) +$(call include,$(bld_root)/cxx/cxx-o.make) +$(call include,$(bld_root)/cxx/cxx-d.make) +$(call include,$(bld_root)/m4/m4.make) diff --git a/libxsd-frontend/xsd-frontend/parser.cxx b/libxsd-frontend/xsd-frontend/parser.cxx new file mode 100644 index 0000000..901a8d3 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/parser.cxx @@ -0,0 +1,5126 @@ +// file      : xsd-frontend/parser.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/types.hxx> +#include <xsd-frontend/parser.hxx> +#include <xsd-frontend/xml.hxx> +#include <xsd-frontend/schema-dom-parser.hxx> + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +#include <cult/containers/map.hxx> +#include <cult/containers/stack.hxx> +#include <cult/containers/vector.hxx> +#include <cult/rtti/type-id.hxx> + +//@@ Do i need this? +// +#include <xercesc/dom/DOM.hpp> + +#include <xercesc/sax/ErrorHandler.hpp> +#include <xercesc/sax/SAXParseException.hpp> + +#include <xercesc/sax2/SAX2XMLReader.hpp> +#include <xercesc/sax2/XMLReaderFactory.hpp> + +#include <xercesc/util/XMLUniDefs.hpp> +#include <xercesc/util/XMLString.hpp> +#include <xercesc/util/PlatformUtils.hpp> +#include <xercesc/util/BinInputStream.hpp> +#include <xercesc/util/BinFileInputStream.hpp> + +#include <xercesc/validators/common/Grammar.hpp> + +#include <xercesc/sax/InputSource.hpp> +#include <xercesc/framework/LocalFileInputSource.hpp> +#include <xercesc/framework/Wrapper4InputSource.hpp> + +#include <iostream> +#include <sstream> +#include <memory>   // std::auto_ptr + +using std::wcout; +using std::wcerr; +using std::endl; + +using Cult::RTTI::TypeId; + +namespace XSDFrontend +{ +  namespace Xerces = XML::Xerces; +  using namespace SemanticGraph; + +  //@@ Port to tracing facility. +  // +  Boolean trace_ = false; + +  String const xsd = L"http://www.w3.org/2001/XMLSchema"; +  String const xse = L"http://www.codesynthesis.com/xmlns/xml-schema-extension"; + +  namespace +  { +    // +    // Exceptions. +    // + +    struct NotNamespace +    { +      NotNamespace (String const& ns) +          : ns_ (ns) +      { +      } + +      String const& +      ns () const +      { +        return ns_; +      } + +    private: +      String ns_; +    }; + +    struct NotName +    { +      NotName (String const& ns, String const& name) +          : ns_ (ns), name_ (name) +      { +      } + +      String const& +      ns () const +      { +        return ns_; +      } + +      String const& +      name () const +      { +        return name_; +      } + +    private: +      String ns_; +      String name_; +    }; + + +    // Name cache. We only support maximum two nodes with the same +    // name in the cache (e.g., element and type). For (rare) cases +    // where there is three or more names, there will be a cache miss. +    // +    struct CacheNodes +    { +      CacheNodes () : first (0), second (0) {} + +      Nameable* first; +      Nameable* second; +    }; + +    typedef Cult::Containers::Map<String, CacheNodes> NodeMap; +    typedef Cult::Containers::Map<String, NodeMap> NamespaceMap; +    typedef Cult::Containers::Vector<SemanticGraph::Member*> DefaultValues; + +    template <typename X> +    X& +    resolve (String const& ns_name, +             String const& uq_name, +             Schema& s_, +             NamespaceMap& cache) +    { +      // First check the cache. +      // +      NamespaceMap::Iterator i (cache.find (ns_name)); + +      if (i != cache.end ()) +      { +        NodeMap::Iterator j (i->second.find (uq_name)); + +        if (j != i->second.end ()) +        { +          X* x; + +          if ((x = dynamic_cast<X*> (j->second.first)) || +              (x = dynamic_cast<X*> (j->second.second))) +              return *x; +        } +      } + +      Scope::NamesIteratorPair nss (s_.find (ns_name)); + +      if (nss.first == nss.second) +        throw NotNamespace (ns_name); + +      for (; nss.first != nss.second; ++nss.first) +      { +        Namespace& ns (dynamic_cast<Namespace&> (nss.first->named ())); + +        Scope::NamesIteratorPair types (ns.find (uq_name)); + +        for (; types.first != types.second; ++types.first) +        { +          if (X* x = dynamic_cast<X*> (&types.first->named ())) +          { +            if (trace_) +              wcout << "successfully resolved '" << ns_name << '#' << uq_name +                    << "'" << endl; + +            // Add to the cache if there are free slots. +            // +            NodeMap& m (i != cache.end () ? i->second : cache[ns_name]); +            CacheNodes& n (m[uq_name]); + +            if (n.first == 0) +              n.first = x; +            else if (n.second == 0) +              n.second = x; + +            return *x; +          } +        } +      } + +      throw NotName (ns_name, uq_name); +    } + +    // +    // +    typedef Cult::Containers::Map<String, String> Facets; + +    Void +    copy_facets (Restricts& r, Facets const& f) +    { +      for (Facets::ConstIterator i (f.begin ()), e (f.end ()); i != e; ++i) +        r.facet_insert (i->first, i->second); +    } + +    // +    // +    struct UnionMemberType +    { +      UnionMemberType (String const& ns, String const& uq) +          : ns_name (ns), uq_name (uq) +      { +      } + +      String ns_name; +      String uq_name; +    }; + +    typedef Cult::Containers::Vector<UnionMemberType> UnionMemberTypes; + +    // +    // +    struct ElementGroupRef +    { +      ElementGroupRef (String const& uq_name_, String const& ns_name_, +                       UnsignedLong min_, UnsignedLong max_, +                       Compositor& compositor, Scope& scope) +          : uq_name (uq_name_), ns_name (ns_name_), +            min (min_), max (max_) +      { +        contains_pos  = compositor.contains_end (); +        if (compositor.contains_begin () != contains_pos) +          --contains_pos; + +        names_pos = scope.names_end (); +        if (scope.names_begin () != names_pos) +          --names_pos; +      } + +      ElementGroupRef (String const& uq_name_, String const& ns_name_, +                       UnsignedLong min_, UnsignedLong max_, +                       Scope& scope) +          : uq_name (uq_name_), ns_name (ns_name_), +            min (min_), max (max_) +      { +        names_pos  = scope.names_end (); +        if (scope.names_begin () != names_pos) +          --names_pos; +      } + +      String uq_name; +      String ns_name; +      UnsignedLong min, max; +      Compositor::ContainsIterator contains_pos; +      Scope::NamesIterator names_pos; +    }; + +    typedef Cult::Containers::Vector<ElementGroupRef> ElementGroupRefs; + + +    // +    // +    struct AttributeGroupRef +    { +      AttributeGroupRef (String const& uq_name_, +                         String const& ns_name_, +                         Scope& scope) +          : uq_name (uq_name_), ns_name (ns_name_) +      { +        names_pos = scope.names_end (); +        if (scope.names_begin () != names_pos) +          --names_pos; +      } + +      String uq_name; +      String ns_name; +      Scope::NamesIterator names_pos; +    }; + +    typedef Cult::Containers::Vector<AttributeGroupRef> AttributeGroupRefs; + + +    // +    // +    template <typename N, typename A> +    struct NodeArgs +    { +      NodeArgs (N& node, A arg) +          : node_ (node), arg_ (arg) +      { +      } + +      operator N& () const +      { +        return node_; +      } + +      template <typename E> +      Void +      add_edge_left (E& e) +      { +        node_.add_edge_left (e, arg_); +      } + +      template <typename E> +      Void +      add_edge_right (E& e) +      { +        node_.add_edge_right (e, arg_); +      } + +    private: +      N& node_; +      A arg_; +    }; + + +    // +    // +    struct Resolver : Traversal::Element, +                      Traversal::Attribute, +                      Traversal::Fundamental::IdRef, +                      Traversal::Fundamental::IdRefs, +                      Traversal::List, +                      Traversal::Union, +                      Traversal::Complex, +                      Traversal::Enumeration, +                      Traversal::ElementGroup, +                      Traversal::AttributeGroup, +                      Traversal::Compositor +    { +      Resolver (Schema& s, +                Boolean& valid, +                NamespaceMap& cache, +                DefaultValues& default_values) +          : s_ (s), +            valid_ (valid), +            cache_ (cache), +            default_values_ (default_values) +      { +        *this >> contains_compositor >> *this; +      } + +      Void +      traverse (SemanticGraph::Attribute& a) +      { +        // Avoid traversing attribute more than once. +        // +        if (!a.context ().count ("attribute-traversed")) +        { +          a.context ().set ("attribute-traversed", true); +          SemanticGraph::Member& m (a); +          resolve_member (m); +        } +      } + +      Void +      traverse (SemanticGraph::Element& e) +      { +        resolve_element (e); +      } + +      Void +      resolve_element (SemanticGraph::Element& e) +      { +        // Avoid resolving element more than once. +        // +        if (e.context ().count ("element-resolved")) +          return; + +        e.context ().set ("element-resolved", true); + +        { +          SemanticGraph::Member& m (e); +          resolve_member (m); +        } + +        if (e.context ().count ("substitution-ns-name")) +        { +          String ns_name (e.context ().get<String> ("substitution-ns-name")); +          String uq_name (e.context ().get<String> ("substitution-uq-name")); + +          e.context ().remove ("substitution-ns-name"); +          e.context ().remove ("substitution-uq-name"); + +          try +          { +            SemanticGraph::Element& root ( +              resolve<SemanticGraph::Element> (ns_name, uq_name, s_, cache_)); + +            s_.new_edge<Substitutes> (e, root); +          } +          catch (NotNamespace const& ex) +          { +            if (valid_) +            { +              wcerr << "ice: unable to resolve namespace '" << ex.ns () << "'" +                    << endl; +              abort (); +            } +          } +          catch (NotName const& ex) +          { +            if (valid_) +            { +              wcerr << "ice: unable to resolve name '" << ex.name () +                    << "' inside namespace '" << ex.ns () << "'" <<endl; +              abort (); +            } +          } +        } +      } + +      Void +      resolve_member (SemanticGraph::Member& m) +      { +        using SemanticGraph::Member; +        using SemanticGraph::Element; +        using SemanticGraph::Attribute; + +        try +        { +          String ns_name; +          String uq_name; + +          if (m.context ().count ("type-ns-name")) +          { +            ns_name = m.context ().get<String> ("type-ns-name"); +            uq_name = m.context ().get<String> ("type-uq-name"); + +            m.context ().remove ("type-ns-name"); +            m.context ().remove ("type-uq-name"); +            m.context ().remove ("edge-type-id"); + +            s_.new_edge<Belongs> ( +              m, resolve<SemanticGraph::Type> (ns_name, uq_name, s_, cache_)); +          } +          else if (m.context ().count ("instance-ns-name")) +          { +            ns_name = m.context ().get<String> ("instance-ns-name"); +            uq_name = m.context ().get<String> ("instance-uq-name"); + +            m.context ().remove ("instance-ns-name"); +            m.context ().remove ("instance-uq-name"); + + +            Member& ref (resolve<Member> (ns_name, uq_name, s_, cache_)); + +            // Make sure the referenced member is fully resolved. +            // @@ Substitutes edge won't be resolved. +            // +            resolve_member (ref); + + +            // Substitution group info. We have to test for both resolved +            // and unresolved cases since we don't know whether it was +            // resolved or not. +            // +            if (ref.is_a<Element> ()) +            { +              Element& m_e (dynamic_cast<Element&> (m)); +              Element& ref_e (dynamic_cast<Element&> (ref)); + +              if (ref_e.substitutes_p ()) +              { +                s_.new_edge<Substitutes> (m_e, ref_e.substitutes ().root ()); +              } +              else if (ref_e.context ().count ("substitution-ns-name")) +              { +                m_e.context ().set ( +                  "substitution-ns-name", +                  ref_e.context ().get<String> ("substitution-ns-name")); + +                m_e.context ().set ( +                  "substitution-uq-name", +                  ref_e.context ().get<String> ("substitution-uq-name")); +              } +            } + +            // +            // +            s_.new_edge<BelongsToNamespace> (m, ref.namespace_ ()); + +            // Transfer default and fixed values if we haven't already +            // gotten them. +            // +            if (!m.default_p ()) +            { +              if (ref.fixed_p ()) +                m.fixed (ref.value ()); +              else if (ref.default_p ()) +              { +                // Default value applies only if the attribute is optional. +                // +                if (Attribute* a = dynamic_cast<Attribute*> (&m)) +                { +                  if (a->optional_p ()) +                    m.default_ (ref.value ()); +                } +                else +                  m.default_ (ref.value ()); +              } + +              if (m.default_p ()) +              { +                m.context ().set ( +                  "dom-node", +                  ref.context ().get<Xerces::DOMElement*> ("dom-node")); +                default_values_.push_back (&m); +              } +            } + +            // Transfer annotation if we haven't already gotten it. +            // +            if (!m.annotated_p () && ref.annotated_p ()) +              s_.new_edge<Annotates> (ref.annotation (), m); + +            // Type info. +            // +            if (ref.typed_p ()) +              s_.new_edge<Belongs> (m, ref.type ()); +            else +            { +              if (valid_) +              { +                wcerr << "ice: referenced instance '" << ns_name << "#" +                      << uq_name << "' is not typed" << endl; +                abort (); +              } +            } +          } +        } +        catch (NotNamespace const& ex) +        { +          if (valid_) +          { +            wcerr << "ice: unable to resolve namespace '" << ex.ns () << "'" +                  << endl; +            abort (); +          } +        } +        catch (NotName const& ex) +        { +          if (valid_) +          { +            wcerr << "ice: unable to resolve name '" << ex.name () +                  << "' inside namespace '" << ex.ns () << "'" <<endl; +            abort (); +          } +        } +      } + +      Void +      traverse (SemanticGraph::Fundamental::IdRef& i) +      { +        ref_type (i); +      } + +      Void +      traverse (SemanticGraph::Fundamental::IdRefs& i) +      { +        ref_type (i); +      } + +      Void +      ref_type (SemanticGraph::Specialization& s) +      { +        if (s.context ().count ("type-ns-name")) +        { +          String ns_name (s.context ().get<String> ("type-ns-name")); +          String uq_name (s.context ().get<String> ("type-uq-name")); + +          s.context ().remove ("type-ns-name"); +          s.context ().remove ("type-uq-name"); +          s.context ().remove ("edge-type-id"); + +          try +          { +            s_.new_edge<Arguments> ( +              resolve<SemanticGraph::Type> (ns_name, uq_name, s_, cache_), s); +          } +          catch (NotName const& ex) +          { +            wcerr << s.file () << ":" << s.line () << ":" << s.column () << ": " +                  << "error: unable to resolve type '" << uq_name << "' " +                  << "in namespace '" << ns_name << "'" << endl; + +            valid_ = false; +          } +        } +      } + +      Void +      traverse (SemanticGraph::List& l) +      { +        if (l.context ().count ("type-ns-name")) +        { +          String ns_name (l.context ().get<String> ("type-ns-name")); +          String uq_name (l.context ().get<String> ("type-uq-name")); + +          l.context ().remove ("type-ns-name"); +          l.context ().remove ("type-uq-name"); +          l.context ().remove ("edge-type-id"); + +          try +          { +            s_.new_edge<Arguments> ( +              resolve<SemanticGraph::Type> (ns_name, uq_name, s_, cache_), l); +          } +          catch (NotName const& ex) +          { +            wcerr << l.file () << ":" << l.line () << ":" << l.column () << ": " +                  << "error: unable to resolve item type '" << uq_name << "' " +                  << "in namespace '" << ns_name << "'" << endl; + +            valid_ = false; +          } +        } + +        Traversal::List::traverse (l); +      } + +      Void +      traverse (SemanticGraph::Union& u) +      { +        using SemanticGraph::Union; + +        if (u.context ().count ("union-member-types")) +        { +          UnionMemberTypes const& m ( +            u.context ().get<UnionMemberTypes> ("union-member-types")); + +          // Process it backwards so that we can just insert each +          // edge in the front. +          // +          for (UnionMemberTypes::ConstReverseIterator i (m.rbegin ()); +               i != m.rend (); i++) +          { +            try +            { +              NodeArgs<Union, Union::ArgumentedIterator> na ( +                u, u.argumented_begin ()); + +              s_.new_edge<Arguments> ( +                resolve<SemanticGraph::Type> ( +                  i->ns_name, i->uq_name, s_, cache_), na); +            } +            catch (NotName const& ex) +            { +              wcerr << u.file () << ":" << u.line () << ":" << u.column () << ": " +                    << "error: unable to resolve item type '" << i->uq_name << "' " +                    << "in namespace '" << i->ns_name << "'" << endl; + +              valid_ = false; +            } +          } + +          u.context ().remove ("union-member-types"); +        } + +        Traversal::Union::traverse (u); +      } + +      Void +      traverse (SemanticGraph::Complex& c) +      { +        // Avoid traversing complex type more than once. +        // +        if (c.context ().count ("complex-type-resolved")) +          return; + +        c.context ().set ("complex-type-resolved", true); + +        // Resolve base type if any. +        // +        if (c.context ().count ("type-ns-name")) +        { +          using Cult::RTTI::TypeId; + +          String ns_name (c.context ().get<String> ("type-ns-name")); +          String uq_name (c.context ().get<String> ("type-uq-name")); +          TypeId edge_id (c.context ().get<TypeId> ("edge-type-id")); + +          c.context ().remove ("type-ns-name"); +          c.context ().remove ("type-uq-name"); +          c.context ().remove ("edge-type-id"); + +          try +          { +            if (edge_id == typeid (Extends)) +            { +              s_.new_edge<Extends> ( +                c, resolve<SemanticGraph::Type> ( +                  ns_name, uq_name, s_, cache_)); +            } +            else if (edge_id == typeid (Restricts)) +            { +              Restricts& r ( +                s_.new_edge<Restricts> ( +                  c, resolve<SemanticGraph::Type> ( +                    ns_name, uq_name, s_, cache_))); + +              if (c.context ().count ("facets")) +              { +                Facets const& f (c.context ().get<Facets> ("facets")); +                copy_facets (r, f); +                c.context ().remove ("facets"); +              } +            } +            else +              assert (false); +          } +          catch (NotName const& ex) +          { +            wcerr << c.file () << ":" << c.line () << ":" << c.column () << ": " +                  << "error: unable to resolve base type '" << uq_name << "' " +                  << "in namespace '" << ns_name << "'" << endl; + +            valid_ = false; +          } +        } + +        // Resolve attribute-group-refs. Do it before element-group-refs +        // so that if the scope was empty they end up at the end. +        // +        if (c.context ().count ("attribute-group-refs")) +        { +          AttributeGroupRefs& refs ( +            c.context ().get<AttributeGroupRefs> ("attribute-group-refs")); + +          // Handle refs from last to first so that multiple insertions +          // to an empty list (always front) end up in proper order. +          // +          for (AttributeGroupRefs::ReverseIterator i (refs.rbegin ()); +               i != refs.rend (); ++i) +          { +            clone_attribute_group_content (*i, c); +          } + +          c.context ().remove ("attribute-group-refs"); +        } + +        // Resolve element-group-ref if any. +        // +        if (c.context ().count ("element-group-ref")) +        { +          using SemanticGraph::Compositor; + +          ElementGroupRef& ref ( +            c.context ().get<ElementGroupRef> ("element-group-ref")); + +          Compositor* comp (clone_element_group_content (c, ref)); + +          // Create ContainsCompositor edge. +          // +          if (comp) +            s_.new_edge<ContainsCompositor> (c, *comp, ref.min, ref.max); + +          c.context ().remove ("element-group-ref"); +        } + +        Traversal::Complex::traverse (c); +      } + +      Void +      traverse (SemanticGraph::Enumeration& e) +      { +        // Resolve base type if any. +        // +        if (e.context ().count ("type-ns-name")) +        { +          String ns_name (e.context ().get<String> ("type-ns-name")); +          String uq_name (e.context ().get<String> ("type-uq-name")); + +          e.context ().remove ("type-ns-name"); +          e.context ().remove ("type-uq-name"); +          e.context ().remove ("edge-type-id"); + +          try +          { +            Restricts& r ( +              s_.new_edge<Restricts> ( +                e, resolve<SemanticGraph::Type> ( +                  ns_name, uq_name, s_, cache_))); + +            if (e.context ().count ("facets")) +            { +              Facets const& f (e.context ().get<Facets> ("facets")); +              copy_facets (r, f); +              e.context ().remove ("facets"); +            } +          } +          catch (NotName const& ex) +          { +            wcerr << e.file () << ":" << e.line () << ":" << e.column () << ": " +                  << "error: unable to resolve base type '" << uq_name << "' " +                  << "in namespace '" << ns_name << "'" << endl; + +            valid_ = false; +          } +        } + +        Traversal::Enumeration::traverse (e); +      } + +      Void +      traverse (SemanticGraph::ElementGroup& g) +      { +        // Avoid traversing groups more than once. +        // +        if (!g.context ().count ("element-group-traversed")) +        { +          g.context ().set ("element-group-traversed", true); +          Traversal::ElementGroup::traverse (g); + +          // Note that setting element-group-resolved after traversing +          // the group allows for a recursive shallow resolution using +          // resolve_element_group. +          // +          g.context ().set ("element-group-resolved", true); +        } +      } + +      // We need a "shallow" resolve to break possible recursing: +      // group->element->complexType->group. +      // +      Void +      resolve_element_group (SemanticGraph::ElementGroup& g) +      { +        using SemanticGraph::Scope; +        using SemanticGraph::Element; + +        // Avoid resolving groups more than once. +        // +        if (!g.context ().count ("element-group-resolved")) +        { +          g.context ().set ("element-group-resolved", true); + +          for (Scope::NamesIterator i (g.names_begin ()); +               i != g.names_end (); ++i) +          { +            if (Element* e = dynamic_cast<Element*> (&i->named ())) +              resolve_element (*e); +          } + +          traverse (g.contains_compositor ().compositor ()); +        } +      } + +      Void +      traverse (SemanticGraph::AttributeGroup& g) +      { +        // Avoid traversing groups more than once. +        // +        if (g.context ().count ("attribute-group-resolved")) +          return; + +        g.context ().set ("attribute-group-resolved", true); + +        // Resolve attribute-group-refs. +        // +        if (g.context ().count ("attribute-group-refs")) +        { +          AttributeGroupRefs& refs ( +            g.context ().get<AttributeGroupRefs> ("attribute-group-refs")); + +          // Handle refs from last to first so that multiple insertions +          // to an empty list (always front) end up in proper order. +          // +          for (AttributeGroupRefs::ReverseIterator i (refs.rbegin ()); +               i != refs.rend (); ++i) +          { +            clone_attribute_group_content (*i, g); +          } + +          g.context ().remove ("attribute-group-refs"); +        } + +        Traversal::AttributeGroup::traverse (g); +      } + +      Void +      traverse (SemanticGraph::Compositor& c) +      { +        using SemanticGraph::Compositor; + +        // Resolve element-group-refs if any. +        // +        if (c.context ().count ("element-group-refs")) +        { +          using SemanticGraph::Scope; + +          ElementGroupRefs& refs ( +            c.context ().get<ElementGroupRefs> ("element-group-refs")); + +          // Handle refs from last to first so that multiple insertions +          // to an empty list (always front) end up in proper order. +          // +          for (ElementGroupRefs::ReverseIterator i (refs.rbegin ()); +               i != refs.rend (); ++i) +          { +            // Find our scope. +            // +            Compositor* j (&c); + +            while(!j->contained_compositor_p ()) +              j = &j->contained_particle ().compositor (); + +            Compositor* comp ( +              clone_element_group_content ( +                dynamic_cast<Scope&> (j->contained_compositor ().container ()), +                *i)); + +            // Create ContainsParticle edge. +            // +            if (comp) +            { +              NodeArgs<Compositor, Compositor::ContainsIterator> na ( +                c, i->contains_pos); +              s_.new_edge<ContainsParticle> (na, *comp, i->min, i->max); +            } +          } + +          c.context ().remove ("element-group-refs"); +        } + +        // Traverse recursively but only particles that are compositors. +        // This way we won't trigger anonymous type traversal (via member) +        // and therefore can call this functions from resolve_element_group +        // to completely resolve a group. +        // +        for (Compositor::ContainsIterator i (c.contains_begin ()), +               e (c.contains_end ()); i != e; ++i) +        { +          SemanticGraph::Particle& p (i->particle ()); + +          if (p.is_a<Compositor> ()) +            dispatch (p); +        } + +        // Traversal::Compositor::traverse (c); +      } + +      SemanticGraph::Compositor* +      clone_element_group_content (SemanticGraph::Scope& s, +                                   ElementGroupRef const& ref) +      { +        using SemanticGraph::Scope; +        using SemanticGraph::Compositor; +        using SemanticGraph::ElementGroup; + +        try +        { +          ElementGroup& g ( +            resolve<ElementGroup> (ref.ns_name, ref.uq_name, s_, cache_)); + +          // Make sure the group and all its content are fully resolved. +          // +          resolve_element_group (g); + +          Scope::NamesIterator pos (ref.names_pos); +          Compositor& root (g.contains_compositor ().compositor ()); +          Compositor& copy (clone_compositor (root, s, pos)); + +          return © +        } +        catch (NotNamespace const& ex) +        { +          if (valid_) +          { +            wcerr << "ice: unable to resolve namespace '" << ex.ns () << "'" +                  << endl; +            abort (); +          } +        } +        catch (NotName const& ex) +        { +          if (valid_) +          { +            wcerr << "ice: unable to resolve name '" << ex.name () +                  << "' inside namespace '" << ex.ns () << "'" << endl; +            abort (); +          } +        } + +        return 0; +      } + +      SemanticGraph::Compositor& +      clone_compositor (SemanticGraph::Compositor& c, +                        SemanticGraph::Scope& scope, +                        SemanticGraph::Scope::NamesIterator& pos) +      { +        using SemanticGraph::Any; +        using SemanticGraph::Element; +        using SemanticGraph::Particle; +        using SemanticGraph::Compositor; + +        Compositor* tmp (0); + +        if (c.is_a<All> ()) +          tmp = &s_.new_node<All> (c.file (), c.line (), c.column ()); +        else if (c.is_a<Choice> ()) +          tmp = &s_.new_node<Choice> (c.file (), c.line (), c.column ()); +        else if (c.is_a<Sequence> ()) +          tmp = &s_.new_node<Sequence> (c.file (), c.line (), c.column ()); +        else +          assert (false); + +        Compositor& copy (*tmp); + +        // Copy annotation. +        // +        if (c.annotated_p ()) +          s_.new_edge<Annotates> (c.annotation (), copy); + +        for (Compositor::ContainsIterator i (c.contains_begin ()); +             i != c.contains_end (); ++i) +        { +          Particle& p (i->particle ()); + +          if (p.is_a<Compositor> ()) +          { +            Compositor& c (dynamic_cast<Compositor&> (p)); +            Compositor& cc (clone_compositor (c, scope, pos)); + +            s_.new_edge<ContainsParticle> (copy, cc, i->min (), i->max ()); +          } +          else if (p.is_a<Element> ()) +          { +            Element& e (dynamic_cast<Element&> (p)); +            Element& ec (clone_element (e)); + +            s_.new_edge<ContainsParticle> (copy, ec, i->min (), i->max ()); + +            NodeArgs<Scope, Scope::NamesIterator> na (scope, pos); +            s_.new_edge<Names> (na, ec, e.name ()); +            ++pos; +          } +          else if (p.is_a<Any> ()) +          { +            Any& a (dynamic_cast<Any&> (p)); +            Any& ac ( +              s_.new_node<Any> (a.file (), a.line (), a.column (), +                                a.namespace_begin (), a.namespace_end ())); + +            ac.prototype (a); + +            s_.new_edge<ContainsParticle> (copy, ac, i->min (), i->max ()); + +            // Transfer annotation. +            // +            if (a.annotated_p ()) +              s_.new_edge<Annotates> (a.annotation (), ac); + +            // Any has no name so we have to come up with a fake one in +            // order to put it into the scope. Note that we cannot reuse +            // the name from the prototype. + +            UnsignedLong count; +            FrontendElements::Context& ctx (scope.context ()); + +            if (!ctx.count ("any-name-count")) +            { +              count = 0; +              ctx.set ("any-name-count", count); +            } +            else +              count = ++(ctx.get<UnsignedLong> ("any-name-count")); + +            std::basic_ostringstream<WideChar> os; +            os << "any #" << count; + +            NodeArgs<Scope, Scope::NamesIterator> na (scope, pos); +            s_.new_edge<Names> (na, ac, os.str ()); +            ++pos; +          } +          else +            assert (false); +        } + +        return copy; +      } + +      // Clone a fully-resolved element. Note that it cannot be used as +      // is to clone ref'ed element (default/fixed value, etc). +      // +      SemanticGraph::Element& +      clone_element (SemanticGraph::Element& e) +      { +        using SemanticGraph::Element; + +        Element& copy ( +        s_.new_node<Element> ( +          e.file (), e.line (), e.column (), e.global_p (), e.qualified_p ())); + +        if (e.qualified_p ()) +          s_.new_edge<BelongsToNamespace> (copy, e.namespace_ ()); + +        // Transfer default and fixed values. +        // +        if (e.fixed_p ()) +          copy.fixed (e.value ()); +        else if (e.default_p ()) +          copy.default_ (e.value ()); + +        if (copy.default_p ()) +        { +          copy.context ().set ( +            "dom-node", +            e.context ().get<Xerces::DOMElement*> ("dom-node")); +          default_values_.push_back (©); +        } + +        // Transfer annotation. +        // +        if (e.annotated_p ()) +          s_.new_edge<Annotates> (e.annotation (), copy); + +        // Belongs edge. +        // +        if (e.typed_p ()) +          s_.new_edge<Belongs> (copy, e.type ()); +        else +          assert (!valid_); + +        // Substitutes edge. +        // +        if (e.substitutes_p ()) +          s_.new_edge<Substitutes> (copy, e.substitutes ().root ()); + +        return copy; +      } + +      Void +      clone_attribute_group_content (AttributeGroupRef& ref, +                                     SemanticGraph::Scope& s) +      { +        using SemanticGraph::Scope; +        using SemanticGraph::Attribute; +        using SemanticGraph::AttributeGroup; + +        try +        { +          AttributeGroup& g ( +            resolve<AttributeGroup> (ref.ns_name, ref.uq_name, s_, cache_)); + +          // Make sure the group and all its content are fully resolved. +          // +          traverse (g); + +          Scope::NamesIterator pos (ref.names_pos); + +          for (Scope::NamesIterator i (g.names_begin ()); +               i != g.names_end (); ++i) +          { +            if (Attribute* p = dynamic_cast<Attribute*> (&i->named ())) +            { +              Attribute& a ( +                s_.new_node<Attribute> (p->file (), +                                        p->line (), +                                        p->column (), +                                        p->optional_p (), +                                        p->global_p (), +                                        p->qualified_p ())); + +              NodeArgs<Scope, Scope::NamesIterator> na (s, pos); +              s_.new_edge<Names> (na, a, p->name ()); +              ++pos; + +              if (p->qualified_p ()) +                s_.new_edge<BelongsToNamespace> (a, p->namespace_ ()); + +              // Transfer default and fixed values if any. +              // +              if (p->fixed_p ()) +                a.fixed (p->value ()); +              else if (p->default_p ()) +                a.default_ (p->value ()); + +              if (a.default_p ()) +              { +                a.context ().set ( +                  "dom-node", +                  p->context ().get<Xerces::DOMElement*> ("dom-node")); +                default_values_.push_back (&a); +              } + +              // Transfer annotation. +              // +              if (p->annotated_p ()) +                s_.new_edge<Annotates> (p->annotation (), a); + +              // Belongs edge. +              // +              if (p->typed_p ()) +                s_.new_edge<Belongs> (a, p->type ()); +              else +                assert (!valid_); +            } +            else if ( +              AnyAttribute* p = dynamic_cast<AnyAttribute*> (&i->named ())) +            { +              AnyAttribute& any ( +                s_.new_node<AnyAttribute> (p->file (), +                                           p->line (), +                                           p->column (), +                                           p->namespace_begin (), +                                           p->namespace_end ())); + +              any.prototype (*p); + +              // Transfer annotation. +              // +              if (p->annotated_p ()) +                s_.new_edge<Annotates> (p->annotation (), any); + +              // AnyAttribute has no name so we have to come up with a fake +              // one in order to put it into the scope. Note that we cannot +              // reuse the name from the attribute group. + +              UnsignedLong count; +              FrontendElements::Context& ctx (s.context ()); + +              if (!ctx.count ("any-attribute-name-count")) +              { +                count = 0; +                ctx.set ("any-attribute-name-count", count); +              } +              else +                count = ++(ctx.get<UnsignedLong> ("any-attribute-name-count")); + +              std::basic_ostringstream<WideChar> os; +              os << "any-attribute #" << count; + +              NodeArgs<Scope, Scope::NamesIterator> na (s, pos); +              s_.new_edge<Names> (na, any, os.str ()); +              ++pos; +            } +          } +        } +        catch (NotNamespace const& ex) +        { +          if (valid_) +          { +            wcerr << "ice: unable to resolve namespace '" << ex.ns () << "'" +                  << endl; +            abort (); +          } +        } +        catch (NotName const& ex) +        { +          if (valid_) +          { +            wcerr << "ice: unable to resolve attribute group name '" +                  << ex.name () << "' inside namespace '" << ex.ns () << "'" +                  << endl; +            abort (); +          } +        } +      } + +    private: +      Schema& s_; +      Boolean& valid_; +      NamespaceMap& cache_; +      DefaultValues& default_values_; + +    private: +      //Traversal::ContainsParticle contains_particle; +      Traversal::ContainsCompositor contains_compositor; +    }; +  } + +  // +  // +  struct FilePathComparator +  { +    Boolean +    operator () (SemanticGraph::Path const& x, +                 SemanticGraph::Path const& y) const +    { +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 +        return x.native_file_string () < y.native_file_string (); +#else +        return x.string () < y.string (); +#endif +    } +  }; + +  // Parser::Impl +  // + +  class Parser::Impl: public NonCopyable +  { +  public: +    ~Impl (); + +    Impl (Boolean proper_restriction, +          Boolean multiple_imports, +          Boolean full_schema_check, +          LocationTranslator*, +          const WarningSet*); + +    Evptr<Schema> +    parse (Path const&); + +    Evptr<Schema> +    parse (Paths const&); + +    Evptr<Schema> +    xml_schema (Path const&); + +  private: +    Void +    fill_xml_schema (Schema&, Path const&); + +  private: +    XML::AutoPtr<Xerces::DOMDocument> +    dom (SemanticGraph::Path const&, Boolean validate); + +    Void +    schema (XML::Element const&); + +    SemanticGraph::Annotation* +    annotation (Boolean process); + +    Void +    import (XML::Element const&); + +    Void +    include (XML::Element const&); + +    Void +    element_group (XML::Element const&, Boolean in_compositor); + +    SemanticGraph::Type* +    simple_type (XML::Element const&); + +    SemanticGraph::Type* +    list (XML::Element const& l, XML::Element const& type); + +    SemanticGraph::Type* +    union_ (XML::Element const& u, XML::Element const& type); + +    SemanticGraph::Type* +    restriction (XML::Element const& r, XML::Element const& type); + +    Void +    enumeration (XML::Element const&); + +    SemanticGraph::Type* +    complex_type (XML::Element const&); + +    All* +    all (XML::Element const&); + +    Choice* +    choice (XML::Element const&, Boolean in_compositor); + +    Sequence* +    sequence (XML::Element const&, Boolean in_compositor); + +    Void +    simple_content (XML::Element const&); + +    Void +    complex_content (XML::Element const&, Complex&); + +    Void +    simple_content_extension (XML::Element const&); + +    Void +    simple_content_restriction (XML::Element const&); + +    Void +    complex_content_extension (XML::Element const&, Complex&); + +    Void +    complex_content_restriction (XML::Element const&, Complex&); + +    Void +    element (XML::Element const&, Boolean global); + +    Void +    attribute (XML::Element const&, Boolean global); + +    Void +    attribute_group (XML::Element const&); + +    Void +    any (XML::Element const&); + +    Void +    any_attribute (XML::Element const&); + +  private: +    Boolean +    is_disabled (Char const* warning) +    { +      return disabled_warnings_all_ || +        (disabled_warnings_ && +         disabled_warnings_->find (warning) != disabled_warnings_->end ()); +    } + +  private: +    Boolean +    more () const +    { +      Iterator const& it (iteration_state_.top ()); + +      return it.l_->getLength () > it.i_; +    } + +    XML::Element +    next () +    { +      Iterator& it (iteration_state_.top ()); + +      return XML::Element ( +        dynamic_cast<Xerces::DOMElement*> (it.l_->item (it.i_++))); +    } + +    Void +    prev () +    { +      Iterator& it (iteration_state_.top ()); + +      if (it.i_) +        --it.i_; +    } + +    Void +    push (XML::Element const& e) +    { +      iteration_state_.push (e.dom_element ()); +    } + +    Void +    pop () +    { +      iteration_state_.pop (); +    } + +  private: +    Void +    push_scope (SemanticGraph::Scope& s) +    { +      scope_stack_.push (&s); +    } + +    Void +    pop_scope () +    { +      scope_stack_.pop (); +    } + +    SemanticGraph::Scope& +    scope () const +    { +      return *(scope_stack_.top ()); +    } + +  private: +    Void +    push_compositor (SemanticGraph::Compositor& c) +    { +      compositor_stack_.push (&c); +    } + +    Void +    pop_compositor () +    { +      assert (!compositor_stack_.empty ()); +      compositor_stack_.pop (); +    } + +    SemanticGraph::Compositor& +    compositor () const +    { +      assert (!compositor_stack_.empty ()); +      return *(compositor_stack_.top ()); +    } + +  private: +    UnsignedLong +    parse_min (String const& m) +    { +      if (m.empty ()) +        return 1; + +      UnsignedLong v; +      std::basic_istringstream<WideChar> is (m); + +      is >> v; +      return v; +    } + +    UnsignedLong +    parse_max (String const& m) +    { +      if (m.empty ()) +        return 1; + +      if (m == L"unbounded") +        return 0; + +      UnsignedLong v; +      std::basic_istringstream<WideChar> is (m); + +      is >> v; +      return v; +    } + +  private: +    SemanticGraph::Namespace& +    cur_ns () const +    { +      // Here I am using the fact that each Schema Names only one +      // Namespace. +      // +      return dynamic_cast<Namespace&> (cur_->names_begin ()->named ()); +    } + +  private: +    String +    unqualified_name (String const& n) +    { +      return XML::uq_name (n); +    } + +    String +    namespace_name (XML::Element const& e, String const& n) +    { +      try +      { +        String p (XML::prefix (n)); + +        // If we are currently handling a chameleon-included schema then +        // the empty prefix is logically translated into acquired target +        // namespace. +        // +        if (cur_chameleon_ && p.empty ()) +          return cur_ns ().name (); + +        // We have to try to resolve even the empty prefix since it can +        // be assigned to a namespace (which takes precedence over names +        // without a namespace). +        // +        return XML::ns_name (e.dom_element (), p); +      } +      catch (XML::NoMapping const& ex) +      { +        if (ex.prefix ().empty ()) +          return String (); +        else +          throw; +      } +    } + +    SemanticGraph::Type& +    ultimate_base (SemanticGraph::Type& t) +    { +      using namespace SemanticGraph; + +      Complex* c = dynamic_cast<Complex*> (&t); + +      if (c != 0 && c->inherits_p ()) +      { +        Type* b (&c->inherits ().base ()); + +        while (true) +        { +          Complex* cb (dynamic_cast<Complex*> (b)); + +          if (cb != 0 && cb->inherits_p ()) +          { +            b = &cb->inherits ().base (); +            continue; +          } + +          break; +        } + +        return *b; +      } +      else +        return t; +    } + +  private: +    template <typename Edge, typename Node> +    Edge* +    set_type (String const& type, XML::Element const& e, Node& node); + +  private: +    XML::PtrVector<Xerces::DOMDocument>* dom_docs_; + +    struct Iterator +    { +      Iterator (Xerces::DOMElement* e) +          : l_ (e->getChildNodes ()), i_ (0) +      { +      } + +      Xerces::DOMNodeList* l_; +      Size i_; +    }; + +    Cult::Containers::Stack<Iterator> iteration_state_; +    SemanticGraph::Schema* s_;   // root schema file +    SemanticGraph::Schema* cur_; // current schema file +    Boolean cur_chameleon_;      // whethere cur_ is chameleon + +    SemanticGraph::Schema* xml_schema_; // XML Schema file +    SemanticGraph::Path xml_schema_path_; + +    // +    // +    Cult::Containers::Stack<SemanticGraph::Scope*> scope_stack_; + +    // +    // +    Cult::Containers::Stack<SemanticGraph::Compositor*> compositor_stack_; + + +    // Map of absolute file path and namespace pair to a Schema node. +    // +    struct SchemaId +    { +      SchemaId (SemanticGraph::Path const& path, String const& ns) +          : path_ (path), ns_ (ns) +      { +      } + + +      friend Boolean +      operator< (SchemaId const& x, SchemaId const& y) +      { +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 +        return x.path_.native_file_string () < y.path_.native_file_string () +          || (x.path_.native_file_string () == y.path_.native_file_string () +              && x.ns_ < y.ns_); +#else +        return x.path_.string () < y.path_.string () +          || (x.path_.string () == y.path_.string () +              && x.ns_ < y.ns_); +#endif +      } + +    private: +      SemanticGraph::Path path_; +      String ns_; +    }; + + +    typedef +    Cult::Containers::Map<SchemaId, SemanticGraph::Schema*> +    SchemaMap; + +    SchemaMap schema_map_; + +    // Path stack for diagnostic. +    // +    Cult::Containers::Stack<SemanticGraph::Path> file_stack_; + +    SemanticGraph::Path const& +    file () +    { +      return file_stack_.top (); +    } + +    // Members with default/fixed values (needed for QName handling). +    // +    DefaultValues default_values_; + +  private: +    Boolean qualify_attribute_; +    Boolean qualify_element_; + +    Boolean valid_; + +    Boolean proper_restriction_; +    Boolean multiple_imports_; +    Boolean full_schema_check_; +    LocationTranslator* loc_translator_; +    const WarningSet* disabled_warnings_; +    Boolean disabled_warnings_all_; + +    NamespaceMap* cache_; +  }; + + +  Parser::Impl:: +  Impl (Boolean proper_restriction, +        Boolean multiple_imports, +        Boolean full_schema_check, +        LocationTranslator* t, +        const WarningSet* dw) +      : s_ (0), +        cur_ (0), +        cur_chameleon_ (false), +        xml_schema_path_ ("XMLSchema.xsd"), +        qualify_attribute_ (false), +        qualify_element_ (false), +        proper_restriction_ (proper_restriction), +        multiple_imports_ (multiple_imports), +        full_schema_check_ (full_schema_check), +        loc_translator_ (t), +        disabled_warnings_ (dw), +        disabled_warnings_all_ (false) +  { +    if (dw && dw->find ("all") != dw->end ()) +      disabled_warnings_all_ = true; + +    // Initialize the Xerces-C++ runtime. +    // +    Xerces::XMLPlatformUtils::Initialize (); +  } + +  Parser::Impl:: +  ~Impl () +  { +    // Terminate the Xerces-C++ runtime. +    // +    Xerces::XMLPlatformUtils::Terminate (); +  } + +  template<typename T> T& +  add_type (Schema& s, Namespace& ns, String name) +  { +    Path path ("XMLSchema.xsd"); +    T& node (s.new_node<T> (path, 0, 0)); +    s.new_edge<Names> (ns, node, name); + +    return node; +  } + +  Void Parser::Impl:: +  fill_xml_schema (Schema& s, Path const& path) +  { +    Namespace& ns (s.new_node<Namespace> (path, 1, 1)); +    s.new_edge<Names> (s, ns, xsd); + +    // anyType and & anySimpleType +    // +    AnyType& any_type ( +      add_type<AnyType>                       (s, ns, L"anyType")); +    add_type<AnySimpleType>                   (s, ns, L"anySimpleType"); + +    // Integers. +    // +    add_type<Fundamental::Byte>               (s, ns, L"byte"); +    add_type<Fundamental::UnsignedByte>       (s, ns, L"unsignedByte"); +    add_type<Fundamental::Short>              (s, ns, L"short"); +    add_type<Fundamental::UnsignedShort>      (s, ns, L"unsignedShort"); +    add_type<Fundamental::Int>                (s, ns, L"int"); +    add_type<Fundamental::UnsignedInt>        (s, ns, L"unsignedInt"); +    add_type<Fundamental::Long>               (s, ns, L"long"); +    add_type<Fundamental::UnsignedLong>       (s, ns, L"unsignedLong"); +    add_type<Fundamental::Integer>            (s, ns, L"integer"); +    add_type<Fundamental::NonPositiveInteger> (s, ns, L"nonPositiveInteger"); +    add_type<Fundamental::NonNegativeInteger> (s, ns, L"nonNegativeInteger"); +    add_type<Fundamental::PositiveInteger>    (s, ns, L"positiveInteger"); +    add_type<Fundamental::NegativeInteger>    (s, ns, L"negativeInteger"); + +    // Boolean. +    // +    add_type<Fundamental::Boolean>            (s, ns, L"boolean"); + +    // Floats. +    // +    add_type<Fundamental::Float>              (s, ns, L"float"); +    add_type<Fundamental::Double>             (s, ns, L"double"); +    add_type<Fundamental::Decimal>            (s, ns, L"decimal"); + +    // Strings +    // +    add_type<Fundamental::String>             (s, ns, L"string"); +    add_type<Fundamental::NormalizedString>   (s, ns, L"normalizedString"); +    add_type<Fundamental::Token>              (s, ns, L"token"); +    add_type<Fundamental::Name>               (s, ns, L"Name"); +    add_type<Fundamental::NameToken>          (s, ns, L"NMTOKEN"); +    add_type<Fundamental::NameTokens>         (s, ns, L"NMTOKENS"); +    add_type<Fundamental::NCName>             (s, ns, L"NCName"); +    add_type<Fundamental::Language>           (s, ns, L"language"); + +    // ID/IDREF. +    // +    add_type<Fundamental::Id>                 (s, ns, L"ID"); + +    Fundamental::IdRef& id_ref ( +      s.new_node<Fundamental::IdRef> (path, 0, 0)); +    s.new_edge<Names> (ns, id_ref, L"IDREF"); +    s.new_edge<Arguments> (any_type, id_ref); + +    Fundamental::IdRefs& id_refs ( +      s.new_node<Fundamental::IdRefs> (path, 0, 0)); +    s.new_edge<Names> (ns, id_refs, L"IDREFS"); +    s.new_edge<Arguments> (any_type, id_refs); + +    // URI. +    // +    add_type<Fundamental::AnyURI>             (s, ns, L"anyURI"); + +    // Qualified name. +    // +    add_type<Fundamental::QName>              (s, ns, L"QName"); + +    // Binary. +    // +    add_type<Fundamental::Base64Binary>       (s, ns, L"base64Binary"); +    add_type<Fundamental::HexBinary>          (s, ns, L"hexBinary"); + +    // Date/time. +    // +    add_type<Fundamental::Date>               (s, ns, L"date"); +    add_type<Fundamental::DateTime>           (s, ns, L"dateTime"); +    add_type<Fundamental::Duration>           (s, ns, L"duration"); +    add_type<Fundamental::Day>                (s, ns, L"gDay"); +    add_type<Fundamental::Month>              (s, ns, L"gMonth"); +    add_type<Fundamental::MonthDay>           (s, ns, L"gMonthDay"); +    add_type<Fundamental::Year>               (s, ns, L"gYear"); +    add_type<Fundamental::YearMonth>          (s, ns, L"gYearMonth"); +    add_type<Fundamental::Time>               (s, ns, L"time"); + +    // Entity. +    // +    add_type<Fundamental::Entity>             (s, ns, L"ENTITY"); +    add_type<Fundamental::Entities>           (s, ns, L"ENTITIES"); + +    // Notation. +    // +    add_type<Fundamental::Notation>           (s, ns, L"NOTATION"); +  } + + +  Evptr<Schema> Parser::Impl:: +  xml_schema (Path const& tu) +  { +    valid_ = true; + +    Evptr<Schema> rs (new Schema (tu, 1, 1)); +    fill_xml_schema (*rs, tu); + +    if (!valid_) +      throw InvalidSchema (); + +    return rs; +  } +  Evptr<Schema> Parser::Impl:: +  parse (Path const& tu) +  { +    valid_ = true; +    schema_map_.clear (); +    default_values_.clear (); + +    XML::PtrVector<Xerces::DOMDocument> dom_docs; +    dom_docs_ = &dom_docs; + +    NamespaceMap cache; +    cache_ = &cache; + +    XML::AutoPtr<Xerces::DOMDocument> d (dom (tu, true)); + +    if (!d) +      throw InvalidSchema (); + +    XML::Element root (d->getDocumentElement ()); +    String ns (root["targetNamespace"]); + +    if (trace_) +      wcout << "target namespace: " << ns << endl; + +    Evptr<Schema> rs (new Schema (tu, root.line (), root.column ())); + +    // Implied schema with fundamental types. +    // +    xml_schema_ = &rs->new_node<Schema> (xml_schema_path_, 1, 1); +    rs->new_edge<Implies> (*rs, *xml_schema_, xml_schema_path_); + +    fill_xml_schema (*xml_schema_, xml_schema_path_); + +    // Parse. +    // +    { +      // Enter the file into schema_map_. +      // +      Path abs_path (system_complete (tu)); +      abs_path.normalize (); +      schema_map_[SchemaId (abs_path, ns)] = rs.get (); +      rs->context ().set ("absolute-path", abs_path); + +      s_ = cur_ = rs.get (); +      { +        file_stack_.push (tu); + +        { +          push_scope ( +            s_->new_node<Namespace> ( +              file (), root.line (), root.column ())); +          s_->new_edge<Names> (*cur_, scope (), ns); + +          { +            schema (root); +          } + +          pop_scope (); +        } + +        file_stack_.pop (); +      } + +      s_ = cur_ = 0; +    } + +    dom_docs_->push_back (d); + +    // Second pass to resolve forward references to types, elements, +    // attributes and groups. +    // +    if (valid_) +    { +      Traversal::Schema schema; + +      struct Uses: Traversal::Uses +      { +        virtual Void +        traverse (Type& u) +        { +          Schema& s (u.schema ()); + +          if (!s.context ().count ("schema-resolved")) +          { +            s.context ().set ("schema-resolved", true); +            Traversal::Uses::traverse (u); +          } +        } +      } uses; + +      Traversal::Names schema_names; +      Traversal::Namespace ns; +      Traversal::Names ns_names; + +      schema >> uses >> schema; +      schema >> schema_names >> ns >> ns_names; + +      Resolver resolver (*rs, valid_, *cache_, default_values_); + +      struct AnonymousMember: Traversal::Attribute, +                              Traversal::Element, +                              Traversal::Member +      { +        AnonymousMember (Traversal::NodeDispatcherBase& d) +        { +          belongs_.node_traverser (d); +        } + +        virtual Void +        traverse (SemanticGraph::Attribute& a) +        { +          traverse_member (a); +        } + +        virtual Void +        traverse (SemanticGraph::Element& e) +        { +          traverse_member (e); +        } + +        Void +        traverse_member (SemanticGraph::Member& m) +        { +          if (m.typed_p () && +              !m.type ().named_p () && +              !m.type ().context ().count ("seen")) +          { +            m.type().context ().set ("seen", true); + +            Traversal::Member::belongs (m, belongs_); + +            m.type ().context ().remove ("seen"); +          } +        } + +      private: +        Traversal::Belongs belongs_; +      } anonymous_member (resolver); + +      struct AnonymousBase: Traversal::Type +      { +        AnonymousBase (Traversal::NodeDispatcherBase& d) +            : base_ (d) +        { +        } + +        virtual Void +        traverse (SemanticGraph::Type& t) +        { +          if (!t.named_p ()) +            base_.dispatch (t); +        } + +      private: +        Traversal::NodeDispatcherBase& base_; +      } anonymous_base (resolver); + +      ns_names >> resolver; +      ns_names >> anonymous_member; + +      Traversal::Names names; +      Traversal::Inherits inherits; +      Traversal::Argumented argumented; +      resolver >> names >> resolver; +      names >> anonymous_member; +      resolver >> inherits >> anonymous_base; +      resolver >> argumented >> anonymous_base; + +      if (trace_) +        wcout << "starting resolution pass" << endl; + +      schema.dispatch (*rs); +    } + +    // Resolve default/fixed values of QName type. +    // +    if (valid_) +    { +      for (DefaultValues::ConstIterator i (default_values_.begin ()), +             e (default_values_.end ()); i != e; ++i) +      { +        SemanticGraph::Member& m (**i); +        SemanticGraph::Type& t (m.type ()); +        SemanticGraph::Context& c (m.context ()); + +        if (ultimate_base (t).is_a<SemanticGraph::Fundamental::QName> ()) +        { +          String v (m.value ()); +          Xerces::DOMElement* e (c.get<Xerces::DOMElement*> ("dom-node")); + +          try +          { +            // We have to try to resolve even the empty prefix since it can +            // be assigned to a namespace (which takes precedence over names +            // without a namespace). +            // +            String ns (XML::ns_name (e, XML::prefix (v))); + +            if (m.fixed_p ()) +              m.fixed (ns + L'#' + v); +            else +              m.default_ (ns + L'#' + v); +          } +          catch (XML::NoMapping const& ex) +          { +            if (!ex.prefix ().empty ()) +            { +              wcerr << m.file () << ":" << m.line () << ":" << m.column () +                    << ": error: unable to resolve namespace for prefix '" +                    <<  ex.prefix () << "'" << endl; + +              valid_ = false; +            } +          } +        } + +        c.remove ("dom-node"); +      } +    } + +    if (!valid_) +      throw InvalidSchema (); + +    return rs; +  } + +  Evptr<Schema> Parser::Impl:: +  parse (Paths const& paths) +  { +    valid_ = true; +    schema_map_.clear (); +    default_values_.clear (); + +    XML::PtrVector<Xerces::DOMDocument> dom_docs; +    dom_docs_ = &dom_docs; + +    NamespaceMap cache; +    cache_ = &cache; + +    Evptr<Schema> rs (new Schema ("", 0, 0)); + +    // Implied schema with fundamental types. +    // +    xml_schema_ = &rs->new_node<Schema> (xml_schema_path_, 1, 1); +    rs->new_edge<Implies> (*rs, *xml_schema_, xml_schema_path_); + +    fill_xml_schema (*xml_schema_, xml_schema_path_); + +    // Parse individual schemas. +    // +    s_ = rs.get (); + +    for (Paths::ConstIterator i (paths.begin ()); i != paths.end (); ++i) +    { +      Path const& tu (*i); +      XML::AutoPtr<Xerces::DOMDocument> d (dom (tu, true)); + +      if (!d) +        throw InvalidSchema (); + +      XML::Element root (d->getDocumentElement ()); +      String ns (root["targetNamespace"]); + +      if (trace_) +        wcout << "target namespace: " << ns << endl; + +      // Check if we already have this schema. +      // +      Path abs_path (system_complete (tu)); +      abs_path.normalize (); +      SchemaId schema_id (abs_path, ns); + +      if (schema_map_.find (schema_id) != schema_map_.end ()) +        continue; + +      Schema& s (s_->new_node<Schema> (tu, root.line (), root.column ())); +      s_->new_edge<Implies> (s, *xml_schema_, xml_schema_path_); +      s_->new_edge<Imports> (*s_, s, tu); + +      // Enter the file into schema_map_. +      // +      schema_map_[schema_id] = &s; +      s.context ().set ("absolute-path", abs_path); + +      cur_ = &s; + +      { +        file_stack_.push (tu); + +        { +          push_scope ( +            s_->new_node<Namespace> ( +              file (), root.line (), root.column ())); +          s_->new_edge<Names> (*cur_, scope (), ns); + +          { +            schema (root); +          } + +          pop_scope (); +        } + +        file_stack_.pop (); +      } + +      cur_ = 0; + +      dom_docs_->push_back (d); + +      if (!valid_) +        break; +    } + +    s_ = 0; + +    // Second pass to resolve forward references to types, elements, +    // attributes and groups. +    // +    if (valid_) +    { +      Traversal::Schema schema; + +      struct Uses: Traversal::Uses +      { +        virtual Void +        traverse (Type& u) +        { +          Schema& s (u.schema ()); + +          if (!s.context ().count ("schema-resolved")) +          { +            s.context ().set ("schema-resolved", true); +            Traversal::Uses::traverse (u); +          } +        } +      } uses; + +      Traversal::Names schema_names; +      Traversal::Namespace ns; +      Traversal::Names ns_names; + +      schema >> uses >> schema; +      schema >> schema_names >> ns >> ns_names; + +      Resolver resolver (*rs, valid_, *cache_, default_values_); + +      struct AnonymousMember: Traversal::Attribute, +                              Traversal::Element, +                              Traversal::Member +      { +        AnonymousMember (Traversal::NodeDispatcherBase& d) +        { +          belongs_.node_traverser (d); +        } + +        virtual Void +        traverse (SemanticGraph::Attribute& a) +        { +          traverse_member (a); +        } + +        virtual Void +        traverse (SemanticGraph::Element& e) +        { +          traverse_member (e); +        } + +        virtual Void +        traverse_member (SemanticGraph::Member& m) +        { +          if (m.typed_p () && +              !m.type ().named_p () && +              !m.type ().context ().count ("seen")) +          { +            m.type().context ().set ("seen", true); + +            Traversal::Member::belongs (m, belongs_); + +            m.type ().context ().remove ("seen"); +          } +        } + +      private: +        Traversal::Belongs belongs_; +      } anonymous_member (resolver); + +      struct AnonymousBase: Traversal::Type +      { +        AnonymousBase (Traversal::NodeDispatcherBase& d) +            : base_ (d) +        { +        } + +        virtual Void +        traverse (SemanticGraph::Type& t) +        { +          if (!t.named_p ()) +            base_.dispatch (t); +        } + +      private: +        Traversal::NodeDispatcherBase& base_; +      } anonymous_base (resolver); + +      ns_names >> resolver; +      ns_names >> anonymous_member; + +      Traversal::Names names; +      Traversal::Inherits inherits; +      Traversal::Argumented argumented; +      resolver >> names >> resolver; +      names >> anonymous_member; +      resolver >> inherits >> anonymous_base; +      resolver >> argumented >> anonymous_base; + +      if (trace_) +        wcout << "starting resolution pass" << endl; + +      schema.dispatch (*rs); +    } + +    // Resolve default/fixed values of QName type. +    // +    if (valid_) +    { +      for (DefaultValues::ConstIterator i (default_values_.begin ()), +             e (default_values_.end ()); i != e; ++i) +      { +        SemanticGraph::Member& m (**i); +        SemanticGraph::Type& t (m.type ()); +        SemanticGraph::Context& c (m.context ()); + +        if (ultimate_base (t).is_a<SemanticGraph::Fundamental::QName> ()) +        { +          String v (m.value ()); +          Xerces::DOMElement* e (c.get<Xerces::DOMElement*> ("dom-node")); + +          try +          { +            // We have to try to resolve even the empty prefix since it can +            // be assigned to a namespace (which takes precedence over names +            // without a namespace). +            // +            String ns (XML::ns_name (e, XML::prefix (v))); + +            if (m.fixed_p ()) +              m.fixed (ns + L'#' + v); +            else +              m.default_ (ns + L'#' + v); +          } +          catch (XML::NoMapping const& ex) +          { +            if (!ex.prefix ().empty ()) +            { +              wcerr << m.file () << ":" << m.line () << ":" << m.column () +                    << ": error: unable to resolve namespace for prefix '" +                    <<  ex.prefix () << "'" << endl; + +              valid_ = false; +            } +          } +        } + +        c.remove ("dom-node"); +      } +    } + +    if (!valid_) +      throw InvalidSchema (); + +    return rs; +  } + +  Void Parser::Impl:: +  schema (XML::Element const& s) +  { +    Boolean old_qa (qualify_attribute_); +    Boolean old_qe (qualify_element_); + +    if (String af = s["attributeFormDefault"]) +      qualify_attribute_ = af == L"qualified"; + +    if (String ef = s["elementFormDefault"]) +      qualify_element_ = ef == L"qualified"; + +    push (s); + +    // Parse leading annotation if any and add it as an annotation for +    // this schema. +    // +    if (Annotation* a = annotation (true)) +      s_->new_edge<Annotates> (*a, *cur_); + +    while (more ()) +    { +      XML::Element e (next ()); +      String name (e.name ()); + +      if (trace_) +        wcout << name << endl; + +      if (name == L"import")         import (e);               else +      if (name == L"include")        include (e);              else +      if (name == L"element")        element (e, true);        else +      if (name == L"attribute")      attribute (e, true);      else +      if (name == L"simpleType")     simple_type (e);          else +      if (name == L"annotation");                              else +      if (name == L"complexType")    complex_type (e);         else +      if (name == L"group")          element_group (e, false); else +      if (name == L"attributeGroup") attribute_group (e);      else +      { +        wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +              << "error: unexpected top-level element: '" << name << "'" +              << endl; + +        valid_ = false; +      } +    } + +    pop (); + +    qualify_attribute_ = old_qa; +    qualify_element_ = old_qe; +  } + +  Void Parser::Impl:: +  import (XML::Element const& i) +  { +    NarrowString loc ( +      XML::transcode_to_narrow ( +        i.dom_element ()->getAttribute ( +          XML::XMLChString ("schemaLocation").c_str ()))); + +    if (loc_translator_) +      loc = loc_translator_->translate (loc); + +    // Ignore empty <import>. +    // +    if (!loc && !i["namespace"]) +      return; + +    Path path, rel_path, abs_path; +    try +    { +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 +      try +      { +        path = Path (loc); +      } +      catch (InvalidPath const&) +      { +        // Retry as a native path. +        // +        path = Path (loc, boost::filesystem::native); +      } +#else +      // The new ABI does not have a fallback native representation +      path = Path (loc.c_str()); +#endif + +      if (path.is_complete ()) +      { +        abs_path = rel_path = path; +      } +      else +      { +        rel_path = file ().branch_path () / path; +        abs_path = system_complete (rel_path); +      } + +      abs_path.normalize (); +    } +    catch (InvalidPath const&) +    { +      wcerr << file () << ":" << i.line () << ":" << i.column () << ": " +            << "error: '" << loc.c_str () << "' is not a valid " +            << "filesystem path" << endl; + +      valid_ = false; +      return; +    } + +    SchemaId schema_id (abs_path, i["namespace"]); + +    if (schema_map_.find (schema_id) != schema_map_.end ()) +    { +      s_->new_edge<Imports> (*cur_, *schema_map_[schema_id], path); +      return; +    } + +    if (trace_) +      wcout << "importing " << rel_path << endl; + +    if (XML::AutoPtr<Xerces::DOMDocument> d  = dom (abs_path, false)) +    { +      XML::Element r (d->getDocumentElement ()); +      String ns (r["targetNamespace"]); + +      if (trace_) +        wcout << "target namespace: " << ns << endl; + +      Schema& s (s_->new_node<Schema> (rel_path, r.line (), r.column ())); +      s_->new_edge<Implies> (s, *xml_schema_, xml_schema_path_); +      s_->new_edge<Imports> (*cur_, s, path); + +      schema_map_[schema_id] = &s; +      s.context ().set ("absolute-path", abs_path); + +      Schema* old_cur (cur_); +      Boolean old_cur_chameleon (cur_chameleon_); +      cur_ = &s; +      cur_chameleon_ = false; + +      { +        file_stack_.push (rel_path); + +        { +          push_scope ( +            s_->new_node<Namespace> (file (), r.line (), r.column ())); +          s_->new_edge<Names> (*cur_, scope (), ns); + +          { +            schema (r); +          } + +          pop_scope (); +        } + +        file_stack_.pop (); +      } + +      cur_chameleon_ = old_cur_chameleon; +      cur_ = old_cur; + +      dom_docs_->push_back (d); +    } +  } + +  Void Parser::Impl:: +  include (XML::Element const& i) +  { +    NarrowString loc ( +      XML::transcode_to_narrow ( +        i.dom_element ()->getAttribute ( +          XML::XMLChString ("schemaLocation").c_str ()))); + +    if (loc_translator_) +      loc = loc_translator_->translate (loc); + +    Path path, rel_path, abs_path; +    try +    { +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 +      try +      { +        path = Path (loc); +      } +      catch (InvalidPath const&) +      { +        // Retry as a native path. +        // +        path = Path (loc, boost::filesystem::native); +      } +#else +      // The new API does not have a fallback native representation. +      path = Path (loc.c_str()); +#endif + +      if (path.is_complete ()) +      { +        abs_path = rel_path = path; +      } +      else +      { +        rel_path = file ().branch_path () / path; +        abs_path = system_complete (rel_path); +      } + +      abs_path.normalize (); +    } +    catch (InvalidPath const&) +    { +      wcerr << file () << ":" << i.line () << ":" << i.column () << ": " +            << "error: '" << loc.c_str () << "' is not a valid " +            << "filesystem path" << endl; + +      valid_ = false; +      return; +    } + +    // Included schema should have the same namespace as ours. +    // +    SchemaId schema_id (abs_path, cur_ns ().name ()); + +    if (schema_map_.find (schema_id) != schema_map_.end ()) +    { +      Schema& s (*schema_map_[schema_id]); + +      // Chemeleon inclusion results in a new Schema node for every +      // namespace. As a result, such a Schema node can only be +      // Source'ed. I use this property to decide which edge to use. +      // + +      if (s.used_p () && s.used_begin ()->is_a<Sources> ()) +        s_->new_edge<Sources> (*cur_, s, path); +      else +        s_->new_edge<Includes> (*cur_, s, path); + +      return; +    } + +    if (trace_) +      wcout << "including " << rel_path << endl; + +    if (XML::AutoPtr<Xerces::DOMDocument> d  = dom (abs_path, false)) +    { +      XML::Element r (d->getDocumentElement ()); +      String ns (r["targetNamespace"]), cur_ns; + +      Schema& s (s_->new_node<Schema> (rel_path, r.line (), r.column ())); +      s_->new_edge<Implies> (s, *xml_schema_, xml_schema_path_); + +      schema_map_[schema_id] = &s; +      s.context ().set ("absolute-path", abs_path); + +      Boolean chameleon (false); + +      if (ns.empty () && !(cur_ns = (cur_->names_begin ())->name ()).empty ()) +      { +        // Chameleon. +        // +        ns = cur_ns; +        s_->new_edge<Sources> (*cur_, s, path); +        chameleon = true; + +        if (trace_) +          wcout << "handling chameleon schema" << endl; +      } +      else +        s_->new_edge<Includes> (*cur_, s, path); + +      if (trace_) +        wcout << "target namespace: " << ns << endl; + +      Schema* old_cur (cur_); +      Boolean old_cur_chameleon (cur_chameleon_); +      cur_ = &s; +      cur_chameleon_ = chameleon; + +      { +        file_stack_.push (rel_path); + +        { +          push_scope ( +            s_->new_node<Namespace> (file (), r.line (), r.column ())); +          s_->new_edge<Names> (*cur_, scope (), ns); + +          { +            schema (r); +          } + +          pop_scope (); +        } + +        file_stack_.pop (); +      } + +      cur_chameleon_ = old_cur_chameleon; +      cur_ = old_cur; + +      dom_docs_->push_back (d); +    } +  } + +  Void Parser::Impl:: +  element_group (XML::Element const& g, Boolean in_compositor) +  { +    if (String name = g["name"]) +    { +      ElementGroup& group ( +        s_->new_node<ElementGroup> (file (), g.line (), g.column ())); + +      s_->new_edge<Names> (scope (), group, name); + +      push_scope (group); +      push (g); + +      annotation (false); + +      XML::Element e (next ()); + +      name = e.name (); + +      if (trace_) +        wcout << name << endl; + +      Compositor* c (0); + +      if (name == L"all")      c = all (e);             else +      if (name == L"choice")   c = choice (e, false);   else +      if (name == L"sequence") c = sequence (e, false); else +      { +        wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +              << "error: expected 'all', 'choice' or 'sequence' " +              << "instead of '" << name << "'" << endl; + +        valid_ = false; +      } + +      // Group's immediate compositor always has cardinality 1,1. +      // +      if (c) +        s_->new_edge<ContainsCompositor> (group, *c, 1, 1); + +      pop (); +      pop_scope (); +    } +    else if (String ref = g["ref"]) +    { +      if (trace_) +        wcout << "element-group-ref " << ref << endl; + +      try +      { +        String uq_name (unqualified_name (ref)); +        String ns_name (namespace_name (g, ref)); + +        // In order to avoid code duplication we are going to let the +        // resolver handle this case. +        // +        if (trace_) +          wcout << "deferring resolution of group name '" << uq_name +                << "' inside namespace '" << ns_name << "'" +                << " until later" << endl; + +        if (in_compositor) +        { +          Compositor& c (compositor ()); + +          ElementGroupRef ref ( +            uq_name, ns_name, +            parse_min (g["minOccurs"]), parse_max (g["maxOccurs"]), +            c, scope ()); + +          if (!c.context ().count ("element-group-refs")) +            c.context ().set ("element-group-refs", ElementGroupRefs ()); + +          c.context ().get<ElementGroupRefs> ( +            "element-group-refs").push_back (ref); +        } +        else +        { +          // This is a group-ref directly in complexType. +          // + +          Scope& s (scope ()); + +          ElementGroupRef ref ( +            uq_name, ns_name, +            parse_min (g["minOccurs"]), parse_max (g["maxOccurs"]), +            s); + +          s.context ().set ("element-group-ref", ref); +        } +      } +      catch (NotNamespace const& ex) +      { +        if (valid_) +        { +          wcerr << file () << ":" << g.line () << ":" << g.column () << ": " +                << "ice: unable to resolve namespace '" << ex.ns () << "'" +                << endl; + +          abort (); +        } +      } +      catch (XML::NoMapping const& ex) +      { +        wcerr << file () << ":" << g.line () << ":" << g.column () << ": " +              << "error: unable to resolve namespace prefix '" << ex.prefix () +              << "' in '" << ref << "'" << endl; + +        valid_ = false; +      } +    } +    else +    { +      wcerr << file () << ":" << g.line () << ":" << g.column () << ": " +            << "error: 'name' or 'ref' attribute is missing in group " +            << "declaration" << endl; + +      valid_ = false; + +      return; +    } +  } + +  //@@ Need RAII for push/pop. +  // + +  Type* Parser::Impl:: +  simple_type (XML::Element const& t) +  { +    Type* r (0); + +    push (t); + +    Annotation* a (annotation (true)); + +    XML::Element e (next ()); + +    String name (e.name ()); + +    if (name == L"list") r = list (e, t); else +    if (name == L"union") r = union_ (e, t); else +    if (name == L"restriction") r = restriction (e, t); else +    { +      wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +            << "error: expected 'list', 'union', or 'restriction' " +            << "instead of '" << name << "'" << endl; + +      valid_ = false; +    } + +    if (r != 0 && a != 0) +      s_->new_edge<Annotates> (*a, *r); + +    pop (); + +    return r; +  } + +  SemanticGraph::Type* Parser::Impl:: +  list (XML::Element const& l, XML::Element const& t) +  { +    if (trace_) +      wcout << "list" << endl; + +    List& node (s_->new_node<List> (file (), t.line (), t.column ())); + +    if (String item_type = l["itemType"]) +    { +      if (trace_) +        wcout << "item type: " << fq_name (l, item_type) << endl; + +      set_type<Arguments> (item_type, l, node); +    } +    else +    { +      // Anonymous list item type. +      // +      push (l); + +      annotation (false); + +      if (more ()) +      { +        XML::Element e (next ()); + +        String name (e.name ()); + +        if (trace_) +          wcout << name << endl; + +        Type* t (0); + +        if (name == L"simpleType")  t = simple_type (e);  else +        { +          wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +                << "error: expected 'simpleType' instead of " +                << "'" << e.name () << "'" << endl; + +          valid_ = false; +        } + +        if (t) +          s_->new_edge<Arguments> (*t, node); +      } +      else +      { +        wcerr << file () << ":" << l.line () << ":" << l.column () << ": " +              << "error: expected 'itemType' attribute or 'simpleType' " +              << "nested element" << endl; + +        valid_ = false; +      } + +      pop (); +    } + +    if (String name = t["name"]) +      s_->new_edge<Names> (scope (), node, name); + +    return &node; +  } + +  namespace +  { +    // +    // List parsing utility functions. +    // + +    // Find first non-space character. +    // +    Size +    find_ns (const WideChar* s, Size size, Size pos) +    { +      while (pos < size && +             (s[pos] == 0x20 || // space +              s[pos] == 0x0D || // carriage return +              s[pos] == 0x09 || // tab +              s[pos] == 0x0A)) +        ++pos; + +      return pos < size ? pos : String::npos; +    } + +    // Find first space character. +    // +    Size +    find_s (const WideChar* s, Size size, Size pos) +    { +      while (pos < size && +             s[pos] != 0x20 && // space +             s[pos] != 0x0D && // carriage return +             s[pos] != 0x09 && // tab +             s[pos] != 0x0A) +        ++pos; + +      return pos < size ? pos : String::npos; +    } +  } + +  SemanticGraph::Type* Parser::Impl:: +  union_ (XML::Element const& u, XML::Element const& t) +  { +    if (trace_) +      wcout << "union" << endl; + +    Union& node (s_->new_node<Union> (file (), t.line (), t.column ())); + +    Boolean has_members (false); + +    if (String members = u["memberTypes"]) +    { +      // Don't bother trying to resolve member types at this point +      // since the order is important so we would have to insert +      // the late resolutions into specific places. It is simpler +      // to just do the whole resolution later. +      // +      const WideChar* data (members.c_str ()); +      Size size (members.size ()); + +      UnionMemberTypes* m (0); + +      // Traverse the type list while logically collapsing spaces. +      // +      for (Size i (find_ns (data, size, 0)); i != String::npos;) +      { +        String s; +        Size j (find_s (data, size, i)); + +        if (j != String::npos) +        { +          s = String (data + i, j - i); +          i = find_ns (data, size, j); +        } +        else +        { +          // Last item. +          // +          s = String (data + i, size - i); +          i = String::npos; +        } + +        if (trace_) +          wcout << "member type: " << fq_name (u, s) << endl; + +        if (m == 0) +        { +          node.context ().set ("union-member-types", UnionMemberTypes ()); +          m = &node.context ().get<UnionMemberTypes> ("union-member-types"); +        } + +        try +        { +          m->push_back ( +            UnionMemberType ( +              namespace_name (u, s), unqualified_name (s))); +        } +        catch (XML::NoMapping const& ex) +        { +          wcerr << file () << ":" << u.line () << ":" << u.column () << ": " +                << "error: unable to resolve namespace prefix " +                << "'" << ex.prefix () << "' in '" << s << "'" << endl; + +          valid_ = false; +        } +      } + +      has_members = (m != 0); +    } + +    // Handle anonymous members. +    // +    push (u); + +    annotation (false); + +    while (more ()) +    { +      XML::Element e (next ()); +      String name (e.name ()); + +      if (trace_) +        wcout << name << endl; + +      Type* t (0); + +      if (name == L"simpleType")  t = simple_type (e);  else +      { +        wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +              << "error: expected 'simpleType' instead of " +              << "'" << e.name () << "'" << endl; + +        valid_ = false; +      } + +      if (t) +        s_->new_edge<Arguments> (*t, node); +    } + +    pop (); + +    if (node.argumented_begin () == node.argumented_end () && !has_members) +    { +      wcerr << file () << ":" << u.line () << ":" << u.column () << ": " +            << "error: expected 'memberTypes' attribute or 'simpleType' " +            << "nested element" << endl; + +      valid_ = false; +    } + +    if (String name = t["name"]) +      s_->new_edge<Names> (scope (), node, name); + +    return &node; +  } + +  Type* Parser::Impl:: +  restriction (XML::Element const& r, XML::Element const& t) +  { +    String base (r["base"]); +    Type* base_type (0); + +    if (base) +    { +      if (trace_) +        wcout << "restriction base: " << fq_name (r, base) << endl; +    } + +    Type* rv (0); + +    push (r); + +    annotation (false); + +    Boolean enum_ (false); + +    if (!base) +    { +      // Anonymous base type. +      // +      if (more ()) +      { +        XML::Element e (next ()); + +        String name (e.name ()); + +        if (trace_) +          wcout << name << endl; + +        if (name == L"simpleType")  base_type = simple_type (e); else +        { +          wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +                << "error: expected 'simpleType' instead of " +                << "'" << e.name () << "'" << endl; + +          valid_ = false; +        } +      } +      else +      { +        wcerr << file () << ":" << r.line () << ":" << r.column () << ": " +              << "error: expected 'base' attribute or 'simpleType' " +              << "nested element" << endl; + +        valid_ = false; +      } + +      if (!valid_) +      { +        pop (); +        return 0; +      } +    } + +    Facets facets; +    Restricts* restricts (0); + +    while (more ()) +    { +      XML::Element e (next ()); +      String name (e.name ()); + +      if (name == L"enumeration") +      { +        // Enumeration +        // +        if (enum_) +          enumeration (e); +        else +        { +          // First +          // +          enum_ = true; + +          Enumeration& node ( +            s_->new_node<Enumeration> (file (), t.line (), t.column ())); + +          if (base_type) +            restricts = &s_->new_edge<Restricts> (node, *base_type); +          else +            restricts = set_type<Restricts> (base, r, node); + +          if (String name = t["name"]) +            s_->new_edge<Names> (scope (), static_cast<Nameable&> (node), name); + +          rv = &node; +          push_scope (node); +          enumeration (e); +        } +      } +      else if (name == L"minExclusive" || +               name == L"minInclusive" || +               name == L"maxExclusive" || +               name == L"maxInclusive" || +               name == L"totalDigits" || +               name == L"fractionDigits" || +               name == L"length" || +               name == L"minLength" || +               name == L"maxLength" || +               name == L"whiteSpace" || +               name == L"pattern") +      { +        facets[name] = e["value"]; +      } +      else +      { +        wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +              << "error: unexpected element '" << name << "' in " +              << "simple type restriction" << endl; + +        valid_ = false; +      } +    } + +    if (enum_) +      pop_scope (); +    else +    { +      Complex& node (s_->new_node<Complex> (file (), t.line (), t.column ())); + +      if (base_type) +        restricts = &s_->new_edge<Restricts> (node, *base_type); +      else +        restricts = set_type<Restricts> (base, r, node); + +      if (String name = t["name"]) +        s_->new_edge<Names> (scope (), node, name); + +      rv = &node; +    } + +    if (!facets.empty ()) +    { +      if (restricts) +        copy_facets (*restricts, facets); +      else +        rv->context ().set ("facets", facets); +    } + +    pop (); + +    return rv; +  } + +  Void Parser::Impl:: +  enumeration (XML::Element const& e) +  { +    String value (e["value"]); + +    if (trace_) +      wcout << "enumeration value: " << value << endl; + +    push (e); +    Annotation* a (annotation (true)); +    pop (); + +    Enumerator& node ( +      s_->new_node<Enumerator> (file (), e.line (), e.column ())); + +    s_->new_edge<Names> (scope (), node, value); +    s_->new_edge<Belongs> (node, dynamic_cast<Type&>(scope ())); + +    if (a != 0) +      s_->new_edge<Annotates> (*a, node); + +  } + +  Type* Parser::Impl:: +  complex_type (XML::Element const& t) +  { +    Type* r (0); + +    Complex& node (s_->new_node<Complex> (file (), t.line (), t.column ())); + +    node.mixed_p (t["mixed"] == L"true" || t["mixed"] == L"1"); + +    if (String name = t["name"]) +      s_->new_edge<Names> (scope (), node, name); + +    r = &node; + +    push_scope (node); +    push (t); + +    if (Annotation* a = annotation (true)) +      s_->new_edge<Annotates> (*a, node); + +    if (more ()) +    { +      XML::Element e (next ()); + +      String name (e.name ()); + +      if (trace_) +        wcout << name << endl; + +      if (name == L"simpleContent")  simple_content (e);        else +      if (name == L"complexContent") complex_content (e, node); else +      { +        Compositor* c (0); + +        if (name == L"all")            c = all (e);              else +        if (name == L"choice")         c = choice (e, false);    else +        if (name == L"sequence")       c = sequence (e, false);  else +        if (name == L"attribute")      attribute (e, false);     else +        if (name == L"anyAttribute")   any_attribute (e);        else +        if (name == L"group")          element_group (e, false); else +        if (name == L"attributeGroup") attribute_group (e);      else +        { +          wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +                << "error: unexpected element '" << name << "'" << endl; + +          valid_ = false; +        } + +        if (c) +          s_->new_edge<ContainsCompositor> ( +            node, *c, parse_min (e["minOccurs"]), parse_max (e["maxOccurs"])); + +        while (more ()) +        { +          XML::Element e (next ()); +          String name (e.name ()); + +          if (name == L"attribute")      attribute (e, false); else +          if (name == L"anyAttribute")   any_attribute (e);    else +          if (name == L"attributeGroup") attribute_group (e);  else +          { +            wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +                  << "error: expected 'attribute', 'anyAttribute', or " +                  << "'attributeGroup' instead of '" << name << "'" << endl; + +            valid_ = false; +          } +        } +      } +    } + +    pop (); +    pop_scope (); + +    return r; +  } + +  All* Parser::Impl:: +  all (XML::Element const& a) +  { +    // 'all' cannot be nested inside 'choice' or 'sequence', nor +    //  can it contain any of those. The only valid  cardinality +    //  values for 'all' are min=0,1 and max=1. +    // +    All& node (s_->new_node<All> (file (), a.line (), a.column ())); + +    push_compositor (node); +    push (a); + +    if (Annotation* a = annotation (true)) +      s_->new_edge<Annotates> (*a, node); + +    while (more ()) +    { +      XML::Element e (next ()); + +      String name (e.name ()); + +      if (name == L"element") element (e, false); else +      { +        wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +              << "error: expected 'element' " +              << "instead of '" << name << "'" << endl; + +        valid_ = false; +      } +    } + +    pop (); +    pop_compositor (); + +    return &node; +  } + +  Choice* Parser::Impl:: +  choice (XML::Element const& c, Boolean in_compositor) +  { +    Choice& node (s_->new_node<Choice> (file (), c.line (), c.column ())); + +    if (in_compositor) +    { +      s_->new_edge<ContainsParticle> ( +        compositor (), node, +        parse_min (c["minOccurs"]), parse_max (c["maxOccurs"])); +    } + +    push_compositor (node); +    push (c); + +    if (Annotation* a = annotation (true)) +      s_->new_edge<Annotates> (*a, node); + +    while (more ()) +    { +      XML::Element e (next ()); + +      String name (e.name ()); + +      if (name == L"any")      any (e);                 else +      if (name == L"choice")   choice (e, true);        else +      if (name == L"element")  element (e, false);      else +      if (name == L"sequence") sequence (e, true);      else +      if (name == L"group")    element_group (e, true); else +      { +        wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +              << "error: expected 'any', 'group', 'choice', 'sequence', " +              << "or 'element' instead of '" << name << "'" << endl; + +        valid_ = false; +      } +    } + +    pop (); +    pop_compositor (); + +    return &node; +  } + +  Sequence* Parser::Impl:: +  sequence (XML::Element const& s, Boolean in_compositor) +  { +    Sequence& node (s_->new_node<Sequence> (file (), s.line (), s.column ())); + +    if (in_compositor) +    { +      s_->new_edge<ContainsParticle> ( +        compositor (), node, +        parse_min (s["minOccurs"]), parse_max (s["maxOccurs"])); +    } + +    push_compositor (node); +    push (s); + +    if (Annotation* a = annotation (true)) +      s_->new_edge<Annotates> (*a, node); + +    while (more ()) +    { +      XML::Element e (next ()); + +      String name (e.name ()); + +      if (name == L"any")      any (e);                 else +      if (name == L"choice")   choice (e, true);        else +      if (name == L"element")  element (e, false);      else +      if (name == L"sequence") sequence (e, true);      else +      if (name == L"group")    element_group (e, true); else +      { +        wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +              << "error: expected 'any', 'group', 'choice', 'sequence', " +              << "or 'element' instead of '" << name << "'" << endl; + +        valid_ = false; +      } +    } + +    pop (); +    pop_compositor (); + +    return &node; +  } + +  Void Parser::Impl:: +  simple_content (XML::Element const& c) +  { +    push (c); + +    annotation (false); + +    XML::Element e (next ()); +    String name (e.name ()); + +    if (name == L"extension")   simple_content_extension (e);   else +    if (name == L"restriction") simple_content_restriction (e); else +    { +      wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +            << "error: expected 'extension' or 'restriction' instead of " +            << "'" << name << "'" << endl; + +      valid_ = false; +    } + +    pop (); +  } + +  Void Parser::Impl:: +  complex_content (XML::Element const& c, Complex& type) +  { +    if (c.attribute_p ("mixed")) +    { +      type.mixed_p (c["mixed"] == L"true" || c["mixed"] == L"1"); +    } + +    push (c); + +    annotation (false); + +    XML::Element e (next ()); +    String name (e.name ()); + +    if (name == L"extension")   complex_content_extension (e, type);   else +    if (name == L"restriction") complex_content_restriction (e, type); else +    { +      wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +            << "error: expected 'extension' or 'restriction' instead of " +            << "'" << name << "'" << endl; + +      valid_ = false; +    } + +    pop (); +  } + +  Void Parser::Impl:: +  simple_content_extension (XML::Element const& e) +  { +    if (trace_) +      wcout << "extension base: " << fq_name (e, e["base"]) << endl; + +    set_type<Extends> (e["base"], e, dynamic_cast<Complex&> (scope ())); + +    push (e); + +    annotation (false); + +    while (more ()) +    { +      XML::Element e (next ()); +      String name (e.name ()); + +      if (name == L"attribute")      attribute (e, false); else +      if (name == L"anyAttribute")   any_attribute (e);    else +      if (name == L"attributeGroup") attribute_group (e);  else +      { +        wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +              << "error: expected 'attribute', 'anyAttribute', or " +              << "'attributeGroup' instead of '" << name << "'" << endl; + +        valid_ = false; +      } +    } + +    pop (); +  } + +  Void Parser::Impl:: +  simple_content_restriction (XML::Element const& r) +  { +    String base (r["base"]); +    Type* base_type (0); + +    if (trace_ && base) +      wcout << "restriction base: " << fq_name (r, base) << endl; + +    push (r); +    annotation (false); + +    if (!base) +    { +      // Anonymous base type. +      // +      if (more ()) +      { +        XML::Element e (next ()); +        String name (e.name ()); + +        if (trace_) +          wcout << name << endl; + +        if (name == L"simpleType")  base_type = simple_type (e); else +        { +          wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +                << "error: expected 'simpleType' instead of " +                << "'" << e.name () << "'" << endl; + +          valid_ = false; +        } +      } +      else +      { +        wcerr << file () << ":" << r.line () << ":" << r.column () << ": " +              << "error: expected 'base' attribute or 'simpleType' " +              << "nested element" << endl; + +        valid_ = false; +      } + +      if (!valid_) +      { +        pop (); +        return; +      } +    } + +    Facets facets; + +    while (more ()) +    { +      XML::Element e (next ()); +      String name (e.name ()); + +      if (name == L"simpleType") +      { +        // This is a "superimposed" restriction where the base +        // content is restricted by specifying another simple +        // type. The attributes are restricted in the ussual +        // way. So in effect we have kind of two base classes. +        // I guess the way to handle this one day would be to +        // copy all the facets from the base-to-this-type +        // part of the hierarchy (will need to "know" facets +        // for the built-in type restrictions as well). For +        // now just ignore it. +        // +      } +      else if (name == L"enumeration") +      { +        // Right now our sementic graph cannot represent enumerations +        // with attributes so we are going to ignore enumerators for +        // now. +        // +      } +      else if (name == L"minExclusive" || +               name == L"minInclusive" || +               name == L"maxExclusive" || +               name == L"maxInclusive" || +               name == L"totalDigits" || +               name == L"fractionDigits" || +               name == L"length" || +               name == L"minLength" || +               name == L"maxLength" || +               name == L"whiteSpace" || +               name == L"pattern") +      { +        facets[name] = e["value"]; +      } +      else if (name == L"attribute") +      { +        if (proper_restriction_) +          attribute (e, false); +      } +      else if (name == L"anyAttribute") +      { +        if (proper_restriction_) +          any_attribute (e); +      } +      else if (name == L"attributeGroup") +      { +        if (proper_restriction_) +          attribute_group (e); +      } +      else +      { +        wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +              << "error: unexpected element '" << name << "' in " +              << "simple content restriction" << endl; + +        valid_ = false; +      } +    } + +    Complex& type (dynamic_cast<Complex&> (scope ())); +    Restricts* restricts = set_type<Restricts> (base, r, type); + +    if (!facets.empty ()) +    { +      if (restricts) +        copy_facets (*restricts, facets); +      else +        type.context ().set ("facets", facets); +    } + +    pop (); +  } + +  Void Parser::Impl:: +  complex_content_extension (XML::Element const& e, Complex& type) +  { +    if (trace_) +      wcout << "extension base: " << fq_name (e, e["base"]) << endl; + +    set_type<Extends> (e["base"], e, dynamic_cast<Complex&> (scope ())); + +    push (e); + +    annotation (false); + +    if (more ()) +    { +      XML::Element e (next ()); +      String name (e.name ()); +      Compositor* c (0); + +      if (name == L"all")            c = all (e);              else +      if (name == L"choice")         c = choice (e, false);    else +      if (name == L"sequence")       c = sequence (e, false);  else +      if (name == L"attribute")      attribute (e, false);     else +      if (name == L"anyAttribute")   any_attribute (e);        else +      if (name == L"group")          element_group (e, false); else +      if (name == L"attributeGroup") attribute_group (e);      else +      { +        wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +              << "error: unexpected element '" << name << "'" << endl; + +        valid_ = false; +      } + +      if (c) +        s_->new_edge<ContainsCompositor> ( +          type, *c, parse_min (e["minOccurs"]), parse_max (e["maxOccurs"])); + +      while (more ()) +      { +        XML::Element e (next ()); +        String name (e.name ()); + +        if (name == L"attribute")      attribute (e, false); else +        if (name == L"anyAttribute")   any_attribute (e);    else +        if (name == L"attributeGroup") attribute_group (e);  else +        { +          wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +                << "error: expected 'attribute', 'anyAttribute', or " +                << "'attributeGroup' instead of '" << name << "'" << endl; + +          valid_ = false; +        } +      } +    } + +    pop (); +  } + +  Void Parser::Impl:: +  complex_content_restriction (XML::Element const& e, Complex& type) +  { +    if (trace_) +      wcout << "restriction base: " << fq_name (e, e["base"]) << endl; + +    set_type<Restricts> (e["base"], e, dynamic_cast<Complex&> (scope ())); + +    // @@ +    // For now we simply skip the contents unless the base is anyType +    // (or a trivial alias thereof). Checking for the trivial alias +    // is further complicated by the fact that it might not be defined +    // at this stage (forward inheritnace) so we will ignore that case +    // as well for now. +    // +    if (!proper_restriction_) +    { +      String base (e["base"]); +      String uq_name (unqualified_name (base)); +      String ns_name (namespace_name (e, base)); + +      if (ns_name != xsd || uq_name != L"anyType") +        return; +    } + +    push (e); + +    annotation (false); + +    if (more ()) +    { +      XML::Element e (next ()); +      String name (e.name ()); +      Compositor* c (0); + +      if (name == L"all")            c = all (e);              else +      if (name == L"choice")         c = choice (e, false);    else +      if (name == L"sequence")       c = sequence (e, false);  else +      if (name == L"attribute")      attribute (e, false);     else +      if (name == L"anyAttribute")   any_attribute (e);        else +      if (name == L"group")          element_group (e, false); else +      if (name == L"attributeGroup") attribute_group (e);      else +      { +        wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +              << "error: unexpected element '" << name << "'" << endl; + +        valid_ = false; +      } + +      if (c) +        s_->new_edge<ContainsCompositor> ( +          type, *c, parse_min (e["minOccurs"]), parse_max (e["maxOccurs"])); + +      while (more ()) +      { +        XML::Element e (next ()); +        String name (e.name ()); + +        if (name == L"attribute")      attribute (e, false); else +        if (name == L"anyAttribute")   any_attribute (e);    else +        if (name == L"attributeGroup") attribute_group (e);  else +        { +          wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +                << "error: expected 'attribute', 'anyAttribute', or " +                << "'attributeGroup' instead of '" << name << "'" << endl; + +          valid_ = false; +        } +      } +    } + +    pop (); +  } + +  Void Parser::Impl:: +  element (XML::Element const& e, Boolean global) +  { +    Boolean qualified (global ? true : qualify_element_); + +    if (String form = e["form"]) +      qualified = form == L"qualified"; + +    if (trace_) +      wcout << "element qualified: " << qualified << endl; + +    if (String name = e["name"]) +    { +      if (trace_) +        wcout << "element name '" << name << "'" << endl; + +      Element& node ( +        s_->new_node<Element> ( +          file (), e.line (), e.column (), global, qualified)); + +      s_->new_edge<Names> (scope (), node, name); + +      if (qualified) +        s_->new_edge<BelongsToNamespace> (node, cur_ns ()); + +      if (!global) +      { +        s_->new_edge<ContainsParticle> ( +          compositor (), node, +          parse_min (e["minOccurs"]), parse_max (e["maxOccurs"])); +      } + +      // Default and fixed values are mutually exclusive. +      // +      if (e.attribute_p ("fixed")) +        node.fixed (e.attribute ("fixed")); +      else if (e.attribute_p ("default")) +        node.default_ (e.attribute ("default")); + +      if (node.default_p ()) +      { +        node.context ().set ("dom-node", e.dom_element ()); +        default_values_.push_back (&node); +      } + +      if (global) +      { +        if (String sg = e["substitutionGroup"]) +        { +          if (trace_) +            wcout << "substitutes " << sg << endl; + +          try +          { +            String uq_name (unqualified_name (sg)); +            String ns_name (namespace_name (e, sg)); + +            node.context ().set ("substitution-ns-name", ns_name); +            node.context ().set ("substitution-uq-name", uq_name); +          } +          catch (XML::NoMapping const& ex) +          { +            wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +                  << "error: unable to resolve namespace prefix '" +                  << ex.prefix () << "' in '" << sg << "'" << endl; + +            valid_ = false; +          } +        } +      } + +      if (String type = e["type"]) +      { +        if (trace_) +          wcout << "element type " << fq_name (e, type) << endl; + +        set_type<Belongs> (type, e, node); + +        // Parse annotation. +        // +        push (e); + +        if (Annotation* a = annotation (true)) +          s_->new_edge<Annotates> (*a, node); + +        pop (); +      } +      else +      { +        // Looks like an anonymous type. +        // +        push (e); + +        if (Annotation* a = annotation (true)) +          s_->new_edge<Annotates> (*a, node); + +        if (more ()) +        { +          XML::Element e (next ()); + +          String name (e.name ()); + +          if (trace_) +            wcout << name << endl; + +          Type* t (0); + +          if (name == L"simpleType")  t = simple_type (e);  else +          if (name == L"complexType") t = complex_type (e); else +          { +            wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +                  << "error: expected 'simpleType' or 'complexType' " +                  << "instead of '" << e.name () << "'" << endl; + +            valid_ = false; +          } + +          if (t) +            s_->new_edge<Belongs> (node, *t); +        } +        else +        { +          // anyType +          // +          if (!is_disabled ("F001")) +          { +            wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +                  << "warning F001: element '" << name << "' is implicitly " +                  << "of anyType" << endl; + +            wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +                  << "info: did you forget to specify 'type' attribute?" +                  << endl; +          } + +          String prefix (ns_prefix (e, xsd)); +          type =  prefix + (prefix.empty () ? L"" : L":") + L"anyType"; + +          set_type<Belongs> (type, e, node); +        } + +        pop (); +      } +    } +    else if (String ref = e["ref"]) +    { +      Element& node ( +        s_->new_node<Element> ( +          file (), e.line (), e.column (), true, true)); + +      // Ref can only be in compositor. +      // +      s_->new_edge<ContainsParticle> ( +        compositor (), node, +        parse_min (e["minOccurs"]), parse_max (e["maxOccurs"])); + + +      // Default and fixed values are mutually exclusive. +      // +      if (e.attribute_p ("fixed")) +        node.fixed (e.attribute ("fixed")); +      else if (e.attribute_p ("default")) +        node.default_ (e.attribute ("default")); + +      if (node.default_p ()) +      { +        node.context ().set ("dom-node", e.dom_element ()); +        default_values_.push_back (&node); +      } + +      // Parse annotation. +      // +      push (e); + +      if (Annotation* a = annotation (true)) +        s_->new_edge<Annotates> (*a, node); + +      pop (); + +      // Try to resolve the prototype. +      // +      try +      { +        String uq_name (unqualified_name (ref)); +        String ns_name (namespace_name (e, ref)); + +        s_->new_edge<Names> (scope (), node, uq_name); + +        Element& prot (resolve<Element> (ns_name, uq_name, *s_, *cache_)); +        s_->new_edge<BelongsToNamespace> (node, prot.namespace_ ()); + +        // Copy substitution group information if any. +        // +        if (prot.context ().count ("substitution-ns-name")) +        { +          node.context ().set ( +            "substitution-ns-name", +            prot.context ().get<String> ("substitution-ns-name")); + +          node.context ().set ( +            "substitution-uq-name", +            prot.context ().get<String> ("substitution-uq-name")); +        } + +        // Transfer default and fixed values if the ref declaration hasn't +        // defined its own. +        // +        if (!node.default_p ()) +        { +          if (prot.fixed_p ()) +            node.fixed (prot.value ()); +          else if (prot.default_p ()) +            node.default_ (prot.value ()); + +          if (node.default_p ()) +          { +            node.context ().set ( +              "dom-node", +              prot.context ().get<Xerces::DOMElement*> ("dom-node")); +            default_values_.push_back (&node); +          } +        } + +        // Transfer annotation if the ref declaration hasn't defined its own. +        // +        if (!node.annotated_p () && prot.annotated_p ()) +          s_->new_edge<Annotates> (prot.annotation (), node); + +        // Set type information. +        // +        if (prot.typed_p ()) +        { +          s_->new_edge<Belongs> (node, prot.type ()); +        } +        else if (prot.context ().count ("type-ns-name")) +        { +          String ns_name (prot.context ().get<String> ("type-ns-name")); +          String uq_name (prot.context ().get<String> ("type-uq-name")); + +          node.context ().set ("type-ns-name", ns_name); +          node.context ().set ("type-uq-name", uq_name); +          node.context ().set ("edge-type-id", TypeId (typeid (Belongs))); + +          if (trace_) +            wcout << "element '" << ref << "' is not typed" << endl +                  << "deferring resolution until later" << endl; +        } +        else +        { +          // This could be a recursive reference to an element who's +          // (anonymous) type is being defined. We are going to let +          // resolver sort out this case. +          // +          node.context ().set ("instance-ns-name", ns_name); +          node.context ().set ("instance-uq-name", uq_name); + +          if (trace_) +            wcout << "looks like a recursive reference to an element '" +                  << ns_name << "#" << uq_name << "' which is being " +                  << "defined" << endl +                  << "deferring resolution until later" << endl; +        } +      } +      catch (NotNamespace const& ex) +      { +        if (valid_) +        { +          wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +                << "ice: unable to resolve namespace '" << ex.ns () << "'" +                << endl; + +          abort (); +        } +      } +      catch (NotName const& ex) +      { +        node.context ().set ("instance-ns-name", ex.ns ()); +        node.context ().set ("instance-uq-name", ex.name ()); + +        if (trace_) +          wcout << "unable to resolve name '" << ex.name () +                << "' inside namespace '" << ex.ns () << "'" << endl +                << "deferring resolution until later" << endl; +      } +      catch (XML::NoMapping const& ex) +      { +        wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +              << "error: unable to resolve namespace prefix '" +              << ex.prefix () << "' in '" << ref << "'" << endl; + +        valid_ = false; +      } +    } +    else +    { +      if (valid_) +      { +        wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +              << "error: 'name' or 'ref' attribute is missing in element " +              << "declaration" << endl; +      } +    } +  } + +  SemanticGraph::Annotation* Parser::Impl:: +  annotation (Boolean process) +  { +    Annotation* r (0); + +    if (more ()) +    { +      XML::Element e (next ()); + +      if (e.name () == L"annotation") +      { +        if (process) +        { +          push (e); + +          while (more ()) +          { +            XML::Element doc (next ()); + +            if (doc.name () == L"documentation") +            { +              using Xerces::DOMNode; +              using Xerces::DOMText; +              using Xerces::DOMElement; + +              // Use first non-structured (text only) documentation element. +              // +              String text; +              Boolean struc (false); +              DOMElement* de (doc.dom_element()); + +              for (DOMNode* n (de->getFirstChild ()); +                   n != 0 && !struc; +                   n = n->getNextSibling ()) +              { +                switch (n->getNodeType ()) +                { +                case DOMNode::TEXT_NODE: +                case DOMNode::CDATA_SECTION_NODE: +                  { +                    DOMText* t (static_cast<DOMText*> (n)); +                    text += XML::transcode (t->getData ()); +                    break; +                  } +                case DOMNode::ELEMENT_NODE: +                  { +                    struc = true; +                    break; +                  } +                default: +                  break; // ignore +                } +              } + +              if (struc) +                continue; + +              r = &s_->new_node<Annotation> ( +                file (), e.line (), e.column (), text); +              break; +            } +          } + +          pop (); +        } +      } +      else +        prev (); +    } + +    return r; +  } + + +  Void Parser::Impl:: +  attribute (XML::Element const& a, Boolean global) +  { +    Boolean optional (true); + +    String use (a["use"]); + +    if (use == L"prohibited") +      return; +    else if (use == L"required") +      optional = false; + +    Boolean qualified (global ? true : qualify_attribute_); + +    if (String form = a["form"]) +      qualified = form == L"qualified"; + +    if (String name = a["name"]) +    { +      if (trace_) +        wcout << "attribute '" << name << "'" << endl; + +      Attribute& node ( +        s_->new_node<Attribute> ( +          file (), a.line (), a.column (), optional, global, qualified)); + +      s_->new_edge<Names> (scope (), node, name); + +      if (qualified) +        s_->new_edge<BelongsToNamespace> (node, cur_ns ()); + + +      // Default and fixed values are mutually exclusive. +      // +      if (a.attribute_p ("fixed")) +        node.fixed (a.attribute ("fixed")); +      else if (a.attribute_p ("default")) +        node.default_ (a.attribute ("default")); + +      if (node.default_p ()) +      { +        node.context ().set ("dom-node", a.dom_element ()); +        default_values_.push_back (&node); +      } + +      if (String type = a["type"]) +      { +        if (trace_) +          wcout << "attribute type: '" << fq_name (a, type) << "'" << endl; + +        set_type<Belongs> (type, a, node); + +        // Parse annotation. +        // +        push (a); + +        if (Annotation* ann = annotation (true)) +          s_->new_edge<Annotates> (*ann, node); + +        pop (); +      } +      else +      { +        // Looks like an anonymous type. +        // +        push (a); + +        if (Annotation* ann = annotation (true)) +          s_->new_edge<Annotates> (*ann, node); + +        if (more ()) +        { +          XML::Element e (next ()); + +          String name (e.name ()); + +          if (trace_) +            wcout << name << endl; + +          Type* t (0); + +          if (name == L"simpleType") t = simple_type (e); else +          { +            wcerr << file () << ":" << a.line () << ":" << a.column () << ": " +                  << "error: expected 'simpleType' instead of '" << e.name () +                  << "'" << endl; + +            valid_ = false; +          } + +          if (t) +            s_->new_edge<Belongs> (node, *t); +        } +        else +        { +          if (!is_disabled ("F002")) +          { +            wcerr << file () << ":" << a.line () << ":" << a.column () << ": " +                  << "warning F002: attribute '" << name << "' is implicitly " +                  << "of anySimpleType" << endl; + +            wcerr << file () << ":" << a.line () << ":" << a.column () << ": " +                  << "info: did you forget to specify 'type' attribute?" +                  << endl; +          } + +          // anySimpleType +          // +          String prefix (ns_prefix (a, xsd)); +          type =  prefix + (prefix.empty () ? L"" : L":") + L"anySimpleType"; + +          set_type<Belongs> (type, a, node); +        } + +        pop (); +      } +    } +    else if (String ref = a["ref"]) +    { +      Attribute& node ( +        s_->new_node<Attribute> ( +          file (), a.line (), a.column (), optional, true, true)); + + +      // Default and fixed values are mutually exclusive. +      // +      if (a.attribute_p ("fixed")) +        node.fixed (a.attribute ("fixed")); +      else if (a.attribute_p ("default")) +        node.default_ (a.attribute ("default")); + +      if (node.default_p ()) +      { +        node.context ().set ("dom-node", a.dom_element ()); +        default_values_.push_back (&node); +      } + +      // Parse annotation. +      // +      push (a); + +      if (Annotation* ann = annotation (true)) +        s_->new_edge<Annotates> (*ann, node); + +      pop (); + +      try +      { +        String uq_name (unqualified_name (ref)); +        String ns_name (namespace_name (a, ref)); + +        s_->new_edge<Names> (scope (), node, uq_name); + +        Attribute& prot (resolve<Attribute> (ns_name, uq_name, *s_, *cache_)); +        s_->new_edge<BelongsToNamespace> (node, prot.namespace_ ()); + +        // Transfer default and fixed values if the ref declaration hasn't +        // defined its own. +        // +        if (!node.default_p ()) +        { +          // Default value applies only if this attribute is optional. +          // +          if (prot.fixed_p ()) +            node.fixed (prot.value ()); +          else if (optional && prot.default_p ()) +            node.default_ (prot.value ()); + +          if (node.default_p ()) +          { +            node.context ().set ( +              "dom-node", +              prot.context ().get<Xerces::DOMElement*> ("dom-node")); +            default_values_.push_back (&node); +          } +        } + +        // Transfer annotation if the ref declaration hasn't defined its own. +        // +        if (!node.annotated_p () && prot.annotated_p ()) +          s_->new_edge<Annotates> (prot.annotation (), node); + +        // Set type. +        // +        if (prot.typed_p ()) +        { +          s_->new_edge<Belongs> (node, prot.type ()); +        } +        else if (prot.context ().count ("type-ns-name")) +        { +          String ns_name (prot.context ().get<String> ("type-ns-name")); +          String uq_name (prot.context ().get<String> ("type-uq-name")); + +          node.context ().set ("type-ns-name", ns_name); +          node.context ().set ("type-uq-name", uq_name); +          node.context ().set ("edge-type-id", TypeId (typeid (Belongs))); + +          if (trace_) +            wcout << "attribute '" << ref << "' is not typed" << endl +                  << "deferring resolution until later" << endl; +        } +        else +        { +          // This could be a recursive reference to an attribute who's +          // (anonymous) type is being defined. We are going to let +          // resolver sort out this case. +          // +          node.context ().set ("instance-ns-name", ns_name); +          node.context ().set ("instance-uq-name", uq_name); + +          if (trace_) +            wcout << "looks like a recursive reference to an attribute '" +                  << ns_name << "#" << uq_name << "' which is being " +                  << "defined" << endl +                  << "deferring resolution until later" << endl; +        } +      } +      catch (NotNamespace const& ex) +      { +        if (valid_) +        { +          wcerr << file () << ":" << a.line () << ":" << a.column () << ": " +                << "ice: unable to resolve namespace '" << ex.ns () << "'" +                << endl; +          abort (); +        } +      } +      catch (NotName const& ex) +      { +        node.context ().set ("instance-ns-name", ex.ns ()); +        node.context ().set ("instance-uq-name", ex.name ()); + +        if (trace_) +          wcout << "unable to resolve name '" << ex.name () +                << "' inside namespace '" << ex.ns () << "'" << endl +                << "deferring resolution until later" << endl; +      } +      catch (XML::NoMapping const& ex) +      { +        wcerr << file () << ":" << a.line () << ":" << a.column () << ": " +              << "error: unable to resolve namespace prefix '" +              << ex.prefix () << "' in '" << ref << "'" << endl; + +        valid_ = false; +      } +    } +    else +    { +      if (valid_) +      { +        wcerr << file () << ":" << a.line () << ":" << a.column () << ": " +              << "error: 'name' or 'ref' attribute is missing in attribute " +              << "declaration" << endl; +      } +    } +  } + +  Void Parser::Impl:: +  attribute_group (XML::Element const& g) +  { +    if (String name = g["name"]) +    { +      // Global definition. +      // +      if (trace_) +        wcout << "attributeGroup '" << name << "'" << endl; + +      AttributeGroup& group ( +        s_->new_node<AttributeGroup> (file (), g.line (), g.column ())); +      s_->new_edge<Names> (scope (), group, name); + +      push_scope (group); +      push (g); + +      annotation (false); + +      while (more ()) +      { +        XML::Element e (next ()); +        String name (e.name ()); + +        if (trace_) +          wcout << name << endl; + +        if (name == L"attribute")      attribute (e, false); else +        if (name == L"anyAttribute")   any_attribute (e);    else +        if (name == L"attributeGroup") attribute_group (e);  else +        { +          wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +                << "error: expected 'attribute', 'anyAttribute', or " +                << "'attributeGroup' instead of '" << name << "'" << endl; + +          valid_ = false; +        } +      } + +      pop (); +      pop_scope (); +    } +    else if (String ref = g["ref"]) +    { +      if (trace_) +        wcout << "attribute-group-ref " << ref << endl; + +      try +      { +        String uq_name (unqualified_name (ref)); +        String ns_name (namespace_name (g, ref)); + +        // In order to avoid code duplication we are going to let the +        // resolver handle this case. +        // +        if (trace_) +          wcout << "deferring resolution of group name '" << uq_name +                << "' inside namespace '" << ns_name << "'" +                << " until later" << endl; + +        Scope& s (scope ()); +        AttributeGroupRef ref (uq_name, ns_name, s); + +        if (!s.context ().count ("attribute-group-refs")) +          s.context ().set ("attribute-group-refs", AttributeGroupRefs ()); + +        s.context ().get<AttributeGroupRefs> ( +          "attribute-group-refs").push_back (ref); +      } +      catch (NotNamespace const& ex) +      { +        if (valid_) +        { +          wcerr << file () << ":" << g.line () << ":" << g.column () << ": " +                << "ice: unable to resolve namespace '" << ex.ns () << "'" +                << endl; +          abort (); +        } +      } +      catch (XML::NoMapping const& ex) +      { +        wcerr << file () << ":" << g.line () << ":" << g.column () << ": " +              << "error: unable to resolve namespace prefix '" +              << ex.prefix () << "' in '" << ref << "'" << endl; + +        valid_ = false; +      } +    } +    else +    { +      wcerr << file () << ":" << g.line () << ":" << g.column () << ": " +            << "error: 'name' or 'ref' attribute is missing in " +            << "attributeGroup declaration" << endl; + +      valid_ = false; +      return; +    } +  } + +  Void Parser::Impl:: +  any (XML::Element const& a) +  { +    if (trace_) +      wcout << "any" << endl; + +    String namespaces (a["namespace"] ? a["namespace"] : L"##any"); + +    Any& any ( +      s_->new_node<Any> (file (), a.line (), a.column (), namespaces)); + +    s_->new_edge<ContainsParticle> ( +      compositor (), any, +      parse_min (a["minOccurs"]), parse_max (a["maxOccurs"])); + +    // Parse annotation. +    // +    push (a); + +    if (Annotation* ann = annotation (true)) +      s_->new_edge<Annotates> (*ann, any); + +    pop (); + +    // Any has no name so we have to come up with a fake one in order to +    // put it into the scope. +    // +    UnsignedLong count; +    FrontendElements::Context& ctx (scope ().context ()); + +    if (!ctx.count ("any-name-count")) +    { +      count = 0; +      ctx.set ("any-name-count", count); +    } +    else +      count = ++(ctx.get<UnsignedLong> ("any-name-count")); + +    std::basic_ostringstream<WideChar> os; +    os << "any #" << count; + +    s_->new_edge<Names> (scope (), any, os.str ()); +  } + +  Void Parser::Impl:: +  any_attribute (XML::Element const& a) +  { +    if (trace_) +      wcout << "anyAttribute" << endl; + +    String namespaces (a["namespace"] ? a["namespace"] : L"##any"); + +    AnyAttribute& any ( +      s_->new_node<AnyAttribute> ( +        file (), a.line (), a.column (), namespaces)); + +    // Parse annotation. +    // +    push (a); + +    if (Annotation* ann = annotation (true)) +      s_->new_edge<Annotates> (*ann, any); + +    pop (); + +    // AnyAttribute has no name so we have to come up with a fake one +    // in order to put it into the scope. +    // + +    UnsignedLong count; +    FrontendElements::Context& ctx (scope ().context ()); + +    if (!ctx.count ("any-attribute-name-count")) +    { +      count = 0; +      ctx.set ("any-attribute-name-count", count); +    } +    else +      count = ++(ctx.get<UnsignedLong> ("any-attribute-name-count")); + +    std::basic_ostringstream<WideChar> os; +    os << "any-attribute #" << count; + +    s_->new_edge<Names> (scope (), any, os.str ()); +  } + +  // Some specializations to get edge orientations right. +  // + +  template <typename Edge, typename Node> +  struct Orientation +  { +    static Edge& +    set_edge (Schema& s, Node& node, Type& type) +    { +      // By default it is node->edge +      // +      return s.template new_edge<Edge> (node, type); +    } +  }; + +  template <typename Node> +  struct Orientation<Arguments, Node> +  { +    static Arguments& +    set_edge (Schema& s, Node& node, Type& type) +    { +      // For Arguments it is type->node. +      // +      return s.template new_edge<Arguments> (type, node); +    } +  }; + +  template <typename Edge, typename Node> +  Edge* Parser::Impl:: +  set_type (String const& type, XML::Element const& e, Node& node) +  { +    Edge* r (0); + +    try +    { +      String uq_name (unqualified_name (type)); +      String ns_name (namespace_name (e, type)); + +      Type& t (resolve<Type> (ns_name, uq_name, *s_, *cache_)); + +      // See if it is an IDREF specialization. +      // +      if (ns_name == xsd && (uq_name == L"IDREF" || uq_name == L"IDREFS")) +      { +        // See if we've got 'xse:refType' attribute. +        // +        if (String ref_type = e.attribute (xse, "refType")) +        { +          if (trace_) +            wcout << "found refType attribute '" << ref_type << "'" << endl; + +          //@@ It is a bit wasteful to create a new spcialization for +          //   each refType. Instead we could lookup the target type +          //   and then navigate through Arguments edges to see if this +          //   type already arguments specialization that we are intersted +          //   in. But for now I will simplify the logic by creating a new +          //   specialization every time. +          // + +          Specialization* spec (0); + +          if (uq_name == L"IDREF") +            spec = &s_->new_node<Fundamental::IdRef> ( +              file (), e.line (), e.column ()); +          else +            spec = &s_->new_node<Fundamental::IdRefs> ( +              file (), e.line (), e.column ()); + +          r = &Orientation<Edge, Node>::set_edge (*s_, node, *spec); + +          set_type<Arguments> (ref_type, e, *spec); +        } +        else +          r = &Orientation<Edge, Node>::set_edge (*s_, node, t); +      } +      else +        r = &Orientation<Edge, Node>::set_edge (*s_, node, t); +    } +    catch (NotNamespace const& ex) +    { +      wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +            << "error: unable to resolve namespace '" << ex.ns () << "'" +            << endl; + +      valid_ = false; + +    } +    catch (NotName const& ex) +    { +      node.context ().set ("type-ns-name", ex.ns ()); +      node.context ().set ("type-uq-name", ex.name ()); +      node.context ().set ("edge-type-id", TypeId (typeid (Edge))); + +      if (trace_) +        wcout << "unable to resolve name '" << ex.name () +              << "' inside namespace '" << ex.ns () << "'" << endl +              << "deferring resolution until later" << endl; +    } +    catch (XML::NoMapping const& ex) +    { +      wcerr << file () << ":" << e.line () << ":" << e.column () << ": " +            << "error: unable to resolve namespace prefix " +            << "'" << ex.prefix () << "' in '" << type << "'" << endl; + +      valid_ = false; +    } + +    return r; +  } + +  // Xerces has a provision to associate a public id with input streams +  // that can later be used in diagnostics. Unfortunately, it doesn't +  // work. So we will have to keep our own track. +  // +  struct Context: public NonCopyable +  { +    // File map for diagnostic. +    // +    Path const& +    file (Path const& abs) const +    { +      FileMap::ConstIterator i (file_map_.find (abs)); + +      if (i != file_map_.end ()) +      { +        return i->second; +      } +      else +      { +        return abs; +      } +    } + +    Void +    map_file (Path const& abs, Path const& rel) +    { +      file_map_[abs] = rel; +    } + +  private: +    typedef Cult::Containers::Map<Path, Path, FilePathComparator> FileMap; +    FileMap file_map_; +  }; + +  // +  // +  class ErrorHandler : public  Xerces::DOMErrorHandler +  { +  public: +    ErrorHandler (Boolean& valid, XSDFrontend::Context const& ctx) +        : valid_ (valid), +          ctx_ (ctx) +    { +    } + +    virtual Boolean +    handleError (Xerces::DOMError const& e) +    { +      // Xerces likes to say "Fatal error encountered during schema scan". +      // We don't need this junk. +      // +      if (!valid_ +          && e.getLocation ()->getLineNumber () == 0 +          && e.getLocation ()->getColumnNumber () == 0) +        return true; + + +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 +      XSDFrontend::SemanticGraph::Path abs_path ( +        XML::transcode_to_narrow (e.getLocation ()->getURI ()), +        boost::filesystem::native); +#else +      XSDFrontend::SemanticGraph::Path abs_path ( +        XML::transcode_to_narrow (e.getLocation ()->getURI ()).c_str()); +#endif + +      XSDFrontend::SemanticGraph::Path rel_path (ctx_.file (abs_path)); + +      wcerr << rel_path << ':' +            << e.getLocation ()->getLineNumber () << ':' +            << e.getLocation ()->getColumnNumber () << ": "; + +      switch (e.getSeverity ()) +      { +      case Xerces::DOMError::DOM_SEVERITY_WARNING: +        { +          wcerr << "warning: "; +          break; +        } +      default: +        { +          wcerr << "error: "; +          valid_ = false; +          break; +        } +      } + +      wcerr << e.getMessage () << endl; + +      return true; +    } + +  private: +    Boolean& valid_; +    XSDFrontend::Context const& ctx_; +  }; + + +  // Failed to open resource. +  // +  struct Open {}; + +  class InputSource: public Xerces::InputSource +  { +  public: +    InputSource ( +      Path const& abs, +      Path const& rel, +      Path const& base, +      XSDFrontend::Context const& ctx, +      Xerces::MemoryManager* mm = Xerces::XMLPlatformUtils::fgMemoryManager) +        : Xerces::InputSource (mm), +          abs_ (abs), +          rel_ (rel), +          base_ (base), +          ctx_ (ctx) +    { +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 +      setSystemId (XML::XMLChString ( +                     String (abs_.native_file_string ())).c_str ()); +#else +      setSystemId (XML::XMLChString (String (abs_.string ())).c_str ()); +#endif +    } + +    virtual Xerces::BinInputStream* +    makeStream () const +    { +      using namespace Xerces; + +      BinFileInputStream* is ( +        new (getMemoryManager ()) +        BinFileInputStream (getSystemId (), getMemoryManager ())); + +      if (!is->getIsOpen ()) +      { +        delete is; + +        wcerr << ctx_.file (base_) << ": error: " +              << "'" << rel_ << "': unable to open in read mode" +              << endl; + +        throw Open (); +      } + +      return is; +    } + +  private: +    Path abs_; +    Path rel_; +    Path base_; +    XSDFrontend::Context const& ctx_; +  }; + + +  class EntityResolver: public Xerces::XMemory, +#if _XERCES_VERSION >= 30000 +                        public Xerces::DOMLSResourceResolver +#else +                        public Xerces::DOMEntityResolver +#endif +  { +  public: +    EntityResolver (XSDFrontend::Context& ctx, LocationTranslator* t) +        : ctx_ (ctx), loc_translator_ (t) +    { +    } + +#if _XERCES_VERSION >= 30000 +    virtual Xerces::DOMLSInput* +    resolveResource(XMLCh const* const, +                    XMLCh const* const, +                    XMLCh const* const /*pub_id*/, +                    XMLCh const* const prv_id, +                    XMLCh const* const base_uri) +#else +    virtual Xerces::DOMInputSource* +    resolveEntity (XMLCh const* const /*pub_id*/, +                   XMLCh const* const prv_id, +                   XMLCh const* const base_uri) +#endif +    { +      /* +      XMLCh empty[1]; +      empty[0] = 0; + +      wcerr << "resolve entity:" << endl +            << "  pub_id " << (pub_id ? pub_id : empty) << endl +            << "  prv_id " << (prv_id ? prv_id : empty) << endl +            << "     uri " << (base_uri ? base_uri : empty) << endl; +      */ + +      // base_uri should be a valid path by now. +      // +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 +      Path base (XML::transcode_to_narrow (base_uri), +                 boost::filesystem::native); +#else +      Path base (XML::transcode_to_narrow (base_uri).c_str()); +#endif + +      if (prv_id == 0) +      { +        //@@ How can I get the line/column numbers for this? +        // +        wcerr << ctx_.file (base) << ": error: " +              << "unable to guess which schema to open" +              << endl; + +        wcerr << ctx_.file (base) << ": info: " +              << "did you forget to specify schemaLocation for import/include?" +              << endl; + +        throw Open (); +      } + +      NarrowString path_str (XML::transcode_to_narrow (prv_id)); + +      if (loc_translator_) +        path_str = loc_translator_->translate (path_str); + +      try +      { +        Path path; + +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 +        try +        { +          path = Path (path_str); +        } +        catch (InvalidPath const&) +        { +          // Retry as a native path. +          // +          path = Path (path_str, boost::filesystem::native); +        } +#else +      // The new ABI does not have a fallback native representation +      path = Path (path_str.c_str()); +#endif + +        Path base_dir (base.branch_path ()); + +        Path abs_path, rel_path; + +        if (path.is_complete ()) +        { +          abs_path = rel_path = path; +        } +        else +        { +          abs_path = base_dir / path; +          rel_path = ctx_.file (base).branch_path () / path; +        } + +        abs_path.normalize (); + +        ctx_.map_file (abs_path, rel_path); + +        using namespace Xerces; + +        InputSource* is ( +          new (XMLPlatformUtils::fgMemoryManager) +          InputSource (abs_path, rel_path, base, ctx_)); + +        // Note that I can't use XMLPlatformUtils::fgMemoryManager here +        // since Wrapper4InputSource is-not-an XMemory. +        // +        return new Wrapper4InputSource (is); +      } +      catch (InvalidPath const&) +      { +        wcerr << ctx_.file (base) << ": error: " +              << "'" << path_str.c_str () << "' is not a valid filesystem path" +              << endl; +        throw; +      } + +      // Will never reach. +      // +      return 0; +    } + +  private: +    XSDFrontend::Context& ctx_; +    LocationTranslator* loc_translator_; +  }; + + +  XML::AutoPtr<Xerces::DOMDocument> Parser::Impl:: +  dom (Path const& tu, Boolean validate) +  { +    using namespace Xerces; + +    try +    { +      XSDFrontend::Context ctx; + +      Path abs_path (system_complete (tu)); +      abs_path.normalize (); +      ctx.map_file (abs_path, tu); + +      InputSource input_source (abs_path, tu, abs_path, ctx); + +      // First validate the schema with Xerces. +      // +      if (validate) +      { +        // Instantiate the DOM parser. +        // +        XMLCh const gLS[] = {chLatin_L, chLatin_S, chNull }; + +        // Get an implementation of the Load-Store (LS) interface. +        // +        DOMImplementationLS* impl ( +          static_cast<DOMImplementationLS*> ( +            DOMImplementationRegistry::getDOMImplementation (gLS))); + +        // Create a DOMBuilder. +        // +#if _XERCES_VERSION >= 30000 +        XML::AutoPtr<DOMLSParser> parser ( +          impl->createLSParser (DOMImplementationLS::MODE_SYNCHRONOUS, 0)); + +        DOMConfiguration* conf (parser->getDomConfig ()); + +        conf->setParameter (XMLUni::fgDOMComments, false); +        conf->setParameter (XMLUni::fgDOMDatatypeNormalization, true); +        conf->setParameter (XMLUni::fgDOMEntities, false); +        conf->setParameter (XMLUni::fgDOMNamespaces, true); +        conf->setParameter (XMLUni::fgDOMValidate, true); +        conf->setParameter (XMLUni::fgDOMElementContentWhitespace, false); +        conf->setParameter (XMLUni::fgXercesSchema, true); + +        // Xerces-C++ 3.1.0 is the first version with working multi import +        // support. +        // +#if _XERCES_VERSION >= 30100 +        conf->setParameter (XMLUni::fgXercesHandleMultipleImports, multiple_imports_); +#endif + +        conf->setParameter (XMLUni::fgXercesSchemaFullChecking, full_schema_check_); +        conf->setParameter (XMLUni::fgXercesValidationErrorAsFatal, true); + +        ErrorHandler eh (valid_, ctx); +        conf->setParameter (XMLUni::fgDOMErrorHandler, &eh); + +        EntityResolver er (ctx, loc_translator_); +        conf->setParameter (XMLUni::fgDOMResourceResolver, &er); + +        Wrapper4InputSource wrap (&input_source, false); +        parser->loadGrammar (&wrap, Grammar::SchemaGrammarType); +#else +        XML::AutoPtr<DOMBuilder> parser ( +          impl->createDOMBuilder (DOMImplementationLS::MODE_SYNCHRONOUS, 0)); + +        parser->setFeature (XMLUni::fgDOMComments, false); +        parser->setFeature (XMLUni::fgDOMDatatypeNormalization, true); +        parser->setFeature (XMLUni::fgDOMEntities, false); +        parser->setFeature (XMLUni::fgDOMNamespaces, true); +        parser->setFeature (XMLUni::fgDOMValidation, true); +        parser->setFeature (XMLUni::fgDOMWhitespaceInElementContent, false); +        parser->setFeature (XMLUni::fgXercesSchema, true); +        parser->setFeature (XMLUni::fgXercesSchemaFullChecking, full_schema_check_); +        parser->setFeature (XMLUni::fgXercesValidationErrorAsFatal, true); + +        ErrorHandler eh (valid_, ctx); +        parser->setErrorHandler (&eh); + +        EntityResolver er (ctx, loc_translator_); +        parser->setEntityResolver (&er); + +        Wrapper4InputSource wrap (&input_source, false); +        parser->loadGrammar (wrap, Grammar::SchemaGrammarType); +#endif +      } + +      if (!valid_) +        return XML::AutoPtr<DOMDocument> (0); + +      // Now do our own parsing. +      // +      std::auto_ptr<XML::SchemaDOMParser> xsd_parser ( +        new (XMLPlatformUtils::fgMemoryManager) XML::SchemaDOMParser ()); + +      xsd_parser->parse (input_source); + +      XML::AutoPtr<DOMDocument> doc (xsd_parser->adoptDocument()); + +      return doc; +    } +    catch (Xerces::XMLException const& e) +    { +      wcerr << tu << ": ice: Xerces::XMLException: " << e.getMessage () +            << endl; + +      abort (); +    } +    catch (Xerces::DOMException const& e) +    { +      Size const size = 2047; +      XMLCh text[size + 1]; + +      wcerr << tu << ": ice: Xerces::DOMException: "; + +      if (DOMImplementation::loadDOMExceptionMsg (e.code, text, size)) +        wcerr << text << endl; +      else +        wcerr << "no message available, error code: " << e.code << endl; + +      abort (); +    } +    catch (InvalidPath const&) +    { +      // Diagnostics has already been issued. +      // +      valid_ = false; +    } +    catch (Open const&) +    { +      // Diagnostics has already been issued. +      // +      valid_ = false; +    } + +    return XML::AutoPtr<DOMDocument> (0); +  } + +  // LocationTranslator +  // +  LocationTranslator:: +  ~LocationTranslator () +  { +  } + +  // Parser +  // +  Parser:: +  ~Parser () +  { +  } + +  Parser:: +  Parser (Boolean proper_restriction, +          Boolean multiple_imports, +          Boolean full_schema_check) +      : impl_ (new Impl (proper_restriction, +                         multiple_imports, +                         full_schema_check, +                         0, +                         0)) +  { +  } + +  Parser:: +  Parser (Boolean proper_restriction, +          Boolean multiple_imports, +          Boolean full_schema_check, +          LocationTranslator& t, +          const WarningSet& d) +      : impl_ (new Impl (proper_restriction, +                         multiple_imports, +                         full_schema_check, +                         &t, +                         &d)) +  { +  } + +  Evptr<SemanticGraph::Schema> Parser:: +  parse (SemanticGraph::Path const& path) +  { +    return impl_->parse (path); +  } + +  Evptr<SemanticGraph::Schema> Parser:: +  parse (SemanticGraph::Paths const& paths) +  { +    return impl_->parse (paths); +  } + +  Evptr<SemanticGraph::Schema> Parser:: +  xml_schema (SemanticGraph::Path const& path) +  { +    return impl_->xml_schema (path); +  } +} diff --git a/libxsd-frontend/xsd-frontend/parser.hxx b/libxsd-frontend/xsd-frontend/parser.hxx new file mode 100644 index 0000000..ac0ff4d --- /dev/null +++ b/libxsd-frontend/xsd-frontend/parser.hxx @@ -0,0 +1,76 @@ +// file      : xsd-frontend/parser.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_PARSER_HXX +#define XSD_FRONTEND_PARSER_HXX + +#include <cult/types.hxx> +#include <cult/containers/set.hxx> + +#include <xsd-frontend/semantic-graph/schema.hxx> + +namespace XSDFrontend +{ +  using namespace Cult::Types; + +  struct InvalidSchema {}; + +  class LocationTranslator +  { +  public: +    virtual +    ~LocationTranslator (); + +    virtual NarrowString +    translate (NarrowString const& location) = 0; +  }; + +  // Set of disabled warning IDs. Special ID "all" disables all +  // warnings. +  // +  typedef Cult::Containers::Set<NarrowString> WarningSet; + +  class Parser: public NonCopyable +  { +  public: +    ~Parser (); + +    Parser (Boolean proper_restriction, +            Boolean multiple_imports, +            Boolean full_schema_check); + +    Parser (Boolean proper_restriction, +            Boolean multiple_imports, +            Boolean full_schema_check, +            LocationTranslator&, +            const WarningSet& disabled); + +  public: +    // Parse a schema file. Throws InvalidSchema in case of a failure. +    // +    Evptr<SemanticGraph::Schema> +    parse (SemanticGraph::Path const&); + +    // Parse a number of schema files all into one semantic graph. +    // Each schema file is imported from an unnamed root translation +    // unit. Throws InvalidSchema in case of a failure. +    // +    Evptr<SemanticGraph::Schema> +    parse (SemanticGraph::Paths const&); + +    // Returns a schema graph that corresponds to the XML Schema +    // namespace with built-in type definitions. The path is fake +    // and is only used as a lable. +    // +    Evptr<SemanticGraph::Schema> +    xml_schema (SemanticGraph::Path const&); + +  private: +    class Impl; +    Evptr<Impl> impl_; +  }; +} + +#endif  // XSD_FRONTEND_PARSER_HXX diff --git a/libxsd-frontend/xsd-frontend/schema-dom-parser.cxx b/libxsd-frontend/xsd-frontend/schema-dom-parser.cxx new file mode 100644 index 0000000..452980c --- /dev/null +++ b/libxsd-frontend/xsd-frontend/schema-dom-parser.cxx @@ -0,0 +1,196 @@ +// file      : xsd-frontend/schema-dom-parser.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/schema-dom-parser.hxx> + +#include <xercesc/dom/DOMDocument.hpp> +#include <xercesc/dom/DOMElement.hpp> +#include <xercesc/dom/DOMAttr.hpp> +#include <xercesc/dom/DOMText.hpp> + +#include <xercesc/framework/XMLValidityCodes.hpp> +#include <xercesc/validators/schema/SchemaSymbols.hpp> + +#include <xercesc/util/XMLString.hpp> + +#include <xercesc/internal/XMLScanner.hpp> +#include <xercesc/internal/ElemStack.hpp> + +namespace XSDFrontend +{ +  namespace XML +  { +    using namespace Xerces; + +    const XMLCh line_key[2] = {chLatin_l, chNull}; +    const XMLCh column_key[2] = {chLatin_c, chNull}; + +    SchemaDOMParser:: +    SchemaDOMParser (MemoryManager* mgr) +        : XercesDOMParser(0, mgr, 0), +          depth_ (-1), +          ann_depth_ (-1), +          inner_ann_depth_ (-1) +    { +      error_reporter_.setErrorReporter (this); +      setValidationScheme (XercesDOMParser::Val_Never); +      setDoNamespaces (true); +    } + +    void SchemaDOMParser:: +    startElement (const XMLElementDecl& decl, +                  const unsigned int url_id, +                  const XMLCh* const prefix, +                  const RefVectorOf<XMLAttr>& attributes, +#if _XERCES_VERSION >= 30000 +                  const XMLSize_t attr_count, +#else +                  const unsigned int attr_count, +#endif +                  const bool empty, +                  const bool root) +    { +      depth_++; + +      if (ann_depth_ == -1) +      { +        if (XMLString::equals(decl.getBaseName(), +                              SchemaSymbols::fgELT_ANNOTATION) && +            XMLString::equals(getURIText(url_id), +                              SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) +        { +          ann_depth_ = depth_; +        } +      } +      else if (depth_ == ann_depth_ + 1) +      { +        inner_ann_depth_ = depth_; +      } + +      XercesDOMParser::startElement ( +        decl, url_id, prefix, attributes, attr_count, false, root); + +      // Set the line/column info. +      // +      ReaderMgr::LastExtEntityInfo info; +      ((ReaderMgr*) fScanner->getLocator())->getLastExtEntityInfo(info); + +#if _XERCES_VERSION >= 30000 +      unsigned long l (static_cast<unsigned long> (info.lineNumber)); +      unsigned long c (static_cast<unsigned long> (info.colNumber)); +#else +      unsigned long l (info.lineNumber == -1 +                       ? 0UL +                       : static_cast<unsigned long> (info.lineNumber)); + +      unsigned long c (info.colNumber == -1 +                       ? 0UL +                       : static_cast<unsigned long> (info.colNumber)); +#endif + +      fCurrentNode->setUserData (line_key, reinterpret_cast<void*> (l), 0); +      fCurrentNode->setUserData (column_key, reinterpret_cast<void*> (c), 0); + +      // If an empty element, call the endElement() now. +      // +      if (empty) +        endElement (decl, url_id, root, prefix); +    } + +    void SchemaDOMParser:: +    endElement (const XMLElementDecl& decl, +                const unsigned int url_id, +                const bool root, +                const XMLCh* const prefix) +    { +      if(ann_depth_ > -1) +      { +        if (inner_ann_depth_ == depth_) +        { +          inner_ann_depth_ = -1; +        } +        else if (ann_depth_ == depth_) +        { +          ann_depth_ = -1; +        } +      } + +      depth_--; + +      XercesDOMParser::endElement (decl, url_id, root, prefix); +    } + +    void SchemaDOMParser:: +    docCharacters (const XMLCh* const s, +#if _XERCES_VERSION >= 30000 +                   const XMLSize_t length, +#else +                   const unsigned int length, +#endif +                   const bool cdata) +    { +      // Ignore chars outside of content. +      // +      if (!fWithinElement) +        return; + +      if (inner_ann_depth_ == -1) +      { +        if (!((ReaderMgr*) fScanner->getReaderMgr())->getCurrentReader()-> +            isAllSpaces(s, length)) +        { +          ReaderMgr::LastExtEntityInfo lastInfo; +          fScanner->getReaderMgr()->getLastExtEntityInfo(lastInfo); +          locator_.setValues(lastInfo.systemId, lastInfo.publicId, +                             lastInfo.lineNumber, lastInfo.colNumber); +          error_reporter_.emitError(XMLValid::NonWSContent, +                                    XMLUni::fgValidityDomain, +                                    &locator_); +        } +      } +      else +      { +        // When it's within either of the 2 annotation sub-elements, +        // characters are allowed and we need to store them. +        // +        XercesDOMParser::docCharacters (s, length, cdata); +      } +    } + +    void SchemaDOMParser:: +    docComment (const XMLCh* const) +    { +      // We don't want any comments. +    } + +    void SchemaDOMParser:: +    startEntityReference (const XMLEntityDecl&) +    { +    } + +    void SchemaDOMParser:: +    endEntityReference (const XMLEntityDecl&) +    { +    } + +    void SchemaDOMParser:: +    ignorableWhitespace (const XMLCh* const s, +#if _XERCES_VERSION >= 30000 +                         const XMLSize_t length, +#else +                         const unsigned int length, +#endif +                         const bool cdata) +    { +      // Ignore chars before the root element. +      // +      if (!fWithinElement || !fIncludeIgnorableWhitespace) +        return; + +      if (ann_depth_ > -1) +        XercesDOMParser::ignorableWhitespace (s, length, cdata); +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/schema-dom-parser.hxx b/libxsd-frontend/xsd-frontend/schema-dom-parser.hxx new file mode 100644 index 0000000..7571677 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/schema-dom-parser.hxx @@ -0,0 +1,93 @@ +// file      : xsd-frontend/schema-dom-parser.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SCHEMA_DOM_PARSER_HXX +#define XSD_FRONTEND_SCHEMA_DOM_PARSER_HXX + +#include <xercesc/parsers/XercesDOMParser.hpp> + +#include <xercesc/dom/DOMElement.hpp> + +#include <xercesc/validators/schema/XSDLocator.hpp> +#include <xercesc/validators/schema/XSDErrorReporter.hpp> + +namespace XSDFrontend +{ +  namespace XML +  { +    namespace Xerces = xercesc; + +    extern const XMLCh line_key[2]; +    extern const XMLCh column_key[2]; + +    class SchemaDOMParser: public Xerces::XercesDOMParser +    { +    public : +      SchemaDOMParser ( +        Xerces::MemoryManager* = Xerces::XMLPlatformUtils::fgMemoryManager); + +      // Callbacks. +      // +      virtual void +      startElement (const Xerces::XMLElementDecl&, +                    const unsigned int url_id, +                    const XMLCh* const prefix, +                    const Xerces::RefVectorOf<Xerces::XMLAttr>& attributes, +#if _XERCES_VERSION >= 30000 +                    const XMLSize_t attribute_count, +#else +                    const unsigned int attribute_count, +#endif +                    const bool empty, +                    const bool root); + +      virtual void +      endElement (const Xerces::XMLElementDecl&, +                  const unsigned int url_id, +                  const bool root, +                  const XMLCh* const prefix); + +      virtual void +      docCharacters (const XMLCh* const, +#if _XERCES_VERSION >= 30000 +                     const XMLSize_t length, +#else +                     const unsigned int length, +#endif +                     const bool cdata); + +      virtual void +      docComment (const XMLCh* const); + +      virtual void +      startEntityReference (const Xerces::XMLEntityDecl&); + +      virtual void +      endEntityReference (const Xerces::XMLEntityDecl&); + +      virtual void +      ignorableWhitespace (const XMLCh* const, +#if _XERCES_VERSION >= 30000 +                           const XMLSize_t length, +#else +                           const unsigned int length, +#endif +                           const bool cdata); +    private: +      SchemaDOMParser (SchemaDOMParser const&); +      SchemaDOMParser& +      operator=(SchemaDOMParser const&); + +    private: +      int depth_; +      int ann_depth_; +      int inner_ann_depth_; +      Xerces::XSDLocator locator_; +      Xerces::XSDErrorReporter error_reporter_; +    }; +  } +} + +#endif // XSD_FRONTEND_SCHEMA_DOM_PARSER_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph.hxx b/libxsd-frontend/xsd-frontend/semantic-graph.hxx new file mode 100644 index 0000000..bee17fc --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph.hxx @@ -0,0 +1,27 @@ +// file      : xsd-frontend/semantic-graph.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_HXX + +#include <xsd-frontend/semantic-graph/annotation.hxx> +#include <xsd-frontend/semantic-graph/any.hxx> +#include <xsd-frontend/semantic-graph/any-attribute.hxx> +#include <xsd-frontend/semantic-graph/attribute.hxx> +#include <xsd-frontend/semantic-graph/attribute-group.hxx> +#include <xsd-frontend/semantic-graph/complex.hxx> +#include <xsd-frontend/semantic-graph/compositors.hxx> +#include <xsd-frontend/semantic-graph/element.hxx> +#include <xsd-frontend/semantic-graph/element-group.hxx> +#include <xsd-frontend/semantic-graph/elements.hxx> +#include <xsd-frontend/semantic-graph/enumeration.hxx> +#include <xsd-frontend/semantic-graph/fundamental.hxx> +#include <xsd-frontend/semantic-graph/list.hxx> +#include <xsd-frontend/semantic-graph/namespace.hxx> +#include <xsd-frontend/semantic-graph/particle.hxx> +#include <xsd-frontend/semantic-graph/schema.hxx> +#include <xsd-frontend/semantic-graph/union.hxx> + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/annotation.cxx b/libxsd-frontend/xsd-frontend/semantic-graph/annotation.cxx new file mode 100644 index 0000000..22793f7 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/annotation.cxx @@ -0,0 +1,50 @@ +// file      : xsd-frontend/semantic-graph/annotation.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/semantic-graph/annotation.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    namespace RTTI = Cult::RTTI; + +    using RTTI::Access; +    using RTTI::TypeInfo; + + +    // Annotates +    // +    namespace +    { +      struct AnnotatesInit +      { +        AnnotatesInit () +        { +          TypeInfo ti (typeid (Annotates)); +          ti.add_base (Access::public_, true, typeid (Edge)); +          RTTI::insert (ti); +        } + +      } annotates_init_; +    } + +    // Annotation +    // +    namespace +    { +      struct AnnotationInit +      { +        AnnotationInit () +        { +          TypeInfo ti (typeid (Annotation)); +          ti.add_base (Access::public_, true, typeid (Node)); +          RTTI::insert (ti); +        } + +      } annotation_init_; +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/annotation.hxx b/libxsd-frontend/xsd-frontend/semantic-graph/annotation.hxx new file mode 100644 index 0000000..661ac72 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/annotation.hxx @@ -0,0 +1,89 @@ +// file      : xsd-frontend/semantic-graph/annotation.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_ANNOTATION_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_ANNOTATION_HXX + +#include <xsd-frontend/semantic-graph/elements.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    // +    // +    class Annotation; + +    class Annotates: public virtual Edge +    { +    public: +      Annotation& +      annotation () +      { +        return *annotation_; +      } + +    protected: +      friend class Bits::Graph<Node, Edge>; + +      Annotates () +          : annotation_ (0) +      { +      } + +      Void +      set_left_node (Annotation& a) +      { +        annotation_ = &a; +      } + +      Void +      set_right_node (Node&) +      { +      } + +      Void +      set_right_node (Edge&) +      { +      } + +    private: +      Annotation* annotation_; +    }; + +    // +    // +    class Annotation: public virtual Node +    { +    public: +      WideString const& +      documentation () const +      { +        return documentation_; +      } + +    protected: +      friend class Bits::Graph<Node, Edge>; + +      Annotation (Path const& file, +                  UnsignedLong line, +                  UnsignedLong column, +                  WideString const& documentation) +          : Node (file, line, column), documentation_ (documentation) +      { +      } + +      Void +      add_edge_left (Annotates&) +      { +      } + +    private: +      WideString documentation_; +    }; +  } +} + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_ANNOTATION_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/any-attribute.cxx b/libxsd-frontend/xsd-frontend/semantic-graph/any-attribute.cxx new file mode 100644 index 0000000..e25e742 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/any-attribute.cxx @@ -0,0 +1,114 @@ +// file      : xsd-frontend/semantic-graph/any-attribute.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/semantic-graph/any-attribute.hxx> +#include <xsd-frontend/semantic-graph/compositors.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    namespace RTTI = Cult::RTTI; + +    using RTTI::Access; +    using RTTI::TypeInfo; + +    namespace +    { +      struct AnyAttributeInit +      { +        AnyAttributeInit () +        { +          TypeInfo ti (typeid (AnyAttribute)); +          ti.add_base (Access::public_, true, typeid (Nameable)); +          RTTI::insert (ti); +        } + +      } any_attribute_init_; +    } + +    AnyAttribute:: +    AnyAttribute (Path const& file, +                  UnsignedLong line, +                  UnsignedLong column, +                  WideString const& namespaces) +        : Node (file, line, column), +          prototype_ (0) +    { +      // Not sure if the separator is just space or any white-space +      // chararcter. +      // + +      for (Size i (0), j (namespaces.find (L' '));;) +      { +        if (j != WideString::npos) +        { +          namespaces_.push_back (WideString (namespaces, i, j - i)); + +          i = j + 1; +          j = namespaces.find (L' ', i); +        } +        else +        { +          // Last element. +          // +          namespaces_.push_back (WideString (namespaces, i)); +          break; +        } +      } +    } + +    AnyAttribute:: +    AnyAttribute (Path const& file, +                  UnsignedLong line, +                  UnsignedLong column, +                  NamespaceIterator begin, +                  NamespaceIterator end) +        : Node (file, line, column), +          prototype_ (0) +    { +      for (; begin != end; ++begin) +        namespaces_.push_back (*begin); +    } + +    namespace +    { +      Namespace& +      namespace_ (Nameable& n) +      { +        // The basic idea goes like this: go up Names edges until you +        // reach Namespace. There are, however, anonymous types which +        // need special handling. In the case of an anonymous type we +        // will go up the first Belongs edge (because the first edge +        // is where the type was defined. +        // + +        if (n.named_p ()) +        { +          Scope& s (n.scope ()); +          Namespace* ns (dynamic_cast<Namespace*> (&n)); + +          return ns ? *ns : namespace_ (s); +        } +        else +        { +          Type& t (dynamic_cast<Type&> (n)); +          Belongs& b (*t.classifies_begin ()); + +          return namespace_ (b.instance ()); +        } +      } +    } + +    Namespace& AnyAttribute:: +    definition_namespace () +    { +      if (prototype_p ()) +        return prototype ().definition_namespace (); + +      return namespace_ (scope ()); +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/any-attribute.hxx b/libxsd-frontend/xsd-frontend/semantic-graph/any-attribute.hxx new file mode 100644 index 0000000..bc8c512 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/any-attribute.hxx @@ -0,0 +1,85 @@ +// file      : xsd-frontend/semantic-graph/any-attribute.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_ANY_ATTRIBUTE_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_ANY_ATTRIBUTE_HXX + +#include <cult/containers/vector.hxx> + +#include <xsd-frontend/semantic-graph/elements.hxx> +#include <xsd-frontend/semantic-graph/namespace.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    class AnyAttribute: public virtual Nameable +    { +      typedef +      Cult::Containers::Vector<WideString> +      Namespaces; + +    public: +      typedef Namespaces::ConstIterator NamespaceIterator; + +      NamespaceIterator +      namespace_begin () const +      { +        return namespaces_.begin (); +      } + +      NamespaceIterator +      namespace_end () const +      { +        return namespaces_.end (); +      } + +    public: +      Boolean +      prototype_p () +      { +        return prototype_ != 0; +      } + +      AnyAttribute& +      prototype () +      { +        assert (prototype_ != 0); +        return *prototype_; +      } + +      Void +      prototype (AnyAttribute& a) +      { +        assert (prototype_ == 0); +        prototype_ = &a; +      } + +    public: +      Namespace& +      definition_namespace (); + +    protected: +      friend class Bits::Graph<Node, Edge>; + +      AnyAttribute (Path const& file, +                    UnsignedLong line, +                    UnsignedLong column, +                    WideString const& namespaces); + +      AnyAttribute (Path const& file, +                    UnsignedLong line, +                    UnsignedLong column, +                    NamespaceIterator begin, +                    NamespaceIterator end); + +    private: +      AnyAttribute* prototype_; +      Namespaces namespaces_; +    }; +  } +} + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_ANY_ATTRIBUTE_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/any.cxx b/libxsd-frontend/xsd-frontend/semantic-graph/any.cxx new file mode 100644 index 0000000..a6c9e72 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/any.cxx @@ -0,0 +1,125 @@ +// file      : xsd-frontend/semantic-graph/any.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/semantic-graph/any.hxx> +#include <xsd-frontend/semantic-graph/compositors.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    namespace RTTI = Cult::RTTI; + +    using RTTI::Access; +    using RTTI::TypeInfo; + +    namespace +    { +      struct AnyInit +      { +        AnyInit () +        { +          TypeInfo ti (typeid (Any)); +          ti.add_base (Access::public_, true, typeid (Nameable)); +          ti.add_base (Access::public_, true, typeid (Particle)); +          RTTI::insert (ti); +        } + +      } any_init_; +    } + +    Any:: +    Any (Path const& file, +         UnsignedLong line, +         UnsignedLong column, +         WideString const& namespaces) +        : Node (file, line, column), +          prototype_ (0) +    { +      // Not sure if the separator is just space or any white-space +      // chararcter. +      // + +      for (Size i (0), j (namespaces.find (L' '));;) +      { +        if (j != WideString::npos) +        { +          namespaces_.push_back (WideString (namespaces, i, j - i)); + +          i = j + 1; +          j = namespaces.find (L' ', i); +        } +        else +        { +          // Last element. +          // +          namespaces_.push_back (WideString (namespaces, i)); +          break; +        } +      } +    } + +    Any:: +    Any (Path const& file, +         UnsignedLong line, +         UnsignedLong column, +         NamespaceIterator begin, +         NamespaceIterator end) +        : Node (file, line, column), +          prototype_ (0) +    { +      for (; begin != end; ++begin) +        namespaces_.push_back (*begin); +    } + +    namespace +    { +      Namespace& +      namespace_ (Nameable& n) +      { +        // The basic idea goes like this: go up Names edges until you +        // reach Namespace. There are, however, anonymous types which +        // need special handling. In the case of an anonymous type we +        // will go up the first Belongs edge (because the first edge +        // is where the type was defined. +        // + +        if (n.named_p ()) +        { +          Scope& s (n.scope ()); +          Namespace* ns (dynamic_cast<Namespace*> (&n)); + +          return ns ? *ns : namespace_ (s); +        } +        else +        { +          Type& t (dynamic_cast<Type&> (n)); +          Belongs& b (*t.classifies_begin ()); + +          return namespace_ (b.instance ()); +        } +      } +    } + +    Namespace& Any:: +    definition_namespace () +    { +      if (prototype_p ()) +        return prototype ().definition_namespace (); + +      // Get to our scope. +      // +      Compositor* c (&contained_particle ().compositor ()); + +      while(!c->contained_compositor_p ()) +        c = &c->contained_particle ().compositor (); + +      Scope& scope ( +        dynamic_cast<Scope&> (c->contained_compositor ().container ())); + +      return namespace_ (scope); +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/any.hxx b/libxsd-frontend/xsd-frontend/semantic-graph/any.hxx new file mode 100644 index 0000000..ded9bd8 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/any.hxx @@ -0,0 +1,90 @@ +// file      : xsd-frontend/semantic-graph/any.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_ANY_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_ANY_HXX + +#include <cult/containers/vector.hxx> + +#include <xsd-frontend/semantic-graph/elements.hxx> +#include <xsd-frontend/semantic-graph/particle.hxx> +#include <xsd-frontend/semantic-graph/namespace.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    class Any: public virtual Nameable, +               public virtual Particle +    { +      typedef +      Cult::Containers::Vector<WideString> +      Namespaces; + +    public: +      typedef Namespaces::ConstIterator NamespaceIterator; + +      NamespaceIterator +      namespace_begin () const +      { +        return namespaces_.begin (); +      } + +      NamespaceIterator +      namespace_end () const +      { +        return namespaces_.end (); +      } + +    public: +      Boolean +      prototype_p () +      { +        return prototype_ != 0; +      } + +      Any& +      prototype () +      { +        assert (prototype_ != 0); +        return *prototype_; +      } + +      Void +      prototype (Any& a) +      { +        assert (prototype_ == 0); +        prototype_ = &a; +      } + +    public: +      Namespace& +      definition_namespace (); + +    protected: +      friend class Bits::Graph<Node, Edge>; + +      Any (Path const& file, +           UnsignedLong line, +           UnsignedLong column, +           WideString const& namespaces); + +      Any (Path const& file, +           UnsignedLong line, +           UnsignedLong column, +           NamespaceIterator begin, +           NamespaceIterator end); + +      using Nameable::add_edge_right; +      using Particle::add_edge_right; + +    private: +      Any* prototype_; +      Namespaces namespaces_; +    }; +  } +} + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_ANY_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/attribute-group.cxx b/libxsd-frontend/xsd-frontend/semantic-graph/attribute-group.cxx new file mode 100644 index 0000000..54bb5df --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/attribute-group.cxx @@ -0,0 +1,39 @@ +// file      : xsd-frontend/semantic-graph/attribute-group.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/semantic-graph/attribute-group.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    namespace RTTI = Cult::RTTI; + +    using RTTI::Access; +    using RTTI::TypeInfo; + + +    namespace +    { +      struct AttributeGroupInit +      { +        AttributeGroupInit () +        { +          TypeInfo ti (typeid (AttributeGroup)); +          ti.add_base (Access::public_, true, typeid (Scope)); +          RTTI::insert (ti); +        } + +      } attribute_group_init_; +    } + +    AttributeGroup:: +    AttributeGroup (Path const& file, UnsignedLong line, UnsignedLong column) +        : Node (file, line, column) +    { +    } + +  } +} diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/attribute-group.hxx b/libxsd-frontend/xsd-frontend/semantic-graph/attribute-group.hxx new file mode 100644 index 0000000..44739f2 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/attribute-group.hxx @@ -0,0 +1,27 @@ +// file      : xsd-frontend/semantic-graph/attribute-group.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_ATTRIBUTE_GROUP_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_ATTRIBUTE_GROUP_HXX + +#include <xsd-frontend/semantic-graph/elements.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    class AttributeGroup: public virtual Scope +    { +    protected: +      friend class Bits::Graph<Node, Edge>; + +      AttributeGroup (Path const& file, +                      UnsignedLong line, +                      UnsignedLong column); +    }; +  } +} + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_ATTRIBUTE_GROUP_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/attribute.cxx b/libxsd-frontend/xsd-frontend/semantic-graph/attribute.cxx new file mode 100644 index 0000000..2e30d4e --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/attribute.cxx @@ -0,0 +1,44 @@ +// file      : xsd-frontend/semantic-graph/attribute.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/semantic-graph/attribute.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    namespace RTTI = Cult::RTTI; + +    using RTTI::Access; +    using RTTI::TypeInfo; + +    namespace +    { +      struct AttributeInit +      { +        AttributeInit () +        { +          TypeInfo ti (typeid (Attribute)); +          ti.add_base (Access::public_, true, typeid (Member)); +          RTTI::insert (ti); +        } + +      } attribute_init_; +    } + +    Attribute:: +    Attribute (Path const& file, +               UnsignedLong line, +               UnsignedLong column, +               Boolean optional, +               Boolean global, +               Boolean qualified) +        : Node (file, line, column), +          Member (global, qualified), +          optional_ (optional) +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/attribute.hxx b/libxsd-frontend/xsd-frontend/semantic-graph/attribute.hxx new file mode 100644 index 0000000..f7a516d --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/attribute.hxx @@ -0,0 +1,39 @@ +// file      : xsd-frontend/semantic-graph/attribute.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_ATTRIBUTE_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_ATTRIBUTE_HXX + +#include <xsd-frontend/semantic-graph/elements.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    class Attribute: public virtual Member +    { +    public: +      Boolean +      optional_p () const +      { +        return optional_; +      } + +    protected: +      friend class Bits::Graph<Node, Edge>; + +      Attribute (Path const& file, +                 UnsignedLong line, +                 UnsignedLong column, +                 Boolean optional, +                 Boolean global, +                 Boolean qualified); +    private: +      Boolean optional_; +    }; +  } +} + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_ATTRIBUTE_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/complex.cxx b/libxsd-frontend/xsd-frontend/semantic-graph/complex.cxx new file mode 100644 index 0000000..0cc265f --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/complex.cxx @@ -0,0 +1,45 @@ +// file      : xsd-frontend/semantic-graph/complex.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/semantic-graph/complex.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    namespace RTTI = Cult::RTTI; + +    using RTTI::Access; +    using RTTI::TypeInfo; + +    namespace +    { +      struct ComplexInit +      { +        ComplexInit () +        { +          TypeInfo ti (typeid (Complex)); +          ti.add_base (Access::public_, true, typeid (Type)); +          ti.add_base (Access::public_, true, typeid (Scope)); +          RTTI::insert (ti); +        } + +      } complex_init_; +    } + +    Complex:: +    Complex () +        : mixed_ (false), contains_compositor_ (0) +    { +    } + +    Complex:: +    Complex (Path const& file, UnsignedLong line, UnsignedLong column) +        : Node (file, line, column), +          mixed_ (false), contains_compositor_ (0) +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/complex.hxx b/libxsd-frontend/xsd-frontend/semantic-graph/complex.hxx new file mode 100644 index 0000000..40327bc --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/complex.hxx @@ -0,0 +1,78 @@ +// file      : xsd-frontend/semantic-graph/complex.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_COMPLEX_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_COMPLEX_HXX + +#include <xsd-frontend/semantic-graph/elements.hxx> +#include <xsd-frontend/semantic-graph/compositors.hxx> + +#include <cult/containers/vector.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    class Complex: public virtual Type, public virtual Scope +    { +    public: +      Boolean +      mixed_p () const +      { +        return mixed_; +      } + +    public: +      Boolean +      contains_compositor_p () +      { +        return contains_compositor_ != 0; +      } + +      ContainsCompositor& +      contains_compositor () +      { +        assert (contains_compositor_ != 0); +        return *contains_compositor_; +      } + +    public: +      Void +      mixed_p (Boolean m) +      { +        mixed_ = m; +      } + +    protected: +      friend class Bits::Graph<Node, Edge>; + +      Complex (); // Virtual inheritance (Enumeration). +      Complex (Path const& file, UnsignedLong line, UnsignedLong column); + +      using Type::add_edge_right; +      using Type::add_edge_left; +      using Scope::add_edge_left; + +      Void +      add_edge_left (ContainsCompositor& e) +      { +        contains_compositor_ = &e; +      } + +      Void +      remove_edge_left (ContainsCompositor& e) +      { +        assert (contains_compositor_ == &e); +        contains_compositor_ = 0; +      } + +    private: +      Boolean mixed_; +      ContainsCompositor* contains_compositor_; +    }; +  } +} + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_COMPLEX_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/compositors.cxx b/libxsd-frontend/xsd-frontend/semantic-graph/compositors.cxx new file mode 100644 index 0000000..08953bc --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/compositors.cxx @@ -0,0 +1,124 @@ +// file      : xsd-frontend/semantic-graph/compositor.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/semantic-graph/compositors.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    namespace RTTI = Cult::RTTI; + +    using RTTI::Access; +    using RTTI::TypeInfo; + + +    // ContainsCompositor +    // +    namespace +    { +      struct ContainsCompositorInit +      { +        ContainsCompositorInit () +        { +          TypeInfo ti (typeid (ContainsCompositor)); +          ti.add_base (Access::public_, true, typeid (Edge)); +          RTTI::insert (ti); +        } + +      } contains_compositor_init_; +    } + +    ContainsCompositor:: +    ContainsCompositor (UnsignedLong min, UnsignedLong max) +        : compositor_ (0), container_ (0), min_ (min), max_ (max) +    { +    } + +    // Compositor +    // +    namespace +    { +      struct CompositorInit +      { +        CompositorInit () +        { +          TypeInfo ti (typeid (Compositor)); +          ti.add_base (Access::public_, true, typeid (Particle)); +          RTTI::insert (ti); +        } + +      } compositor_init_; +    } + + +    // All +    // +    namespace +    { +      struct AllInit +      { +        AllInit () +        { +          TypeInfo ti (typeid (All)); +          ti.add_base (Access::public_, true, typeid (Compositor)); +          RTTI::insert (ti); +        } + +      } all_init_; +    } + +    All:: +    All (Path const& file, UnsignedLong line, UnsignedLong column) +        : Node (file, line, column) +    { +    } + + +    // Choice +    // +    namespace +    { +      struct ChoiceInit +      { +        ChoiceInit () +        { +          TypeInfo ti (typeid (Choice)); +          ti.add_base (Access::public_, true, typeid (Compositor)); +          RTTI::insert (ti); +        } + +      } choice_init_; +    } + +    Choice:: +    Choice (Path const& file, UnsignedLong line, UnsignedLong column) +        : Node (file, line, column) +    { +    } + +    // Sequence +    // +    namespace +    { +      struct SequenceInit +      { +        SequenceInit () +        { +          TypeInfo ti (typeid (Sequence)); +          ti.add_base (Access::public_, true, typeid (Compositor)); +          RTTI::insert (ti); +        } + +      } sequence_init_; +    } + +    Sequence:: +    Sequence (Path const& file, UnsignedLong line, UnsignedLong column) +        : Node (file, line, column) +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/compositors.hxx b/libxsd-frontend/xsd-frontend/semantic-graph/compositors.hxx new file mode 100644 index 0000000..c82d8a4 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/compositors.hxx @@ -0,0 +1,263 @@ +// file      : xsd-frontend/semantic-graph/compositors.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_COMPOSITORS_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_COMPOSITORS_HXX + +#include <cult/containers/list.hxx> + +#include <xsd-frontend/semantic-graph/elements.hxx> +#include <xsd-frontend/semantic-graph/particle.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    // +    // +    class ContainsCompositor: public virtual Edge +    { +    public: +      Compositor& +      compositor () const +      { +        return *compositor_; +      } + +      Node& +      container () const +      { +        return *container_; +      } + +    public: +      UnsignedLong +      min () const +      { +        return min_; +      } + +      UnsignedLong +      max () const +      { +        return max_; +      } + +    protected: +      friend class Bits::Graph<Node, Edge>; + +      ContainsCompositor (UnsignedLong min, UnsignedLong max); + +      Void +      set_left_node (Node& n) +      { +        container_ = &n; +      } + +      Void +      set_right_node (Compositor& n) +      { +        compositor_ = &n; +      } + +      Void +      clear_left_node (Node& n) +      { +        assert (container_ == &n); +        container_ = 0; +      } + +      Void +      clear_right_node (Compositor& n) +      { +        assert (compositor_ == &n); +        compositor_ = 0; +      } + +    private: +      Compositor* compositor_; +      Node* container_; +      UnsignedLong min_, max_; +    }; + + +    // +    // +    class Compositor: public virtual Particle +    { +      typedef +      Cult::Containers::List<ContainsParticle*> +      ContainsList; + +    public: +      typedef +      Bits::PointerIterator<ContainsList::Iterator> +      ContainsIterator; + +      typedef +      Bits::PointerIterator<ContainsList::ConstIterator> +      ContainsConstIterator; + +      ContainsIterator +      contains_begin () +      { +        return contains_.begin (); +      } + +      ContainsIterator +      contains_end () +      { +        return contains_.end (); +      } + +      ContainsConstIterator +      contains_begin () const +      { +        return contains_.begin (); +      } + +      ContainsConstIterator +      contains_end () const +      { +        return contains_.end (); +      } + +    public: +      Boolean +      contained_compositor_p () +      { +        return contained_compositor_ != 0; +      } + +      ContainsCompositor& +      contained_compositor () +      { +        assert (contained_compositor_ != 0); +        return *contained_compositor_; +      } + +    public: +      UnsignedLong +      min () const +      { +        if (contained_compositor_ != 0) +          return contained_compositor_->min (); +        else +          return Particle::min (); +      } + +      UnsignedLong +      max () const +      { +        if (contained_compositor_ != 0) +          return contained_compositor_->max (); +        else +          return Particle::max (); +      } + +    protected: +      friend class Bits::Graph<Node, Edge>; + +      Compositor () +          : contained_compositor_ (0) +      { +      } + +      Void +      add_edge_left (ContainsParticle& e) +      { +        contains_.push_back (&e); +      } + +      Void +      remove_edge_left (ContainsParticle& e) +      { +        for (ContainsList::Iterator i (contains_.begin ()); +             i != contains_.end (); ++i) +        { +          if (*i == &e) +          { +            contains_.erase (i); +            break; +          } +        } +      } + +      //@@ Ideally should be protected but then NodeArg has no way to +      //   access it. Maybe when (if) I move NodeArg into Grpah I can +      //   resolve this. +      // +    public: +      Void +      add_edge_left (ContainsParticle& e, ContainsIterator const& after) +      { +        if (after.base () == contains_.end ()) +          contains_.push_front (&e); +        else +        { +          ContainsList::Iterator i (after.base ()); +          contains_.insert (++i, &e); +        } +      } + +    protected: +      using Node::add_edge_right; +      using Particle::add_edge_right; +      using Particle::remove_edge_right; + +      Void +      add_edge_right (ContainsCompositor& e) +      { +        contained_compositor_ = &e; +      } + +      Void +      remove_edge_right (ContainsCompositor& e) +      { +        assert (contained_compositor_ == &e); +        contained_compositor_ = 0; +      } + +    private: +      ContainsList contains_; +      ContainsCompositor* contained_compositor_; +    }; + + +    // +    // +    class All: public virtual Compositor +    { +    protected: +      friend class Bits::Graph<Node, Edge>; + +      All (Path const& file, UnsignedLong line, UnsignedLong column); +    }; + + +    // +    // +    class Choice: public virtual Compositor +    { +    protected: +      friend class Bits::Graph<Node, Edge>; + +      Choice (Path const& file, UnsignedLong line, UnsignedLong column); +    }; + + +    // +    // +    class Sequence: public virtual Compositor +    { +    protected: +      friend class Bits::Graph<Node, Edge>; + +      Sequence (Path const& file, UnsignedLong line, UnsignedLong column); +    }; +  } +} + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_COMPOSITORS_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/element-group.cxx b/libxsd-frontend/xsd-frontend/semantic-graph/element-group.cxx new file mode 100644 index 0000000..0e71aa6 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/element-group.cxx @@ -0,0 +1,38 @@ +// file      : xsd-frontend/semantic-graph/element-group.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/semantic-graph/element-group.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    namespace RTTI = Cult::RTTI; + +    using RTTI::Access; +    using RTTI::TypeInfo; + + +    namespace +    { +      struct ElementGroupInit +      { +        ElementGroupInit () +        { +          TypeInfo ti (typeid (ElementGroup)); +          ti.add_base (Access::public_, true, typeid (Scope)); +          RTTI::insert (ti); +        } + +      } element_group_init_; +    } + +    ElementGroup:: +    ElementGroup (Path const& file, UnsignedLong line, UnsignedLong column) +        : Node (file, line, column), contains_compositor_ (0) +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/element-group.hxx b/libxsd-frontend/xsd-frontend/semantic-graph/element-group.hxx new file mode 100644 index 0000000..23514b5 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/element-group.hxx @@ -0,0 +1,45 @@ +// file      : xsd-frontend/semantic-graph/element-group.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_ELEMENT_GROUP_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_ELEMENT_GROUP_HXX + +#include <xsd-frontend/semantic-graph/elements.hxx> +#include <xsd-frontend/semantic-graph/compositors.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    class ElementGroup: public virtual Scope +    { +    public: +      ContainsCompositor& +      contains_compositor () +      { +        assert (contains_compositor_ != 0); +        return *contains_compositor_; +      } + +    protected: +      friend class Bits::Graph<Node, Edge>; + +      ElementGroup (Path const& file, UnsignedLong line, UnsignedLong column); + +      using Scope::add_edge_left; + +      Void +      add_edge_left (ContainsCompositor& e) +      { +        contains_compositor_ = &e; +      } + +    private: +      ContainsCompositor* contains_compositor_; +    }; +  } +} + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_ELEMENT_GROUP_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/element.cxx b/libxsd-frontend/xsd-frontend/semantic-graph/element.cxx new file mode 100644 index 0000000..1d8cda5 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/element.cxx @@ -0,0 +1,63 @@ +// file      : xsd-frontend/semantic-graph/element.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/semantic-graph/element.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    namespace RTTI = Cult::RTTI; + +    using RTTI::Access; +    using RTTI::TypeInfo; + + +    // Substitutes +    // +    namespace +    { +      struct SubstitutesInit +      { +        SubstitutesInit () +        { +          TypeInfo ti (typeid (Substitutes)); +          ti.add_base (Access::public_, true, typeid (Edge)); +          RTTI::insert (ti); +        } + +      } substitutes_init_; +    } + +    // Element +    // +    namespace +    { +      struct ElementInit +      { +        ElementInit () +        { +          TypeInfo ti (typeid (Element)); +          ti.add_base (Access::public_, true, typeid (Member)); +          ti.add_base (Access::public_, true, typeid (Particle)); +          RTTI::insert (ti); +        } + +      } element_init_; +    } + +    Element:: +    Element (Path const& file, +             UnsignedLong line, +             UnsignedLong column, +             Boolean global, +             Boolean qualified) +        : Node (file, line, column), +          Member (global, qualified), +          substitutes_ (0) +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/element.hxx b/libxsd-frontend/xsd-frontend/semantic-graph/element.hxx new file mode 100644 index 0000000..e7046e4 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/element.hxx @@ -0,0 +1,105 @@ +// file      : xsd-frontend/semantic-graph/element.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_ELEMENT_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_ELEMENT_HXX + +#include <xsd-frontend/semantic-graph/elements.hxx> +#include <xsd-frontend/semantic-graph/particle.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    class Element; + +    class Substitutes: public virtual Edge +    { +    public: +      Element& +      substitution () const +      { +        return *substitution_; +      } + +      Element& +      root () const +      { +        return *root_; +      } + +    protected: +      friend class Bits::Graph<Node, Edge>; + +      Substitutes () +      { +      } + +      Void +      set_left_node (Element& n) +      { +        substitution_ = &n; +      } + +      Void +      set_right_node (Element& n) +      { +        root_ = &n; +      } + +    private: +      Element* root_; +      Element* substitution_; +    }; + + +    class Element: public virtual Member, +                   public virtual Particle +    { +    public: +      Boolean +      substitutes_p () const +      { +        return substitutes_ != 0; +      } + +      Substitutes& +      substitutes () const +      { +        assert (substitutes_ != 0); +        return *substitutes_; +      } + +    protected: +      friend class Bits::Graph<Node, Edge>; + +      Element (Path const& file, +               UnsignedLong line, +               UnsignedLong column, +               Boolean global, +               Boolean qualified); + +      Void +      add_edge_left (Substitutes& e) +      { +        substitutes_ = &e; +      } + +      Void +      add_edge_right (Substitutes&) +      { +      } + +      using Member::add_edge_left; +      using Member::add_edge_right; +      using Particle::add_edge_right; + +    private: +      Substitutes* substitutes_; +    }; +  } +} + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_ELEMENT_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/elements.cxx b/libxsd-frontend/xsd-frontend/semantic-graph/elements.cxx new file mode 100644 index 0000000..6a2addf --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/elements.cxx @@ -0,0 +1,350 @@ +// file      : xsd-frontend/semantic-graph/elements.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <algorithm> + +#include <xsd-frontend/semantic-graph/elements.hxx> +#include <xsd-frontend/semantic-graph/annotation.hxx> + +using namespace std; + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    // Node +    // +    Annotation& Node:: +    annotation () +    { +      return annotates_->annotation (); +    } + +    // Type +    // +    Void Type:: +    remove_edge_left (Arguments& a) +    { +      ArgumentsSet::Iterator i (arguments_.find (&a)); +      assert (i != arguments_.end ()); +      arguments_.erase (i); +    } + +    // Specialization +    // +    Void Specialization:: +    remove_edge_right (Arguments& a) +    { +      // The number of entries should be small so linear search will do. +      // +      Argumented::Iterator i ( +        std::find (argumented_.begin (), argumented_.end (), &a)); + +      assert (i != argumented_.end ()); +      argumented_.erase (i); +    } + +    namespace RTTI = Cult::RTTI; + +    using RTTI::Access; +    using RTTI::TypeInfo; + +    namespace +    { +      // Edge +      // +      struct EdgeInit +      { +        EdgeInit () +        { +          TypeInfo ti (typeid (Edge)); +          RTTI::insert (ti); +        } + +      } edge_init_; + + +      // Node +      // +      struct NodeInit +      { +        NodeInit () +        { +          TypeInfo ti (typeid (Node)); +          RTTI::insert (ti); +        } + +      } node_init_; + + +      // Names +      // +      struct NamesInit +      { +        NamesInit () +        { +          TypeInfo ti (typeid (Names)); +          ti.add_base (Access::public_, true, typeid (Edge)); +          RTTI::insert (ti); +        } + +      } names_init_; + + +      // Nameable +      // +      struct NameableInit +      { +        NameableInit () +        { +          TypeInfo ti (typeid (Nameable)); +          ti.add_base (Access::public_, true, typeid (Node)); +          RTTI::insert (ti); +        } + +      } nameable_init_; + + +      // Scope +      // +      struct ScopeInit +      { +        ScopeInit () +        { +          TypeInfo ti (typeid (Scope)); +          ti.add_base (Access::public_, true, typeid (Nameable)); +          RTTI::insert (ti); +        } + +      } scope_init_; + + +      // Type +      // +      struct TypeInit +      { +        TypeInit () +        { +          TypeInfo ti (typeid (Type)); +          ti.add_base (Access::public_, true, typeid (Nameable)); +          RTTI::insert (ti); +        } + +      } type_init_; + + +      // Instance +      // +      struct InstanceInit +      { +        InstanceInit () +        { +          TypeInfo ti (typeid (Instance)); +          ti.add_base (Access::public_, true, typeid (Nameable)); +          RTTI::insert (ti); +        } + +      } instance_init_; + + +      // Belongs +      // +      struct BelongsInit +      { +        BelongsInit () +        { +          TypeInfo ti (typeid (Belongs)); +          ti.add_base (Access::public_, true, typeid (Edge)); +          RTTI::insert (ti); +        } + +      } belongs_init_; + + + +      // Inherits +      // +      struct InheritsInit +      { +        InheritsInit () +        { +          TypeInfo ti (typeid (Inherits)); +          ti.add_base (Access::public_, true, typeid (Edge)); +          RTTI::insert (ti); +        } + +      } inherits_init_; + + +      // Extends +      // +      struct ExtendsInit +      { +        ExtendsInit () +        { +          TypeInfo ti (typeid (Extends)); +          ti.add_base (Access::public_, true, typeid (Inherits)); +          RTTI::insert (ti); +        } + +      } extends_init_; + + +      // Restricts +      // +      struct RestrictsInit +      { +        RestrictsInit () +        { +          TypeInfo ti (typeid (Restricts)); +          ti.add_base (Access::public_, true, typeid (Inherits)); +          RTTI::insert (ti); +        } + +      } restricts_init_; + + +      // BelongsToNamespace +      // +      struct BelongsToNamespaceInit +      { +        BelongsToNamespaceInit () +        { +          TypeInfo ti (typeid (BelongsToNamespace)); +          ti.add_base (Access::public_, true, typeid (Edge)); +          RTTI::insert (ti); +        } + +      } belongs_to_namespace_init_; + + +      // Member +      // +      struct MemberInit +      { +        MemberInit () +        { +          TypeInfo ti (typeid (Member)); +          ti.add_base (Access::public_, true, typeid (Instance)); +          RTTI::insert (ti); +        } + +      } member_init_; + + +      // Specialization +      // +      struct SpecializationInit +      { +        SpecializationInit () +        { +          TypeInfo ti (typeid (Specialization)); +          ti.add_base (Access::public_, true, typeid (Type)); +          RTTI::insert (ti); +        } + +      } specialization_init_; + + +      // Arguments +      // +      struct ArgumentsInit +      { +        ArgumentsInit () +        { +          TypeInfo ti (typeid (Arguments)); +          ti.add_base (Access::public_, true, typeid (Edge)); +          RTTI::insert (ti); +        } + +      } arguments_init_; + + +      /* +      // Contains +      // +      struct ContainsInit +      { +        ContainsInit () +        { +          TypeInfo ti (typeid (Contains)); +          ti.add_base (Access::public_, true, typeid (Edge)); +          RTTI::insert (ti); +        } + +      } contains_init_; + + +      // Container +      // +      struct ContainerInit +      { +        ContainerInit () +        { +          TypeInfo ti (typeid (Container)); +          ti.add_base (Access::public_, true, typeid (Node)); +          RTTI::insert (ti); +        } + +      } container_init_; +      */ + + +      // AnyType +      // +      namespace +      { +        struct AnyTypeInit +        { +          AnyTypeInit () +          { +            TypeInfo ti (typeid (AnyType)); +            ti.add_base (Access::public_, true, typeid (SemanticGraph::Type)); +            RTTI::insert (ti); +          } + +        } any_type_init_; +      } + + +      // AnySimpleType +      // +      namespace +      { +        struct AnySimpleTypeInit +        { +          AnySimpleTypeInit () +          { +            TypeInfo ti (typeid (AnySimpleType)); +            ti.add_base (Access::public_, true, typeid (Type)); +            RTTI::insert (ti); +          } + +        } any_simple_type_init_; +      } +    } + + +    // Instance +    // +    Type& Instance:: +    type () const +    { +      return belongs ().type (); +    } +  } +} + +// Path +// +std::wostream& +operator<< (std::wostream& os, XSDFrontend::SemanticGraph::Path const& path) +{ +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 +  return os << path.native_file_string ().c_str (); +#else +  return os << path.string ().c_str (); +#endif +} diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/elements.hxx b/libxsd-frontend/xsd-frontend/semantic-graph/elements.hxx new file mode 100644 index 0000000..78b6615 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/elements.hxx @@ -0,0 +1,1247 @@ +// file      : xsd-frontend/semantic-graph/elements.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_ELEMENTS_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_ELEMENTS_HXX + +#include <iosfwd> + +#include <boost/filesystem/path.hpp> +#include <boost/filesystem/operations.hpp> +#include <boost/filesystem/exception.hpp> + +#include <cult/types.hxx> + +#include <cult/rtti/type-info.hxx> + +#include <cult/containers/set.hxx> +#include <cult/containers/map.hxx> +#include <cult/containers/list.hxx> +#include <cult/containers/pair.hxx> +#include <cult/containers/graph.hxx> +#include <cult/containers/vector.hxx> + +#include <frontend-elements/context.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    using namespace Cult::Types; + +    namespace Bits +    { +      using Cult::Containers::Graph; + +      //@@ Should end up in Cult::Meta +      // +      template <typename X> +      struct strip_pointer +      { +        typedef X Type; +      }; + +      template <typename X> +      struct strip_pointer<X*> +      { +        typedef X Type; +      }; + +      template <typename I> +      struct PointerIterator +      { +        typedef +        typename strip_pointer<typename I::Value>::Type +        Value; + +        typedef I BaseIterator; +        typedef Value& Reference; +        typedef Value* Pointer; + +        PointerIterator () +            : i_ () // i_ can be of a pointer type. +        { +        } + +        PointerIterator (I const& i) +            : i_ (i) +        { +        } + +      public: +        Reference +        operator* () const +        { +          return **i_; +        } + +        Pointer +        operator-> () const +        { +          return *i_; +        } + +        I const& +        base () const +        { +          return i_; +        } + +      public: +        PointerIterator& +        operator++ () +        { +          ++i_; +          return *this; +        } + +        PointerIterator +        operator++ (Int) +        { +          PointerIterator r (*this); +          ++i_; +          return r; +        } + +        PointerIterator& +        operator-- () +        { +          --i_; +          return *this; +        } + +        PointerIterator +        operator-- (Int) +        { +          PointerIterator r (*this); +          --i_; +          return r; +        } + +      private: +        I i_; +      }; + +      template <typename I> +      inline +      Boolean +      operator== (PointerIterator<I> const& a, PointerIterator<I> const& b) +      { +        return a.base () == b.base (); +      } + +      template <typename I> +      inline +      Boolean +      operator!= (PointerIterator<I> const& a, PointerIterator<I> const& b) +      { +        return a.base () != b.base (); +      } + +      template <typename I> +      inline +      typename PointerIterator<I>::BaseIterator::difference_type +      operator- (PointerIterator<I> const& a, PointerIterator<I> const& b) +      { +        return a.base () - b.base (); +      } +    } + +    // +    // +    typedef +    boost::filesystem::filesystem_error +    InvalidPath; + +    typedef +    boost::filesystem::path +    Path; + +    typedef +    Cult::Containers::Vector<Path> +    Paths; + +    typedef +    FrontendElements::Context +    Context; + +    // +    // +    class Node; +    class Edge; + +    // +    // +    class Annotates; +    class Annotation; + +    // +    // +    class Edge +    { +    public: +      Context& +      context () const +      { +        return context_; +      } + +      virtual +      ~Edge () +      { +      } + +    public: +      template <typename X> +      Boolean +      is_a () const +      { +        return dynamic_cast<X const*> (this) != 0; +      } + +    protected: +      friend class Bits::Graph<Node, Edge>; + +      Edge () +      { +      } + +    private: +      mutable Context context_; +    }; + +    inline Boolean +    operator== (Edge const& x, Edge const& y) +    { +      return &x == &y; +    } + + +    // +    // +    class Node +    { +    public: +      Context& +      context () const +      { +        return context_; +      } + +    public: +      Path const& +      file () const +      { +        return file_; +      } + +      UnsignedLong +      line () const +      { +        return line_; +      } + +      UnsignedLong +      column () const +      { +        return column_; +      } + +    public: +      Boolean +      annotated_p () const +      { +        return annotates_ != 0; +      } + +      Annotates& +      annotated () const +      { +        return *annotates_; +      } + +      Annotation& +      annotation (); + +    public: +      template <typename X> +      Boolean +      is_a () const +      { +        return dynamic_cast<X const*> (this) != 0; +      } + +    public: + +      virtual +      ~Node () +      { +      } + +    protected: +      friend class Bits::Graph<Node, Edge>; + +      Node (Path const& file, UnsignedLong line, UnsignedLong column) +          : annotates_ (0), file_ (file), line_ (line), column_ (column) +      { +      } + +      Node () // For virtual inheritance. +      { +        abort (); // Told you so! +      } + +      Void +      add_edge_right (Annotates& a) +      { +        annotates_ = &a; +      } + +    private: +      mutable Context context_; +      Annotates* annotates_; +      Path file_; +      UnsignedLong line_; +      UnsignedLong column_; +    }; + +    inline Boolean +    operator== (Node const& x, Node const& y) +    { +      return &x == &y; +    } + + +    // +    // +    typedef WideString Name; + + +    // +    // +    class Scope; +    class Nameable; + + +    // +    // +    class Names: public virtual Edge +    { +    public: +      Name +      name () const +      { +        return name_; +      } + +      Scope& +      scope () const +      { +        return *scope_; +      } + +      Nameable& +      named () const +      { +        return *named_; +      } + +    protected: +      friend class Bits::Graph<Node, Edge>; + +      Names (Name const& name) +          : name_ (name) +      { +      } + +      Void +      set_left_node (Scope& n) +      { +        scope_ = &n; +      } + +      Void +      set_right_node (Nameable& n) +      { +        named_ = &n; +      } + +      Void +      clear_left_node (Scope& n) +      { +        assert (scope_ == &n); +        scope_ = 0; +      } + +      Void +      clear_right_node (Nameable& n) +      { +        assert (named_ == &n); +        named_ = 0; +      } + +    private: +      Scope* scope_; +      Nameable* named_; +      Name name_; +    }; + + +    class Nameable: public virtual Node +    { +    public: +      Boolean +      named_p () const +      { +        return named_ != 0; +      } + +      Name +      name () const +      { +        assert (named_p ()); +        return named_->name (); +      } + +      Scope& +      scope () +      { +        assert (named_p ()); +        return named_->scope (); +      } + +      Names& +      named () +      { +        assert (named_p ()); +        return *named_; +      } + +    protected: +      friend class Bits::Graph<Node, Edge>; + +      Nameable () +          : named_ (0) +      { +      } + +      Void +      add_edge_right (Names& e) +      { +        named_ = &e; +      } + +      Void +      remove_edge_right (Names& e) +      { +        assert (named_ == &e); +        named_ = 0; +      } + +      using Node::add_edge_right; + +    private: +      Names* named_; +    }; + + +    // +    // +    typedef +    Cult::Containers::Set<Nameable*> +    Nameables; + + +    // +    // +    class Scope: public virtual Nameable +    { +    protected: +      typedef +      Cult::Containers::List<Names*> +      NamesList; + +      typedef +      Cult::Containers::Map<Names*, NamesList::Iterator> +      ListIteratorMap; + +      typedef +      Cult::Containers::Map<Name, NamesList> +      NamesMap; + +    public: +      typedef +      Bits::PointerIterator<NamesList::Iterator> +      NamesIterator; + +      typedef +      Bits::PointerIterator<NamesList::ConstIterator> +      NamesConstIterator; + +      typedef +      Cult::Containers::Pair <NamesConstIterator, NamesConstIterator> +      NamesIteratorPair; + +      NamesIterator +      names_begin () +      { +        return names_.begin (); +      } + +      NamesIterator +      names_end () +      { +        return names_.end (); +      } + +      NamesConstIterator +      names_begin () const +      { +        return names_.begin (); +      } + +      NamesConstIterator +      names_end () const +      { +        return names_.end (); +      } + +      virtual NamesIteratorPair +      find (Name const& name) const +      { +        NamesMap::ConstIterator i (names_map_.find (name)); + +        if (i == names_map_.end ()) +          return NamesIteratorPair (names_.end (), names_.end ()); +        else +          return NamesIteratorPair (i->second.begin (), i->second.end ()); +      } + +      NamesIterator +      find (Names& e) +      { +        ListIteratorMap::Iterator i (iterator_map_.find (&e)); +        return i != iterator_map_.end () ? i->second : names_.end (); +      } + +    protected: +      friend class Bits::Graph<Node, Edge>; + +      Scope (Path const& file, UnsignedLong line, UnsignedLong column) +          : Node (file, line, column) +      { +      } + +      Scope () +      { +      } + +      Void +      add_edge_left (Names& e) +      { +        NamesList::Iterator i (names_.insert (names_.end (), &e)); +        iterator_map_[&e] = i; +        names_map_[e.name ()].push_back (&e); +      } + +      Void +      remove_edge_left (Names& e) +      { +        ListIteratorMap::Iterator i (iterator_map_.find (&e)); +        assert (i != iterator_map_.end ()); + +        names_.erase (i->second); +        iterator_map_.erase (i); + +        NamesMap::Iterator j (names_map_.find (e.name ())); + +        for (NamesList::Iterator i (j->second.begin ()); +             i != j->second.end (); ++i) +        { +          if (*i == &e) +            i = j->second.erase (i); +        } +      } + +      //@@ Ideally should be protected but then NodeArg has no way to +      //   access it. Maybe when (if) I move NodeArg into Grpah I can +      //   resolve this. +      // +    public: +      Void +      add_edge_left (Names& e, NamesIterator const& after) +      { +        NamesList::Iterator i; + +        if (after.base () == names_.end ()) +          i = names_.insert (names_.begin (), &e); +        else +        { +          NamesList::Iterator j (after.base ()); +          i = names_.insert (++j, &e); +        } + +        iterator_map_[&e] = i; +        names_map_[e.name ()].push_back (&e); +      } + +    protected: +      using Nameable::add_edge_right; + +    private: +      NamesList names_; +      ListIteratorMap iterator_map_; +      NamesMap names_map_; +    }; + + +    // +    // +    class Belongs; +    class Inherits; +    class Arguments; + +    class Type: public virtual Nameable +    { +    protected: +      typedef +      Cult::Containers::Vector<Belongs*> +      Classifies; + +      typedef +      Cult::Containers::Vector<Inherits*> +      Begets; + +      typedef +      Cult::Containers::Set<Arguments*> +      ArgumentsSet; + +    public: +      typedef +      Bits::PointerIterator<Classifies::ConstIterator> +      ClassifiesIterator; + +      ClassifiesIterator +      classifies_begin () const +      { +        return classifies_.begin (); +      } + +      ClassifiesIterator +      classifies_end () const +      { +        return classifies_.end (); +      } + +      // +      // +      Boolean +      inherits_p () const +      { +        return inherits_ != 0; +      } + +      Inherits& +      inherits () const +      { +        assert (inherits_ != 0); +        return *inherits_; +      } + +      // +      // +      typedef +      Bits::PointerIterator<Begets::ConstIterator> +      BegetsIterator; + +      BegetsIterator +      begets_begin () const +      { +        return begets_.begin (); +      } + +      BegetsIterator +      begets_end () const +      { +        return begets_.end (); +      } + +      // +      // +      typedef +      Bits::PointerIterator<ArgumentsSet::ConstIterator> +      ArgumentsIterator; + +      ArgumentsIterator +      arguments_begin () const +      { +        return arguments_.begin (); +      } + +      ArgumentsIterator +      arguments_end () const +      { +        return arguments_.end (); +      } + +    protected: +      friend class Bits::Graph<Node, Edge>; + +      Type () +          : inherits_ (0) +      { +      } + +      Void +      add_edge_right (Belongs& e) +      { +        classifies_.push_back (&e); +      } + +      Void +      add_edge_right (Inherits& e) +      { +        begets_.push_back (&e); +      } + +      using Nameable::add_edge_right; + +      Void +      add_edge_left (Arguments& a) +      { +        arguments_.insert (&a); +      } + +      Void +      remove_edge_left (Arguments&); + +      Void +      add_edge_left (Inherits& e) +      { +        inherits_ = &e; +      } + +    private: +      Inherits* inherits_; +      Begets begets_; +      Classifies classifies_; +      ArgumentsSet arguments_; +    }; + + +    class Instance: public virtual Nameable +    { +    public: +      Belongs& +      belongs () const +      { +        return *belongs_; +      } + +      Type& +      type () const; + +      Boolean +      typed_p () const +      { +        return belongs_ != 0; +      } + +    protected: +      friend class Bits::Graph<Node, Edge>; + +      Instance () +          : belongs_ (0) +      { +      } + +      Void +      add_edge_left (Belongs& e) +      { +        belongs_ = &e; +      } + +    private: +      Belongs* belongs_; +    }; + + +    class Belongs: public virtual Edge +    { +    public: +      Instance& +      instance () const +      { +        return *instance_; +      } + +      Type& +      type () const +      { +        return *type_; +      } + +    protected: +      friend class Bits::Graph<Node, Edge>; + +      Belongs () +      { +      } + +      Void +      set_left_node (Instance& n) +      { +        instance_ = &n; +      } + +      Void +      set_right_node (Type& n) +      { +        type_ = &n; +      } + +    private: +      Instance* instance_; +      Type* type_; +    }; + + +    // +    // +    class Inherits: public virtual Edge +    { +    public: +      Type& +      base () const +      { +        return *base_; +      } + +      Type& +      derived () const +      { +        return *derived_; +      } + +    protected: +      friend class Bits::Graph<Node, Edge>; + +      Inherits () +      { +      } + +      Void +      set_left_node (Type& n) +      { +        derived_ = &n; +      } + +      Void +      set_right_node (Type& n) +      { +        base_ = &n; +      } + +    private: +      Type* base_; +      Type* derived_; +    }; + + +    class Extends: public virtual Inherits +    { +    protected: +      friend class Bits::Graph<Node, Edge>; + +      Extends () +      { +      } +    }; + +    class Restricts: public virtual Inherits +    { +    protected: +      typedef +      Cult::Containers::Map<WideString, WideString> +      Facets; + +    public: +      typedef +      Facets::Iterator +      FacetIterator; + +      Boolean +      facet_empty () +      { +        return facets_.empty (); +      } + +      FacetIterator +      facet_begin () +      { +        return facets_.begin (); +      } + +      FacetIterator +      facet_end () +      { +        return facets_.end (); +      } + +      FacetIterator +      facet_find (WideString const& name) +      { +        return facets_.find (name); +      } + +      Void +      facet_insert (String const& name, String const& value) +      { +        facets_[name] = value; +      } + +    protected: +      friend class Bits::Graph<Node, Edge>; + +      Restricts () +      { +      } + +    protected: +      Facets facets_; +    }; + + +    // +    // +    class Member; +    class Namespace; + +    class BelongsToNamespace: public virtual Edge +    { +    public: +      Member& +      member () const +      { +        assert (member_ != 0); +        return *member_; +      } + +      Namespace& +      namespace_ () const +      { +        assert (namespace__ != 0); +        return *namespace__; +      } + +    protected: +      friend class Bits::Graph<Node, Edge>; + +      BelongsToNamespace () +          : member_ (0), namespace__ (0) +      { +      } + +      Void +      set_left_node (Member& n) +      { +        member_ = &n; +      } + +      Void +      set_right_node (Namespace& n) +      { +        namespace__ = &n; +      } + +    private: +      Member* member_; +      Namespace* namespace__; +    }; + +    // +    // +    class Member: public virtual Instance +    { +    public: +      // Member is global either if it is defined outside any type +      // or it is a ref="" of a global member. +      // +      Boolean +      global_p () const +      { +        return global_; +      } + +      Boolean +      qualified_p () const +      { +        return qualified_; +      } + +      // Note that only qualified members belong to a namespace. +      // +      Namespace& +      namespace_ () const +      { +        assert (belongs_to_namespace_ != 0); +        return belongs_to_namespace_->namespace_ (); +      } + + +      // Default and fixed value API. Note that the fixed value semantics +      // is a superset of the default value semantics. As such setting the +      // fixed value appears as if the default value was also set. +      // +      Boolean +      default_p () const +      { +        return value_type_ != ValueType::none; +      } + +      Boolean +      fixed_p () const +      { +        return value_type_ == ValueType::fixed; +      } + +      struct NoValue {}; + +      WideString +      value () const +      { +        if (value_type_ != ValueType::none) +          return value_; +        else +          throw NoValue (); +      } + +      // +      // +      Void +      default_ (WideString const& v) +      { +        value_ = v; +        value_type_ = ValueType::default_; +      } + +      Void +      fixed (WideString const& v) +      { +        value_ = v; +        value_type_ = ValueType::fixed; +      } + +    protected: +      friend class Bits::Graph<Node, Edge>; + +      Member (Boolean global, Boolean qualified) +          : global_ (global), +            qualified_ (qualified), +            belongs_to_namespace_ (0), +            value_type_ (ValueType::none) +      { +      } + +      Void +      add_edge_left (BelongsToNamespace& e) +      { +        // In the parser we sometimes re-add the same adge. +        // +        belongs_to_namespace_ = &e; +      } + +      using Instance::add_edge_left; + +    private: +      Boolean global_; +      Boolean qualified_; +      BelongsToNamespace* belongs_to_namespace_; + +      struct ValueType +      { +        enum Value +        { +          none, +          default_, +          fixed +        }; +      }; + +      WideString value_; +      ValueType::Value value_type_; +    }; + + +    // Parametric types. +    // + +    class Specialization: public virtual Type +    { +      typedef +      Cult::Containers::Vector<Arguments*> +      Argumented; + +    public: +      typedef +      Bits::PointerIterator<Argumented::Iterator> +      ArgumentedIterator; + +      typedef +      Bits::PointerIterator<Argumented::ConstIterator> +      ArgumentedConstIterator; + +      ArgumentedIterator +      argumented_begin () +      { +        return argumented_.begin (); +      } + +      ArgumentedConstIterator +      argumented_begin () const +      { +        return argumented_.begin (); +      } + +      ArgumentedIterator +      argumented_end () +      { +        return argumented_.end (); +      } + +      ArgumentedConstIterator +      argumented_end () const +      { +        return argumented_.end (); +      } + +      // Shortcut for one-argument specializations. +      // +      Arguments& +      argumented () const +      { +        return *argumented_[0]; +      } + +    protected: +      friend class Bits::Graph<Node, Edge>; + +      using Type::add_edge_right; + +      Void +      add_edge_right (Arguments& a) +      { +        argumented_.push_back (&a); +      } + +      Void +      remove_edge_right (Arguments&); + +    public: +      Void +      add_edge_right (Arguments& a, ArgumentedIterator const& pos) +      { +        argumented_.insert (pos.base (), &a); +      } + +    private: +      Argumented argumented_; +    }; + + +    class Arguments: public virtual Edge +    { +    public: +      Type& +      type () const +      { +        return *type_; +      } + +      Specialization& +      specialization () const +      { +        return *specialization_; +      } + +    protected: +      friend class Bits::Graph<Node, Edge>; + +      void +      set_left_node (Type& n) +      { +        type_ = &n; +      } + +      void +      clear_left_node (Type& n) +      { +        assert (type_ == &n); +        type_ = 0; +      } + +      void +      set_right_node (Specialization& s) +      { +        specialization_ = &s; +      } + +      void +      clear_right_node (Specialization& s) +      { +        assert (specialization_ == &s); +        specialization_ = 0; +      } + +    private: +      Type* type_; +      Specialization* specialization_; +    }; + + +    // +    // +    class AnyType: public virtual Type +    { +    protected: +      friend class Bits::Graph<Node, Edge>; + +      AnyType (Path const& file, UnsignedLong line, UnsignedLong column) +          : Node (file, line, column) +      { +      } + +      AnyType () // For virtual inheritance. +      { +      } +    }; + + +    // +    // +    class AnySimpleType: public virtual Type +    { +    protected: +      friend class Bits::Graph<Node, Edge>; + +      AnySimpleType (Path const& file, UnsignedLong line, UnsignedLong column) +          : Node (file, line, column) +      { +      } + +      AnySimpleType () // For virtual inheritance. +      { +      } +    }; +  } +} + +// ADL won't find it because Path is a typedef. Note that this +// function prints in native format. +// +std::wostream& +operator<< (std::wostream& os, XSDFrontend::SemanticGraph::Path const& path); + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_ELEMENTS_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/enumeration.cxx b/libxsd-frontend/xsd-frontend/semantic-graph/enumeration.cxx new file mode 100644 index 0000000..adcf71e --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/enumeration.cxx @@ -0,0 +1,67 @@ +// file      : xsd-frontend/semantic-graph/enumeration.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/semantic-graph/enumeration.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    namespace RTTI = Cult::RTTI; + +    using RTTI::Access; +    using RTTI::TypeInfo; + +    namespace +    { +      // Enumeration +      // +      struct EnumerationInit +      { +        EnumerationInit () +        { +          TypeInfo ti (typeid (Enumeration)); +          ti.add_base (Access::public_, true, typeid (Complex)); +          RTTI::insert (ti); +        } + +      } enumeration_init_; + + +      // Enumerator +      // +      struct EnumeratorInit +      { +        EnumeratorInit () +        { +          TypeInfo ti (typeid (Enumerator)); +          ti.add_base (Access::public_, true, typeid (Instance)); +          RTTI::insert (ti); +        } + +      } enumerator_init_; +    } + + +    // Enumeration +    // + +    Enumeration:: +    Enumeration (Path const& file, UnsignedLong line, UnsignedLong column) +        : Node (file, line, column) +    { +    } + + +    // Enumerator +    // + +    Enumerator:: +    Enumerator (Path const& file, UnsignedLong line, UnsignedLong column) +        : Node (file, line, column) +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/enumeration.hxx b/libxsd-frontend/xsd-frontend/semantic-graph/enumeration.hxx new file mode 100644 index 0000000..a21e8f3 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/enumeration.hxx @@ -0,0 +1,35 @@ +// file      : xsd-frontend/semantic-graph/enumeration.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_ENUMERATION_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_ENUMERATION_HXX + +#include <xsd-frontend/semantic-graph/elements.hxx> +#include <xsd-frontend/semantic-graph/complex.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    class Enumeration: public virtual Complex +    { +    protected: +      friend class Bits::Graph<Node, Edge>; + +      Enumeration (Path const& file, UnsignedLong line, UnsignedLong column); +    }; + + +    class Enumerator: public virtual Instance +    { +    protected: +      friend class Bits::Graph<Node, Edge>; + +      Enumerator (Path const& file, UnsignedLong line, UnsignedLong column); +    }; +  } +} + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_ENUMERATION_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/fundamental.cxx.m4 b/libxsd-frontend/xsd-frontend/semantic-graph/fundamental.cxx.m4 new file mode 100644 index 0000000..cc1316c --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/fundamental.cxx.m4 @@ -0,0 +1,216 @@ +divert(-1) + +# file      : xsd-frontend/semantic-graph/fundamental.cxx.m4 +# author    : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +# license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +include(`fundamental.m4') + +define(`fundamental_type', +  `fundamental_type_impl(`make_class_name(`$1')', `make_var_name(`$1')')') + + +define(`fundamental_type_impl', ` + +      // $1 +      // +      namespace +      { +        struct $1Init +        { +          $1Init () +          { +            TypeInfo ti (typeid ($1)); +            ti.add_base (Access::public_, true, typeid (Type)); +            RTTI::insert (ti); +          } + +        } $2_init_; +      } + +      $1:: +      $1 (Path const& file, +          SemanticGraph::UnsignedLong line, +          SemanticGraph::UnsignedLong column) +        : Node (file, line, column) +      { +      }') + +divert(0)dnl +dnl +dnl +dnl +// file      : xsd-frontend/semantic-graph/fundamental.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Note, that this file is automatically generated! +// + +#include <xsd-frontend/semantic-graph/fundamental.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    namespace Fundamental +    { +      namespace RTTI = Cult::RTTI; + +      using RTTI::Access; +      using RTTI::TypeInfo; + + +      // Type +      // +      namespace +      { +        struct TypeInit +        { +          TypeInit () +          { +            TypeInfo ti (typeid (Type)); +            ti.add_base (Access::public_, true, typeid (SemanticGraph::Type)); +            RTTI::insert (ti); +          } + +        } any_type_init_; +      } + +      Type:: +      Type () +      { +      } +dnl +dnl Integers. +dnl +fundamental_type(`byte') +fundamental_type(`unsigned byte') +fundamental_type(`short') +fundamental_type(`unsigned short') +fundamental_type(`int') +fundamental_type(`unsigned int') +fundamental_type(`long') +fundamental_type(`unsigned long') +fundamental_type(`integer') +fundamental_type(`non positive integer') +fundamental_type(`non negative integer') +fundamental_type(`positive integer') +fundamental_type(`negative integer') +dnl +dnl Boolean. +dnl +fundamental_type(`boolean') +dnl +dnl Floats. +dnl +fundamental_type(`float') +fundamental_type(`double') +fundamental_type(`decimal') +dnl +dnl Strings. +dnl +fundamental_type(`string') +fundamental_type(`normalized string') +fundamental_type(`token') +fundamental_type(`name') +fundamental_type(`name token') +fundamental_type(`name tokens') +fundamental_type(`NC name') +fundamental_type(`language') +dnl +dnl Qualified name. +dnl +fundamental_type(`q name') +dnl +dnl ID/IDREF. +dnl +fundamental_type(`id') + + +      // IdRef +      // +      namespace +      { +        struct IdRefInit +        { +          IdRefInit () +          { +            TypeInfo ti (typeid (IdRef)); +	    ti.add_base (Access::public_, true, typeid (Type)); +            ti.add_base (Access::public_, true, typeid (Specialization)); +            RTTI::insert (ti); +          } + +        } id_ref_init_; +      } + +      IdRef:: +      IdRef (Path const& file, +             SemanticGraph::UnsignedLong line, +             SemanticGraph::UnsignedLong column) +          : Node (file, line, column) +      { +      } + + +      // IdRefs +      // +      namespace +      { +        struct IdRefsInit +        { +          IdRefsInit () +          { +            TypeInfo ti (typeid (IdRefs)); +	    ti.add_base (Access::public_, true, typeid (Type)); +            ti.add_base (Access::public_, true, typeid (Specialization)); +            RTTI::insert (ti); +          } + +        } id_refs_init_; +      } + +      IdRefs:: +      IdRefs (Path const& file, +              SemanticGraph::UnsignedLong line, +              SemanticGraph::UnsignedLong column) +          : Node (file, line, column) +      { +      } +dnl +dnl URI. +dnl +fundamental_type(`any URI') +dnl +dnl Binary. +dnl +fundamental_type(`base 64 binary') +fundamental_type(`hex binary') +dnl +dnl Date/time. +dnl +fundamental_type(`date') +fundamental_type(`date time') +fundamental_type(`duration') +fundamental_type(`day') +fundamental_type(`month') +fundamental_type(`month day') +fundamental_type(`year') +fundamental_type(`year month') +fundamental_type(`time') +dnl +dnl Entity. +dnl +fundamental_type(`entity') +fundamental_type(`entities') +dnl +dnl Notation. +dnl +fundamental_type(`notation') +dnl +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/fundamental.hxx.m4 b/libxsd-frontend/xsd-frontend/semantic-graph/fundamental.hxx.m4 new file mode 100644 index 0000000..f5a88a9 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/fundamental.hxx.m4 @@ -0,0 +1,165 @@ +divert(-1) + +# file      : xsd-frontend/semantic-graph/fundamental.hxx.m4 +# author    : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +# license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +include(`fundamental.m4') + +define(`fundamental_type', `fundamental_type_impl(`make_class_name(`$1')', `$1')') + +define(`fundamental_type_impl', ` + +      // +      // +      class $1: public virtual Type +      { +      protected: +        friend class Bits::Graph<Node, Edge>; + +        $1 (Path const& file, +            SemanticGraph::UnsignedLong line, +            SemanticGraph::UnsignedLong column); +      };') +divert(0)dnl +dnl +dnl +dnl +// file      : xsd-frontend/semantic-graph/fundamental.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Note, that this file is automatically generated! +// + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_FUNDAMENTAL_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_FUNDAMENTAL_HXX + +#include <xsd-frontend/semantic-graph/elements.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    namespace Fundamental +    { +      // +      // +      class Type: public virtual SemanticGraph::Type +      { +      protected: +        friend class Bits::Graph<Node, Edge>; + +        Type (); +      }; +dnl +dnl Integers. +dnl +fundamental_type(`byte') +fundamental_type(`unsigned byte') +fundamental_type(`short') +fundamental_type(`unsigned short') +fundamental_type(`int') +fundamental_type(`unsigned int') +fundamental_type(`long') +fundamental_type(`unsigned long') +fundamental_type(`integer') +fundamental_type(`non positive integer') +fundamental_type(`non negative integer') +fundamental_type(`positive integer') +fundamental_type(`negative integer') +dnl +dnl Boolean. +dnl +fundamental_type(`boolean') +dnl +dnl Floats. +dnl +fundamental_type(`float') +fundamental_type(`double') +fundamental_type(`decimal') +dnl +dnl Strings. +dnl +fundamental_type(`string') +fundamental_type(`normalized string') +fundamental_type(`token') +fundamental_type(`name') +fundamental_type(`name token') +fundamental_type(`name tokens') +fundamental_type(`NC name') +fundamental_type(`language') +dnl +dnl Qualified name. +dnl +fundamental_type(`q name') +dnl +dnl ID/IDREF. +dnl +fundamental_type(`id') + + +      // +      // +      class IdRef: public virtual Type, +                   public virtual Specialization +      { +      protected: +        friend class Bits::Graph<Node, Edge>; + +        IdRef (Path const& file, +               SemanticGraph::UnsignedLong line, +               SemanticGraph::UnsignedLong column); +      }; + + +      // +      // +      class IdRefs: public virtual Type, +                    public virtual Specialization +      { +      protected: +        friend class Bits::Graph<Node, Edge>; + +        IdRefs (Path const& file, +                SemanticGraph::UnsignedLong line, +                SemanticGraph::UnsignedLong column); +      }; +dnl +dnl URI. +dnl +fundamental_type(`any URI') +dnl +dnl Binary. +dnl +fundamental_type(`base 64 binary') +fundamental_type(`hex binary') +dnl +dnl Date/time. +dnl +fundamental_type(`date') +fundamental_type(`date time') +fundamental_type(`duration') +fundamental_type(`day') +fundamental_type(`month') +fundamental_type(`month day') +fundamental_type(`year') +fundamental_type(`year month') +fundamental_type(`time') +dnl +dnl Entity. +dnl +fundamental_type(`entity') +fundamental_type(`entities') +dnl +dnl Notation. +dnl +fundamental_type(`notation') +dnl +    } +  } +} + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_FUNDAMENTAL_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/fundamental.m4 b/libxsd-frontend/xsd-frontend/semantic-graph/fundamental.m4 new file mode 100644 index 0000000..735b35d --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/fundamental.m4 @@ -0,0 +1,18 @@ +# file      : xsd-frontend/semantic-graph/fundamental.m4 +# author    : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +# license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +define(`upcase', `translit(`$*', `a-z', `A-Z')') + + +define(`capitalize_word', +  `regexp(`$1', `^\(.\)\(.*\)', `upcase(`\1')`\2'')') + + +define(`capitalize', +  `patsubst(`$1', `\w+', `capitalize_word(`\&')')') + +define(`make_class_name', `patsubst(capitalize(`$1'), ` ')') + +define(`make_var_name', `patsubst(`$1', ` ', `_')') diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/list.cxx b/libxsd-frontend/xsd-frontend/semantic-graph/list.cxx new file mode 100644 index 0000000..3184041 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/list.cxx @@ -0,0 +1,37 @@ +// file      : xsd-frontend/semantic-graph/list.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/semantic-graph/list.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    namespace RTTI = Cult::RTTI; + +    using RTTI::Access; +    using RTTI::TypeInfo; + +    namespace +    { +      struct ListInit +      { +        ListInit () +        { +          TypeInfo ti (typeid (List)); +          ti.add_base (Access::public_, true, typeid (Specialization)); +          RTTI::insert (ti); +        } + +      } list_init_; +    } + +    List:: +    List (Path const& file, UnsignedLong line, UnsignedLong column) +        : Node (file, line, column) +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/list.hxx b/libxsd-frontend/xsd-frontend/semantic-graph/list.hxx new file mode 100644 index 0000000..3ba0c02 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/list.hxx @@ -0,0 +1,25 @@ +// file      : xsd-frontend/semantic-graph/list.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_LIST_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_LIST_HXX + +#include <xsd-frontend/semantic-graph/elements.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    class List: public virtual Specialization +    { +    protected: +      friend class Bits::Graph<Node, Edge>; + +      List (Path const& file, UnsignedLong line, UnsignedLong column); +    }; +  } +} + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_LIST_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/namespace.cxx b/libxsd-frontend/xsd-frontend/semantic-graph/namespace.cxx new file mode 100644 index 0000000..789b5d8 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/namespace.cxx @@ -0,0 +1,37 @@ +// file      : xsd-frontend/semantic-graph/namespace.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/semantic-graph/namespace.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    namespace RTTI = Cult::RTTI; + +    using RTTI::Access; +    using RTTI::TypeInfo; + +    namespace +    { +      struct NamespaceInit +      { +        NamespaceInit () +        { +          TypeInfo ti (typeid (Namespace)); +          ti.add_base (Access::public_, true, typeid (Scope)); +          RTTI::insert (ti); +        } + +      } namespace_init_; +    } + +    Namespace:: +    Namespace (Path const& file, UnsignedLong line, UnsignedLong column) +        : Node (file, line, column) +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/namespace.hxx b/libxsd-frontend/xsd-frontend/semantic-graph/namespace.hxx new file mode 100644 index 0000000..25bd1c0 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/namespace.hxx @@ -0,0 +1,32 @@ +// file      : xsd-frontend/semantic-graph/namespace.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_NAMESPACE_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_NAMESPACE_HXX + +#include <xsd-frontend/semantic-graph/elements.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    class Namespace : public virtual Scope +    { +    protected: +      friend class Bits::Graph<Node, Edge>; + +      Namespace (Path const& file, UnsignedLong line, UnsignedLong column); + +      Void +      add_edge_right (BelongsToNamespace&) +      { +      } + +      using Scope::add_edge_right; +    }; +  } +} + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_NAMESPACE_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/particle.cxx b/libxsd-frontend/xsd-frontend/semantic-graph/particle.cxx new file mode 100644 index 0000000..f8c93de --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/particle.cxx @@ -0,0 +1,61 @@ +// file      : xsd-frontend/semantic-graph/particle.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/semantic-graph/particle.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    namespace RTTI = Cult::RTTI; + +    using RTTI::Access; +    using RTTI::TypeInfo; + +    // ContainsParticle +    // +    namespace +    { +      struct ContainsParticleInit +      { +        ContainsParticleInit () +        { +          TypeInfo ti (typeid (ContainsParticle)); +          ti.add_base (Access::public_, true, typeid (Edge)); +          RTTI::insert (ti); +        } + +      } contains_particle_init_; +    } + +    ContainsParticle:: +    ContainsParticle (UnsignedLong min, UnsignedLong max) +        : particle_ (0), compositor_ (0), min_ (min), max_ (max) +    { +    } + +    // Particle +    // +    namespace +    { +      struct ParticleInit +      { +        ParticleInit () +        { +          TypeInfo ti (typeid (Particle)); +          ti.add_base (Access::public_, true, typeid (Node)); +          RTTI::insert (ti); +        } + +      } particle_init_; +    } + +    Particle:: +    Particle () +        : contained_particle_ (0) +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/particle.hxx b/libxsd-frontend/xsd-frontend/semantic-graph/particle.hxx new file mode 100644 index 0000000..df48de4 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/particle.hxx @@ -0,0 +1,145 @@ +// file      : xsd-frontend/semantic-graph/particle.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_PARTICLE_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_PARTICLE_HXX + +#include <xsd-frontend/semantic-graph/elements.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    // +    // +    class Particle; +    class Compositor; + + +    // +    // +    class ContainsParticle: public virtual Edge +    { +    public: +      Particle& +      particle () const +      { +        return *particle_; +      } + +      Compositor& +      compositor () const +      { +        return *compositor_; +      } + +    public: +      UnsignedLong +      min () const +      { +        return min_; +      } + +      UnsignedLong +      max () const +      { +        return max_; +      } + +    protected: +      friend class Bits::Graph<Node, Edge>; + +      ContainsParticle (UnsignedLong min, UnsignedLong max); + +      Void +      set_left_node (Compositor& n) +      { +        compositor_ = &n; +      } + +      Void +      set_right_node (Particle& n) +      { +        particle_ = &n; +      } + +      Void +      clear_left_node (Compositor& n) +      { +        assert (compositor_ == &n); +        compositor_ = 0; +      } + +      Void +      clear_right_node (Particle& n) +      { +        assert (particle_ == &n); +        particle_ = 0; +      } + +    private: +      Particle* particle_; +      Compositor* compositor_; +      UnsignedLong min_, max_; +    }; + +    // +    // +    class Particle: public virtual Node +    { +    public: +      Boolean +      contained_particle_p () +      { +        return contained_particle_ != 0; +      } + +      ContainsParticle& +      contained_particle () +      { +        assert (contained_particle_ != 0); +        return *contained_particle_; +      } + +    public: +      UnsignedLong +      min () const +      { +        assert (contained_particle_ != 0); +        return contained_particle_->min (); +      } + +      UnsignedLong +      max () const +      { +        assert (contained_particle_ != 0); +        return contained_particle_->max (); +      } + +    protected: +      friend class Bits::Graph<Node, Edge>; + +      Particle (); + +      Void +      add_edge_right (ContainsParticle& e) +      { +        contained_particle_ = &e; +      } + +      Void +      remove_edge_right (ContainsParticle& e) +      { +        assert (contained_particle_ == &e); +        contained_particle_ = 0; +      } + +    private: +      ContainsParticle* contained_particle_; +    }; +  } +} + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_PARTICLE_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/schema.cxx b/libxsd-frontend/xsd-frontend/semantic-graph/schema.cxx new file mode 100644 index 0000000..f812797 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/schema.cxx @@ -0,0 +1,139 @@ +// file      : xsd-frontend/semantic-graph/schema.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/semantic-graph/schema.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    namespace RTTI = Cult::RTTI; + +    using RTTI::Access; +    using RTTI::TypeInfo; + +    namespace +    { +      // Uses +      // +      struct UsesInit +      { +        UsesInit () +        { +          TypeInfo ti (typeid (Uses)); +          ti.add_base (Access::public_, true, typeid (Edge)); +          RTTI::insert (ti); +        } + +      } uses_init_; + + +      // Implies +      // +      struct ImpliesInit +      { +        ImpliesInit () +        { +          TypeInfo ti (typeid (Implies)); +          ti.add_base (Access::public_, true, typeid (Uses)); +          RTTI::insert (ti); +        } + +      } implies_init_; + + +      // Sources +      // +      struct SourcesInit +      { +        SourcesInit () +        { +          TypeInfo ti (typeid (Sources)); +          ti.add_base (Access::public_, true, typeid (Uses)); +          RTTI::insert (ti); +        } + +      } sources_init_; + + +      // Includes +      // +      struct IncludesInit +      { +        IncludesInit () +        { +          TypeInfo ti (typeid (Includes)); +          ti.add_base (Access::public_, true, typeid (Uses)); +          RTTI::insert (ti); +        } + +      } includes_init_; + + +      // Imports +      // +      struct ImportsInit +      { +        ImportsInit () +        { +          TypeInfo ti (typeid (Imports)); +          ti.add_base (Access::public_, true, typeid (Uses)); +          RTTI::insert (ti); +        } + +      } imports_init_; + + +      // Schema +      // +      struct SchemaInit +      { +        SchemaInit () +        { +          TypeInfo ti (typeid (Schema)); +          ti.add_base (Access::public_, true, typeid (Scope)); +          RTTI::insert (ti); +        } + +      } schema_init_; +    } + + +    // Schema +    // +    Schema::NamesIteratorPair Schema:: +    find (Name const& name) const +    { +      // Here we are going to create an illusion that the namespace +      // hierarchy is flat. +      names_.clear (); +      schemas_.clear (); + +      find_ (name, names_, schemas_); + +      return NamesIteratorPair (NamesConstIterator (names_.begin ()), +                                NamesConstIterator (names_.end ())); +    } + +    Void Schema:: +    find_ (Name const& name, NamesList& names, SchemaSet& set) const +    { +      set.insert (this); + +      // Check our own namespace first so it will end up first in the list. +      // +      NamesIteratorPair pair (Scope::find (name)); +      names.insert (names.end (), pair.first.base (), pair.second.base ()); + +      for (UsesIterator i (uses_begin ()), end (uses_end ()); i != end; ++i) +      { +        Schema& s (i->schema ()); + +        if (set.find (&s) == set.end ()) +          s.find_ (name, names, set); +      } +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/schema.hxx b/libxsd-frontend/xsd-frontend/semantic-graph/schema.hxx new file mode 100644 index 0000000..10d2f75 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/schema.hxx @@ -0,0 +1,281 @@ +// file      : xsd-frontend/semantic-graph/schema.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_SCHEMA_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_SCHEMA_HXX + +#include <cult/containers/set.hxx> + +#include <xsd-frontend/semantic-graph/elements.hxx> +#include <xsd-frontend/semantic-graph/namespace.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    // +    // +    class Schema; + + +    class Uses: public virtual Edge +    { +    public: +      Schema& +      user () const +      { +        return *user_; +      } + +      Schema& +      schema () const +      { +        return *schema_; +      } + +      Path +      path () const +      { +        return path_; +      } + +    protected: +      friend class Bits::Graph<Node, Edge>; + +      Uses (Path const& path) +          : path_ (path) +      { +      } + +      Void +      set_left_node (Schema& s) +      { +        user_ = &s; +      } + +      Void +      set_right_node (Schema& s) +      { +        schema_ = &s; +      } + +    private: +      Path path_; +      Schema* user_; +      Schema* schema_; +    }; + + +    // +    // +    class Implies: public virtual Uses +    { +    protected: +      friend class Bits::Graph<Node, Edge>; + +      Implies (Path const& path) +          : Uses (path) +      { +      } +    }; + + +    // +    // +    class Sources: public virtual Uses +    { +    protected: +      friend class Bits::Graph<Node, Edge>; + +      Sources (Path const& path) +          : Uses (path) +      { +      } +    }; + + +    // +    // +    class Includes: public virtual Uses +    { +    protected: +      friend class Bits::Graph<Node, Edge>; + +      Includes (Path const& path) +          : Uses (path) +      { +      } +    }; + + +    // +    // +    class Imports: public virtual Uses +    { +    protected: +      friend class Bits::Graph<Node, Edge>; + +      Imports (Path const& path) +          : Uses (path) +      { +      } +    }; + + +    // +    // +    class Schema: public virtual Scope, +                  private Bits::Graph<Node, Edge>, +                  public NonCopyable +    { +      typedef +      Cult::Containers::Vector<Uses*> +      UsesList; + +      typedef +      Cult::Containers::Vector<Uses*> +      UsedList; + +    public: +      Schema (Path const& file, UnsignedLong line, UnsignedLong column) +          : SemanticGraph::Node (file, line, column) +      { +      } + +    public: +      typedef +      Bits::PointerIterator<UsesList::ConstIterator> +      UsesIterator; + +      UsesIterator +      uses_begin () const +      { +        return uses_.begin (); +      } + +      UsesIterator +      uses_end () const +      { +        return uses_.end (); +      } + +      typedef +      Bits::PointerIterator<UsedList::ConstIterator> +      UsedIterator; + +      UsedIterator +      used_begin () const +      { +        return used_.begin (); +      } + +      UsedIterator +      used_end () const +      { +        return used_.end (); +      } + +      Boolean +      used_p () const +      { +        return used_begin () != used_end (); +      } + +      virtual NamesIteratorPair +      find (Name const& name) const; + +    public: +      using Bits::Graph<SemanticGraph::Node, Edge>::new_edge; +      using Bits::Graph<SemanticGraph::Node, Edge>::reset_left_node; +      using Bits::Graph<SemanticGraph::Node, Edge>::reset_right_node; +      using Bits::Graph<SemanticGraph::Node, Edge>::add_edge_left; +      using Bits::Graph<SemanticGraph::Node, Edge>::add_edge_right; +      using Bits::Graph<SemanticGraph::Node, Edge>::delete_node; +      using Bits::Graph<SemanticGraph::Node, Edge>::delete_edge; + +      template <typename T> +      T& +      new_node (Path const& file, UnsignedLong line, UnsignedLong column) +      { +        return graph ().new_node<T> (file, line, column); +      } + +      template <typename T, typename A0> +      T& +      new_node (Path const& file, UnsignedLong line, UnsignedLong column, +                A0 const& a0) +      { +        return graph ().new_node<T> (file, line, column, a0); +      } + +      template <typename T, typename A0, typename A1> +      T& +      new_node (Path const& file, UnsignedLong line, UnsignedLong column, +                A0 const& a0, A1 const& a1) +      { +        return graph ().new_node<T> (file, line, column, a0, a1); +      } + +      template <typename T, typename A0, typename A1, typename A2> +      T& +      new_node (Path const& file, UnsignedLong line, UnsignedLong column, +                A0 const& a0, A1 const& a1, A2 const& a2) +      { +        return graph ().new_node<T> (file, line, column, a0, a1, a2); +      } + +      template <typename T, typename A0, typename A1, typename A2, +                typename A3> +      T& +      new_node (Path const& file, UnsignedLong line, UnsignedLong column, +                A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3) +      { +        return graph ().new_node<T> (file, line, column, a0, a1, a2, a3); +      } + +    protected: +      //@@ gcc bug #21146 +      // +      friend class Bits::Graph<SemanticGraph::Node, Edge>; + +      using Scope::add_edge_left; +      using Node::add_edge_right; + +      Void +      add_edge_left (Uses& e) +      { +        uses_.push_back (&e); +      } + +      Void +      add_edge_right (Uses& e) +      { +        used_.push_back (&e); +      } + +    private: +      Bits::Graph<SemanticGraph::Node, Edge>& +      graph () +      { +        return *this; +      } + +    private: +      UsesList uses_; +      UsedList used_; + +    private: +      typedef Cult::Containers::Set<Schema const*> SchemaSet; + +      Void +      find_ (Name const& name, NamesList&, SchemaSet&) const; + +      mutable NamesList names_; +      mutable SchemaSet schemas_; +    }; +  } +} + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_SCHEMA_HXX diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/union.cxx b/libxsd-frontend/xsd-frontend/semantic-graph/union.cxx new file mode 100644 index 0000000..b4b4cf0 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/union.cxx @@ -0,0 +1,37 @@ +// file      : xsd-frontend/semantic-graph/union.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/semantic-graph/union.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    namespace RTTI = Cult::RTTI; + +    using RTTI::Access; +    using RTTI::TypeInfo; + +    namespace +    { +      struct UnionInit +      { +        UnionInit () +        { +          TypeInfo ti (typeid (Union)); +          ti.add_base (Access::public_, true, typeid (Specialization)); +          RTTI::insert (ti); +        } + +      } union_init_; +    } + +    Union:: +    Union (Path const& file, UnsignedLong line, UnsignedLong column) +        : Node (file, line, column) +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/semantic-graph/union.hxx b/libxsd-frontend/xsd-frontend/semantic-graph/union.hxx new file mode 100644 index 0000000..62df730 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/semantic-graph/union.hxx @@ -0,0 +1,25 @@ +// file      : xsd-frontend/semantic-graph/union.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_SEMANTIC_GRAPH_UNION_HXX +#define XSD_FRONTEND_SEMANTIC_GRAPH_UNION_HXX + +#include <xsd-frontend/semantic-graph/elements.hxx> + +namespace XSDFrontend +{ +  namespace SemanticGraph +  { +    class Union: public virtual Specialization +    { +    protected: +      friend class Bits::Graph<Node, Edge>; + +      Union (Path const& file, UnsignedLong line, UnsignedLong column); +    }; +  } +} + +#endif  // XSD_FRONTEND_SEMANTIC_GRAPH_UNION_HXX diff --git a/libxsd-frontend/xsd-frontend/transformations/anonymous.cxx b/libxsd-frontend/xsd-frontend/transformations/anonymous.cxx new file mode 100644 index 0000000..118fd5d --- /dev/null +++ b/libxsd-frontend/xsd-frontend/transformations/anonymous.cxx @@ -0,0 +1,739 @@ +// file      : xsd-frontend/transformations/anonymous.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/transformations/anonymous.hxx> + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +#include <iostream> +#include <sstream> + +using std::wcerr; +using std::endl; + +namespace XSDFrontend +{ +  using namespace Cult; + +  typedef WideString String; + +  namespace +  { +    using Transformations::AnonymousNameTranslator; + +    class Context +    { +    public: +      Context (SemanticGraph::Schema& schema_, +               SemanticGraph::Path const& file, +               AnonymousNameTranslator& trans_, +               Boolean du) +          : schema_path_ (file), +            ns_ (0), +            failed_ (false), +            trans (trans_), +            detect_unstable (du), +            schema (schema_), +            schema_path (schema_path_), +            ns (ns_), +            failed (failed_) +      { + +      } + +    protected: +      Context (Context& c) +          : trans (c.trans), +            detect_unstable (c.detect_unstable), +            schema (c.schema), +            schema_path (c.schema_path), +            ns (c.ns), +            failed (c.failed) +      { +      } + +    public: +      struct UnstableConflict +      { +        UnstableConflict (SemanticGraph::Type& type) +            : type_ (type) +        { +        } + +        SemanticGraph::Type& +        type () const +        { +          return type_; +        } + +      private: +        SemanticGraph::Type& type_; +      }; + +      Boolean +      conflict (String const& name) +      { +        using SemanticGraph::Type; +        using SemanticGraph::Schema; + +        if (Type* t1 = find (schema, name)) +        { +          // Check if this is a stable conflict. A conflict is unstable +          // if a conflicting type is visible from the root schema but +          // is not visible from the schema where the conflicting +          // element is defined. +          // +          if (detect_unstable) +          { +            Schema& s (dynamic_cast<Schema&> (ns->scope ())); + +            Type* t2 (find (s, name)); + +            if (t1 != t2) +              throw UnstableConflict (*t1); +          } + +          return true; +        } + +        return false; +      } + +      SemanticGraph::Type* +      find (SemanticGraph::Schema& schema, String const& name) +      { +        using SemanticGraph::Type; +        using SemanticGraph::Scope; +        using SemanticGraph::Namespace; + +        String ns_name (ns->name ()); + +        // Get all namespaces across include/import hierarchy with +        // our namespace name. +        // +        Scope::NamesIteratorPair nip (schema.find (ns_name)); + +        for (; nip.first != nip.second; ++nip.first) +        { +          Namespace& ns (dynamic_cast<Namespace&> (nip.first->named ())); + +          Scope::NamesIteratorPair types (ns.find (name)); + +          for (; types.first != types.second; ++types.first) +          { +            if (Type* t = dynamic_cast<Type*> (&types.first->named ())) +            { +              return t; +            } +          } +        } + +        return 0; +      } + +    public: +      SemanticGraph::Path +      path (SemanticGraph::Nameable& n) +      { +        using SemanticGraph::Scope; +        using SemanticGraph::Schema; +        using SemanticGraph::Uses; + +        Schema* schema (0); + +        for (Scope* s (dynamic_cast<Scope*> (&n) +                       ? dynamic_cast<Scope*> (&n) : &n.scope ());; +             s = &s->scope ()) +        { +          if ((schema = dynamic_cast<Schema*> (s))) +            break; +        } + +        if (!schema->used_p ()) +          return schema_path; + +        Uses& u (*schema->used_begin ()); +        return u.path (); +      } + +    public: +      String +      xpath (SemanticGraph::Nameable& n) +      { +        if (dynamic_cast<SemanticGraph::Namespace*> (&n) != 0) +          return L"<namespace-level>"; // There is a bug if you see this. + +        assert (n.named_p ()); + +        SemanticGraph::Scope& scope (n.scope ()); + +        if (dynamic_cast<SemanticGraph::Namespace*> (&scope) != 0) +          return n.name (); + +        return xpath (scope) + L"/" + n.name (); +      } + +    private: +      SemanticGraph::Path const schema_path_; +      SemanticGraph::Namespace* ns_; +      Boolean failed_; + +    public: +      AnonymousNameTranslator& trans; +      Boolean detect_unstable; + +    public: +      SemanticGraph::Schema& schema; +      SemanticGraph::Path const& schema_path; +      SemanticGraph::Namespace*& ns; +      Boolean& failed; +    }; + + +    // Go into implied/included/imported schemas while making sure +    // we don't process the same stuff more than once. +    // +    struct Uses: Traversal::Uses +    { +      virtual Void +      traverse (Type& u) +      { +        SemanticGraph::Schema& s (u.schema ()); + +        if (!s.context ().count ("xsd-frontend-anonymous-seen")) +        { +          s.context ().set ("xsd-frontend-anonymous-seen", true); +          Traversal::Uses::traverse (u); +        } +      } +    }; + +    // Keep track which namespace we are in. +    // +    struct Namespace: Traversal::Namespace +    { +      Namespace (SemanticGraph::Namespace*& ns) +          : ns_ (ns) +      { +      } + +      Void +      pre (SemanticGraph::Namespace& ns) +      { +        ns_ = &ns; +      } + +      Void +      post (SemanticGraph::Namespace&) +      { +        ns_ = 0; +      } + +    private: +      SemanticGraph::Namespace*& ns_; +    }; + +    // +    // +    struct Type: Traversal::List, +                 Traversal::Union, +                 Traversal::Complex, +                 protected virtual Context +    { +      Type (Context& c) +          : Context (c) +      { +      } + +      virtual Void +      traverse (SemanticGraph::List& l) +      { +        SemanticGraph::Type& t (l.argumented ().type ()); + +        //@@ This IDREF stuff is really ugly! +        // +        if (!t.named_p () && +            !t.is_a<SemanticGraph::Fundamental::IdRef> () && +            !t.is_a<SemanticGraph::Fundamental::IdRefs> ()) +        { +          try +          { +            // Run the name through the translation service. +            // +            SemanticGraph::Path file (path (l)); +            String file_str; + +            // Try to use the portable representation of the path. If that +            // fails, fall back to the native representation. +            // +            try +            { +              file_str = file.string (); +            } +            catch (SemanticGraph::InvalidPath const&) +            { +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 +              file_str = file.native_file_string (); +#else +              file_str = file.string (); +#endif +            } + +            String name ( +              trans.translate ( +                file_str, ns->name (), l.name () + L"_item", xpath (l))); + +            // Make sure the name is unique. +            // +            UnsignedLong n (1); +            String escaped (name); + +            while (conflict (escaped)) +            { +              std::wostringstream os; +              os << n++; +              escaped = name + os.str (); +            } + +            t.context ().set ("anonymous", true); +            schema.new_edge<SemanticGraph::Names> (*ns, t, escaped); +          } +          catch (UnstableConflict const& ex) +          { +            SemanticGraph::Type& t (ex.type ()); + +            wcerr << l.file () << ":" << l.line () << ":" << l.column () +                  << ": error: list type name '" << xpath (l) << "' " +                  << "creates an unstable conflict when used as a base " +                  << "for the item type name" +                  << endl; + +            wcerr << t.file () << ":" << t.line () << ":" << t.column () +                  << ": info: conflicting type is defined here" << endl; + +            wcerr << l.file () << ":" << l.line () << ":" << l.column () +                  << ": info: " +                  << "use --anonymous-regex to resolve this conflict" +                  << endl; + +            wcerr << l.file () << ":" << l.line () << ":" << l.column () +                  << ": info: " +                  << "and don't forget to pass the same option when " +                  << "translating '" << l.file ().leaf () << "' and all " +                  << "the schemas that refer to it" << endl; + +            failed = true; +          } +        } +      } + +      virtual Void +      traverse (SemanticGraph::Union& u) +      { +        String file_str; + +        for (SemanticGraph::Union::ArgumentedIterator i ( +               u.argumented_begin ()); i != u.argumented_end (); ++i) +        { +          SemanticGraph::Type& t (i->type ()); + +          if (!t.named_p () && +              !t.is_a<SemanticGraph::Fundamental::IdRef> () && +              !t.is_a<SemanticGraph::Fundamental::IdRefs> ()) +          { +            try +            { +              // Run the name through the translation service. +              // + +              if (!file_str) +              { +                SemanticGraph::Path file (path (u)); + +                // Try to use the portable representation of the path. If +                // that fails, fall back to the native representation. +                // +                try +                { +                  file_str = file.string (); +                } +                catch (SemanticGraph::InvalidPath const&) +                { +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 +                  file_str = file.native_file_string (); +#else +                  file_str = file.string (); +#endif +                } +              } + +              String name ( +                trans.translate ( +                  file_str, ns->name (), u.name () + L"_member", xpath (u))); + +              // Make sure the name is unique. +              // +              UnsignedLong n (1); +              String escaped (name); + +              while (conflict (escaped)) +              { +                std::wostringstream os; +                os << n++; +                escaped = name + os.str (); +              } + +              t.context ().set ("anonymous", true); +              schema.new_edge<SemanticGraph::Names> (*ns, t, escaped); +            } +            catch (UnstableConflict const& ex) +            { +              SemanticGraph::Type& t (ex.type ()); + +              wcerr << u.file () << ":" << u.line () << ":" << u.column () +                    << ": error: union type name '" << xpath (u) << "' " +                    << "creates an unstable conflict when used as a base " +                    << "for the member type name" +                    << endl; + +              wcerr << t.file () << ":" << t.line () << ":" << t.column () +                    << ": info: conflicting type is defined here" << endl; + +              wcerr << u.file () << ":" << u.line () << ":" << u.column () +                    << ": info: " +                    << "use --anonymous-regex to resolve this conflict" +                    << endl; + +              wcerr << u.file () << ":" << u.line () << ":" << u.column () +                    << ": info: " +                    << "and don't forget to pass the same option when " +                    << "translating '" << u.file ().leaf () << "' and all " +                    << "the schemas that refer to it" << endl; + +              failed = true; +            } +          } +        } +      } + +      virtual Void +      traverse (SemanticGraph::Complex& c) +      { +        if (!c.inherits_p ()) +          return; + +        SemanticGraph::Type& t (c.inherits ().base ()); + +        //@@ This IDREF stuff is really ugly! +        // +        if (!t.named_p () && +            !t.is_a<SemanticGraph::Fundamental::IdRef> () && +            !t.is_a<SemanticGraph::Fundamental::IdRefs> ()) +        { +          try +          { +            // Run the name through the translation service. +            // +            SemanticGraph::Path file (path (c)); +            String file_str; + +            // Try to use the portable representation of the path. If that +            // fails, fall back to the native representation. +            // +            try +            { +              file_str = file.string (); +            } +            catch (SemanticGraph::InvalidPath const&) +            { +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 +              file_str = file.native_file_string (); +#else +              file_str = file.string (); +#endif +            } + +            String name ( +              trans.translate ( +                file_str, ns->name (), c.name () + L"_base", xpath (c))); + +            // Make sure the name is unique. +            // +            UnsignedLong n (1); +            String escaped (name); + +            while (conflict (escaped)) +            { +              std::wostringstream os; +              os << n++; +              escaped = name + os.str (); +            } + +            t.context ().set ("anonymous", true); +            schema.new_edge<SemanticGraph::Names> (*ns, t, escaped); +          } +          catch (UnstableConflict const& ex) +          { +            SemanticGraph::Type& t (ex.type ()); + +            wcerr << c.file () << ":" << c.line () << ":" << c.column () +                  << ": error: simple type name '" << xpath (c) << "' " +                  << "creates an unstable conflict when used as a base " +                  << "for the base type name" +                  << endl; + +            wcerr << t.file () << ":" << t.line () << ":" << t.column () +                  << ": info: conflicting type is defined here" << endl; + +            wcerr << c.file () << ":" << c.line () << ":" << c.column () +                  << ": info: " +                  << "use --anonymous-regex to resolve this conflict" +                  << endl; + +            wcerr << c.file () << ":" << c.line () << ":" << c.column () +                  << ": info: " +                  << "and don't forget to pass the same option when " +                  << "translating '" << c.file ().leaf () << "' and all " +                  << "the schemas that refer to it" << endl; + +            failed = true; +          } +        } +      } +    }; + + +    // +    // +    struct Member: Traversal::Element, +                   Traversal::Attribute, +                   protected virtual Context +    { +      Member (Context& c) +          : Context (c) +      { +      } + +      virtual Void +      traverse (SemanticGraph::Element& e) +      { +        SemanticGraph::Type& t (e.type ()); + +        //@@ This IDREF stuff is really ugly! +        // +        if (!t.named_p () && +            !t.is_a<SemanticGraph::Fundamental::IdRef> () && +            !t.is_a<SemanticGraph::Fundamental::IdRefs> ()) +        { +          try +          { +            traverse_ (e); +          } +          catch (UnstableConflict const& ex) +          { +            SemanticGraph::Type& t (ex.type ()); + +            wcerr << e.file () << ":" << e.line () << ":" << e.column () +                  << ": error: element name '" << xpath (e) << "' " +                  << "creates an unstable conflict when used as a type name" +                  << endl; + +            wcerr << t.file () << ":" << t.line () << ":" << t.column () +                  << ": info: conflicting type is defined here" << endl; + +            wcerr << e.file () << ":" << e.line () << ":" << e.column () +                  << ": info: " +                  << "use --anonymous-regex to resolve this conflict" +                  << endl; + +            wcerr << e.file () << ":" << e.line () << ":" << e.column () +                  << ": info: " +                  << "and don't forget to pass the same option when " +                  << "translating '" << e.file ().leaf () << "' and all " +                  << "the schemas that refer to it" << endl; + +            failed = true; +          } +        } +      } + +      virtual Void +      traverse (SemanticGraph::Attribute& a) +      { +        SemanticGraph::Type& t (a.type ()); + +        //@@ This IDREF stuff us really ugly! +        // +        if (!t.named_p () && +            !t.is_a<SemanticGraph::Fundamental::IdRef> () && +            !t.is_a<SemanticGraph::Fundamental::IdRefs> ()) +        { +          try +          { +            traverse_ (a); +          } +          catch (UnstableConflict const& ex) +          { +            SemanticGraph::Type& t (ex.type ()); + +            wcerr << a.file () << ":" << a.line () << ":" << a.column () +                  << ": error: attribute name '" << xpath (a) << "' " +                  << "creates an unstable conflict when used as a type name" +                  << endl; + +            wcerr << t.file () << ":" << t.line () << ":" << t.column () +                  << ": info: conflicting type is defined here" << endl; + +            wcerr << a.file () << ":" << a.line () << ":" << a.column () +                  << ": info: " +                  << "use --anonymous-regex to resolve this conflict" +                  << endl; + +            wcerr << a.file () << ":" << a.line () << ":" << a.column () +                  << ": info: " +                  << "and don't forget to pass the same option when " +                  << "translating '" << a.file ().leaf () << "' and all " +                  << "the schemas that refer to it" << endl; + +            failed = true; +          } +        } +      } + +      Void +      traverse_ (SemanticGraph::Member& m) +      { +        using SemanticGraph::Type; + +        Type& t (m.type ()); + +        // Normally this will be the member which also "defined" the type. +        // However, in some cases of cyclic schema inclusion, this does +        // not happen. As a result we need an extra check that will make +        // sure we create the Names edge in the same Schema node as the +        // one which contains the member which initially defined this +        // type. See the cyclic-inclusion test for an example. +        // + +        // Find the first member that this type classifies. +        // +        for (Type::ClassifiesIterator i (t.classifies_begin ()); +             i != t.classifies_end (); ++i) +        { +          SemanticGraph::Instance& inst (i->instance ()); + +          if (inst.is_a<SemanticGraph::Member> ()) +          { +            // If it is the same member as the one we are traversing, +            // then continue. +            // +            if (&inst == &m) +              break; +            else +              return; +          } +        } + +        // Run the name through the translation service. +        // +        SemanticGraph::Path file (path (m)); +        String file_str; + +        // Try to use the portable representation of the path. If that +        // fails, fall back to the native representation. +        // +        try +        { +          file_str = file.string (); +        } +        catch (SemanticGraph::InvalidPath const&) +        { +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 +          file_str = file.native_file_string (); +#else +          file_str = file.string (); +#endif +        } + +        String name ( +          trans.translate (file_str, ns->name (), m.name (), xpath (m))); + +        // Make sure the name is unique. +        // +        UnsignedLong n (1); +        String escaped (name); + +        while (conflict (escaped)) +        { +          std::wostringstream os; +          os << n++; +          escaped = name + os.str (); +        } + +        t.context ().set ("anonymous", true); +        schema.new_edge<SemanticGraph::Names> (*ns, t, escaped); +      } +    }; +  } + +  namespace Transformations +  { +    Anonymous:: +    Anonymous (AnonymousNameTranslator& trans) +        : trans_ (trans) +    { +    } + +    Void Anonymous:: +    transform (SemanticGraph::Schema& s, +               SemanticGraph::Path const& f, +               Boolean duc) +    { +      Context ctx (s, f, trans_, duc); + +      Traversal::Schema schema; +      Uses uses; + +      schema >> uses >> schema; + +      Traversal::Names schema_names; +      Namespace ns (ctx.ns); +      Traversal::Names ns_names_member; +      Traversal::Names ns_names_type; + +      schema >> schema_names >> ns; +      ns >> ns_names_member; +      ns >> ns_names_type; + +      Type type (ctx); +      ns_names_type >> type; + +      Traversal::Scope scope; // Goes to both types and groups. +      Member member (ctx); + +      ns_names_member >> scope; +      ns_names_member >> member; + +      Traversal::Names names; + +      scope >> names >> member; + +      // Some twisted schemas do recusive inclusions. +      // +      s.context ().set ("xsd-frontend-anonymous-seen", true); + +      schema.dispatch (s); + +      if (ctx.failed) +        throw Failed (); +    } + +    AnonymousNameTranslator:: +    ~AnonymousNameTranslator () +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/transformations/anonymous.hxx b/libxsd-frontend/xsd-frontend/transformations/anonymous.hxx new file mode 100644 index 0000000..2409822 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/transformations/anonymous.hxx @@ -0,0 +1,60 @@ +// file      : xsd-frontend/transformations/anonymous.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRANSFORMATIONS_ANONYMOUS_HXX +#define XSD_FRONTEND_TRANSFORMATIONS_ANONYMOUS_HXX + +#include <cult/types.hxx> + +#include <xsd-frontend/semantic-graph/elements.hxx> // Path +#include <xsd-frontend/semantic-graph/schema.hxx> + +namespace XSDFrontend +{ +  namespace Transformations +  { +    using namespace Cult::Types; + +    class AnonymousNameTranslator +    { +    public: +      virtual +      ~AnonymousNameTranslator (); + +      // The file argument is empty for the currect translation +      // unit. +      // +      virtual WideString +      translate (WideString const& file, +                 WideString const& ns, +                 WideString const& name, +                 WideString const& xpath) = 0; +    }; + +    // This transformation morphs anonymous types into named ones +    // with the names derived from the enclosing attributes and +    // elements. If the detect_unstable_conflicts argument is true +    // then the transformation detects and reports unstable conflicts +    // in name assignment. +    // +    class Anonymous +    { +    public: +      struct Failed {}; + +      Anonymous (AnonymousNameTranslator&); + +      Void +      transform (SemanticGraph::Schema&, +                 SemanticGraph::Path const&, +                 Boolean detect_unstable_conflicts); + +    private: +      AnonymousNameTranslator& trans_; +    }; +  } +} + +#endif // XSD_FRONTEND_TRANSFORMATIONS_ANONYMOUS_HXX diff --git a/libxsd-frontend/xsd-frontend/transformations/enum-synthesis.cxx b/libxsd-frontend/xsd-frontend/transformations/enum-synthesis.cxx new file mode 100644 index 0000000..e10b9d3 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/transformations/enum-synthesis.cxx @@ -0,0 +1,249 @@ +// file      : xsd-frontend/transformations/enum-synthesis.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/transformations/enum-synthesis.hxx> + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +#include <cult/containers/set.hxx> + +namespace XSDFrontend +{ +  using namespace Cult; +  typedef WideString String; + +  namespace +  { +    typedef Cult::Containers::Set<String> Enumerators; + +    struct Enumerator: Traversal::Enumerator +    { +      Enumerator (SemanticGraph::Schema& s, +                  SemanticGraph::Enumeration& e, +                  Enumerators& enumerators) +          : schema_ (s), enum_ (e), enumerators_ (enumerators) +      { +      } + +      virtual Void +      traverse (Type& e) +      { +        String const& name (e.name ()); + +        if (enumerators_.find (name) == enumerators_.end ()) +        { +          enumerators_.insert (name); + +          // Clone the enumerator and add it to enum_. +          // +          Type& c (schema_.new_node<Type> (e.file (), e.line (), e.column ())); + +          schema_.new_edge<SemanticGraph::Names> (enum_, c, name); +          schema_.new_edge<SemanticGraph::Belongs> (c, enum_); + +          if (e.annotated_p ()) +            schema_.new_edge<SemanticGraph::Annotates> (e.annotation (), c); +        } +      } + +    private: +      SemanticGraph::Schema& schema_; +      SemanticGraph::Enumeration& enum_; +      Enumerators& enumerators_; +    }; + +    // +    // +    struct Union: Traversal::Union +    { +      Union (SemanticGraph::Schema& schema) +          : schema_ (schema) +      { +      } + +      virtual Void +      traverse (Type& u) +      { +        using SemanticGraph::Enumeration; + +        SemanticGraph::Context& uc (u.context ()); + +        if (uc.count ("xsd-frontend-enum-synthesis-processed")) +          return; + +        uc.set ("xsd-frontend-enum-synthesis-processed", true); + +        // First see if this union is suitable for synthesis. +        // +        SemanticGraph::Type* base (0); + +        for (Type::ArgumentedIterator i (u.argumented_begin ()); +             i != u.argumented_end (); ++i) +        { +          if (i->type ().is_a<SemanticGraph::Union> ()) +          { +            // See if we can synthesize an enum for this union. This +            // call can change the value i->type() returns. +            // +            dispatch (i->type ()); +          } + +          SemanticGraph::Type& t (i->type ()); + +          if (!t.is_a<Enumeration> ()) +            return; + +          // Make sure all the enums have a common base. +          // +          if (base == 0) +            base = &t; +          else +          { +            // Traverse the inheritance hierarchy until we fine a +            // common base. +            // +            while (base != 0) +            { +              SemanticGraph::Type* b (&t); + +              for (; b != base && b->inherits_p (); +                   b = &b->inherits ().base ()) ; + +              if (base == b) +                break; + +              // Could not find any match on this level. Go one step +              // lower and try again. +              // +              base = base->inherits_p () ? &base->inherits ().base () : 0; +            } + +            if (base == 0) +              return; // No common base. +          } +        } + +        if (base == 0) +          return; // Empty union. + +        // So this union is suitable for synthesis. Base variable points +        // to the "most-derived" common base type. +        // +        Enumeration& e (schema_.new_node<Enumeration> ( +                          u.file (), u.line (), u.column ())); + +        schema_.new_edge<SemanticGraph::Restricts> (e, *base); + +        // Copy enumerators from the member enums. +        // +        { +          Enumerators set; +          Traversal::Enumeration en; +          Traversal::Names names; +          Enumerator er (schema_, e, set); +          en >> names >> er; + +          for (Type::ArgumentedIterator i (u.argumented_begin ()); +               i != u.argumented_end (); ++i) +          { +            en.dispatch (i->type ()); +          } +        } + +        // Reset edges pointing to union to point to enum. +        // +        if (u.annotated_p ()) +        { +          schema_.reset_right_node (u.annotated (), e); +          schema_.add_edge_right (e, u.annotated ()); +        } + +        schema_.reset_right_node (u.named (), e); +        schema_.add_edge_right (e, u.named ()); + +        for (Type::ClassifiesIterator i (u.classifies_begin ()), +               end (u.classifies_end ()); i != end; ++i) +        { +          schema_.reset_right_node (*i, e); +          schema_.add_edge_right (e, *i); +        } + +        for (Type::BegetsIterator i (u.begets_begin ()), +               end (u.begets_end ()); i != end; ++i) +        { +          schema_.reset_right_node (*i, e); +          schema_.add_edge_right (e, *i); +        } + +        for (Type::ArgumentsIterator i (u.arguments_begin ()), +               end (u.arguments_end ()); i != end; ++i) +        { +          schema_.reset_left_node (*i, e); +          schema_.add_edge_left (e, *i); +        } + +        // Remove Arguments edges pointing to the union. +        // +        while (u.argumented_begin () != u.argumented_end ()) +        { +          SemanticGraph::Arguments& a (*u.argumented_begin ()); +          schema_.delete_edge (a.type (), a.specialization (), a); +        } + +        // Copy context and delete the union node. +        // +        e.context ().swap (uc); +        schema_.delete_node (u); +      } + +    private: +      SemanticGraph::Schema& schema_; +    }; + +    // Go into implied/included/imported schemas while making sure +    // we don't process the same stuff more than once. +    // +    struct Uses: Traversal::Uses +    { +      virtual Void +      traverse (Type& u) +      { +        SemanticGraph::Schema& s (u.schema ()); + +        if (!s.context ().count ("xsd-frontend-enum-synthesis-seen")) +        { +          s.context ().set ("xsd-frontend-enum-synthesis-seen", true); +          Traversal::Uses::traverse (u); +        } +      } +    }; +  } + +  namespace Transformations +  { +    Void EnumSynthesis:: +    transform (SemanticGraph::Schema& s, SemanticGraph::Path const&) +    { +      Traversal::Schema schema; +      Uses uses; + +      schema >> uses >> schema; + +      Traversal::Names schema_names; +      Traversal::Namespace ns; +      Traversal::Names ns_names; +      Union u (s); + +      schema >> schema_names >> ns >> ns_names >> u; + +      // Some twisted schemas do recusive inclusions. +      // +      s.context ().set ("xsd-frontend-enum-synthesis-seen", true); + +      schema.dispatch (s); +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/transformations/enum-synthesis.hxx b/libxsd-frontend/xsd-frontend/transformations/enum-synthesis.hxx new file mode 100644 index 0000000..e3c38c7 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/transformations/enum-synthesis.hxx @@ -0,0 +1,33 @@ +// file      : xsd-frontend/transformations/enum-synthesis.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRANSFORMATIONS_ENUM_SYNTHESIS_HXX +#define XSD_FRONTEND_TRANSFORMATIONS_ENUM_SYNTHESIS_HXX + +#include <cult/types.hxx> + +#include <xsd-frontend/semantic-graph/elements.hxx> // Path +#include <xsd-frontend/semantic-graph/schema.hxx> + +namespace XSDFrontend +{ +  namespace Transformations +  { +    using namespace Cult::Types; + +    // This transformation replaces unions of one or more enumerations +    // with the same base with an equivalent synthesized enumeration. +    // This transformation assumes that there are no anonymous types. +    // +    class EnumSynthesis +    { +    public: +      Void +      transform (SemanticGraph::Schema&, SemanticGraph::Path const&); +    }; +  } +} + +#endif // XSD_FRONTEND_TRANSFORMATIONS_ENUM_SYNTHESIS_HXX diff --git a/libxsd-frontend/xsd-frontend/transformations/restriction.cxx b/libxsd-frontend/xsd-frontend/transformations/restriction.cxx new file mode 100644 index 0000000..c58d98f --- /dev/null +++ b/libxsd-frontend/xsd-frontend/transformations/restriction.cxx @@ -0,0 +1,582 @@ +// file      : xsd-frontend/transformations/restriction.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/transformations/restriction.hxx> + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +#include <cult/containers/vector.hxx> + +#include <iostream> + +using std::wcerr; +using std::endl; + +namespace XSDFrontend +{ +  using namespace Cult; + +  typedef WideString String; +  typedef Transformations::Restriction::Failed Failed; +  typedef Containers::Vector<SemanticGraph::Complex*> BaseList; + +  namespace +  { +    // +    // +    struct Complex: Traversal::Complex +    { +      Complex (SemanticGraph::Schema& schema) +          : schema_ (schema) +      { +      } + +      virtual Void +      traverse (Type& c) +      { +        using namespace SemanticGraph; +        using SemanticGraph::Complex; + +        if (c.context ().count ("xsd-frontend-restriction-seen")) +          return; + +        c.context ().set ("xsd-frontend-restriction-seen", true); + +        // The base content model can be spread over several types +        // in the inheritance-by-extension hierarchy. +        // +        BaseList base_model; + +        // Since attribute wildcards don't have names, we will have +        // to rely on their relative position to find association. +        // +        BaseList base_list; + +        // Current implementation of semantic graph uses the same Restricts +        // edge for both simple type/content restriction and complex content +        // restriction. Here we are interested in the complex content only. +        // +        // +        if (c.inherits_p () && +            c.inherits ().is_a<Restricts> () && +            !c.inherits ().base ().is_a<AnyType> ()) +        { +          // Go down our inheritance hierarchy until the end or the previous +          // restriction. +          // +          Complex* base (&c); + +          while ((base = dynamic_cast<Complex*> (&base->inherits ().base ()))) +          { +            traverse (*base); // Make sure our base is processed. + +            // Handle attributes. +            // +            merge_attributes (c, *base); + +            base_list.push_back (base); + +            // Collect types that have complex content. +            // +            if (base->contains_compositor_p ()) +              base_model.push_back (base); + +            if (!base->inherits_p () || base->inherits ().is_a<Restricts> ()) +              break; +          } + +          // Handle attribute wildcards. +          // +          handle_any_attributes (c, base_list); + +          // Handle complex content (not for the faint of heart). +          // +          if (c.contains_compositor_p ()) +          { +            // Traverse both restricted content model and base content +            // model (in base_model) while looking for matches. +            // +            Compositor& root (c.contains_compositor ().compositor ()); + +            if (base_model.size () == 1) +              handle (root, +                      base_model[0]->contains_compositor ().compositor ()); +            else +            { +              Compositor::ContainsIterator i (root.contains_begin ()); +              BaseList::ReverseIterator j (base_model.rbegin ()); + +              for (; i != root.contains_end (); ++i, ++j) +              { +                Particle& p (i->particle ()); + +                if (!p.is_a<Compositor> ()) +                { +                  wcerr << p.file () << ":" << p.line () << ":" << p.column () +                        << ": error: expected compositor instead of particle" +                        << endl; +                  throw Failed (); +                } + +                for (; j != base_model.rend (); ++j) +                { +                  if (match (p, (*j)->contains_compositor ().compositor ())) +                  { +                    handle (p, (*j)->contains_compositor ().compositor ()); +                    break; +                  } +                } + +                if (j == base_model.rend ()) +                  break; +              } + +              if (i != root.contains_end ()) +              { +                Particle& p (i->particle ()); + +                wcerr << p.file () << ":" << p.line () << ":" << p.column () +                      << ": error: unable to match restricted compositor" +                      << endl; +                throw Failed (); +              } +            } +          } +        } + +        // Traverse anonymous types (via elements & attributes). +        // +        Traversal::Complex::names (c); +      } + +    private: +      Void +      handle (SemanticGraph::Particle& r, SemanticGraph::Particle& b) +      { +        using namespace SemanticGraph; + +        if (r.is_a<Compositor> ()) +        { +          Compositor& rc (dynamic_cast<Compositor&> (r)); +          Compositor& bc (dynamic_cast<Compositor&> (b)); + +          Compositor::ContainsIterator i (rc.contains_begin ()); +          Compositor::ContainsIterator j (bc.contains_begin ()); + +          for (; i != rc.contains_end (); ++i, ++j) +          { +            for (; j != bc.contains_end (); ++j) +            { +              Particle& rp (i->particle ()); +              Particle& bp (j->particle ()); + +              if (typeid (rp) != typeid (bp)) +                continue; + +              if (match (rp, bp)) +              { +                handle (rp, bp); +                break; +              } +            } + +            if (j == bc.contains_end ()) +              break; +          } + +          if (i != rc.contains_end ()) +          { +            Particle& p (i->particle ()); + +            wcerr << p.file () << ":" << p.line () << ":" << p.column () +                  << ": error: unable to match restricted particle" +                  << endl; +            throw Failed (); +          } + +          rc.context ().set ("xsd-frontend-restriction-correspondence", &bc); +        } +        else if (r.is_a<Element> ()) +        { +          // Element +          // +          r.context ().set ("xsd-frontend-restriction-correspondence", +                            dynamic_cast<Element*> (&b)); +        } +        else +        { +          // Wildcard +          // +          r.context ().set ("xsd-frontend-restriction-correspondence", +                            dynamic_cast<Any*> (&b)); +        } +      } + +      Boolean +      match (SemanticGraph::Particle& r, SemanticGraph::Particle& b) +      { +        using namespace SemanticGraph; + +        if (typeid (r) != typeid (b)) +          return false; + +        if (r.is_a<Compositor> ()) +        { +          Compositor& rc (dynamic_cast<Compositor&> (r)); +          Compositor& bc (dynamic_cast<Compositor&> (b)); + +          Compositor::ContainsIterator i (rc.contains_begin ()); + +          if (i == rc.contains_end ()) +            return true; + +          Particle& rp (i->particle ()); + +          for (Compositor::ContainsIterator j (bc.contains_begin ()); +               j != bc.contains_end (); ++j) +          { +            Particle& bp (j->particle ()); + +            if (typeid (rp) != typeid (bp)) +              continue; + +            if (match (rp, bp)) +              return true; +          } +        } +        else if (r.is_a<Element> ()) +        { +          Element& re (dynamic_cast<Element&> (r)); +          Element& be (dynamic_cast<Element&> (b)); + +          if (re.qualified_p ()) +          { +            if (be.qualified_p () && +                re.name () == be.name () && +                re.namespace_ ().name () == be.namespace_ ().name ()) +              return true; +          } +          else +          { +            if (!be.qualified_p () && re.name () == be.name ()) +              return true; +          } + +          // @@ Need to take into account substitution groups. +          // +        } +        else +        { +          // Wildcard. +          // + +          // @@ To handle this properly we will need to analyze +          //    namespaces. +          // +          return true; +        } + +        return false; +      } + +      Void +      merge_attributes (SemanticGraph::Complex& c, +                        SemanticGraph::Complex& base) +      { +        using namespace SemanticGraph; + +        for (Scope::NamesIterator i (base.names_begin ()), +               e (base.names_end ()); i != e; ++i) +        { +          Attribute* prot (dynamic_cast<Attribute*> (&i->named ())); + +          if (prot == 0) +            continue; + +          Name name (prot->name ()); +          Scope::NamesIteratorPair r (c.find (name)); + +          Attribute* a (0); + +          for (; r.first != r.second; ++r.first) +          { +            a = dynamic_cast<Attribute*> (&r.first->named ()); + +            if (a == 0) +              continue; + +            if (prot->qualified_p ()) +            { +              if (a->qualified_p () && +                  prot->namespace_ ().name () == a->namespace_ ().name ()) +              { +                break; +              } +            } +            else +            { +              if (!a->qualified_p ()) +                break; +            } + +            a = 0; +          } + +          if (a == 0) +          { +            a = &schema_.new_node<Attribute> (prot->file (), +                                              prot->line (), +                                              prot->column (), +                                              prot->optional_p (), +                                              prot->global_p (), +                                              prot->qualified_p ()); + +            schema_.new_edge<Names> (c, *a, name); + +            // Transfer namespace. +            // +            if (prot->qualified_p ()) +            { +              schema_.new_edge<BelongsToNamespace> (*a, prot->namespace_ ()); +            } + +            // Default and fixed values if any. +            // +            if (prot->fixed_p ()) +              a->fixed (prot->value ()); +            else if (prot->default_p ()) +              a->default_ (prot->value ()); + +            // Belongs edge. +            // +            schema_.new_edge<Belongs> (*a, prot->type ()); + +            // Transfer annotation. +            // +            if (prot->annotated_p ()) +              schema_.new_edge<Annotates> (prot->annotation (), *a); +          } + +          a->context ().set ("xsd-frontend-restriction-correspondence", prot); +        } +      } + +      Void +      handle_any_attributes (SemanticGraph::Complex& c, BaseList& bl) +      { +        using namespace SemanticGraph; + +        BaseList::ReverseIterator bi (bl.rbegin ()), be (bl.rend ()); +        Scope::NamesIterator si; + +        if (bi != be) +          si = (*bi)->names_begin (); + +        for (Scope::NamesIterator i (c.names_begin ()), +               e (c.names_end ()); i != e; ++i) +        { +          AnyAttribute* a (dynamic_cast<AnyAttribute*> (&i->named ())); + +          if (a == 0) +            continue; + +          AnyAttribute* p (0); + +          while (bi != be) +          { +            for (; si != (*bi)->names_end (); ++si) +            { +              p = dynamic_cast<AnyAttribute*> (&si->named ()); + +              if (p != 0) +              { +                ++si; +                break; +              } +            } + +            if (p != 0) +              break; + +            // Didn't find anything in this base. Move on to the next. +            // +            ++bi; + +            if (bi != be) +              si = (*bi)->names_begin (); +          } + +          if (p != 0) +          { +            a->context ().set ("xsd-frontend-restriction-correspondence", p); +          } +          else +          { +            wcerr << a->file () << ":" << a->line () << ":" << a->column () +                  << ": error: unable to find matching wildcard in base type" +                  << endl; +            throw Failed (); +          } +        } +      } + +    private: +      SemanticGraph::Schema& schema_; +    }; + +    // +    // +    struct Anonymous : Traversal::Element, +                       Traversal::Attribute +    { +      Anonymous (Traversal::NodeDispatcherBase& d1) +          : complex_ (&d1, 0) +      { +        *this >> belongs_ >> complex_; +      } + +      Anonymous (Traversal::NodeDispatcherBase& d1, +                 Traversal::NodeDispatcherBase& d2) +          : complex_ (&d1, &d2) +      { +        *this >> belongs_ >> complex_; +      } + +      // Hooks. +      // +    public: +      virtual void +      member_pre (SemanticGraph::Member&) +      { +      } + +      virtual void +      member_post (SemanticGraph::Member&) +      { +      } + +    public: + +      virtual Void +      traverse (SemanticGraph::Element& e) +      { +        SemanticGraph::Type& t (e.type ()); + +        if (!t.named_p () && !t.context ().count ("seen")) +        { +          t.context ().set ("seen", true); + +          member_pre (e); + +          Element::belongs (e, belongs_); + +          member_post (e); + +          t.context ().remove ("seen"); +        } +      } + +      virtual Void +      traverse (SemanticGraph::Attribute& a) +      { +        SemanticGraph::Type& t (a.type ()); + +        if (!t.named_p () && !t.context ().count ("seen")) +        { +          t.context ().set ("seen", true); + +          member_pre (a); + +          Attribute::belongs (a, belongs_); + +          member_post (a); + +          t.context ().remove ("seen"); +        } +      } + +    private: +      struct Complex : Traversal::Complex +      { +        Complex (Traversal::NodeDispatcherBase* d1, +                 Traversal::NodeDispatcherBase* d2) +            : d1_ (d1), d2_ (d2) +        { +        } + +        virtual Void +        traverse (SemanticGraph::Complex& c) +        { +          if (d1_) +            d1_->dispatch (c); + +          if (d2_) +            d2_->dispatch (c); +        } + +      private: +        Traversal::NodeDispatcherBase* d1_; +        Traversal::NodeDispatcherBase* d2_; + +      } complex_; + +      Traversal::Belongs belongs_; +    }; + + +    // Go into implied/included/imported schemas while making sure +    // we don't process the same stuff more than once. +    // +    struct Uses: Traversal::Uses +    { +      virtual Void +      traverse (Type& u) +      { +        SemanticGraph::Schema& s (u.schema ()); + +        if (!s.context ().count ("xsd-frontend-restriction-seen")) +        { +          s.context ().set ("xsd-frontend-restriction-seen", true); +          Traversal::Uses::traverse (u); +        } +      } +    }; +  } + +  namespace Transformations +  { +    Void Restriction:: +    transform (SemanticGraph::Schema& s, SemanticGraph::Path const&) +    { +      Traversal::Schema schema; +      Uses uses; + +      schema >> uses >> schema; + +      Traversal::Names schema_names; +      Traversal::Namespace ns; +      Traversal::Names ns_names; + +      schema >> schema_names >> ns >> ns_names; + +      Complex complex_type (s); +      Anonymous anonymous (complex_type); + +      ns_names >> complex_type; +      ns_names >> anonymous; + +      Traversal::Names names; + +      complex_type >> names >> anonymous; + +      // Some twisted schemas do recusive inclusions. +      // +      s.context ().set ("xsd-frontend-restriction-seen", true); + +      schema.dispatch (s); +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/transformations/restriction.hxx b/libxsd-frontend/xsd-frontend/transformations/restriction.hxx new file mode 100644 index 0000000..7c3282e --- /dev/null +++ b/libxsd-frontend/xsd-frontend/transformations/restriction.hxx @@ -0,0 +1,39 @@ +// file      : xsd-frontend/transformations/restriction.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRANSFORMATIONS_RESTRICTION_HXX +#define XSD_FRONTEND_TRANSFORMATIONS_RESTRICTION_HXX + +#include <cult/types.hxx> + +#include <xsd-frontend/semantic-graph/elements.hxx> // Path +#include <xsd-frontend/semantic-graph/schema.hxx> + +namespace XSDFrontend +{ +  namespace Transformations +  { +    using namespace Cult::Types; + +    // This transformation performs two major tasks. It transfers omitted +    // attribute declarations from the base to derived-by-restriction type +    // and establishes correspondence between particles and compositors by +    // adding the "xsd-frontend-restriction-correspondence" key-value pair +    // in the context that contains a pointer to the corresponding particle +    // or compositor in the base. Note that restriction of anyType is +    // a special case and is not handled by this transformation. +    // +    class Restriction +    { +    public: +      struct Failed {}; + +      Void +      transform (SemanticGraph::Schema&, SemanticGraph::Path const&); +    }; +  } +} + +#endif // XSD_FRONTEND_TRANSFORMATIONS_RESTRICTION_HXX diff --git a/libxsd-frontend/xsd-frontend/transformations/schema-per-type.cxx b/libxsd-frontend/xsd-frontend/transformations/schema-per-type.cxx new file mode 100644 index 0000000..9ac8445 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/transformations/schema-per-type.cxx @@ -0,0 +1,453 @@ +// file      : xsd-frontend/transformations/schema-per-type.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/transformations/schema-per-type.hxx> + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +#include <cult/containers/map.hxx> +#include <cult/containers/set.hxx> +#include <cult/containers/vector.hxx> + +#include <sstream> +#include <iostream> + +#include <strings.h> // strcasecmp + +using std::wcerr; +using std::endl; + +namespace XSDFrontend +{ +  using namespace Cult; + +  typedef WideString String; +  typedef Transformations::SchemaPerType::Failed Failed; + +  typedef Containers::Vector<SemanticGraph::Schema*> Schemas; +  typedef Containers::Map<SemanticGraph::Type*, +                          SemanticGraph::Schema*> TypeSchemaMap; + +  // Compare file paths case-insensitively. +  // +  struct FileComparator +  { +    Boolean +    operator() (NarrowString const& x, NarrowString const& y) const +    { +      return strcasecmp (x.c_str (), y.c_str ()) < 0; +    } +  }; + +  typedef Containers::Set<NarrowString, FileComparator> FileSet; + +  namespace +  { +    // Go into included and imported schemas while making sure +    // we don't process the same stuff more than once. +    // +    struct Uses: Traversal::Includes, +                 Traversal::Imports, +                 Traversal::Implies +    { +      Uses (Schemas& schemas, SemanticGraph::Schema*& xsd) +          : schemas_ (schemas), xsd_ (xsd) +      { +        xsd_ = 0; +      } + +      virtual Void +      traverse (SemanticGraph::Includes& i) +      { +        SemanticGraph::Schema& s (i.schema ()); + +        if (!s.context ().count ("xsd-frontend-schema-per-type-seen")) +        { +          schemas_.push_back (&s); +          s.context ().set ("xsd-frontend-schema-per-type-seen", true); +          Traversal::Includes::traverse (i); +        } +      } + +      virtual Void +      traverse (SemanticGraph::Imports& i) +      { +        SemanticGraph::Schema& s (i.schema ()); + +        if (!s.context ().count ("xsd-frontend-schema-per-type-seen")) +        { +          schemas_.push_back (&s); +          s.context ().set ("xsd-frontend-schema-per-type-seen", true); +          Traversal::Imports::traverse (i); +        } +      } + +      virtual Void +      traverse (SemanticGraph::Implies& i) +      { +        if (xsd_ == 0) +          xsd_ = &i.schema (); +      } + +    private: +      Schemas& schemas_; +      SemanticGraph::Schema*& xsd_; +    }; + +    Void +    process_schema (SemanticGraph::Schema& s, +                    SemanticGraph::Schema& root, +                    SemanticGraph::Schema& xsd, +                    TypeSchemaMap& tsm, +                    FileSet& file_set, +                    Transformations::SchemaPerTypeTranslator& trans) +    { +      using namespace SemanticGraph; + +      Path xsd_path ("XMLSchema.xsd"); +      Namespace& ns (dynamic_cast<Namespace&> (s.names_begin ()->named ())); + +      // We should be careful with iterator caching since we are going to +      // remove some of the nodes. +      // +      for (Scope::NamesIterator i (ns.names_begin ()); i != ns.names_end ();) +      { +        Nameable& n (i->named ()); + +        if (n.is_a<Type> ()) +        { +          String name (n.name ()); + +          // Remove from the namespace. +          // +          Scope::NamesIterator tmp (i++); +          root.delete_edge (ns, n, *tmp); + +          // Add a new schema node. +          // +          Path path; +          String tn (trans.translate_type (ns.name (), name)); +          String wbase (tn ? tn : name); + +          try +          { +            NarrowString base (wbase.to_narrow ()); + +            // Escape directory separators unless they came from the +            // translator. +            // +            if (!tn) +            { +              for (NarrowString::Iterator i (base.begin ()), e (base.end ()); +                   i != e; ++i) +              { +                if (*i == '/' || *i == '\\') +                  *i = '_'; +              } +            } + +            // Make sure it is unique. +            // +            NarrowString file_name (base); + +            for (UnsignedLong i (1); +                 file_set.find (file_name) != file_set.end (); +                 ++i) +            { +              std::ostringstream os; +              os << i; +              file_name = base + os.str (); +            } + +            file_set.insert (file_name); +            file_name += ".xsd"; + +            try +            { +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 +              path = Path (file_name); +#else +              path = Path (file_name.c_str()); +#endif +            } +            catch (InvalidPath const&) +            { +              wcerr << "error: '" << file_name.c_str () << "' is not a valid " +                    << "filesystem path" << endl; + +              wcerr << "info: use type to file name translation mechanism " +                    << "to resolve this" << endl; + +              throw Failed (); +            } +          } +          catch (String::NonRepresentable const&) +          { +            wcerr << "error: '" << wbase << "' cannot be represented as a " +                  << "narrow string" << endl; + +            wcerr << "info: use type to file name translation mechanism " +                  << "to resolve this" << endl; + +            throw Failed (); +          } + +          Schema& ts (root.new_node<Schema> (path, 1, 1)); +          root.new_edge<Implies> (ts, xsd, xsd_path); + +          Namespace& tns (root.new_node<Namespace> (path, 1, 1)); +          root.new_edge<Names> (ts, tns, ns.name ()); +          root.new_edge<Names> (tns, n, name); + +          // Add include to the original schema and enter into the +          // type-schema map. +          // +          root.new_edge<Includes> (s, ts, path); +          tsm[&dynamic_cast<Type&> (n)] = &ts; +        } +        else +          ++i; +      } +    } + +    struct Type: Traversal::List, +                 Traversal::Complex, +                 Traversal::Member +    { +      Type (SemanticGraph::Schema& schema, +            SemanticGraph::Schema& root, +            Char const* by_value_key, +            TypeSchemaMap& tsm) +          : schema_ (schema), +            root_ (root), +            by_value_key_ (by_value_key), +            tsm_ (tsm) +      { +        *this >> names_ >> *this; +      } + +      virtual Void +      traverse (SemanticGraph::List& l) +      { +        // Treat item type as base type since it is impossible +        // to create recursive constructs using list. +        // +        SemanticGraph::Type& t (l.argumented ().type ()); +        set_dep (t, false); +      } + +      virtual Void +      traverse (SemanticGraph::Complex& c) +      { +        if (c.inherits_p ()) +          set_dep (c.inherits ().base (), false); + +        Traversal::Complex::names (c); +      } + +      virtual Void +      traverse (SemanticGraph::Member& m) +      { +        SemanticGraph::Type& t (m.type ()); + +        Boolean weak ( +          by_value_key_ == 0 || +          !t.context ().count (by_value_key_) || +          !t.context ().get<Boolean> (by_value_key_)); + +        set_dep (t, weak); +      } + +    private: +      Void +      set_dep (SemanticGraph::Type& t, Boolean weak) +      { +        using namespace SemanticGraph; + +        TypeSchemaMap::Iterator i (tsm_.find (&t)); + +        // If a type is not present in the map then it must be +        // a built-in type. +        // +        if (i == tsm_.end ()) +          return; + +        // Check if we already saw this type. Theoretically, it could +        // be that we need to upgrade the type of include from weak to +        // strong. But because inheritance is handled first, the type +        // in the set will already be with the right type. +        // +        if (type_set_.find (&t) != type_set_.end ()) +          return; + +        type_set_.insert (&t); + +        Schema& s (*i->second); +        Path path (s.used_begin ()->path ()); +        SemanticGraph::Uses* u; + +        if (s.names_begin ()->name () == schema_.names_begin ()->name ()) +          u = &root_.new_edge<Includes> (schema_, s, path); +        else +          u = &root_.new_edge<Imports> (schema_, s, path); + +        if (weak) +          u->context().set ("weak", true); +      } + +    private: +      SemanticGraph::Schema& schema_; +      SemanticGraph::Schema& root_; +      Char const* by_value_key_; +      TypeSchemaMap& tsm_; +      Containers::Set<SemanticGraph::Type*> type_set_; + +      Traversal::Names names_; +    }; +  } + +  namespace Transformations +  { +    SchemaPerType:: +    SchemaPerType (SchemaPerTypeTranslator& trans, Char const* by_value_key) +        : by_value_key_ (by_value_key), trans_ (trans) +    { +    } + +    Schemas SchemaPerType:: +    transform (SemanticGraph::Schema& root) +    { +      // Collect initial schema nodes. +      // +      Schemas schemas; +      SemanticGraph::Schema* xsd; + +      { +        Traversal::Schema schema; +        Uses uses (schemas, xsd); + +        schema >> uses >> schema; + +        // Some twisted schemas do recusive inclusions. +        // +        root.context ().set ("xsd-frontend-schema-per-type-seen", true); + +        schema.dispatch (root); +      } + +      // wcerr << schemas.size () << " initial schema nodes" << endl; + +      // Add the schema file names to the file set. +      // +      FileSet file_set; + +      for (Schemas::Iterator i (schemas.begin ()); i != schemas.end (); ++i) +      { +        SemanticGraph::Path const& path ( +          (*i)->context ().get<SemanticGraph::Path> ("absolute-path")); + +        // Translate the schema file name. +        // +        NarrowString abs_path; + +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 +        // Try to use the portable representation of the path. If that +        // fails, fall back to the native representation. +        // +        try +        { +          abs_path = path.string (); +        } +        catch (SemanticGraph::InvalidPath const&) +        { +          abs_path = path.native_file_string (); +        } +#else +        // The new ABI does not have a fallback native representation +        abs_path = path.string (); +#endif + +        NarrowString tf (trans_.translate_schema (abs_path)); +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 +        NarrowString file (tf ? tf : path.leaf ()); +#else +        NarrowString file (tf ? tf : path.filename ().string()); +#endif + +        Size p (file.rfind ('.')); +        NarrowString ext ( +          p != NarrowString::npos ? NarrowString (file, p) : ""); + +        NarrowString base ( +          p != NarrowString::npos ? NarrowString (file, 0, p) : file); + +        // Make sure it is unique. +        // +        NarrowString new_name (base); + +        for (UnsignedLong n (1); +             file_set.find (new_name) != file_set.end (); +             ++n) +        { +          std::ostringstream os; +          os << n; +          new_name = base + os.str (); +        } + +        file_set.insert (new_name); +        new_name += ext; + +        try +        { +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 +          (*i)->context ().set ("renamed", SemanticGraph::Path (new_name)); +#else +          (*i)->context ().set ("renamed", SemanticGraph::Path (new_name.c_str())); +#endif +        } +        catch (SemanticGraph::InvalidPath const&) +        { +          wcerr << "error: '" << new_name.c_str () << "' is not a valid " +                << "filesystem path" << endl; + +          wcerr << "info: use schema file name translation mechanism " +                << "to resolve this" << endl; + +          throw Failed (); +        } +      } + +      // Process each schema node. +      // +      TypeSchemaMap tsm; + +      for (Schemas::Iterator i (schemas.begin ()); i != schemas.end (); ++i) +      { +        process_schema (**i, root, *xsd, tsm, file_set, trans_); +      } + +      // wcerr << tsm.size () << " type schema nodes" << endl; + +      // Establish include/import dependencies. While at it add the +      // new schemas to the list which we will return. +      // +      for (TypeSchemaMap::Iterator i (tsm.begin ()); i != tsm.end (); ++i) +      { +        SemanticGraph::Schema& s (*i->second); +        Type t (s, root, by_value_key_, tsm); +        t.dispatch (*i->first); +        schemas.push_back (&s); +      } + +      return schemas; +    } + +    SchemaPerTypeTranslator:: +    ~SchemaPerTypeTranslator () +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/transformations/schema-per-type.hxx b/libxsd-frontend/xsd-frontend/transformations/schema-per-type.hxx new file mode 100644 index 0000000..89b6d83 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/transformations/schema-per-type.hxx @@ -0,0 +1,61 @@ +// file      : xsd-frontend/transformations/schema-per-type.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRANSFORMATIONS_SCHEMA_PER_TYPE_HXX +#define XSD_FRONTEND_TRANSFORMATIONS_SCHEMA_PER_TYPE_HXX + +#include <cult/types.hxx> +#include <cult/containers/vector.hxx> + +#include <xsd-frontend/semantic-graph/elements.hxx> // Path +#include <xsd-frontend/semantic-graph/schema.hxx> + +namespace XSDFrontend +{ +  namespace Transformations +  { +    using namespace Cult::Types; + +    class SchemaPerTypeTranslator +    { +    public: +      virtual +      ~SchemaPerTypeTranslator (); + +      // The following two functions should return empty string if +      // there is no match. +      // +      virtual WideString +      translate_type (WideString const& ns, WideString const& name) = 0; + +      virtual NarrowString +      translate_schema (NarrowString const& abs_path) = 0; +    }; + +    // This transformation restructures the semantic graph to have +    // each type definition in a seperate schema file. +    // +    class SchemaPerType +    { +    public: +      struct Failed {}; + +      // If a type of an element or attribute has a context entry +      // with the by_value_key key and it is true, then the schema +      // for this type is included "strongly". +      // +      SchemaPerType (SchemaPerTypeTranslator&, Char const* by_value_key = 0); + +      Cult::Containers::Vector<SemanticGraph::Schema*> +      transform (SemanticGraph::Schema&); + +    private: +      Char const* by_value_key_; +      SchemaPerTypeTranslator& trans_; +    }; +  } +} + +#endif // XSD_FRONTEND_TRANSFORMATIONS_SCHEMA_PER_TYPE_HXX diff --git a/libxsd-frontend/xsd-frontend/transformations/simplifier.cxx b/libxsd-frontend/xsd-frontend/transformations/simplifier.cxx new file mode 100644 index 0000000..2ccaed2 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/transformations/simplifier.cxx @@ -0,0 +1,167 @@ +// file      : xsd-frontend/transformations/simplifier.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/transformations/simplifier.hxx> + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +#include <cult/containers/vector.hxx> + +namespace XSDFrontend +{ +  using namespace Cult; + +  namespace +  { +    struct Compositor: Traversal::All, +                       Traversal::Choice, +                       Traversal::Sequence +    { +      Compositor (SemanticGraph::Schema& root) +          : root_ (root) +      { +      } + +      virtual Void +      traverse (SemanticGraph::All& a) +      { +        // The all compositor cannot contain compositors. +        // +        if (a.contains_begin () == a.contains_end ()) +          remove (a); +      } + +      virtual Void +      traverse (SemanticGraph::Choice& c) +      { +        // Do the depth-first traversal so that we take into account +        // the potential removal of nested compositors. +        // +        using SemanticGraph::Compositor; + +        for (Compositor::ContainsIterator i (c.contains_begin ()); +             i != c.contains_end ();) +        { +          edge_traverser ().dispatch (*i++); +        } + +        Choice::contains (c); + +        if (c.contains_begin () == c.contains_end ()) +          remove (c); +      } + +      virtual Void +      traverse (SemanticGraph::Sequence& s) +      { +        // Do the depth-first traversal so that we take into account +        // the potential removal of nested compositors. +        // +        using SemanticGraph::Compositor; + +        for (Compositor::ContainsIterator i (s.contains_begin ()); +             i != s.contains_end ();) +        { +          edge_traverser ().dispatch (*i++); +        } + +        if (s.contains_begin () == s.contains_end ()) +          remove (s); +      } + +    private: +      virtual Void +      remove (SemanticGraph::Compositor& c) +      { +        using SemanticGraph::Node; +        using SemanticGraph::Choice; +        using SemanticGraph::Complex; +        using SemanticGraph::Compositor; + +        if (c.contained_particle_p ()) +        { +          Compositor& com (c.contained_particle ().compositor ()); + +          // Empty compositors in choice are important. +          // +          if (!com.is_a<Choice> ()) +            root_.delete_edge (com, c, c.contained_particle ()); +        } +        else +        { +          Complex& con ( +            dynamic_cast<Complex&> (c.contained_compositor ().container ())); +          root_.delete_edge (con, c, c.contained_compositor ()); +        } +      } + +    private: +      SemanticGraph::Schema& root_; +    }; + +    // +    // +    struct Type: Traversal::Complex +    { +      virtual Void +      traverse (SemanticGraph::Complex& c) +      { +        if (c.contains_compositor_p ()) +          Complex::contains_compositor (c); +      } +    }; + +    // Go into implied/included/imported schemas while making sure +    // we don't process the same stuff more than once. +    // +    struct Uses: Traversal::Uses +    { +      virtual Void +      traverse (Type& u) +      { +        SemanticGraph::Schema& s (u.schema ()); + +        if (!s.context ().count ("xsd-frontend-simplifier-seen")) +        { +          s.context ().set ("xsd-frontend-simplifier-seen", true); +          Traversal::Uses::traverse (u); +        } +      } +    }; +  } + +  namespace Transformations +  { +    Void Simplifier:: +    transform (SemanticGraph::Schema& s, SemanticGraph::Path const&) +    { +      Traversal::Schema schema; +      Uses uses; + +      schema >> uses >> schema; + +      Traversal::Names schema_names; +      Traversal::Namespace ns; +      Traversal::Names ns_names; +      Type type; + +      schema >> schema_names >> ns >> ns_names >> type; + +      Compositor compositor (s); +      Traversal::ContainsCompositor contains_compositor; +      Traversal::ContainsParticle contains_particle; + +      type >> contains_compositor >> compositor; +      compositor >> contains_particle >> compositor; + +      // Some twisted schemas do recusive inclusions. +      // +      s.context ().set ("xsd-frontend-simplifier-seen", true); + +      schema.dispatch (s); +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/transformations/simplifier.hxx b/libxsd-frontend/xsd-frontend/transformations/simplifier.hxx new file mode 100644 index 0000000..676c166 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/transformations/simplifier.hxx @@ -0,0 +1,33 @@ +// file      : xsd-frontend/transformations/simplifier.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRANSFORMATIONS_SIMPLIFIER_HXX +#define XSD_FRONTEND_TRANSFORMATIONS_SIMPLIFIER_HXX + +#include <cult/types.hxx> + +#include <xsd-frontend/semantic-graph/elements.hxx> // Path +#include <xsd-frontend/semantic-graph/schema.hxx> + +namespace XSDFrontend +{ +  namespace Transformations +  { +    using namespace Cult::Types; + +    // This transformation performs various schema simplifications +    // (e.g., removing empty compositors, etc). This transformation +    // assumes that there are no anonymous types. +    // +    class Simplifier +    { +    public: +      Void +      transform (SemanticGraph::Schema&, SemanticGraph::Path const&); +    }; +  } +} + +#endif // XSD_FRONTEND_TRANSFORMATIONS_SIMPLIFIER_HXX diff --git a/libxsd-frontend/xsd-frontend/traversal.hxx b/libxsd-frontend/xsd-frontend/traversal.hxx new file mode 100644 index 0000000..9b1c359 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal.hxx @@ -0,0 +1,26 @@ +// file      : xsd-frontend/traversal.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRAVERSAL_HXX +#define XSD_FRONTEND_TRAVERSAL_HXX + +#include <xsd-frontend/traversal/any.hxx> +#include <xsd-frontend/traversal/any-attribute.hxx> +#include <xsd-frontend/traversal/attribute.hxx> +#include <xsd-frontend/traversal/attribute-group.hxx> +#include <xsd-frontend/traversal/complex.hxx> +#include <xsd-frontend/traversal/compositors.hxx> +#include <xsd-frontend/traversal/element.hxx> +#include <xsd-frontend/traversal/element-group.hxx> +#include <xsd-frontend/traversal/elements.hxx> +#include <xsd-frontend/traversal/enumeration.hxx> +#include <xsd-frontend/traversal/fundamental.hxx> +#include <xsd-frontend/traversal/list.hxx> +#include <xsd-frontend/traversal/namespace.hxx> +#include <xsd-frontend/traversal/particle.hxx> +#include <xsd-frontend/traversal/schema.hxx> +#include <xsd-frontend/traversal/union.hxx> + +#endif  // XSD_FRONTEND_TRAVERSAL_HXX diff --git a/libxsd-frontend/xsd-frontend/traversal/any-attribute.hxx b/libxsd-frontend/xsd-frontend/traversal/any-attribute.hxx new file mode 100644 index 0000000..55ed999 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/any-attribute.hxx @@ -0,0 +1,22 @@ +// file      : xsd-frontend/traversal/any-attribute.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRAVERSAL_ANY_ATTRIBUTE_HXX +#define XSD_FRONTEND_TRAVERSAL_ANY_ATTRIBUTE_HXX + +#include <xsd-frontend/traversal/elements.hxx> +#include <xsd-frontend/semantic-graph/any-attribute.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    typedef +    Node<SemanticGraph::AnyAttribute> +    AnyAttribute; +  } +} + +#endif  // XSD_FRONTEND_TRAVERSAL_ANY_ATTRIBUTE_HXX diff --git a/libxsd-frontend/xsd-frontend/traversal/any.hxx b/libxsd-frontend/xsd-frontend/traversal/any.hxx new file mode 100644 index 0000000..505d336 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/any.hxx @@ -0,0 +1,22 @@ +// file      : xsd-frontend/traversal/any.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRAVERSAL_ANY_HXX +#define XSD_FRONTEND_TRAVERSAL_ANY_HXX + +#include <xsd-frontend/traversal/elements.hxx> +#include <xsd-frontend/semantic-graph/any.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    typedef +    Node<SemanticGraph::Any> +    Any; +  } +} + +#endif  // XSD_FRONTEND_TRAVERSAL_ANY_HXX diff --git a/libxsd-frontend/xsd-frontend/traversal/attribute-group.cxx b/libxsd-frontend/xsd-frontend/traversal/attribute-group.cxx new file mode 100644 index 0000000..e5c2237 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/attribute-group.cxx @@ -0,0 +1,30 @@ +// file      : xsd-frontend/traversal/attribute-group.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/traversal/attribute-group.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    Void AttributeGroup:: +    traverse (Type& g) +    { +      pre (g); +      names (g); +      post (g); +    } + +    Void AttributeGroup:: +    pre (Type&) +    { +    } + +    Void AttributeGroup:: +    post (Type&) +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/traversal/attribute-group.hxx b/libxsd-frontend/xsd-frontend/traversal/attribute-group.hxx new file mode 100644 index 0000000..cd01a97 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/attribute-group.hxx @@ -0,0 +1,30 @@ +// file      : xsd-frontend/traversal/attribute-group.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRAVERSAL_ATTRIBUTE_GROUP_HXX +#define XSD_FRONTEND_TRAVERSAL_ATTRIBUTE_GROUP_HXX + +#include <xsd-frontend/traversal/elements.hxx> +#include <xsd-frontend/semantic-graph/attribute-group.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    struct AttributeGroup: ScopeTemplate<SemanticGraph::AttributeGroup> +    { +      virtual Void +      traverse (Type&); + +      virtual Void +      pre (Type&); + +      virtual Void +      post (Type&); +    }; +  } +} + +#endif  // XSD_FRONTEND_TRAVERSAL_ATTRIBUTE_GROUP_HXX diff --git a/libxsd-frontend/xsd-frontend/traversal/attribute.cxx b/libxsd-frontend/xsd-frontend/traversal/attribute.cxx new file mode 100644 index 0000000..c051667 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/attribute.cxx @@ -0,0 +1,48 @@ +// file      : xsd-frontend/traversal/attribute.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/traversal/attribute.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    Void Attribute:: +    traverse (Type& a) +    { +      pre (a); +      belongs (a); +      name (a); +      post (a); +    } + +    Void Attribute:: +    pre (Type&) +    { +    } + +    Void Attribute:: +    belongs (Type& a, EdgeDispatcherBase& d) +    { +      d.dispatch (a.belongs ()); +    } + +    Void Attribute:: +    belongs (Type& a) +    { +      belongs (a, *this); +    } + +    Void Attribute:: +    name (Type&) +    { +    } + +    Void Attribute:: +    post (Type&) +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/traversal/attribute.hxx b/libxsd-frontend/xsd-frontend/traversal/attribute.hxx new file mode 100644 index 0000000..feb6b31 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/attribute.hxx @@ -0,0 +1,41 @@ +// file      : xsd-frontend/traversal/attribute.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRAVERSAL_ATTRIBUTE_HXX +#define XSD_FRONTEND_TRAVERSAL_ATTRIBUTE_HXX + +#include <xsd-frontend/traversal/elements.hxx> + +#include <xsd-frontend/semantic-graph/attribute.hxx> + + +namespace XSDFrontend +{ +  namespace Traversal +  { +    struct Attribute : Node<SemanticGraph::Attribute> +    { +      virtual Void +      traverse (Type&); + +      virtual Void +      pre (Type&); + +      virtual Void +      belongs (Type&, EdgeDispatcherBase&); + +      virtual Void +      belongs (Type&); + +      virtual Void +      name (Type&); + +      virtual Void +      post (Type&); +    }; +  } +} + +#endif  // XSD_FRONTEND_TRAVERSAL_ATTRIBUTE_HXX diff --git a/libxsd-frontend/xsd-frontend/traversal/complex.cxx b/libxsd-frontend/xsd-frontend/traversal/complex.cxx new file mode 100644 index 0000000..d6cfc41 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/complex.cxx @@ -0,0 +1,64 @@ +// file      : xsd-frontend/traversal/complex.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/traversal/complex.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    Void Complex:: +    traverse (Type& c) +    { +      pre (c); +      name (c); +      inherits (c); +      names (c); +      contains_compositor (c); +      post (c); +    } + +    Void Complex:: +    pre (Type&) +    { +    } + +    Void Complex:: +    name (Type&) +    { +    } + +    Void Complex:: +    inherits (Type& c) +    { +      inherits (c, *this); +    } + +    Void Complex:: +    inherits (Type& c, EdgeDispatcherBase& d) +    { +      if (c.inherits_p ()) +        d.dispatch (c.inherits ()); +    } + +    Void Complex:: +    contains_compositor (Type& c) +    { +      contains_compositor (c, *this); +    } + +    Void Complex:: +    contains_compositor (Type& c, EdgeDispatcherBase& d) +    { +      if (c.contains_compositor_p ()) +        d.dispatch (c.contains_compositor ()); +    } + +    Void Complex:: +    post (Type&) +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/traversal/complex.hxx b/libxsd-frontend/xsd-frontend/traversal/complex.hxx new file mode 100644 index 0000000..3dd7e7b --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/complex.hxx @@ -0,0 +1,45 @@ +// file      : xsd-frontend/traversal/complex.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRAVERSAL_COMPLEX_HXX +#define XSD_FRONTEND_TRAVERSAL_COMPLEX_HXX + +#include <xsd-frontend/traversal/elements.hxx> +#include <xsd-frontend/semantic-graph/complex.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    struct Complex : ScopeTemplate<SemanticGraph::Complex> +    { +      virtual Void +      traverse (Type&); + +      virtual Void +      pre (Type&); + +      virtual Void +      name (Type&); + +      virtual Void +      inherits (Type&); + +      Void +      inherits (Type&, EdgeDispatcherBase&); + +      virtual Void +      contains_compositor (Type&); + +      Void +      contains_compositor (Type&, EdgeDispatcherBase&); + +      virtual Void +      post (Type&); +    }; +  } +} + +#endif  // XSD_FRONTEND_TRAVERSAL_COMPLEX_HXX diff --git a/libxsd-frontend/xsd-frontend/traversal/compositors.cxx b/libxsd-frontend/xsd-frontend/traversal/compositors.cxx new file mode 100644 index 0000000..d3089fc --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/compositors.cxx @@ -0,0 +1,165 @@ +// file      : xsd-frontend/traversal/compositors.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/traversal/compositors.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    // ContainsParticle +    // +    Void ContainsParticle:: +    traverse (Type& c) +    { +      dispatch (c.particle ()); +    } + + +    // ContainsCompositor +    // +    Void ContainsCompositor:: +    traverse (Type& c) +    { +      dispatch (c.compositor ()); +    } + + +    // Compositor +    // +    Void Compositor:: +    traverse (Type& c) +    { +      pre (c); +      contains (c); +      post (c); +    } + +    Void Compositor:: +    pre (Type&) +    { +    } + +    Void Compositor:: +    contains (Type& c) +    { +      iterate_and_dispatch ( +        c.contains_begin (), c.contains_end (), edge_traverser ()); +    } + +    Void Compositor:: +    contains (Type& c, EdgeDispatcherBase& d) +    { +      iterate_and_dispatch (c.contains_begin (), c.contains_end (), d); +    } + +    Void Compositor:: +    post (Type&) +    { +    } + + +    // All +    // +    Void All:: +    traverse (Type& c) +    { +      pre (c); +      contains (c); +      post (c); +    } + +    Void All:: +    pre (Type&) +    { +    } + +    Void All:: +    contains (Type& c) +    { +      iterate_and_dispatch ( +        c.contains_begin (), c.contains_end (), edge_traverser ()); +    } + +    Void All:: +    contains (Type& c, EdgeDispatcherBase& d) +    { +      iterate_and_dispatch (c.contains_begin (), c.contains_end (), d); +    } + +    Void All:: +    post (Type&) +    { +    } + + +    // Choice +    // +    Void Choice:: +    traverse (Type& c) +    { +      pre (c); +      contains (c); +      post (c); +    } + +    Void Choice:: +    pre (Type&) +    { +    } + +    Void Choice:: +    contains (Type& c) +    { +      iterate_and_dispatch ( +        c.contains_begin (), c.contains_end (), edge_traverser ()); +    } + +    Void Choice:: +    contains (Type& c, EdgeDispatcherBase& d) +    { +      iterate_and_dispatch (c.contains_begin (), c.contains_end (), d); +    } + +    Void Choice:: +    post (Type&) +    { +    } + + +    // Sequence +    // +    Void Sequence:: +    traverse (Type& c) +    { +      pre (c); +      contains (c); +      post (c); +    } + +    Void Sequence:: +    pre (Type&) +    { +    } + +    Void Sequence:: +    contains (Type& c) +    { +      iterate_and_dispatch ( +        c.contains_begin (), c.contains_end (), edge_traverser ()); +    } + +    Void Sequence:: +    contains (Type& c, EdgeDispatcherBase& d) +    { +      iterate_and_dispatch (c.contains_begin (), c.contains_end (), d); +    } + +    Void Sequence:: +    post (Type&) +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/traversal/compositors.hxx b/libxsd-frontend/xsd-frontend/traversal/compositors.hxx new file mode 100644 index 0000000..e81460b --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/compositors.hxx @@ -0,0 +1,136 @@ +// file      : xsd-frontend/traversal/compositors.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRAVERSAL_COMPOSITORS_HXX +#define XSD_FRONTEND_TRAVERSAL_COMPOSITORS_HXX + +#include <xsd-frontend/traversal/elements.hxx> +#include <xsd-frontend/semantic-graph/compositors.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    // +    // +    struct ContainsParticle: Edge<SemanticGraph::ContainsParticle> +    { +      ContainsParticle () +      { +      } + +      ContainsParticle (NodeBase& n) +      { +        node_traverser (n); +      } + +      virtual Void +      traverse (Type&); +    }; + + +    // +    // +    struct ContainsCompositor: Edge<SemanticGraph::ContainsCompositor> +    { +      ContainsCompositor () +      { +      } + +      ContainsCompositor (NodeBase& n) +      { +        node_traverser (n); +      } + +      virtual Void +      traverse (Type&); +    }; + +    // +    // +    struct Compositor : Node<SemanticGraph::Compositor> +    { +      virtual Void +      traverse (Type&); + +      virtual Void +      pre (Type&); + +      virtual Void +      contains (Type&); + +      virtual Void +      contains (Type&, EdgeDispatcherBase&); + +      virtual Void +      post (Type&); +    }; + + +    // +    // +    struct All : Node<SemanticGraph::All> +    { +      virtual Void +      traverse (Type&); + +      virtual Void +      pre (Type&); + +      virtual Void +      contains (Type&); + +      virtual Void +      contains (Type&, EdgeDispatcherBase&); + +      virtual Void +      post (Type&); +    }; + + +    // +    // +    struct Choice : Node<SemanticGraph::Choice> +    { +      virtual Void +      traverse (Type&); + +      virtual Void +      pre (Type&); + +      virtual Void +      contains (Type&); + +      virtual Void +      contains (Type&, EdgeDispatcherBase&); + +      virtual Void +      post (Type&); +    }; + + +    // +    // +    struct Sequence : Node<SemanticGraph::Sequence> +    { +      virtual Void +      traverse (Type&); + +      virtual Void +      pre (Type&); + +      virtual Void +      contains (Type&); + +      virtual Void +      contains (Type&, EdgeDispatcherBase&); + +      virtual Void +      post (Type&); +    }; +  } +} + +#endif  // XSD_FRONTEND_TRAVERSAL_COMPOSITORS_HXX diff --git a/libxsd-frontend/xsd-frontend/traversal/element-group.cxx b/libxsd-frontend/xsd-frontend/traversal/element-group.cxx new file mode 100644 index 0000000..cb7a51a --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/element-group.cxx @@ -0,0 +1,43 @@ +// file      : xsd-frontend/traversal/element-group.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/traversal/element-group.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    Void ElementGroup:: +    traverse (Type& g) +    { +      pre (g); +      names (g); +      contains_compositor (g); +      post (g); +    } + +    Void ElementGroup:: +    pre (Type&) +    { +    } + +    Void ElementGroup:: +    contains_compositor (Type& g, EdgeDispatcherBase& d) +    { +      d.dispatch (g.contains_compositor ()); +    } + +    Void ElementGroup:: +    contains_compositor (Type& g) +    { +      contains_compositor (g, *this); +    } + +    Void ElementGroup:: +    post (Type&) +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/traversal/element-group.hxx b/libxsd-frontend/xsd-frontend/traversal/element-group.hxx new file mode 100644 index 0000000..8ebe0bd --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/element-group.hxx @@ -0,0 +1,36 @@ +// file      : xsd-frontend/traversal/element-group.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRAVERSAL_ELEMENT_GROUP_HXX +#define XSD_FRONTEND_TRAVERSAL_ELEMENT_GROUP_HXX + +#include <xsd-frontend/traversal/elements.hxx> +#include <xsd-frontend/semantic-graph/element-group.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    struct ElementGroup: ScopeTemplate<SemanticGraph::ElementGroup> +    { +      virtual Void +      traverse (Type&); + +      virtual Void +      pre (Type&); + +      virtual Void +      contains_compositor (Type&); + +      virtual Void +      contains_compositor (Type&, EdgeDispatcherBase&); + +      virtual Void +      post (Type&); +    }; +  } +} + +#endif  // XSD_FRONTEND_TRAVERSAL_ELEMENT_GROUP_HXX diff --git a/libxsd-frontend/xsd-frontend/traversal/element.cxx b/libxsd-frontend/xsd-frontend/traversal/element.cxx new file mode 100644 index 0000000..7f296ee --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/element.cxx @@ -0,0 +1,48 @@ +// file      : xsd-frontend/traversal/element.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/traversal/element.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    Void Element:: +    traverse (Type& m) +    { +      pre (m); +      belongs (m); +      name (m); +      post (m); +    } + +    Void Element:: +    pre (Type&) +    { +    } + +    Void Element:: +    belongs (Type& m, EdgeDispatcherBase& d) +    { +      d.dispatch (m.belongs ()); +    } + +    Void Element:: +    belongs (Type& m) +    { +      belongs (m, edge_traverser ()); +    } + +    Void Element:: +    name (Type&) +    { +    } + +    Void Element:: +    post (Type&) +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/traversal/element.hxx b/libxsd-frontend/xsd-frontend/traversal/element.hxx new file mode 100644 index 0000000..d5187ad --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/element.hxx @@ -0,0 +1,39 @@ +// file      : xsd-frontend/traversal/element.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRAVERSAL_ELEMENT_HXX +#define XSD_FRONTEND_TRAVERSAL_ELEMENT_HXX + +#include <xsd-frontend/traversal/elements.hxx> +#include <xsd-frontend/semantic-graph/element.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    struct Element : Node<SemanticGraph::Element> +    { +      virtual Void +      traverse (Type&); + +      virtual Void +      pre (Type&); + +      virtual Void +      belongs (Type&, EdgeDispatcherBase&); + +      virtual Void +      belongs (Type&); + +      virtual Void +      name (Type&); + +      virtual Void +      post (Type&); +    }; +  } +} + +#endif  // XSD_FRONTEND_TRAVERSAL_ELEMENT_HXX diff --git a/libxsd-frontend/xsd-frontend/traversal/elements.cxx b/libxsd-frontend/xsd-frontend/traversal/elements.cxx new file mode 100644 index 0000000..b1c47a0 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/elements.cxx @@ -0,0 +1,77 @@ +// file      : xsd-frontend/traversal/elements.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/traversal/elements.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    // Instance +    // +    Void Instance:: +    traverse (Type& a) +    { +      pre (a); +      belongs (a); +      post (a); +    } + +    Void Instance:: +    pre (Type&) +    { +    } + +    Void Instance:: +    belongs (Type& a, EdgeDispatcherBase& d) +    { +      d.dispatch (a.belongs ()); +    } + +    Void Instance:: +    belongs (Type& a) +    { +      belongs (a, edge_traverser ()); +    } + +    Void Instance:: +    post (Type&) +    { +    } + + +    // Member +    // +    Void Member:: +    traverse (Type& a) +    { +      pre (a); +      belongs (a); +      post (a); +    } + +    Void Member:: +    pre (Type&) +    { +    } + +    Void Member:: +    belongs (Type& a, EdgeDispatcherBase& d) +    { +      d.dispatch (a.belongs ()); +    } + +    Void Member:: +    belongs (Type& a) +    { +      belongs (a, edge_traverser ()); +    } + +    Void Member:: +    post (Type&) +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/traversal/elements.hxx b/libxsd-frontend/xsd-frontend/traversal/elements.hxx new file mode 100644 index 0000000..c405a1b --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/elements.hxx @@ -0,0 +1,480 @@ +// file      : xsd-frontend/traversal/elements.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRAVERSAL_ELEMENTS_HXX +#define XSD_FRONTEND_TRAVERSAL_ELEMENTS_HXX + +#include <cult/types.hxx> + +#include <frontend-elements/traversal.hxx> + +#include <xsd-frontend/semantic-graph/elements.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    using namespace Cult::Types; + +    namespace Bits +    { +      using FrontendElements::Traversal::TraverserBase; +      using FrontendElements::Traversal::Traverser; + +      using FrontendElements::Traversal::DispatcherBase; +      using FrontendElements::Traversal::Dispatcher; + +    } + +    typedef Bits::DispatcherBase<SemanticGraph::Node> NodeDispatcherBase; +    typedef Bits::DispatcherBase<SemanticGraph::Edge> EdgeDispatcherBase; + + +    // +    // +    struct NodeBase : virtual Bits::Dispatcher<SemanticGraph::Node>, +                      virtual Bits::Dispatcher<SemanticGraph::Edge> +    { +      Void +      edge_traverser (EdgeDispatcherBase& d) +      { +        Bits::Dispatcher<SemanticGraph::Edge>::traverser (d); +      } + +      EdgeDispatcherBase& +      edge_traverser () +      { +        return *this; +      } + +    public: +      using Bits::Dispatcher<SemanticGraph::Node>::dispatch; +      using Bits::Dispatcher<SemanticGraph::Edge>::dispatch; + +      using Bits::Dispatcher<SemanticGraph::Node>::map; + +      using Bits::Dispatcher<SemanticGraph::Edge>::iterate_and_dispatch; +    }; + + +    // +    // +    template <typename T> +    struct Node : Bits::TraverserBase<SemanticGraph::Node>, virtual NodeBase +    { +      typedef +      T +      Type; + +      Node () +      { +        map (typeid (Type), *this); +      } + +      virtual Void +      traverse (Type&) = 0; + +      virtual Void +      trampoline (SemanticGraph::Node& i) +      { +        traverse (dynamic_cast<Type&> (i)); +      } + +      virtual Void +      trampoline (SemanticGraph::Node const&) +      { +        abort (); +      } +    }; + + +    // +    // +    struct EdgeBase : virtual Bits::Dispatcher<SemanticGraph::Edge>, +                      virtual Bits::Dispatcher<SemanticGraph::Node> +    { +      Void +      node_traverser (NodeDispatcherBase& d) +      { +        Bits::Dispatcher<SemanticGraph::Node>::traverser (d); +      } + +      NodeDispatcherBase& +      node_traverser () +      { +        return *this; +      } + +    public: +      using Bits::Dispatcher<SemanticGraph::Edge>::dispatch; +      using Bits::Dispatcher<SemanticGraph::Node>::dispatch; + +      using Bits::Dispatcher<SemanticGraph::Edge>::map; + +      using Bits::Dispatcher<SemanticGraph::Node>::iterate_and_dispatch; +    }; + +    template <typename T> +    struct Edge : Bits::TraverserBase<SemanticGraph::Edge>, virtual EdgeBase +    { +      typedef +      T +      Type; + +      Edge () +      { +        map (typeid (Type), *this); +      } + +      virtual Void +      traverse (Type&) = 0; + +      virtual Void +      trampoline (SemanticGraph::Edge& i) +      { +        traverse (dynamic_cast<Type&> (i)); +      } + +      virtual Void +      trampoline (SemanticGraph::Edge const&) +      { +        abort (); +      } +    }; + +    inline +    EdgeBase& +    operator>> (NodeBase& n, EdgeBase& e) +    { +      n.edge_traverser (e); +      return e; +    } + +    inline +    NodeBase& +    operator>> (EdgeBase& e, NodeBase& n) +    { +      e.node_traverser (n); +      return n; +    } + +    // Edges +    // + +    // +    // +    struct Names : Edge<SemanticGraph::Names> +    { +      Names () +      { +      } + +      Names (NodeBase& n) +      { +        node_traverser (n); +      } + +      virtual Void +      traverse (Type& e) +      { +        dispatch (e.named ()); +      } +    }; + + +    // +    // +    struct Belongs : Edge<SemanticGraph::Belongs> +    { +      Belongs () +      { +      } + +      Belongs (NodeBase& n) +      { +        node_traverser (n); +      } + +      virtual Void +      traverse (Type& e) +      { +        dispatch (e.type ()); +      } +    }; + + +    // Nodes +    // + + +    // +    // +    struct Nameable : Node<SemanticGraph::Nameable> +    { +    }; + + +    // +    // +    template <typename T> +    struct ScopeTemplate : Node<T> +    { +    public: +      virtual Void +      traverse (T& s) +      { +        names (s); +      } + +      template<typename X> +      Void +      names (T& s, +             EdgeDispatcherBase& d, +             Void (X::*pre_) (T&) = (Void (ScopeTemplate<T>::*)(T&)) (0), +             Void (X::*post_) (T&) = (Void (ScopeTemplate<T>::*)(T&)) (0), +             Void (X::*none_) (T&) = (Void (ScopeTemplate<T>::*)(T&)) (0), +             Void (X::*next_) (T&) = (Void (ScopeTemplate<T>::*)(T&)) (0)) +      { +        X* this_ (dynamic_cast<X*> (this)); + +        typename T::NamesIterator b (s.names_begin ()), e (s.names_end ()); + +        if (b != e) +        { +          if (pre_) +            (this_->*pre_) (s); + +          //iterate_and_dispatch (b, e, d, *this_, next_, s); + +          for (; b != s.names_end ();) +          { +            d.dispatch (*b); + +            if (++b != s.names_end () && next_ != 0) +              (this_->*next_) (s); +          } + +          if (post_) +            (this_->*post_) (s); +        } +        else +        { +          if (none_) +            (this_->*none_) (s); +        } +      } + +      virtual Void +      names (T& s, EdgeDispatcherBase& d) +      { +        names<ScopeTemplate<T> > (s, d); +      } + +      virtual Void +      names (T& s) +      { +        names (s, +               *this, +               &ScopeTemplate<T>::names_pre, +               &ScopeTemplate<T>::names_post, +               &ScopeTemplate<T>::names_none, +               &ScopeTemplate<T>::names_next); +      } + +      virtual Void +      names_pre (T&) +      { +      } + +      virtual Void +      names_next (T&) +      { +      } + +      virtual Void +      names_post (T&) +      { +      } + +      virtual Void +      names_none (T&) +      { +      } +    }; + + +    // +    // +    typedef +    ScopeTemplate<SemanticGraph::Scope> +    Scope; + + +    // +    // +    struct Type : Node<SemanticGraph::Type> +    { +      virtual Void +      traverse (SemanticGraph::Type&) = 0; +    }; + + +    // +    // +    struct Instance : Node<SemanticGraph::Instance> +    { +      virtual Void +      traverse (Type&); + +      virtual Void +      pre (Type&); + +      virtual Void +      belongs (Type&, EdgeDispatcherBase&); + +      virtual Void +      belongs (Type&); + +      virtual Void +      post (Type&); +    }; + + +    // +    // +    struct Member : Node<SemanticGraph::Member> +    { +      virtual Void +      traverse (Type&); + +      virtual Void +      pre (Type&); + +      virtual Void +      belongs (Type&, EdgeDispatcherBase&); + +      virtual Void +      belongs (Type&); + +      virtual Void +      post (Type&); +    }; + + +    // +    // +    struct Inherits : Edge<SemanticGraph::Inherits> +    { +      Inherits () +      { +      } + +      Inherits (NodeBase& n) +      { +        node_traverser (n); +      } + +      virtual Void +      traverse (Type& e) +      { +        dispatch (e.base ()); +      } +    }; + + +    // +    // +    struct Extends : Edge<SemanticGraph::Extends> +    { +      Extends () +      { +      } + +      Extends (NodeBase& n) +      { +        node_traverser (n); +      } + +      virtual Void +      traverse (Type& e) +      { +        dispatch (e.base ()); +      } +    }; + + +    // +    // +    struct Restricts : Edge<SemanticGraph::Restricts> +    { +      Restricts () +      { +      } + +      Restricts (NodeBase& n) +      { +        node_traverser (n); +      } + +      virtual Void +      traverse (Type& e) +      { +        dispatch (e.base ()); +      } +    }; + + +    // +    // +    struct Argumented : Edge<SemanticGraph::Arguments> +    { +      Argumented () +      { +      } + +      Argumented (NodeBase& n) +      { +        node_traverser (n); +      } + +      virtual Void +      traverse (Type& a) +      { +        dispatch (a.type ()); +      } +    }; + + +    /* +    // +    // +    struct Contains : Edge<SemanticGraph::Contains> +    { +      virtual Void +      traverse (Type& e) +      { +        dispatch (e.element ()); +      } +    }; +    */ + +    // +    // +    typedef +    Node<SemanticGraph::AnyType> +    AnyType; + + +    // +    // +    typedef +    Node<SemanticGraph::AnySimpleType> +    AnySimpleType; +  } +} + +#include <xsd-frontend/traversal/elements.txx> + +#endif  // XSD_FRONTEND_TRAVERSAL_ELEMENTS_HXX diff --git a/libxsd-frontend/xsd-frontend/traversal/elements.txx b/libxsd-frontend/xsd-frontend/traversal/elements.txx new file mode 100644 index 0000000..b673a8d --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/elements.txx @@ -0,0 +1,11 @@ +// file      : xsd-frontend/traversal/elements.txx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace XSDFrontend +{ +  namespace Traversal +  { +  } +} diff --git a/libxsd-frontend/xsd-frontend/traversal/enumeration.cxx b/libxsd-frontend/xsd-frontend/traversal/enumeration.cxx new file mode 100644 index 0000000..a8a49a5 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/enumeration.cxx @@ -0,0 +1,91 @@ +// file      : xsd-frontend/traversal/enumeration.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/traversal/enumeration.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    // Enumeration +    // +    Void Enumeration:: +    traverse (Type& e) +    { +      pre (e); +      name (e); +      inherits (e); +      names (e); +      post (e); +    } + +    Void Enumeration:: +    pre (Type&) +    { +    } + +    Void Enumeration:: +    name (Type&) +    { +    } + +    Void Enumeration:: +    inherits (Type& e) +    { +      inherits (e, *this); +    } + +    Void Enumeration:: +    inherits (Type& e, EdgeDispatcherBase& d) +    { +      if (e.inherits_p ()) +        d.dispatch (e.inherits ()); +    } + +    Void Enumeration:: +    post (Type&) +    { +    } + + +    // Enumerator +    // +    Void Enumerator:: +    traverse (Type& e) +    { +      pre (e); +      belongs (e); +      name (e); +      post (e); +    } + +    Void Enumerator:: +    pre (Type&) +    { +    } + +    Void Enumerator:: +    belongs (Type& e, EdgeDispatcherBase& d) +    { +      d.dispatch (e.belongs ()); +    } + +    Void Enumerator:: +    belongs (Type& e) +    { +      belongs (e, edge_traverser ()); +    } + +    Void Enumerator:: +    name (Type&) +    { +    } + +    Void Enumerator:: +    post (Type&) +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/traversal/enumeration.hxx b/libxsd-frontend/xsd-frontend/traversal/enumeration.hxx new file mode 100644 index 0000000..c6d7f04 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/enumeration.hxx @@ -0,0 +1,60 @@ +// file      : xsd-frontend/traversal/enumeration.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRAVERSAL_ENUMERATION_HXX +#define XSD_FRONTEND_TRAVERSAL_ENUMERATION_HXX + +#include <xsd-frontend/traversal/elements.hxx> +#include <xsd-frontend/semantic-graph/enumeration.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    struct Enumeration : ScopeTemplate<SemanticGraph::Enumeration> +    { +      virtual Void +      traverse (Type&); + +      virtual Void +      pre (Type&); + +      virtual Void +      name (Type&); + +      virtual Void +      inherits (Type&); + +      Void +      inherits (Type&, EdgeDispatcherBase&); + +      virtual Void +      post (Type&); +    }; + +    struct Enumerator : Node<SemanticGraph::Enumerator> +    { +      virtual Void +      traverse (Type&); + +      virtual Void +      pre (Type&); + +      virtual Void +      belongs (Type&, EdgeDispatcherBase&); + +      virtual Void +      belongs (Type&); + +      virtual Void +      name (Type&); + +      virtual Void +      post (Type&); +    }; +  } +} + +#endif  // XSD_FRONTEND_TRAVERSAL_ENUMERATION_HXX diff --git a/libxsd-frontend/xsd-frontend/traversal/fundamental.cxx b/libxsd-frontend/xsd-frontend/traversal/fundamental.cxx new file mode 100644 index 0000000..b9cadec --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/fundamental.cxx @@ -0,0 +1,13 @@ +// file      : xsd-frontend/traversal/fundamental.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/traversal/fundamental.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +  } +} diff --git a/libxsd-frontend/xsd-frontend/traversal/fundamental.hxx b/libxsd-frontend/xsd-frontend/traversal/fundamental.hxx new file mode 100644 index 0000000..5c20d9c --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/fundamental.hxx @@ -0,0 +1,234 @@ +// file      : xsd-frontend/traversal/fundamental.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRAVERSAL_FUNDAMENTAL_HXX +#define XSD_FRONTEND_TRAVERSAL_FUNDAMENTAL_HXX + +#include <xsd-frontend/traversal/elements.hxx> +#include <xsd-frontend/semantic-graph/fundamental.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    namespace Fundamental +    { +      typedef +      Node<SemanticGraph::Fundamental::Type> +      Type; + +      // Integers. +      // +      typedef +      Node<SemanticGraph::Fundamental::Byte> +      Byte; + +      typedef +      Node<SemanticGraph::Fundamental::UnsignedByte> +      UnsignedByte; + +      typedef +      Node<SemanticGraph::Fundamental::Short> +      Short; + +      typedef +      Node<SemanticGraph::Fundamental::UnsignedShort> +      UnsignedShort; + +      typedef +      Node<SemanticGraph::Fundamental::Int> +      Int; + +      typedef +      Node<SemanticGraph::Fundamental::UnsignedInt> +      UnsignedInt; + +      typedef +      Node<SemanticGraph::Fundamental::Long> +      Long; + +      typedef +      Node<SemanticGraph::Fundamental::UnsignedLong> +      UnsignedLong; + +      typedef +      Node<SemanticGraph::Fundamental::Integer> +      Integer; + +      typedef +      Node<SemanticGraph::Fundamental::NonPositiveInteger> +      NonPositiveInteger; + +      typedef +      Node<SemanticGraph::Fundamental::NonNegativeInteger> +      NonNegativeInteger; + +      typedef +      Node<SemanticGraph::Fundamental::PositiveInteger> +      PositiveInteger; + +      typedef +      Node<SemanticGraph::Fundamental::NegativeInteger> +      NegativeInteger; + + +      // Boolean. +      // +      typedef +      Node<SemanticGraph::Fundamental::Boolean> +      Boolean; + + +      // Floats. +      // +      typedef +      Node<SemanticGraph::Fundamental::Float> +      Float; + +      typedef +      Node<SemanticGraph::Fundamental::Double> +      Double; + +      typedef +      Node<SemanticGraph::Fundamental::Decimal> +      Decimal; + + +      // Strings. +      // +      typedef +      Node<SemanticGraph::Fundamental::String> +      String; + +      typedef +      Node<SemanticGraph::Fundamental::NormalizedString> +      NormalizedString; + +      typedef +      Node<SemanticGraph::Fundamental::Token> +      Token; + +      typedef +      Node<SemanticGraph::Fundamental::Name> +      Name; + +      typedef +      Node<SemanticGraph::Fundamental::NameToken> +      NameToken; + +      typedef +      Node<SemanticGraph::Fundamental::NameTokens> +      NameTokens; + +      typedef +      Node<SemanticGraph::Fundamental::NCName> +      NCName; + +      typedef +      Node<SemanticGraph::Fundamental::Language> +      Language; + + +      // Qualified name. +      // +      typedef +      Node<SemanticGraph::Fundamental::QName> +      QName; + + +      // ID/IDREF. +      // +      typedef +      Node<SemanticGraph::Fundamental::Id> +      Id; + +      typedef +      Node<SemanticGraph::Fundamental::IdRef> +      IdRef; + +      typedef +      Node<SemanticGraph::Fundamental::IdRefs> +      IdRefs; + + +      // URI. +      // +      typedef +      Node<SemanticGraph::Fundamental::AnyURI> +      AnyURI; + + +      // Binary. +      // +      typedef +      Node<SemanticGraph::Fundamental::Base64Binary> +      Base64Binary; + +      typedef +      Node<SemanticGraph::Fundamental::HexBinary> +      HexBinary; + + +      // Date/time. +      // +      typedef +      Node<SemanticGraph::Fundamental::Date> +      Date; + +      typedef +      Node<SemanticGraph::Fundamental::DateTime> +      DateTime; + +      typedef +      Node<SemanticGraph::Fundamental::Duration> +      Duration; + +      typedef +      Node<SemanticGraph::Fundamental::Day> +      Day; + +      typedef +      Node<SemanticGraph::Fundamental::Month> +      Month; + +      typedef +      Node<SemanticGraph::Fundamental::MonthDay> +      MonthDay; + +      typedef +      Node<SemanticGraph::Fundamental::Year> +      Year; + +      typedef +      Node<SemanticGraph::Fundamental::YearMonth> +      YearMonth; + +      typedef +      Node<SemanticGraph::Fundamental::Time> +      Time; + + +      // Entity. +      // +      typedef +      Node<SemanticGraph::Fundamental::Entity> +      Entity; + +      typedef +      Node<SemanticGraph::Fundamental::Entities> +      Entities; + + +      // Notation. +      // +      typedef +      Node<SemanticGraph::Fundamental::Notation> +      Notation; +    } +  } +} + + +#endif  // XSD_FRONTEND_TRAVERSAL_FUNDAMENTAL_HXX diff --git a/libxsd-frontend/xsd-frontend/traversal/list.cxx b/libxsd-frontend/xsd-frontend/traversal/list.cxx new file mode 100644 index 0000000..ec434ba --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/list.cxx @@ -0,0 +1,48 @@ +// file      : xsd-frontend/traversal/list.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/traversal/list.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    Void List:: +    traverse (Type& l) +    { +      pre (l); +      argumented (l); +      name (l); +      post (l); +    } + +    Void List:: +    pre (Type&) +    { +    } + +    Void List:: +    argumented (Type& l) +    { +      argumented (l, *this); +    } + +    Void List:: +    argumented (Type& l, EdgeDispatcherBase& d) +    { +      d.dispatch (l.argumented ()); +    } + +    Void List:: +    name (Type&) +    { +    } + +    Void List:: +    post (Type&) +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/traversal/list.hxx b/libxsd-frontend/xsd-frontend/traversal/list.hxx new file mode 100644 index 0000000..2bbc136 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/list.hxx @@ -0,0 +1,39 @@ +// file      : xsd-frontend/traversal/list.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRAVERSAL_LIST_HXX +#define XSD_FRONTEND_TRAVERSAL_LIST_HXX + +#include <xsd-frontend/traversal/elements.hxx> +#include <xsd-frontend/semantic-graph/list.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    struct List: Node<SemanticGraph::List> +    { +      virtual Void +      traverse (Type&); + +      virtual Void +      pre (Type&); + +      virtual Void +      argumented (Type&); + +      virtual Void +      argumented (Type&, EdgeDispatcherBase& d); + +      virtual Void +      name (Type&); + +      virtual Void +      post (Type&); +    }; +  } +} + +#endif  // XSD_FRONTEND_TRAVERSAL_LIST_HXX diff --git a/libxsd-frontend/xsd-frontend/traversal/namespace.cxx b/libxsd-frontend/xsd-frontend/traversal/namespace.cxx new file mode 100644 index 0000000..cbc6ef2 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/namespace.cxx @@ -0,0 +1,13 @@ +// file      : xsd-frontend/traversal/namespace.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/traversal/namespace.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +  } +} diff --git a/libxsd-frontend/xsd-frontend/traversal/namespace.hxx b/libxsd-frontend/xsd-frontend/traversal/namespace.hxx new file mode 100644 index 0000000..22305e1 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/namespace.hxx @@ -0,0 +1,45 @@ +// file      : xsd-frontend/traversal/namespace.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRAVERSAL_NAMESPACE_HXX +#define XSD_FRONTEND_TRAVERSAL_NAMESPACE_HXX + +#include <xsd-frontend/traversal/elements.hxx> +#include <xsd-frontend/semantic-graph/namespace.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    struct Namespace: ScopeTemplate<SemanticGraph::Namespace> +    { +      virtual Void +      traverse (Type& m) +      { +        pre (m); +        name (m); +        names (m); +        post (m); +      } + +      virtual Void +      pre (Type&) +      { +      } + +      virtual Void +      name (Type&) +      { +      } + +      virtual Void +      post (Type&) +      { +      } +    }; +  } +} + +#endif  // XSD_FRONTEND_TRAVERSAL_NAMESPACE_HXX diff --git a/libxsd-frontend/xsd-frontend/traversal/particle.cxx b/libxsd-frontend/xsd-frontend/traversal/particle.cxx new file mode 100644 index 0000000..e3d3a97 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/particle.cxx @@ -0,0 +1,31 @@ +// file      : xsd-frontend/traversal/particle.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/traversal/particle.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    // Particle +    // +    Void Particle:: +    traverse (Type& c) +    { +      pre (c); +      post (c); +    } + +    Void Particle:: +    pre (Type&) +    { +    } + +    Void Particle:: +    post (Type&) +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/traversal/particle.hxx b/libxsd-frontend/xsd-frontend/traversal/particle.hxx new file mode 100644 index 0000000..3584c12 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/particle.hxx @@ -0,0 +1,30 @@ +// file      : xsd-frontend/traversal/particle.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRAVERSAL_PARTICLE_HXX +#define XSD_FRONTEND_TRAVERSAL_PARTICLE_HXX + +#include <xsd-frontend/traversal/elements.hxx> +#include <xsd-frontend/semantic-graph/particle.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    struct Particle : Node<SemanticGraph::Particle> +    { +      virtual Void +      traverse (Type&); + +      virtual Void +      pre (Type&); + +      virtual Void +      post (Type&); +    }; +  } +} + +#endif  // XSD_FRONTEND_TRAVERSAL_PARTICLE_HXX diff --git a/libxsd-frontend/xsd-frontend/traversal/schema.cxx b/libxsd-frontend/xsd-frontend/traversal/schema.cxx new file mode 100644 index 0000000..acfca26 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/schema.cxx @@ -0,0 +1,13 @@ +// file      : xsd-frontend/traversal/schema.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/traversal/schema.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +  } +} diff --git a/libxsd-frontend/xsd-frontend/traversal/schema.hxx b/libxsd-frontend/xsd-frontend/traversal/schema.hxx new file mode 100644 index 0000000..a975475 --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/schema.hxx @@ -0,0 +1,150 @@ +// file      : xsd-frontend/traversal/schema.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRAVERSAL_SCHEMA_HXX +#define XSD_FRONTEND_TRAVERSAL_SCHEMA_HXX + +#include <xsd-frontend/traversal/elements.hxx> +#include <xsd-frontend/semantic-graph/schema.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    // +    // +    struct Uses: Edge<SemanticGraph::Uses> +    { +      Uses () +      { +      } + +      Uses (NodeBase& n) +      { +        node_traverser (n); +      } + +      virtual Void +      traverse (Type& e) +      { +        dispatch (e.schema ()); +      } +    }; + +    // +    // +    struct Implies: Edge<SemanticGraph::Implies> +    { +      Implies () +      { +      } + +      Implies (NodeBase& n) +      { +        node_traverser (n); +      } + +      virtual Void +      traverse (Type& e) +      { +        dispatch (e.schema ()); +      } +    }; + + +    // +    // +    struct Sources: Edge<SemanticGraph::Sources> +    { +      Sources () +      { +      } + +      Sources (NodeBase& n) +      { +        node_traverser (n); +      } + +      virtual Void +      traverse (Type& e) +      { +        dispatch (e.schema ()); +      } +    }; + + +    // +    // +    struct Includes: Edge<SemanticGraph::Includes> +    { +      Includes () +      { +      } + +      Includes (NodeBase& n) +      { +        node_traverser (n); +      } + +      virtual Void +      traverse (Type& e) +      { +        dispatch (e.schema ()); +      } +    }; + + +    // +    // +    struct Imports: Edge<SemanticGraph::Imports> +    { +      Imports () +      { +      } + +      Imports (NodeBase& n) +      { +        node_traverser (n); +      } + +      virtual Void +      traverse (Type& e) +      { +        dispatch (e.schema ()); +      } +    }; + + +    // +    // +    struct Schema: ScopeTemplate<SemanticGraph::Schema> +    { +      virtual Void +      traverse (Type& s) +      { +        pre (s); + +        iterate_and_dispatch ( +          s.uses_begin (), s.uses_end (), edge_traverser ()); + +        names (s); + +        post (s); +      } + +      virtual Void +      pre (Type&) +      { +      } + +      virtual Void +      post (Type&) +      { +      } +    }; +  } +} + +#endif  // XSD_FRONTEND_TRAVERSAL_SCHEMA_HXX diff --git a/libxsd-frontend/xsd-frontend/traversal/union.cxx b/libxsd-frontend/xsd-frontend/traversal/union.cxx new file mode 100644 index 0000000..acf419a --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/union.cxx @@ -0,0 +1,48 @@ +// file      : xsd-frontend/traversal/union.cxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/traversal/union.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    Void Union:: +    traverse (Type& u) +    { +      pre (u); +      argumented (u); +      name (u); +      post (u); +    } + +    Void Union:: +    pre (Type&) +    { +    } + +    Void Union:: +    argumented (Type& u) +    { +      argumented (u, *this); +    } + +    Void Union:: +    argumented (Type& u, EdgeDispatcherBase& d) +    { +      iterate_and_dispatch (u.argumented_begin (), u.argumented_end (), d); +    } + +    Void Union:: +    name (Type&) +    { +    } + +    Void Union:: +    post (Type&) +    { +    } +  } +} diff --git a/libxsd-frontend/xsd-frontend/traversal/union.hxx b/libxsd-frontend/xsd-frontend/traversal/union.hxx new file mode 100644 index 0000000..e3d31bd --- /dev/null +++ b/libxsd-frontend/xsd-frontend/traversal/union.hxx @@ -0,0 +1,39 @@ +// file      : xsd-frontend/traversal/union.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TRAVERSAL_UNION_HXX +#define XSD_FRONTEND_TRAVERSAL_UNION_HXX + +#include <xsd-frontend/traversal/elements.hxx> +#include <xsd-frontend/semantic-graph/union.hxx> + +namespace XSDFrontend +{ +  namespace Traversal +  { +    struct Union: Node<SemanticGraph::Union> +    { +      virtual Void +      traverse (Type&); + +      virtual Void +      pre (Type&); + +      virtual Void +      argumented (Type&); + +      virtual Void +      argumented (Type&, EdgeDispatcherBase& d); + +      virtual Void +      name (Type&); + +      virtual Void +      post (Type&); +    }; +  } +} + +#endif  // XSD_FRONTEND_TRAVERSAL_UNION_HXX diff --git a/libxsd-frontend/xsd-frontend/types.hxx b/libxsd-frontend/xsd-frontend/types.hxx new file mode 100644 index 0000000..b3059fd --- /dev/null +++ b/libxsd-frontend/xsd-frontend/types.hxx @@ -0,0 +1,18 @@ +// file      : xsd-frontend/types.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_TYPES_HXX +#define XSD_FRONTEND_TYPES_HXX + +#include <cult/types.hxx> + +namespace XSDFrontend +{ +  using namespace Cult::Types; + +  typedef Cult::WideString String; +} + +#endif  // XSD_FRONTEND_TYPES_HXX diff --git a/libxsd-frontend/xsd-frontend/xml.hxx b/libxsd-frontend/xsd-frontend/xml.hxx new file mode 100644 index 0000000..8c9b01c --- /dev/null +++ b/libxsd-frontend/xsd-frontend/xml.hxx @@ -0,0 +1,567 @@ +// file      : xsd-frontend/xml.hxx +// author    : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_FRONTEND_XML_HXX +#define XSD_FRONTEND_XML_HXX + +#include <ostream> + +#include <xercesc/dom/DOM.hpp> +#include <xercesc/util/XMLString.hpp> + +#include <cult/containers/vector.hxx> + +#include <xsd-frontend/types.hxx> +#include <xsd-frontend/schema-dom-parser.hxx> + +namespace XSDFrontend +{ +  namespace XML +  { +    namespace Xerces = xercesc; + +    inline +    String +    transcode (XMLCh const* s, Size length) +    { +      if (sizeof (WideChar) == 4) +      { +        // UTF-32 +        // +        XMLCh const* end (s + length); + +        // Find what the resulting buffer size will be. +        // +        Size rl (0); +        Boolean valid (true); + +        for (XMLCh const* p (s); p < end; ++p) +        { +          rl++; + +          if ((*p >= 0xD800) && (*p <= 0xDBFF)) +          { +            // Make sure we have one more char and it has a valid +            // value for the second char in a surrogate pair. +            // +            if (++p == end || !((*p >= 0xDC00) && (*p <= 0xDFFF))) +            { +              valid = false; +              break; +            } +          } +        } + +        if (!valid) +          return String (); + +        String r; +        r.reserve (rl + 1); +        r.resize (rl); +        WideChar* rs (const_cast<WideChar*> (r.c_str ())); + +        Size i (0); + +        for (XMLCh const* p (s); p < end; ++p) +        { +          XMLCh x (*p); + +          if (x < 0xD800 || x > 0xDBFF) +            rs[i++] = WideChar (x); +          else +            rs[i++] = ((x - 0xD800) << 10) + (*++p - 0xDC00) + 0x10000; +        } + +        return r; +      } +      else if (sizeof (WideChar) == 2) +      { +        // UTF-16 +        // +        return String (reinterpret_cast<const WideChar*> (s), length); +      } +      else +        return String (); +    } + +    inline +    String +    transcode (XMLCh const* s) +    { +      return transcode (s,  Xerces::XMLString::stringLen (s)); +    } + +    inline +    NarrowString +    transcode_to_narrow (XMLCh const* xs) +    { +      Char* s (Xerces::XMLString::transcode (xs)); +      NarrowString r (s); +      Xerces::XMLString::release (&s); +      return r; +    } + +    inline +    XMLCh* +    transcode (String const& str) +    { +      Size l (str.size ()); +      WideChar const* s (str.c_str ()); + +      if (sizeof (WideChar) == 4) +      { +        // Find what the resulting buffer size will be. +        // +        Size rl (0); + +        for (WideChar const* p (s); p < s + l; ++p) +        { +          rl += (*p & 0xFFFF0000) ? 2 : 1; +        } + +        XMLCh* r (new XMLCh[rl + 1]); +        XMLCh* ir (r); + +        for (WideChar const* p (s); p < s + l; ++p) +        { +          WideChar w (*p); + +          if (w & 0xFFFF0000) +          { +            // Surrogate pair. +            // +            *ir++ = static_cast<XMLCh> (((w - 0x10000) >> 10) + 0xD800); +            *ir++ = static_cast<XMLCh> ((w & 0x3FF) + 0xDC00); +          } +          else +            *ir++ = static_cast<XMLCh> (w); +        } + +        *ir = XMLCh (0); + +        return r; +      } +      else if (sizeof (WideChar) == 2) +      { +        XMLCh* r (new XMLCh[l + 1]); +        XMLCh* ir (r); + +        for (Size i (0); i < l; ++ir, ++i) +          *ir = static_cast<XMLCh> (s[i]); + +        *ir = XMLCh (0); + +        return r; +      } +      else +        return 0; +    } + +    class XMLChString +    { +    public : +      XMLChString (String const& s) +          : s_ (transcode (s)) +      { +      } + +      XMLChString (WideChar const* s) +          : s_ (transcode (String (s))) +      { +      } + +      ~XMLChString () +      { +        delete[] s_; +      } + +      XMLCh const* +      c_str () const +      { +        return s_; +      } + +    private: +      XMLChString (XMLChString const&); + +      XMLChString& +      operator= (XMLChString const&); + +    private: +      XMLCh* s_; +    }; + + +    class Element +    { +    public: +      Element (Xerces::DOMElement* e) +          : e_ (e), +            name_ (transcode (e->getLocalName ())), +            namespace__ (transcode (e->getNamespaceURI ())) +      { +      } + +      String +      name () const +      { +        return name_; +      } + +      String +      namespace_ () const +      { +        return namespace__; +      } + +    public: +      UnsignedLong +      line () const +      { +        //@@ cache +        // +        return reinterpret_cast<UnsignedLong> (e_->getUserData (line_key)); +      } + +      UnsignedLong +      column () const +      { +        //@@ cache +        // +        return reinterpret_cast<UnsignedLong> (e_->getUserData (column_key)); +      } + +    public: +      Element +      parent () const +      { +        return dynamic_cast<Xerces::DOMElement*>(e_->getParentNode ()); +      } + +    public: +      // Attribute identified by a name. +      // +      Boolean +      attribute_p (String const& name) const +      { +        return attribute_p ("", name); +      } + +      String +      attribute (String const& name) const +      { +        return attribute ("", name); +      } + +      String +      operator[] (String const& name) const +      { +        return attribute (name); +      } + +      // Attribute identified by namespace and name. +      // + +      Boolean +      attribute_p (String const& namespace_, String const& name) const +      { +        Xerces::DOMAttr* a ( +          e_->getAttributeNodeNS ( +            XMLChString (namespace_).c_str (), +            XMLChString (name).c_str ())); + +        return a != 0; +      } + +      String +      attribute (String const& namespace_, String const& name) const +      { +        XMLCh const* value ( +          e_->getAttributeNS ( +            XMLChString (namespace_).c_str (), +            XMLChString (name).c_str ())); + +        return transcode (value); +      } + +    public: +      Xerces::DOMElement* +      dom_element () const +      { +        return e_; +      } + +    private: +      Xerces::DOMElement* e_; + +      String name_; +      String namespace__; +    }; + +    inline String +    prefix (String const& n) +    { +      Size i (0); +      while (i < n.length () && n[i] != L':') ++i; + +      //std::wcerr << "prefix " << n << " " +      //           << String (n, i == n.length () ? i : 0, i) << std::endl; + +      return String (n, i == n.length () ? i : 0, i); +    } + +    inline String +    uq_name (String const& n) +    { +      Size i (0); +      while (i < n.length () && n[i] != L':') ++i; + +      return String (n.c_str () + (i == n.length () ? 0 : i + 1)); +    } + +    struct NoMapping +    { +      NoMapping (String const& prefix) +          : prefix_ (prefix) +      { +      } + +      String const& +      prefix () const +      { +        return prefix_; +      } + +    private: +      String prefix_; +    }; + +    // Throws NoMapping if there is no prefix-namespace association. +    // +    inline String +    ns_name (Xerces::DOMElement const* e, String const& prefix) +    { +      // 'xml' prefix requires special handling and Xerces folks refuse +      // to handle this in DOM so I have to do it myself. +      // +      if (prefix == L"xml") +        return L"http://www.w3.org/XML/1998/namespace"; + +      // 0 means "no prefix" to Xerces. +      // +      XMLCh const* xns ( +        e->lookupNamespaceURI ( +          prefix.empty () ? 0 : XMLChString (prefix).c_str ())); + +      if (xns == 0) +        throw NoMapping (prefix); + +      return transcode (xns); +    } + +    class NoPrefix {}; + +    inline String +    ns_prefix (Element const& e, String const& wns) +    { +      XMLChString ns (wns); + +#if _XERCES_VERSION >= 30000 +      XMLCh const* p ( +        e.dom_element ()->lookupPrefix (ns.c_str ())); +#else +      XMLCh const* p ( +        e.dom_element ()->lookupNamespacePrefix (ns.c_str (), false)); +#endif + +      if (p == 0) +      { +        Boolean r (e.dom_element ()->isDefaultNamespace (ns.c_str ())); + +        if (r) +          return L""; +        else +        { +          // 'xml' prefix requires special handling and Xerces folks refuse +          // to handle this in DOM so I have to do it myself. +          // +          if (wns == L"http://www.w3.org/XML/1998/namespace") +            return L"xml"; + +          throw NoPrefix (); +        } +      } + +      return transcode (p); +    } + +    inline String +    fq_name (Element const& e, String const& n) +    { +      String un (uq_name (n)); + +      try +      { +        String ns (ns_name (e.dom_element (), prefix (n))); +        return ns + L'#' + un; +      } +      catch (XML::NoMapping const&) +      { +        return un; +      } +    } + + +    // Simple auto_ptr version that calls release() instead of delete. +    // + +    template <typename X> +    struct AutoPtrRef +    { +      X* x_; + +      explicit +      AutoPtrRef (X* x) +          : x_ (x) +      { +      } +    }; + +    template <typename X> +    struct AutoPtr +    { +      ~AutoPtr () +      { +        reset (); +      } + +      explicit +      AutoPtr (X* x = 0) +          : x_ (x) +      { +      } + +      AutoPtr (AutoPtr& y) +          : x_ (y.release ()) +      { +      } + +      AutoPtr (AutoPtrRef<X> r) +          : x_ (r.x_) +      { +      } + +      AutoPtr& +      operator= (AutoPtr& y) +      { +        if (this != &y) +        { +          reset (y.release ()); +        } + +        return *this; +      } + +      AutoPtr& +      operator= (AutoPtrRef<X> r) +      { +        if (r.x_ != x_) +        { +          reset (r.x_); +        } + +        return *this; +      } + +      operator AutoPtrRef<X> () +      { +        return AutoPtrRef<X> (release ()); +      } + +    public: +      X& +      operator* () const +      { +        return *x_; +      } + +      X* +      operator-> () const +      { +        return x_; +      } + +      X* +      get () const +      { +        return x_; +      } + +      X* +      release () +      { +        X* x (x_); +        x_ = 0; +        return x; +      } + +      void +      reset (X* x = 0) +      { +        if (x_) +          x_->release (); + +        x_ = x; +      } + +      // Conversion to bool. +      // +      typedef X* (AutoPtr::*BooleanConvertible)() const; + +      operator BooleanConvertible () const throw () +      { +        return x_ ? &AutoPtr<X>::operator-> : 0; +      } + +    private: +      X* x_; +    }; + +    template <typename X> +    struct PtrVector: Cult::Containers::Vector<X*> +    { +      typedef Cult::Containers::Vector<X*> Base; + +      ~PtrVector () +      { +        for (typename Base::Iterator i (this->begin ()), e (this->end ()); +             i != e; ++i) +        { +          if (*i) +            (*i)->release (); +        } +      } + +      Void +      push_back (AutoPtr<X>& x) +      { +        Base::push_back (0); +        this->back () = x.release (); +      } +    }; +  } +} + +// Xerces DOoM. +// +// +inline +std::wostream& +operator<< (std::wostream& o, XMLCh const* s) +{ +  return o << XSDFrontend::XML::transcode (s); +} + +#endif  // XSD_FRONTEND_XML_HXX  | 
