1 /* This file is part of Shapes.
3 * Shapes is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
8 * Shapes is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with Shapes. If not, see <http://www.gnu.org/licenses/>.
16 * Copyright 2008 Henrik Tidefelt
19 #include "shapesscanner.h"
22 #include "shapestypes.h"
27 using namespace Shapes
;
28 #include "shapesparser.h"
35 ShapesScanner::ShapesScanner( )
36 : yyFlexLexer( 0, & std::cerr
), moreState( false ), lastleng( 0 ),
37 showFiles( false ), randSeedSet( false ), interactive_( false )
39 shapeslloc
= Ast::THE_UNKNOWN_LOCATION
;
40 unitTable
[ "bp" ] = 1;
41 unitTable
[ "mm" ] = 0.1 * 72 / 2.54;
42 unitTable
[ "cm" ] = 72 / 2.54;
43 unitTable
[ "m" ] = 100 * 72 / 2.54;
44 unitTable
[ "in" ] = 72;
47 ShapesScanner::~ShapesScanner( )
51 ShapesScanner::setInteractive( bool interactive
)
53 interactive_
= interactive
;
56 // The following method is placed in shapesyylex to access YY_BUF_SIZE
57 // ShapesScanner::start( )
60 ShapesScanner::setSourceDir( const std::string
& sourceDir
)
62 sourceDir_
= sourceDir
;
66 ShapesScanner::push_backNeedPath( const std::string
& path
)
69 path
[ path
.size( ) - 1 ] == '/' )
71 needSearchPath
.push_back( path
);
75 needSearchPath
.push_back( path
+ "/" );
80 ShapesScanner::push_frontNeedPath( const std::string
& path
)
83 path
[ path
.size( ) - 1 ] == '/' )
85 needSearchPath
.push_front( path
);
89 needSearchPath
.push_front( path
+ "/" );
94 ShapesScanner::pop_frontNeedPath( )
96 needSearchPath
.pop_front( );
100 ShapesScanner::setShowFiles( bool _showFiles
)
102 showFiles
= _showFiles
;
107 ShapesScanner::more( )
109 moreState
= true; // This one is for ourselves to use in DoBeforeEachAction
110 yy_more_flag
= 1; // This one is for flex, and will be reset before we reach doBeforeEachAction
115 ShapesScanner::doBeforeEachAction( )
119 shapeslloc
.lastColumn
+= yyleng
- lastleng
;
123 shapeslloc
.firstLine
= shapeslloc
.lastLine
;
124 shapeslloc
.firstColumn
= shapeslloc
.lastColumn
;
125 shapeslloc
.lastColumn
= shapeslloc
.firstColumn
+ yyleng
;
131 ShapesScanner::lookupUnitFactor( const char * name
) const
133 typedef typeof unitTable MapType
;
134 MapType::const_iterator i
= unitTable
.find( name
);
135 if( i
== unitTable
.end( ) )
139 return 1 / i
->second
;
143 ShapesScanner::strtoLength( const char * str
) const
146 double scalar
= strtod( str
, &endp
);
147 typedef typeof unitTable MapType
;
148 MapType::const_iterator i
= unitTable
.find( endp
);
149 if( i
== unitTable
.end( ) )
151 throw "Malformed length.";
153 return scalar
* i
->second
;
157 ShapesScanner::searchFile( const std::string
& suffix
) const
159 struct stat theStatDummy
;
160 std::string res
= searchFile( suffix
, & theStatDummy
);
163 for( size_t i
= 0; i
< locStack
.size( ); ++i
)
167 std::cerr
<< " " << res
<< std::endl
;
173 ShapesScanner::searchFile( const std::string
& suffix
, struct stat
* dstStat
) const
177 if( suffix
.empty( ) )
179 throw Exceptions::InternalError( strrefdup( "ShapesScanner::searchFile called with empty argument." ) );
182 if( suffix
[ 0 ] == '/' )
185 if( stat( res
.c_str( ), dstStat
) == 0 )
189 throw Exceptions::FileReadOpenError( shapeslloc
, strrefdup( suffix
), 0, 0 );
192 if( needSearchPath
.empty( ) )
194 throw Exceptions::ScannerError( shapeslloc
, strrefdup( "Relative file inclusion impossible since search path is empty." ) );
197 typedef typeof needSearchPath ListType
;
198 for( ListType::const_iterator i
= needSearchPath
.begin( ); i
!= needSearchPath
.end( ); ++i
)
200 res
= needpathWithSuffix( *i
, suffix
);
202 if( stat( res
.c_str( ), dstStat
) == 0 )
207 throw Exceptions::FileReadOpenError( shapeslloc
, strrefdup( suffix
), & sourceDir_
, & needSearchPath
);
211 ShapesScanner::needpathWithSuffix( const std::string
& needpath
, const std::string
& suffix
) const
213 if( needpath
[0] == '/' )
215 return needpath
+ suffix
;
217 else if( needpath
== "./" )
219 return sourceDir_
+ suffix
;
223 return sourceDir_
+ needpath
+ suffix
;
228 ShapesScanner::rinseString( )
230 /* Both types of strings are terminated by a two byte sequence, ") or ยด. */
231 size_t bytecount
= yyleng
- ( ( yyleng
>= 3 && yytext
[ yyleng
- 3 ] == '\n' ) ? 3 : 2 );
232 char * res
= new char[ bytecount
+ 1 ];
233 memcpy( res
, yytext
, bytecount
);
234 res
[ bytecount
] = '\0';
235 shapeslval
.Lang_String
= new Lang::String( RefCountPtr
< const char >( res
), bytecount
);
239 ShapesScanner::concatenateDataString( )
241 /* Remember: strcpy, strdup and friends may fail here, since the string may contain zeros. */
243 char * res
= new char[ dataStringTotalLength_
+ 1 ];
245 while( ! dataStringChunks_
.empty( ) )
247 char * ptr
= dataStringChunks_
.front( ).first
;
248 memcpy( dst
, ptr
, dataStringChunks_
.front( ).second
);
249 dst
+= dataStringChunks_
.front( ).second
;
251 dataStringChunks_
.pop_front( );
254 shapeslval
.Lang_String
= new Lang::String( RefCountPtr
< const char >( res
), dataStringTotalLength_
);