KiCad PCB EDA Suite
Loading...
Searching...
No Matches
am_param.cpp
Go to the documentation of this file.
1
4
5/*
6 * This program source code file is part of KiCad, a free EDA CAD application.
7 *
8 * Copyright (C) 1992-2017 Jean-Pierre Charras <jp.charras at wanadoo.fr>
9 * Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
10 * Copyright The KiCad Developers, see AUTHORS.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, see <https://www.gnu.org/licenses/>.
24 */
25
26#include <am_param.h>
27#include <am_primitive.h>
28#include <aperture_macro.h>
29#include <macros.h>
30
31extern int ReadInt( char*& text, bool aSkipSeparator = true );
32extern double ReadDouble( char*& text, bool aSkipSeparator = true );
33extern double Evaluate( AM_PARAM_EVAL_STACK& aExp );
34
35/* Class AM_PARAM
36 * holds a parameter value for an "aperture macro" as defined within
37 * standard RS274X. The parameter can be a constant, i.e. "immediate" parameter,
38 * or depend on some defered values, defined in a D_CODE, by the ADD command.
39 * Note the actual value could need an evaluation from an arithmetical expression
40 * items in the expression are stored in .
41 * A simple definition is just a value stored in one item in m_paramStack
42 */
44{
45 m_index = -1;
46}
47
54{
55 bool is_immediate = true;
56 for( unsigned ii = 0; ii < m_paramStack.size(); ii++ )
57 {
58 if( m_paramStack[ii].IsDefered() )
59 { // a defered value is found in operand list,
60 // so the parameter is not immediate
61 is_immediate = false;
62 break;
63 }
64 }
65 return is_immediate;
66}
67
68
69double AM_PARAM::GetValueFromMacro( APERTURE_MACRO* aApertureMacro ) const
70{
71 // In macros, actual values are sometimes given by an expression like:
72 // 0-$2/2-$4
73 // Because arithmetic predence is used, the parameters (values (double) and operators)
74 // are stored in a stack, with all numeric values converted to the actual values
75 // when they are defered parameters
76 // Each item is stored in a AM_PARAM_EVAL (a value or an operator)
77 //
78 // Then the stack with all values resolved is parsed and numeric values
79 // calculated according to the precedence of operators
80 double curr_value = 0.0;
81 parm_item_type op_code;
82
84
85 for( unsigned ii = 0; ii < m_paramStack.size(); ii++ )
86 {
87 AM_PARAM_ITEM item = m_paramStack[ii];
88
89 switch( item.GetType() )
90 {
91 case ADD:
92 case SUB:
93 case MUL:
94 case DIV: // just an operator for next parameter value
95 case OPEN_PAR:
96 case CLOSE_PAR: // Priority modifiers: store in stack
97 op_code = item.GetType();
98 ops.emplace_back( op_code );
99 break;
100
101 case PUSHPARM:
102 // a defered value: get the actual parameter from the aperture macro
103 if( aApertureMacro ) // should be always true here
104 {
105 // Get the actual value
106 curr_value = aApertureMacro->GetLocalParamValue( item.GetIndex() );
107 }
108 else
109 {
110 wxFAIL_MSG( wxT( "AM_PARAM::GetValue(): NULL param aApertureMacro" ) );
111 }
112
113 ops.emplace_back( curr_value );
114 break;
115
116 case PUSHVALUE: // a value is on the stack:
117 curr_value = item.GetValue();
118 ops.emplace_back( curr_value );
119 break;
120
121 default:
122 wxFAIL_MSG( wxString::Format( wxT( "AM_PARAM::GetValue(): unexpected prm type %d" ),
123 item.GetType() ) );
124 break;
125 }
126 }
127
128 double result = Evaluate( ops );
129
130 return result;
131}
132
133
139void AM_PARAM::PushOperator( parm_item_type aType, double aValue )
140{
141 AM_PARAM_ITEM item( aType, aValue);
142 m_paramStack.push_back( item );
143}
144
145void AM_PARAM::PushOperator( parm_item_type aType, int aValue )
146{
147 AM_PARAM_ITEM item( aType, aValue);
148 m_paramStack.push_back( item );
149}
150
165{
166 bool found = false;
167 int ivalue;
168 double dvalue;
169 bool end = false;
170
171 while( !end )
172 {
173 switch( *aText )
174 {
175 case ',':
176 aText++;
177
178 if( !found ) // happens when a string starts by ',' before any param
179 break; // just skip this separator
180
182
183 case '\n':
184 case '\r':
185 case 0: // EOL
186 case '*': // Terminator in a gerber command
187 end = true;
188 break;
189
190 case ' ':
191 aText++;
192 break;
193
194 case '$':
195 // defered value defined later, in ADD command which define defered parameters
196 ++aText;
197 ivalue = ReadInt( aText, false );
198
199 if( m_index < 1 )
200 SetIndex( ivalue );
201
202 PushOperator( PUSHPARM, ivalue );
203 found = true;
204 break;
205
206 case '/':
207 PushOperator( DIV );
208 aText++;
209 break;
210
211 case '(': // Open a block to evaluate an expression between '(' and ')'
213 aText++;
214 break;
215
216 case ')': // close a block between '(' and ')'
218 aText++;
219 break;
220
221 case 'x':
222 case 'X':
223 PushOperator( MUL );
224 aText++;
225 break;
226
227 case '-':
228 case '+':
229 // Test if this is an operator between 2 params, or the sign of a value
230 if( m_paramStack.size() > 0 && !m_paramStack.back().IsOperator() )
231 { // Seems an operator
232 PushOperator( *aText == '+' ? ADD : SUB );
233 aText++;
234 }
235 else
236 { // seems the sign of a value
237 dvalue = ReadDouble( aText, false );
238 PushOperator( PUSHVALUE, dvalue );
239 found = true;
240 }
241 break;
242
243 case '=': // A local definition found like $4=$3/2
244 // At this point, one defered parameter is expected to be read.
245 // this parameter value (the index) is stored in m_index.
246 // The list of items is cleared
247 aText++;
248 m_paramStack.clear();
249 found = false;
250 break;
251
252 default:
253 dvalue = ReadDouble( aText, false );
254 PushOperator( PUSHVALUE, dvalue );
255 found = true;
256 break;
257 }
258 }
259
260 return found;
261}
double Evaluate(AM_PARAM_EVAL_STACK &aExp)
Evaluate an basic arithmetic expression (infix notation) with precedence The expression is a sequence...
Definition evaluate.cpp:98
int ReadInt(char *&text, bool aSkipSeparator=true)
Read an integer from an ASCII character buffer.
double ReadDouble(char *&text, bool aSkipSeparator=true)
Read a double precision floating point number from an ASCII character buffer.
parm_item_type
Definition am_param.h:145
@ OPEN_PAR
Definition am_param.h:146
@ MUL
Definition am_param.h:146
@ SUB
Definition am_param.h:146
@ CLOSE_PAR
Definition am_param.h:146
@ DIV
Definition am_param.h:146
@ PUSHVALUE
Definition am_param.h:146
@ ADD
Definition am_param.h:146
@ PUSHPARM
Definition am_param.h:146
std::vector< AM_PARAM_EVAL > AM_PARAM_EVAL_STACK
Definition am_param.h:206
Hold an operand for an AM_PARAM as defined within standard RS274X.
Definition am_param.h:216
double GetValue() const
Definition am_param.h:237
unsigned GetIndex() const
Definition am_param.h:247
parm_item_type GetType() const
Definition am_param.h:242
bool ReadParamFromAmDef(char *&aText)
Read one aperture macro parameter.
Definition am_param.cpp:164
void SetIndex(int aIndex)
Definition am_param.h:310
void PushOperator(parm_item_type aType, double aValue)
Add an operator/operand to the current stack.
Definition am_param.cpp:139
bool IsImmediate() const
Test if this AM_PARAM holds an immediate parameter or is a pointer into a parameter held by an owning...
Definition am_param.cpp:53
std::vector< AM_PARAM_ITEM > m_paramStack
List of operands/operators to evaluate the actual value if a par def is $3/2, there are 3 items in st...
Definition am_param.h:343
int m_index
has meaning to define parameter local to an aperture macro this is the id of a parameter defined like...
Definition am_param.h:337
double GetValueFromMacro(APERTURE_MACRO *aApertureMacro) const
Definition am_param.cpp:69
Support the "aperture macro" defined within standard RS274X.
double GetLocalParamValue(int aIndex)
This file contains miscellaneous commonly used macros and functions.
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition macros.h:79
VECTOR2I end
wxString result
Test unit parsing edge cases and error handling.