include-stack.i (17247B)
1 /* -*- C++ -*- vim:set syntax=cpp: 2 * 3 * (C) 2004-2009 Frank-Rene Schaefer 4 * 5 * __QUEX_INCLUDE_GUARD__ANALYZER__STRUCT__INCLUDE_STACK_I may be undefined in case 6 * that multiple lexical analyzers are used. Then, the name of the 7 * QUEX_NAME(Accumulator) must be different. */ 8 #ifndef __QUEX_INCLUDE_GUARD__ANALYZER__STRUCT__INCLUDE_STACK_I 9 #define __QUEX_INCLUDE_GUARD__ANALYZER__STRUCT__INCLUDE_STACK_I 10 11 #ifndef QUEX_TYPE_ANALYZER 12 # error "Macro QUEX_TYPE_ANALYZER must be defined before inclusion of this file." 13 #endif 14 15 16 QUEX_NAMESPACE_MAIN_OPEN 17 18 /* Level (1) __________________________________________________________________ 19 * */ 20 QUEX_INLINE bool 21 QUEX_MEMBER_FUNCTION2(include_push, file_name, 22 const char* FileName, 23 const char* CodecName /* = 0x0 */) 24 { 25 QUEX_MAP_THIS_TO_ME(QUEX_TYPE_ANALYZER) 26 bool verdict_f; 27 QUEX_NAME(ByteLoader)* byte_loader; 28 29 byte_loader = QUEX_NAME(ByteLoader_FILE_new_from_file_name)(FileName); 30 if( ! byte_loader ) { 31 return false; 32 } 33 byte_loader->ownership = E_Ownership_LEXICAL_ANALYZER; 34 verdict_f = QUEX_MEMBER_FUNCTION_CALL3(include_push, ByteLoader, FileName, byte_loader, CodecName); 35 if( ! verdict_f ) { 36 QUEX_NAME(ByteLoader_delete)(&byte_loader); 37 } 38 return verdict_f; 39 } 40 41 /* Level (2) __________________________________________________________________ 42 * */ 43 QUEX_INLINE bool 44 QUEX_MEMBER_FUNCTION4(include_push, FILE, 45 const char* InputName, 46 __QUEX_STD_FILE* fh, 47 const char* CodecName /* = 0x0 */, 48 bool BinaryModeF) 49 { 50 QUEX_MAP_THIS_TO_ME(QUEX_TYPE_ANALYZER) 51 bool verdict_f; 52 QUEX_NAME(ByteLoader)* byte_loader; 53 __quex_assert( fh ); 54 55 /* At the time of this writing 'stdin' as located in the C++ global 56 * namespace. This seemed suspicous to the author. To avoid compilation 57 * errors in the future the test for the standard input is only active in 58 * 'C'. It is only about user information anyway. So better no risks taken. 59 * <fschaef 2010y02m06d> */ 60 61 setbuf(fh, 0); /* turn off system based buffering! 62 ** ** this is essential to profit from the quex buffer! */ 63 byte_loader = QUEX_NAME(ByteLoader_FILE_new)(fh, BinaryModeF); 64 /* NOT: Abort/return if byte_loader == 0 !! 65 * Incomplete construction => propper destruction IMPOSSIBLE! */ 66 if( ! byte_loader ) { 67 return false; 68 } 69 byte_loader->ownership = E_Ownership_LEXICAL_ANALYZER; 70 verdict_f = QUEX_MEMBER_FUNCTION_CALL3(include_push, ByteLoader, InputName, 71 byte_loader, CodecName); 72 if( ! verdict_f ) { 73 QUEX_NAME(ByteLoader_delete)(&byte_loader); 74 } 75 return verdict_f; 76 } 77 78 #ifndef __QUEX_OPTION_PLAIN_C 79 QUEX_INLINE bool 80 QUEX_MEMBER_FUNCTION4(include_push, istream, 81 const char* InputName, 82 std::istream* istream_p, 83 const char* CodecName /* = 0x0 */, 84 bool BinaryModeF /* = false */) 85 { 86 QUEX_MAP_THIS_TO_ME(QUEX_TYPE_ANALYZER) 87 bool verdict_f; 88 QUEX_NAME(ByteLoader)* byte_loader; 89 __quex_assert( istream_p ); 90 91 byte_loader = QUEX_NAME(ByteLoader_stream_new)(istream_p); 92 byte_loader->binary_mode_f = BinaryModeF; 93 94 /* NOT: Abort/return if byte_loader == 0 !! 95 * Incomplete construction => propper destruction IMPOSSIBLE! */ 96 if( ! byte_loader ) { 97 return false; 98 } 99 byte_loader->ownership = E_Ownership_LEXICAL_ANALYZER; 100 verdict_f = QUEX_MEMBER_FUNCTION_CALL3(include_push, ByteLoader, InputName, 101 byte_loader, CodecName); 102 if( ! verdict_f ) { 103 QUEX_NAME(ByteLoader_delete)(&byte_loader); 104 } 105 return verdict_f; 106 } 107 #endif 108 109 110 #if defined(__QUEX_OPTION_WCHAR_T) && ! defined(__QUEX_OPTION_PLAIN_C) 111 QUEX_INLINE bool 112 QUEX_MEMBER_FUNCTION4(include_push, wistream, 113 const char* InputName, 114 std::wistream* istream_p, 115 const char* CodecName /* = 0x0 */, 116 bool BinaryModeF /* = false */) 117 { 118 QUEX_MAP_THIS_TO_ME(QUEX_TYPE_ANALYZER) 119 bool verdict_f; 120 QUEX_NAME(ByteLoader)* byte_loader; 121 __quex_assert( istream_p ); 122 123 byte_loader = QUEX_NAME(ByteLoader_stream_new)(istream_p); 124 byte_loader->binary_mode_f = BinaryModeF; 125 126 /* NOT: Abort/return if byte_loader == 0 !! 127 * Incomplete construction => propper destruction IMPOSSIBLE! */ 128 if( ! byte_loader ) { 129 return false; 130 } 131 byte_loader->ownership = E_Ownership_LEXICAL_ANALYZER; 132 verdict_f = QUEX_MEMBER_FUNCTION_CALL3(include_push, ByteLoader, InputName, 133 byte_loader, CodecName); 134 if( ! verdict_f ) { 135 QUEX_NAME(ByteLoader_delete)(&byte_loader); 136 } 137 return verdict_f; 138 } 139 #endif 140 141 #if defined(__QUEX_OPTION_UNIT_TEST) && ! defined (__QUEX_OPTION_PLAIN_C) 142 /* StrangeStreams are not for C-language stuff */ 143 template<class UnderlyingStreamT> QUEX_INLINE bool 144 QUEX_MEMBER_FUNCTION3(include_push, strange_stream, 145 const char* InputName, 146 quex::StrangeStream<UnderlyingStreamT>* istream_p, 147 const char* CodecName /* = 0x0 */) 148 { 149 QUEX_MAP_THIS_TO_ME(QUEX_TYPE_ANALYZER) 150 bool verdict_f; 151 QUEX_NAME(ByteLoader)* byte_loader; 152 __quex_assert( istream_p ); 153 154 byte_loader = QUEX_NAME(ByteLoader_stream_new)(istream_p); 155 byte_loader->binary_mode_f = false; 156 /* NOT: Abort/return if byte_loader == 0 !! 157 * Incomplete construction => propper destruction IMPOSSIBLE! */ 158 if( ! byte_loader ) { 159 return false; 160 } 161 byte_loader->ownership = E_Ownership_LEXICAL_ANALYZER; 162 verdict_f = QUEX_MEMBER_FUNCTION_CALL3(include_push, ByteLoader, InputName, 163 byte_loader, CodecName); 164 if( ! verdict_f ) { 165 QUEX_NAME(ByteLoader_delete)(&byte_loader); 166 } 167 return verdict_f; 168 } 169 #endif 170 171 172 /* Level (3) __________________________________________________________________ 173 * */ 174 QUEX_INLINE bool 175 QUEX_MEMBER_FUNCTION3(include_push, ByteLoader, 176 const char* InputName, 177 QUEX_NAME(ByteLoader)* byte_loader, 178 const char* CodecName) 179 { 180 QUEX_MAP_THIS_TO_ME(QUEX_TYPE_ANALYZER) 181 bool verdict_f; 182 QUEX_NAME(LexatomLoader)* filler; 183 QUEX_NAME(Asserts_construct)(CodecName); 184 185 filler = QUEX_NAME(LexatomLoader_new_DEFAULT)(byte_loader, CodecName); 186 /* NOT: Abort/return if filler == 0 !! 187 * Incomplete construction => propper destruction IMPOSSIBLE! */ 188 if( filler ) { 189 filler->ownership = E_Ownership_LEXICAL_ANALYZER; 190 } 191 verdict_f = QUEX_MEMBER_FUNCTION_CALL2(include_push, LexatomLoader, InputName, 192 filler); 193 if( ! verdict_f && filler->ownership == E_Ownership_LEXICAL_ANALYZER ) { 194 me->buffer.filler->delete_self(me->buffer.filler); 195 me->buffer.filler = (QUEX_NAME(LexatomLoader)*)0; 196 } 197 return verdict_f; 198 } 199 200 /* Level (4) __________________________________________________________________ 201 * */ 202 QUEX_INLINE bool 203 QUEX_MEMBER_FUNCTION2(include_push, LexatomLoader, 204 const char* InputName, 205 QUEX_NAME(LexatomLoader)* filler) 206 { 207 QUEX_MAP_THIS_TO_ME(QUEX_TYPE_ANALYZER) 208 bool verdict_f; 209 QUEX_TYPE_LEXATOM* memory; 210 QUEX_NAME(Buffer) new_buffer_setup; 211 212 memory = (QUEX_TYPE_LEXATOM*)QUEXED(MemoryManager_allocate)( 213 QUEX_SETTING_BUFFER_SIZE * sizeof(QUEX_TYPE_LEXATOM), 214 E_MemoryObjectType_BUFFER_MEMORY); 215 /* NOT: Abort/return if memory == 0 !! 216 * Incomplete construction => propper destruction IMPOSSIBLE! */ 217 218 QUEX_NAME(Buffer_construct)(&new_buffer_setup, filler, 219 memory, QUEX_SETTING_BUFFER_SIZE, 220 (QUEX_TYPE_LEXATOM*)0, 221 E_Ownership_LEXICAL_ANALYZER); 222 223 /* The 'new_buffer_setup' is only copied including the reference to the 224 * new memory. However, the box object 'new_buffer_setup' is left alone. */ 225 verdict_f = QUEX_MEMBER_FUNCTION_CALLO2(basic_include_push, InputName, 226 &new_buffer_setup); 227 if( ! verdict_f ) { 228 QUEXED(MemoryManager_free)(memory, E_MemoryObjectType_BUFFER_MEMORY); 229 } 230 return verdict_f; 231 } 232 233 /* Level (5) __________________________________________________________________ 234 * */ 235 QUEX_INLINE bool 236 QUEX_MEMBER_FUNCTION4(include_push, memory, 237 const char* InputName, 238 QUEX_TYPE_LEXATOM* Memory, 239 const size_t MemorySize, 240 QUEX_TYPE_LEXATOM* EndOfFileP) 241 /* When memory is provided from extern, the 'external entity' is 242 * responsible for filling it. There is no 'file/stream handle', no 'byte 243 * loader', and 'no buffer filler'. */ 244 { 245 QUEX_MAP_THIS_TO_ME(QUEX_TYPE_ANALYZER) 246 QUEX_NAME(Buffer) new_buffer_setup; 247 QUEX_ASSERT_MEMORY(Memory, MemorySize, EndOfFileP); 248 249 QUEX_NAME(Buffer_construct)(&new_buffer_setup, 250 (QUEX_NAME(LexatomLoader)*)0, 251 Memory, MemorySize, EndOfFileP, 252 E_Ownership_EXTERNAL); 253 254 /* The 'new_buffer_setup' is only copied including the reference to the 255 * new memory. However, the box object 'new_buffer_setup' is left alone. */ 256 return QUEX_MEMBER_FUNCTION_CALLO2(basic_include_push, InputName, 257 &new_buffer_setup); 258 } 259 260 QUEX_INLINE bool 261 QUEX_MEMBER_FUNCTIONO2(basic_include_push, 262 const char* InputNameP, 263 QUEX_NAME(Buffer)* new_buffer_setup) 264 { 265 QUEX_MAP_THIS_TO_ME(QUEX_TYPE_ANALYZER) 266 QUEX_NAME(Memento)* memento; 267 268 memento = (QUEX_NAME(Memento)*)QUEXED(MemoryManager_allocate)( 269 sizeof(QUEX_NAME(Memento)), 270 E_MemoryObjectType_MEMENTO); 271 if( ! memento ) { 272 return false; 273 } 274 # ifndef __QUEX_OPTION_PLAIN_C 275 /* Use placement 'new' for explicit call of constructor. 276 * Necessary in C++: Call to constructor for user defined members. */ 277 new ((void*)memento) QUEX_NAME(Memento); 278 # endif 279 280 if( me->buffer.filler ) 281 { 282 /* By default overtake the byte order reversion behavior of the 283 * including buffer. */ 284 new_buffer_setup->filler->_byte_order_reversion_active_f = \ 285 me->buffer.filler->_byte_order_reversion_active_f; 286 } 287 288 /* 'memento->__input_name' points to previously allocated memory. */ 289 memento->__input_name = me->__input_name; 290 me->__input_name = (char*)0; /* Release ownership. */ 291 memento->_parent_memento = me->_parent_memento; 292 memento->buffer = me->buffer; 293 memento->__current_mode_p = me->__current_mode_p; 294 memento->current_analyzer_function = me->current_analyzer_function; 295 # if defined(QUEX_OPTION_AUTOMATIC_ANALYSIS_CONTINUATION_ON_MODE_CHANGE) \ 296 || defined(QUEX_OPTION_ASSERTS) 297 memento->DEBUG_analyzer_function_at_entry = me->DEBUG_analyzer_function_at_entry; 298 # endif 299 __QUEX_IF_COUNT(memento->counter = me->counter); 300 301 me->buffer = *new_buffer_setup; 302 __QUEX_IF_COUNT(QUEX_NAME(Counter_construct)(&me->counter); ) 303 304 /* Deriberately not subject to include handling: 305 * -- Mode stack. 306 * -- Token and token queues. 307 * -- Post categorizer. */ 308 if( ! QUEX_MEMBER_FUNCTION_CALLO2(user_memento_pack, InputNameP, memento) ) { 309 QUEXED(MemoryManager_free)(memento, E_MemoryObjectType_MEMENTO); 310 return false; 311 } 312 313 if( ! QUEX_MEMBER_FUNCTION_CALLO1(input_name_set, InputNameP) ) { 314 QUEXED(MemoryManager_free)(memento, E_MemoryObjectType_MEMENTO); 315 return false; 316 } 317 318 /* Put memento on stack AFTER user has done to it its duties. */ 319 me->_parent_memento = memento; 320 321 return true; 322 } 323 324 QUEX_INLINE bool 325 QUEX_MEMBER_FUNCTIONO(include_pop) 326 /* RETURNS: true, if there was a memento that has been restored. 327 * false, else. */ 328 { 329 QUEX_MAP_THIS_TO_ME(QUEX_TYPE_ANALYZER) 330 QUEX_NAME(Memento)* memento; 331 /* Not included? return 'false' to indicate we're on the top level */ 332 if( ! me->_parent_memento ) return false; 333 334 /* Buffer_destruct() takes care of propper destructor calls for byte- 335 * loaders, buffer fillers, and converters. */ 336 QUEX_NAME(Buffer_destruct)(&me->buffer); 337 338 memento = me->_parent_memento; 339 me->_parent_memento = memento->_parent_memento; 340 /* memento_unpack(): 341 * => Current mode 342 * => __current_mode_p 343 * current_analyzer_function 344 * DEBUG_analyzer_function_at_entry 345 * => Line/Column Counters 346 * 347 * Unchanged by memento_unpack(): 348 * -- Mode stack 349 * -- Tokens and token queues. 350 * -- Accumulator. 351 * -- Post categorizer. 352 * -- File handle by constructor */ 353 354 /* Copy Back of content that was stored upon inclusion. */ 355 356 if( me->__input_name ) { 357 QUEXED(MemoryManager_free)(me->__input_name, E_MemoryObjectType_BUFFER_MEMORY); 358 } 359 /* 'memento->__input_name' points to previously allocated memory. 360 * 'me->__input_name' takes ownership again over allocated memory. */ 361 me->__input_name = memento->__input_name; 362 me->buffer = memento->buffer; 363 me->__current_mode_p = memento->__current_mode_p; 364 me->current_analyzer_function = memento->current_analyzer_function; 365 # if defined(QUEX_OPTION_AUTOMATIC_ANALYSIS_CONTINUATION_ON_MODE_CHANGE) \ 366 || defined(QUEX_OPTION_ASSERTS) 367 me->DEBUG_analyzer_function_at_entry = memento->DEBUG_analyzer_function_at_entry; 368 # endif 369 __QUEX_IF_COUNT(me->counter = memento->counter); 370 371 QUEX_MEMBER_FUNCTION_CALLO1(user_memento_unpack,memento); 372 373 # ifndef __QUEX_OPTION_PLAIN_C 374 /* Counterpart to placement new: Explicit destructor call. 375 * Necessary in C++: Trigger call to destructor for user defined members.*/ 376 memento->~QUEX_NAME(Memento_tag)(); 377 # endif 378 379 QUEXED(MemoryManager_free)((void*)memento, E_MemoryObjectType_MEMENTO); 380 381 /* Return to including file succesful */ 382 return true; 383 } 384 385 QUEX_INLINE void 386 QUEX_MEMBER_FUNCTIONO(include_stack_delete) 387 { 388 QUEX_MAP_THIS_TO_ME(QUEX_TYPE_ANALYZER) 389 while( QUEX_MEMBER_FUNCTION_CALLO(include_pop) ); 390 } 391 392 QUEX_INLINE bool 393 QUEX_MEMBER_FUNCTIONO1(include_detect_recursion, 394 const char* InputName) 395 { 396 QUEX_MAP_THIS_TO_ME(QUEX_TYPE_ANALYZER) 397 QUEX_NAME(Memento)* iterator; 398 for(iterator = me->_parent_memento; iterator ; 399 iterator = iterator->_parent_memento ) { 400 if( __QUEX_STD_strcmp(iterator->__input_name, InputName) == 0 ) { 401 return true; 402 } 403 } 404 return false; 405 } 406 407 QUEX_NAMESPACE_MAIN_CLOSE 408 409 #endif /* __QUEX_INCLUDE_GUARD__ANALYZER__STRUCT__INCLUDE_STACK_I */