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  // Fall through
846  case T_path:
847  case T_polygon:
848  if( growth->shape )
849  Unexpected( tok );
850  growth->shape = new PATH( growth, tok );
851  doPATH( (PATH*) growth->shape );
852  break;
853 
854  case T_qarc:
855  if( growth->shape )
856  Unexpected( tok );
857  growth->shape = new QARC( growth );
858  doQARC( (QARC*) growth->shape );
859  break;
860 
861  case T_window:
862  WINDOW* window;
863  window = new WINDOW( growth );
864  growth->windows.push_back( window );
865  doWINDOW( window );
866  break;
867 
868  default:
869  Unexpected( CurText() );
870  }
871 
872  tok = NextTok();
873  }
874 }
875 
876 
878 {
879  /* from page 143 of specctra spec:
880 
881  (connect
882  {(terminal <object_type> [<pin_reference> ])}
883  )
884  */
885 
886  T tok = NextTok();
887 
888  while( tok != T_RIGHT )
889  {
890  if( tok!=T_LEFT )
891  Expecting( T_LEFT );
892 
893  tok = NextTok();
894 
895  switch( tok )
896  {
897  case T_terminal:
898  // since we do not use the terminal information, simlpy toss it.
899  while( ( tok = NextTok() ) != T_RIGHT && tok != T_EOF )
900  ;
901  break;
902 
903  default:
904  Unexpected( CurText() );
905  }
906 
907  tok = NextTok();
908  }
909 }
910 
911 
913 {
914  T tok = NextTok();
915 
916  while( tok != T_RIGHT )
917  {
918  if( tok!=T_LEFT )
919  Expecting( T_LEFT );
920 
921  tok = NextTok();
922  switch( tok )
923  {
924  case T_rect:
925  if( growth->shape )
926  Unexpected( tok );
927  growth->shape = new RECTANGLE( growth );
928  doRECTANGLE( (RECTANGLE*) growth->shape );
929  break;
930 
931  case T_circle:
932  if( growth->shape )
933  Unexpected( tok );
934  growth->shape = new CIRCLE( growth );
935  doCIRCLE( (CIRCLE*) growth->shape );
936  break;
937 
938  case T_polyline_path:
939  tok = T_path;
940  // Fall through
941  case T_path:
942  case T_polygon:
943  if( growth->shape )
944  Unexpected( tok );
945  growth->shape = new PATH( growth, tok );
946  doPATH( (PATH*) growth->shape );
947  break;
948 
949  case T_qarc:
950  if( growth->shape )
951  Unexpected( tok );
952  growth->shape = new QARC( growth );
953  doQARC( (QARC*) growth->shape );
954  break;
955 
956  default:
957  Unexpected( CurText() );
958  }
959 
960  tok = NextTok();
961  }
962 }
963 
964 
966 {
967  T tok = NextTok();
968 
969  if( tok != T_LEFT )
970  Expecting( T_LEFT );
971 
972  tok = NextTok();
973  if( tok == T_rect )
974  {
975  if( growth->paths.size() )
976  Unexpected( "rect when path already encountered" );
977 
978  growth->rectangle = new RECTANGLE( growth );
979  doRECTANGLE( growth->rectangle );
980  NeedRIGHT();
981  }
982  else if( tok == T_path )
983  {
984  if( growth->rectangle )
985  Unexpected( "path when rect already encountered" );
986 
987  for(;;)
988  {
989  if( tok != T_path )
990  Expecting( T_path );
991 
992  PATH* path = new PATH( growth, T_path );
993  growth->paths.push_back( path );
994 
995  doPATH( path );
996 
997  tok = NextTok();
998  if( tok == T_RIGHT )
999  break;
1000 
1001  if( tok != T_LEFT )
1002  Expecting(T_LEFT);
1003 
1004  tok = NextTok();
1005  }
1006  }
1007  else
1008  Expecting( "rect|path" );
1009 }
1010 
1011 
1012 void SPECCTRA_DB::doPATH( PATH* growth )
1013 {
1014  T tok = NextTok();
1015 
1016  if( !IsSymbol( tok ) && tok != T_NUMBER ) // a layer name can be like a number like +12
1017  Expecting( "layer_id" );
1018 
1019  growth->layer_id = CurText();
1020 
1021  if( NextTok() != T_NUMBER )
1022  Expecting( "aperture_width" );
1023 
1024  growth->aperture_width = strtod( CurText(), NULL );
1025 
1026  POINT ptTemp;
1027 
1028  tok = NextTok();
1029 
1030  do
1031  {
1032  if( tok != T_NUMBER )
1033  Expecting( T_NUMBER );
1034  ptTemp.x = strtod( CurText(), NULL );
1035 
1036  if( NextTok() != T_NUMBER )
1037  Expecting( T_NUMBER );
1038  ptTemp.y = strtod( CurText(), NULL );
1039 
1040  growth->points.push_back( ptTemp );
1041 
1042  } while( (tok = NextTok())!=T_RIGHT && tok!=T_LEFT );
1043 
1044  if( tok == T_LEFT )
1045  {
1046  if( NextTok() != T_aperture_type )
1048 
1049  tok = NextTok();
1050  if( tok!=T_round && tok!=T_square )
1051  Expecting( "round|square" );
1052 
1053  growth->aperture_type = tok;
1054 
1055  NeedRIGHT();
1056  }
1057 }
1058 
1059 
1061 {
1062  NeedSYMBOL();
1063  growth->layer_id = CurText();
1064 
1065  if( NextTok() != T_NUMBER )
1066  Expecting( T_NUMBER );
1067  growth->point0.x = strtod( CurText(), NULL );
1068 
1069  if( NextTok() != T_NUMBER )
1070  Expecting( T_NUMBER );
1071  growth->point0.y = strtod( CurText(), NULL );
1072 
1073  if( NextTok() != T_NUMBER )
1074  Expecting( T_NUMBER );
1075  growth->point1.x = strtod( CurText(), NULL );
1076 
1077  if( NextTok() != T_NUMBER )
1078  Expecting( T_NUMBER );
1079  growth->point1.y = strtod( CurText(), NULL );
1080 
1081  NeedRIGHT();
1082 }
1083 
1084 
1086 {
1087  T tok;
1088 
1090  growth->layer_id = CurText();
1091 
1092  if( NextTok() != T_NUMBER )
1093  Expecting( T_NUMBER );
1094  growth->diameter = strtod( CurText(), 0 );
1095 
1096  tok = NextTok();
1097  if( tok == T_NUMBER )
1098  {
1099  growth->vertex.x = strtod( CurText(), 0 );
1100 
1101  if( NextTok() != T_NUMBER )
1102  Expecting( T_NUMBER );
1103  growth->vertex.y = strtod( CurText(), 0 );
1104 
1105  tok = NextTok();
1106  }
1107 
1108  if( tok != T_RIGHT )
1109  Expecting( T_RIGHT );
1110 }
1111 
1112 
1113 void SPECCTRA_DB::doQARC( QARC* growth )
1114 {
1115  NeedSYMBOL();
1116  growth->layer_id = CurText();
1117 
1118  if( NextTok() != T_NUMBER )
1119  Expecting( T_NUMBER );
1120  growth->aperture_width = strtod( CurText(), 0 );
1121 
1122  for( int i=0; i<3; ++i )
1123  {
1124  if( NextTok() != T_NUMBER )
1125  Expecting( T_NUMBER );
1126  growth->vertex[i].x = strtod( CurText(), 0 );
1127 
1128  if( NextTok() != T_NUMBER )
1129  Expecting( T_NUMBER );
1130  growth->vertex[i].y = strtod( CurText(), 0 );
1131  }
1132 
1133  NeedRIGHT();
1134 }
1135 
1136 
1138 {
1139  NeedSYMBOL();
1140  growth->value = CurText();
1141  NeedRIGHT();
1142 }
1143 
1144 
1146 {
1147  T tok = NextTok();
1148 
1149  if( tok<0 )
1150  Unexpected( CurText() );
1151 
1152  growth->value = tok;
1153 
1154  NeedRIGHT();
1155 }
1156 
1157 
1158 void SPECCTRA_DB::doVIA( VIA* growth )
1159 {
1160  T tok;
1161 
1162  while( (tok = NextTok()) != T_RIGHT )
1163  {
1164  if( tok == T_LEFT )
1165  {
1166  if( NextTok() != T_spare )
1167  Expecting( T_spare );
1168 
1169  while( (tok = NextTok()) != T_RIGHT )
1170  {
1171  if( !IsSymbol( tok ) )
1172  Expecting( T_SYMBOL );
1173 
1174  growth->spares.push_back( CurText() );
1175  }
1176  }
1177  else if( IsSymbol( tok ) )
1178  {
1179  growth->padstacks.push_back( CurText() );
1180  }
1181  else
1182  Unexpected( CurText() );
1183  }
1184 }
1185 
1186 
1188 {
1189  T tok;
1190 
1191  while( (tok = NextTok()) != T_RIGHT )
1192  {
1193  if( tok != T_LEFT )
1194  Expecting( T_LEFT );
1195 
1196  tok = NextTok();
1197  switch( tok )
1198  {
1199  case T_via_at_smd:
1200  tok = NextTok();
1201  if( tok!=T_on && tok!=T_off )
1202  Expecting( "on|off" );
1203  growth->via_at_smd = (tok==T_on);
1204  NeedRIGHT();
1205  break;
1206 
1207  case T_off_grid:
1210  case T_same_net_checking:
1212  case T_noise_calculation:
1213  case T_noise_accumulation:
1215  case T_bbv_ctr2ctr:
1216  case T_average_pair_length:
1217  case T_crosstalk_model:
1218  case T_roundoff_rotation:
1219  case T_microvia:
1220  case T_reroute_order_viols:
1221  TOKPROP* tokprop;
1222  tokprop = new TOKPROP( growth, tok );
1223  growth->Append( tokprop );
1224  doTOKPROP( tokprop );
1225  break;
1226 
1227  default:
1228  Unexpected( CurText() );
1229  }
1230  }
1231 }
1232 
1233 
1235 {
1236  T tok;
1237  PROPERTY property; // construct it once here, append multiple times.
1238 
1239  while( (tok = NextTok()) != T_RIGHT )
1240  {
1241  if( tok != T_LEFT )
1242  Expecting( T_LEFT );
1243 
1245  property.name = CurText();
1246 
1248  property.value = CurText();
1249 
1250  growth->push_back( property );
1251 
1252  NeedRIGHT();
1253  }
1254 }
1255 
1256 
1258 {
1259  T tok = NextTok();
1260 
1261  if( !IsSymbol(tok) )
1263 
1264  growth->name = CurText();
1265 
1266  while( (tok = NextTok()) != T_RIGHT )
1267  {
1268  if( tok != T_LEFT )
1269  Expecting( T_LEFT );
1270 
1271  tok = NextTok();
1272  switch( tok )
1273  {
1274  case T_type:
1275  tok = NextTok();
1276  if( tok!=T_signal && tok!=T_power && tok!=T_mixed && tok!=T_jumper )
1277  Expecting( "signal|power|mixed|jumper" );
1278  growth->layer_type = tok;
1279  if( NextTok()!=T_RIGHT )
1280  Expecting(T_RIGHT);
1281  break;
1282 
1283  case T_rule:
1284  growth->rules = new RULE( growth, T_rule );
1285  doRULE( growth->rules );
1286  break;
1287 
1288  case T_property:
1289  doPROPERTIES( &growth->properties );
1290  break;
1291 
1292  case T_direction:
1293  tok = NextTok();
1294  switch( tok )
1295  {
1296  case T_horizontal:
1297  case T_vertical:
1298  case T_orthogonal:
1299  case T_positive_diagonal:
1300  case T_negative_diagonal:
1301  case T_diagonal:
1302  case T_off:
1303  growth->direction = tok;
1304  break;
1305  default:
1306  // the spec has an example show an abbreviation of the "horizontal" keyword. Ouch.
1307  if( !strcmp( "hori", CurText() ) )
1308  {
1309  growth->direction = T_horizontal;
1310  break;
1311  }
1312  else if( !strcmp( "vert", CurText() ) )
1313  {
1314  growth->direction = T_vertical;
1315  break;
1316  }
1317  Expecting( "horizontal|vertical|orthogonal|positive_diagonal|negative_diagonal|diagonal|off" );
1318  }
1319  if( NextTok()!=T_RIGHT )
1320  Expecting(T_RIGHT);
1321  break;
1322 
1323  case T_cost:
1324  tok = NextTok();
1325  switch( tok )
1326  {
1327  case T_forbidden:
1328  case T_high:
1329  case T_medium:
1330  case T_low:
1331  case T_free:
1332  growth->cost = tok;
1333  break;
1334  case T_NUMBER:
1335  // store as negative so we can differentiate between
1336  // T (positive) and T_NUMBER (negative)
1337  growth->cost = -atoi( CurText() );
1338  break;
1339  default:
1340  Expecting( "forbidden|high|medium|low|free|<positive_integer>|-1" );
1341  }
1342  tok = NextTok();
1343  if( tok == T_LEFT )
1344  {
1345  if( NextTok() != T_type )
1346  Unexpected( CurText() );
1347 
1348  tok = NextTok();
1349  if( tok!=T_length && tok!=T_way )
1350  Expecting( "length|way" );
1351 
1352  growth->cost_type = tok;
1353  if( NextTok()!=T_RIGHT )
1354  Expecting(T_RIGHT);
1355 
1356  tok = NextTok();
1357  }
1358  if( tok!=T_RIGHT )
1359  Expecting(T_RIGHT);
1360  break;
1361 
1362  case T_use_net:
1363  while( (tok = NextTok()) != T_RIGHT )
1364  {
1365  if( !IsSymbol(tok) )
1366  Expecting( T_SYMBOL );
1367 
1368  growth->use_net.push_back( CurText() );
1369  }
1370  break;
1371 
1372  default:
1373  Unexpected( CurText() );
1374  }
1375  }
1376 }
1377 
1378 
1379 void SPECCTRA_DB::doRULE( RULE* growth )
1380 {
1381  std::string builder;
1382  int bracketNesting = 1; // we already saw the opening T_LEFT
1383  T tok = T_NONE;
1384 
1385  while( bracketNesting!=0 && tok!=T_EOF )
1386  {
1387  tok = NextTok();
1388 
1389  if( tok==T_LEFT)
1390  ++bracketNesting;
1391 
1392  else if( tok==T_RIGHT )
1393  --bracketNesting;
1394 
1395  if( bracketNesting >= 1 )
1396  {
1397  if( PrevTok()!=T_LEFT && tok!=T_RIGHT && (tok!=T_LEFT || bracketNesting>2) )
1398  builder += ' ';
1399 
1400  if( tok==T_STRING )
1401  builder += quote_char;
1402 
1403  builder += CurText();
1404 
1405  if( tok==T_STRING )
1406  builder += quote_char;
1407  }
1408 
1409  // When the nested rule is closed with a T_RIGHT and we are back down
1410  // to bracketNesting == 1, (inside the <rule_descriptor> but outside
1411  // the last rule). Then save the last rule and clear the string builder.
1412  if( bracketNesting == 1 )
1413  {
1414  growth->rules.push_back( builder );
1415  builder.clear();
1416  }
1417  }
1418 
1419  if( tok==T_EOF )
1420  Unexpected( T_EOF );
1421 }
1422 
1423 
1424 #if 0
1425 void SPECCTRA_DB::doPLACE_RULE( PLACE_RULE* growth, bool expect_object_type )
1426 {
1427  /* (place_rule [<structure_place_rule_object> ]
1428  {[<spacing_descriptor> |
1429  <permit_orient_descriptor> |
1430  <permit_side_descriptor> |
1431  <opposite_side_descriptor> ]}
1432  )
1433  */
1434 
1435  T tok = NextTok();
1436 
1437  if( tok!=T_LEFT )
1438  Expecting( T_LEFT );
1439 
1440  tok = NextTok();
1441  if( tok==T_object_type )
1442  {
1443  if( !expect_object_type )
1444  Unexpected( tok );
1445 
1446  /* [(object_type
1447  [pcb |
1448  image_set [large | small | discrete | capacitor | resistor]
1449  [(image_type [smd | pin])]]
1450  )]
1451  */
1452 
1453  tok = NextTok();
1454  switch( tok )
1455  {
1456  case T_pcb:
1457  growth->object_type = tok;
1458  break;
1459 
1460  case T_image_set:
1461  tok = NextTok();
1462  switch( tok )
1463  {
1464  case T_large:
1465  case T_small:
1466  case T_discrete:
1467  case T_capacitor:
1468  case T_resistor:
1469  growth->object_type = tok;
1470  break;
1471  default:
1472  Unexpected( CurText() );
1473  }
1474  break;
1475 
1476  default:
1477  Unexpected( CurText() );
1478  }
1479 
1480  tok = NextTok();
1481  if( tok == T_LEFT )
1482  {
1483  tok = NextTok();
1484  if( tok != T_image_type )
1486 
1487  tok = NextTok();
1488  if( tok!=T_smd && tok!=T_pin )
1489  Expecting( "smd|pin" );
1490 
1491  NeedRIGHT();
1492 
1493  tok = NextTok();
1494  }
1495 
1496  if( tok != T_RIGHT )
1497  Expecting( T_RIGHT );
1498 
1499  tok = NextTok();
1500  }
1501 
1502  /* {[<spacing_descriptor> |
1503  <permit_orient_descriptor> |
1504  <permit_side_descriptor> | <opposite_side_descriptor> ]}
1505  */
1506  doRULE( growth );
1507 }
1508 #endif
1509 
1510 
1512 {
1513  T tok = NextTok();
1514 
1515  if( IsSymbol(tok) )
1516  {
1517  growth->region_id = CurText();
1518  tok = NextTok();
1519  }
1520 
1521  for(;;)
1522  {
1523  if( tok != T_LEFT )
1524  Expecting( T_LEFT );
1525 
1526  tok = NextTok();
1527  switch( tok )
1528  {
1529  case T_rect:
1530  if( growth->rectangle )
1531  Unexpected( tok );
1532  growth->rectangle = new RECTANGLE( growth );
1533  doRECTANGLE( growth->rectangle );
1534  break;
1535 
1536  case T_polygon:
1537  if( growth->polygon )
1538  Unexpected( tok );
1539  growth->polygon = new PATH( growth, T_polygon );
1540  doPATH( growth->polygon );
1541  break;
1542 
1543  case T_region_net:
1544  case T_region_class:
1545  STRINGPROP* stringprop;
1546  stringprop = new STRINGPROP( growth, tok );
1547  growth->Append( stringprop );
1548  doSTRINGPROP( stringprop );
1549  break;
1550 
1551  case T_region_class_class:
1552  CLASS_CLASS* class_class;
1553  class_class = new CLASS_CLASS( growth, tok );
1554  growth->Append( class_class );
1555  doCLASS_CLASS( class_class );
1556  break;
1557 
1558  case T_rule:
1559  if( growth->rules )
1560  Unexpected( tok );
1561  growth->rules = new RULE( growth, T_rule );
1562  doRULE( growth->rules );
1563  break;
1564 
1565  default:
1566  Unexpected( CurText() );
1567  }
1568 
1569  tok = NextTok();
1570  if( tok == T_RIGHT )
1571  {
1572  if( !growth->rules )
1573  Expecting( T_rule );
1574  break;
1575  }
1576  }
1577 }
1578 
1579 
1581 {
1582  T tok = NextTok();
1583 
1584  if( tok != T_LEFT )
1585  Expecting( T_LEFT );
1586 
1587  while( (tok = NextTok()) != T_RIGHT )
1588  {
1589  switch( tok )
1590  {
1591  case T_classes:
1592  if( growth->classes )
1593  Unexpected( tok );
1594  growth->classes = new CLASSES( growth );
1595  doCLASSES( growth->classes );
1596  break;
1597 
1598  case T_rule:
1599  // only T_class_class takes a T_rule
1600  if( growth->Type() == T_region_class_class )
1601  Unexpected( tok );
1602  RULE* rule;
1603  rule = new RULE( growth, T_rule );
1604  growth->Append( rule );
1605  doRULE( rule );
1606  break;
1607 
1608  case T_layer_rule:
1609  // only T_class_class takes a T_layer_rule
1610  if( growth->Type() == T_region_class_class )
1611  Unexpected( tok );
1612  LAYER_RULE* layer_rule;
1613  layer_rule = new LAYER_RULE( growth );
1614  growth->Append( layer_rule );
1615  doLAYER_RULE( layer_rule );
1616  break;
1617 
1618  default:
1619  Unexpected( tok );
1620  }
1621  }
1622 }
1623 
1624 
1626 {
1627  T tok = NextTok();
1628 
1629  // require at least 2 class_ids
1630 
1631  if( !IsSymbol( tok ) )
1632  Expecting( "class_id" );
1633 
1634  growth->class_ids.push_back( CurText() );
1635 
1636  do
1637  {
1638  tok = NextTok();
1639  if( !IsSymbol( tok ) )
1640  Expecting( "class_id" );
1641 
1642  growth->class_ids.push_back( CurText() );
1643 
1644  } while( (tok = NextTok()) != T_RIGHT );
1645 }
1646 
1647 
1648 void SPECCTRA_DB::doGRID( GRID* growth )
1649 {
1650  T tok = NextTok();
1651 
1652  switch( tok )
1653  {
1654  case T_via:
1655  case T_wire:
1656  case T_via_keepout:
1657  case T_snap:
1658  case T_place:
1659  growth->grid_type = tok;
1660  if( NextTok() != T_NUMBER )
1661  Expecting( T_NUMBER );
1662  growth->dimension = strtod( CurText(), 0 );
1663  tok = NextTok();
1664  if( tok == T_LEFT )
1665  {
1666  while( (tok=NextTok()) != T_RIGHT )
1667  {
1668  if( tok==T_direction )
1669  {
1670  if( growth->grid_type == T_place )
1671  Unexpected( tok );
1672  tok = NextTok();
1673  if( tok!=T_x && tok!=T_y )
1674  Unexpected( CurText() );
1675  growth->direction = tok;
1676  if( NextTok() != T_RIGHT )
1677  Expecting(T_RIGHT);
1678  }
1679  else if( tok==T_offset )
1680  {
1681  if( growth->grid_type == T_place )
1682  Unexpected( tok );
1683 
1684  if( NextTok() != T_NUMBER )
1685  Expecting( T_NUMBER );
1686 
1687  growth->offset = strtod( CurText(), 0 );
1688 
1689  if( NextTok() != T_RIGHT )
1690  Expecting(T_RIGHT);
1691  }
1692  else if( tok==T_image_type )
1693  {
1694  if( growth->grid_type != T_place )
1695  Unexpected( tok );
1696  tok = NextTok();
1697  if( tok!=T_smd && tok!=T_pin )
1698  Unexpected( CurText() );
1699  growth->image_type = tok;
1700  if( NextTok() != T_RIGHT )
1701  Expecting(T_RIGHT);
1702  }
1703  }
1704  }
1705  break;
1706 
1707  default:
1708  Unexpected( tok );
1709  }
1710 }
1711 
1712 
1714 {
1715  T tok;
1716 
1717  NeedSYMBOL();
1718 
1719  do
1720  {
1721  growth->layer_ids.push_back( CurText() );
1722 
1723  } while( IsSymbol(tok = NextTok()) );
1724 
1725  if( tok != T_LEFT )
1726  Expecting( T_LEFT );
1727 
1728  if( NextTok() != T_rule )
1729  Expecting( T_rule );
1730 
1731  growth->rule = new RULE( growth, T_rule );
1732  doRULE( growth->rule );
1733 
1734  NeedRIGHT();
1735 }
1736 
1737 
1739 {
1740  T tok = NextTok();
1741 
1742  if( !IsSymbol( tok ) )
1743  Expecting( "component_id" );
1744 
1745  growth->component_id = CurText();
1746 
1747  tok = NextTok();
1748  if( tok == T_NUMBER )
1749  {
1750  POINT point;
1751 
1752  point.x = strtod( CurText(), 0 );
1753 
1754  if( NextTok() != T_NUMBER )
1755  Expecting( T_NUMBER );
1756  point.y = strtod( CurText(), 0 );
1757 
1758  growth->SetVertex( point );
1759 
1760  tok = NextTok();
1761  if( tok!=T_front && tok!=T_back )
1762  Expecting( "front|back" );
1763  growth->side = tok;
1764 
1765  if( NextTok() != T_NUMBER )
1766  Expecting( "rotation" );
1767  growth->SetRotation( strtod( CurText(), 0) );
1768  }
1769 
1770  while( (tok = NextTok()) != T_RIGHT )
1771  {
1772  if( tok != T_LEFT )
1773  Expecting( T_LEFT );
1774 
1775  tok = NextTok();
1776  switch( tok )
1777  {
1778  case T_mirror:
1779  tok = NextTok();
1780  if( tok==T_x || tok==T_y || tok==T_xy || tok==T_off )
1781  growth->mirror = tok;
1782  else
1783  Expecting("x|y|xy|off");
1784  break;
1785 
1786  case T_status:
1787  tok = NextTok();
1788  if( tok==T_added || tok==T_deleted || tok==T_substituted )
1789  growth->status = tok;
1790  else
1791  Expecting("added|deleted|substituted");
1792  break;
1793 
1794  case T_logical_part:
1795  if( growth->logical_part.size() )
1796  Unexpected( tok );
1797  tok = NextTok();
1798  if( !IsSymbol( tok ) )
1799  Expecting( "logical_part_id");
1800  growth->logical_part = CurText();
1801  break;
1802 
1803  case T_place_rule:
1804  if( growth->place_rules )
1805  Unexpected( tok );
1806  growth->place_rules = new RULE( growth, T_place_rule );
1807  doRULE( growth->place_rules );
1808  break;
1809 
1810  case T_property:
1811  if( growth->properties.size() )
1812  Unexpected( tok );
1813  doPROPERTIES( &growth->properties );
1814  break;
1815 
1816  case T_lock_type:
1817  tok = NextTok();
1818  if( tok==T_position || tok==T_gate || tok==T_subgate || tok==T_pin )
1819  growth->lock_type = tok;
1820  else
1821  Expecting("position|gate|subgate|pin");
1822  break;
1823 
1824  case T_rule:
1825  if( growth->rules || growth->region )
1826  Unexpected( tok );
1827  growth->rules = new RULE( growth, T_rule );
1828  doRULE( growth->rules );
1829  break;
1830 
1831  case T_region:
1832  if( growth->rules || growth->region )
1833  Unexpected( tok );
1834  growth->region = new REGION( growth );
1835  doREGION( growth->region );
1836  break;
1837 
1838  case T_pn:
1839  if( growth->part_number.size() )
1840  Unexpected( tok );
1842  growth->part_number = CurText();
1843  NeedRIGHT();
1844  break;
1845 
1846  default:
1847  Unexpected( tok );
1848  }
1849  }
1850 }
1851 
1852 
1854 {
1855  T tok = NextTok();
1856 
1857  if( !IsSymbol( tok ) && tok != T_NUMBER )
1858  Expecting( "image_id" );
1859  growth->image_id = CurText();
1860 
1861  while( (tok = NextTok()) != T_RIGHT )
1862  {
1863  if( tok != T_LEFT )
1864  Expecting( T_LEFT );
1865 
1866  tok = NextTok();
1867  switch( tok )
1868  {
1869  case T_place:
1870  PLACE* place;
1871  place = new PLACE( growth );
1872  growth->places.push_back( place );
1873  doPLACE( place );
1874  break;
1875 
1876  default:
1877  Unexpected(tok);
1878  }
1879  }
1880 }
1881 
1882 
1884 {
1885  T tok;
1886 
1887  while( (tok = NextTok()) != T_RIGHT )
1888  {
1889  if( tok == T_EOF )
1890  Unexpected( T_EOF );
1891 
1892  if( tok != T_LEFT )
1893  Expecting( T_LEFT );
1894 
1895  tok = NextTok();
1896 
1897  switch( tok )
1898  {
1899  case T_unit:
1900  case T_resolution:
1901  growth->unit = new UNIT_RES( growth, tok );
1902  if( tok==T_resolution )
1903  doRESOLUTION( growth->unit );
1904  else
1905  doUNIT( growth->unit );
1906  break;
1907 
1908  case T_place_control:
1909  NeedRIGHT();
1910  tok = NextTok();
1911  if( tok != T_flip_style )
1913 
1914  tok = NextTok();
1915  if( tok==T_mirror_first || tok==T_rotate_first )
1916  growth->flip_style = tok;
1917  else
1918  Expecting( "mirror_first|rotate_first" );
1919 
1920  NeedRIGHT();
1921  NeedRIGHT();
1922  break;
1923 
1924  case T_component:
1925  COMPONENT* component;
1926  component = new COMPONENT( growth );
1927  growth->components.push_back( component );
1928  doCOMPONENT( component );
1929  break;
1930 
1931  default:
1932  Unexpected( tok );
1933  }
1934  }
1935 }
1936 
1937 
1939 {
1940  T tok = NextTok();
1941 
1942  /* (padstack <padstack_id >
1943  [<unit_descriptor> ]
1944  {(shape <shape_descriptor>
1945  [<reduced_shape_descriptor> ]
1946  [(connect [on | off])]
1947  [{<window_descriptor> }]
1948  )}
1949  [<attach_descriptor> ]
1950  [{<pad_via_site_descriptor> }]
1951  [(rotate [on | off])]
1952  [(absolute [on | off])]
1953  [(rule <clearance_descriptor> )])
1954  */
1955 
1956  // padstack_id may be a number
1957  if( !IsSymbol( tok ) && tok!=T_NUMBER )
1958  Expecting( "padstack_id" );
1959 
1960  growth->padstack_id = CurText();
1961 
1962  while( (tok = NextTok()) != T_RIGHT )
1963  {
1964  if( tok != T_LEFT )
1965  Expecting( T_LEFT );
1966 
1967  tok = NextTok();
1968  switch( tok )
1969  {
1970  case T_unit:
1971  if( growth->unit )
1972  Unexpected( tok );
1973  growth->unit = new UNIT_RES( growth, tok );
1974  doUNIT( growth->unit );
1975  break;
1976 
1977  case T_rotate:
1978  tok = NextTok();
1979  if( tok!=T_on && tok!=T_off )
1980  Expecting( "on|off" );
1981  growth->rotate = tok;
1982  NeedRIGHT();
1983  break;
1984 
1985  case T_absolute:
1986  tok = NextTok();
1987  if( tok!=T_on && tok!=T_off )
1988  Expecting( "on|off" );
1989  growth->absolute = tok;
1990  NeedRIGHT();
1991  break;
1992 
1993  case T_shape:
1994  SHAPE* shape;
1995  shape = new SHAPE( growth );
1996  growth->Append( shape );
1997  doSHAPE( shape );
1998  break;
1999 
2000  case T_attach:
2001  tok = NextTok();
2002  if( tok!=T_off && tok!=T_on )
2003  Expecting( "off|on" );
2004  growth->attach = tok;
2005  tok = NextTok();
2006  if( tok == T_LEFT )
2007  {
2008  if( NextTok() != T_use_via )
2009  Expecting( T_use_via );
2010 
2011  NeedSYMBOL();
2012  growth->via_id = CurText();
2013 
2014  NeedRIGHT();
2015  NeedRIGHT();
2016  }
2017  break;
2018 
2019  /*
2020  case T_via_site: not supported
2021  break;
2022  */
2023 
2024  case T_rule:
2025  if( growth->rules )
2026  Unexpected( tok );
2027  growth->rules = new RULE( growth, T_rule );
2028  doRULE( growth->rules );
2029  break;
2030 
2031  default:
2032  Unexpected( CurText() );
2033  }
2034  }
2035 }
2036 
2037 
2039 {
2040  T tok;
2041 
2042  /* (shape <shape_descriptor>
2043  [<reduced_shape_descriptor> ]
2044  [(connect [on | off])]
2045  [{<window_descriptor> }])
2046  */
2047 
2048  while( (tok = NextTok()) != T_RIGHT )
2049  {
2050  if( tok != T_LEFT )
2051  Expecting( T_LEFT );
2052 
2053  tok = NextTok();
2054  switch( tok )
2055  {
2056  case T_polyline_path:
2057  tok = T_path;
2058  // Fall through
2059  case T_rect:
2060  case T_circle:
2061  case T_path:
2062  case T_polygon:
2063  case T_qarc:
2064 L_done_that:
2065  if( growth->shape )
2066  Unexpected( tok );
2067  break;
2068 
2069  default:
2070  // the example in the spec uses "circ" instead of "circle". Bad!
2071  if( !strcmp( "circ", CurText() ) )
2072  {
2073  tok = T_circle;
2074  goto L_done_that;
2075  }
2076  }
2077 
2078  switch( tok )
2079  {
2080  case T_rect:
2081  growth->shape = new RECTANGLE( growth );
2082  doRECTANGLE( (RECTANGLE*) growth->shape );
2083  break;
2084 
2085  case T_circle:
2086  growth->shape = new CIRCLE( growth );
2087  doCIRCLE( (CIRCLE*)growth->shape );
2088  break;
2089 
2090  case T_path:
2091  case T_polygon:
2092  growth->shape = new PATH( growth, tok );
2093  doPATH( (PATH*)growth->shape );
2094  break;
2095 
2096  case T_qarc:
2097  growth->shape = new QARC( growth );
2098  doQARC( (QARC*)growth->shape );
2099  break;
2100 
2101  case T_connect:
2102  tok = NextTok();
2103  if( tok!=T_on && tok!=T_off )
2104  Expecting( "on|off" );
2105  growth->connect = tok;
2106  NeedRIGHT();
2107  break;
2108 
2109  case T_window:
2110  WINDOW* window;
2111  window = new WINDOW( growth );
2112  growth->windows.push_back( window );
2113  doWINDOW( window );
2114  break;
2115 
2116  default:
2117  Unexpected( CurText() );
2118  }
2119  }
2120 }
2121 
2122 
2124 {
2125  T tok = NextTok();
2126 
2127  /* <image_descriptor >::=
2128  (image <image_id >
2129  [(side [front | back | both])]
2130  [<unit_descriptor> ]
2131  [<outline_descriptor> ]
2132  {(pin <padstack_id > [(rotate <rotation> )]
2133  [<reference_descriptor> | <pin_array_descriptor> ]
2134  [<user_property_descriptor> ])}
2135  [{<conductor_shape_descriptor> }]
2136  [{<conductor_via_descriptor> }]
2137  [<rule_descriptor> ]
2138  [<place_rule_descriptor> ]
2139  [{<keepout_descriptor> }]
2140  [<image_property_descriptor> ]
2141  )
2142  */
2143 
2144  if( !IsSymbol( tok ) && tok != T_NUMBER )
2145  Expecting( "image_id" );
2146 
2147  growth->image_id = CurText();
2148 
2149  while( (tok = NextTok()) != T_RIGHT )
2150  {
2151  if( tok != T_LEFT )
2152  Expecting( T_LEFT );
2153 
2154  tok = NextTok();
2155  switch( tok )
2156  {
2157  case T_unit:
2158  if( growth->unit )
2159  Unexpected( tok );
2160  growth->unit = new UNIT_RES( growth, tok );
2161  doUNIT( growth->unit );
2162  break;
2163 
2164  case T_side:
2165  tok = NextTok();
2166  if( tok!=T_front && tok!=T_back && tok!=T_both )
2167  Expecting( "front|back|both" );
2168  growth->side = tok;
2169  NeedRIGHT();
2170  break;
2171 
2172  case T_outline:
2173  SHAPE* outline;
2174  outline = new SHAPE( growth, T_outline ); // use SHAPE for T_outline
2175  growth->Append( outline );
2176  doSHAPE( outline );
2177  break;
2178 
2179  case T_pin:
2180  PIN* pin;
2181  pin = new PIN( growth );
2182  growth->pins.push_back( pin );
2183  doPIN( pin );
2184  break;
2185 
2186  case T_rule:
2187  if( growth->rules )
2188  Unexpected( tok );
2189  growth->rules = new RULE( growth, tok );
2190  doRULE( growth->rules );
2191  break;
2192 
2193  case T_place_rule:
2194  if( growth->place_rules )
2195  Unexpected( tok );
2196  growth->place_rules = new RULE( growth, tok );
2197  doRULE( growth->place_rules );
2198  break;
2199 
2200  case T_keepout:
2201  case T_place_keepout:
2202  case T_via_keepout:
2203  case T_wire_keepout:
2204  case T_bend_keepout:
2205  case T_elongate_keepout:
2206  KEEPOUT* keepout;
2207  keepout = new KEEPOUT( growth, tok );
2208  growth->keepouts.push_back( keepout );
2209  doKEEPOUT( keepout );
2210  break;
2211 
2212  default:
2213  Unexpected( CurText() );
2214  }
2215  }
2216 }
2217 
2218 
2219 void SPECCTRA_DB::doPIN( PIN* growth )
2220 {
2221  T tok = NextTok();
2222 
2223  /* (pin <padstack_id > [(rotate <rotation> )]
2224  [<reference_descriptor> | <pin_array_descriptor> ]
2225  [<user_property_descriptor> ])
2226  */
2227 
2228  // a padstack_id may be a number
2229  if( !IsSymbol( tok ) && tok!=T_NUMBER )
2230  Expecting( "padstack_id" );
2231 
2232  growth->padstack_id = CurText();
2233 
2234  while( (tok = NextTok()) != T_RIGHT )
2235  {
2236  if( tok == T_LEFT )
2237  {
2238  tok = NextTok();
2239  if( tok != T_rotate )
2240  Expecting( T_rotate );
2241 
2242  if( NextTok() != T_NUMBER )
2243  Expecting( T_NUMBER );
2244  growth->SetRotation( strtod( CurText(), 0 ) );
2245  NeedRIGHT();
2246  }
2247  else
2248  {
2249  if( !IsSymbol(tok) && tok!=T_NUMBER )
2250  Expecting( "pin_id" );
2251 
2252  growth->pin_id = CurText();
2253 
2254  if( NextTok() != T_NUMBER )
2255  Expecting( T_NUMBER );
2256  growth->vertex.x = strtod( CurText(), 0 );
2257 
2258  if( NextTok() != T_NUMBER )
2259  Expecting( T_NUMBER );
2260  growth->vertex.y = strtod( CurText(), 0 );
2261  }
2262  }
2263 }
2264 
2265 
2267 {
2268  T tok;
2269 
2270  /* <library_descriptor >::=
2271  (library
2272  [<unit_descriptor> ]
2273  {<image_descriptor> }
2274  [{<jumper_descriptor> }]
2275  {<padstack_descriptor> }
2276  {<via_array_template_descriptor> }
2277  [<directory_descriptor> ]
2278  [<extra_image_directory_descriptor> ]
2279  [{<family_family_descriptor> }]
2280  [{<image_image_descriptor> }]
2281  )
2282  */
2283 
2284  while( (tok = NextTok()) != T_RIGHT )
2285  {
2286  if( tok != T_LEFT )
2287  Expecting( T_LEFT );
2288 
2289  tok = NextTok();
2290  switch( tok )
2291  {
2292  case T_unit:
2293  if( growth->unit )
2294  Unexpected( tok );
2295  growth->unit = new UNIT_RES( growth, tok );
2296  doUNIT( growth->unit );
2297  break;
2298 
2299  case T_padstack:
2300  PADSTACK* padstack;
2301  padstack = new PADSTACK();
2302  growth->AddPadstack( padstack );
2303  doPADSTACK( padstack );
2304  break;
2305 
2306  case T_image:
2307  IMAGE* image;
2308  image = new IMAGE( growth );
2309  growth->images.push_back( image );
2310  doIMAGE( image );
2311  break;
2312 
2313  default:
2314  Unexpected( CurText() );
2315  }
2316  }
2317 }
2318 
2319 
2320 void SPECCTRA_DB::doNET( NET* growth )
2321 {
2322  T tok = NextTok();
2323  PIN_REFS* pin_refs;
2324 
2325  /* <net_descriptor >::=
2326  (net <net_id >
2327  [(unassigned)]
2328  [(net_number <integer >)]
2329  [(pins {<pin_reference> }) | (order {<pin_reference> })]
2330  [<component_order_descriptor> ]
2331  [(type [fix | normal])]
2332  [<user_property_descriptor> ]
2333  [<circuit_descriptor> ]
2334  [<rule_descriptor> ]
2335  [{<layer_rule_descriptor> }]
2336  [<fromto_descriptor> ]
2337  [(expose {<pin_reference> })]
2338  [(noexpose {<pin_reference> })]
2339  [(source {<pin_reference> })]
2340  [(load {<pin_reference> })]
2341  [(terminator {<pin_reference> })]
2342  [(supply [power | ground])]
2343  )
2344  */
2345 
2346  if( !IsSymbol( tok ) )
2347  Expecting( "net_id" );
2348 
2349  growth->net_id = CurText();
2350 
2351  while( (tok = NextTok()) != T_RIGHT )
2352  {
2353  if( tok != T_LEFT )
2354  Expecting( T_LEFT );
2355 
2356  tok = NextTok();
2357  switch( tok )
2358  {
2359  case T_unassigned:
2360  growth->unassigned = true;
2361  NeedRIGHT();
2362  break;
2363 
2364  case T_net_number:
2365  if( NextTok() != T_NUMBER )
2366  Expecting( T_NUMBER );
2367  growth->net_number = atoi( CurText() );
2368  NeedRIGHT();
2369  break;
2370 
2371  case T_pins:
2372  case T_order:
2373  growth->pins_type = tok;
2374  pin_refs = &growth->pins;
2375  goto L_pins;
2376 
2377  case T_expose:
2378  pin_refs = &growth->expose;
2379  goto L_pins;
2380 
2381  case T_noexpose:
2382  pin_refs = &growth->noexpose;
2383  goto L_pins;
2384 
2385  case T_source:
2386  pin_refs = &growth->source;
2387  goto L_pins;
2388 
2389  case T_load:
2390  pin_refs = &growth->load;
2391  goto L_pins;
2392 
2393  case T_terminator:
2394  pin_refs = &growth->terminator;
2395  //goto L_pins;
2396 
2397 L_pins:
2398  {
2399  PIN_REF empty( growth );
2400  while( (tok = NextTok()) != T_RIGHT )
2401  {
2402  // copy the empty one, then fill its copy later thru pin_ref.
2403  pin_refs->push_back( empty );
2404 
2405  PIN_REF* pin_ref = &pin_refs->back();
2406 
2407  readCOMPnPIN( &pin_ref->component_id, &pin_ref->pin_id );
2408  }
2409  }
2410  break;
2411 
2412  case T_comp_order:
2413  if( growth->comp_order )
2414  Unexpected( tok );
2415  growth->comp_order = new COMP_ORDER( growth );
2416  doCOMP_ORDER( growth->comp_order );
2417  break;
2418 
2419  case T_type:
2420  tok = NextTok();
2421  if( tok!=T_fix && tok!=T_normal )
2422  Expecting( "fix|normal" );
2423  growth->type = tok;
2424  NeedRIGHT();
2425  break;
2426 
2427 /* @todo
2428  case T_circuit:
2429  break;
2430 */
2431 
2432  case T_rule:
2433  if( growth->rules )
2434  Unexpected( tok );
2435  growth->rules = new RULE( growth, T_rule );
2436  doRULE( growth->rules );
2437  break;
2438 
2439  case T_layer_rule:
2440  LAYER_RULE* layer_rule;
2441  layer_rule = new LAYER_RULE( growth );
2442  growth->layer_rules.push_back( layer_rule );
2443  doLAYER_RULE( layer_rule );
2444  break;
2445 
2446  case T_fromto:
2447  FROMTO* fromto;
2448  fromto = new FROMTO( growth );
2449  growth->fromtos.push_back( fromto );
2450  doFROMTO( fromto );
2451  break;
2452 
2453  default:
2454  Unexpected( CurText() );
2455  }
2456  }
2457 }
2458 
2459 
2461 {
2462  T tok;
2463 
2464  /* <topology_descriptor >::=
2465  (topology {[<fromto_descriptor> |
2466  <component_order_descriptor> ]})
2467  */
2468 
2469  while( (tok = NextTok()) != T_RIGHT )
2470  {
2471  if( tok != T_LEFT )
2472  Expecting( T_LEFT );
2473 
2474  tok = NextTok();
2475  switch( tok )
2476  {
2477  case T_fromto:
2478  FROMTO* fromto;
2479  fromto = new FROMTO( growth );
2480  growth->fromtos.push_back( fromto );
2481  doFROMTO( fromto );
2482  break;
2483 
2484  case T_comp_order:
2485  COMP_ORDER* comp_order;
2486  comp_order = new COMP_ORDER( growth );
2487  growth->comp_orders.push_back( comp_order );
2488  doCOMP_ORDER( comp_order );
2489  break;
2490 
2491  default:
2492  Unexpected( CurText() );
2493  }
2494  }
2495 }
2496 
2497 
2499 {
2500  T tok;
2501 
2502  /* <class_descriptor >::=
2503  (class
2504  <class_id > {[{<net_id >} | {<composite_name_list> }]}
2505  [<circuit_descriptor> ]
2506  [<rule_descriptor> ]
2507  [{<layer_rule_descriptor> }]
2508  [<topology_descriptor> ]
2509  )
2510  */
2511 
2512  NeedSYMBOL();
2513 
2514  growth->class_id = CurText();
2515 
2516  // do net_ids, do not support <composite_name_list>s at this time
2517  while( IsSymbol(tok = NextTok()) )
2518  {
2519  growth->net_ids.push_back( CurText() );
2520  }
2521 
2522 
2523  while( tok != T_RIGHT )
2524  {
2525  if( tok != T_LEFT )
2526  Expecting( T_LEFT );
2527 
2528  tok = NextTok();
2529  switch( tok )
2530  {
2531  case T_rule:
2532  if( growth->rules )
2533  Unexpected( tok );
2534  growth->rules = new RULE( growth, T_rule );
2535  doRULE( growth->rules );
2536  break;
2537 
2538  case T_layer_rule:
2539  LAYER_RULE* layer_rule;
2540  layer_rule = new LAYER_RULE( growth );
2541  growth->layer_rules.push_back( layer_rule );
2542  doLAYER_RULE( layer_rule );
2543  break;
2544 
2545  case T_topology:
2546  if( growth->topology )
2547  Unexpected( tok );
2548  growth->topology = new TOPOLOGY( growth );
2549  doTOPOLOGY( growth->topology );
2550  break;
2551 
2552  case T_circuit: // handle all the circuit_descriptor here as strings
2553  {
2554  std::string builder;
2555  int bracketNesting = 1; // we already saw the opening T_LEFT
2556  tok = T_NONE;
2557 
2558  while( bracketNesting!=0 && tok!=T_EOF )
2559  {
2560  tok = NextTok();
2561 
2562  if( tok==T_LEFT)
2563  ++bracketNesting;
2564 
2565  else if( tok==T_RIGHT )
2566  --bracketNesting;
2567 
2568  if( bracketNesting >= 1 )
2569  {
2570  T previousTok = (T) PrevTok();
2571 
2572  if( previousTok!=T_LEFT && previousTok!=T_circuit && tok!=T_RIGHT )
2573  builder += ' ';
2574 
2575  if( tok==T_STRING )
2576  builder += quote_char;
2577 
2578  builder += CurText();
2579 
2580  if( tok==T_STRING )
2581  builder += quote_char;
2582  }
2583 
2584  // When the nested rule is closed with a T_RIGHT and we are back down
2585  // to bracketNesting == 0, then save the builder and break;
2586  if( bracketNesting == 0 )
2587  {
2588  growth->circuit.push_back( builder );
2589  break;
2590  }
2591  }
2592 
2593  if( tok==T_EOF )
2594  Unexpected( T_EOF );
2595  } // scope bracket
2596  break;
2597 
2598  default:
2599  Unexpected( CurText() );
2600  } // switch
2601 
2602  tok = NextTok();
2603 
2604  } // while
2605 }
2606 
2607 
2609 {
2610  T tok;
2611 
2612  /* <network_descriptor >::=
2613  (network
2614  {<net_descriptor>}
2615  [{<class_descriptor> }]
2616  [{<class_class_descriptor> }]
2617  [{<group_descriptor> }]
2618  [{<group_set_descriptor> }]
2619  [{<pair_descriptor> }]
2620  [{<bundle_descriptor> }]
2621  )
2622  */
2623 
2624  while( (tok = NextTok()) != T_RIGHT )
2625  {
2626  if( tok != T_LEFT )
2627  Expecting( T_LEFT );
2628 
2629  tok = NextTok();
2630  switch( tok )
2631  {
2632  case T_net:
2633  NET* net;
2634  net = new NET( growth );
2635  growth->nets.push_back( net );
2636  doNET( net );
2637  break;
2638 
2639  case T_class:
2640  CLASS* myclass;
2641  myclass = new CLASS( growth );
2642  growth->classes.push_back( myclass );
2643  doCLASS( myclass );
2644  break;
2645 
2646  default:
2647  Unexpected( CurText() );
2648  }
2649  }
2650 }
2651 
2652 
2654 {
2655  T tok;
2656 
2657  /* <component_order_descriptor >::=
2658  (comp_order {<placement_id> })
2659  */
2660 
2661  while( IsSymbol(tok = NextTok()) )
2662  {
2663  growth->placement_ids.push_back( CurText() );
2664  }
2665 
2666  if( tok != T_RIGHT )
2667  Expecting( T_RIGHT );
2668 }
2669 
2670 
2672 {
2673  T tok;
2674 
2675  /* <fromto_descriptor >::=
2676  {(fromto
2677  [<pin_reference> | <virtual_pin_descriptor> ] | <component_id >]
2678  [<pin_reference> | <virtual_pin_descriptor> | <component_id >]
2679  [(type [fix | normal | soft])]
2680  [(net <net_id >)]
2681  [<rule_descriptor> ]
2682  [<circuit_descriptor> ]
2683  [{<layer_rule_descriptor> }]
2684  )}
2685  */
2686 
2687 
2688  // read the first two grammar items in as 2 single tokens, i.e. do not
2689  // split apart the <pin_reference>s into 3 separate tokens. Do this by
2690  // turning off the string delimiter in the lexer.
2691 
2692  char old = SetStringDelimiter( 0 );
2693 
2694  if( !IsSymbol(NextTok() ) )
2695  {
2696  SetStringDelimiter( old );
2697  Expecting( T_SYMBOL );
2698  }
2699  growth->fromText = CurText();
2700 
2701  if( !IsSymbol(NextTok() ) )
2702  {
2703  SetStringDelimiter( old );
2704  Expecting( T_SYMBOL );
2705  }
2706  growth->toText = CurText();
2707 
2708  SetStringDelimiter( old );
2709 
2710  while( (tok = NextTok()) != T_RIGHT )
2711  {
2712  if( tok != T_LEFT )
2713  Expecting( T_LEFT );
2714 
2715  tok = NextTok();
2716  switch( tok )
2717  {
2718  case T_type:
2719  tok = NextTok();
2720  if( tok!=T_fix && tok!=T_normal && tok!=T_soft )
2721  Expecting( "fix|normal|soft" );
2722  growth->fromto_type = tok;
2723  NeedRIGHT();
2724  break;
2725 
2726  case T_rule:
2727  if( growth->rules )
2728  Unexpected( tok );
2729  growth->rules = new RULE( growth, T_rule );
2730  doRULE( growth->rules );
2731  break;
2732 
2733  case T_layer_rule:
2734  LAYER_RULE* layer_rule;
2735  layer_rule = new LAYER_RULE( growth );
2736  growth->layer_rules.push_back( layer_rule );
2737  doLAYER_RULE( layer_rule );
2738  break;
2739 
2740  case T_net:
2741  if( growth->net_id.size() )
2742  Unexpected( tok );
2743  NeedSYMBOL();
2744  growth->net_id = CurText();
2745  NeedRIGHT();
2746  break;
2747 
2748  // circuit descriptor not supported at this time
2749 
2750  default:
2751  Unexpected( CurText() );
2752  }
2753  }
2754 }
2755 
2756 
2757 void SPECCTRA_DB::doWIRE( WIRE* growth )
2758 {
2759  T tok;
2760 
2761  /* <wire_shape_descriptor >::=
2762  (wire
2763  <shape_descriptor>
2764  [(net <net_id >)]
2765  [(turret <turret#> )]
2766  [(type [fix | route | normal | protect])]
2767  [(attr [test | fanout | bus | jumper])]
2768  [(shield <net_id >)]
2769  [{<window_descriptor> }]
2770  [(connect
2771  (terminal <object_type> [<pin_reference> ])
2772  (terminal <object_type> [<pin_reference> ])
2773  )]
2774  [(supply)]
2775  )
2776  */
2777 
2778  while( (tok = NextTok()) != T_RIGHT )
2779  {
2780  if( tok != T_LEFT )
2781  Expecting( T_LEFT );
2782 
2783  tok = NextTok();
2784  switch( tok )
2785  {
2786  case T_rect:
2787  if( growth->shape )
2788  Unexpected( tok );
2789  growth->shape = new RECTANGLE( growth );
2790  doRECTANGLE( (RECTANGLE*) growth->shape );
2791  break;
2792 
2793  case T_circle:
2794  if( growth->shape )
2795  Unexpected( tok );
2796  growth->shape = new CIRCLE( growth );
2797  doCIRCLE( (CIRCLE*) growth->shape );
2798  break;
2799 
2800  case T_polyline_path:
2801  tok = T_path;
2802  // Fall through
2803  case T_path:
2804  case T_polygon:
2805  if( growth->shape )
2806  Unexpected( tok );
2807  growth->shape = new PATH( growth, tok );
2808  doPATH( (PATH*) growth->shape );
2809  break;
2810 
2811  case T_qarc:
2812  if( growth->shape )
2813  Unexpected( tok );
2814  growth->shape = new QARC( growth );
2815  doQARC( (QARC*) growth->shape );
2816  break;
2817 
2818  case T_net:
2820  growth->net_id = CurText();
2821  NeedRIGHT();
2822  break;
2823 
2824  case T_turret:
2825  if( NextTok() != T_NUMBER )
2826  Expecting( T_NUMBER );
2827  growth->turret = atoi( CurText() );
2828  NeedRIGHT();
2829  break;
2830 
2831  case T_type:
2832  tok = NextTok();
2833  if( tok!=T_fix && tok!=T_route && tok!=T_normal && tok!=T_protect )
2834  Expecting( "fix|route|normal|protect" );
2835  growth->wire_type = tok;
2836  NeedRIGHT();
2837  break;
2838 
2839  case T_attr:
2840  tok = NextTok();
2841  if( tok!=T_test && tok!=T_fanout && tok!=T_bus && tok!=T_jumper )
2842  Expecting( "test|fanout|bus|jumper" );
2843  growth->attr = tok;
2844  NeedRIGHT();
2845  break;
2846 
2847  case T_shield:
2848  NeedSYMBOL();
2849  growth->shield = CurText();
2850  NeedRIGHT();
2851  break;
2852 
2853  case T_window:
2854  WINDOW* window;
2855  window = new WINDOW( growth );
2856  growth->windows.push_back( window );
2857  doWINDOW( window );
2858  break;
2859 
2860  case T_connect:
2861  if( growth->connect )
2862  Unexpected( tok );
2863  growth->connect = new CONNECT( growth );
2864  doCONNECT( growth->connect );
2865  break;
2866 
2867  case T_supply:
2868  growth->supply = true;
2869  NeedRIGHT();
2870  break;
2871 
2872  default:
2873  Unexpected( CurText() );
2874  }
2875  }
2876 }
2877 
2878 
2880 {
2881  T tok;
2882  POINT point;
2883 
2884  /* <wire_via_descriptor >::=
2885  (via
2886  <padstack_id > {<vertex> }
2887  [(net <net_id >)]
2888  [(via_number <via#> )]
2889  [(type [fix | route | normal | protect])]
2890  [(attr [test | fanout | jumper |
2891  virtual_pin <virtual_pin_name> ])]
2892  [(contact {<layer_id >})]
2893  [(supply)]
2894  )
2895  (virtual_pin
2896  <virtual_pin_name> <vertex> (net <net_id >)
2897  )
2898  */
2899 
2900  NeedSYMBOL();
2901  growth->padstack_id = CurText();
2902 
2903  while( (tok = NextTok()) == T_NUMBER )
2904  {
2905  point.x = strtod( CurText(), 0 );
2906 
2907  if( NextTok() != T_NUMBER )
2908  Expecting( "vertex.y" );
2909 
2910  point.y = strtod( CurText(), 0 );
2911 
2912  growth->vertexes.push_back( point );
2913  }
2914 
2915  while( tok != T_RIGHT )
2916  {
2917  if( tok != T_LEFT )
2918  Expecting( T_LEFT );
2919 
2920  tok = NextTok();
2921  switch( tok )
2922  {
2923  case T_net:
2924  NeedSYMBOL();
2925  growth->net_id = CurText();
2926  NeedRIGHT();
2927  break;
2928 
2929  case T_via_number:
2930  if( NextTok() != T_NUMBER )
2931  Expecting( "<via#>" );
2932  growth->via_number = atoi( CurText() );
2933  NeedRIGHT();
2934  break;
2935 
2936  case T_type:
2937  tok = NextTok();
2938  if( tok!=T_fix && tok!=T_route && tok!=T_normal && tok!=T_protect )
2939  Expecting( "fix|route|normal|protect" );
2940  growth->via_type = tok;
2941  NeedRIGHT();
2942  break;
2943 
2944  case T_attr:
2945  tok = NextTok();
2946  if( tok!=T_test && tok!=T_fanout && tok!=T_jumper && tok!=T_virtual_pin )
2947  Expecting( "test|fanout|jumper|virtual_pin" );
2948  growth->attr = tok;
2949  if( tok == T_virtual_pin )
2950  {
2951  NeedSYMBOL();
2952  growth->virtual_pin_name = CurText();
2953  }
2954  NeedRIGHT();
2955  break;
2956 
2957  case T_contact:
2958  NeedSYMBOL();
2959  tok = T_SYMBOL;
2960  while( IsSymbol(tok) )
2961  {
2962  growth->contact_layers.push_back( CurText() );
2963  tok = NextTok();
2964  }
2965  if( tok != T_RIGHT )
2966  Expecting( T_RIGHT );
2967  break;
2968 
2969  case T_supply:
2970  growth->supply = true;
2971  NeedRIGHT();
2972  break;
2973 
2974  default:
2975  Unexpected( CurText() );
2976  }
2977 
2978  tok = NextTok();
2979  }
2980 }
2981 
2982 
2984 {
2985  T tok;
2986 
2987  /* <wiring_descriptor >::=
2988  (wiring
2989  [<unit_descriptor> | <resolution_descriptor> | null]
2990  {<wire_descriptor> }
2991  [<test_points_descriptor> ]
2992  {[<supply_pin_descriptor> ]}
2993  )
2994  */
2995 
2996  while( (tok = NextTok()) != T_RIGHT )
2997  {
2998  if( tok != T_LEFT )
2999  Expecting( T_LEFT );
3000 
3001  tok = NextTok();
3002  switch( tok )
3003  {
3004  case T_unit:
3005  if( growth->unit )
3006  Unexpected( tok );
3007  growth->unit = new UNIT_RES( growth, tok );
3008  doUNIT( growth->unit );
3009  break;
3010 
3011  case T_resolution:
3012  if( growth->unit )
3013  Unexpected( tok );
3014  growth->unit = new UNIT_RES( growth, tok );
3015  doRESOLUTION( growth->unit );
3016  break;
3017 
3018  case T_wire:
3019  WIRE* wire;
3020  wire = new WIRE( growth );
3021  growth->wires.push_back( wire );
3022  doWIRE( wire );
3023  break;
3024 
3025  case T_via:
3026  WIRE_VIA* wire_via;
3027  wire_via = new WIRE_VIA( growth );
3028  growth->wire_vias.push_back( wire_via );
3029  doWIRE_VIA( wire_via );
3030  break;
3031 
3032  default:
3033  Unexpected( CurText() );
3034  }
3035  }
3036 }
3037 
3038 
3040 {
3041  T tok;
3042 
3043  /* <ancestor_file_descriptor >::=
3044  (ancestor <file_path_name> (created_time <time_stamp> )
3045  [(comment <comment_string> )])
3046  */
3047 
3048  NeedSYMBOL();
3049  growth->filename = CurText();
3050 
3051  while( (tok = NextTok()) != T_RIGHT )
3052  {
3053  if( tok != T_LEFT )
3054  Expecting( T_LEFT );
3055 
3056  tok = NextTok();
3057  switch( tok )
3058  {
3059  case T_created_time:
3060  readTIME( &growth->time_stamp );
3061  NeedRIGHT();
3062  break;
3063 
3064  case T_comment:
3065  NeedSYMBOL();
3066  growth->comment = CurText();
3067  NeedRIGHT();
3068  break;
3069 
3070  default:
3071  Unexpected( CurText() );
3072  }
3073  }
3074 }
3075 
3076 
3078 {
3079  T tok;
3080 
3081  /* <history_descriptor >::=
3082  (history [{<ancestor_file_descriptor> }] <self_descriptor> )
3083  */
3084 
3085  while( (tok = NextTok()) != T_RIGHT )
3086  {
3087  if( tok != T_LEFT )
3088  Expecting( T_LEFT );
3089 
3090  tok = NextTok();
3091  switch( tok )
3092  {
3093  case T_ancestor:
3094  ANCESTOR* ancestor;
3095  ancestor = new ANCESTOR( growth );
3096  growth->ancestors.push_back( ancestor );
3097  doANCESTOR( ancestor );
3098  break;
3099 
3100  case T_self:
3101  while( (tok = NextTok()) != T_RIGHT )
3102  {
3103  if( tok != T_LEFT )
3104  Expecting( T_LEFT );
3105 
3106  tok = NextTok();
3107  switch( tok )
3108  {
3109  case T_created_time:
3110  readTIME( &growth->time_stamp );
3111  NeedRIGHT();
3112  break;
3113 
3114  case T_comment:
3115  NeedSYMBOL();
3116  growth->comments.push_back( CurText() );
3117  NeedRIGHT();
3118  break;
3119 
3120  default:
3121  Unexpected( CurText() );
3122  }
3123  }
3124  break;
3125 
3126  default:
3127  Unexpected( CurText() );
3128  }
3129  }
3130 }
3131 
3132 
3134 {
3135  T tok;
3136 
3137  /* <session_file_descriptor >::=
3138  (session <session_id >
3139  (base_design <path/filename >)
3140  [<history_descriptor> ]
3141  [<session_structure_descriptor> ]
3142  [<placement_descriptor> ]
3143  [<floor_plan_descriptor> ]
3144  [<net_pin_changes_descriptor> ]
3145  [<was_is_descriptor> ]
3146  <swap_history_descriptor> ]
3147  [<route_descriptor> ]
3148  )
3149  */
3150 
3151  NeedSYMBOL();
3152  growth->session_id = CurText();
3153 
3154  while( (tok = NextTok()) != T_RIGHT )
3155  {
3156  if( tok != T_LEFT )
3157  Expecting( T_LEFT );
3158 
3159  tok = NextTok();
3160  switch( tok )
3161  {
3162  case T_base_design:
3163  NeedSYMBOL();
3164  growth->base_design = CurText();
3165  NeedRIGHT();
3166  break;
3167 
3168  case T_history:
3169  if( growth->history )
3170  Unexpected( tok );
3171  growth->history = new HISTORY( growth );
3172  doHISTORY( growth->history );
3173  break;
3174 
3175  case T_structure:
3176  if( growth->structure )
3177  Unexpected( tok );
3178  growth->structure = new STRUCTURE( growth );
3179  doSTRUCTURE( growth->structure );
3180  break;
3181 
3182  case T_placement:
3183  if( growth->placement )
3184  Unexpected( tok );
3185  growth->placement = new PLACEMENT( growth );
3186  doPLACEMENT( growth->placement );
3187  break;
3188 
3189  case T_was_is:
3190  if( growth->was_is )
3191  Unexpected( tok );
3192  growth->was_is = new WAS_IS( growth );
3193  doWAS_IS( growth->was_is );
3194  break;
3195 
3196  case T_routes:
3197  if( growth->route )
3198  Unexpected( tok );
3199  growth->route = new ROUTE( growth );
3200  doROUTE( growth->route );
3201  break;
3202 
3203  default:
3204  Unexpected( CurText() );
3205  }
3206  }
3207 }
3208 
3209 
3211 {
3212  T tok;
3213  PIN_PAIR empty( growth );
3214  PIN_PAIR* pin_pair;
3215 
3216  /* <was_is_descriptor >::=
3217  (was_is {(pins <pin_reference> <pin_reference> )})
3218  */
3219 
3220  // none of the pins is ok too
3221  while( (tok = NextTok()) != T_RIGHT )
3222  {
3223 
3224  if( tok != T_LEFT )
3225  Expecting( T_LEFT );
3226 
3227  tok = NextTok();
3228  switch( tok )
3229  {
3230  case T_pins:
3231  // copy the empty one, then fill its copy later thru pin_pair.
3232  growth->pin_pairs.push_back( empty );
3233  pin_pair= &growth->pin_pairs.back();
3234 
3235  NeedSYMBOL(); // readCOMPnPIN() expects 1st token to have been read
3236  readCOMPnPIN( &pin_pair->was.component_id, &pin_pair->was.pin_id );
3237 
3238  NeedSYMBOL(); // readCOMPnPIN() expects 1st token to have been read
3239  readCOMPnPIN( &pin_pair->is.component_id, &pin_pair->is.pin_id );
3240 
3241  NeedRIGHT();
3242  break;
3243 
3244  default:
3245  Unexpected( CurText() );
3246  }
3247  }
3248 }
3249 
3250 
3252 {
3253  T tok;
3254 
3255  /* <route_descriptor >::=
3256  (routes
3257  <resolution_descriptor>
3258  <parser_descriptor>
3259  <structure_out_descriptor>
3260  <library_out_descriptor>
3261  <network_out_descriptor>
3262  <test_points_descriptor>
3263  )
3264  */
3265 
3266  while( (tok = NextTok()) != T_RIGHT )
3267  {
3268  if( tok != T_LEFT )
3269  Expecting( T_LEFT );
3270 
3271  tok = NextTok();
3272  switch( tok )
3273  {
3274  case T_resolution:
3275  if( growth->resolution )
3276  Unexpected( tok );
3277  growth->resolution = new UNIT_RES( growth, tok );
3278  doRESOLUTION( growth->resolution );
3279  break;
3280 
3281  case T_parser:
3282  if( growth->parser )
3283  {
3284 #if 0 // Electra 2.9.1 emits two (parser ) elements in a row.
3285  // Work around their bug for now.
3286  Unexpected( tok );
3287 #else
3288  delete growth->parser;
3289 #endif
3290  }
3291  growth->parser = new PARSER( growth );
3292  doPARSER( growth->parser );
3293  break;
3294 
3295  case T_structure_out:
3296  if( growth->structure_out )
3297  Unexpected( tok );
3298  growth->structure_out = new STRUCTURE_OUT( growth );
3299  doSTRUCTURE_OUT( growth->structure_out );
3300  break;
3301 
3302  case T_library_out:
3303  if( growth->library )
3304  Unexpected( tok );
3305  growth->library = new LIBRARY( growth, tok );
3306  doLIBRARY( growth->library );
3307  break;
3308 
3309  case T_network_out:
3310  while( (tok = NextTok()) != T_RIGHT )
3311  {
3312  if( tok != T_LEFT )
3313  Expecting( T_LEFT );
3314 
3315  tok = NextTok();
3316  if( tok != T_net ) // it is class NET_OUT, but token T_net
3317  Unexpected( CurText() );
3318 
3319  NET_OUT* net_out;
3320  net_out = new NET_OUT( growth );
3321 
3322  growth->net_outs.push_back( net_out );
3323  doNET_OUT( net_out );
3324  }
3325  break;
3326 
3327  default:
3328  Unexpected( CurText() );
3329  }
3330  }
3331 }
3332 
3333 
3335 {
3336  T tok;
3337 
3338  /* <net_out_descriptor >::=
3339  (net <net_id >
3340  [(net_number <integer >)]
3341  [<rule_descriptor> ]
3342  {[<wire_shape_descriptor> | <wire_guide_descriptor> |
3343  <wire_via_descriptor> | <bond_shape_descriptor> ]}
3344  {[<supply_pin_descriptor> ]}
3345  )
3346  */
3347 
3349  growth->net_id = CurText();
3350 
3351  while( (tok = NextTok()) != T_RIGHT )
3352  {
3353  if( tok != T_LEFT )
3354  Expecting( T_LEFT );
3355 
3356  tok = NextTok();
3357  switch( tok )
3358  {
3359  case T_net_number:
3360  tok = NextTok();
3361  if( tok!= T_NUMBER )
3362  Expecting( T_NUMBER );
3363  growth->net_number = atoi( CurText() );
3364  NeedRIGHT();
3365  break;
3366 
3367  case T_rule:
3368  if( growth->rules )
3369  Unexpected( tok );
3370  growth->rules = new RULE( growth, tok );
3371  doRULE( growth->rules );
3372  break;
3373 
3374  case T_wire:
3375  WIRE* wire;
3376  wire = new WIRE( growth );
3377  growth->wires.push_back( wire );
3378  doWIRE( wire );
3379  break;
3380 
3381  case T_via:
3382  WIRE_VIA* wire_via;
3383  wire_via = new WIRE_VIA( growth );
3384  growth->wire_vias.push_back( wire_via );
3385  doWIRE_VIA( wire_via );
3386  break;
3387 
3388  case T_supply_pin:
3389  SUPPLY_PIN* supply_pin;
3390  supply_pin = new SUPPLY_PIN( growth );
3391  growth->supply_pins.push_back( supply_pin );
3392  doSUPPLY_PIN( supply_pin );
3393  break;
3394 
3395  default:
3396  Unexpected( CurText() );
3397  }
3398  }
3399 }
3400 
3401 
3403 {
3404  T tok;
3405  PIN_REF empty(growth);
3406 
3407  /* <supply_pin_descriptor >::=
3408  (supply_pin {<pin_reference> } [(net <net_id >)])
3409  */
3410 
3411  NeedSYMBOL();
3412  growth->net_id = CurText();
3413 
3414  while( (tok = NextTok()) != T_RIGHT )
3415  {
3416  if( IsSymbol(tok) )
3417  {
3418  growth->pin_refs.push_back( empty );
3419 
3420  PIN_REF* pin_ref = &growth->pin_refs.back();
3421 
3422  readCOMPnPIN( &pin_ref->component_id, &pin_ref->pin_id );
3423  }
3424  else if( tok == T_LEFT )
3425  {
3426  tok = NextTok();
3427  if( tok != T_net )
3428  Expecting( T_net );
3429  growth->net_id = CurText();
3430  NeedRIGHT();
3431  }
3432  else
3433  Unexpected( CurText() );
3434  }
3435 }
3436 
3437 
3438 void SPECCTRA_DB::ExportPCB( wxString aFilename, bool aNameChange )
3439 {
3440  if( pcb )
3441  {
3442  FILE_OUTPUTFORMATTER formatter( aFilename, wxT( "wt" ), quote_char[0] );
3443 
3444  if( aNameChange )
3445  pcb->pcbname = TO_UTF8( aFilename );
3446 
3447  pcb->Format( &formatter, 0 );
3448  }
3449 }
3450 
3451 
3452 void SPECCTRA_DB::ExportSESSION( wxString aFilename )
3453 {
3454  if( session )
3455  {
3456  FILE_OUTPUTFORMATTER formatter( aFilename, wxT( "wt" ), quote_char[0] );
3457 
3458  session->Format( &formatter, 0 );
3459  }
3460 }
3461 
3462 
3464 {
3465  PCB* pcb = new PCB();
3466 
3467  pcb->parser = new PARSER( pcb );
3468  pcb->resolution = new UNIT_RES( pcb, T_resolution );
3469  pcb->unit = new UNIT_RES( pcb, T_unit );
3470 
3471  pcb->structure = new STRUCTURE( pcb );
3472  pcb->structure->boundary = new BOUNDARY( pcb->structure );
3473  pcb->structure->via = new VIA( pcb->structure );
3474  pcb->structure->rules = new RULE( pcb->structure, T_rule );
3475 
3476  pcb->placement = new PLACEMENT( pcb );
3477 
3478  pcb->library = new LIBRARY( pcb );
3479 
3480  pcb->network = new NETWORK( pcb );
3481 
3482  pcb->wiring = new WIRING( pcb );
3483 
3484  return pcb;
3485 }
3486 
3487 
3488 //-----<ELEM>---------------------------------------------------------------
3489 
3490 ELEM::ELEM( T aType, ELEM* aParent ) :
3491  type( aType ),
3492  parent( aParent )
3493 {
3494 }
3495 
3496 
3498 {
3499 }
3500 
3501 const char* ELEM::Name() const
3502 {
3503  return SPECCTRA_DB::TokenName( type );
3504 }
3505 
3507 {
3508  if( parent )
3509  return parent->GetUnits();
3510 
3511  return &UNIT_RES::Default;
3512 }
3513 
3514 
3515 void ELEM::Format( OUTPUTFORMATTER* out, int nestLevel )
3516 {
3517  out->Print( nestLevel, "(%s\n", Name() );
3518 
3519  FormatContents( out, nestLevel+1 );
3520 
3521  out->Print( nestLevel, ")\n" );
3522 }
3523 
3524 
3526 {
3527  for( int i=0; i<Length(); ++i )
3528  {
3529  At(i)->Format( out, nestLevel );
3530  }
3531 }
3532 
3533 
3534 int ELEM_HOLDER::FindElem( T aType, int instanceNum )
3535 {
3536  int repeats=0;
3537  for( unsigned i=0; i<kids.size(); ++i )
3538  {
3539  if( kids[i].Type() == aType )
3540  {
3541  if( repeats == instanceNum )
3542  return i;
3543  ++repeats;
3544  }
3545  }
3546  return -1;
3547 }
3548 
3549 
3550 // a reasonably small memory price to pay for improved performance
3552 
3553 
3554 //-----<UNIT_RES>---------------------------------------------------------
3555 
3557 
3558 
3559 //-----<PADSTACK>---------------------------------------------------------
3560 
3562 {
3563  // printf( "PADSTACK::Compare( %p, %p)\n", lhs, rhs );
3564 
3565  if( !lhs->hash.size() )
3566  lhs->hash = lhs->makeHash();
3567 
3568  if( !rhs->hash.size() )
3569  rhs->hash = rhs->makeHash();
3570 
3571  int result = lhs->hash.compare( rhs->hash );
3572  if( result )
3573  return result;
3574 
3575  // Via names hold the drill diameters, so we have to include those to discern
3576  // between two vias with same copper size but with different drill sizes.
3577  result = lhs->padstack_id.compare( rhs->padstack_id );
3578 
3579  return result;
3580 }
3581 
3582 
3583 //-----<IMAGE>------------------------------------------------------------
3584 
3585 int IMAGE::Compare( IMAGE* lhs, IMAGE* rhs )
3586 {
3587  if( !lhs->hash.size() )
3588  lhs->hash = lhs->makeHash();
3589 
3590  if( !rhs->hash.size() )
3591  rhs->hash = rhs->makeHash();
3592 
3593  int result = lhs->hash.compare( rhs->hash );
3594 
3595  // printf("\"%s\" \"%s\" ret=%d\n", lhs->hash.c_str(), rhs->hash.c_str(), result );
3596 
3597  return result;
3598 }
3599 
3600 
3601 //-----<COMPONENT>--------------------------------------------------------
3602 
3603 /*
3604 int COMPONENT::Compare( COMPONENT* lhs, COMPONENT* rhs )
3605 {
3606  if( !lhs->hash.size() )
3607  lhs->hash = lhs->makeHash();
3608 
3609  if( !rhs->hash.size() )
3610  rhs->hash = rhs->makeHash();
3611 
3612  int result = lhs->hash.compare( rhs->hash );
3613  return result;
3614 }
3615 */
3616 
3617 //-----<PARSER>-----------------------------------------------------------
3618 PARSER::PARSER( ELEM* aParent ) :
3619  ELEM( T_parser, aParent )
3620 {
3621  string_quote = '"';
3622  space_in_quoted_tokens = false;
3623 
3624  case_sensitive = false;
3625  wires_include_testpoint = false;
3626  routes_include_testpoint = false;
3627  routes_include_guides = false;
3629  via_rotate_first = true;
3630  generated_by_freeroute = false;
3631 
3632  host_cad = "KiCad's Pcbnew";
3633  wxString msg = GetBuildVersion();
3634  host_version = TO_UTF8(msg);
3635 }
3636 
3637 
3638 void PARSER::FormatContents( OUTPUTFORMATTER* out, int nestLevel )
3639 {
3640  out->Print( nestLevel, "(string_quote %c)\n", string_quote );
3641  out->Print( nestLevel, "(space_in_quoted_tokens %s)\n", space_in_quoted_tokens ? "on" : "off" );
3642  out->Print( nestLevel, "(host_cad \"%s\")\n", host_cad.c_str() );
3643  out->Print( nestLevel, "(host_version \"%s\")\n", host_version.c_str() );
3644 
3645  for( STRINGS::iterator i=constants.begin(); i!=constants.end(); )
3646  {
3647  const std::string& s1 = *i++;
3648  const std::string& s2 = *i++;
3649 
3650  const char* q1 = out->GetQuoteChar( s1.c_str() );
3651  const char* q2 = out->GetQuoteChar( s2.c_str() );
3652  out->Print( nestLevel, "(constant %s%s%s %s%s%s)\n",
3653  q1, s1.c_str(), q1,
3654  q2, s2.c_str(), q2 );
3655  }
3656 
3658  out->Print( nestLevel, "(routes_include%s%s%s)\n",
3659  routes_include_testpoint ? " testpoint" : "",
3660  routes_include_guides ? " guides" : "",
3661  routes_include_image_conductor ? " image_conductor" : "");
3662 
3664  out->Print( nestLevel, "(wires_include testpoint)\n" );
3665 
3666  if( !via_rotate_first )
3667  out->Print( nestLevel, "(via_rotate_first off)\n" );
3668 
3669  if( case_sensitive )
3670  out->Print( nestLevel, "(case_sensitive %s)\n", case_sensitive ? "on" : "off" );
3671 }
3672 
3673 
3674 void PLACE::Format( OUTPUTFORMATTER* out, int nestLevel )
3675 {
3676  bool useMultiLine;
3677 
3678  const char* quote = out->GetQuoteChar( component_id.c_str() );
3679 
3680  if( place_rules || properties.size() || rules || region )
3681  {
3682  useMultiLine = true;
3683 
3684  out->Print( nestLevel, "(%s %s%s%s\n", Name(),
3685  quote, component_id.c_str(), quote );
3686 
3687  out->Print( nestLevel+1, "%s", "" );
3688  }
3689  else
3690  {
3691  useMultiLine = false;
3692 
3693  out->Print( nestLevel, "(%s %s%s%s", Name(),
3694  quote, component_id.c_str(), quote );
3695  }
3696 
3697  if( hasVertex )
3698  {
3699  out->Print( 0, " %.6g %.6g", vertex.x, vertex.y );
3700 
3701  out->Print( 0, " %s", GetTokenText( side ) );
3702 
3703  out->Print( 0, " %.6g", rotation );
3704  }
3705 
3706  const char* space = " "; // one space, as c string.
3707 
3708  if( mirror != T_NONE )
3709  {
3710  out->Print( 0, "%s(mirror %s)", space, GetTokenText( mirror ) );
3711  space = "";
3712  }
3713 
3714  if( status != T_NONE )
3715  {
3716  out->Print( 0, "%s(status %s)", space, GetTokenText( status ) );
3717  space = "";
3718  }
3719 
3720  if( logical_part.size() )
3721  {
3722  quote = out->GetQuoteChar( logical_part.c_str() );
3723  out->Print( 0, "%s(logical_part %s%s%s)", space,
3724  quote, logical_part.c_str(), quote );
3725  space = "";
3726  }
3727 
3728  if( useMultiLine )
3729  {
3730  out->Print( 0, "\n" );
3731  if( place_rules )
3732  {
3733  place_rules->Format( out, nestLevel+1 );
3734  }
3735 
3736  if( properties.size() )
3737  {
3738  out->Print( nestLevel+1, "(property \n" );
3739 
3740  for( PROPERTIES::const_iterator i = properties.begin();
3741  i != properties.end(); ++i )
3742  {
3743  i->Format( out, nestLevel+2 );
3744  }
3745  out->Print( nestLevel+1, ")\n" );
3746  }
3747  if( lock_type != T_NONE )
3748  out->Print( nestLevel+1, "(lock_type %s)\n", GetTokenText(lock_type) );
3749  if( rules )
3750  rules->Format( out, nestLevel+1 );
3751 
3752  if( region )
3753  region->Format( out, nestLevel+1 );
3754 
3755  if( part_number.size() )
3756  {
3757  quote = out->GetQuoteChar( part_number.c_str() );
3758  out->Print( nestLevel+1, "(PN %s%s%s)\n",
3759  quote, part_number.c_str(), quote );
3760  }
3761  }
3762  else
3763  {
3764  if( lock_type != T_NONE )
3765  {
3766  out->Print( 0, "%s(lock_type %s)", space, GetTokenText(lock_type) );
3767  space = "";
3768  }
3769 
3770  if( part_number.size() )
3771  {
3772  quote = out->GetQuoteChar( part_number.c_str() );
3773  out->Print( 0, "%s(PN %s%s%s)", space,
3774  quote, part_number.c_str(), quote );
3775  }
3776  }
3777 
3778  out->Print( 0, ")\n" );
3779 }
3780 
3781 } // namespace DSN
3782 
3783 
3784 //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:1011
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:2428
bool space_in_quoted_tokens
Definition: specctra.h:372
DSN_T side
Definition: specctra.h:1984
POINT vertex[3]
Definition: specctra.h:776
std::string layer_id
Definition: specctra.h:443
std::string pin_id
Definition: specctra.h:1929
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:2469
DSN_T lock_type
Definition: specctra.h:1681
double aperture_width
Definition: specctra.h:775
std::string shield
Definition: specctra.h:2864
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:2114
ELEM(DSN_T aType, ELEM *aParent=0)
Definition: specctra.cpp:3490
STRINGS placement_ids
Definition: specctra.h:2538
DSN_T attr
Definition: specctra.h:2863
Class NET corresponds to a in the DSN spec.
Definition: specctra.h:2568
This source file implements export and import capabilities to the specctra dsn file format...
Definition: specctra.cpp:62
COPPER_PLANES planes
Definition: specctra.h:1543
PIN_PAIRS pin_pairs
Definition: specctra.h:3507
CLASSES * classes
Definition: specctra.h:1099
void doCLASS_CLASS(CLASS_CLASS *growth)
Definition: specctra.cpp:1580
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:2730
STRINGS comments
Definition: specctra.h:3273
void doGRID(GRID *growth)
Definition: specctra.cpp:1648
double y
Definition: specctra.h:97
std::string net_id
Definition: specctra.h:2572
bool via_rotate_first
Definition: specctra.h:378
DSN_T direction
T_x | T_y | -1 for both.
Definition: specctra.h:1454
UNIT_RES * unit
Definition: specctra.h:3097
FROMTOS fromtos
Definition: specctra.h:2593
void doWIRE(WIRE *growth)
Definition: specctra.cpp:2757
STRINGS padstacks
Definition: specctra.h:1015
KEEPOUTS keepouts
Definition: specctra.h:1997
std::string component_id
Definition: specctra.h:2430
char SetStringDelimiter(char aStringDelimiter)
Function SetStringDelimiter changes the string delimiter from the default " to some other character a...
Definition: dsnlexer.h:344
Definition: hash_eda.h:42
void doCONTROL(CONTROL *growth)
Definition: specctra.cpp:1187
PIN_REFS pin_refs
Definition: specctra.h:3317
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:3506
RULE * rules
Definition: specctra.h:1539
void doROUTE(ROUTE *growth)
Definition: specctra.cpp:3251
STRINGS class_ids
Definition: specctra.h:1076
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:3485
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:3572
PINS pins
Definition: specctra.h:1992
Class SESSION corresponds to the in the specctra dsn spec.
Definition: specctra.h:3533
void doTOKPROP(TOKPROP *growth)
Definition: specctra.cpp:1145
NET_OUTS net_outs
Definition: specctra.h:3422
void doLAYER(LAYER *growth)
Definition: specctra.cpp:1257
double offset
Definition: specctra.h:1455
ELEM * shape
Definition: specctra.h:903
void doSPECCTRA_LAYER_PAIR(SPECCTRA_LAYER_PAIR *growth)
Definition: specctra.cpp:574
RULE * rules
Definition: specctra.h:2471
Class BOARD to handle a board.
std::string base_design
Definition: specctra.h:3538
static int Compare(PADSTACK *lhs, PADSTACK *rhs)
Function Compare compares two objects of this type and returns <0, 0, or >0.
Definition: specctra.cpp:3561
void doPROPERTIES(PROPERTIES *growth)
Definition: specctra.cpp:1234
std::string part_number
Definition: specctra.h:1688
std::string net_id
Definition: specctra.h:3318
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:2589
bool routes_include_testpoint
Definition: specctra.h:375
void doNET(NET *growth)
Definition: specctra.cpp:2320
std::string logical_part
Definition: specctra.h:1675
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:1529
void doPLACE(PLACE *growth)
Definition: specctra.cpp:1738
POINTS vertexes
Definition: specctra.h:2962
void doVIA(VIA *growth)
Definition: specctra.cpp:1158
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:2585
std::string quote_char
Definition: specctra.h:3616
UNIT_RES * unit
Definition: specctra.h:2105
UNIT_RES * resolution
Definition: specctra.h:3141
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:2235
void doRESOLUTION(UNIT_RES *growth)
Definition: specctra.cpp:526
void doWIRING(WIRING *growth)
Definition: specctra.cpp:2983
Class CLASS corresponds to the in the specctra spec.
Definition: specctra.h:2721
void doREGION(REGION *growth)
Definition: specctra.cpp:1511
PLACES places
Definition: specctra.h:1746
double x
Definition: specctra.h:96
int direction
Definition: specctra.h:1182
ELEM * At(int aIndex) const
Definition: specctra.h:343
STRUCTURE * structure
Definition: specctra.h:3541
std::string via_id
Definition: specctra.h:2112
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:3884
void SetRotation(double aRotation)
Definition: specctra.h:1944
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:3143
virtual ~ELEM()
Definition: specctra.cpp:3497
void doCOMPONENT(COMPONENT *growth)
Definition: specctra.cpp:1853
PIN_REFS noexpose
Definition: specctra.h:2580
COMP_ORDER * comp_order
Definition: specctra.h:2595
RULE * rules
Definition: specctra.h:1408
Class PROPERTIES is a name/value tuple with unique names and optional values.
Definition: properties.h:34
WIRING * wiring
Definition: specctra.h:3147
PIN_REF was
Definition: specctra.h:3493
Class WAS_IS corresponds to the in the specctra dsn spec.
Definition: specctra.h:3503
static PCB * MakePCB()
Function MakePCB makes a PCB with all the default ELEMs and parts on the heap.
Definition: specctra.cpp:3463
std::string net_id
Definition: specctra.h:2963
DSN_T grid_type
T_via | T_wire | T_via_keepout | T_place | T_snap.
Definition: specctra.h:1452
std::string class_id
Definition: specctra.h:2725
void doIMAGE(IMAGE *growth)
Definition: specctra.cpp:2123
int cost_type
T_length | T_way.
Definition: specctra.h:1184
IMAGES images
Definition: specctra.h:2236
STRUCTURE_OUT * structure_out
Definition: specctra.h:3420
DSN_T image_type
Definition: specctra.h:1456
std::string layer_id
Definition: specctra.h:580
PIN_REF is
Definition: specctra.h:3494
BOUNDARY * place_boundary
Definition: specctra.h:1536
bool supply
Definition: specctra.h:2867
time_t time_stamp
Definition: specctra.h:3272
DSN_T via_type
Definition: specctra.h:2965
DSN_T status
Definition: specctra.h:1673
void ExportPCB(wxString aFilename, bool aNameChange=false)
Function ExportPCB writes the internal PCB instance out as a SPECTRA DSN format file.
Definition: specctra.cpp:3438
Class RULE corresponds to the in the specctra dsn spec.
Definition: specctra.h:492
void SetVertex(const POINT &aVertex)
Definition: specctra.h:1718
Functions relatives to tracks, vias and segments used to fill zones.
RECTANGLE * rectangle
Definition: specctra.h:1400
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:1538
This file contains miscellaneous commonly used macros and functions.
void doLIBRARY(LIBRARY *growth)
Definition: specctra.cpp:2266
void doANCESTOR(ANCESTOR *growth)
Definition: specctra.cpp:3039
STRINGS layer_ids
Definition: specctra.h:536
POINT vertex
Definition: specctra.h:1670
void doWINDOW(WINDOW *growth)
Definition: specctra.cpp:912
void SetSESSION(SESSION *aSession)
Function SetSESSION deletes any existing SESSION and replaces it with the given one.
Definition: specctra.h:3895
void doRULE(RULE *growth)
Definition: specctra.cpp:1379
static int Compare(IMAGE *lhs, IMAGE *rhs)
Function Compare compares two objects of this type and returns <0, 0, or >0.
Definition: specctra.cpp:3585
Class PATH supports both the and the per the specctra dsn spec...
Definition: specctra.h:576
bool unassigned
Definition: specctra.h:2573
int turret
Definition: specctra.h:2861
const char * Name() const
Definition: specctra.cpp:3501
Class COMP_ORDER corresponds to the .
Definition: specctra.h:2534
FROMTOS fromtos
Definition: specctra.h:2696
double rotation
Definition: specctra.h:1667
bool hasVertex
Definition: specctra.h:1669
#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:2858
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:1181
void doCOMP_ORDER(COMP_ORDER *growth)
Definition: specctra.cpp:2653
std::string comment
Definition: specctra.h:3228
ANCESTORS ancestors
Definition: specctra.h:3271
WIRES wires
Definition: specctra.h:3098
RULE * place_rules
Definition: specctra.h:1548
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:2473
std::string image_id
Definition: specctra.h:1983
int net_number
Definition: specctra.h:2574
std::string name
Definition: specctra.h:1180
WIRES wires
Definition: specctra.h:3368
PIN_REFS terminator
Definition: specctra.h:2583
std::string net_id
Definition: specctra.h:2470
Class TOKPROP is a container for a single property whose value is another DSN_T token.
Definition: specctra.h:1342
std::string session_id
Definition: specctra.h:3537
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:3176
std::string host_version
Definition: specctra.h:385
RULE * place_rules
Definition: specctra.h:1995
DSN::T CurTok()
Function CurTok returns whatever NextTok() returned the last time it was called.
void doCLASS(CLASS *growth)
Definition: specctra.cpp:2498
DSN_T rotate
Definition: specctra.h:2109
Class COPPER_PLANE corresponds to a in the specctra dsn spec.
Definition: specctra.h:1325
wxString GetBuildVersion()
Function GetBuildVersion Return the build version string.
DSN_T attach
Definition: specctra.h:2111
bool routes_include_image_conductor
Definition: specctra.h:377
std::string padstack_id
Definition: specctra.h:2961
void doPADSTACK(PADSTACK *growth)
Definition: specctra.cpp:1938
RULE * rules
Definition: specctra.h:3367
DSN_T side
Definition: specctra.h:1665
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:1012
Class PLACE implements the in the specctra dsn spec.
Definition: specctra.h:1659
void doSUPPLY_PIN(SUPPLY_PIN *growth)
Definition: specctra.cpp:3402
LAYER_NOISE_WEIGHT * layer_noise_weight
Definition: specctra.h:1533
void doRECTANGLE(RECTANGLE *growth)
Definition: specctra.cpp:1060
bool via_at_smd
Definition: specctra.h:1138
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:3077
PROPERTIES properties
Definition: specctra.h:1679
PARSER * parser
Definition: specctra.h:3419
DSN_T connect
Definition: specctra.h:1867
PIN_REFS expose
Definition: specctra.h:2579
LIBRARY * library
Definition: specctra.h:3421
std::string hash
a hash string used by Compare(), not Format()ed/exported.
Definition: specctra.h:2102
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:1677
PATH * polygon
Definition: specctra.h:1401
std::string filename
Definition: specctra.h:3227
SUPPLY_PINS supply_pins
Definition: specctra.h:3370
std::string region_id
Definition: specctra.h:1397
std::string image_id
Definition: specctra.h:1745
void AddPadstack(PADSTACK *aPadstack)
Definition: specctra.h:2254
std::string component_id
reference designator
Definition: specctra.h:1663
Class PADSTACK holds either a via or a pad definition.
Definition: specctra.h:2098
void Append(ELEM *aElem)
Definition: specctra.h:321
WIRE_VIAS wire_vias
Definition: specctra.h:3099
Definition: hash_eda.h:43
std::string fromText
Definition: specctra.h:2466
void ExportSESSION(wxString aFilename)
Function ExportSESSION writes the internal SESSION instance out as a SPECTRA DSN format file...
Definition: specctra.cpp:3452
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:2582
WIRE_VIAS wire_vias
Definition: specctra.h:3369
POINT vertex
Definition: specctra.h:729
CLASSLIST classes
Definition: specctra.h:2812
REGIONS regions
Definition: specctra.h:1546
void doPCB(PCB *growth)
Definition: specctra.cpp:282
WINDOWS windows
Definition: specctra.h:2865
RECTANGLE * rectangle
Definition: specctra.h:655
RULE * rules
Definition: specctra.h:1684
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:3625
void doCLASSES(CLASSES *growth)
Definition: specctra.cpp:1625
double dimension
Definition: specctra.h:1453
std::string layer_id
Definition: specctra.h:726
std::string padstack_id
Definition: specctra.h:1926
std::string layer_id
Definition: specctra.h:774
UNIT_RES * resolution
Definition: specctra.h:3418
void doWIRE_VIA(WIRE_VIA *growth)
Definition: specctra.cpp:2879
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:3515
DSN_T type
Definition: specctra.h:199
PARSER * parser
Definition: specctra.h:3140
void doCIRCLE(CIRCLE *growth)
Definition: specctra.cpp:1085
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:327
void SetRotation(double aRotation)
Definition: specctra.h:1725
int LAYER_NUM
Type LAYER_NUM can be replaced with int and removed.
SESSION * session
Definition: specctra.h:3614
LIBRARY * library
Definition: specctra.h:3145
DSN_T flip_style
Definition: specctra.h:1793
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:1863
PLACEMENT * placement
Definition: specctra.h:3542
LAYER_RULES layer_rules
Definition: specctra.h:2591
void doSTRINGPROP(STRINGPROP *growth)
Definition: specctra.cpp:1137
void doPIN(PIN *growth)
Definition: specctra.cpp:2219
static const char * TokenName(DSN::T aTok)
Function TokenName returns the name of the token in ASCII form.
STRINGS spares
Definition: specctra.h:1016
time_t time_stamp
Definition: specctra.h:3229
COMP_ORDERS comp_orders
Definition: specctra.h:2698
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:1185
bool case_sensitive
Definition: specctra.h:373
void doTOPOLOGY(TOPOLOGY *growth)
Definition: specctra.cpp:2460
Class COMPONENT implements the in the specctra dsn spec.
Definition: specctra.h:1739
Class LIBRARY corresponds to the in the specctra dsn specification.
Definition: specctra.h:2231
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:1791
Class WIRE corresponds to in the specctra dsn spec.
Definition: specctra.h:2847
std::vector< PIN_REF > PIN_REFS
Definition: specctra.h:2459
PATHS paths
Definition: specctra.h:654
STRINGS contact_layers
Definition: specctra.h:2968
int net_number
Definition: specctra.h:3366
STRINGS layerIds
indexed by PCB layer number
Definition: specctra.h:3622
DSN_T value
Definition: specctra.h:1346
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:3534
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:3144
void doSHAPE(SHAPE *growth)
Definition: specctra.cpp:2038
Class STRINGPROP is a container for a single property whose value is a string.
Definition: specctra.h:1370
LAYER_RULES layer_rules
Definition: specctra.h:2734
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:2732
UNIT_RES * unit
Definition: specctra.h:1985
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:1713
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:3525
static bool empty(const wxTextEntryBase *aCtrl)
RULE * rules
Definition: specctra.h:1994
double aperture_width
Definition: specctra.h:581
REGION * region
Definition: specctra.h:1685
BOUNDARY * boundary
Definition: specctra.h:1535
DSN_T mirror
Definition: specctra.h:1672
std::string padstack_id
Definition: specctra.h:2104
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:3544
Class NET_OUT corresponds to the of the specctra dsn spec.
Definition: specctra.h:3361
PARSER(ELEM *aParent)
Definition: specctra.cpp:3618
UNIT_RES * unit
Definition: specctra.h:3142
STRINGS use_net
Definition: specctra.h:1186
ELEM * shape
Definition: specctra.h:837
void doPLACEMENT(PLACEMENT *growth)
Definition: specctra.cpp:1883
int cost
[forbidden | high | medium | low | free | | -1]
Definition: specctra.h:1183
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:3674
LAYERS layers
Definition: specctra.h:1531
PIN_REFS pins
Definition: specctra.h:2577
Class WIRE_VIA corresponds to in the specctra dsn spec.
Definition: specctra.h:2957
void doNETWORK(NETWORK *growth)
Definition: specctra.cpp:2608
std::string value
Definition: specctra.h:1374
TOPOLOGY * topology
Definition: specctra.h:2736
void doNET_OUT(NET_OUT *growth)
Definition: specctra.cpp:3334
PIN_REFS source
Definition: specctra.h:2581
Class ELEM is a base class for any DSN element class.
Definition: specctra.h:194
std::string virtual_pin_name
Definition: specctra.h:2967
std::string pin_id
Definition: specctra.h:2431
WINDOWS windows
Definition: specctra.h:894
DSN_T wire_type
Definition: specctra.h:2862
int PRINTF_FUNC Print(int nestLevel, const char *fmt,...)
Function Print formats and writes text to the output stream.
Definition: richio.cpp:404
WINDOWS windows
Definition: specctra.h:1878
CONNECT * connect
Definition: specctra.h:2866
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:3628
void doCONNECT(CONNECT *growth)
Definition: specctra.cpp:877
DSN_T Type() const
Definition: specctra.h:231
PROPERTIES properties
Definition: specctra.h:1188
STRINGS net_ids
Definition: specctra.h:2727
Class SUPPLY_PIN corresponds to the in the specctra dsn spec.
Definition: specctra.h:3313
std::string hash
a hash string used by Compare(), not Format()ed/exported.
Definition: specctra.h:1981
DSN_T absolute
Definition: specctra.h:2110
std::string pcbname
Definition: specctra.h:3139
Class KEEPOUT is used for and .
Definition: specctra.h:884
void doQARC(QARC *growth)
Definition: specctra.cpp:1113
std::string name
Definition: specctra.h:889
NETWORK * network
Definition: specctra.h:3146
void doSESSION(SESSION *growth)
Definition: specctra.cpp:3133
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:3638
HISTORY * history
Definition: specctra.h:3540
void doPARSER(PARSER *growth)
Definition: specctra.cpp:387
RULE * place_rules
Definition: specctra.h:892
WAS_IS * was_is
Definition: specctra.h:3543
const char * CurText()
Function CurText returns a pointer to the current token's text.
Definition: dsnlexer.h:479
std::string toText
Definition: specctra.h:2467
Class PARSER is simply a configuration record per the SPECCTRA DSN file spec.
Definition: specctra.h:367
void doFROMTO(FROMTO *growth)
Definition: specctra.cpp:2671
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:774
COMPONENTS components
Definition: specctra.h:1795
Class WIRING corresponds to in the specctra dsn spec.
Definition: specctra.h:3093
void doUNIT(UNIT_RES *growth)
Definition: specctra.cpp:553
std::string net_id
Definition: specctra.h:3365
std::string net_id
Definition: specctra.h:2860
POINT vertex
Definition: specctra.h:1930
static STRING_FORMATTER sf
Definition: specctra.h:222
void doWAS_IS(WAS_IS *growth)
Definition: specctra.cpp:3210
SPECCTRA_LAYER_PAIRS layer_pairs
Definition: specctra.h:1300
void doBOUNDARY(BOUNDARY *growth)
Definition: specctra.cpp:965
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:2576
KEEPOUTS keepouts
Definition: specctra.h:1541