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.

279 lines
7.9 KiB

  1. /**
  2. * @file datafile_read_write.cpp
  3. */
  4. /*
  5. * This program source code file is part of KiCad, a free EDA CAD application.
  6. *
  7. * Copyright (C) 2012 Jean-Pierre Charras
  8. * Copyright (C) 1992-2012 KiCad Developers, see change_log.txt for contributors.
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU General Public License
  12. * as published by the Free Software Foundation; either version 2
  13. * of the License, or (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, you may find one here:
  22. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  23. * or you may search the http://www.gnu.org website for the version 2 license,
  24. * or you may write to the Free Software Foundation, Inc.,
  25. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  26. */
  27. #include <macros.h>
  28. #include <common.h>
  29. #include <kicad_string.h>
  30. #include <appl_wxstruct.h>
  31. #include <pcb_calculator.h>
  32. #include <pcb_calculator_datafile_lexer.h>
  33. #include <class_regulator_data.h>
  34. #include <datafile_read_write.h>
  35. #include <build_version.h>
  36. using namespace PCBCALC_DATA_T;
  37. static const char* getTokenName( T aTok )
  38. {
  39. return PCB_CALCULATOR_DATAFILE_LEXER::TokenName( aTok );
  40. }
  41. bool PCB_CALCULATOR_FRAME::ReadDataFile()
  42. {
  43. FILE* file = wxFopen( GetDataFilename(), wxT( "rt" ) );
  44. if( file == NULL )
  45. return false;
  46. // Switch the locale to standard C (needed to read/write floating point numbers
  47. LOCALE_IO toggle;
  48. PCB_CALCULATOR_DATAFILE * datafile = new PCB_CALCULATOR_DATAFILE( &m_RegulatorList );
  49. // dataReader dtor will close file
  50. FILE_LINE_READER dataReader( file, GetDataFilename() );
  51. PCB_CALCULATOR_DATAFILE_PARSER datafile_parser( &dataReader );
  52. try
  53. {
  54. datafile_parser.Parse( datafile );
  55. }
  56. catch( IO_ERROR& ioe )
  57. {
  58. delete datafile;
  59. ioe.errorText += '\n';
  60. ioe.errorText += _("Data file error.");
  61. wxMessageBox( ioe.errorText );
  62. return false;
  63. }
  64. delete datafile;
  65. return true;
  66. }
  67. bool PCB_CALCULATOR_FRAME::WriteDataFile()
  68. {
  69. // Switch the locale to standard C (needed to read/write floating point numbers
  70. LOCALE_IO toggle;
  71. std::auto_ptr<PCB_CALCULATOR_DATAFILE> datafile( new PCB_CALCULATOR_DATAFILE( &m_RegulatorList ) );
  72. try
  73. {
  74. FILE_OUTPUTFORMATTER formatter( GetDataFilename() );
  75. int nestlevel = datafile->WriteHeader( &formatter );
  76. datafile->Format( &formatter, nestlevel );
  77. while( nestlevel-- )
  78. formatter.Print( nestlevel, ")\n" );
  79. }
  80. catch( IO_ERROR ioe )
  81. {
  82. return false;
  83. }
  84. m_RegulatorListChanged = false;
  85. return true;
  86. }
  87. PCB_CALCULATOR_DATAFILE::PCB_CALCULATOR_DATAFILE( REGULATOR_LIST * aList )
  88. {
  89. m_list = aList;
  90. }
  91. static const char* regtype_str[] =
  92. {
  93. "normal", "3terminal"
  94. };
  95. int PCB_CALCULATOR_DATAFILE::WriteHeader( OUTPUTFORMATTER* aFormatter ) const throw( IO_ERROR )
  96. {
  97. int nestlevel = 0;
  98. aFormatter->Print( nestlevel++, "(datafile\n");
  99. aFormatter->Print( nestlevel++, "(version 1)\n" );
  100. aFormatter->Print( nestlevel++, "(date %s)\n",
  101. aFormatter->Quotew( DateAndTime() ).c_str() );
  102. aFormatter->Print( nestlevel++, "(tool %s)\n",
  103. aFormatter->Quotew( wxGetApp().GetAppName() +
  104. wxChar(' ') + GetBuildVersion() ).c_str() );
  105. return nestlevel;
  106. }
  107. void PCB_CALCULATOR_DATAFILE::Format( OUTPUTFORMATTER* aFormatter,
  108. int aNestLevel ) const throw( IO_ERROR )
  109. {
  110. // Write regulators list:
  111. aFormatter->Print( aNestLevel++, "(%s\n", getTokenName( T_regulators ) );
  112. for( unsigned ii = 0; ii < m_list->m_List.size(); ii++ )
  113. {
  114. REGULATOR_DATA * item = m_list->m_List[ii];
  115. aFormatter->Print( aNestLevel, "(%s %s\n", getTokenName( T_regulator ),
  116. aFormatter->Quotew(item->m_Name ).c_str() );
  117. aFormatter->Print( aNestLevel+1, "(%s %g)\n", getTokenName( T_reg_vref ),
  118. item->m_Vref );
  119. if( item->m_Iadj != 0 && item->m_Type == 1)
  120. {
  121. aFormatter->Print( aNestLevel+1, "(%s %g)\n", getTokenName( T_reg_iadj ),
  122. item->m_Iadj );
  123. }
  124. aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_reg_type ),
  125. regtype_str[item->m_Type] );
  126. aFormatter->Print( aNestLevel, ")\n" );
  127. }
  128. aFormatter->Print( --aNestLevel, ")\n" );
  129. }
  130. void PCB_CALCULATOR_DATAFILE::Parse( PCB_CALCULATOR_DATAFILE_PARSER* aParser )
  131. throw( IO_ERROR, PARSE_ERROR )
  132. {
  133. aParser->Parse( this );
  134. }
  135. // PCB_CALCULATOR_DATAFILE_PARSER
  136. PCB_CALCULATOR_DATAFILE_PARSER::PCB_CALCULATOR_DATAFILE_PARSER( LINE_READER* aReader ) :
  137. PCB_CALCULATOR_DATAFILE_LEXER( aReader )
  138. {
  139. }
  140. PCB_CALCULATOR_DATAFILE_PARSER::PCB_CALCULATOR_DATAFILE_PARSER( char* aLine, wxString aSource ) :
  141. PCB_CALCULATOR_DATAFILE_LEXER( aLine, aSource )
  142. {
  143. }
  144. void PCB_CALCULATOR_DATAFILE_PARSER::Parse( PCB_CALCULATOR_DATAFILE* aDataList ) throw( IO_ERROR, PARSE_ERROR )
  145. {
  146. T token;
  147. while( ( token = NextTok() ) != T_EOF)
  148. {
  149. if( token == T_LEFT )
  150. {
  151. token = NextTok();
  152. if( token == T_regulators )
  153. {
  154. ParseRegulatorDescr( aDataList );
  155. continue;
  156. }
  157. }
  158. }
  159. }
  160. void PCB_CALCULATOR_DATAFILE_PARSER::ParseRegulatorDescr( PCB_CALCULATOR_DATAFILE* aDataList )
  161. throw( IO_ERROR, PARSE_ERROR )
  162. {
  163. T token;
  164. wxString name;
  165. double vref, iadj;
  166. int type;
  167. while( ( token = NextTok() ) != T_RIGHT )
  168. {
  169. if( token == T_EOF)
  170. Unexpected( T_EOF );
  171. if( token == T_LEFT )
  172. token = NextTok();
  173. if( token == T_regulator )
  174. {
  175. type = 0;
  176. vref = 0.0;
  177. // Read name
  178. token = NextTok();
  179. name = FROM_UTF8( CurText() );
  180. while( ( token = NextTok() ) != T_RIGHT )
  181. {
  182. if( token == T_EOF)
  183. Unexpected( T_EOF );
  184. if( token == T_LEFT )
  185. token = NextTok();
  186. switch( token )
  187. {
  188. case T_reg_vref: // the voltage reference value
  189. token = NextTok();
  190. if( token != T_NUMBER )
  191. Expecting( T_NUMBER );
  192. sscanf( CurText(), "%lf" , &vref);
  193. NeedRIGHT();
  194. break;
  195. case T_reg_iadj: // the Iadj reference value
  196. token = NextTok();
  197. if( token != T_NUMBER )
  198. Expecting( T_NUMBER );
  199. sscanf( CurText(), "%lf" , &iadj);
  200. NeedRIGHT();
  201. break;
  202. case T_reg_type: // type: normal or 3 terminal reg
  203. token = NextTok();
  204. if( stricmp( CurText(), regtype_str[0] ) == 0 )
  205. type = 0;
  206. else if( stricmp( CurText(), regtype_str[1] ) == 0 )
  207. type = 1;
  208. else
  209. Unexpected( CurText() );
  210. NeedRIGHT();
  211. break;
  212. default:
  213. Unexpected( CurText() );
  214. break;
  215. }
  216. }
  217. if( ! name.IsEmpty() )
  218. {
  219. if( type != 1 )
  220. iadj = 0.0;
  221. REGULATOR_DATA * new_item = new REGULATOR_DATA(name, vref, type, iadj );
  222. aDataList->m_list->Add( new_item );
  223. }
  224. }
  225. }
  226. }