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