You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

220 lines
5.6 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
  5. * Copyright (C) 2013 KiCad Developers, see CHANGELOG.TXT for contributors.
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * as published by the Free Software Foundation; either version 2
  10. * of the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, you may find one here:
  19. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  20. * or you may search the http://www.gnu.org website for the version 2 license,
  21. * or you may write to the Free Software Foundation, Inc.,
  22. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  23. */
  24. // Something in either <boost/property_tree/ptree.hpp> causes a bunch of compiler
  25. // errors in <wx/msw/winundef.h> version 2.9 on MinGW.
  26. #include <macros.h>
  27. #include <boost/property_tree/ptree.hpp>
  28. #include <assert.h>
  29. #include <ptree.h>
  30. typedef PTREE::const_iterator CITER;
  31. typedef PTREE::iterator ITER;
  32. #if defined(DEBUG)
  33. #define D(x) x
  34. #else
  35. #define D(x)
  36. #endif
  37. #define CTL_OMIT_NL (1<<0)
  38. #define CTL_IN_ATTRS (1<<1)
  39. //-----<Scan>------------------------------------------------------------------
  40. /**
  41. * Function scanList
  42. * reads a sexpr list from the input stream into a new node with key
  43. * aLexer->CurText().
  44. */
  45. inline void scanList( PTREE* aTree, DSNLEXER* aLexer )
  46. {
  47. assert( aLexer->CurTok() == DSN_LEFT );
  48. int tok = aLexer->NextTok();
  49. const char* key = aLexer->CurText();
  50. //D(printf( "%s: '%s'\n", __func__, key );)
  51. PTREE* list = &aTree->push_back( PTREE::value_type( key, PTREE() ) )->second;
  52. if( tok != DSN_RIGHT )
  53. {
  54. while( ( tok = aLexer->NextTok() ) != DSN_RIGHT )
  55. {
  56. if( tok == DSN_EOF )
  57. aLexer->Unexpected( DSN_EOF );
  58. Scan( list, aLexer );
  59. }
  60. }
  61. }
  62. inline void scanAtom( PTREE* aTree, DSNLEXER* aLexer )
  63. {
  64. const char* key = aLexer->CurText();
  65. //D(printf( "%s: '%s'\n", __func__, key );)
  66. aTree->push_back( PTREE::value_type( key, PTREE() ) );
  67. }
  68. void Scan( PTREE* aTree, DSNLEXER* aLexer )
  69. {
  70. int tok = aLexer->CurTok();
  71. // conditionally read first token.
  72. if( tok == DSN_NONE )
  73. tok = aLexer->NextTok();
  74. if( tok == DSN_EOF )
  75. {
  76. aLexer->Unexpected( DSN_EOF );
  77. }
  78. if( tok == DSN_LEFT )
  79. {
  80. scanList( aTree, aLexer );
  81. }
  82. else
  83. {
  84. scanAtom( aTree, aLexer );
  85. }
  86. }
  87. //-----<Format>------------------------------------------------------------------
  88. inline bool isAtom( CPTREE& aTree )
  89. {
  90. return aTree.size()==0 && aTree.data().size()==0;
  91. }
  92. inline bool isLast( CPTREE& aTree, CITER it )
  93. {
  94. CITER next = it;
  95. ++next;
  96. return next == aTree.end();
  97. }
  98. inline CITER next( CITER it )
  99. {
  100. CITER n = it;
  101. return ++n;
  102. }
  103. static void formatNode( OUTPUTFORMATTER* out, int aNestLevel, int aCtl,
  104. const std::string& aKey, CPTREE& aTree );
  105. static void formatList( OUTPUTFORMATTER* out, int aNestLevel, int aCtl, CPTREE& aTree )
  106. {
  107. for( CITER it = aTree.begin(); it != aTree.end(); ++it )
  108. {
  109. // Processing a tree which was read in with xml_parser?
  110. if( it->first == "<xmlattr>" )
  111. {
  112. formatList( out, aNestLevel, aCtl | CTL_IN_ATTRS, it->second );
  113. continue;
  114. }
  115. int ctl = 0;
  116. if( isLast( aTree, it ) ) // is "it" the last one?
  117. {
  118. //if( !( aCtl & CTL_IN_ATTRS ) )
  119. ctl = CTL_OMIT_NL;
  120. }
  121. else if( isAtom( next( it )->second ) )
  122. {
  123. /* if( !( aCtl & CTL_IN_ATTRS ) ) */
  124. ctl = CTL_OMIT_NL;
  125. }
  126. formatNode( out, aNestLevel+1, ctl, it->first, it->second );
  127. }
  128. }
  129. static void formatNode( OUTPUTFORMATTER* out, int aNestLevel, int aCtl,
  130. const std::string& aKey, CPTREE& aTree )
  131. {
  132. if( !isAtom( aTree ) ) // is a list, not an atom
  133. {
  134. int ctl = CTL_OMIT_NL;
  135. // aTree is list and its first child is a list
  136. if( aTree.size() && !isAtom( aTree.begin()->second ) && !aTree.data().size() )
  137. ctl = 0;
  138. out->Print( aNestLevel, "(%s%s", out->Quotes( aKey ).c_str(), ctl & CTL_OMIT_NL ? "" : "\n" );
  139. if( aTree.data().size() ) // sexpr format does not use data()
  140. {
  141. out->Print( 0, " %s%s",
  142. out->Quotes( aTree.data() ).c_str(),
  143. aTree.size() ? "\n" : ""
  144. );
  145. }
  146. formatList( out, aNestLevel, aCtl, aTree );
  147. out->Print( 0, ")%s", aCtl & CTL_OMIT_NL ? "" : "\n" );
  148. }
  149. else // is an atom, not a list
  150. {
  151. out->Print( 0, " %s", out->Quotes( aKey ).c_str() );
  152. }
  153. }
  154. void Format( OUTPUTFORMATTER* out, int aNestLevel, int aCtl, CPTREE& aTree )
  155. {
  156. if( aTree.size() == 1 && !aTree.data().size() )
  157. {
  158. // The topmost node is basically only a container for the document root.
  159. // It anchors the paths which traverse the tree deeper.
  160. CITER it = aTree.begin();
  161. formatNode( out, aNestLevel, aCtl, it->first, it->second );
  162. }
  163. else
  164. {
  165. // This is not expected, neither for sexpr nor xml.
  166. formatNode( out, aNestLevel, aCtl, "", aTree );
  167. }
  168. }