Example: Changed glyph-outline.shape for use with FontConfig.
[shapes.git] / source / shapesscanner.cc
blob50b722b7c2ddf1f9e42a4aed1f6dddda051b6e71
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, bool runtime ) const
159 struct stat theStatDummy;
160 std::string res = searchFile( suffix, & theStatDummy, runtime );
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, bool runtime ) const
175 std::string res;
177 if( suffix.empty( ) )
179 if( runtime )
181 throw strrefdup( "Empty file name." ); /* This string should be embedded in a catchable exception by the caller. */
183 else
185 throw Exceptions::InternalError( strrefdup( "ShapesScanner::searchFile called with empty argument." ) );
189 if( suffix[ 0 ] == '/' )
191 res = suffix;
192 if( stat( res.c_str( ), dstStat ) == 0 )
194 return res;
196 if( runtime )
198 std::ostringstream msg;
199 msg << "The absolute filename \"" << suffix << "\" does not name a file." ;
200 throw strrefdup( msg ); /* This string should be embedded in a catchable exception by the caller. */
202 else
204 throw Exceptions::FileReadOpenError( shapeslloc, strrefdup( suffix ), 0, 0 );
208 if( needSearchPath.empty( ) )
210 if( runtime )
212 std::ostringstream msg;
213 msg << "The relative filename \"" << suffix << "\" cannot be searched since the search path is empty." ;
214 throw strrefdup( msg ); /* This string should be embedded in a catchable exception by the caller. */
216 else
218 throw Exceptions::ScannerError( shapeslloc, strrefdup( "Relative file inclusion impossible since search path is empty." ) );
222 typedef typeof needSearchPath ListType;
223 for( ListType::const_iterator i = needSearchPath.begin( ); i != needSearchPath.end( ); ++i )
225 res = needpathWithSuffix( *i, suffix );
227 if( stat( res.c_str( ), dstStat ) == 0 )
229 return res;
232 if( runtime )
234 std::ostringstream msg;
235 msg << "The relative filename \"" << suffix << "\" did not name a file in the search path." ;
236 throw strrefdup( msg ); /* This string should be embedded in a catchable exception by the caller. */
238 else
240 throw Exceptions::FileReadOpenError( shapeslloc, strrefdup( suffix ), & sourceDir_, & needSearchPath );
244 std::string
245 ShapesScanner::needpathWithSuffix( const std::string & needpath, const std::string & suffix ) const
247 if( needpath[0] == '/' )
249 return needpath + suffix;
251 else if( needpath == "./" )
253 return sourceDir_ + suffix;
255 else
257 return sourceDir_ + needpath + suffix;
261 void
262 ShapesScanner::rinseString( )
264 /* Both types of strings are terminated by a two byte sequence, ") or ยด. */
265 size_t bytecount = yyleng - ( ( yyleng >= 3 && yytext[ yyleng - 3 ] == '\n' ) ? 3 : 2 );
266 char * res = new char[ bytecount + 1 ];
267 memcpy( res, yytext, bytecount );
268 res[ bytecount ] = '\0';
269 shapeslval.Lang_String = new Lang::String( RefCountPtr< const char >( res ), bytecount );
272 void
273 ShapesScanner::concatenateDataString( )
275 /* Remember: strcpy, strdup and friends may fail here, since the string may contain zeros. */
277 char * res = new char[ dataStringTotalLength_ + 1 ];
278 char * dst = res;
279 while( ! dataStringChunks_.empty( ) )
281 char * ptr = dataStringChunks_.front( ).first;
282 memcpy( dst, ptr, dataStringChunks_.front( ).second );
283 dst += dataStringChunks_.front( ).second;
284 delete ptr;
285 dataStringChunks_.pop_front( );
287 *dst = '\0';
288 shapeslval.Lang_String = new Lang::String( RefCountPtr< const char >( res ), dataStringTotalLength_ );