KiCad PCB EDA Suite
specctra.cpp
Go to the documentation of this file.
1 
2 /*
3  * This program source code file is part of KiCad, a free EDA CAD application.
4  *
5  * Copyright (C) 2007-2011 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
6  * Copyright (C) 2007-2020 KiCad Developers, see change_log.txt for contributors.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
26 
27 /* This source file implements export and import capabilities to the
28  specctra dsn file format. The grammar for that file format is documented
29  fairly well. There are classes for each major type of descriptor in the
30  spec.
31 
32  Since there are so many classes in here, it may be helpful to generate
33  the Doxygen directory:
34 
35  $ cd <kicadSourceRoot>
36  $ doxygen
37 
38  Then you can view the html documentation in the <kicadSourceRoot>/doxygen
39  directory. The main class in this file is SPECCTRA_DB and its main
40  functions are LoadPCB(), LoadSESSION(), and ExportPCB().
41 
42  Wide use is made of boost::ptr_vector<> and std::vector<> template classes.
43  If the contained object is small, then std::vector tends to be used.
44  If the contained object is large, variable size, or would require writing
45  an assignment operator() or copy constructor, then boost::ptr_vector
46  cannot be beat.
47 */
48 
49 
50 #include <cstdarg>
51 #include <cstdio>
52 
53 #include <build_version.h>
54 
55 #include <board.h>
56 #include <track.h>
57 
58 #include "specctra.h"
59 #include <macros.h>
60 
61 
62 namespace DSN {
63 
64 #define NESTWIDTH 2
65 
66 //-----<SPECCTRA_DB>-------------------------------------------------
67 
68 
69 const char* GetTokenText( T aTok )
70 {
71  return SPECCTRA_LEXER::TokenName( aTok );
72 }
73 
75 {
76  // specctra wants top physical layer first, then going down to the
77  // bottom most physical layer in physical sequence.
78  // Same as KiCad now except for B_Cu
79  unsigned layerCount = aBoard->GetCopperLayerCount();
80 
81  m_layerIds.clear();
82  m_pcbLayer2kicad.resize( layerCount );
83  m_kicadLayer2pcb.resize( B_Cu + 1 );
84 
85 #if 0 // was:
86  for( LAYER_NUM kiNdx = layerCount - 1, pcbNdx=FIRST_LAYER;
87  kiNdx >= 0; --kiNdx, ++pcbNdx )
88  {
89  LAYER_NUM kilayer = (kiNdx>0 && kiNdx==layerCount-1) ? F_Cu : kiNdx;
90 
91  // establish bi-directional mapping between KiCad's BOARD layer and PCB layer
92  pcbLayer2kicad[pcbNdx] = kilayer;
93  kicadLayer2pcb[kilayer] = pcbNdx;
94 
95  // save the specctra layer name in SPECCTRA_DB::layerIds for later.
96  layerIds.push_back( TO_UTF8( aBoard->GetLayerName( ToLAYER_ID( kilayer ) ) ) );
97  }
98 #else
99 
100  // establish bi-directional mapping between KiCad's BOARD layer and PCB layer
101 
102  for( unsigned i = 0; i < m_kicadLayer2pcb.size(); ++i )
103  {
104  if( i < layerCount-1 )
105  m_kicadLayer2pcb[i] = i;
106  else
107  m_kicadLayer2pcb[i] = layerCount - 1;
108  }
109 
110  for( unsigned i = 0; i < m_pcbLayer2kicad.size(); ++i )
111  {
112  PCB_LAYER_ID id = ( i < layerCount-1 ) ? ToLAYER_ID( i ) : B_Cu;
113 
114  m_pcbLayer2kicad[i] = id;
115 
116  // save the specctra layer name in SPECCTRA_DB::layerIds for later.
117  m_layerIds.push_back(TO_UTF8( aBoard->GetLayerName( id ) ) );
118  }
119 
120 #endif
121 }
122 
123 
124 int SPECCTRA_DB::findLayerName( const std::string& aLayerName ) const
125 {
126  for( int i=0; i < int( m_layerIds.size()); ++i )
127  {
128  if( 0 == aLayerName.compare( m_layerIds[i] ) )
129  return i;
130  }
131  return -1;
132 }
133 
134 void SPECCTRA_DB::readCOMPnPIN( std::string* component_id, std::string* pin_id )
135 {
136  T tok;
137 
138  static const char pin_def[] = "<pin_reference>::=<component_id>-<pin_id>";
139 
140  if( !IsSymbol( (T) CurTok() ) )
141  Expecting( pin_def );
142 
143  // case for: A12-14, i.e. no wrapping quotes. This should be a single
144  // token, so split it.
145  if( CurTok() != T_STRING )
146  {
147  const char* toktext = CurText();
148  const char* dash = strchr( toktext, '-' );
149 
150  if( !dash )
151  Expecting( pin_def );
152 
153  while( toktext != dash )
154  *component_id += *toktext++;
155 
156  ++toktext; // skip the dash
157 
158  while( *toktext )
159  *pin_id += *toktext++;
160  }
161 
162  // quoted string: "U12"-"14" or "U12"-14, 3 tokens in either case
163  else
164  {
165  *component_id = CurText();
166 
167  tok = NextTok();
168  if( tok!=T_DASH )
169  Expecting( pin_def );
170 
171  NextTok(); // accept anything after the dash.
172  *pin_id = CurText();
173  }
174 }
175 
176 
177 void SPECCTRA_DB::readTIME( time_t* time_stamp )
178 {
179  T tok;
180 
181  struct tm mytime;
182 
183  static const char time_toks[] = "<month> <day> <hour> : <minute> : <second> <year>";
184 
185  static const char* months[] = { // index 0 = Jan
186  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
187  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL
188  };
189 
190  NeedSYMBOL(); // month
191 
192  const char* ptok = CurText();
193 
194  mytime.tm_mon = 0; // remains if we don't find a month match.
195  for( int m=0; months[m]; ++m )
196  {
197  if( !strcasecmp( months[m], ptok ) )
198  {
199  mytime.tm_mon = m;
200  break;
201  }
202  }
203 
204  tok = NextTok(); // day
205  if( tok != T_NUMBER )
206  Expecting( time_toks );
207  mytime.tm_mday = atoi( CurText() );
208 
209  tok = NextTok(); // hour
210  if( tok != T_NUMBER )
211  Expecting( time_toks );
212  mytime.tm_hour = atoi( CurText() );
213 
214  // : colon
215  NeedSYMBOL();
216  if( *CurText() != ':' || strlen( CurText() )!=1 )
217  Expecting( time_toks );
218 
219  tok = NextTok(); // minute
220  if( tok != T_NUMBER )
221  Expecting( time_toks );
222  mytime.tm_min = atoi( CurText() );
223 
224  // : colon
225  NeedSYMBOL();
226  if( *CurText() != ':' || strlen( CurText() )!=1 )
227  Expecting( time_toks );
228 
229  tok = NextTok(); // second
230  if( tok != T_NUMBER )
231  Expecting( time_toks );
232  mytime.tm_sec = atoi( CurText() );
233 
234  tok = NextTok(); // year
235  if( tok != T_NUMBER )
236  Expecting( time_toks );
237  mytime.tm_year = atoi( CurText() ) - 1900;
238 
239  *time_stamp = mktime( &mytime );
240 }
241 
242 
243 void SPECCTRA_DB::LoadPCB( const wxString& aFilename )
244 {
245  FILE_LINE_READER curr_reader( aFilename );
246 
247  PushReader( &curr_reader );
248 
249  if( NextTok() != T_LEFT )
250  Expecting( T_LEFT );
251 
252  if( NextTok() != T_pcb )
253  Expecting( T_pcb );
254 
255  SetPCB( new PCB() );
256 
257  doPCB( m_pcb );
258  PopReader();
259 }
260 
261 
262 void SPECCTRA_DB::LoadSESSION( const wxString& aFilename )
263 {
264  FILE_LINE_READER curr_reader( aFilename );
265 
266  PushReader( &curr_reader );
267 
268  if( NextTok() != T_LEFT )
269  Expecting( T_LEFT );
270 
271  if( NextTok() != T_session )
272  Expecting( T_session );
273 
274  SetSESSION( new SESSION() );
275 
276  doSESSION( m_session );
277 
278  PopReader();
279 }
280 
281 
282 void SPECCTRA_DB::doPCB( PCB* growth )
283 {
284  T tok;
285 
286  /* <design_descriptor >::=
287  (pcb <pcb_id >
288  [<parser_descriptor> ]
289  [<capacitance_resolution_descriptor> ]
290  [<conductance_resolution_descriptor> ]
291  [<current_resolution_descriptor> ]
292  [<inductance_resolution_descriptor> ]
293  [<resistance_resolution_descriptor> ]
294  [<resolution_descriptor> ]
295  [<time_resolution_descriptor> ]
296  [<voltage_resolution_descriptor> ]
297  [<unit_descriptor> ]
298  [<structure_descriptor> | <file_descriptor> ]
299  [<placement_descriptor> | <file_descriptor> ]
300  [<library_descriptor> | <file_descriptor> ]
301  [<floor_plan_descriptor> | <file_descriptor> ]
302  [<part_library_descriptor> | <file_descriptor> ]
303  [<network_descriptor> | <file_descriptor> ]
304  [<wiring_descriptor> ]
305  [<color_descriptor> ]
306  )
307  */
308 
309  NeedSYMBOL();
310  growth->pcbname = CurText();
311 
312  while( (tok = NextTok()) != T_RIGHT )
313  {
314  if( tok != T_LEFT )
315  Expecting( T_LEFT );
316 
317  tok = NextTok();
318  switch( tok )
319  {
320  case T_parser:
321  if( growth->parser )
322  Unexpected( tok );
323  growth->parser = new PARSER( growth );
324  doPARSER( growth->parser );
325  break;
326 
327  case T_unit:
328  if( growth->unit )
329  Unexpected( tok );
330  growth->unit = new UNIT_RES( growth, tok );
331  doUNIT( growth->unit );
332  break;
333 
334  case T_resolution:
335  if( growth->resolution )
336  Unexpected( tok );
337  growth->resolution = new UNIT_RES( growth, tok );
338  doRESOLUTION( growth->resolution );
339  break;
340 
341  case T_structure:
342  if( growth->structure )
343  Unexpected( tok );
344  growth->structure = new STRUCTURE( growth );
345  doSTRUCTURE( growth->structure );
346  break;
347 
348  case T_placement:
349  if( growth->placement )
350  Unexpected( tok );
351  growth->placement = new PLACEMENT( growth );
352  doPLACEMENT( growth->placement );
353  break;
354 
355  case T_library:
356  if( growth->library )
357  Unexpected( tok );
358  growth->library = new LIBRARY( growth );
359  doLIBRARY( growth->library );
360  break;
361 
362  case T_network:
363  if( growth->network )
364  Unexpected( tok );
365  growth->network = new NETWORK( growth );
366  doNETWORK( growth->network );
367  break;
368 
369  case T_wiring:
370  if( growth->wiring )
371  Unexpected( tok );
372  growth->wiring = new WIRING( growth );
373  doWIRING( growth->wiring );
374  break;
375 
376  default:
377  Unexpected( CurText() );
378  }
379  }
380 
381  tok = NextTok();
382  if( tok != T_EOF )
383  Expecting( T_EOF );
384 }
385 
386 
388 {
389  T tok;
390  std::string const1;
391  std::string const2;
392 
393  /* <parser_descriptor >::=
394  (parser
395  [(string_quote <quote_char >)]
396  (space_in_quoted_tokens [on | off])
397  [(host_cad <id >)]
398  [(host_version <id >)]
399  [{(constant <id > <id >)}]
400  [(write_resolution] {<character> <positive_integer >})]
401  [(routes_include {[testpoint | guides |
402  image_conductor]})]
403  [(wires_include testpoint)]
404  [(case_sensitive [on | off])]
405  [(via_rotate_first [on | off])]
406  )
407  */
408 
409  while( (tok = NextTok()) != T_RIGHT )
410  {
411  if( tok != T_LEFT )
412  Expecting( T_LEFT );
413 
414  tok = NextTok();
415  switch( tok )
416  {
417  case T_STRING_QUOTE:
418  tok = NextTok();
419  if( tok != T_QUOTE_DEF )
420  Expecting( T_QUOTE_DEF );
421  SetStringDelimiter( (unsigned char) *CurText() );
422  growth->string_quote = *CurText();
423  m_quote_char = CurText();
424  NeedRIGHT();
425  break;
426 
427  case T_space_in_quoted_tokens:
428  tok = NextTok();
429  if( tok!=T_on && tok!=T_off )
430  Expecting( "on|off" );
431  SetSpaceInQuotedTokens( tok==T_on );
432  growth->space_in_quoted_tokens = (tok==T_on);
433  NeedRIGHT();
434  break;
435 
436  case T_host_cad:
437  NeedSYMBOL();
438  growth->host_cad = CurText();
439  NeedRIGHT();
440  break;
441 
442  case T_host_version:
443  NeedSYMBOLorNUMBER();
444  growth->host_version = CurText();
445  NeedRIGHT();
446  break;
447 
448  case T_constant:
449  NeedSYMBOLorNUMBER();
450  const1 = CurText();
451  NeedSYMBOLorNUMBER();
452  const2 = CurText();
453  NeedRIGHT();
454  growth->constants.push_back( const1 );
455  growth->constants.push_back( const2 );
456  break;
457 
458  case T_write_resolution: // [(writee_resolution {<character> <positive_integer >})]
459  while( (tok = NextTok()) != T_RIGHT )
460  {
461  if( tok!=T_SYMBOL )
462  Expecting( T_SYMBOL );
463  tok = NextTok();
464  if( tok!=T_NUMBER )
465  Expecting( T_NUMBER );
466  // @todo
467  }
468  break;
469 
470  case T_routes_include: // [(routes_include {[testpoint | guides | image_conductor]})]
471  while( (tok = NextTok()) != T_RIGHT )
472  {
473  switch( tok )
474  {
475  case T_testpoint:
476  growth->routes_include_testpoint = true;
477  break;
478  case T_guide:
479  growth->routes_include_guides = true;
480  break;
481  case T_image_conductor:
482  growth->routes_include_image_conductor = true;
483  break;
484  default:
485  Expecting( "testpoint|guides|image_conductor" );
486  }
487  }
488  break;
489 
490  case T_wires_include: // [(wires_include testpoint)]
491  tok = NextTok();
492  if( tok != T_testpoint )
493  Expecting( T_testpoint );
494  growth->routes_include_testpoint = true;
495  NeedRIGHT();
496  break;
497 
498  case T_case_sensitive:
499  tok = NextTok();
500  if( tok!=T_on && tok!=T_off )
501  Expecting( "on|off" );
502  growth->case_sensitive = (tok==T_on);
503  NeedRIGHT();
504  break;
505 
506  case T_via_rotate_first: // [(via_rotate_first [on | off])]
507  tok = NextTok();
508  if( tok!=T_on && tok!=T_off )
509  Expecting( "on|off" );
510  growth->via_rotate_first = (tok==T_on);
511  NeedRIGHT();
512  break;
513 
514  case T_generated_by_freeroute:
515  growth->generated_by_freeroute = true;
516  NeedRIGHT();
517  break;
518 
519  default:
520  Unexpected( CurText() );
521  }
522  }
523 }
524 
525 
527 {
528  T tok = NextTok();
529 
530  switch( tok )
531  {
532  case T_inch:
533  case T_mil:
534  case T_cm:
535  case T_mm:
536  case T_um:
537  growth->units = tok;
538  break;
539  default:
540  Expecting( "inch|mil|cm|mm|um" );
541  }
542 
543  tok = NextTok();
544  if( tok != T_NUMBER )
545  Expecting( T_NUMBER );
546 
547  growth->value = atoi( CurText() );
548 
549  NeedRIGHT();
550 }
551 
552 
554 {
555  T tok = NextTok();
556 
557  switch( tok )
558  {
559  case T_inch:
560  case T_mil:
561  case T_cm:
562  case T_mm:
563  case T_um:
564  growth->units = tok;
565  break;
566  default:
567  Expecting( "inch|mil|cm|mm|um" );
568  }
569 
570  NeedRIGHT();
571 }
572 
573 
575 {
576  NeedSYMBOL();
577  growth->layer_id0 = CurText();
578 
579  NeedSYMBOL();
580  growth->layer_id1 = CurText();
581 
582  if( NextTok() != T_NUMBER )
583  Expecting( T_NUMBER );
584  growth->layer_weight = strtod( CurText(), 0 );
585 
586  NeedRIGHT();
587 }
588 
589 
591 
592 {
593  T tok;
594 
595  while( (tok = NextTok()) != T_RIGHT )
596  {
597  if( tok != T_LEFT )
598  Expecting( T_LEFT );
599 
600  if( NextTok() != T_layer_pair )
601  Expecting( T_layer_pair );
602 
603  SPECCTRA_LAYER_PAIR* layer_pair = new SPECCTRA_LAYER_PAIR( growth );
604  growth->layer_pairs.push_back( layer_pair );
605  doSPECCTRA_LAYER_PAIR( layer_pair );
606  }
607 }
608 
609 
611 {
612  T tok;
613 
614  while( (tok = NextTok()) != T_RIGHT )
615  {
616  if( tok != T_LEFT )
617  Expecting( T_LEFT );
618 
619  tok = NextTok();
620  switch( tok )
621  {
622  case T_unit:
623  if( growth->unit )
624  Unexpected( tok );
625  growth->unit = new UNIT_RES( growth, tok );
626  doUNIT( growth->unit );
627  break;
628 
629  case T_resolution:
630  if( growth->unit )
631  Unexpected( tok );
632  growth->unit = new UNIT_RES( growth, tok );
633  doRESOLUTION( growth->unit );
634  break;
635 
636  case T_layer_noise_weight:
637  if( growth->layer_noise_weight )
638  Unexpected( tok );
639  growth->layer_noise_weight = new LAYER_NOISE_WEIGHT( growth );
641  break;
642 
643  case T_place_boundary:
644 L_place:
645  if( growth->place_boundary )
646  Unexpected( tok );
647  growth->place_boundary = new BOUNDARY( growth, T_place_boundary );
648  doBOUNDARY( growth->place_boundary );
649  break;
650 
651  case T_boundary:
652  if( growth->boundary )
653  {
654  if( growth->place_boundary )
655  Unexpected( tok );
656  goto L_place;
657  }
658  growth->boundary = new BOUNDARY( growth );
659  doBOUNDARY( growth->boundary );
660  break;
661 
662  case T_plane:
663  COPPER_PLANE* plane;
664  plane = new COPPER_PLANE( growth );
665  growth->planes.push_back( plane );
666  doKEEPOUT( plane );
667  break;
668 
669  case T_region:
670  REGION* region;
671  region = new REGION( growth );
672  growth->regions.push_back( region );
673  doREGION( region );
674  break;
675 
676  case T_snap_angle:
677  STRINGPROP* stringprop;
678  stringprop = new STRINGPROP( growth, T_snap_angle );
679  growth->Append( stringprop );
680  doSTRINGPROP( stringprop );
681  break;
682 
683  case T_via:
684  if( growth->via )
685  Unexpected( tok );
686  growth->via = new VIA( growth );
687  doVIA( growth->via );
688  break;
689 
690  case T_control:
691  if( growth->control )
692  Unexpected( tok );
693  growth->control = new CONTROL( growth );
694  doCONTROL( growth->control );
695  break;
696 
697  case T_layer:
698  LAYER* layer;
699  layer = new LAYER( growth );
700  growth->layers.push_back( layer );
701  doLAYER( layer );
702  break;
703 
704  case T_rule:
705  if( growth->rules )
706  Unexpected( tok );
707  growth->rules = new RULE( growth, T_rule );
708  doRULE( growth->rules );
709  break;
710 
711  case T_place_rule:
712  if( growth->place_rules )
713  Unexpected( tok );
714  growth->place_rules = new RULE( growth, T_place_rule );
715  doRULE( growth->place_rules );
716  break;
717 
718  case T_keepout:
719  case T_place_keepout:
720  case T_via_keepout:
721  case T_wire_keepout:
722  case T_bend_keepout:
723  case T_elongate_keepout:
724  KEEPOUT* keepout;
725  keepout = new KEEPOUT( growth, tok );
726  growth->keepouts.push_back( keepout );
727  doKEEPOUT( keepout );
728  break;
729 
730  case T_grid:
731  GRID* grid;
732  grid = new GRID( growth );
733  growth->grids.push_back( grid );
734  doGRID( grid );
735  break;
736 
737  default:
738  Unexpected( CurText() );
739  }
740  }
741 }
742 
743 
745 {
746  /*
747  <structure_out_descriptor >::=
748  (structure_out
749  {<layer_descriptor> }
750  [<rule_descriptor> ]
751  )
752  */
753 
754  T tok = NextTok();
755 
756  while( tok != T_RIGHT )
757  {
758  if( tok != T_LEFT )
759  Expecting( T_LEFT );
760 
761  tok = NextTok();
762  switch( tok )
763  {
764  case T_layer:
765  LAYER* layer;
766  layer = new LAYER( growth );
767  growth->layers.push_back( layer );
768  doLAYER( layer );
769  break;
770 
771  case T_rule:
772  if( growth->rules )
773  Unexpected( tok );
774  growth->rules = new RULE( growth, T_rule );
775  doRULE( growth->rules );
776  break;
777 
778  default:
779  Unexpected( CurText() );
780  }
781 
782  tok = NextTok();
783  }
784 }
785 
786 
788 {
789  T tok = NextTok();
790 
791  if( IsSymbol(tok) )
792  {
793  growth->name = CurText();
794  tok = NextTok();
795  }
796 
797  if( tok!=T_LEFT )
798  Expecting( T_LEFT );
799 
800  while( tok != T_RIGHT )
801  {
802  if( tok!=T_LEFT )
803  Expecting( T_LEFT );
804 
805  tok = NextTok();
806  switch( tok )
807  {
808  case T_sequence_number:
809  if( NextTok() != T_NUMBER )
810  Expecting( T_NUMBER );
811  growth->sequence_number = atoi( CurText() );
812  NeedRIGHT();
813  break;
814 
815  case T_rule:
816  if( growth->rules )
817  Unexpected( tok );
818  growth->rules = new RULE( growth, T_rule );
819  doRULE( growth->rules );
820  break;
821 
822  case T_place_rule:
823  if( growth->place_rules )
824  Unexpected( tok );
825  growth->place_rules = new RULE( growth, T_place_rule );
826  doRULE( growth->place_rules );
827  break;
828 
829  case T_rect:
830  if( growth->shape )
831  Unexpected( tok );
832  growth->shape = new RECTANGLE( growth );
833  doRECTANGLE( (RECTANGLE*) growth->shape );
834  break;
835 
836  case T_circle:
837  if( growth->shape )
838  Unexpected( tok );
839  growth->shape = new CIRCLE( growth );
840  doCIRCLE( (CIRCLE*) growth->shape );
841  break;
842 
843  case T_polyline_path:
844  tok = T_path;
846 
847  case T_path:
848  case T_polygon:
849  if( growth->shape )
850  Unexpected( tok );
851  growth->shape = new PATH( growth, tok );
852  doPATH( (PATH*) growth->shape );
853  break;
854 
855  case T_qarc:
856  if( growth->shape )
857  Unexpected( tok );
858  growth->shape = new QARC( growth );
859  doQARC( (QARC*) growth->shape );
860  break;
861 
862  case T_window:
863  WINDOW* window;
864  window = new WINDOW( growth );
865  growth->windows.push_back( window );
866  doWINDOW( window );
867  break;
868 
869  default:
870  Unexpected( CurText() );
871  }
872 
873  tok = NextTok();
874  }
875 }
876 
877 
879 {
880  /* from page 143 of specctra spec:
881 
882  (connect
883  {(terminal <object_type> [<pin_reference> ])}
884  )
885  */
886 
887  T tok = NextTok();
888 
889  while( tok != T_RIGHT )
890  {
891  if( tok!=T_LEFT )
892  Expecting( T_LEFT );
893 
894  tok = NextTok();
895 
896  switch( tok )
897  {
898  case T_terminal:
899  // since we do not use the terminal information, simlpy toss it.
900  while( ( tok = NextTok() ) != T_RIGHT && tok != T_EOF )
901  ;
902  break;
903 
904  default:
905  Unexpected( CurText() );
906  }
907 
908  tok = NextTok();
909  }
910 }
911 
912 
914 {
915  T tok = NextTok();
916 
917  while( tok != T_RIGHT )
918  {
919  if( tok!=T_LEFT )
920  Expecting( T_LEFT );
921 
922  tok = NextTok();
923  switch( tok )
924  {
925  case T_rect:
926  if( growth->shape )
927  Unexpected( tok );
928  growth->shape = new RECTANGLE( growth );
929  doRECTANGLE( (RECTANGLE*) growth->shape );
930  break;
931 
932  case T_circle:
933  if( growth->shape )
934  Unexpected( tok );
935  growth->shape = new CIRCLE( growth );
936  doCIRCLE( (CIRCLE*) growth->shape );
937  break;
938 
939  case T_polyline_path:
940  tok = T_path;
942 
943  case T_path:
944  case T_polygon:
945  if( growth->shape )
946  Unexpected( tok );
947  growth->shape = new PATH( growth, tok );
948  doPATH( (PATH*) growth->shape );
949  break;
950 
951  case T_qarc:
952  if( growth->shape )
953  Unexpected( tok );
954  growth->shape = new QARC( growth );
955  doQARC( (QARC*) growth->shape );
956  break;
957 
958  default:
959  Unexpected( CurText() );
960  }
961 
962  tok = NextTok();
963  }
964 }
965 
966 
968 {
969  T tok = NextTok();
970 
971  if( tok != T_LEFT )
972  Expecting( T_LEFT );
973 
974  tok = NextTok();
975  if( tok == T_rect )
976  {
977  if( growth->paths.size() )
978  Unexpected( "rect when path already encountered" );
979 
980  growth->rectangle = new RECTANGLE( growth );
981  doRECTANGLE( growth->rectangle );
982  NeedRIGHT();
983  }
984  else if( tok == T_path )
985  {
986  if( growth->rectangle )
987  Unexpected( "path when rect already encountered" );
988 
989  for(;;)
990  {
991  if( tok != T_path )
992  Expecting( T_path );
993 
994  PATH* path = new PATH( growth, T_path );
995  growth->paths.push_back( path );
996 
997  doPATH( path );
998 
999  tok = NextTok();
1000  if( tok == T_RIGHT )
1001  break;
1002 
1003  if( tok != T_LEFT )
1004  Expecting(T_LEFT);
1005 
1006  tok = NextTok();
1007  }
1008  }
1009  else
1010  Expecting( "rect|path" );
1011 }
1012 
1013 
1014 void SPECCTRA_DB::doPATH( PATH* growth )
1015 {
1016  T tok = NextTok();
1017 
1018  if( !IsSymbol( tok ) && tok != T_NUMBER ) // a layer name can be like a number like +12
1019  Expecting( "layer_id" );
1020 
1021  growth->layer_id = CurText();
1022 
1023  if( NextTok() != T_NUMBER )
1024  Expecting( "aperture_width" );
1025 
1026  growth->aperture_width = strtod( CurText(), NULL );
1027 
1028  POINT ptTemp;
1029 
1030  tok = NextTok();
1031 
1032  do
1033  {
1034  if( tok != T_NUMBER )
1035  Expecting( T_NUMBER );
1036  ptTemp.x = strtod( CurText(), NULL );
1037 
1038  if( NextTok() != T_NUMBER )
1039  Expecting( T_NUMBER );
1040  ptTemp.y = strtod( CurText(), NULL );
1041 
1042  growth->points.push_back( ptTemp );
1043 
1044  } while( (tok = NextTok())!=T_RIGHT && tok!=T_LEFT );
1045 
1046  if( tok == T_LEFT )
1047  {
1048  if( NextTok() != T_aperture_type )
1049  Expecting( T_aperture_type );
1050 
1051  tok = NextTok();
1052  if( tok!=T_round && tok!=T_square )
1053  Expecting( "round|square" );
1054 
1055  growth->aperture_type = tok;
1056 
1057  NeedRIGHT();
1058  }
1059 }
1060 
1061 
1063 {
1064  NeedSYMBOL();
1065  growth->layer_id = CurText();
1066 
1067  if( NextTok() != T_NUMBER )
1068  Expecting( T_NUMBER );
1069  growth->point0.x = strtod( CurText(), NULL );
1070 
1071  if( NextTok() != T_NUMBER )
1072  Expecting( T_NUMBER );
1073  growth->point0.y = strtod( CurText(), NULL );
1074 
1075  if( NextTok() != T_NUMBER )
1076  Expecting( T_NUMBER );
1077  growth->point1.x = strtod( CurText(), NULL );
1078 
1079  if( NextTok() != T_NUMBER )
1080  Expecting( T_NUMBER );
1081  growth->point1.y = strtod( CurText(), NULL );
1082 
1083  NeedRIGHT();
1084 }
1085 
1086 
1088 {
1089  T tok;
1090 
1091  NeedSYMBOLorNUMBER();
1092  growth->layer_id = CurText();
1093 
1094  if( NextTok() != T_NUMBER )
1095  Expecting( T_NUMBER );
1096  growth->diameter = strtod( CurText(), 0 );
1097 
1098  tok = NextTok();
1099  if( tok == T_NUMBER )
1100  {
1101  growth->vertex.x = strtod( CurText(), 0 );
1102 
1103  if( NextTok() != T_NUMBER )
1104  Expecting( T_NUMBER );
1105  growth->vertex.y = strtod( CurText(), 0 );
1106 
1107  tok = NextTok();
1108  }
1109 
1110  if( tok != T_RIGHT )
1111  Expecting( T_RIGHT );
1112 }
1113 
1114 
1115 void SPECCTRA_DB::doQARC( QARC* growth )
1116 {
1117  NeedSYMBOL();
1118  growth->layer_id = CurText();
1119 
1120  if( NextTok() != T_NUMBER )
1121  Expecting( T_NUMBER );
1122  growth->aperture_width = strtod( CurText(), 0 );
1123 
1124  for( int i=0; i<3; ++i )
1125  {
1126  if( NextTok() != T_NUMBER )
1127  Expecting( T_NUMBER );
1128  growth->vertex[i].x = strtod( CurText(), 0 );
1129 
1130  if( NextTok() != T_NUMBER )
1131  Expecting( T_NUMBER );
1132  growth->vertex[i].y = strtod( CurText(), 0 );
1133  }
1134 
1135  NeedRIGHT();
1136 }
1137 
1138 
1140 {
1141  NeedSYMBOL();
1142  growth->value = CurText();
1143  NeedRIGHT();
1144 }
1145 
1146 
1148 {
1149  T tok = NextTok();
1150 
1151  if( tok<0 )
1152  Unexpected( CurText() );
1153 
1154  growth->value = tok;
1155 
1156  NeedRIGHT();
1157 }
1158 
1159 
1160 void SPECCTRA_DB::doVIA( VIA* growth )
1161 {
1162  T tok;
1163 
1164  while( (tok = NextTok()) != T_RIGHT )
1165  {
1166  if( tok == T_LEFT )
1167  {
1168  if( NextTok() != T_spare )
1169  Expecting( T_spare );
1170 
1171  while( (tok = NextTok()) != T_RIGHT )
1172  {
1173  if( !IsSymbol( tok ) )
1174  Expecting( T_SYMBOL );
1175 
1176  growth->spares.push_back( CurText() );
1177  }
1178  }
1179  else if( IsSymbol( tok ) )
1180  {
1181  growth->padstacks.push_back( CurText() );
1182  }
1183  else
1184  Unexpected( CurText() );
1185  }
1186 }
1187 
1188 
1190 {
1191  T tok;
1192 
1193  while( (tok = NextTok()) != T_RIGHT )
1194  {
1195  if( tok != T_LEFT )
1196  Expecting( T_LEFT );
1197 
1198  tok = NextTok();
1199  switch( tok )
1200  {
1201  case T_via_at_smd:
1202  tok = NextTok();
1203  if( tok!=T_on && tok!=T_off )
1204  Expecting( "on|off" );
1205  growth->via_at_smd = (tok==T_on);
1206  NeedRIGHT();
1207  break;
1208 
1209  case T_off_grid:
1210  case T_route_to_fanout_only:
1211  case T_force_to_terminal_point:
1212  case T_same_net_checking:
1213  case T_checking_trim_by_pin:
1214  case T_noise_calculation:
1215  case T_noise_accumulation:
1216  case T_include_pins_in_crosstalk:
1217  case T_bbv_ctr2ctr:
1218  case T_average_pair_length:
1219  case T_crosstalk_model:
1220  case T_roundoff_rotation:
1221  case T_microvia:
1222  case T_reroute_order_viols:
1223  TOKPROP* tokprop;
1224  tokprop = new TOKPROP( growth, tok );
1225  growth->Append( tokprop );
1226  doTOKPROP( tokprop );
1227  break;
1228 
1229  default:
1230  Unexpected( CurText() );
1231  }
1232  }
1233 }
1234 
1235 
1237 {
1238  T tok;
1239  PROPERTY property; // construct it once here, append multiple times.
1240 
1241  while( (tok = NextTok()) != T_RIGHT )
1242  {
1243  if( tok != T_LEFT )
1244  Expecting( T_LEFT );
1245 
1246  NeedSYMBOLorNUMBER();
1247  property.name = CurText();
1248 
1249  NeedSYMBOLorNUMBER();
1250  property.value = CurText();
1251 
1252  growth->push_back( property );
1253 
1254  NeedRIGHT();
1255  }
1256 }
1257 
1258 
1260 {
1261  T tok = NextTok();
1262 
1263  if( !IsSymbol(tok) )
1264  Expecting(T_SYMBOL);
1265 
1266  growth->name = CurText();
1267 
1268  while( (tok = NextTok()) != T_RIGHT )
1269  {
1270  if( tok != T_LEFT )
1271  Expecting( T_LEFT );
1272 
1273  tok = NextTok();
1274  switch( tok )
1275  {
1276  case T_type:
1277  tok = NextTok();
1278  if( tok!=T_signal && tok!=T_power && tok!=T_mixed && tok!=T_jumper )
1279  Expecting( "signal|power|mixed|jumper" );
1280  growth->layer_type = tok;
1281  if( NextTok()!=T_RIGHT )
1282  Expecting(T_RIGHT);
1283  break;
1284 
1285  case T_rule:
1286  growth->rules = new RULE( growth, T_rule );
1287  doRULE( growth->rules );
1288  break;
1289 
1290  case T_property:
1291  doPROPERTIES( &growth->properties );
1292  break;
1293 
1294  case T_direction:
1295  tok = NextTok();
1296  switch( tok )
1297  {
1298  case T_horizontal:
1299  case T_vertical:
1300  case T_orthogonal:
1301  case T_positive_diagonal:
1302  case T_negative_diagonal:
1303  case T_diagonal:
1304  case T_off:
1305  growth->direction = tok;
1306  break;
1307  default:
1308  // the spec has an example show an abbreviation of the "horizontal" keyword. Ouch.
1309  if( !strcmp( "hori", CurText() ) )
1310  {
1311  growth->direction = T_horizontal;
1312  break;
1313  }
1314  else if( !strcmp( "vert", CurText() ) )
1315  {
1316  growth->direction = T_vertical;
1317  break;
1318  }
1319  Expecting( "horizontal|vertical|orthogonal|positive_diagonal|negative_diagonal|diagonal|off" );
1320  }
1321  if( NextTok()!=T_RIGHT )
1322  Expecting(T_RIGHT);
1323  break;
1324 
1325  case T_cost:
1326  tok = NextTok();
1327  switch( tok )
1328  {
1329  case T_forbidden:
1330  case T_high:
1331  case T_medium:
1332  case T_low:
1333  case T_free:
1334  growth->cost = tok;
1335  break;
1336  case T_NUMBER:
1337  // store as negative so we can differentiate between
1338  // T (positive) and T_NUMBER (negative)
1339  growth->cost = -atoi( CurText() );
1340  break;
1341  default:
1342  Expecting( "forbidden|high|medium|low|free|<positive_integer>|-1" );
1343  }
1344  tok = NextTok();
1345  if( tok == T_LEFT )
1346  {
1347  if( NextTok() != T_type )
1348  Unexpected( CurText() );
1349 
1350  tok = NextTok();
1351  if( tok!=T_length && tok!=T_way )
1352  Expecting( "length|way" );
1353 
1354  growth->cost_type = tok;
1355  if( NextTok()!=T_RIGHT )
1356  Expecting(T_RIGHT);
1357 
1358  tok = NextTok();
1359  }
1360  if( tok!=T_RIGHT )
1361  Expecting(T_RIGHT);
1362  break;
1363 
1364  case T_use_net:
1365  while( (tok = NextTok()) != T_RIGHT )
1366  {
1367  if( !IsSymbol(tok) )
1368  Expecting( T_SYMBOL );
1369 
1370  growth->use_net.push_back( CurText() );
1371  }
1372  break;
1373 
1374  default:
1375  Unexpected( CurText() );
1376  }
1377  }
1378 }
1379 
1380 
1381 void SPECCTRA_DB::doRULE( RULE* growth )
1382 {
1383  std::string builder;
1384  int bracketNesting = 1; // we already saw the opening T_LEFT
1385  T tok = T_NONE;
1386 
1387  while( bracketNesting!=0 && tok!=T_EOF )
1388  {
1389  tok = NextTok();
1390 
1391  if( tok==T_LEFT)
1392  ++bracketNesting;
1393 
1394  else if( tok==T_RIGHT )
1395  --bracketNesting;
1396 
1397  if( bracketNesting >= 1 )
1398  {
1399  if( PrevTok()!=T_LEFT && tok!=T_RIGHT && (tok!=T_LEFT || bracketNesting>2) )
1400  builder += ' ';
1401 
1402  if( tok==T_STRING )
1403  builder += m_quote_char;
1404 
1405  builder += CurText();
1406 
1407  if( tok==T_STRING )
1408  builder += m_quote_char;
1409  }
1410 
1411  // When the nested rule is closed with a T_RIGHT and we are back down
1412  // to bracketNesting == 1, (inside the <rule_descriptor> but outside
1413  // the last rule). Then save the last rule and clear the string builder.
1414  if( bracketNesting == 1 )
1415  {
1416  growth->rules.push_back( builder );
1417  builder.clear();
1418  }
1419  }
1420 
1421  if( tok==T_EOF )
1422  Unexpected( T_EOF );
1423 }
1424 
1425 
1426 #if 0
1427 void SPECCTRA_DB::doPLACE_RULE( PLACE_RULE* growth, bool expect_object_type )
1428 {
1429  /* (place_rule [<structure_place_rule_object> ]
1430  {[<spacing_descriptor> |
1431  <permit_orient_descriptor> |
1432  <permit_side_descriptor> |
1433  <opposite_side_descriptor> ]}
1434  )
1435  */
1436 
1437  T tok = NextTok();
1438 
1439  if( tok!=T_LEFT )
1440  Expecting( T_LEFT );
1441 
1442  tok = NextTok();
1443  if( tok==T_object_type )
1444  {
1445  if( !expect_object_type )
1446  Unexpected( tok );
1447 
1448  /* [(object_type
1449  [pcb |
1450  image_set [large | small | discrete | capacitor | resistor]
1451  [(image_type [smd | pin])]]
1452  )]
1453  */
1454 
1455  tok = NextTok();
1456  switch( tok )
1457  {
1458  case T_pcb:
1459  growth->object_type = tok;
1460  break;
1461 
1462  case T_image_set:
1463  tok = NextTok();
1464  switch( tok )
1465  {
1466  case T_large:
1467  case T_small:
1468  case T_discrete:
1469  case T_capacitor:
1470  case T_resistor:
1471  growth->object_type = tok;
1472  break;
1473  default:
1474  Unexpected( CurText() );
1475  }
1476  break;
1477 
1478  default:
1479  Unexpected( CurText() );
1480  }
1481 
1482  tok = NextTok();
1483  if( tok == T_LEFT )
1484  {
1485  tok = NextTok();
1486  if( tok != T_image_type )
1487  Expecting( T_image_type );
1488 
1489  tok = NextTok();
1490  if( tok!=T_smd && tok!=T_pin )
1491  Expecting( "smd|pin" );
1492 
1493  NeedRIGHT();
1494 
1495  tok = NextTok();
1496  }
1497 
1498  if( tok != T_RIGHT )
1499  Expecting( T_RIGHT );
1500 
1501  tok = NextTok();
1502  }
1503 
1504  /* {[<spacing_descriptor> |
1505  <permit_orient_descriptor> |
1506  <permit_side_descriptor> | <opposite_side_descriptor> ]}
1507  */
1508  doRULE( growth );
1509 }
1510 #endif
1511 
1512 
1514 {
1515  T tok = NextTok();
1516 
1517  if( IsSymbol(tok) )
1518  {
1519  growth->region_id = CurText();
1520  tok = NextTok();
1521  }
1522 
1523  for(;;)
1524  {
1525  if( tok != T_LEFT )
1526  Expecting( T_LEFT );
1527 
1528  tok = NextTok();
1529  switch( tok )
1530  {
1531  case T_rect:
1532  if( growth->rectangle )
1533  Unexpected( tok );
1534  growth->rectangle = new RECTANGLE( growth );
1535  doRECTANGLE( growth->rectangle );
1536  break;
1537 
1538  case T_polygon:
1539  if( growth->polygon )
1540  Unexpected( tok );
1541  growth->polygon = new PATH( growth, T_polygon );
1542  doPATH( growth->polygon );
1543  break;
1544 
1545  case T_region_net:
1546  case T_region_class:
1547  STRINGPROP* stringprop;
1548  stringprop = new STRINGPROP( growth, tok );
1549  growth->Append( stringprop );
1550  doSTRINGPROP( stringprop );
1551  break;
1552 
1553  case T_region_class_class:
1554  CLASS_CLASS* class_class;
1555  class_class = new CLASS_CLASS( growth, tok );
1556  growth->Append( class_class );
1557  doCLASS_CLASS( class_class );
1558  break;
1559 
1560  case T_rule:
1561  if( growth->rules )
1562  Unexpected( tok );
1563  growth->rules = new RULE( growth, T_rule );
1564  doRULE( growth->rules );
1565  break;
1566 
1567  default:
1568  Unexpected( CurText() );
1569  }
1570 
1571  tok = NextTok();
1572  if( tok == T_RIGHT )
1573  {
1574  if( !growth->rules )
1575  Expecting( T_rule );
1576  break;
1577  }
1578  }
1579 }
1580 
1581 
1583 {
1584  T tok = NextTok();
1585 
1586  if( tok != T_LEFT )
1587  Expecting( T_LEFT );
1588 
1589  while( (tok = NextTok()) != T_RIGHT )
1590  {
1591  switch( tok )
1592  {
1593  case T_classes:
1594  if( growth->classes )
1595  Unexpected( tok );
1596  growth->classes = new CLASSES( growth );
1597  doCLASSES( growth->classes );
1598  break;
1599 
1600  case T_rule:
1601  // only T_class_class takes a T_rule
1602  if( growth->Type() == T_region_class_class )
1603  Unexpected( tok );
1604  RULE* rule;
1605  rule = new RULE( growth, T_rule );
1606  growth->Append( rule );
1607  doRULE( rule );
1608  break;
1609 
1610  case T_layer_rule:
1611  // only T_class_class takes a T_layer_rule
1612  if( growth->Type() == T_region_class_class )
1613  Unexpected( tok );
1614  LAYER_RULE* layer_rule;
1615  layer_rule = new LAYER_RULE( growth );
1616  growth->Append( layer_rule );
1617  doLAYER_RULE( layer_rule );
1618  break;
1619 
1620  default:
1621  Unexpected( tok );
1622  }
1623  }
1624 }
1625 
1626 
1628 {
1629  T tok = NextTok();
1630 
1631  // require at least 2 class_ids
1632 
1633  if( !IsSymbol( tok ) )
1634  Expecting( "class_id" );
1635 
1636  growth->class_ids.push_back( CurText() );
1637 
1638  do
1639  {
1640  tok = NextTok();
1641  if( !IsSymbol( tok ) )
1642  Expecting( "class_id" );
1643 
1644  growth->class_ids.push_back( CurText() );
1645 
1646  } while( (tok = NextTok()) != T_RIGHT );
1647 }
1648 
1649 
1650 void SPECCTRA_DB::doGRID( GRID* growth )
1651 {
1652  T tok = NextTok();
1653 
1654  switch( tok )
1655  {
1656  case T_via:
1657  case T_wire:
1658  case T_via_keepout:
1659  case T_snap:
1660  case T_place:
1661  growth->grid_type = tok;
1662  if( NextTok() != T_NUMBER )
1663  Expecting( T_NUMBER );
1664  growth->dimension = strtod( CurText(), 0 );
1665  tok = NextTok();
1666  if( tok == T_LEFT )
1667  {
1668  while( (tok=NextTok()) != T_RIGHT )
1669  {
1670  if( tok==T_direction )
1671  {
1672  if( growth->grid_type == T_place )
1673  Unexpected( tok );
1674  tok = NextTok();
1675  if( tok!=T_x && tok!=T_y )
1676  Unexpected( CurText() );
1677  growth->direction = tok;
1678  if( NextTok() != T_RIGHT )
1679  Expecting(T_RIGHT);
1680  }
1681  else if( tok==T_offset )
1682  {
1683  if( growth->grid_type == T_place )
1684  Unexpected( tok );
1685 
1686  if( NextTok() != T_NUMBER )
1687  Expecting( T_NUMBER );
1688 
1689  growth->offset = strtod( CurText(), 0 );
1690 
1691  if( NextTok() != T_RIGHT )
1692  Expecting(T_RIGHT);
1693  }
1694  else if( tok==T_image_type )
1695  {
1696  if( growth->grid_type != T_place )
1697  Unexpected( tok );
1698  tok = NextTok();
1699  if( tok!=T_smd && tok!=T_pin )
1700  Unexpected( CurText() );
1701  growth->image_type = tok;
1702  if( NextTok() != T_RIGHT )
1703  Expecting(T_RIGHT);
1704  }
1705  }
1706  }
1707  break;
1708 
1709  default:
1710  Unexpected( tok );
1711  }
1712 }
1713 
1714 
1716 {
1717  T tok;
1718 
1719  NeedSYMBOL();
1720 
1721  do
1722  {
1723  growth->layer_ids.push_back( CurText() );
1724 
1725  } while( IsSymbol(tok = NextTok()) );
1726 
1727  if( tok != T_LEFT )
1728  Expecting( T_LEFT );
1729 
1730  if( NextTok() != T_rule )
1731  Expecting( T_rule );
1732 
1733  growth->rule = new RULE( growth, T_rule );
1734  doRULE( growth->rule );
1735 
1736  NeedRIGHT();
1737 }
1738 
1739 
1741 {
1742  T tok = NextTok();
1743 
1744  if( !IsSymbol( tok ) )
1745  Expecting( "component_id" );
1746 
1747  growth->component_id = CurText();
1748 
1749  tok = NextTok();
1750  if( tok == T_NUMBER )
1751  {
1752  POINT point;
1753 
1754  point.x = strtod( CurText(), 0 );
1755 
1756  if( NextTok() != T_NUMBER )
1757  Expecting( T_NUMBER );
1758  point.y = strtod( CurText(), 0 );
1759 
1760  growth->SetVertex( point );
1761 
1762  tok = NextTok();
1763  if( tok!=T_front && tok!=T_back )
1764  Expecting( "front|back" );
1765  growth->side = tok;
1766 
1767  if( NextTok() != T_NUMBER )
1768  Expecting( "rotation" );
1769  growth->SetRotation( strtod( CurText(), 0) );
1770  }
1771 
1772  while( (tok = NextTok()) != T_RIGHT )
1773  {
1774  if( tok != T_LEFT )
1775  Expecting( T_LEFT );
1776 
1777  tok = NextTok();
1778  switch( tok )
1779  {
1780  case T_mirror:
1781  tok = NextTok();
1782  if( tok==T_x || tok==T_y || tok==T_xy || tok==T_off )
1783  growth->mirror = tok;
1784  else
1785  Expecting("x|y|xy|off");
1786  break;
1787 
1788  case T_status:
1789  tok = NextTok();
1790  if( tok==T_added || tok==T_deleted || tok==T_substituted )
1791  growth->status = tok;
1792  else
1793  Expecting("added|deleted|substituted");
1794  break;
1795 
1796  case T_logical_part:
1797  if( growth->logical_part.size() )
1798  Unexpected( tok );
1799  tok = NextTok();
1800  if( !IsSymbol( tok ) )
1801  Expecting( "logical_part_id");
1802  growth->logical_part = CurText();
1803  break;
1804 
1805  case T_place_rule:
1806  if( growth->place_rules )
1807  Unexpected( tok );
1808  growth->place_rules = new RULE( growth, T_place_rule );
1809  doRULE( growth->place_rules );
1810  break;
1811 
1812  case T_property:
1813  if( growth->properties.size() )
1814  Unexpected( tok );
1815  doPROPERTIES( &growth->properties );
1816  break;
1817 
1818  case T_lock_type:
1819  tok = NextTok();
1820  if( tok==T_position || tok==T_gate || tok==T_subgate || tok==T_pin )
1821  growth->lock_type = tok;
1822  else
1823  Expecting("position|gate|subgate|pin");
1824  break;
1825 
1826  case T_rule:
1827  if( growth->rules || growth->region )
1828  Unexpected( tok );
1829  growth->rules = new RULE( growth, T_rule );
1830  doRULE( growth->rules );
1831  break;
1832 
1833  case T_region:
1834  if( growth->rules || growth->region )
1835  Unexpected( tok );
1836  growth->region = new REGION( growth );
1837  doREGION( growth->region );
1838  break;
1839 
1840  case T_pn:
1841  if( growth->part_number.size() )
1842  Unexpected( tok );
1843  NeedSYMBOLorNUMBER();
1844  growth->part_number = CurText();
1845  NeedRIGHT();
1846  break;
1847 
1848  default:
1849  Unexpected( tok );
1850  }
1851  }
1852 }
1853 
1854 
1856 {
1857  T tok = NextTok();
1858 
1859  if( !IsSymbol( tok ) && tok != T_NUMBER )
1860  Expecting( "image_id" );
1861  growth->image_id = CurText();
1862 
1863  while( (tok = NextTok()) != T_RIGHT )
1864  {
1865  if( tok != T_LEFT )
1866  Expecting( T_LEFT );
1867 
1868  tok = NextTok();
1869  switch( tok )
1870  {
1871  case T_place:
1872  PLACE* place;
1873  place = new PLACE( growth );
1874  growth->places.push_back( place );
1875  doPLACE( place );
1876  break;
1877 
1878  default:
1879  Unexpected(tok);
1880  }
1881  }
1882 }
1883 
1884 
1886 {
1887  T tok;
1888 
1889  while( (tok = NextTok()) != T_RIGHT )
1890  {
1891  if( tok == T_EOF )
1892  Unexpected( T_EOF );
1893 
1894  if( tok != T_LEFT )
1895  Expecting( T_LEFT );
1896 
1897  tok = NextTok();
1898 
1899  switch( tok )
1900  {
1901  case T_unit:
1902  case T_resolution:
1903  growth->unit = new UNIT_RES( growth, tok );
1904  if( tok==T_resolution )
1905  doRESOLUTION( growth->unit );
1906  else
1907  doUNIT( growth->unit );
1908  break;
1909 
1910  case T_place_control:
1911  NeedRIGHT();
1912  tok = NextTok();
1913  if( tok != T_flip_style )
1914  Expecting( T_flip_style );
1915 
1916  tok = NextTok();
1917  if( tok==T_mirror_first || tok==T_rotate_first )
1918  growth->flip_style = tok;
1919  else
1920  Expecting( "mirror_first|rotate_first" );
1921 
1922  NeedRIGHT();
1923  NeedRIGHT();
1924  break;
1925 
1926  case T_component:
1927  COMPONENT* component;
1928  component = new COMPONENT( growth );
1929  growth->components.push_back( component );
1930  doCOMPONENT( component );
1931  break;
1932 
1933  default:
1934  Unexpected( tok );
1935  }
1936  }
1937 }
1938 
1939 
1941 {
1942  T tok = NextTok();
1943 
1944  /* (padstack <padstack_id >
1945  [<unit_descriptor> ]
1946  {(shape <shape_descriptor>
1947  [<reduced_shape_descriptor> ]
1948  [(connect [on | off])]
1949  [{<window_descriptor> }]
1950  )}
1951  [<attach_descriptor> ]
1952  [{<pad_via_site_descriptor> }]
1953  [(rotate [on | off])]
1954  [(absolute [on | off])]
1955  [(rule <clearance_descriptor> )])
1956  */
1957 
1958  // padstack_id may be a number
1959  if( !IsSymbol( tok ) && tok!=T_NUMBER )
1960  Expecting( "padstack_id" );
1961 
1962  growth->padstack_id = CurText();
1963 
1964  while( (tok = NextTok()) != T_RIGHT )
1965  {
1966  if( tok != T_LEFT )
1967  Expecting( T_LEFT );
1968 
1969  tok = NextTok();
1970  switch( tok )
1971  {
1972  case T_unit:
1973  if( growth->unit )
1974  Unexpected( tok );
1975  growth->unit = new UNIT_RES( growth, tok );
1976  doUNIT( growth->unit );
1977  break;
1978 
1979  case T_rotate:
1980  tok = NextTok();
1981  if( tok!=T_on && tok!=T_off )
1982  Expecting( "on|off" );
1983  growth->rotate = tok;
1984  NeedRIGHT();
1985  break;
1986 
1987  case T_absolute:
1988  tok = NextTok();
1989  if( tok!=T_on && tok!=T_off )
1990  Expecting( "on|off" );
1991  growth->absolute = tok;
1992  NeedRIGHT();
1993  break;
1994 
1995  case T_shape:
1996  SHAPE* shape;
1997  shape = new SHAPE( growth );
1998  growth->Append( shape );
1999  doSHAPE( shape );
2000  break;
2001 
2002  case T_attach:
2003  tok = NextTok();
2004  if( tok!=T_off && tok!=T_on )
2005  Expecting( "off|on" );
2006  growth->attach = tok;
2007  tok = NextTok();
2008  if( tok == T_LEFT )
2009  {
2010  if( NextTok() != T_use_via )
2011  Expecting( T_use_via );
2012 
2013  NeedSYMBOL();
2014  growth->via_id = CurText();
2015 
2016  NeedRIGHT();
2017  NeedRIGHT();
2018  }
2019  break;
2020 
2021  /*
2022  case T_via_site: not supported
2023  break;
2024  */
2025 
2026  case T_rule:
2027  if( growth->rules )
2028  Unexpected( tok );
2029  growth->rules = new RULE( growth, T_rule );
2030  doRULE( growth->rules );
2031  break;
2032 
2033  default:
2034  Unexpected( CurText() );
2035  }
2036  }
2037 }
2038 
2039 
2041 {
2042  T tok;
2043 
2044  /* (shape <shape_descriptor>
2045  [<reduced_shape_descriptor> ]
2046  [(connect [on | off])]
2047  [{<window_descriptor> }])
2048  */
2049 
2050  while( (tok = NextTok()) != T_RIGHT )
2051  {
2052  if( tok != T_LEFT )
2053  Expecting( T_LEFT );
2054 
2055  tok = NextTok();
2056  switch( tok )
2057  {
2058  case T_polyline_path:
2059  tok = T_path;
2061 
2062  case T_rect:
2063  case T_circle:
2064  case T_path:
2065  case T_polygon:
2066  case T_qarc:
2067 L_done_that:
2068  if( growth->shape )
2069  Unexpected( tok );
2070  break;
2071 
2072  default:
2073  // the example in the spec uses "circ" instead of "circle". Bad!
2074  if( !strcmp( "circ", CurText() ) )
2075  {
2076  tok = T_circle;
2077  goto L_done_that;
2078  }
2079  }
2080 
2081  switch( tok )
2082  {
2083  case T_rect:
2084  growth->shape = new RECTANGLE( growth );
2085  doRECTANGLE( (RECTANGLE*) growth->shape );
2086  break;
2087 
2088  case T_circle:
2089  growth->shape = new CIRCLE( growth );
2090  doCIRCLE( (CIRCLE*)growth->shape );
2091  break;
2092 
2093  case T_path:
2094  case T_polygon:
2095  growth->shape = new PATH( growth, tok );
2096  doPATH( (PATH*)growth->shape );
2097  break;
2098 
2099  case T_qarc:
2100  growth->shape = new QARC( growth );
2101  doQARC( (QARC*)growth->shape );
2102  break;
2103 
2104  case T_connect:
2105  tok = NextTok();
2106  if( tok!=T_on && tok!=T_off )
2107  Expecting( "on|off" );
2108  growth->connect = tok;
2109  NeedRIGHT();
2110  break;
2111 
2112  case T_window:
2113  WINDOW* window;
2114  window = new WINDOW( growth );
2115  growth->windows.push_back( window );
2116  doWINDOW( window );
2117  break;
2118 
2119  default:
2120  Unexpected( CurText() );
2121  }
2122  }
2123 }
2124 
2125 
2127 {
2128  T tok = NextTok();
2129 
2130  /* <image_descriptor >::=
2131  (image <image_id >
2132  [(side [front | back | both])]
2133  [<unit_descriptor> ]
2134  [<outline_descriptor> ]
2135  {(pin <padstack_id > [(rotate <rotation> )]
2136  [<reference_descriptor> | <pin_array_descriptor> ]
2137  [<user_property_descriptor> ])}
2138  [{<conductor_shape_descriptor> }]
2139  [{<conductor_via_descriptor> }]
2140  [<rule_descriptor> ]
2141  [<place_rule_descriptor> ]
2142  [{<keepout_descriptor> }]
2143  [<image_property_descriptor> ]
2144  )
2145  */
2146 
2147  if( !IsSymbol( tok ) && tok != T_NUMBER )
2148  Expecting( "image_id" );
2149 
2150  growth->image_id = CurText();
2151 
2152  while( (tok = NextTok()) != T_RIGHT )
2153  {
2154  if( tok != T_LEFT )
2155  Expecting( T_LEFT );
2156 
2157  tok = NextTok();
2158  switch( tok )
2159  {
2160  case T_unit:
2161  if( growth->unit )
2162  Unexpected( tok );
2163  growth->unit = new UNIT_RES( growth, tok );
2164  doUNIT( growth->unit );
2165  break;
2166 
2167  case T_side:
2168  tok = NextTok();
2169  if( tok!=T_front && tok!=T_back && tok!=T_both )
2170  Expecting( "front|back|both" );
2171  growth->side = tok;
2172  NeedRIGHT();
2173  break;
2174 
2175  case T_outline:
2176  SHAPE* outline;
2177  outline = new SHAPE( growth, T_outline ); // use SHAPE for T_outline
2178  growth->Append( outline );
2179  doSHAPE( outline );
2180  break;
2181 
2182  case T_pin:
2183  PIN* pin;
2184  pin = new PIN( growth );
2185  growth->pins.push_back( pin );
2186  doPIN( pin );
2187  break;
2188 
2189  case T_rule:
2190  if( growth->rules )
2191  Unexpected( tok );
2192  growth->rules = new RULE( growth, tok );
2193  doRULE( growth->rules );
2194  break;
2195 
2196  case T_place_rule:
2197  if( growth->place_rules )
2198  Unexpected( tok );
2199  growth->place_rules = new RULE( growth, tok );
2200  doRULE( growth->place_rules );
2201  break;
2202 
2203  case T_keepout:
2204  case T_place_keepout:
2205  case T_via_keepout:
2206  case T_wire_keepout:
2207  case T_bend_keepout:
2208  case T_elongate_keepout:
2209  KEEPOUT* keepout;
2210  keepout = new KEEPOUT( growth, tok );
2211  growth->keepouts.push_back( keepout );
2212  doKEEPOUT( keepout );
2213  break;
2214 
2215  default:
2216  Unexpected( CurText() );
2217  }
2218  }
2219 }
2220 
2221 
2222 void SPECCTRA_DB::doPIN( PIN* growth )
2223 {
2224  T tok = NextTok();
2225 
2226  /* (pin <padstack_id > [(rotate <rotation> )]
2227  [<reference_descriptor> | <pin_array_descriptor> ]
2228  [<user_property_descriptor> ])
2229  */
2230 
2231  // a padstack_id may be a number
2232  if( !IsSymbol( tok ) && tok!=T_NUMBER )
2233  Expecting( "padstack_id" );
2234 
2235  growth->padstack_id = CurText();
2236 
2237  while( (tok = NextTok()) != T_RIGHT )
2238  {
2239  if( tok == T_LEFT )
2240  {
2241  tok = NextTok();
2242  if( tok != T_rotate )
2243  Expecting( T_rotate );
2244 
2245  if( NextTok() != T_NUMBER )
2246  Expecting( T_NUMBER );
2247  growth->SetRotation( strtod( CurText(), 0 ) );
2248  NeedRIGHT();
2249  }
2250  else
2251  {
2252  if( !IsSymbol(tok) && tok!=T_NUMBER )
2253  Expecting( "pin_id" );
2254 
2255  growth->pin_id = CurText();
2256 
2257  if( NextTok() != T_NUMBER )
2258  Expecting( T_NUMBER );
2259  growth->vertex.x = strtod( CurText(), 0 );
2260 
2261  if( NextTok() != T_NUMBER )
2262  Expecting( T_NUMBER );
2263  growth->vertex.y = strtod( CurText(), 0 );
2264  }
2265  }
2266 }
2267 
2268 
2270 {
2271  T tok;
2272 
2273  /* <library_descriptor >::=
2274  (library
2275  [<unit_descriptor> ]
2276  {<image_descriptor> }
2277  [{<jumper_descriptor> }]
2278  {<padstack_descriptor> }
2279  {<via_array_template_descriptor> }
2280  [<directory_descriptor> ]
2281  [<extra_image_directory_descriptor> ]
2282  [{<family_family_descriptor> }]
2283  [{<image_image_descriptor> }]
2284  )
2285  */
2286 
2287  while( (tok = NextTok()) != T_RIGHT )
2288  {
2289  if( tok != T_LEFT )
2290  Expecting( T_LEFT );
2291 
2292  tok = NextTok();
2293  switch( tok )
2294  {
2295  case T_unit:
2296  if( growth->unit )
2297  Unexpected( tok );
2298  growth->unit = new UNIT_RES( growth, tok );
2299  doUNIT( growth->unit );
2300  break;
2301 
2302  case T_padstack:
2303  PADSTACK* padstack;
2304  padstack = new PADSTACK();
2305  growth->AddPadstack( padstack );
2306  doPADSTACK( padstack );
2307  break;
2308 
2309  case T_image:
2310  IMAGE* image;
2311  image = new IMAGE( growth );
2312  growth->images.push_back( image );
2313  doIMAGE( image );
2314  break;
2315 
2316  default:
2317  Unexpected( CurText() );
2318  }
2319  }
2320 }
2321 
2322 
2323 void SPECCTRA_DB::doNET( NET* growth )
2324 {
2325  T tok = NextTok();
2326  PIN_REFS* pin_refs;
2327 
2328  /* <net_descriptor >::=
2329  (net <net_id >
2330  [(unassigned)]
2331  [(net_number <integer >)]
2332  [(pins {<pin_reference> }) | (order {<pin_reference> })]
2333  [<component_order_descriptor> ]
2334  [(type [fix | normal])]
2335  [<user_property_descriptor> ]
2336  [<circuit_descriptor> ]
2337  [<rule_descriptor> ]
2338  [{<layer_rule_descriptor> }]
2339  [<fromto_descriptor> ]
2340  [(expose {<pin_reference> })]
2341  [(noexpose {<pin_reference> })]
2342  [(source {<pin_reference> })]
2343  [(load {<pin_reference> })]
2344  [(terminator {<pin_reference> })]
2345  [(supply [power | ground])]
2346  )
2347  */
2348 
2349  if( !IsSymbol( tok ) )
2350  Expecting( "net_id" );
2351 
2352  growth->net_id = CurText();
2353 
2354  while( (tok = NextTok()) != T_RIGHT )
2355  {
2356  if( tok != T_LEFT )
2357  Expecting( T_LEFT );
2358 
2359  tok = NextTok();
2360  switch( tok )
2361  {
2362  case T_unassigned:
2363  growth->unassigned = true;
2364  NeedRIGHT();
2365  break;
2366 
2367  case T_net_number:
2368  if( NextTok() != T_NUMBER )
2369  Expecting( T_NUMBER );
2370  growth->net_number = atoi( CurText() );
2371  NeedRIGHT();
2372  break;
2373 
2374  case T_pins:
2375  case T_order:
2376  growth->pins_type = tok;
2377  pin_refs = &growth->pins;
2378  goto L_pins;
2379 
2380  case T_expose:
2381  pin_refs = &growth->expose;
2382  goto L_pins;
2383 
2384  case T_noexpose:
2385  pin_refs = &growth->noexpose;
2386  goto L_pins;
2387 
2388  case T_source:
2389  pin_refs = &growth->source;
2390  goto L_pins;
2391 
2392  case T_load:
2393  pin_refs = &growth->load;
2394  goto L_pins;
2395 
2396  case T_terminator:
2397  pin_refs = &growth->terminator;
2398  //goto L_pins;
2399 
2400 L_pins:
2401  {
2402  PIN_REF empty( growth );
2403  while( (tok = NextTok()) != T_RIGHT )
2404  {
2405  // copy the empty one, then fill its copy later thru pin_ref.
2406  pin_refs->push_back( empty );
2407 
2408  PIN_REF* pin_ref = &pin_refs->back();
2409 
2410  readCOMPnPIN( &pin_ref->component_id, &pin_ref->pin_id );
2411  }
2412  }
2413  break;
2414 
2415  case T_comp_order:
2416  if( growth->comp_order )
2417  Unexpected( tok );
2418  growth->comp_order = new COMP_ORDER( growth );
2419  doCOMP_ORDER( growth->comp_order );
2420  break;
2421 
2422  case T_type:
2423  tok = NextTok();
2424  if( tok!=T_fix && tok!=T_normal )
2425  Expecting( "fix|normal" );
2426  growth->type = tok;
2427  NeedRIGHT();
2428  break;
2429 
2430 /* @todo
2431  case T_circuit:
2432  break;
2433 */
2434 
2435  case T_rule:
2436  if( growth->rules )
2437  Unexpected( tok );
2438  growth->rules = new RULE( growth, T_rule );
2439  doRULE( growth->rules );
2440  break;
2441 
2442  case T_layer_rule:
2443  LAYER_RULE* layer_rule;
2444  layer_rule = new LAYER_RULE( growth );
2445  growth->layer_rules.push_back( layer_rule );
2446  doLAYER_RULE( layer_rule );
2447  break;
2448 
2449  case T_fromto:
2450  FROMTO* fromto;
2451  fromto = new FROMTO( growth );
2452  growth->fromtos.push_back( fromto );
2453  doFROMTO( fromto );
2454  break;
2455 
2456  default:
2457  Unexpected( CurText() );
2458  }
2459  }
2460 }
2461 
2462 
2464 {
2465  T tok;
2466 
2467  /* <topology_descriptor >::=
2468  (topology {[<fromto_descriptor> |
2469  <component_order_descriptor> ]})
2470  */
2471 
2472  while( (tok = NextTok()) != T_RIGHT )
2473  {
2474  if( tok != T_LEFT )
2475  Expecting( T_LEFT );
2476 
2477  tok = NextTok();
2478  switch( tok )
2479  {
2480  case T_fromto:
2481  FROMTO* fromto;
2482  fromto = new FROMTO( growth );
2483  growth->fromtos.push_back( fromto );
2484  doFROMTO( fromto );
2485  break;
2486 
2487  case T_comp_order:
2488  COMP_ORDER* comp_order;
2489  comp_order = new COMP_ORDER( growth );
2490  growth->comp_orders.push_back( comp_order );
2491  doCOMP_ORDER( comp_order );
2492  break;
2493 
2494  default:
2495  Unexpected( CurText() );
2496  }
2497  }
2498 }
2499 
2500 
2502 {
2503  T tok;
2504 
2505  /* <class_descriptor >::=
2506  (class
2507  <class_id > {[{<net_id >} | {<composite_name_list> }]}
2508  [<circuit_descriptor> ]
2509  [<rule_descriptor> ]
2510  [{<layer_rule_descriptor> }]
2511  [<topology_descriptor> ]
2512  )
2513  */
2514 
2515  NeedSYMBOL();
2516 
2517  growth->class_id = CurText();
2518 
2519  // do net_ids, do not support <composite_name_list>s at this time
2520  while( IsSymbol(tok = NextTok()) )
2521  {
2522  growth->net_ids.push_back( CurText() );
2523  }
2524 
2525 
2526  while( tok != T_RIGHT )
2527  {
2528  if( tok != T_LEFT )
2529  Expecting( T_LEFT );
2530 
2531  tok = NextTok();
2532  switch( tok )
2533  {
2534  case T_rule:
2535  if( growth->rules )
2536  Unexpected( tok );
2537  growth->rules = new RULE( growth, T_rule );
2538  doRULE( growth->rules );
2539  break;
2540 
2541  case T_layer_rule:
2542  LAYER_RULE* layer_rule;
2543  layer_rule = new LAYER_RULE( growth );
2544  growth->layer_rules.push_back( layer_rule );
2545  doLAYER_RULE( layer_rule );
2546  break;
2547 
2548  case T_topology:
2549  if( growth->topology )
2550  Unexpected( tok );
2551  growth->topology = new TOPOLOGY( growth );
2552  doTOPOLOGY( growth->topology );
2553  break;
2554 
2555  case T_circuit: // handle all the circuit_descriptor here as strings
2556  {
2557  std::string builder;
2558  int bracketNesting = 1; // we already saw the opening T_LEFT
2559  tok = T_NONE;
2560 
2561  while( bracketNesting!=0 && tok!=T_EOF )
2562  {
2563  tok = NextTok();
2564 
2565  if( tok==T_LEFT)
2566  ++bracketNesting;
2567 
2568  else if( tok==T_RIGHT )
2569  --bracketNesting;
2570 
2571  if( bracketNesting >= 1 )
2572  {
2573  T previousTok = (T) PrevTok();
2574 
2575  if( previousTok!=T_LEFT && previousTok!=T_circuit && tok!=T_RIGHT )
2576  builder += ' ';
2577 
2578  if( tok==T_STRING )
2579  builder += m_quote_char;
2580 
2581  builder += CurText();
2582 
2583  if( tok==T_STRING )
2584  builder += m_quote_char;
2585  }
2586 
2587  // When the nested rule is closed with a T_RIGHT and we are back down
2588  // to bracketNesting == 0, then save the builder and break;
2589  if( bracketNesting == 0 )
2590  {
2591  growth->circuit.push_back( builder );
2592  break;
2593  }
2594  }
2595 
2596  if( tok==T_EOF )
2597  Unexpected( T_EOF );
2598  } // scope bracket
2599  break;
2600 
2601  default:
2602  Unexpected( CurText() );
2603  } // switch
2604 
2605  tok = NextTok();
2606 
2607  } // while
2608 }
2609 
2610 
2612 {
2613  T tok;
2614 
2615  /* <network_descriptor >::=
2616  (network
2617  {<net_descriptor>}
2618  [{<class_descriptor> }]
2619  [{<class_class_descriptor> }]
2620  [{<group_descriptor> }]
2621  [{<group_set_descriptor> }]
2622  [{<pair_descriptor> }]
2623  [{<bundle_descriptor> }]
2624  )
2625  */
2626 
2627  while( (tok = NextTok()) != T_RIGHT )
2628  {
2629  if( tok != T_LEFT )
2630  Expecting( T_LEFT );
2631 
2632  tok = NextTok();
2633  switch( tok )
2634  {
2635  case T_net:
2636  NET* net;
2637  net = new NET( growth );
2638  growth->nets.push_back( net );
2639  doNET( net );
2640  break;
2641 
2642  case T_class:
2643  CLASS* myclass;
2644  myclass = new CLASS( growth );
2645  growth->classes.push_back( myclass );
2646  doCLASS( myclass );
2647  break;
2648 
2649  default:
2650  Unexpected( CurText() );
2651  }
2652  }
2653 }
2654 
2655 
2657 {
2658  T tok;
2659 
2660  /* <component_order_descriptor >::=
2661  (comp_order {<placement_id> })
2662  */
2663 
2664  while( IsSymbol(tok = NextTok()) )
2665  {
2666  growth->placement_ids.push_back( CurText() );
2667  }
2668 
2669  if( tok != T_RIGHT )
2670  Expecting( T_RIGHT );
2671 }
2672 
2673 
2675 {
2676  T tok;
2677 
2678  /* <fromto_descriptor >::=
2679  {(fromto
2680  [<pin_reference> | <virtual_pin_descriptor> ] | <component_id >]
2681  [<pin_reference> | <virtual_pin_descriptor> | <component_id >]
2682  [(type [fix | normal | soft])]
2683  [(net <net_id >)]
2684  [<rule_descriptor> ]
2685  [<circuit_descriptor> ]
2686  [{<layer_rule_descriptor> }]
2687  )}
2688  */
2689 
2690 
2691  // read the first two grammar items in as 2 single tokens, i.e. do not
2692  // split apart the <pin_reference>s into 3 separate tokens. Do this by
2693  // turning off the string delimiter in the lexer.
2694 
2695  char old = SetStringDelimiter( 0 );
2696 
2697  if( !IsSymbol(NextTok() ) )
2698  {
2699  SetStringDelimiter( old );
2700  Expecting( T_SYMBOL );
2701  }
2702  growth->fromText = CurText();
2703 
2704  if( !IsSymbol(NextTok() ) )
2705  {
2706  SetStringDelimiter( old );
2707  Expecting( T_SYMBOL );
2708  }
2709  growth->toText = CurText();
2710 
2711  SetStringDelimiter( old );
2712 
2713  while( (tok = NextTok()) != T_RIGHT )
2714  {
2715  if( tok != T_LEFT )
2716  Expecting( T_LEFT );
2717 
2718  tok = NextTok();
2719  switch( tok )
2720  {
2721  case T_type:
2722  tok = NextTok();
2723  if( tok!=T_fix && tok!=T_normal && tok!=T_soft )
2724  Expecting( "fix|normal|soft" );
2725  growth->fromto_type = tok;
2726  NeedRIGHT();
2727  break;
2728 
2729  case T_rule:
2730  if( growth->rules )
2731  Unexpected( tok );
2732  growth->rules = new RULE( growth, T_rule );
2733  doRULE( growth->rules );
2734  break;
2735 
2736  case T_layer_rule:
2737  LAYER_RULE* layer_rule;
2738  layer_rule = new LAYER_RULE( growth );
2739  growth->layer_rules.push_back( layer_rule );
2740  doLAYER_RULE( layer_rule );
2741  break;
2742 
2743  case T_net:
2744  if( growth->net_id.size() )
2745  Unexpected( tok );
2746  NeedSYMBOL();
2747  growth->net_id = CurText();
2748  NeedRIGHT();
2749  break;
2750 
2751  // circuit descriptor not supported at this time
2752 
2753  default:
2754  Unexpected( CurText() );
2755  }
2756  }
2757 }
2758 
2759 
2760 void SPECCTRA_DB::doWIRE( WIRE* growth )
2761 {
2762  T tok;
2763 
2764  /* <wire_shape_descriptor >::=
2765  (wire
2766  <shape_descriptor>
2767  [(net <net_id >)]
2768  [(turret <turret#> )]
2769  [(type [fix | route | normal | protect])]
2770  [(attr [test | fanout | bus | jumper])]
2771  [(shield <net_id >)]
2772  [{<window_descriptor> }]
2773  [(connect
2774  (terminal <object_type> [<pin_reference> ])
2775  (terminal <object_type> [<pin_reference> ])
2776  )]
2777  [(supply)]
2778  )
2779  */
2780 
2781  while( (tok = NextTok()) != T_RIGHT )
2782  {
2783  if( tok != T_LEFT )
2784  Expecting( T_LEFT );
2785 
2786  tok = NextTok();
2787  switch( tok )
2788  {
2789  case T_rect:
2790  if( growth->shape )
2791  Unexpected( tok );
2792  growth->shape = new RECTANGLE( growth );
2793  doRECTANGLE( (RECTANGLE*) growth->shape );
2794  break;
2795 
2796  case T_circle:
2797  if( growth->shape )
2798  Unexpected( tok );
2799  growth->shape = new CIRCLE( growth );
2800  doCIRCLE( (CIRCLE*) growth->shape );
2801  break;
2802 
2803  case T_polyline_path:
2804  tok = T_path;
2806 
2807  case T_path:
2808  case T_polygon:
2809  if( growth->shape )
2810  Unexpected( tok );
2811  growth->shape = new PATH( growth, tok );
2812  doPATH( (PATH*) growth->shape );
2813  break;
2814 
2815  case T_qarc:
2816  if( growth->shape )
2817  Unexpected( tok );
2818  growth->shape = new QARC( growth );
2819  doQARC( (QARC*) growth->shape );
2820  break;
2821 
2822  case T_net:
2823  NeedSYMBOLorNUMBER();
2824  growth->net_id = CurText();
2825  NeedRIGHT();
2826  break;
2827 
2828  case T_turret:
2829  if( NextTok() != T_NUMBER )
2830  Expecting( T_NUMBER );
2831  growth->turret = atoi( CurText() );
2832  NeedRIGHT();
2833  break;
2834 
2835  case T_type:
2836  tok = NextTok();
2837  if( tok!=T_fix && tok!=T_route && tok!=T_normal && tok!=T_protect )
2838  Expecting( "fix|route|normal|protect" );
2839  growth->wire_type = tok;
2840  NeedRIGHT();
2841  break;
2842 
2843  case T_attr:
2844  tok = NextTok();
2845  if( tok!=T_test && tok!=T_fanout && tok!=T_bus && tok!=T_jumper )
2846  Expecting( "test|fanout|bus|jumper" );
2847  growth->attr = tok;
2848  NeedRIGHT();
2849  break;
2850 
2851  case T_shield:
2852  NeedSYMBOL();
2853  growth->shield = CurText();
2854  NeedRIGHT();
2855  break;
2856 
2857  case T_window:
2858  WINDOW* window;
2859  window = new WINDOW( growth );
2860  growth->windows.push_back( window );
2861  doWINDOW( window );
2862  break;
2863 
2864  case T_connect:
2865  if( growth->connect )
2866  Unexpected( tok );
2867  growth->connect = new CONNECT( growth );
2868  doCONNECT( growth->connect );
2869  break;
2870 
2871  case T_supply:
2872  growth->supply = true;
2873  NeedRIGHT();
2874  break;
2875 
2876  default:
2877  Unexpected( CurText() );
2878  }
2879  }
2880 }
2881 
2882 
2884 {
2885  T tok;
2886  POINT point;
2887 
2888  /* <wire_via_descriptor >::=
2889  (via
2890  <padstack_id > {<vertex> }
2891  [(net <net_id >)]
2892  [(via_number <via#> )]
2893  [(type [fix | route | normal | protect])]
2894  [(attr [test | fanout | jumper |
2895  virtual_pin <virtual_pin_name> ])]
2896  [(contact {<layer_id >})]
2897  [(supply)]
2898  )
2899  (virtual_pin
2900  <virtual_pin_name> <vertex> (net <net_id >)
2901  )
2902  */
2903 
2904  NeedSYMBOL();
2905  growth->padstack_id = CurText();
2906 
2907  while( (tok = NextTok()) == T_NUMBER )
2908  {
2909  point.x = strtod( CurText(), 0 );
2910 
2911  if( NextTok() != T_NUMBER )
2912  Expecting( "vertex.y" );
2913 
2914  point.y = strtod( CurText(), 0 );
2915 
2916  growth->vertexes.push_back( point );
2917  }
2918 
2919  while( tok != T_RIGHT )
2920  {
2921  if( tok != T_LEFT )
2922  Expecting( T_LEFT );
2923 
2924  tok = NextTok();
2925  switch( tok )
2926  {
2927  case T_net:
2928  NeedSYMBOL();
2929  growth->net_id = CurText();
2930  NeedRIGHT();
2931  break;
2932 
2933  case T_via_number:
2934  if( NextTok() != T_NUMBER )
2935  Expecting( "<via#>" );
2936  growth->via_number = atoi( CurText() );
2937  NeedRIGHT();
2938  break;
2939 
2940  case T_type:
2941  tok = NextTok();
2942  if( tok!=T_fix && tok!=T_route && tok!=T_normal && tok!=T_protect )
2943  Expecting( "fix|route|normal|protect" );
2944  growth->via_type = tok;
2945  NeedRIGHT();
2946  break;
2947 
2948  case T_attr:
2949  tok = NextTok();
2950  if( tok!=T_test && tok!=T_fanout && tok!=T_jumper && tok!=T_virtual_pin )
2951  Expecting( "test|fanout|jumper|virtual_pin" );
2952  growth->attr = tok;
2953  if( tok == T_virtual_pin )
2954  {
2955  NeedSYMBOL();
2956  growth->virtual_pin_name = CurText();
2957  }
2958  NeedRIGHT();
2959  break;
2960 
2961  case T_contact:
2962  NeedSYMBOL();
2963  tok = T_SYMBOL;
2964  while( IsSymbol(tok) )
2965  {
2966  growth->contact_layers.push_back( CurText() );
2967  tok = NextTok();
2968  }
2969  if( tok != T_RIGHT )
2970  Expecting( T_RIGHT );
2971  break;
2972 
2973  case T_supply:
2974  growth->supply = true;
2975  NeedRIGHT();
2976  break;
2977 
2978  default:
2979  Unexpected( CurText() );
2980  }
2981 
2982  tok = NextTok();
2983  }
2984 }
2985 
2986 
2988 {
2989  T tok;
2990 
2991  /* <wiring_descriptor >::=
2992  (wiring
2993  [<unit_descriptor> | <resolution_descriptor> | null]
2994  {<wire_descriptor> }
2995  [<test_points_descriptor> ]
2996  {[<supply_pin_descriptor> ]}
2997  )
2998  */
2999 
3000  while( (tok = NextTok()) != T_RIGHT )
3001  {
3002  if( tok != T_LEFT )
3003  Expecting( T_LEFT );
3004 
3005  tok = NextTok();
3006  switch( tok )
3007  {
3008  case T_unit:
3009  if( growth->unit )
3010  Unexpected( tok );
3011  growth->unit = new UNIT_RES( growth, tok );
3012  doUNIT( growth->unit );
3013  break;
3014 
3015  case T_resolution:
3016  if( growth->unit )
3017  Unexpected( tok );
3018  growth->unit = new UNIT_RES( growth, tok );
3019  doRESOLUTION( growth->unit );
3020  break;
3021 
3022  case T_wire:
3023  WIRE* wire;
3024  wire = new WIRE( growth );
3025  growth->wires.push_back( wire );
3026  doWIRE( wire );
3027  break;
3028 
3029  case T_via:
3030  WIRE_VIA* wire_via;
3031  wire_via = new WIRE_VIA( growth );
3032  growth->wire_vias.push_back( wire_via );
3033  doWIRE_VIA( wire_via );
3034  break;
3035 
3036  default:
3037  Unexpected( CurText() );
3038  }
3039  }
3040 }
3041 
3042 
3044 {
3045  T tok;
3046 
3047  /* <ancestor_file_descriptor >::=
3048  (ancestor <file_path_name> (created_time <time_stamp> )
3049  [(comment <comment_string> )])
3050  */
3051 
3052  NeedSYMBOL();
3053  growth->filename = CurText();
3054 
3055  while( (tok = NextTok()) != T_RIGHT )
3056  {
3057  if( tok != T_LEFT )
3058  Expecting( T_LEFT );
3059 
3060  tok = NextTok();
3061  switch( tok )
3062  {
3063  case T_created_time:
3064  readTIME( &growth->time_stamp );
3065  NeedRIGHT();
3066  break;
3067 
3068  case T_comment:
3069  NeedSYMBOL();
3070  growth->comment = CurText();
3071  NeedRIGHT();
3072  break;
3073 
3074  default:
3075  Unexpected( CurText() );
3076  }
3077  }
3078 }
3079 
3080 
3082 {
3083  T tok;
3084 
3085  /* <history_descriptor >::=
3086  (history [{<ancestor_file_descriptor> }] <self_descriptor> )
3087  */
3088 
3089  while( (tok = NextTok()) != T_RIGHT )
3090  {
3091  if( tok != T_LEFT )
3092  Expecting( T_LEFT );
3093 
3094  tok = NextTok();
3095  switch( tok )
3096  {
3097  case T_ancestor:
3098  ANCESTOR* ancestor;
3099  ancestor = new ANCESTOR( growth );
3100  growth->ancestors.push_back( ancestor );
3101  doANCESTOR( ancestor );
3102  break;
3103 
3104  case T_self:
3105  while( (tok = NextTok()) != T_RIGHT )
3106  {
3107  if( tok != T_LEFT )
3108  Expecting( T_LEFT );
3109 
3110  tok = NextTok();
3111  switch( tok )
3112  {
3113  case T_created_time:
3114  readTIME( &growth->time_stamp );
3115  NeedRIGHT();
3116  break;
3117 
3118  case T_comment:
3119  NeedSYMBOL();
3120  growth->comments.push_back( CurText() );
3121  NeedRIGHT();
3122  break;
3123 
3124  default:
3125  Unexpected( CurText() );
3126  }
3127  }
3128  break;
3129 
3130  default:
3131  Unexpected( CurText() );
3132  }
3133  }
3134 }
3135 
3136 
3138 {
3139  T tok;
3140 
3141  /* <session_file_descriptor >::=
3142  (session <session_id >
3143  (base_design <path/filename >)
3144  [<history_descriptor> ]
3145  [<session_structure_descriptor> ]
3146  [<placement_descriptor> ]
3147  [<floor_plan_descriptor> ]
3148  [<net_pin_changes_descriptor> ]
3149  [<was_is_descriptor> ]
3150  <swap_history_descriptor> ]
3151  [<route_descriptor> ]
3152  )
3153  */
3154 
3155  NeedSYMBOL();
3156  growth->session_id = CurText();
3157 
3158  while( (tok = NextTok()) != T_RIGHT )
3159  {
3160  if( tok != T_LEFT )
3161  Expecting( T_LEFT );
3162 
3163  tok = NextTok();
3164  switch( tok )
3165  {
3166  case T_base_design:
3167  NeedSYMBOL();
3168  growth->base_design = CurText();
3169  NeedRIGHT();
3170  break;
3171 
3172  case T_history:
3173  if( growth->history )
3174  Unexpected( tok );
3175  growth->history = new HISTORY( growth );
3176  doHISTORY( growth->history );
3177  break;
3178 
3179  case T_structure:
3180  if( growth->structure )
3181  Unexpected( tok );
3182  growth->structure = new STRUCTURE( growth );
3183  doSTRUCTURE( growth->structure );
3184  break;
3185 
3186  case T_placement:
3187  if( growth->placement )
3188  Unexpected( tok );
3189  growth->placement = new PLACEMENT( growth );
3190  doPLACEMENT( growth->placement );
3191  break;
3192 
3193  case T_was_is:
3194  if( growth->was_is )
3195  Unexpected( tok );
3196  growth->was_is = new WAS_IS( growth );
3197  doWAS_IS( growth->was_is );
3198  break;
3199 
3200  case T_routes:
3201  if( growth->route )
3202  Unexpected( tok );
3203  growth->route = new ROUTE( growth );
3204  doROUTE( growth->route );
3205  break;
3206 
3207  default:
3208  Unexpected( CurText() );
3209  }
3210  }
3211 }
3212 
3213 
3215 {
3216  T tok;
3217  PIN_PAIR empty( growth );
3218  PIN_PAIR* pin_pair;
3219 
3220  /* <was_is_descriptor >::=
3221  (was_is {(pins <pin_reference> <pin_reference> )})
3222  */
3223 
3224  // none of the pins is ok too
3225  while( (tok = NextTok()) != T_RIGHT )
3226  {
3227 
3228  if( tok != T_LEFT )
3229  Expecting( T_LEFT );
3230 
3231  tok = NextTok();
3232  switch( tok )
3233  {
3234  case T_pins:
3235  // copy the empty one, then fill its copy later thru pin_pair.
3236  growth->pin_pairs.push_back( empty );
3237  pin_pair= &growth->pin_pairs.back();
3238 
3239  NeedSYMBOL(); // readCOMPnPIN() expects 1st token to have been read
3240  readCOMPnPIN( &pin_pair->was.component_id, &pin_pair->was.pin_id );
3241 
3242  NeedSYMBOL(); // readCOMPnPIN() expects 1st token to have been read
3243  readCOMPnPIN( &pin_pair->is.component_id, &pin_pair->is.pin_id );
3244 
3245  NeedRIGHT();
3246  break;
3247 
3248  default:
3249  Unexpected( CurText() );
3250  }
3251  }
3252 }
3253 
3254 
3256 {
3257  T tok;
3258 
3259  /* <route_descriptor >::=
3260  (routes
3261  <resolution_descriptor>
3262  <parser_descriptor>
3263  <structure_out_descriptor>
3264  <library_out_descriptor>
3265  <network_out_descriptor>
3266  <test_points_descriptor>
3267  )
3268  */
3269 
3270  while( (tok = NextTok()) != T_RIGHT )
3271  {
3272  if( tok != T_LEFT )
3273  Expecting( T_LEFT );
3274 
3275  tok = NextTok();
3276  switch( tok )
3277  {
3278  case T_resolution:
3279  if( growth->resolution )
3280  Unexpected( tok );
3281  growth->resolution = new UNIT_RES( growth, tok );
3282  doRESOLUTION( growth->resolution );
3283  break;
3284 
3285  case T_parser:
3286  if( growth->parser )
3287  {
3288 #if 0 // Electra 2.9.1 emits two (parser ) elements in a row.
3289  // Work around their bug for now.
3290  Unexpected( tok );
3291 #else
3292  delete growth->parser;
3293 #endif
3294  }
3295  growth->parser = new PARSER( growth );
3296  doPARSER( growth->parser );
3297  break;
3298 
3299  case T_structure_out:
3300  if( growth->structure_out )
3301  Unexpected( tok );
3302  growth->structure_out = new STRUCTURE_OUT( growth );
3303  doSTRUCTURE_OUT( growth->structure_out );
3304  break;
3305 
3306  case T_library_out:
3307  if( growth->library )
3308  Unexpected( tok );
3309  growth->library = new LIBRARY( growth, tok );
3310  doLIBRARY( growth->library );
3311  break;
3312 
3313  case T_network_out:
3314  while( (tok = NextTok()) != T_RIGHT )
3315  {
3316  if( tok != T_LEFT )
3317  Expecting( T_LEFT );
3318 
3319  tok = NextTok();
3320  if( tok != T_net ) // it is class NET_OUT, but token T_net
3321  Unexpected( CurText() );
3322 
3323  NET_OUT* net_out;
3324  net_out = new NET_OUT( growth );
3325 
3326  growth->net_outs.push_back( net_out );
3327  doNET_OUT( net_out );
3328  }
3329  break;
3330 
3331  default:
3332  Unexpected( CurText() );
3333  }
3334  }
3335 }
3336 
3337 
3339 {
3340  T tok;
3341 
3342  /* <net_out_descriptor >::=
3343  (net <net_id >
3344  [(net_number <integer >)]
3345  [<rule_descriptor> ]
3346  {[<wire_shape_descriptor> | <wire_guide_descriptor> |
3347  <wire_via_descriptor> | <bond_shape_descriptor> ]}
3348  {[<supply_pin_descriptor> ]}
3349  )
3350  */
3351 
3352  NeedSYMBOLorNUMBER();
3353  growth->net_id = CurText();
3354 
3355  while( (tok = NextTok()) != T_RIGHT )
3356  {
3357  if( tok != T_LEFT )
3358  Expecting( T_LEFT );
3359 
3360  tok = NextTok();
3361  switch( tok )
3362  {
3363  case T_net_number:
3364  tok = NextTok();
3365  if( tok!= T_NUMBER )
3366  Expecting( T_NUMBER );
3367  growth->net_number = atoi( CurText() );
3368  NeedRIGHT();
3369  break;
3370 
3371  case T_rule:
3372  if( growth->rules )
3373  Unexpected( tok );
3374  growth->rules = new RULE( growth, tok );
3375  doRULE( growth->rules );
3376  break;
3377 
3378  case T_wire:
3379  WIRE* wire;
3380  wire = new WIRE( growth );
3381  growth->wires.push_back( wire );
3382  doWIRE( wire );
3383  break;
3384 
3385  case T_via:
3386  WIRE_VIA* wire_via;
3387  wire_via = new WIRE_VIA( growth );
3388  growth->wire_vias.push_back( wire_via );
3389  doWIRE_VIA( wire_via );
3390  break;
3391 
3392  case T_supply_pin:
3393  SUPPLY_PIN* supply_pin;
3394  supply_pin = new SUPPLY_PIN( growth );
3395  growth->supply_pins.push_back( supply_pin );
3396  doSUPPLY_PIN( supply_pin );
3397  break;
3398 
3399  default:
3400  Unexpected( CurText() );
3401  }
3402  }
3403 }
3404 
3405 
3407 {
3408  T tok;
3409  PIN_REF empty(growth);
3410 
3411  /* <supply_pin_descriptor >::=
3412  (supply_pin {<pin_reference> } [(net <net_id >)])
3413  */
3414 
3415  NeedSYMBOL();
3416  growth->net_id = CurText();
3417 
3418  while( (tok = NextTok()) != T_RIGHT )
3419  {
3420  if( IsSymbol(tok) )
3421  {
3422  growth->pin_refs.push_back( empty );
3423 
3424  PIN_REF* pin_ref = &growth->pin_refs.back();
3425 
3426  readCOMPnPIN( &pin_ref->component_id, &pin_ref->pin_id );
3427  }
3428  else if( tok == T_LEFT )
3429  {
3430  tok = NextTok();
3431  if( tok != T_net )
3432  Expecting( T_net );
3433  growth->net_id = CurText();
3434  NeedRIGHT();
3435  }
3436  else
3437  Unexpected( CurText() );
3438  }
3439 }
3440 
3441 
3442 void SPECCTRA_DB::ExportPCB( const wxString& aFilename, bool aNameChange )
3443 {
3444  if( m_pcb )
3445  {
3446  FILE_OUTPUTFORMATTER formatter( aFilename, wxT( "wt" ), m_quote_char[0] );
3447 
3448  if( aNameChange )
3449  m_pcb->pcbname = TO_UTF8( aFilename );
3450 
3451  m_pcb->Format( &formatter, 0 );
3452  }
3453 }
3454 
3455 
3456 void SPECCTRA_DB::ExportSESSION( const wxString& aFilename )
3457 {
3458  if( m_session )
3459  {
3460  FILE_OUTPUTFORMATTER formatter( aFilename, wxT( "wt" ), m_quote_char[0] );
3461 
3462  m_session->Format( &formatter, 0 );
3463  }
3464 }
3465 
3466 
3468 {
3469  PCB* pcb = new PCB();
3470 
3471  pcb->parser = new PARSER( pcb );
3472  pcb->resolution = new UNIT_RES( pcb, T_resolution );
3473  pcb->unit = new UNIT_RES( pcb, T_unit );
3474 
3475  pcb->structure = new STRUCTURE( pcb );
3476  pcb->structure->boundary = new BOUNDARY( pcb->structure );
3477  pcb->structure->via = new VIA( pcb->structure );
3478  pcb->structure->rules = new RULE( pcb->structure, T_rule );
3479 
3480  pcb->placement = new PLACEMENT( pcb );
3481 
3482  pcb->library = new LIBRARY( pcb );
3483 
3484  pcb->network = new NETWORK( pcb );
3485 
3486  pcb->wiring = new WIRING( pcb );
3487 
3488  return pcb;
3489 }
3490 
3491 
3492 //-----<ELEM>---------------------------------------------------------------
3493 
3494 ELEM::ELEM( T aType, ELEM* aParent ) :
3495  type( aType ),
3496  parent( aParent )
3497 {
3498 }
3499 
3500 
3502 {
3503 }
3504 
3505 const char* ELEM::Name() const
3506 {
3507  return SPECCTRA_DB::TokenName( type );
3508 }
3509 
3511 {
3512  if( parent )
3513  return parent->GetUnits();
3514 
3515  return &UNIT_RES::Default;
3516 }
3517 
3518 
3519 void ELEM::Format( OUTPUTFORMATTER* out, int nestLevel )
3520 {
3521  out->Print( nestLevel, "(%s\n", Name() );
3522 
3523  FormatContents( out, nestLevel+1 );
3524 
3525  out->Print( nestLevel, ")\n" );
3526 }
3527 
3528 
3530 {
3531  for( int i = 0; i < Length(); ++i )
3532  At(i)->Format( out, nestLevel );
3533 }
3534 
3535 
3536 int ELEM_HOLDER::FindElem( T aType, int instanceNum )
3537 {
3538  int repeats=0;
3539 
3540  for( unsigned i = 0; i < kids.size(); ++i )
3541  {
3542  if( kids[i].Type() == aType )
3543  {
3544  if( repeats == instanceNum )
3545  return i;
3546 
3547  ++repeats;
3548  }
3549  }
3550 
3551  return -1;
3552 }
3553 
3554 
3555 // a reasonably small memory price to pay for improved performance
3557 
3558 
3559 //-----<UNIT_RES>---------------------------------------------------------
3560 
3561 UNIT_RES UNIT_RES::Default( NULL, T_resolution );
3562 
3563 
3564 //-----<PADSTACK>---------------------------------------------------------
3565 
3567 {
3568  if( !lhs->hash.size() )
3569  lhs->hash = lhs->makeHash();
3570 
3571  if( !rhs->hash.size() )
3572  rhs->hash = rhs->makeHash();
3573 
3574  int result = lhs->hash.compare( rhs->hash );
3575  if( result )
3576  return result;
3577 
3578  // Via names hold the drill diameters, so we have to include those to discern
3579  // between two vias with same copper size but with different drill sizes.
3580  result = lhs->padstack_id.compare( rhs->padstack_id );
3581 
3582  return result;
3583 }
3584 
3585 
3586 //-----<IMAGE>------------------------------------------------------------
3587 
3588 int IMAGE::Compare( IMAGE* lhs, IMAGE* rhs )
3589 {
3590  if( !lhs->hash.size() )
3591  lhs->hash = lhs->makeHash();
3592 
3593  if( !rhs->hash.size() )
3594  rhs->hash = rhs->makeHash();
3595 
3596  int result = lhs->hash.compare( rhs->hash );
3597 
3598  return result;
3599 }
3600 
3601 
3602 //-----<COMPONENT>--------------------------------------------------------
3603 
3604 /*
3605 int COMPONENT::Compare( COMPONENT* lhs, COMPONENT* rhs )
3606 {
3607  if( !lhs->hash.size() )
3608  lhs->hash = lhs->makeHash();
3609 
3610  if( !rhs->hash.size() )
3611  rhs->hash = rhs->makeHash();
3612 
3613  int result = lhs->hash.compare( rhs->hash );
3614  return result;
3615 }
3616 */
3617 
3618 //-----<PARSER>-----------------------------------------------------------
3619 PARSER::PARSER( ELEM* aParent ) :
3620  ELEM( T_parser, aParent )
3621 {
3622  string_quote = '"';
3623  space_in_quoted_tokens = false;
3624 
3625  case_sensitive = false;
3626  wires_include_testpoint = false;
3627  routes_include_testpoint = false;
3628  routes_include_guides = false;
3630  via_rotate_first = true;
3631  generated_by_freeroute = false;
3632 
3633  host_cad = "KiCad's Pcbnew";
3634  wxString msg = GetBuildVersion();
3635  host_version = TO_UTF8(msg);
3636 }
3637 
3638 
3639 void PARSER::FormatContents( OUTPUTFORMATTER* out, int nestLevel )
3640 {
3641  out->Print( nestLevel, "(string_quote %c)\n", string_quote );
3642  out->Print( nestLevel, "(space_in_quoted_tokens %s)\n", space_in_quoted_tokens ? "on" : "off" );
3643  out->Print( nestLevel, "(host_cad \"%s\")\n", host_cad.c_str() );
3644  out->Print( nestLevel, "(host_version \"%s\")\n", host_version.c_str() );
3645 
3646  for( STRINGS::iterator i=constants.begin(); i!=constants.end(); )
3647  {
3648  const std::string& s1 = *i++;
3649  const std::string& s2 = *i++;
3650 
3651  const char* q1 = out->GetQuoteChar( s1.c_str() );
3652  const char* q2 = out->GetQuoteChar( s2.c_str() );
3653  out->Print( nestLevel, "(constant %s%s%s %s%s%s)\n",
3654  q1, s1.c_str(), q1,
3655  q2, s2.c_str(), q2 );
3656  }
3657 
3659  {
3660  out->Print( nestLevel, "(routes_include%s%s%s)\n",
3661  routes_include_testpoint ? " testpoint" : "",
3662  routes_include_guides ? " guides" : "",
3663  routes_include_image_conductor ? " image_conductor" : "" );
3664  }
3665 
3667  out->Print( nestLevel, "(wires_include testpoint)\n" );
3668 
3669  if( !via_rotate_first )
3670  out->Print( nestLevel, "(via_rotate_first off)\n" );
3671 
3672  if( case_sensitive )
3673  out->Print( nestLevel, "(case_sensitive %s)\n", case_sensitive ? "on" : "off" );
3674 }
3675 
3676 
3677 void PLACE::Format( OUTPUTFORMATTER* out, int nestLevel )
3678 {
3679  bool useMultiLine;
3680 
3681  const char* quote = out->GetQuoteChar( component_id.c_str() );
3682 
3683  if( place_rules || properties.size() || rules || region )
3684  {
3685  useMultiLine = true;
3686 
3687  out->Print( nestLevel, "(%s %s%s%s\n",
3688  Name(),
3689  quote, component_id.c_str(), quote );
3690 
3691  out->Print( nestLevel+1, "%s", "" );
3692  }
3693  else
3694  {
3695  useMultiLine = false;
3696 
3697  out->Print( nestLevel, "(%s %s%s%s",
3698  Name(),
3699  quote, component_id.c_str(), quote );
3700  }
3701 
3702  if( hasVertex )
3703  {
3704  out->Print( 0, " %.6f %.6f", vertex.x, vertex.y );
3705 
3706  out->Print( 0, " %s", GetTokenText( side ) );
3707 
3708  out->Print( 0, " %.6f", rotation );
3709  }
3710 
3711  const char* space = " "; // one space, as c string.
3712 
3713  if( mirror != T_NONE )
3714  {
3715  out->Print( 0, "%s(mirror %s)", space, GetTokenText( mirror ) );
3716  space = "";
3717  }
3718 
3719  if( status != T_NONE )
3720  {
3721  out->Print( 0, "%s(status %s)", space, GetTokenText( status ) );
3722  space = "";
3723  }
3724 
3725  if( logical_part.size() )
3726  {
3727  quote = out->GetQuoteChar( logical_part.c_str() );
3728  out->Print( 0, "%s(logical_part %s%s%s)", space, quote, logical_part.c_str(), quote );
3729  space = "";
3730  }
3731 
3732  if( useMultiLine )
3733  {
3734  out->Print( 0, "\n" );
3735  if( place_rules )
3736  {
3737  place_rules->Format( out, nestLevel+1 );
3738  }
3739 
3740  if( properties.size() )
3741  {
3742  out->Print( nestLevel+1, "(property \n" );
3743 
3744  for( PROPERTIES::const_iterator i = properties.begin(); i != properties.end(); ++i )
3745  i->Format( out, nestLevel+2 );
3746 
3747  out->Print( nestLevel+1, ")\n" );
3748  }
3749 
3750  if( lock_type != T_NONE )
3751  out->Print( nestLevel+1, "(lock_type %s)\n", GetTokenText(lock_type) );
3752 
3753  if( rules )
3754  rules->Format( out, nestLevel+1 );
3755 
3756  if( region )
3757  region->Format( out, nestLevel+1 );
3758 
3759  if( part_number.size() )
3760  {
3761  quote = out->GetQuoteChar( part_number.c_str() );
3762  out->Print( nestLevel+1, "(PN %s%s%s)\n", quote, part_number.c_str(), quote );
3763  }
3764  }
3765  else
3766  {
3767  if( lock_type != T_NONE )
3768  {
3769  out->Print( 0, "%s(lock_type %s)", space, GetTokenText(lock_type) );
3770  space = "";
3771  }
3772 
3773  if( part_number.size() )
3774  {
3775  quote = out->GetQuoteChar( part_number.c_str() );
3776  out->Print( 0, "%s(PN %s%s%s)", space, quote, part_number.c_str(), quote );
3777  }
3778  }
3779 
3780  out->Print( 0, ")\n" );
3781 }
3782 
3783 } // namespace DSN
3784 
3785 
3786 //EOF
DSN_T units
Definition: specctra.h:404
void LoadSESSION(const wxString &aFilename)
Function LoadSESSION is a recursive descent parser for a SPECCTRA DSN "session" file.
Definition: specctra.cpp:262
VIA corresponds to the <via_descriptor> in the specctra dsn spec.
Definition: specctra.h:1024
void doLAYER_NOISE_WEIGHT(LAYER_NOISE_WEIGHT *growth)
Definition: specctra.cpp:590
PIN_REF corresponds to the <pin_reference> definition in the specctra dsn spec.
Definition: specctra.h:2449
bool space_in_quoted_tokens
Definition: specctra.h:371
DSN_T side
Definition: specctra.h:1999
static int Compare(IMAGE *lhs, IMAGE *rhs)
Function Compare compares two objects of this type and returns <0, 0, or >0.
Definition: specctra.cpp:3588
POINT vertex[3]
Definition: specctra.h:782
std::string layer_id
Definition: specctra.h:439
std::string pin_id
Definition: specctra.h:1944
void buildLayerMaps(BOARD *aBoard)
Function buildLayerMaps creates a few data translation structures for layer name and number mapping b...
Definition: specctra.cpp:74
void doKEEPOUT(KEEPOUT *growth)
Definition: specctra.cpp:787
DSN_T fromto_type
Definition: specctra.h:2490
DSN_T lock_type
Definition: specctra.h:1696
double aperture_width
Definition: specctra.h:781
std::string shield
Definition: specctra.h:2890
RULE * rules
Definition: specctra.h:2130
ELEM(DSN_T aType, ELEM *aParent=0)
Definition: specctra.cpp:3494
STRINGS placement_ids
Definition: specctra.h:2560
DSN_T attr
Definition: specctra.h:2889
NET corresponds to a <net_descriptor> in the DSN spec.
Definition: specctra.h:2591
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:342
This source file implements export and import capabilities to the specctra dsn file format.
Definition: specctra.cpp:62
COPPER_PLANES planes
Definition: specctra.h:1558
PIN_PAIRS pin_pairs
Definition: specctra.h:3533
CLASSES * classes
Definition: specctra.h:1113
void doCLASS_CLASS(CLASS_CLASS *growth)
Definition: specctra.cpp:1582
STRINGS circuit
circuit descriptor list
Definition: specctra.h:2756
STRINGS comments
Definition: specctra.h:3299
void doGRID(GRID *growth)
Definition: specctra.cpp:1650
double y
Definition: specctra.h:96
std::string net_id
Definition: specctra.h:2595
bool via_rotate_first
Definition: specctra.h:377
DSN_T direction
T_x | T_y | -1 for both.
Definition: specctra.h:1469
UNIT_RES * unit
Definition: specctra.h:3123
FROMTOS fromtos
Definition: specctra.h:2616
void doWIRE(WIRE *growth)
Definition: specctra.cpp:2760
STRINGS padstacks
Definition: specctra.h:1028
KEEPOUTS keepouts
Definition: specctra.h:2012
std::string component_id
Definition: specctra.h:2451
void doCONTROL(CONTROL *growth)
Definition: specctra.cpp:1189
PIN_REFS pin_refs
Definition: specctra.h:3343
RULE * rules
Definition: specctra.h:1554
void doROUTE(ROUTE *growth)
Definition: specctra.cpp:3255
STRINGS class_ids
Definition: specctra.h:1090
Struct PIN_PAIR is used within the WAS_IS class below to hold a pair of PIN_REFs and corresponds to t...
Definition: specctra.h:3511
void Format(OUTPUTFORMATTER *out, int nestLevel) override
Function Format writes this object as ASCII out to an OUTPUTFORMATTER according to the SPECCTRA DSN f...
Definition: specctra.h:3598
PINS pins
Definition: specctra.h:2007
SESSION corresponds to the <session_file_descriptor> in the specctra dsn spec.
Definition: specctra.h:3559
void doTOKPROP(TOKPROP *growth)
Definition: specctra.cpp:1147
NET_OUTS net_outs
Definition: specctra.h:3448
void doLAYER(LAYER *growth)
Definition: specctra.cpp:1259
double offset
Definition: specctra.h:1470
ELEM * shape
Definition: specctra.h:914
void doSPECCTRA_LAYER_PAIR(SPECCTRA_LAYER_PAIR *growth)
Definition: specctra.cpp:574
RULE * rules
Definition: specctra.h:2492
std::string base_design
Definition: specctra.h:3564
static int Compare(PADSTACK *lhs, PADSTACK *rhs)
Function Compare compares two objects of this type and returns <0, 0, or >0.
Definition: specctra.cpp:3566
const char * Name() const
Definition: specctra.cpp:3505
void doPROPERTIES(PROPERTIES *growth)
Definition: specctra.cpp:1236
std::string part_number
Definition: specctra.h:1703
std::string net_id
Definition: specctra.h:3344
void Format(OUTPUTFORMATTER *out, int nestLevel) override
Function Format writes this object as ASCII out to an OUTPUTFORMATTER according to the SPECCTRA DSN f...
Definition: specctra.h:501
void doSTRUCTURE_OUT(STRUCTURE_OUT *growth)
Definition: specctra.cpp:744
RULE * rules
Definition: specctra.h:2612
bool routes_include_testpoint
Definition: specctra.h:374
void doNET(NET *growth)
Definition: specctra.cpp:2323
std::string logical_part
Definition: specctra.h:1690
RULE * rules
Definition: specctra.h:902
virtual void FormatContents(OUTPUTFORMATTER *out, int nestLevel)
Function FormatContents writes the contents as ASCII out to an OUTPUTFORMATTER according to the SPECC...
Definition: specctra.h:263
UNIT_RES * unit
Definition: specctra.h:1544
void doPLACE(PLACE *growth)
Definition: specctra.cpp:1740
POINTS vertexes
Definition: specctra.h:2988
void doVIA(VIA *growth)
Definition: specctra.cpp:1160
UNIT_RES is a holder for either a T_unit or T_resolution object which are usually mutually exclusive ...
Definition: specctra.h:400
DSN_T type
T_fix | T_normal.
Definition: specctra.h:2608
UNIT_RES * unit
Definition: specctra.h:2121
UNIT_RES * resolution
Definition: specctra.h:3167
STRINGS m_layerIds
indexed by PCB layer number
Definition: specctra.h:3646
An interface used to output 8 bit text in a convenient way.
Definition: richio.h:306
UNIT_RES * unit
Definition: specctra.h:2255
void doRESOLUTION(UNIT_RES *growth)
Definition: specctra.cpp:526
void doWIRING(WIRING *growth)
Definition: specctra.cpp:2987
CLASS corresponds to the <class_descriptor> in the specctra spec.
Definition: specctra.h:2747
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition: macros.h:83
void doREGION(REGION *growth)
Definition: specctra.cpp:1513
PLACES places
Definition: specctra.h:1761
double x
Definition: specctra.h:95
int direction
Definition: specctra.h:1192
STRUCTURE * structure
Definition: specctra.h:3567
std::string via_id
Definition: specctra.h:2128
ELEM * parent
Definition: specctra.h:199
void SetPCB(PCB *aPcb)
Function SetPCB deletes any existing PCB and replaces it with the given one.
Definition: specctra.h:3904
void SetRotation(double aRotation)
Definition: specctra.h:1959
STRUCTURE * structure
Definition: specctra.h:3169
virtual ~ELEM()
Definition: specctra.cpp:3501
void doCOMPONENT(COMPONENT *growth)
Definition: specctra.cpp:1855
PIN_REFS noexpose
Definition: specctra.h:2603
COMP_ORDER * comp_order
Definition: specctra.h:2618
RULE * rules
Definition: specctra.h:1423
A name/value tuple with unique names and optional values.
Definition: properties.h:33
WIRING * wiring
Definition: specctra.h:3173
PIN_REF was
Definition: specctra.h:3519
WAS_IS corresponds to the <was_is_descriptor> in the specctra dsn spec.
Definition: specctra.h:3529
static PCB * MakePCB()
Function MakePCB makes a PCB with all the default ELEMs and parts on the heap.
Definition: specctra.cpp:3467
std::string net_id
Definition: specctra.h:2989
DSN_T grid_type
T_via | T_wire | T_via_keepout | T_place | T_snap.
Definition: specctra.h:1467
std::string class_id
Definition: specctra.h:2751
void doIMAGE(IMAGE *growth)
Definition: specctra.cpp:2126
int cost_type
T_length | T_way.
Definition: specctra.h:1194
IMAGES images
Definition: specctra.h:2256
STRUCTURE_OUT * structure_out
Definition: specctra.h:3446
DSN_T image_type
Definition: specctra.h:1471
std::string layer_id
Definition: specctra.h:582
PIN_REF is
Definition: specctra.h:3520
BOUNDARY * place_boundary
Definition: specctra.h:1551
bool supply
Definition: specctra.h:2893
time_t time_stamp
Definition: specctra.h:3298
DSN_T via_type
Definition: specctra.h:2991
DSN_T status
Definition: specctra.h:1688
RULE corresponds to the <rule_descriptor> in the specctra dsn spec.
Definition: specctra.h:488
void SetVertex(const POINT &aVertex)
Definition: specctra.h:1733
RECTANGLE * rectangle
Definition: specctra.h:1415
std::string makeHash()
Function makeHash returns a string which uniquely represents this ELEM amoung other ELEMs of the same...
Definition: specctra.h:211
CONTROL * control
Definition: specctra.h:1553
This file contains miscellaneous commonly used macros and functions.
void doLIBRARY(LIBRARY *growth)
Definition: specctra.cpp:2269
void doANCESTOR(ANCESTOR *growth)
Definition: specctra.cpp:3043
STRINGS layer_ids
Definition: specctra.h:534
POINT vertex
Definition: specctra.h:1685
void doWINDOW(WINDOW *growth)
Definition: specctra.cpp:913
void SetSESSION(SESSION *aSession)
Function SetSESSION deletes any existing SESSION and replaces it with the given one.
Definition: specctra.h:3915
int findLayerName(const std::string &aLayerName) const
Function findLayerName returns the PCB layer index for a given layer name, within the specctra sessio...
Definition: specctra.cpp:124
void doRULE(RULE *growth)
Definition: specctra.cpp:1381
PATH supports both the <path_descriptor> and the <polygon_descriptor> per the specctra dsn spec.
Definition: specctra.h:578
bool unassigned
Definition: specctra.h:2596
int turret
Definition: specctra.h:2887
COMP_ORDER corresponds to the <component_order_descriptor>.
Definition: specctra.h:2556
FROMTOS fromtos
Definition: specctra.h:2722
double rotation
Definition: specctra.h:1682
bool hasVertex
Definition: specctra.h:1684
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:96
ELEM * shape
Definition: specctra.h:2884
DSN_T layer_type
one of: T_signal, T_power, T_mixed, T_jumper
Definition: specctra.h:1191
void FormatContents(OUTPUTFORMATTER *out, int nestLevel) override
Function FormatContents writes the contents as ASCII out to an OUTPUTFORMATTER according to the SPECC...
Definition: specctra.cpp:3639
void doCOMP_ORDER(COMP_ORDER *growth)
Definition: specctra.cpp:2656
std::string comment
Definition: specctra.h:3254
ANCESTORS ancestors
Definition: specctra.h:3297
WIRES wires
Definition: specctra.h:3124
RULE * place_rules
Definition: specctra.h:1563
PCB_LAYER_ID
A quick note on layer IDs:
A LINE_READER that reads from an open file.
Definition: richio.h:172
POINT point0
one of two opposite corners
Definition: specctra.h:441
std::vector< int > m_kicadLayer2pcb
maps BOARD layer number to PCB layer numbers
Definition: specctra.h:3648
LAYER_RULES layer_rules
Definition: specctra.h:2494
std::string image_id
Definition: specctra.h:1998
int net_number
Definition: specctra.h:2597
std::string name
Definition: specctra.h:1190
WIRES wires
Definition: specctra.h:3394
PIN_REFS terminator
Definition: specctra.h:2606
std::string net_id
Definition: specctra.h:2491
#define NULL
TOKPROP is a container for a single property whose value is another DSN_T token.
Definition: specctra.h:1355
std::string session_id
Definition: specctra.h:3563
PARSER(ELEM *aParent)
Definition: specctra.cpp:3619
void Format(OUTPUTFORMATTER *out, int nestLevel) override
Function Format writes this object as ASCII out to an OUTPUTFORMATTER according to the SPECCTRA DSN f...
Definition: specctra.h:3202
std::string host_version
Definition: specctra.h:384
RULE * place_rules
Definition: specctra.h:2010
void doCLASS(CLASS *growth)
Definition: specctra.cpp:2501
DSN_T rotate
Definition: specctra.h:2125
COPPER_PLANE corresponds to a <plane_descriptor> in the specctra dsn spec.
Definition: specctra.h:1338
wxString GetBuildVersion()
Get the full KiCad version string.
DSN_T attach
Definition: specctra.h:2127
bool routes_include_image_conductor
Definition: specctra.h:376
std::string padstack_id
Definition: specctra.h:2987
void doPADSTACK(PADSTACK *growth)
Definition: specctra.cpp:1940
RULE * rules
Definition: specctra.h:3393
DSN_T side
Definition: specctra.h:1680
void doPATH(PATH *growth)
Definition: specctra.cpp:1014
PLACE implements the <placement_reference> in the specctra dsn spec.
Definition: specctra.h:1674
void doSUPPLY_PIN(SUPPLY_PIN *growth)
Definition: specctra.cpp:3406
LAYER_NOISE_WEIGHT * layer_noise_weight
Definition: specctra.h:1548
void doRECTANGLE(RECTANGLE *growth)
Definition: specctra.cpp:1062
bool via_at_smd
Definition: specctra.h:1152
void doHISTORY(HISTORY *growth)
Definition: specctra.cpp:3081
PROPERTIES properties
Definition: specctra.h:1694
PARSER * parser
Definition: specctra.h:3445
DSN_T connect
Definition: specctra.h:1882
PIN_REFS expose
Definition: specctra.h:2602
LIBRARY * library
Definition: specctra.h:3447
std::string hash
a hash string used by Compare(), not Format()ed/exported.
Definition: specctra.h:2118
void readTIME(time_t *time_stamp)
Function readTIME reads a <time_stamp> which consists of 8 lexer tokens: "month date hour : minute : ...
Definition: specctra.cpp:177
ELEM_ARRAY kids
ELEM pointers.
Definition: specctra.h:286
RULE * place_rules
Definition: specctra.h:1692
PATH * polygon
Definition: specctra.h:1416
std::string filename
Definition: specctra.h:3253
SUPPLY_PINS supply_pins
Definition: specctra.h:3396
std::string region_id
Definition: specctra.h:1412
std::string image_id
Definition: specctra.h:1760
void AddPadstack(PADSTACK *aPadstack)
Definition: specctra.h:2274
std::string component_id
reference designator
Definition: specctra.h:1678
PADSTACK holds either a via or a pad definition.
Definition: specctra.h:2114
void Append(ELEM *aElem)
Definition: specctra.h:320
WIRE_VIAS wire_vias
Definition: specctra.h:3125
std::string fromText
Definition: specctra.h:2487
PIN_REFS load
Definition: specctra.h:2605
WIRE_VIAS wire_vias
Definition: specctra.h:3395
POINT vertex
Definition: specctra.h:735
CLASSLIST classes
Definition: specctra.h:2838
REGIONS regions
Definition: specctra.h:1561
void doPCB(PCB *growth)
Definition: specctra.cpp:282
WINDOWS windows
Definition: specctra.h:2891
RECTANGLE * rectangle
Definition: specctra.h:660
RULE * rules
Definition: specctra.h:1699
void doSTRUCTURE(STRUCTURE *growth)
Definition: specctra.cpp:610
void doCLASSES(CLASSES *growth)
Definition: specctra.cpp:1627
double dimension
Definition: specctra.h:1468
std::string layer_id
Definition: specctra.h:732
std::string padstack_id
Definition: specctra.h:1941
std::string layer_id
Definition: specctra.h:780
UNIT_RES * resolution
Definition: specctra.h:3444
void doWIRE_VIA(WIRE_VIA *growth)
Definition: specctra.cpp:2883
virtual void Format(OUTPUTFORMATTER *out, int nestLevel)
Function Format writes this object as ASCII out to an OUTPUTFORMATTER according to the SPECCTRA DSN f...
Definition: specctra.cpp:3519
DSN_T type
Definition: specctra.h:198
PARSER * parser
Definition: specctra.h:3166
void doCIRCLE(CIRCLE *growth)
Definition: specctra.cpp:1087
static const char * GetQuoteChar(const char *wrapee, const char *quote_char)
Perform quote character need determination according to the Specctra DSN specification.
Definition: richio.cpp:331
This item represents a net.
void SetRotation(double aRotation)
Definition: specctra.h:1740
int LAYER_NUM
This can be replaced with int and removed.
LIBRARY * library
Definition: specctra.h:3171
DSN_T flip_style
Definition: specctra.h:1808
SHAPE corresponds to the "(shape ..)" element in the specctra dsn spec.
Definition: specctra.h:1878
PLACEMENT * placement
Definition: specctra.h:3568
LAYER_RULES layer_rules
Definition: specctra.h:2614
void doSTRINGPROP(STRINGPROP *growth)
Definition: specctra.cpp:1139
void doPIN(PIN *growth)
Definition: specctra.cpp:2222
STRINGS spares
Definition: specctra.h:1029
time_t time_stamp
Definition: specctra.h:3255
COMP_ORDERS comp_orders
Definition: specctra.h:2724
void LoadPCB(const wxString &aFilename)
Function LoadPCB is a recursive descent parser for a SPECCTRA DSN "design" file.
Definition: specctra.cpp:243
RULE * rules
Definition: specctra.h:1195
bool case_sensitive
Definition: specctra.h:372
void doTOPOLOGY(TOPOLOGY *growth)
Definition: specctra.cpp:2463
COMPONENT implements the <component_descriptor> in the specctra dsn spec.
Definition: specctra.h:1754
LIBRARY corresponds to the <library_descriptor> in the specctra dsn specification.
Definition: specctra.h:2251
STRINGS constants
This holds pairs of strings, one pair for each constant definition.
Definition: specctra.h:381
std::vector< PCB_LAYER_ID > m_pcbLayer2kicad
maps PCB layer number to BOARD layer numbers
Definition: specctra.h:3649
char string_quote
Definition: specctra.h:370
Struct POINT is a holder for a point in the SPECCTRA DSN coordinate system.
Definition: specctra.h:93
std::string host_cad
Definition: specctra.h:383
#define FIRST_LAYER
POINT point1
Definition: specctra.h:442
UNIT_RES * unit
Definition: specctra.h:1806
WIRE corresponds to <wire_shape_descriptor> in the specctra dsn spec.
Definition: specctra.h:2873
std::vector< PIN_REF > PIN_REFS
Definition: specctra.h:2480
PATHS paths
Definition: specctra.h:659
STRINGS contact_layers
Definition: specctra.h:2994
void ExportPCB(const wxString &aFilename, bool aNameChange=false)
Function ExportPCB writes the internal PCB instance out as a SPECTRA DSN format file.
Definition: specctra.cpp:3442
int net_number
Definition: specctra.h:3392
DSN_T value
Definition: specctra.h:1359
DSN_T aperture_type
Definition: specctra.h:586
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:190
int sequence_number
Definition: specctra.h:901
DSN_T Type() const
Definition: specctra.h:230
POINTS points
Definition: specctra.h:585
int FindElem(DSN_T aType, int instanceNum=0)
Function FindElem finds a particular instance number of a given type of ELEM.
Definition: specctra.cpp:3536
static UNIT_RES Default
A static instance which holds the default units of T_inch and 2540000.
Definition: specctra.h:413
PLACEMENT * placement
Definition: specctra.h:3170
void doSHAPE(SHAPE *growth)
Definition: specctra.cpp:2040
STRINGPROP is a container for a single property whose value is a string.
Definition: specctra.h:1384
LAYER_RULES layer_rules
Definition: specctra.h:2760
void readCOMPnPIN(std::string *component_id, std::string *pid_id)
Function readCOMPnPIN reads a <pin_reference> and splits it into the two parts which are on either si...
Definition: specctra.cpp:134
RULE * rules
Definition: specctra.h:2758
UNIT_RES * unit
Definition: specctra.h:2000
int GetCopperLayerCount() const
Definition: board.cpp:435
void doLAYER_RULE(LAYER_RULE *growth)
Definition: specctra.cpp:1715
bool routes_include_guides
Definition: specctra.h:375
virtual void FormatContents(OUTPUTFORMATTER *out, int nestLevel) override
Function FormatContents writes the contents as ASCII out to an OUTPUTFORMATTER according to the SPECC...
Definition: specctra.cpp:3529
SESSION * m_session
Definition: specctra.h:3638
static bool empty(const wxTextEntryBase *aCtrl)
RULE * rules
Definition: specctra.h:2009
double aperture_width
Definition: specctra.h:583
REGION * region
Definition: specctra.h:1700
BOUNDARY * boundary
Definition: specctra.h:1550
DSN_T mirror
Definition: specctra.h:1687
std::string padstack_id
Definition: specctra.h:2120
const char * GetTokenText(T aTok)
Function GetTokenText is in the DSN namespace and returns the C string representing a SPECCTRA_DB::ke...
Definition: specctra.cpp:69
Used for text file output.
Definition: richio.h:453
ROUTE * route
Definition: specctra.h:3570
NET_OUT corresponds to the <net_out_descriptor> of the specctra dsn spec.
Definition: specctra.h:3387
UNIT_RES * unit
Definition: specctra.h:3168
virtual UNIT_RES * GetUnits() const
Function GetUnits returns the units for this section.
Definition: specctra.cpp:3510
STRINGS use_net
Definition: specctra.h:1196
ELEM * shape
Definition: specctra.h:846
void doPLACEMENT(PLACEMENT *growth)
Definition: specctra.cpp:1885
int cost
[forbidden | high | medium | low | free | <positive_integer> | -1]
Definition: specctra.h:1193
void Format(OUTPUTFORMATTER *out, int nestLevel) override
Function Format writes this object as ASCII out to an OUTPUTFORMATTER according to the SPECCTRA DSN f...
Definition: specctra.cpp:3677
LAYERS layers
Definition: specctra.h:1546
PIN_REFS pins
Definition: specctra.h:2600
ELEM * At(int aIndex) const
Definition: specctra.h:342
WIRE_VIA corresponds to <wire_via_descriptor> in the specctra dsn spec.
Definition: specctra.h:2983
void doNETWORK(NETWORK *growth)
Definition: specctra.cpp:2611
std::string value
Definition: specctra.h:1388
TOPOLOGY * topology
Definition: specctra.h:2762
void doNET_OUT(NET_OUT *growth)
Definition: specctra.cpp:3338
PIN_REFS source
Definition: specctra.h:2604
ELEM is a base class for any DSN element class.
Definition: specctra.h:193
std::string virtual_pin_name
Definition: specctra.h:2993
std::string pin_id
Definition: specctra.h:2452
WINDOWS windows
Definition: specctra.h:905
DSN_T wire_type
Definition: specctra.h:2888
int PRINTF_FUNC Print(int nestLevel, const char *fmt,...)
Format and write text to the output stream.
Definition: richio.cpp:408
WINDOWS windows
Definition: specctra.h:1893
CONNECT * connect
Definition: specctra.h:2892
bool wires_include_testpoint
Definition: specctra.h:373
void doCONNECT(CONNECT *growth)
Definition: specctra.cpp:878
PROPERTIES properties
Definition: specctra.h:1198
STRINGS net_ids
Definition: specctra.h:2753
SUPPLY_PIN corresponds to the <supply_pin_descriptor> in the specctra dsn spec.
Definition: specctra.h:3339
void ExportSESSION(const wxString &aFilename)
Function ExportSESSION writes the internal SESSION instance out as a SPECTRA DSN format file.
Definition: specctra.cpp:3456
std::string hash
a hash string used by Compare(), not Format()ed/exported.
Definition: specctra.h:1996
DSN_T absolute
Definition: specctra.h:2126
std::string pcbname
Definition: specctra.h:3165
KEEPOUT is used for <keepout_descriptor> and <plane_descriptor>.
Definition: specctra.h:895
void doQARC(QARC *growth)
Definition: specctra.cpp:1115
std::string name
Definition: specctra.h:900
NETWORK * network
Definition: specctra.h:3172
void doSESSION(SESSION *growth)
Definition: specctra.cpp:3137
Implement an OUTPUTFORMATTER to a memory buffer.
Definition: richio.h:411
HISTORY * history
Definition: specctra.h:3566
void doPARSER(PARSER *growth)
Definition: specctra.cpp:387
int Length() const
Function Length returns the number of ELEMs in this ELEM.
Definition: specctra.h:315
RULE * place_rules
Definition: specctra.h:903
WAS_IS * was_is
Definition: specctra.h:3569
std::string toText
Definition: specctra.h:2488
PARSER is simply a configuration record per the SPECCTRA DSN file spec.
Definition: specctra.h:366
void doFROMTO(FROMTO *growth)
Definition: specctra.cpp:2674
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:905
COMPONENTS components
Definition: specctra.h:1810
WIRING corresponds to <wiring_descriptor> in the specctra dsn spec.
Definition: specctra.h:3119
void doUNIT(UNIT_RES *growth)
Definition: specctra.cpp:553
std::string net_id
Definition: specctra.h:3391
std::string net_id
Definition: specctra.h:2886
POINT vertex
Definition: specctra.h:1945
static STRING_FORMATTER sf
Definition: specctra.h:221
std::string m_quote_char
Definition: specctra.h:3640
void doWAS_IS(WAS_IS *growth)
Definition: specctra.cpp:3214
SPECCTRA_LAYER_PAIRS layer_pairs
Definition: specctra.h:1313
void doBOUNDARY(BOUNDARY *growth)
Definition: specctra.cpp:967
double diameter
Definition: specctra.h:734
STRINGS rules
rules are saved in std::string form.
Definition: specctra.h:492
bool generated_by_freeroute
Definition: specctra.h:378
DSN_T pins_type
T_pins | T_order, type of field 'pins' below.
Definition: specctra.h:2599
KEEPOUTS keepouts
Definition: specctra.h:1556