KiCad PCB EDA Suite
class_am_param.cpp
Go to the documentation of this file.
1 
5 /*
6  * This program source code file is part of KiCad, a free EDA CAD application.
7  *
8  * Copyright (C) 1992-2010 Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>
9  * Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
10  * Copyright (C) 1992-2010 KiCad Developers, see change_log.txt for contributors.
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, you may find one here:
24  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
25  * or you may search the http://www.gnu.org website for the version 2 license,
26  * or you may write to the Free Software Foundation, Inc.,
27  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
28  */
29 
30 #include <class_am_param.h>
31 #include <class_aperture_macro.h>
32 
33 extern int ReadInt( char*& text, bool aSkipSeparator = true );
34 extern double ReadDouble( char*& text, bool aSkipSeparator = true );
35 
36 /* Class AM_PARAM
37  * holds a parameter value for an "aperture macro" as defined within
38  * standard RS274X. The parameter can be a constant, i.e. "immediate" parameter,
39  * or depend on some defered values, defined in a D_CODE, by the ADD command.
40  * Note the actual value could need an evaluation from an arithmetical expression
41  * items in the expression are stored in .
42  * A simple definition is just a value stored in one item in m_paramStack
43  */
45 {
46  m_index = -1;
47 }
48 
55 {
56  bool isimmediate = true;
57  for( unsigned ii = 0; ii < m_paramStack.size(); ii++ )
58  {
59  if( m_paramStack[ii].IsDefered() )
60  { // a defered value is found in operand list,
61  // so the parameter is not immediate
62  isimmediate = false;
63  break;
64  }
65  }
66  return isimmediate;
67 }
68 
69 double AM_PARAM::GetValue( const D_CODE* aDcode ) const
70 {
71  double paramvalue = 0.0;
72  double curr_value = 0.0;
73  parm_item_type state = POPVALUE;
74 
75  for( unsigned ii = 0; ii < m_paramStack.size(); ii++ )
76  {
77  AM_PARAM_ITEM item = m_paramStack[ii];
78  switch( item.GetType() )
79  {
80  case ADD:
81  case SUB:
82  case MUL:
83  case DIV: // just an operator for next parameter value: store it
84  state = item.GetType();
85  break;
86 
87  case PUSHPARM:
88  // get the parameter from the aDcode
89  if( aDcode ) // should be always true here
90  {
91  if( item.GetIndex() <= aDcode->GetParamCount() )
92  curr_value = aDcode->GetParam( item.GetIndex() );
93  else // Get parameter from local param definition
94  {
95  const APERTURE_MACRO * am_parent = aDcode->GetMacro();
96  curr_value = am_parent->GetLocalParam( aDcode, item.GetIndex() );
97  }
98  }
99  else
100  {
101  wxLogDebug( wxT( "AM_PARAM::GetValue(): NULL param aDcode\n" ) );
102  }
103  // Fall through
104  case PUSHVALUE: // a value is on the stack:
105  if( item.GetType() == PUSHVALUE )
106  curr_value = item.GetValue();
107  switch( state )
108  {
109  case POPVALUE:
110  paramvalue = curr_value;
111  break;
112 
113  case ADD:
114  paramvalue += curr_value;
115  break;
116 
117  case SUB:
118  paramvalue -= curr_value;
119  break;
120 
121  case MUL:
122  paramvalue *= curr_value;
123  break;
124 
125  case DIV:
126  paramvalue /= curr_value;
127  break;
128 
129  default:
130  wxLogDebug( wxT( "AM_PARAM::GetValue() : unexpected operator\n" ) );
131  break;
132  }
133  break;
134 
135  default:
136  wxLogDebug( wxT( "AM_PARAM::GetValue(): unexpected type\n" ) );
137  break;
138  }
139  }
140  return paramvalue;
141 }
142 
148 void AM_PARAM::PushOperator( parm_item_type aType, double aValue )
149 {
150  AM_PARAM_ITEM item( aType, aValue);
151  m_paramStack.push_back( item );
152 }
153 
154 void AM_PARAM::PushOperator( parm_item_type aType, int aValue )
155 {
156  AM_PARAM_ITEM item( aType, aValue);
157  m_paramStack.push_back( item );
158 }
159 
173 bool AM_PARAM::ReadParam( char*& aText )
174 {
175  bool found = false;
176  int ivalue;
177  double dvalue;
178  bool end = false;
179 
180  while( !end )
181  {
182  switch( *aText )
183  {
184  case ',':
185  aText++;
186  // fall through
187  case 0: // EOL
188  case '*': // Terminator in a gerber command
189  end = true;
190  break;
191 
192  case ' ':
193  aText++;
194  break;
195 
196  case '$':
197  // defered value defined later, in ADD command which define defered parameters
198  ++aText;
199  ivalue = ReadInt( aText, false );
200  if( m_index < 1 )
201  SetIndex( ivalue );
202  PushOperator( PUSHPARM, ivalue );
203  found = true;
204  break;
205 
206  case '/':
207  PushOperator( DIV );
208  aText++;
209  break;
210 
211  case 'x':
212  case 'X':
213  PushOperator( MUL );
214  aText++;
215  break;
216 
217  case '-':
218  case '+':
219  // Test if this is an operator between 2 params, or the sign of a value
220  if( m_paramStack.size() > 0 && !m_paramStack.back().IsOperator() )
221  { // Seems an operator
222  PushOperator( *aText == '+' ? ADD : SUB );
223  aText++;
224  }
225  else
226  { // seems the sign of a value
227  dvalue = ReadDouble( aText, false );
228  PushOperator( PUSHVALUE, dvalue );
229  found = true;
230  }
231  break;
232 
233  case '=': // A local definition found like $4=$3/2
234  // At this point, one defered parameter is expected to be read.
235  // this parameter value (the index) is stored in m_index.
236  // The list of items is cleared
237  aText++;
238  m_paramStack.clear();
239  found = false;
240  break;
241 
242  default:
243  dvalue = ReadDouble( aText, false );
244  PushOperator( PUSHVALUE, dvalue );
245  found = true;
246  break;
247  }
248  }
249 
250  return found;
251 }
std::vector< AM_PARAM_ITEM > m_paramStack
double ReadDouble(char *&text, bool aSkipSeparator=true)
Function ReadDouble reads a double from an ASCII character buffer.
double GetParam(unsigned aIdx) const
GetParam() Returns a parameter stored in parameter list.
Definition: dcode.h:142
unsigned GetIndex() const
Class AM_PARAM holds an operand for an AM_PARAM as defined within standard RS274X.
bool ReadParam(char *&aText)
Function ReadParam Read one aperture macro parameter a parameter can be: a number a reference to an a...
void PushOperator(parm_item_type aType, double aValue)
function PushOperator add an operator/operand to the current stack
parm_item_type GetType() const
double GetValue(const D_CODE *aDcode) const
unsigned GetParamCount() const
GetParamCount() Returns the number of parameters stored in parameter list.
Definition: dcode.h:132
bool IsImmediate() const
Function IsImmediate tests if this AM_PARAM holds an immediate parameter or is a pointer into a param...
double GetLocalParam(const D_CODE *aDcode, unsigned aParamId) const
function GetLocalParam Usually, parameters are defined inside the aperture primitive using immediate ...
int ReadInt(char *&text, bool aSkipSeparator=true)
Function ReadInt reads an int from an ASCII character buffer.
Class D_CODE holds a gerber DCODE (also called Aperture) definition.
Definition: dcode.h:81
parm_item_type
double GetValue() const
APERTURE_MACRO * GetMacro() const
Definition: dcode.h:158
void SetIndex(int aIndex)
Struct APERTURE_MACRO helps support the "aperture macro" defined within standard RS274X.