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