Updating the changelog in the VERSION file, and version_sync.
[shapes.git] / source / shapesscanner.cc
blobffd4760859eb6f33b1a532cd009fa081a1091d04
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
6 * any later version.
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"
20 #include "yyltype.h"
22 #include "shapestypes.h"
23 #include "ast.h"
24 #include "astflow.h"
25 #include "astclass.h"
27 using namespace Shapes;
28 #include "shapesparser.h"
30 #include <iostream>
32 using namespace std;
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( )
48 { }
50 void
51 ShapesScanner::setInteractive( bool interactive )
53 interactive_ = interactive;
56 // The following method is placed in shapesyylex to access YY_BUF_SIZE
57 // ShapesScanner::start( )
59 void
60 ShapesScanner::setSourceDir( const std::string & sourceDir )
62 sourceDir_ = sourceDir;
65 void
66 ShapesScanner::push_backNeedPath( const std::string & path )
68 if( path.empty( ) ||
69 path[ path.size( ) - 1 ] == '/' )
71 needSearchPath.push_back( path );
73 else
75 needSearchPath.push_back( path + "/" );
79 void
80 ShapesScanner::push_frontNeedPath( const std::string & path )
82 if( path.empty( ) ||
83 path[ path.size( ) - 1 ] == '/' )
85 needSearchPath.push_front( path );
87 else
89 needSearchPath.push_front( path + "/" );
93 void
94 ShapesScanner::pop_frontNeedPath( )
96 needSearchPath.pop_front( );
99 void
100 ShapesScanner::setShowFiles( bool _showFiles )
102 showFiles = _showFiles;
106 void
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
111 lastleng = yyleng;
114 void
115 ShapesScanner::doBeforeEachAction( )
117 if( moreState )
119 shapeslloc.lastColumn += yyleng - lastleng;
121 else
123 shapeslloc.firstLine = shapeslloc.lastLine;
124 shapeslloc.firstColumn = shapeslloc.lastColumn;
125 shapeslloc.lastColumn = shapeslloc.firstColumn + yyleng;
127 moreState = false;
130 double
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( ) )
137 return -1;
139 return 1 / i->second;
142 Concrete::Length
143 ShapesScanner::strtoLength( const char * str ) const
145 char * endp;
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;
156 std::string
157 ShapesScanner::searchFile( const std::string & suffix ) const
159 struct stat theStatDummy;
160 std::string res = searchFile( suffix, & theStatDummy );
161 if( showFiles )
163 for( size_t i = 0; i < locStack.size( ); ++i )
165 std::cerr << " " ;
167 std::cerr << " " << res << std::endl ;
169 return res;
172 std::string
173 ShapesScanner::searchFile( const std::string & suffix, struct stat * dstStat ) const
175 std::string res;
177 if( suffix.empty( ) )
179 throw Exceptions::InternalError( strrefdup( "ShapesScanner::searchFile called with empty argument." ) );
182 if( suffix[ 0 ] == '/' )
184 res = suffix;
185 if( stat( res.c_str( ), dstStat ) == 0 )
187 return res;
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 )
204 return res;
207 throw Exceptions::FileReadOpenError( shapeslloc, strrefdup( suffix ), & sourceDir_, & needSearchPath );
210 std::string
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;
221 else
223 return sourceDir_ + needpath + suffix;
227 void
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 );
238 void
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 ];
244 char * dst = res;
245 while( ! dataStringChunks_.empty( ) )
247 char * ptr = dataStringChunks_.front( ).first;
248 memcpy( dst, ptr, dataStringChunks_.front( ).second );
249 dst += dataStringChunks_.front( ).second;
250 delete ptr;
251 dataStringChunks_.pop_front( );
253 *dst = '\0';
254 shapeslval.Lang_String = new Lang::String( RefCountPtr< const char >( res ), dataStringTotalLength_ );