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