diff --git a/common/string.cpp b/common/string.cpp index cf07d307db..ca630ada3d 100644 --- a/common/string.cpp +++ b/common/string.cpp @@ -20,15 +20,7 @@ int ReadDelimitedText( char* aDest, const char* aSource, int aDestSize ) while( (cc = *aSource++) != 0 && aDest < limit ) { - if( cc == '\\' ) - { - cc = *aSource++; - - if( inside ) - *aDest++ = cc; - } - - else if( cc == '"' ) + if( cc == '"' ) { if( inside ) break; // 2nd double quote is end of delimited text @@ -38,7 +30,19 @@ int ReadDelimitedText( char* aDest, const char* aSource, int aDestSize ) else if( inside ) { - *aDest++ = cc; + if( cc == '\\' ) + { + cc = *aSource++; + + // do no copy the escape byte if it is followed by \ or " + if( cc != '"' && cc != '\\' ) + *aDest++ = '\\'; + + if( aDest < limit ) + *aDest++ = cc; + } + else + *aDest++ = cc; } } diff --git a/new/make-dir-lib-source-test-data.sh b/new/make-dir-lib-source-test-data.sh index 704d44840b..5f804ef372 100755 --- a/new/make-dir-lib-source-test-data.sh +++ b/new/make-dir-lib-source-test-data.sh @@ -8,6 +8,10 @@ PARTS="eyes ears feet" REVS="rev1 rev5 rev10" +LINE="(line (pts (xy 12 13)(xy 12 20))(line_width 1.5))" +RECT="(rectangle (start 4 5)(end 6 8)(line_width 2.3)(fill transparent))" +CIRCLE="(circle (center 1 0)(radius 5)(line_width 2.1)(fill none))" +ARC="(arc (pos 22 33)(radius 12)(start 2 4)(end 13 33)(line_width 2.3)(fill filled))" for C in ${CATEGORIES}; do @@ -16,10 +20,10 @@ for C in ${CATEGORIES}; do for P in ${PARTS}; do for R in ${REVS}; do - echo "(part $C/$P (value 22)(footprint SM0805))" > $BASEDIR/$C/$P.part.$R + echo "(part $C/$P (value 22)(footprint SM0805)(model Airplane)$LINE$RECT$CIRCLE$ARC)" > $BASEDIR/$C/$P.part.$R done # also make the part without a rev: - echo "(part $C/$P (value 22)(footprint SM0805))" > $BASEDIR/$C/$P.part + echo "(part $C/$P (value 22)(footprint SM0805)(model Airplane)$LINE$RECT$CIRCLE$ARC)" > $BASEDIR/$C/$P.part done done diff --git a/new/sch_part.h b/new/sch_part.h index 03ecf2531f..4b3ea04890 100644 --- a/new/sch_part.h +++ b/new/sch_part.h @@ -34,6 +34,7 @@ public: virtual ~BASE_GRAPHIC() {} }; +typedef std::vector POINTS; class POLY_LINE : BASE_GRAPHIC { @@ -41,8 +42,8 @@ class POLY_LINE : BASE_GRAPHIC friend class SWEET_PARSER; protected: - double width; - std::vector pts; + double lineWidth; + POINTS pts; public: POLY_LINE( PART* aOwner ) : @@ -51,9 +52,64 @@ public: }; +class RECTANGLE : BASE_GRAPHIC +{ + friend class PART; + friend class SWEET_PARSER; + +protected: + double lineWidth; + int fillType; // T_none, T_filled, or T_transparent + POINT start; + POINT end; + +public: + RECTANGLE( PART* aOwner ) : + BASE_GRAPHIC( aOwner ) + {} }; +class CIRCLE : BASE_GRAPHIC +{ + friend class PART; + friend class SWEET_PARSER; + +protected: + double lineWidth; + int fillType; // T_none, T_filled, or T_transparent + POINT center; + int radius; + +public: + CIRCLE( PART* aOwner ) : + BASE_GRAPHIC( aOwner ) + {} +}; + + +class ARC : BASE_GRAPHIC +{ + friend class PART; + friend class SWEET_PARSER; + +protected: + double lineWidth; + int fillType; // T_none, T_filled, or T_transparent + POINT pos; + int radius; + POINT start; + POINT end; + +public: + ARC( PART* aOwner ) : + BASE_GRAPHIC( aOwner ) + {} +}; + +} // namespace SCH + + //---------------------- @@ -133,7 +189,12 @@ protected: // not likely to have C++ descendants, but protected none-the-le /// Alternate body forms. //ALTERNATES alternates; - // lots of other stuff, like the mandatory properties, but no units, since we went with dimensionless + // mandatory properties + wxString value; + wxString footprint; + wxString model; + wxString keywords; + public: @@ -160,6 +221,33 @@ public: */ void Parse( SWEET_PARSER* aParser, LIB_TABLE* aLibTable ) throw( IO_ERROR, PARSE_ERROR ); + void SetValue( const wxString& aValue ) + { + value = aValue; + } + const wxString& GetValue() + { + return value; + } + + void SetFootprint( const wxString& aFootprint ) + { + footprint = aFootprint; + } + const wxString& GetFootprint() + { + return footprint; + } + + void SetModel( const wxString& aModel ) + { + model = aModel; + } + const wxString& GetModel() + { + return model; + } + /* void SetBody( const STR_UTF& aSExpression ) { diff --git a/new/sch_sweet_parser.cpp b/new/sch_sweet_parser.cpp index a3b994b00b..150486406e 100644 --- a/new/sch_sweet_parser.cpp +++ b/new/sch_sweet_parser.cpp @@ -27,6 +27,8 @@ #include #include +#include // FROM_UTF8() + using namespace SCH; using namespace PR; @@ -203,29 +205,66 @@ void SWEET_PARSER::Parse( PART* me, LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_E break; case T_line: + case T_polyline: POLY_LINE* pl; pl = new POLY_LINE( me ); me->graphics.push_back( pl ); parsePolyLine( pl ); break; + case T_rectangle: + RECTANGLE* rect; + rect = new RECTANGLE( me ); + me->graphics.push_back( rect ); + parseRectangle( rect ); + break; + + case T_circle: + CIRCLE* circ; + circ = new CIRCLE( me ); + me->graphics.push_back( circ ); + parseCircle( circ ); + break; + + case T_arc: + ARC* arc; + arc = new ARC( me ); + me->graphics.push_back( arc ); + parseArc( arc ); + break; - /* case T_value: if( contains & PB(VALUE) ) Duplicate( tok ); contains |= PB(VALUE); NeedSYMBOLorNUMBER(); - // me->value = CurText(); + me->SetValue( FROM_UTF8( CurText() ) ); + // @todo handle optional (effects..) here NeedRIGHT(); break; case T_footprint: + if( contains & PB(FOOTPRINT) ) + Duplicate( tok ); + contains |= PB(FOOTPRINT); + NeedSYMBOLorNUMBER(); + me->SetFootprint( FROM_UTF8( CurText() ) ); + // @todo handle optional (effects..) here + NeedRIGHT(); break; case T_model: + if( contains & PB(MODEL) ) + Duplicate( tok ); + contains |= PB(MODEL); + NeedSYMBOLorNUMBER(); + me->SetModel( FROM_UTF8( CurText() ) ); + // @todo handle optional (effects..) here + NeedRIGHT(); break; + + /* case T_keywords: break; @@ -256,18 +295,6 @@ void SWEET_PARSER::Parse( PART* me, LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_E case T_route_pin_swap: break; - case T_polyline: - break; - - case T_rectangle: - break; - - case T_circle: - break; - - case T_arc: - break; - case T_bezier: break; @@ -299,14 +326,15 @@ void SWEET_PARSER::parsePolyLine( POLY_LINE* me ) NeedLEFT(); while( ( tok = NextTok() ) != T_RIGHT ) { - NeedLEFT(); + if( tok == T_LEFT ) + tok = NextTok(); - tok = NextTok(); switch( tok ) { case T_line_width: NeedNUMBER( "line_width" ); - me->width = strtod( CurText(), NULL ); + me->lineWidth = strtod( CurText(), NULL ); + NeedRIGHT(); break; case T_pts: @@ -319,13 +347,20 @@ void SWEET_PARSER::parsePolyLine( POLY_LINE* me ) if( tok != T_xy ) Expecting( T_xy ); - /* @todo resume here, its late - NeedNUMBER(); - */ + me->pts.push_back( POINT() ); + + NeedNUMBER( "x" ); + me->pts.back().x = internal( CurText() ); + + NeedNUMBER( "y" ); + me->pts.back().y = internal( CurText() ); + + NeedRIGHT(); } break; case T_fill: + // @todo figure this out, maybe spit into polygon break; default: @@ -334,3 +369,238 @@ void SWEET_PARSER::parsePolyLine( POLY_LINE* me ) } } + +void SWEET_PARSER::parseRectangle( RECTANGLE* me ) +{ + T tok; + bool sawStart = false; + bool sawEnd = false; + bool sawWidth = false; + bool sawFill = false; + + NeedLEFT(); + while( ( tok = NextTok() ) != T_RIGHT ) + { + if( tok == T_LEFT ) + tok = NextTok(); + + switch( tok ) + { + case T_line_width: + if( sawWidth ) + Duplicate( tok ); + NeedNUMBER( "line_width" ); + me->lineWidth = strtod( CurText(), NULL ); + sawWidth = true; + NeedRIGHT(); + break; + + case T_fill: + if( sawFill ) + Duplicate( tok ); + tok = NeedSYMBOL(); + switch( tok ) + { + case T_none: + case T_filled: + case T_transparent: + me->fillType = tok; + break; + default: + Expecting( "none|filled|transparent" ); + } + NeedRIGHT(); + sawFill = true; + break; + + case T_start: + if( sawStart ) + Duplicate( tok ); + NeedNUMBER( "x" ); + me->start.x = internal( CurText() ); + NeedNUMBER( "y" ); + me->start.y = internal( CurText() ); + NeedRIGHT(); + sawStart = true; + break; + + case T_end: + if( sawEnd ) + Duplicate( tok ); + NeedNUMBER( "x" ); + me->end.x = internal( CurText() ); + NeedNUMBER( "y" ); + me->end.y = internal( CurText() ); + NeedRIGHT(); + sawEnd = true; + break; + + default: + Expecting( "start|end|line_width|fill" ); + } + } +} + + +void SWEET_PARSER::parseCircle( CIRCLE* me ) +{ + T tok; + bool sawCenter = false; + bool sawRadius = false; + bool sawWidth = false; + bool sawFill = false; + + NeedLEFT(); + while( ( tok = NextTok() ) != T_RIGHT ) + { + if( tok == T_LEFT ) + tok = NextTok(); + + switch( tok ) + { + case T_line_width: + if( sawWidth ) + Duplicate( tok ); + NeedNUMBER( "line_width" ); + me->lineWidth = strtod( CurText(), NULL ); + sawWidth = true; + NeedRIGHT(); + break; + + case T_fill: + if( sawFill ) + Duplicate( tok ); + tok = NeedSYMBOL(); + switch( tok ) + { + case T_none: + case T_filled: + case T_transparent: + me->fillType = tok; + break; + default: + Expecting( "none|filled|transparent" ); + } + NeedRIGHT(); + sawFill = true; + break; + + case T_center: + if( sawCenter ) + Duplicate( tok ); + NeedNUMBER( "center x" ); + me->center.x = internal( CurText() ); + NeedNUMBER( "center y" ); + me->center.y = internal( CurText() ); + NeedRIGHT(); + sawCenter = true; + break; + + case T_radius: + if( sawRadius ) + Duplicate( tok ); + NeedNUMBER( "radius" ); + me->radius = internal( CurText() ); + NeedRIGHT(); + sawRadius = true; + break; + + default: + Expecting( "center|radius|line_width|fill" ); + } + } +} + + +void SWEET_PARSER::parseArc( ARC* me ) +{ + T tok; + bool sawPos = false; + bool sawStart = false; + bool sawEnd = false; + bool sawRadius = false; + bool sawWidth = false; + bool sawFill = false; + + NeedLEFT(); + while( ( tok = NextTok() ) != T_RIGHT ) + { + if( tok == T_LEFT ) + tok = NextTok(); + + switch( tok ) + { + case T_line_width: + if( sawWidth ) + Duplicate( tok ); + NeedNUMBER( "line_width" ); + me->lineWidth = strtod( CurText(), NULL ); + sawWidth = true; + NeedRIGHT(); + break; + + case T_fill: + if( sawFill ) + Duplicate( tok ); + tok = NeedSYMBOL(); + switch( tok ) + { + case T_none: + case T_filled: + case T_transparent: + me->fillType = tok; + break; + default: + Expecting( "none|filled|transparent" ); + } + NeedRIGHT(); + sawFill = true; + break; + + case T_pos: + if( sawPos ) + Duplicate( tok ); + NeedNUMBER( "pos x" ); + me->pos.x = internal( CurText() ); + NeedNUMBER( "pos y" ); + me->pos.y = internal( CurText() ); + NeedRIGHT(); + sawPos = true; + break; + + case T_radius: + if( sawRadius ) + Duplicate( tok ); + NeedNUMBER( "radius" ); + me->radius = internal( CurText() ); + NeedRIGHT(); + sawRadius = true; + break; + + case T_start: + if( sawStart ) + Duplicate( tok ); + NeedNUMBER( "start x" ); + me->start.x = internal( CurText() ); + NeedNUMBER( "start y" ); + me->start.y = internal( CurText() ); + NeedRIGHT(); + sawStart = true; + break; + + case T_end: + if( sawEnd ) + Duplicate( tok ); + NeedNUMBER( "end x" ); + me->end.x = internal( CurText() ); + NeedNUMBER( "end y" ); + me->end.y = internal( CurText() ); + NeedRIGHT(); + sawEnd = true; + break; + + default: + Expecting( "center|radius|line_width|fill" ); + } + } +} diff --git a/new/sch_sweet_parser.h b/new/sch_sweet_parser.h index 518b1710a3..4674836abb 100644 --- a/new/sch_sweet_parser.h +++ b/new/sch_sweet_parser.h @@ -34,6 +34,9 @@ namespace SCH { class LIB_TABLE; class PART; class POLY_LINE; +class RECTANGLE; +class CIRCLE; +class ARC; /** @@ -54,7 +57,9 @@ class SWEET_PARSER : public SWEET_LEXER void parseExtends( PART* me ); void parsePolyLine( POLY_LINE* me ); - + void parseRectangle( RECTANGLE* me ); + void parseCircle( CIRCLE* me ); + void parseArc( ARC* me ); public: diff --git a/new/sweet.keywords b/new/sweet.keywords index 60e4e387c8..01cd8e7c8a 100644 --- a/new/sweet.keywords +++ b/new/sweet.keywords @@ -14,6 +14,7 @@ end end_angle extends fill +filled font footprint input @@ -56,6 +57,7 @@ size start start_angle text +transparent tristate unconnected units