changeset 1:d45d5c75afaa

first release
author dwinter
date Mon, 23 Jul 2012 09:54:49 +0200
parents 8190d724dc01
children d5de1d6e9338
files dottoxml/README.TXT dottoxml/src/COPYING dottoxml/src/X11Colors.py dottoxml/src/dot.py dottoxml/src/dottoxml.py
diffstat 5 files changed, 1872 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dottoxml/README.TXT	Mon Jul 23 09:54:49 2012 +0200
@@ -0,0 +1,14 @@
+Original at:
+
+http://www.mydarc.de/dl9obn/programming/python/dottoxml/#current
+
+small change in dot.py
+
+
+added:
+
+  # HACK DW, no label in attrs, dann label in attrs = node.label
+        else:
+            self.attribs["label"]=self.label
+
+         
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dottoxml/src/COPYING	Mon Jul 23 09:54:49 2012 +0200
@@ -0,0 +1,416 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, 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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+	Appendix: 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) 19yy  <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., 675 Mass Ave, Cambridge, MA 02139, 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) 19yy 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.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dottoxml/src/X11Colors.py	Mon Jul 23 09:54:49 2012 +0200
@@ -0,0 +1,677 @@
+# coding: latin-1
+# Copyright (c) 2009,2010 Dirk Baechle.
+# www: http://www.mydarc.de/dl9obn/programming/python/dottoxml
+# mail: dl9obn AT darc.de
+#
+# 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.,
+# 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+"""
+  X11 color names and their RGB values
+"""
+
+# Mapping color names to RGB values
+color_map = {
+"aliceblue" : "#f0f8ff",
+"antiquewhite" : "#faebd7",
+"antiquewhite1" : "#ffefdb",
+"antiquewhite2" : "#eedfcc",
+"antiquewhite3" : "#cdc0b0",
+"antiquewhite4" : "#8b8378",
+"aquamarine" : "#7fffd4",
+"aquamarine1" : "#7fffd4",
+"aquamarine2" : "#76eec6",
+"aquamarine3" : "#66cdaa",
+"aquamarine4" : "#458b74",
+"azure" : "#f0ffff",
+"azure1" : "#f0ffff",
+"azure2" : "#e0eeee",
+"azure3" : "#c1cdcd",
+"azure4" : "#838b8b",
+"beige" : "#f5f5dc",
+"bisque" : "#ffe4c4",
+"bisque1" : "#ffe4c4",
+"bisque2" : "#eed5b7",
+"bisque3" : "#cdb79e",
+"bisque4" : "#8b7d6b",
+"black" : "#000000",
+"blanchedalmond" : "#ffebcd",
+"blue" : "#0000ff",
+"blue1" : "#0000ff",
+"blue2" : "#0000ee",
+"blue3" : "#0000cd",
+"blue4" : "#00008b",
+"blueviolet" : "#8a2be2",
+"brown" : "#a52a2a",
+"brown1" : "#ff4040",
+"brown2" : "#ee3b3b",
+"brown3" : "#cd3333",
+"brown4" : "#8b2323",
+"burlywood" : "#deb887",
+"burlywood1" : "#ffd39b",
+"burlywood2" : "#eec591",
+"burlywood3" : "#cdaa7d",
+"burlywood4" : "#8b7355",
+"cadetblue" : "#5f9ea0",
+"cadetblue1" : "#98f5ff",
+"cadetblue2" : "#8ee5ee",
+"cadetblue3" : "#7ac5cd",
+"cadetblue4" : "#53868b",
+"chartreuse" : "#7fff00",
+"chartreuse1" : "#7fff00",
+"chartreuse2" : "#76ee00",
+"chartreuse3" : "#66cd00",
+"chartreuse4" : "#458b00",
+"chocolate" : "#d2691e",
+"chocolate1" : "#ff7f24",
+"chocolate2" : "#ee7621",
+"chocolate3" : "#cd661d",
+"chocolate4" : "#8b4513",
+"coral" : "#ff7f50",
+"coral1" : "#ff7256",
+"coral2" : "#ee6a50",
+"coral3" : "#cd5b45",
+"coral4" : "#8b3e2f",
+"cornflowerblue" : "#6495ed",
+"cornsilk" : "#fff8dc",
+"cornsilk1" : "#fff8dc",
+"cornsilk2" : "#eee8cd",
+"cornsilk3" : "#cdc8b1",
+"cornsilk4" : "#8b8878",
+"crimson" : "#dc143c",
+"cyan" : "#00ffff",
+"cyan1" : "#00ffff",
+"cyan2" : "#00eeee",
+"cyan3" : "#00cdcd",
+"cyan4" : "#008b8b",
+"darkgoldenrod" : "#b8860b",
+"darkgoldenrod1" : "#ffb90f",
+"darkgoldenrod2" : "#eead0e",
+"darkgoldenrod3" : "#cd950c",
+"darkgoldenrod4" : "#8b6508",
+"darkgreen" : "#006400",
+"darkkhaki" : "#bdb76b",
+"darkolivegreen" : "#556b2f",
+"darkolivegreen1" : "#caff70",
+"darkolivegreen2" : "#bcee68",
+"darkolivegreen3" : "#a2cd5a",
+"darkolivegreen4" : "#6e8b3d",
+"darkorange" : "#ff8c00",
+"darkorange1" : "#ff7f00",
+"darkorange2" : "#ee7600",
+"darkorange3" : "#cd6600",
+"darkorange4" : "#8b4500",
+"darkorchid" : "#9932cc",
+"darkorchid1" : "#bf3eff",
+"darkorchid2" : "#b23aee",
+"darkorchid3" : "#9a32cd",
+"darkorchid4" : "#68228b",
+"darksalmon" : "#e9967a",
+"darkseagreen" : "#8fbc8f",
+"darkseagreen1" : "#c1ffc1",
+"darkseagreen2" : "#b4eeb4",
+"darkseagreen3" : "#9bcd9b",
+"darkseagreen4" : "#698b69",
+"darkslateblue" : "#483d8b",
+"darkslategray" : "#2f4f4f",
+"darkslategray1" : "#97ffff",
+"darkslategray2" : "#8deeee",
+"darkslategray3" : "#79cdcd",
+"darkslategray4" : "#528b8b",
+"darkslategrey" : "#2f4f4f",
+"darkturquoise" : "#00ced1",
+"darkviolet" : "#9400d3",
+"deeppink" : "#ff1493",
+"deeppink1" : "#ff1493",
+"deeppink2" : "#ee1289",
+"deeppink3" : "#cd1076",
+"deeppink4" : "#8b0a50",
+"deepskyblue" : "#00bfff",
+"deepskyblue1" : "#00bfff",
+"deepskyblue2" : "#00b2ee",
+"deepskyblue3" : "#009acd",
+"deepskyblue4" : "#00688b",
+"dimgray" : "#696969",
+"dimgrey" : "#696969",
+"dodgerblue" : "#1e90ff",
+"dodgerblue1" : "#1e90ff",
+"dodgerblue2" : "#1c86ee",
+"dodgerblue3" : "#1874cd",
+"dodgerblue4" : "#104e8b",
+"firebrick" : "#b22222",
+"firebrick1" : "#ff3030",
+"firebrick2" : "#ee2c2c",
+"firebrick3" : "#cd2626",
+"firebrick4" : "#8b1a1a",
+"floralwhite" : "#fffaf0",
+"forestgreen" : "#228b22",
+"gainsboro" : "#dcdcdc",
+"ghostwhite" : "#f8f8ff",
+"gold" : "#ffd700",
+"gold1" : "#ffd700",
+"gold2" : "#eec900",
+"gold3" : "#cdad00",
+"gold4" : "#8b7500",
+"goldenrod" : "#daa520",
+"goldenrod1" : "#ffc125",
+"goldenrod2" : "#eeb422",
+"goldenrod3" : "#cd9b1d",
+"goldenrod4" : "#8b6914",
+"gray" : "#c0c0c0",
+"gray0" : "#000000",
+"gray1" : "#030303",
+"gray2" : "#050505",
+"gray3" : "#080808",
+"gray4" : "#0a0a0a",
+"gray5" : "#0d0d0d",
+"gray6" : "#0f0f0f",
+"gray7" : "#121212",
+"gray8" : "#141414",
+"gray9" : "#171717",
+"gray10" : "#1a1a1a",
+"gray11" : "#1c1c1c",
+"gray12" : "#1f1f1f",
+"gray13" : "#212121",
+"gray14" : "#242424",
+"gray15" : "#262626",
+"gray16" : "#292929",
+"gray17" : "#2b2b2b",
+"gray18" : "#2e2e2e",
+"gray19" : "#303030",
+"gray20" : "#333333",
+"gray21" : "#363636",
+"gray22" : "#383838",
+"gray23" : "#3b3b3b",
+"gray24" : "#3d3d3d",
+"gray25" : "#404040",
+"gray26" : "#424242",
+"gray27" : "#454545",
+"gray28" : "#474747",
+"gray29" : "#4a4a4a",
+"gray30" : "#4d4d4d",
+"gray31" : "#4f4f4f",
+"gray32" : "#525252",
+"gray33" : "#545454",
+"gray34" : "#575757",
+"gray35" : "#595959",
+"gray36" : "#5c5c5c",
+"gray37" : "#5e5e5e",
+"gray38" : "#616161",
+"gray39" : "#636363",
+"gray40" : "#666666",
+"gray41" : "#696969",
+"gray42" : "#6b6b6b",
+"gray43" : "#6e6e6e",
+"gray44" : "#707070",
+"gray45" : "#737373",
+"gray46" : "#757575",
+"gray47" : "#787878",
+"gray48" : "#7a7a7a",
+"gray49" : "#7d7d7d",
+"gray50" : "#7f7f7f",
+"gray51" : "#828282",
+"gray52" : "#858585",
+"gray53" : "#878787",
+"gray54" : "#8a8a8a",
+"gray55" : "#8c8c8c",
+"gray56" : "#8f8f8f",
+"gray57" : "#919191",
+"gray58" : "#949494",
+"gray59" : "#969696",
+"gray60" : "#999999",
+"gray61" : "#9c9c9c",
+"gray62" : "#9e9e9e",
+"gray63" : "#a1a1a1",
+"gray64" : "#a3a3a3",
+"gray65" : "#a6a6a6",
+"gray66" : "#a8a8a8",
+"gray67" : "#ababab",
+"gray68" : "#adadad",
+"gray69" : "#b0b0b0",
+"gray70" : "#b3b3b3",
+"gray71" : "#b5b5b5",
+"gray72" : "#b8b8b8",
+"gray73" : "#bababa",
+"gray74" : "#bdbdbd",
+"gray75" : "#bfbfbf",
+"gray76" : "#c2c2c2",
+"gray77" : "#c4c4c4",
+"gray78" : "#c7c7c7",
+"gray79" : "#c9c9c9",
+"gray80" : "#cccccc",
+"gray81" : "#cfcfcf",
+"gray82" : "#d1d1d1",
+"gray83" : "#d4d4d4",
+"gray84" : "#d6d6d6",
+"gray85" : "#d9d9d9",
+"gray86" : "#dbdbdb",
+"gray87" : "#dedede",
+"gray88" : "#e0e0e0",
+"gray89" : "#e3e3e3",
+"gray90" : "#e5e5e5",
+"gray91" : "#e8e8e8",
+"gray92" : "#ebebeb",
+"gray93" : "#ededed",
+"gray94" : "#f0f0f0",
+"gray95" : "#f2f2f2",
+"gray96" : "#f5f5f5",
+"gray97" : "#f7f7f7",
+"gray98" : "#fafafa",
+"gray99" : "#fcfcfc",
+"gray100" : "#ffffff",
+"green" : "#00ff00",
+"green1" : "#00ff00",
+"green2" : "#00ee00",
+"green3" : "#00cd00",
+"green4" : "#008b00",
+"greenyellow" : "#adff2f",
+"grey" : "#c0c0c0",
+"grey0" : "#000000",
+"grey1" : "#030303",
+"grey2" : "#050505",
+"grey3" : "#080808",
+"grey4" : "#0a0a0a",
+"grey5" : "#0d0d0d",
+"grey6" : "#0f0f0f",
+"grey7" : "#121212",
+"grey8" : "#141414",
+"grey9" : "#171717",
+"grey10" : "#1a1a1a",
+"grey11" : "#1c1c1c",
+"grey12" : "#1f1f1f",
+"grey13" : "#212121",
+"grey14" : "#242424",
+"grey15" : "#262626",
+"grey16" : "#292929",
+"grey17" : "#2b2b2b",
+"grey18" : "#2e2e2e",
+"grey19" : "#303030",
+"grey20" : "#333333",
+"grey21" : "#363636",
+"grey22" : "#383838",
+"grey23" : "#3b3b3b",
+"grey24" : "#3d3d3d",
+"grey25" : "#404040",
+"grey26" : "#424242",
+"grey27" : "#454545",
+"grey28" : "#474747",
+"grey29" : "#4a4a4a",
+"grey30" : "#4d4d4d",
+"grey31" : "#4f4f4f",
+"grey32" : "#525252",
+"grey33" : "#545454",
+"grey34" : "#575757",
+"grey35" : "#595959",
+"grey36" : "#5c5c5c",
+"grey37" : "#5e5e5e",
+"grey38" : "#616161",
+"grey39" : "#636363",
+"grey40" : "#666666",
+"grey41" : "#696969",
+"grey42" : "#6b6b6b",
+"grey43" : "#6e6e6e",
+"grey44" : "#707070",
+"grey45" : "#737373",
+"grey46" : "#757575",
+"grey47" : "#787878",
+"grey48" : "#7a7a7a",
+"grey49" : "#7d7d7d",
+"grey50" : "#7f7f7f",
+"grey51" : "#828282",
+"grey52" : "#858585",
+"grey53" : "#878787",
+"grey54" : "#8a8a8a",
+"grey55" : "#8c8c8c",
+"grey56" : "#8f8f8f",
+"grey57" : "#919191",
+"grey58" : "#949494",
+"grey59" : "#969696",
+"grey60" : "#999999",
+"grey61" : "#9c9c9c",
+"grey62" : "#9e9e9e",
+"grey63" : "#a1a1a1",
+"grey64" : "#a3a3a3",
+"grey65" : "#a6a6a6",
+"grey66" : "#a8a8a8",
+"grey67" : "#ababab",
+"grey68" : "#adadad",
+"grey69" : "#b0b0b0",
+"grey70" : "#b3b3b3",
+"grey71" : "#b5b5b5",
+"grey72" : "#b8b8b8",
+"grey73" : "#bababa",
+"grey74" : "#bdbdbd",
+"grey75" : "#bfbfbf",
+"grey76" : "#c2c2c2",
+"grey77" : "#c4c4c4",
+"grey78" : "#c7c7c7",
+"grey79" : "#c9c9c9",
+"grey80" : "#cccccc",
+"grey81" : "#cfcfcf",
+"grey82" : "#d1d1d1",
+"grey83" : "#d4d4d4",
+"grey84" : "#d6d6d6",
+"grey85" : "#d9d9d9",
+"grey86" : "#dbdbdb",
+"grey87" : "#dedede",
+"grey88" : "#e0e0e0",
+"grey89" : "#e3e3e3",
+"grey90" : "#e5e5e5",
+"grey91" : "#e8e8e8",
+"grey92" : "#ebebeb",
+"grey93" : "#ededed",
+"grey94" : "#f0f0f0",
+"grey95" : "#f2f2f2",
+"grey96" : "#f5f5f5",
+"grey97" : "#f7f7f7",
+"grey98" : "#fafafa",
+"grey99" : "#fcfcfc",
+"grey100" : "#ffffff",
+"honeydew" : "#f0fff0",
+"honeydew1" : "#f0fff0",
+"honeydew2" : "#e0eee0",
+"honeydew3" : "#c1cdc1",
+"honeydew4" : "#838b83",
+"hotpink" : "#ff69b4",
+"hotpink1" : "#ff6eb4",
+"hotpink2" : "#ee6aa7",
+"hotpink3" : "#cd6090",
+"hotpink4" : "#8b3a62",
+"indianred" : "#cd5c5c",
+"indianred1" : "#ff6a6a",
+"indianred2" : "#ee6363",
+"indianred3" : "#cd5555",
+"indianred4" : "#8b3a3a",
+"indigo" : "#4b0082",
+"ivory" : "#fffff0",
+"ivory1" : "#fffff0",
+"ivory2" : "#eeeee0",
+"ivory3" : "#cdcdc1",
+"ivory4" : "#8b8b83",
+"khaki" : "#f0e68c",
+"khaki1" : "#fff68f",
+"khaki2" : "#eee685",
+"khaki3" : "#cdc673",
+"khaki4" : "#8b864e",
+"lavender" : "#e6e6fa",
+"lavenderblush" : "#fff0f5",
+"lavenderblush1" : "#fff0f5",
+"lavenderblush2" : "#eee0e5",
+"lavenderblush3" : "#cdc1c5",
+"lavenderblush4" : "#8b8386",
+"lawngreen" : "#7cfc00",
+"lemonchiffon" : "#fffacd",
+"lemonchiffon1" : "#fffacd",
+"lemonchiffon2" : "#eee9bf",
+"lemonchiffon3" : "#cdc9a5",
+"lemonchiffon4" : "#8b8970",
+"lightblue" : "#add8e6",
+"lightblue1" : "#bfefff",
+"lightblue2" : "#b2dfee",
+"lightblue3" : "#9ac0cd",
+"lightblue4" : "#68838b",
+"lightcoral" : "#f08080",
+"lightcyan" : "#e0ffff",
+"lightcyan1" : "#e0ffff",
+"lightcyan2" : "#d1eeee",
+"lightcyan3" : "#b4cdcd",
+"lightcyan4" : "#7a8b8b",
+"lightgoldenrod" : "#eedd82",
+"lightgoldenrod1" : "#ffec8b",
+"lightgoldenrod2" : "#eedc82",
+"lightgoldenrod3" : "#cdbe70",
+"lightgoldenrod4" : "#8b814c",
+"lightgoldenrodyellow" : "#fafad2",
+"lightgray" : "#d3d3d3",
+"lightgrey" : "#d3d3d3",
+"lightpink" : "#ffb6c1",
+"lightpink1" : "#ffaeb9",
+"lightpink2" : "#eea2ad",
+"lightpink3" : "#cd8c95",
+"lightpink4" : "#8b5f65",
+"lightsalmon" : "#ffa07a",
+"lightsalmon1" : "#ffa07a",
+"lightsalmon2" : "#ee9572",
+"lightsalmon3" : "#cd8162",
+"lightsalmon4" : "#8b5742",
+"lightseagreen" : "#20b2aa",
+"lightskyblue" : "#87cefa",
+"lightskyblue1" : "#b0e2ff",
+"lightskyblue2" : "#a4d3ee",
+"lightskyblue3" : "#8db6cd",
+"lightskyblue4" : "#607b8b",
+"lightslateblue" : "#8470ff",
+"lightslategray" : "#778899",
+"lightslategrey" : "#778899",
+"lightsteelblue" : "#b0c4de",
+"lightsteelblue1" : "#cae1ff",
+"lightsteelblue2" : "#bcd2ee",
+"lightsteelblue3" : "#a2b5cd",
+"lightsteelblue4" : "#6e7b8b",
+"lightyellow" : "#ffffe0",
+"lightyellow1" : "#ffffe0",
+"lightyellow2" : "#eeeed1",
+"lightyellow3" : "#cdcdb4",
+"lightyellow4" : "#8b8b7a",
+"limegreen" : "#32cd32",
+"linen" : "#faf0e6",
+"magenta" : "#ff00ff",
+"magenta1" : "#ff00ff",
+"magenta2" : "#ee00ee",
+"magenta3" : "#cd00cd",
+"magenta4" : "#8b008b",
+"maroon" : "#b03060",
+"maroon1" : "#ff34b3",
+"maroon2" : "#ee30a7",
+"maroon3" : "#cd2990",
+"maroon4" : "#8b1c62",
+"mediumaquamarine" : "#66cdaa",
+"mediumblue" : "#0000cd",
+"mediumorchid" : "#ba55d3",
+"mediumorchid1" : "#e066ff",
+"mediumorchid2" : "#d15fee",
+"mediumorchid3" : "#b452cd",
+"mediumorchid4" : "#7a378b",
+"mediumpurple" : "#9370db",
+"mediumpurple1" : "#ab82ff",
+"mediumpurple2" : "#9f79ee",
+"mediumpurple3" : "#8968cd",
+"mediumpurple4" : "#5d478b",
+"mediumseagreen" : "#3cb371",
+"mediumslateblue" : "#7b68ee",
+"mediumspringgreen" : "#00fa9a",
+"mediumturquoise" : "#48d1cc",
+"mediumvioletred" : "#c71585",
+"midnightblue" : "#191970",
+"mintcream" : "#f5fffa",
+"mistyrose" : "#ffe4e1",
+"mistyrose1" : "#ffe4e1",
+"mistyrose2" : "#eed5d2",
+"mistyrose3" : "#cdb7b5",
+"mistyrose4" : "#8b7d7b",
+"moccasin" : "#ffe4b5",
+"navajowhite" : "#ffdead",
+"navajowhite1" : "#ffdead",
+"navajowhite2" : "#eecfa1",
+"navajowhite3" : "#cdb38b",
+"navajowhite4" : "#8b795e",
+"navy" : "#000080",
+"navyblue" : "#000080",
+"oldlace" : "#fdf5e6",
+"olivedrab" : "#6b8e23",
+"olivedrab1" : "#c0ff3e",
+"olivedrab2" : "#b3ee3a",
+"olivedrab3" : "#9acd32",
+"olivedrab4" : "#698b22",
+"orange" : "#ffa500",
+"orange1" : "#ffa500",
+"orange2" : "#ee9a00",
+"orange3" : "#cd8500",
+"orange4" : "#8b5a00",
+"orangered" : "#ff4500",
+"orangered1" : "#ff4500",
+"orangered2" : "#ee4000",
+"orangered3" : "#cd3700",
+"orangered4" : "#8b2500",
+"orchid" : "#da70d6",
+"orchid1" : "#ff83fa",
+"orchid2" : "#ee7ae9",
+"orchid3" : "#cd69c9",
+"orchid4" : "#8b4789",
+"palegoldenrod" : "#eee8aa",
+"palegreen" : "#98fb98",
+"palegreen1" : "#9aff9a",
+"palegreen2" : "#90ee90",
+"palegreen3" : "#7ccd7c",
+"palegreen4" : "#548b54",
+"paleturquoise" : "#afeeee",
+"paleturquoise1" : "#bbffff",
+"paleturquoise2" : "#aeeeee",
+"paleturquoise3" : "#96cdcd",
+"paleturquoise4" : "#668b8b",
+"palevioletred" : "#db7093",
+"palevioletred1" : "#ff82ab",
+"palevioletred2" : "#ee799f",
+"palevioletred3" : "#cd6889",
+"palevioletred4" : "#8b475d",
+"papayawhip" : "#ffefd5",
+"peachpuff" : "#ffdab9",
+"peachpuff1" : "#ffdab9",
+"peachpuff2" : "#eecbad",
+"peachpuff3" : "#cdaf95",
+"peachpuff4" : "#8b7765",
+"peru" : "#cd853f",
+"pink" : "#ffc0cb",
+"pink1" : "#ffb5c5",
+"pink2" : "#eea9b8",
+"pink3" : "#cd919e",
+"pink4" : "#8b636c",
+"plum" : "#dda0dd",
+"plum1" : "#ffbbff",
+"plum2" : "#eeaeee",
+"plum3" : "#cd96cd",
+"plum4" : "#8b668b",
+"powderblue" : "#b0e0e6",
+"purple" : "#a020f0",
+"purple1" : "#9b30ff",
+"purple2" : "#912cee",
+"purple3" : "#7d26cd",
+"purple4" : "#551a8b",
+"red" : "#ff0000",
+"red1" : "#ff0000",
+"red2" : "#ee0000",
+"red3" : "#cd0000",
+"red4" : "#8b0000",
+"rosybrown" : "#bc8f8f",
+"rosybrown1" : "#ffc1c1",
+"rosybrown2" : "#eeb4b4",
+"rosybrown3" : "#cd9b9b",
+"rosybrown4" : "#8b6969",
+"royalblue" : "#4169e1",
+"royalblue1" : "#4876ff",
+"royalblue2" : "#436eee",
+"royalblue3" : "#3a5fcd",
+"royalblue4" : "#27408b",
+"saddlebrown" : "#8b4513",
+"salmon" : "#fa8072",
+"salmon1" : "#ff8c69",
+"salmon2" : "#ee8262",
+"salmon3" : "#cd7054",
+"salmon4" : "#8b4c39",
+"sandybrown" : "#f4a460",
+"seagreen" : "#2e8b57",
+"seagreen1" : "#54ff9f",
+"seagreen2" : "#4eee94",
+"seagreen3" : "#43cd80",
+"seagreen4" : "#2e8b57",
+"seashell" : "#fff5ee",
+"seashell1" : "#fff5ee",
+"seashell2" : "#eee5de",
+"seashell3" : "#cdc5bf",
+"seashell4" : "#8b8682",
+"sienna" : "#a0522d",
+"sienna1" : "#ff8247",
+"sienna2" : "#ee7942",
+"sienna3" : "#cd6839",
+"sienna4" : "#8b4726",
+"skyblue" : "#87ceeb",
+"skyblue1" : "#87ceff",
+"skyblue2" : "#7ec0ee",
+"skyblue3" : "#6ca6cd",
+"skyblue4" : "#4a708b",
+"slateblue" : "#6a5acd",
+"slateblue1" : "#836fff",
+"slateblue2" : "#7a67ee",
+"slateblue3" : "#6959cd",
+"slateblue4" : "#473c8b",
+"slategray" : "#708090",
+"slategray1" : "#c6e2ff",
+"slategray2" : "#b9d3ee",
+"slategray3" : "#9fb6cd",
+"slategray4" : "#6c7b8b",
+"slategrey" : "#708090",
+"snow" : "#fffafa",
+"snow1" : "#fffafa",
+"snow2" : "#eee9e9",
+"snow3" : "#cdc9c9",
+"snow4" : "#8b8989",
+"springgreen" : "#00ff7f",
+"springgreen1" : "#00ff7f",
+"springgreen2" : "#00ee76",
+"springgreen3" : "#00cd66",
+"springgreen4" : "#008b45",
+"steelblue" : "#4682b4",
+"steelblue1" : "#63b8ff",
+"steelblue2" : "#5cacee",
+"steelblue3" : "#4f94cd",
+"steelblue4" : "#36648b",
+"tan" : "#d2b48c",
+"tan1" : "#ffa54f",
+"tan2" : "#ee9a49",
+"tan3" : "#cd853f",
+"tan4" : "#8b5a2b",
+"thistle" : "#d8bfd8",
+"thistle1" : "#ffe1ff",
+"thistle2" : "#eed2ee",
+"thistle3" : "#cdb5cd",
+"thistle4" : "#8b7b8b",
+"tomato" : "#ff6347",
+"tomato1" : "#ff6347",
+"tomato2" : "#ee5c42",
+"tomato3" : "#cd4f39",
+"tomato4" : "#8b3626",
+"transparent" : "#fffffe",
+"turquoise" : "#40e0d0",
+"turquoise1" : "#00f5ff",
+"turquoise2" : "#00e5ee",
+"turquoise3" : "#00c5cd",
+"turquoise4" : "#00868b",
+"violet" : "#ee82ee",
+"violetred" : "#d02090",
+"violetred1" : "#ff3e96",
+"violetred2" : "#ee3a8c",
+"violetred3" : "#cd3278",
+"violetred4" : "#8b2252",
+"wheat" : "#f5deb3",
+"wheat1" : "#ffe7ba",
+"wheat2" : "#eed8ae",
+"wheat3" : "#cdba96",
+"wheat4" : "#8b7e66",
+"white" : "#ffffff",
+"whitesmoke" : "#f5f5f5",
+"yellow" : "#ffff00",
+"yellow1" : "#ffff00",
+"yellow2" : "#eeee00",
+"yellow3" : "#cdcd00",
+"yellow4" : "#8b8b00",
+"yellowgreen" : "#9acd32",
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dottoxml/src/dot.py	Mon Jul 23 09:54:49 2012 +0200
@@ -0,0 +1,445 @@
+# coding: latin-1
+# Copyright (c) 2009,2010 Dirk Baechle.
+# www: http://www.mydarc.de/dl9obn/programming/python/dottoxml
+# mail: dl9obn AT darc.de
+#
+# 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.,
+# 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+"""
+  Helper classes and functions for the dottoxml.py tool
+"""
+
+import re
+import X11Colors
+
+r_label = re.compile(r'label\s*=\s*"\s*\{[^\}]*\}\s*"\s*')
+r_labelstart = re.compile(r'label\s*=\s*"\s*\{')
+r_labelclose = re.compile(r'\}\s*"')
+
+def compileAttributes(attribs):
+    """ return the list of attributes as a DOT text string """
+    atxt = ""
+    first = True
+    for key, value in attribs.iteritems():
+        if not first:
+            atxt += ", %s=\"%s\"" % (key, value)
+        else:
+            atxt += "%s=\"%s\"" % (key, value)
+            first = False
+            
+    return "[%s]" % atxt
+
+def parseAttributes(attribs):
+    """ parse the attribute list and return a key/value dict for it """
+    adict = {}
+    tlist = []
+    lmode = False
+    ltext = ''
+    # First pass: split entries by ,
+    for a in attribs.split(','):
+        if r_label.findall(a):
+            tlist.append(a)
+        elif r_labelstart.findall(a):
+            ltext = a
+            lmode = True
+        else:
+            if lmode:
+                ltext += ",%s" % a
+                if r_labelclose.findall(a):
+                    lmode = False
+                    tlist.append(ltext)
+            else:
+                tlist.append(a)
+
+    # Second pass: split keys from values by =
+    for t in tlist:
+        apos = t.find('=')
+        if apos > 0:
+            adict[t[:apos].strip()] = t[apos+1:].strip().strip('"')
+
+    return adict
+
+def getLabelAttributes(label):
+    """ return the sections of the label attributes in a list structure """
+    sections = []
+    slist = label.split('|')
+    for s in slist:
+        mlist = []
+        s = s.replace('\\r','\\l')
+        s = s.replace('\\n','\\l')
+        alist = s.split('\\l')
+        for a in alist:
+            a = a.strip()
+            if a != "":
+                mlist.append(a)
+        sections.append(mlist)
+    return sections
+
+def colorNameToRgb(fcol, defaultcol):
+    """ convert the color name fcol to an RGB string, if required """
+    if not fcol.startswith('#'):
+        return X11Colors.color_map.get(fcol, defaultcol)
+    else:
+        return fcol
+    
+def getColorAttribute(attribs, key, defaultcol, conf):
+    """ extract the color for the attribute key and convert it
+        to RGB format if required
+    """
+    if conf.Colors:
+        if attribs.has_key(key):
+            return colorNameToRgb(attribs[key], defaultcol)
+    return defaultcol
+
+def escapeNewlines(label):
+    """ convert the newline escape sequences in the given label """
+    l = label.replace('\\n','\n')
+    l = l.replace('\\l','\n')
+    l = l.replace('\\r','\n')
+    return l
+
+class Node:
+    """ a single node in the graph """
+    def __init__(self):
+        self.label = ""
+        self.id = 0
+        self.attribs = {}
+        self.referenced = False
+        self.sections = []
+
+    def initFromString(self, line):
+        """ extract node info from the given text line """
+        spos = line.find('[')
+        atts = ""
+        if spos >= 0:
+            atts = line[spos+1:]
+            line = line[:spos].strip()
+        # Process label
+        self.label = line.strip('"')
+        # Process attributes
+        if len(atts):
+            spos = atts.rfind(']')
+            if spos > 0:
+                atts = atts[:spos]
+                self.attribs = parseAttributes(atts)
+        # Process sections
+        if self.attribs.has_key("label"):
+            tlabel = self.attribs["label"]
+            if (tlabel != "" and     
+                tlabel.startswith('{') and
+                tlabel.endswith('}')):
+                tlabel = tlabel[1:-1]
+                self.sections = getLabelAttributes(tlabel)
+        # HACK DW, no label in attrs, dann label in attrs = node.label
+        else:
+            self.attribs["label"]=self.label
+
+    def getLabel(self, conf, multiline=False):
+        """ return the label of the node """
+        if conf.NodeLabels:
+            if self.attribs.has_key('label'):
+                if len(self.sections) > 0:
+                    if multiline:
+                        return '\n'.join(self.sections[0])
+                    else:
+                        return ','.join(self.sections[0])
+                else:
+                    return self.attribs['label']
+            else:
+                return self.label
+        else:
+            return ""
+
+    def getLabelWidth(self, conf, multiline=False):
+        """ return the maximum width label of the node label"""
+        if conf.NodeLabels:
+            if self.attribs.has_key('label'):
+                if len(self.sections) > 0:
+                    if multiline:
+                        # Find maximum label width
+                        width = 1
+                        for s in self.sections[0]:
+                            if len(s) > width:
+                                width = len(s)
+                        for s in self.sections[1]:
+                            if len(s) > width:
+                                width = len(s)
+                        for s in self.sections[2]:
+                            if len(s) > width:
+                                width = len(s)
+                        return width
+                    else:
+                        return len(','.join(self.sections[0]))
+                else:
+                    return len(self.attribs['label'])
+            else:
+                return len(self.label)
+        else:
+            return 0
+
+    def complementAttributes(self, node):
+        """ from node copy all new attributes, that do not exist in self """
+        for a in node.attribs:
+            if not self.attribs.has_key(a):
+                self.attribs[a] = node.attribs[a]
+                
+    def exportDot(self, o, conf):
+        """ write the node in DOT format to the given file """
+        if len(self.attribs) > 0:
+            o.write("\"%s\" %s;\n" % (self.label, compileAttributes(self.attribs)))
+        else:
+            o.write("\"%s\";\n" % (self.label))
+
+    def exportGDF(self, o, conf):
+        """ write the node in GDF format to the given file """
+        tlabel = self.getLabel(conf)
+        if tlabel == "":
+            tlabel = "n%d" % self.id
+        o.write("%s\n" % tlabel)
+
+    def exportGML(self, o, conf):
+        """ write the node in GML format to the given file """
+        o.write("  node [\n")
+        o.write("    id %d\n" % self.id)
+        o.write("    label\n")
+        o.write("    \"%s\"\n" % self.getLabel(conf))
+        o.write("  ]\n")
+
+    def exportGraphml(self, doc, parent, conf):        
+        """ export the node in Graphml format and append it to the parent XML node """
+        node = doc.createElement(u'node')
+        node.setAttribute(u'id',u'n%d' % self.id)
+        
+        data0 = doc.createElement(u'data')
+        data0.setAttribute(u'key', u'd0')
+
+        exportUml = False
+        if len(self.sections) > 0 and conf.NodeUml and not conf.LumpAttributes:
+            exportUml = True
+            snode = doc.createElement(u'y:UMLClassNode')
+        else:
+            snode = doc.createElement(u'y:ShapeNode')
+        geom = doc.createElement(u'y:Geometry')
+        geom.setAttribute(u'height',u'30.0')
+        geom.setAttribute(u'width',u'30.0')
+        geom.setAttribute(u'x',u'0.0')
+        geom.setAttribute(u'y',u'0.0')
+        snode.appendChild(geom)
+        color = getColorAttribute(self.attribs, 'color', conf.DefaultNodeColor, conf)
+        fill = doc.createElement(u'y:Fill')
+        fill.setAttribute(u'color',u'%s' % color)
+        fill.setAttribute(u'transparent',u'false')
+        snode.appendChild(fill)
+        border = doc.createElement(u'y:BorderStyle')
+        border.setAttribute(u'color',u'#000000')
+        border.setAttribute(u'type',u'line')
+        border.setAttribute(u'width',u'1.0')
+        snode.appendChild(border)
+        color = getColorAttribute(self.attribs, 'fontcolor', conf.DefaultNodeTextColor, conf)        
+        label = doc.createElement(u'y:NodeLabel')
+        if conf.LumpAttributes:
+            label.setAttribute(u'alignment',u'left')
+        else:
+            label.setAttribute(u'alignment',u'center')
+        label.setAttribute(u'autoSizePolicy',u'content')
+        label.setAttribute(u'fontFamily',u'Dialog')
+        label.setAttribute(u'fontSize',u'12')
+        label.setAttribute(u'fontStyle',u'plain')
+        label.setAttribute(u'hasBackgroundColor',u'false')
+        label.setAttribute(u'hasLineColor',u'false')
+        label.setAttribute(u'modelName',u'internal')
+        label.setAttribute(u'modelPosition',u'c')
+        label.setAttribute(u'textColor',u'%s' % color)
+        label.setAttribute(u'visible',u'true')
+        nodeLabelText = escapeNewlines(self.getLabel(conf, True))
+        if conf.LumpAttributes:
+            # Find maximum label width
+            width = self.getLabelWidth(conf, True)
+            nodeLabelText += '\n' + conf.SepChar*width + '\n'
+            nodeLabelText += u'%s\n' % '\n'.join(self.sections[1])
+            nodeLabelText += conf.SepChar*width + '\n'
+            nodeLabelText += u'%s' % '\n'.join(self.sections[2])
+        label.appendChild(doc.createTextNode(u'%s' % nodeLabelText))        
+        snode.appendChild(label)
+        if exportUml and not conf.LumpAttributes:
+            shape = doc.createElement(u'y:UML')
+            shape.setAttribute(u'clipContent',u'true')
+            shape.setAttribute(u'constraint',u'')
+            shape.setAttribute(u'omitDetails',u'false')
+            shape.setAttribute(u'stereotype',u'') 
+            shape.setAttribute(u'use3DEffect',u'true')
+     
+            alabel = doc.createElement(u'y:AttributeLabel')
+            alabel.appendChild(doc.createTextNode(u'%s' % '\n'.join(self.sections[1])))
+            shape.appendChild(alabel)
+            mlabel = doc.createElement(u'y:MethodLabel')
+            mlabel.appendChild(doc.createTextNode(u'%s' % '\n'.join(self.sections[2])))
+            shape.appendChild(mlabel)
+        else:
+            shape = doc.createElement(u'y:Shape')
+            shape.setAttribute(u'type',u'rectangle')
+        snode.appendChild(shape)
+        data0.appendChild(snode)
+        node.appendChild(data0)
+
+        data1 = doc.createElement(u'data')
+        data1.setAttribute(u'key', u'd1')
+        node.appendChild(data1)
+        
+        if self.attribs.get("URL","")!="":
+            
+            data3 = doc.createElement(u'data')
+            data3.setAttribute(u'key', u'd4')
+            data3.appendChild(doc.createTextNode(u'%s' % self.attribs.get("URL","")))    
+            node.appendChild(data3)
+            
+        parent.appendChild(node)
+
+class Edge:
+    """ a single edge in the graph """
+    def __init__(self):
+        self.id = 0
+        self.src = ""
+        self.dest = ""
+        self.attribs = {}
+
+    def initFromString(self, line):
+        """ extract edge info from the given text line """
+        spos = line.find('[')
+        atts = ""
+        if spos >= 0:
+            atts = line[spos+1:]
+            line = line[:spos].strip()
+
+        # Process labels
+        ll = line.replace('->',' ').split()
+        if len(ll) > 1:
+            self.src = ll[0].strip('"')
+            self.dest = ll[1].rstrip(';').strip('"')
+        # Process attributes
+        if len(atts):
+            spos = atts.rfind(']')
+            if spos > 0:
+                atts = atts[:spos]
+                self.attribs = parseAttributes(atts)
+                        
+    def getLabel(self, nodes, conf):
+        """ return the label of the edge """
+        if conf.EdgeLabels:
+            if self.attribs.has_key('label'):
+                return self.attribs['label']
+            else:
+                if conf.EdgeLabelsAutoComplete:
+                    srclink = self.src
+                    destlink = self.dest
+                    if (nodes[self.src].attribs.has_key('label')):
+                        srclink = nodes[self.src].attribs['label']
+                    if (nodes[self.dest].attribs.has_key('label')):
+                        destlink = nodes[self.dest].attribs['label']
+                    return "%s -> %s" % (srclink, destlink)
+                else:
+                    return ""
+        else:
+            return ""
+
+    def complementAttributes(self, edge):
+        """ from edge copy all new attributes, that do not exist in self """
+        for a in edge.attribs:
+            if not self.attribs.has_key(a):
+                self.attribs[a] = edge.attribs[a]
+                
+    def exportDot(self, o, nodes, conf):
+        """ write the edge in DOT format to the given file """
+        if len(self.attribs) > 0:
+            o.write("\"%s\" -> \"%s\" %s;\n" % (self.src, self.dest, compileAttributes(self.attribs)))
+        else:
+            o.write("\"%s\" -> \"%s\";\n" % (self.src, self.dest))
+
+    def exportGDF(self, o, nodes, conf):
+        """ write the edge in GDF format to the given file """
+        slabel = self.src.getLabel(conf)
+        if slabel == "":
+            slabel = "n%d" % self.src.id
+        dlabel = self.dest.getLabel(conf)
+        if dlabel == "":
+            dlabel = "n%d" % self.dest.id
+        o.write("%s,%s\n" % (slabel, dlabel))
+
+    def exportGML(self, o, nodes, conf):
+        """ write the edge in GML format to the given file """
+        o.write("  edge [\n")
+        o.write("    source %d\n" % nodes[self.src].id)
+        o.write("    target %d\n" % nodes[self.dest].id)
+        o.write("    label\n")
+        o.write("    \"%s\"\n" % self.getLabel(nodes, conf))
+        o.write("  ]\n")
+
+    def exportGraphml(self, doc, parent, nodes, conf):
+        """ export the edge in Graphml format and append it to the parent XML node """
+        edge = doc.createElement(u'edge')
+        edge.setAttribute(u'id',u'e%d' % self.id)
+        edge.setAttribute(u'source',u'n%d' % nodes[self.src].id)
+        edge.setAttribute(u'target',u'n%d' % nodes[self.dest].id)
+        
+        data2 = doc.createElement(u'data')
+        data2.setAttribute(u'key', u'd2')
+
+        pedge = doc.createElement(u'y:PolyLineEdge')
+        line = doc.createElement(u'y:LineStyle')      
+        color = getColorAttribute(self.attribs, 'color', conf.DefaultEdgeColor, conf)
+        line.setAttribute(u'color',u'%s' % color)
+        line.setAttribute(u'type', u'line')
+        line.setAttribute(u'width', u'1.0')
+        pedge.appendChild(line)
+        arrow = doc.createElement(u'y:Arrows')
+        arrow_tail = conf.DefaultArrowTail
+        arrow_head = conf.DefaultArrowHead
+        if conf.Arrows:
+            if self.attribs.has_key('arrowtail'):
+                arrow_head = self.attribs['arrowtail']
+            if self.attribs.has_key('arrowhead'):
+                arrow_tail = self.attribs['arrowhead']
+        arrow.setAttribute(u'source',u'%s' % arrow_head)                
+        arrow.setAttribute(u'target',u'%s' % arrow_tail)                
+        pedge.appendChild(arrow)
+        if conf.EdgeLabels:
+            tlabel = self.getLabel(nodes, conf)
+            if tlabel != "":
+                label = doc.createElement(u'y:EdgeLabel')
+                color = getColorAttribute(self.attribs, 'fontcolor', conf.DefaultEdgeTextColor, conf)
+                label.setAttribute(u'alignment',u'center')
+                label.setAttribute(u'distance',u'2.0')
+                label.setAttribute(u'fontFamily',u'Dialog')
+                label.setAttribute(u'fontSize',u'12')
+                label.setAttribute(u'fontStyle',u'plain')
+                label.setAttribute(u'hasBackgroundColor',u'false')
+                label.setAttribute(u'hasLineColor',u'false')
+                label.setAttribute(u'modelName',u'six_pos')
+                label.setAttribute(u'modelPosition',u'tail')
+                label.setAttribute(u'textColor',u'%s' % color)
+                label.setAttribute(u'visible',u'true')
+                label.setAttribute(u'preferredPlacement',u'anywhere')
+                label.setAttribute(u'ratio',u'0.5')
+                label.appendChild(doc.createTextNode(u'%s' % escapeNewlines(tlabel)))        
+                pedge.appendChild(label)
+        bend = doc.createElement(u'y:BendStyle')      
+        bend.setAttribute(u'smoothed', u'false')
+        pedge.appendChild(bend)
+        data2.appendChild(pedge)
+        edge.appendChild(data2)
+
+        data3 = doc.createElement(u'data')
+        data3.setAttribute(u'key', u'd3')
+        edge.appendChild(data3)
+        
+        parent.appendChild(edge)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dottoxml/src/dottoxml.py	Mon Jul 23 09:54:49 2012 +0200
@@ -0,0 +1,320 @@
+# coding: latin-1
+# Copyright (c) 2009,2010,2011,2012 Dirk Baechle.
+# www: http://www.mydarc.de/dl9obn/programming/python/dottoxml
+# mail: dl9obn AT darc.de
+#
+# 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.,
+# 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+"""
+  %dottoxml.py [options] <infile.dot> <outfile.graphml>
+
+  convert a DOT file to Graphml XML (and various other formats)
+"""
+
+import sys
+import locale
+import optparse
+
+import dot
+
+# Usage message
+usgmsg = "Usage: dottoxml.py [options] infile.dot outfile.graphml"
+
+def usage():
+    print "dottoxml 1.3, 2012-04-04, Dirk Baechle\n"
+    print usgmsg
+    print "Hint: Try '-h' or '--help' for further infos!"
+
+def exportDot(o, nodes, edges, options):
+    o.write("graph [\n")
+
+    for k,nod in nodes.iteritems():
+        nod.exportDot(o,options)
+    for el in edges:
+        el.exportDot(o,nodes,options)
+
+def exportGML(o, nodes, edges, options):
+    o.write("graph [\n")
+    o.write("  comment \"Created by dottoxml.py\"\n")
+    o.write("  directed 1\n")
+    o.write("  IsPlanar 1\n")
+
+    for k,nod in nodes.iteritems():
+        nod.exportGML(o,options)
+    for el in edges:
+        el.exportGML(o,nodes,options)
+
+    o.write("]\n")
+
+def exportGraphml(o, nodes, edges, options):
+    import xml.dom.minidom
+    doc = xml.dom.minidom.Document()
+    root = doc.createElement(u'graphml')
+    root.setAttribute(u'xmlns',u'http://graphml.graphdrawing.org/xmlns/graphml')
+    root.setAttribute(u'xmlns:xsi',u'http://www.w3.org/2001/XMLSchema-instance')
+    root.setAttribute(u'xmlns:y',u'http://www.yworks.com/xml/graphml')
+    root.setAttribute(u'xsi:schemaLocation',u'http://graphml.graphdrawing.org/xmlns/graphml http://www.yworks.com/xml/schema/graphml/1.0/ygraphml.xsd')
+    doc.appendChild(root)        
+    key = doc.createElement(u'key')
+    key.setAttribute(u'for',u'node')    
+    key.setAttribute(u'id',u'd0')    
+    key.setAttribute(u'yfiles.type',u'nodegraphics')    
+    root.appendChild(key)
+
+    key = doc.createElement(u'key')
+    key.setAttribute(u'attr.name',u'description')    
+    key.setAttribute(u'attr.type',u'string')    
+    key.setAttribute(u'for',u'node')    
+    key.setAttribute(u'id',u'd1')    
+    root.appendChild(key)
+
+    key = doc.createElement(u'key')
+    key.setAttribute(u'for',u'edge')    
+    key.setAttribute(u'id',u'd2')    
+    key.setAttribute(u'yfiles.type',u'edgegraphics')    
+    root.appendChild(key)
+
+    key = doc.createElement(u'key')
+    key.setAttribute(u'attr.name',u'description')    
+    key.setAttribute(u'attr.type',u'string')    
+    key.setAttribute(u'for',u'edge')    
+    key.setAttribute(u'id',u'd3')    
+    root.appendChild(key)
+
+    key = doc.createElement(u'key')
+    key.setAttribute(u'for',u'node')    
+    key.setAttribute(u'id',u'd4')    
+    key.setAttribute(u'attr.name',u'url')    
+    key.setAttribute(u'attr.type',u'string')    
+    root.appendChild(key)
+
+    graph = doc.createElement(u'graph')
+    graph.setAttribute(u'edgedefault',u'directed')    
+    graph.setAttribute(u'id',u'G')    
+    graph.setAttribute(u'parse.edges',u'%d' % len(edges))   
+    graph.setAttribute(u'parse.nodes',u'%d' % len(nodes))
+    graph.setAttribute(u'parse.order', u'free')    
+    
+    for k,nod in nodes.iteritems():
+        nod.exportGraphml(doc, graph, options)
+    for el in edges:
+        el.exportGraphml(doc, graph, nodes, options)
+
+    root.appendChild(graph)
+    
+    data = doc.createElement(u'data')
+    data.setAttribute(u'key',u'd4')    
+    res = doc.createElement(u'y:Resources')
+    data.appendChild(res)    
+    root.appendChild(data)
+    
+    o.write(doc.toxml(encoding="utf-8"))
+
+def exportGDF(o, nodes, edges, options):
+    o.write("nodedef> name\n")
+    for k,nod in nodes.iteritems():
+        nod.exportGDF(o, options)
+    for el in edges:
+        el.exportGDF(o,nodes,options)
+    o.write("edgedef> node1,node2\n")
+
+def main():
+    parser = optparse.OptionParser(usage=usgmsg)
+    parser.add_option('-f', '--format',
+                      action='store', dest='format', default='Graphml',
+                      help='selects the output format (Graphml|GML|GDF) [default : %default]')
+    parser.add_option('-v', '--verbose',
+                      action='store_true', dest='verbose', default=False,
+                      help='enables messages (infos, warnings)')
+    parser.add_option('-s', '--sweep',
+                      action='store_true', dest='sweep', default=False,
+                      help='sweep nodes (remove nodes that are not connected)')
+    parser.add_option('--nn', '--no-nodes',
+                      action='store_false', dest='NodeLabels', default=True,
+                      help='do not output any node labels [Graphml]')
+    parser.add_option('--ne', '--no-edges',
+                      action='store_false', dest='EdgeLabels', default=True,
+                      help='do not output any edge labels [Graphml]')
+    parser.add_option('--nu', '--no-uml',
+                      action='store_false', dest='NodeUml', default=True,
+                      help='do not output any node methods/attributes in UML [Graphml]')
+    parser.add_option('--na', '--no-arrows',
+                      action='store_false', dest='Arrows', default=True,
+                      help='do not output any arrows [Graphml]')
+    parser.add_option('--nc', '--no-colors',
+                      action='store_false', dest='Colors', default=True,
+                      help='do not output any colors [Graphml]')
+    parser.add_option('--la', '--lump-attributes',
+                      action='store_true', dest='LumpAttributes', default=False,
+                      help='lump class attributes/methods together with the node label [Graphml]')
+    parser.add_option('--sc', '--separator-char',
+                      action='store', dest='SepChar', default='_', metavar='SEPCHAR',
+                      help='default separator char when lumping attributes/methods [default : "_"]')
+    parser.add_option('--ae', '--auto-edges',
+                      action='store_true', dest='EdgeLabelsAutoComplete', default=False,
+                      help='auto-complete edge labels')
+    parser.add_option('--ah', '--arrowhead',
+                      action='store', dest='DefaultArrowHead', default='none', metavar='TYPE',
+                      help='sets the default appearance of arrow heads for edges (normal|diamond|dot|...) [default : %default]')
+    parser.add_option('--at', '--arrowtail',
+                      action='store', dest='DefaultArrowTail', default='none', metavar='TYPE',
+                      help='sets the default appearance of arrow tails for edges (normal|diamond|dot|...) [default : %default]')
+    parser.add_option('--cn', '--color-nodes',
+                      action='store', dest='DefaultNodeColor', default='#CCCCFF', metavar='COLOR',
+                      help='default node color [default : "#CCCCFF"]')
+    parser.add_option('--ce', '--color-edges',
+                      action='store', dest='DefaultEdgeColor', default='#000000', metavar='COLOR',
+                      help='default edge color [default : "#000000"]')
+    parser.add_option('--cnt', '--color-nodes-text',
+                      action='store', dest='DefaultNodeTextColor', default='#000000', metavar='COLOR',
+                      help='default node text color for labels [default : "#000000"]')
+    parser.add_option('--cet', '--color-edges-text',
+                      action='store', dest='DefaultEdgeTextColor', default='#000000', metavar='COLOR',
+                      help='default edge text color for labels [default : "#000000"]')
+    parser.add_option('--ienc', '--input-encoding',
+                      action='store', dest='InputEncoding', default='', metavar='ENCODING',
+                      help='override encoding for input file [default : locale setting]')
+    parser.add_option('--oenc', '--output-encoding',
+                      action='store', dest='OutputEncoding', default='', metavar='ENCODING',
+                      help='override encoding for text output files [default : locale setting]')
+
+    options, args = parser.parse_args()
+    
+    if len(args) < 2:
+        usage()
+        sys.exit(1)
+
+    infile = args[0]
+    outfile = args[1]
+
+    options.DefaultNodeColor = dot.colorNameToRgb(options.DefaultNodeColor, '#CCCCFF')
+    options.DefaultEdgeColor = dot.colorNameToRgb(options.DefaultEdgeColor, '#000000')
+    options.DefaultNodeTextColor = dot.colorNameToRgb(options.DefaultNodeTextColor, '#000000')
+    options.DefaultEdgeTextColor = dot.colorNameToRgb(options.DefaultEdgeTextColor, '#000000')
+    
+    preferredEncoding = locale.getpreferredencoding()
+    if options.InputEncoding == "":
+        options.InputEncoding = preferredEncoding
+    if options.OutputEncoding == "":
+        options.OutputEncoding = preferredEncoding
+    
+    if options.verbose:
+        print "Input file: %s " % infile
+        print "Output file: %s " % outfile
+        print "Output format: %s" % options.format.lower()
+        print "Input encoding: %s" % options.InputEncoding
+        if options.format.lower() == "graphml":
+            print "Output encoding: utf-8 (fix for Graphml)"
+        else:
+            print "Output encoding: %s" % options.OutputEncoding
+
+    # Collect nodes and edges
+    nodes = {}
+    edges = []
+    default_edge = None
+    default_node = None
+    nid = 1
+    eid = 1
+    f = open(infile, 'r')
+    for l in f.readlines():
+        l = unicode(l, options.InputEncoding)
+        if l.find('->') >= 0:
+            # Process edge
+            e = dot.Edge()
+            e.initFromString(l)
+            e.id = eid
+            eid += 1
+            if default_edge:
+                e.complementAttributes(default_edge)
+            edges.append(e)
+        elif (l.find('[') > 0 and
+              l.find(']') > 0 and
+              l.find(';') > 0):
+            # Process node
+            n = dot.Node()
+            n.initFromString(l)
+            lowlabel = n.label.lower()
+            if (lowlabel != 'graph' and
+                lowlabel != 'edge' and
+                lowlabel != 'node'):
+                n.id = nid
+                nid += 1
+                if default_node:
+                    n.complementAttributes(default_node)
+                nodes[n.label] = n
+            else:
+                if lowlabel == 'edge':
+                    default_edge = n
+                elif lowlabel == 'node':
+                    default_node = n   
+        elif l.find('charset=') >=0:
+            # Pick up input encoding from DOT file
+            li = l.strip().split('=')
+            if len(li) == 2:
+                ienc = li[1].strip('"')
+                if ienc != "":
+                    options.InputEncoding = ienc
+                    if options.verbose:
+                        print "Info: Picked up input encoding '%s' from the DOT file." % ienc
+            
+    f.close()
+    
+    # Add single nodes, if required
+    for e in edges:
+        if not nodes.has_key(e.src):
+            n = dot.Node()
+            n.label = e.src
+            n.id = nid
+            nid += 1
+            nodes[e.src] = n
+        if not nodes.has_key(e.dest):
+            n = dot.Node()
+            n.label = e.dest
+            n.id = nid
+            nid += 1
+            nodes[e.dest] = n
+        nodes[e.src].referenced = True
+        nodes[e.dest].referenced = True
+
+    if options.verbose:
+        print "\nNodes: %d " % len(nodes)
+        print "Edges: %d " % len(edges)
+    
+    if options.sweep:
+        rnodes = {}
+        for key, n in nodes.iteritems():
+            if n.referenced:
+                rnodes[key] = n
+        nodes = rnodes
+        if options.verbose:
+            print "\nNodes after sweep: %d " % len(nodes)
+    
+    # Output
+    o = open(outfile, 'w')
+    format = options.format.lower()
+    if format == 'dot':
+        exportDot(o, nodes, edges, options)
+    elif format == 'graphml':
+        exportGraphml(o, nodes, edges, options)
+    elif format == 'gdf':
+        exportGDF(o, nodes, edges, options)
+    else: # GML
+        exportGML(o, nodes, edges, options)
+    o.close()
+
+    if options.verbose:
+        print "\nDone."
+
+if __name__ == '__main__':
+    main()
+