KiCad PCB EDA Suite
pcb_parser_tool.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2019 KiCad Developers, see CHANGELOG.TXT for contributors.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you may find one here:
18  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19  * or you may search the http://www.gnu.org website for the version 2 license,
20  * or you may write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
25 
26 #include <cstdio>
27 #include <string>
28 
29 #include <common.h>
30 #include <profile.h>
31 
32 #include <wx/cmdline.h>
33 
34 #include <class_board_item.h>
35 #include <kicad_plugin.h>
36 #include <pcb_parser.h>
37 #include <richio.h>
38 
39 #include <wx/cmdline.h>
40 
43 
44 
45 using PARSE_DURATION = std::chrono::microseconds;
46 
47 
54 bool parse( std::istream& aStream, bool aVerbose )
55 {
56  // Take input from stdin
58  reader.SetStream( aStream );
59 
60  PCB_PARSER parser;
61 
62  parser.SetLineReader( &reader );
63 
64  BOARD_ITEM* board = nullptr;
65 
66  PARSE_DURATION duration{};
67 
68  try
69  {
70  PROF_COUNTER timer;
71  board = parser.Parse();
72 
73  duration = timer.SinceStart<PARSE_DURATION>();
74  }
75  catch( const IO_ERROR& parse_error )
76  {
77  std::cerr << parse_error.Problem() << std::endl;
78  std::cerr << parse_error.Where() << std::endl;
79  }
80 
81  if( aVerbose )
82  {
83  std::cout << "Took: " << duration.count() << "us" << std::endl;
84  }
85 
86  return board != nullptr;
87 }
88 
89 
90 static const wxCmdLineEntryDesc g_cmdLineDesc[] = {
91  { wxCMD_LINE_SWITCH, "h", "help", _( "displays help on the command line parameters" ).mb_str(),
92  wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP },
93  { wxCMD_LINE_SWITCH, "v", "verbose", _( "print parsing information" ).mb_str() },
94  { wxCMD_LINE_PARAM, nullptr, nullptr, _( "input file" ).mb_str(), wxCMD_LINE_VAL_STRING,
95  wxCMD_LINE_PARAM_OPTIONAL | wxCMD_LINE_PARAM_MULTIPLE },
96  { wxCMD_LINE_NONE }
97 };
98 
99 
101 {
103 };
104 
105 
106 int pcb_parser_main_func( int argc, char** argv )
107 {
108 #ifdef __AFL_COMPILER
109  __AFL_INIT();
110 #endif
111 
112  wxMessageOutput::Set( new wxMessageOutputStderr );
113  wxCmdLineParser cl_parser( argc, argv );
114  cl_parser.SetDesc( g_cmdLineDesc );
115  cl_parser.AddUsageText(
116  _( "This program parses PCB files, either from the "
117  "stdin stream or from the given filenames. This can be used either for "
118  "standalone testing of the parser or for fuzz testing." ) );
119 
120  int cmd_parsed_ok = cl_parser.Parse();
121  if( cmd_parsed_ok != 0 )
122  {
123  // Help and invalid input both stop here
124  return ( cmd_parsed_ok == -1 ) ? KI_TEST::RET_CODES::OK : KI_TEST::RET_CODES::BAD_CMDLINE;
125  }
126 
127  const bool verbose = cl_parser.Found( "verbose" );
128 
129  bool ok = true;
130 
131  const auto file_count = cl_parser.GetParamCount();
132 
133  if( file_count == 0 )
134  {
135  // Parse the file provided on stdin - used by AFL to drive the
136  // program
137  // while (__AFL_LOOP(2))
138  {
139  ok = parse( std::cin, verbose );
140  }
141  }
142  else
143  {
144  // Parse 'n' files given on the command line
145  // (this is useful for input minimisation (e.g. afl-tmin) as
146  // well as manual testing
147  for( unsigned i = 0; i < file_count; i++ )
148  {
149  const auto filename = cl_parser.GetParam( i ).ToStdString();
150 
151  if( verbose )
152  std::cout << "Parsing: " << filename << std::endl;
153 
154  std::ifstream fin;
155  fin.open( filename );
156 
157  ok = ok && parse( fin, verbose );
158  }
159  }
160 
161  if( !ok )
163 
164  return KI_TEST::RET_CODES::OK;
165 }
166 
167 
169  { "pcb_parser", "Parse a KiCad PCB file", pcb_parser_main_func } );
Tools can define their own statuses from here onwards.
BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
PCB_PARSER reads a Pcbnew s-expression formatted LINE_READER object and returns the appropriate BOARD...
Definition: pcb_parser.h:69
Classes BOARD_ITEM and BOARD_CONNECTED_ITEM.
#define OK
bool parse(std::istream &aStream, bool aVerbose)
Parse a PCB or footprint file from the given input stream.
The command line was not correct for the tool.
static bool registered
The class PROF_COUNTER is a small class to help profiling.
Definition: profile.h:44
virtual const wxString Problem() const
what was the problem?
Definition: exceptions.cpp:45
virtual const wxString Where() const
where did the Problem() occur?
Definition: exceptions.cpp:39
void SetStream(std::istream &aStream)
Set the stream for this line reader.
static bool Register(const KI_TEST::UTILITY_PROGRAM &aProgInfo)
Register a utility program factory function against an ID string.
LINE_READER that wraps a given std::istream instance.
BOARD_ITEM * Parse()
Definition: pcb_parser.cpp:481
static const wxCmdLineEntryDesc g_cmdLineDesc[]
std::chrono::microseconds PARSE_DURATION
LINE_READER * SetLineReader(LINE_READER *aReader)
Function SetLineReader sets aLineReader into the parser, and returns the previous one,...
Definition: pcb_parser.h:337
int pcb_parser_main_func(int argc, char **argv)
#define _(s)
Definition: 3d_actions.cpp:33
The common library.
DURATION SinceStart(bool aSinceLast=false)
Definition: profile.h:129
Pcbnew s-expression file format parser definition.
Struct IO_ERROR is a class used to hold an error message and may be used when throwing exceptions con...
Definition: ki_exception.h:76
PARSER_RET_CODES
Definition: sexpr_parse.cpp:99