1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
22 #pragma warning(push, 1)
25 #include "pdfparse.hxx"
27 // workaround windows compiler: do not include multi_pass.hpp
28 #include <boost/spirit/include/classic_core.hpp>
29 #include <boost/spirit/include/classic_utility.hpp>
30 #include <boost/spirit/include/classic_error_handling.hpp>
31 #include <boost/spirit/include/classic_file_iterator.hpp>
32 #include <boost/bind.hpp>
35 #include <rtl/strbuf.hxx>
36 #include <rtl/alloc.h>
38 // disable warnings again because someone along the line has enabled them
40 #pragma warning(push, 1)
43 using namespace boost::spirit
;
44 using namespace pdfparse
;
47 class StringEmitContext
: public EmitContext
51 StringEmitContext() : EmitContext(), m_aBuf(256) {}
52 virtual ~StringEmitContext() {}
53 virtual bool write( const void* pBuf
, unsigned int nLen
) throw() SAL_OVERRIDE
55 m_aBuf
.append( static_cast<const sal_Char
*>(pBuf
), nLen
);
58 virtual unsigned int getCurPos() throw() SAL_OVERRIDE
{ return m_aBuf
.getLength(); }
59 virtual bool copyOrigBytes( unsigned int nOrigOffset
, unsigned int nLen
) throw() SAL_OVERRIDE
60 { return (nOrigOffset
+nLen
< static_cast<unsigned int>(m_aBuf
.getLength()) ) &&
61 write( m_aBuf
.getStr() + nOrigOffset
, nLen
); }
62 virtual unsigned int readOrigBytes( unsigned int nOrigOffset
, unsigned int nLen
, void* pBuf
) throw() SAL_OVERRIDE
64 if( nOrigOffset
+nLen
< static_cast<unsigned int>(m_aBuf
.getLength()) )
66 memcpy( pBuf
, m_aBuf
.getStr()+nOrigOffset
, nLen
);
72 OString
getString() { return m_aBuf
.makeStringAndClear(); }
75 template< class iteratorT
>
76 class PDFGrammar
: public grammar
< PDFGrammar
<iteratorT
> >
80 PDFGrammar( const iteratorT
& first
)
81 : m_fDouble( 0.0 ), m_aGlobalBegin( first
) {}
84 if( !m_aObjectStack
.empty() )
85 delete m_aObjectStack
.front();
89 std::vector
< unsigned int > m_aUIntStack
;
90 std::vector
< PDFEntry
* > m_aObjectStack
;
91 OString m_aErrorString
;
92 iteratorT m_aGlobalBegin
;
95 struct pdf_string_parser
97 typedef nil_t result_t
;
98 template <typename ScannerT
>
100 operator()(ScannerT
const& scan
, result_t
&) const
102 std::ptrdiff_t len
= 0;
105 while( ! scan
.at_end() )
111 if( nBraceLevel
< 0 )
116 else if( c
== '\\' ) // ignore escaped braces
119 ++scan
.first
; // tdf#63054: avoid skipping spaces
120 if( scan
.first
== scan
.last
) // tdf#63054: avoid skipping spaces
126 return scan
.at_end() ? -1 : len
;
130 template< typename ScannerT
>
133 definition( const PDFGrammar
<iteratorT
>& rSelf
)
135 PDFGrammar
<iteratorT
>* pSelf
= const_cast< PDFGrammar
<iteratorT
>* >( &rSelf
);
137 // workaround workshop compiler: comment_p doesn't work
138 // comment = comment_p("%")[boost::bind(&PDFGrammar::pushComment, pSelf, _1, _2 )];
139 comment
= lexeme_d
[ (ch_p('%') >> *(~ch_p('\r') & ~ch_p('\n')) >> eol_p
)[boost::bind(&PDFGrammar::pushComment
, pSelf
, _1
, _2
)] ];
141 boolean
= (str_p("true") | str_p("false"))[boost::bind(&PDFGrammar::pushBool
, pSelf
, _1
, _2
)];
143 // workaround workshop compiler: confix_p doesn't work
144 //stream = confix_p( "stream", *anychar_p, "endstream" )[boost::bind(&PDFGrammar::emitStream, pSelf, _1, _2 )];
145 stream
= (str_p("stream") >> *(anychar_p
- str_p("endstream")) >> str_p("endstream"))[boost::bind(&PDFGrammar::emitStream
, pSelf
, _1
, _2
)];
149 >> (*(anychar_p
-chset_p("\t\n\f\r ()<>[]{}/%")-ch_p('\0')))
150 [boost::bind(&PDFGrammar::pushName
, pSelf
, _1
, _2
)] ];
152 // workaround workshop compiler: confix_p doesn't work
153 //stringtype = ( confix_p("(",*anychar_p, ")") |
154 // confix_p("<",*xdigit_p, ">") )
155 // [boost::bind(&PDFGrammar::pushString,pSelf, _1, _2)];
157 stringtype
= ( ( ch_p('(') >> functor_parser
<pdf_string_parser
>() >> ch_p(')') ) |
158 ( ch_p('<') >> *xdigit_p
>> ch_p('>') ) )
159 [boost::bind(&PDFGrammar::pushString
,pSelf
, _1
, _2
)];
161 null_object
= str_p( "null" )[boost::bind(&PDFGrammar::pushNull
, pSelf
, _1
, _2
)];
163 #ifdef USE_ASSIGN_ACTOR
164 objectref
= ( uint_p
[push_back_a(pSelf
->m_aUIntStack
)]
165 >> uint_p
[push_back_a(pSelf
->m_aUIntStack
)]
168 )[boost::bind(&PDFGrammar::pushObjectRef
, pSelf
, _1
, _2
)];
170 objectref
= ( uint_p
[boost::bind(&PDFGrammar::push_back_action_uint
, pSelf
, _1
)]
171 >> uint_p
[boost::bind(&PDFGrammar::push_back_action_uint
, pSelf
, _1
)]
174 )[boost::bind(&PDFGrammar::pushObjectRef
, pSelf
, _1
, _2
)];
177 #ifdef USE_ASSIGN_ACTOR
178 simple_type
= objectref
| name
|
179 ( real_p
[assign_a(pSelf
->m_fDouble
)] >> eps_p
)
180 [boost::bind(&PDFGrammar::pushDouble
, pSelf
, _1
, _2
)]
181 | stringtype
| boolean
| null_object
;
183 simple_type
= objectref
| name
|
184 ( real_p
[boost::bind(&PDFGrammar::assign_action_double
, pSelf
, _1
)] >> eps_p
)
185 [boost::bind(&PDFGrammar::pushDouble
, pSelf
, _1
, _2
)]
186 | stringtype
| boolean
| null_object
;
189 dict_begin
= str_p( "<<" )[boost::bind(&PDFGrammar::beginDict
, pSelf
, _1
, _2
)];
190 dict_end
= str_p( ">>" )[boost::bind(&PDFGrammar::endDict
, pSelf
, _1
, _2
)];
192 array_begin
= str_p("[")[boost::bind(&PDFGrammar::beginArray
,pSelf
, _1
, _2
)];
193 array_end
= str_p("]")[boost::bind(&PDFGrammar::endArray
,pSelf
, _1
, _2
)];
195 #ifdef USE_ASSIGN_ACTOR
196 object_begin
= uint_p
[push_back_a(pSelf
->m_aUIntStack
)]
197 >> uint_p
[push_back_a(pSelf
->m_aUIntStack
)]
198 >> str_p("obj" )[boost::bind(&PDFGrammar::beginObject
, pSelf
, _1
, _2
)];
200 object_begin
= uint_p
[boost::bind(&PDFGrammar::push_back_action_uint
, pSelf
, _1
)]
201 >> uint_p
[boost::bind(&PDFGrammar::push_back_action_uint
, pSelf
, _1
)]
202 >> str_p("obj" )[boost::bind(&PDFGrammar::beginObject
, pSelf
, _1
, _2
)];
204 object_end
= str_p( "endobj" )[boost::bind(&PDFGrammar::endObject
, pSelf
, _1
, _2
)];
206 xref
= str_p( "xref" ) >> uint_p
>> uint_p
208 +( repeat_p(10)[digit_p
]
210 >> repeat_p(5)[digit_p
]
212 >> ( ch_p('n') | ch_p('f') )
213 >> repeat_p(2)[space_p
]
216 dict_element
= dict_begin
| comment
| simple_type
217 | array_begin
| array_end
| dict_end
;
219 object
= object_begin
224 trailer
= str_p( "trailer" )[boost::bind(&PDFGrammar::beginTrailer
,pSelf
,_1
,_2
)]
226 >> str_p("startxref")
228 >> str_p("%%EOF")[boost::bind(&PDFGrammar::endTrailer
,pSelf
,_1
,_2
)];
230 #ifdef USE_ASSIGN_ACTOR
231 pdfrule
= ! (lexeme_d
[
233 >> uint_p
[push_back_a(pSelf
->m_aUIntStack
)]
235 >> uint_p
[push_back_a(pSelf
->m_aUIntStack
)]
236 >> *((~ch_p('\r') & ~ch_p('\n')))
238 ])[boost::bind(&PDFGrammar::haveFile
,pSelf
, _1
, _2
)]
239 >> *( comment
| object
| ( xref
>> trailer
) );
241 pdfrule
= ! (lexeme_d
[
243 >> uint_p
[boost::bind(&PDFGrammar::push_back_action_uint
, pSelf
, _1
)]
245 >> uint_p
[boost::bind(&PDFGrammar::push_back_action_uint
, pSelf
, _1
)]
246 >> *((~ch_p('\r') & ~ch_p('\n')))
248 ])[boost::bind(&PDFGrammar::haveFile
,pSelf
, _1
, _2
)]
249 >> *( comment
| object
| ( xref
>> trailer
) );
252 rule
< ScannerT
> comment
, stream
, boolean
, name
, stringtype
, null_object
, simple_type
,
253 objectref
, array
, value
, dict_element
, dict_begin
, dict_end
,
254 array_begin
, array_end
, object
, object_begin
, object_end
,
255 xref
, trailer
, pdfrule
;
257 const rule
< ScannerT
>& start() const { return pdfrule
; }
260 #ifndef USE_ASSIGN_ACTOR
261 void push_back_action_uint( unsigned int i
)
263 m_aUIntStack
.push_back( i
);
265 void assign_action_double( double d
)
271 static void parseError( const char* pMessage
, iteratorT pLocation
)
273 throw_( pLocation
, pMessage
);
276 OString
iteratorToString( iteratorT first
, iteratorT last
) const
278 OStringBuffer
aStr( 32 );
279 while( first
!= last
)
281 aStr
.append( *first
);
284 return aStr
.makeStringAndClear();
287 void haveFile( iteratorT pBegin
, SAL_UNUSED_PARAMETER iteratorT
/*pEnd*/ )
289 if( m_aObjectStack
.empty() )
291 PDFFile
* pFile
= new PDFFile();
292 pFile
->m_nMinor
= m_aUIntStack
.back();
293 m_aUIntStack
.pop_back();
294 pFile
->m_nMajor
= m_aUIntStack
.back();
295 m_aUIntStack
.pop_back();
296 m_aObjectStack
.push_back( pFile
);
299 parseError( "found file header in unusual place", pBegin
);
302 void pushComment( iteratorT first
, iteratorT last
)
304 // add a comment to the current stack element
305 PDFComment
* pComment
=
306 new PDFComment(iteratorToString(first
,last
));
307 if( m_aObjectStack
.empty() )
308 m_aObjectStack
.push_back( new PDFPart() );
309 PDFContainer
* pContainer
= dynamic_cast<PDFContainer
*>(m_aObjectStack
.back());
310 if( pContainer
== NULL
)
311 parseError( "comment without container", first
);
312 pContainer
->m_aSubElements
.push_back( pComment
);
315 void insertNewValue( PDFEntry
* pNewValue
, iteratorT pPos
)
317 PDFContainer
* pContainer
= NULL
;
318 const char* pMsg
= NULL
;
319 if( ! m_aObjectStack
.empty() &&
320 (pContainer
= dynamic_cast<PDFContainer
*>(m_aObjectStack
.back())) != NULL
)
322 if( dynamic_cast<PDFDict
*>(pContainer
) == NULL
&&
323 dynamic_cast<PDFArray
*>(pContainer
) == NULL
)
325 PDFObject
* pObj
= dynamic_cast<PDFObject
*>(pContainer
);
328 if( pObj
->m_pObject
== NULL
)
329 pObj
->m_pObject
= pNewValue
;
332 pMsg
= "second value for object";
336 else if( dynamic_cast<PDFDict
*>(pNewValue
) )
338 PDFTrailer
* pTrailer
= dynamic_cast<PDFTrailer
*>(pContainer
);
341 if( pTrailer
->m_pDict
== NULL
)
342 pTrailer
->m_pDict
= dynamic_cast<PDFDict
*>(pNewValue
);
354 pContainer
->m_aSubElements
.push_back( pNewValue
);
359 if( dynamic_cast<PDFContainer
*>(pNewValue
) )
360 pMsg
= "array without container";
362 pMsg
= "value without container";
365 parseError( pMsg
, pPos
);
369 void pushName( iteratorT first
, iteratorT last
)
371 insertNewValue( new PDFName(iteratorToString(first
,last
)), first
);
374 void pushDouble( iteratorT first
, SAL_UNUSED_PARAMETER iteratorT
/*last*/ )
376 insertNewValue( new PDFNumber(m_fDouble
), first
);
379 void pushString( iteratorT first
, iteratorT last
)
381 insertNewValue( new PDFString(iteratorToString(first
,last
)), first
);
384 void pushBool( iteratorT first
, iteratorT last
)
386 insertNewValue( new PDFBool( (last
-first
== 4) ), first
);
389 void pushNull( iteratorT first
, SAL_UNUSED_PARAMETER iteratorT
)
391 insertNewValue( new PDFNull(), first
);
395 void beginObject( iteratorT first
, SAL_UNUSED_PARAMETER iteratorT
/*last*/ )
397 if( m_aObjectStack
.empty() )
398 m_aObjectStack
.push_back( new PDFPart() );
400 unsigned int nGeneration
= m_aUIntStack
.back();
401 m_aUIntStack
.pop_back();
402 unsigned int nObject
= m_aUIntStack
.back();
403 m_aUIntStack
.pop_back();
405 PDFObject
* pObj
= new PDFObject( nObject
, nGeneration
);
406 pObj
->m_nOffset
= first
- m_aGlobalBegin
;
408 PDFContainer
* pContainer
= dynamic_cast<PDFContainer
*>(m_aObjectStack
.back());
410 ( dynamic_cast<PDFFile
*>(pContainer
) ||
411 dynamic_cast<PDFPart
*>(pContainer
) ) )
413 pContainer
->m_aSubElements
.push_back( pObj
);
414 m_aObjectStack
.push_back( pObj
);
417 parseError( "object in wrong place", first
);
420 void endObject( iteratorT first
, SAL_UNUSED_PARAMETER iteratorT
)
422 if( m_aObjectStack
.empty() )
423 parseError( "endobj without obj", first
);
424 else if( dynamic_cast<PDFObject
*>(m_aObjectStack
.back()) == NULL
)
425 parseError( "spurious endobj", first
);
427 m_aObjectStack
.pop_back();
430 void pushObjectRef( iteratorT first
, SAL_UNUSED_PARAMETER iteratorT
)
432 unsigned int nGeneration
= m_aUIntStack
.back();
433 m_aUIntStack
.pop_back();
434 unsigned int nObject
= m_aUIntStack
.back();
435 m_aUIntStack
.pop_back();
436 insertNewValue( new PDFObjectRef(nObject
,nGeneration
), first
);
439 void beginDict( iteratorT first
, SAL_UNUSED_PARAMETER iteratorT
)
441 PDFDict
* pDict
= new PDFDict();
442 pDict
->m_nOffset
= first
- m_aGlobalBegin
;
444 insertNewValue( pDict
, first
);
445 // will not come here if insertion fails (exception)
446 m_aObjectStack
.push_back( pDict
);
448 void endDict( iteratorT first
, SAL_UNUSED_PARAMETER iteratorT
)
450 PDFDict
* pDict
= NULL
;
451 if( m_aObjectStack
.empty() )
452 parseError( "dictionary end without begin", first
);
453 else if( (pDict
= dynamic_cast<PDFDict
*>(m_aObjectStack
.back())) == NULL
)
454 parseError( "spurious dictionary end", first
);
456 m_aObjectStack
.pop_back();
458 PDFEntry
* pOffender
= pDict
->buildMap();
461 StringEmitContext aCtx
;
462 aCtx
.write( "offending dictionary element: ", 30 );
463 pOffender
->emit( aCtx
);
464 m_aErrorString
= aCtx
.getString();
465 parseError( m_aErrorString
.getStr(), first
);
469 void beginArray( iteratorT first
, SAL_UNUSED_PARAMETER iteratorT
)
471 PDFArray
* pArray
= new PDFArray();
472 pArray
->m_nOffset
= first
- m_aGlobalBegin
;
474 insertNewValue( pArray
, first
);
475 // will not come here if insertion fails (exception)
476 m_aObjectStack
.push_back( pArray
);
479 void endArray( iteratorT first
, SAL_UNUSED_PARAMETER iteratorT
)
481 if( m_aObjectStack
.empty() )
482 parseError( "array end without begin", first
);
483 else if( dynamic_cast<PDFArray
*>(m_aObjectStack
.back()) == NULL
)
484 parseError( "spurious array end", first
);
486 m_aObjectStack
.pop_back();
489 void emitStream( iteratorT first
, iteratorT last
)
491 if( m_aObjectStack
.empty() )
492 parseError( "stream without object", first
);
493 PDFObject
* pObj
= dynamic_cast<PDFObject
*>(m_aObjectStack
.back());
494 if( pObj
&& pObj
->m_pObject
)
496 if( pObj
->m_pStream
)
497 parseError( "multiple streams in object", first
);
499 PDFDict
* pDict
= dynamic_cast<PDFDict
*>(pObj
->m_pObject
);
502 PDFStream
* pStream
= new PDFStream( first
- m_aGlobalBegin
, last
- m_aGlobalBegin
, pDict
);
504 pObj
->m_pStream
= pStream
;
505 pObj
->m_aSubElements
.push_back( pStream
);
509 parseError( "stream without object", first
);
512 void beginTrailer( iteratorT first
, SAL_UNUSED_PARAMETER iteratorT
)
514 if( m_aObjectStack
.empty() )
515 m_aObjectStack
.push_back( new PDFPart() );
517 PDFTrailer
* pTrailer
= new PDFTrailer();
518 pTrailer
->m_nOffset
= first
- m_aGlobalBegin
;
520 PDFContainer
* pContainer
= dynamic_cast<PDFContainer
*>(m_aObjectStack
.back());
522 ( dynamic_cast<PDFFile
*>(pContainer
) ||
523 dynamic_cast<PDFPart
*>(pContainer
) ) )
525 pContainer
->m_aSubElements
.push_back( pTrailer
);
526 m_aObjectStack
.push_back( pTrailer
);
529 parseError( "trailer in wrong place", first
);
532 void endTrailer( iteratorT first
, SAL_UNUSED_PARAMETER iteratorT
)
534 if( m_aObjectStack
.empty() )
535 parseError( "%%EOF without trailer", first
);
536 else if( dynamic_cast<PDFTrailer
*>(m_aObjectStack
.back()) == NULL
)
537 parseError( "spurious %%EOF", first
);
539 m_aObjectStack
.pop_back();
544 PDFEntry
* PDFReader::read( const char* pBuffer
, unsigned int nLen
)
546 PDFGrammar
<const char*> aGrammar( pBuffer
);
550 #if OSL_DEBUG_LEVEL > 1
551 boost::spirit::parse_info
<const char*> aInfo
=
553 boost::spirit::parse( pBuffer
,
556 boost::spirit::space_p
);
557 #if OSL_DEBUG_LEVEL > 1
558 SAL_INFO("sdext.pdfimport.pdfparse", "parseinfo: stop = " << aInfo
.stop
<< " (buff=" << pBuffer
<< ", offset = " << aInfo
.stop
- pBuffer
<< "), hit = " << (aInfo
.hit
? OUString("true") : OUString("false")) << ", full = " << (aInfo
.full
? OUString("true") : OUString("false")) << ", length = " << (int)aInfo
.length
);
561 catch( const parser_error
<const char*, const char*>& rError
)
563 #if OSL_DEBUG_LEVEL > 1
565 unsigned int nElem
= aGrammar
.m_aObjectStack
.size();
566 for( unsigned int i
= 0; i
< nElem
; i
++ )
567 aTmp
+= " " + OString(typeid( *(aGrammar
.m_aObjectStack
[i
]) ).name());
569 SAL_WARN("sdext.pdfimport.pdfparse", "parse error: " << rError
.descriptor
<< " at buffer pos " << rError
.where
- pBuffer
<< ", object stack: " << aTmp
);
573 PDFEntry
* pRet
= NULL
;
574 unsigned int nEntries
= aGrammar
.m_aObjectStack
.size();
577 pRet
= aGrammar
.m_aObjectStack
.back();
578 aGrammar
.m_aObjectStack
.pop_back();
580 #if OSL_DEBUG_LEVEL > 1
581 else if( nEntries
> 1 )
582 SAL_WARN("sdext.pdfimport.pdfparse", "error got " << nEntries
<< " stack objects in parse" );
589 PDFEntry
* PDFReader::read( const char* pFileName
)
593 since converting to boost 1.39 file_iterator does not work anymore on all Windows systems
594 C++ stdlib istream_iterator does not allow "-" apparently
595 using spirit 2.0 doesn't work in our environment with the MSC
597 So for the time being bite the bullet and read the whole file.
598 FIXME: give Spirit 2.x another try when we upgrade boost again.
600 PDFEntry
* pRet
= NULL
;
601 FILE* fp
= fopen( pFileName
, "rb" );
604 fseek( fp
, 0, SEEK_END
);
605 unsigned int nLen
= (unsigned int)ftell( fp
);
606 fseek( fp
, 0, SEEK_SET
);
607 char* pBuf
= (char*)rtl_allocateMemory( nLen
);
610 fread( pBuf
, 1, nLen
, fp
);
611 pRet
= read( pBuf
, nLen
);
612 rtl_freeMemory( pBuf
);
618 file_iterator
<> file_start( pFileName
);
621 file_iterator
<> file_end
= file_start
.make_end();
622 PDFGrammar
< file_iterator
<> > aGrammar( file_start
);
626 #if OSL_DEBUG_LEVEL > 1
627 boost::spirit::parse_info
< file_iterator
<> > aInfo
=
629 boost::spirit::parse( file_start
,
632 boost::spirit::space_p
);
633 #if OSL_DEBUG_LEVEL > 1
634 SAL_INFO("sdext.pdfimport.pdfparse", "parseinfo: stop at offset = " << aInfo
.stop
- file_start
<< ", hit = " << (aInfo
.hit
? "true" : "false") << ", full = " << (aInfo
.full
? "true" : "false") << ", length = " << aInfo
.length
);
637 catch( const parser_error
< const char*, file_iterator
<> >& rError
)
639 SAL_WARN("sdext.pdfimport.pdfparse", "parse error: " << rError
.descriptor
<< " at buffer pos " << rError
.where
- file_start
);
640 #if OSL_DEBUG_LEVEL > 1
642 unsigned int nElem
= aGrammar
.m_aObjectStack
.size();
643 for( unsigned int i
= 0; i
< nElem
; i
++ )
646 aTmp
+= OUString(typeid( *(aGrammar
.m_aObjectStack
[i
]) ).name(),
647 strlen(typeid( *(aGrammar
.m_aObjectStack
[i
]) ).name()),
648 RTL_TEXTENCODING_ASCII_US
);
650 SAL_WARN("sdext.pdfimport.pdfparse", "parse error object stack: " << aTmp
);
654 PDFEntry
* pRet
= NULL
;
655 unsigned int nEntries
= aGrammar
.m_aObjectStack
.size();
658 pRet
= aGrammar
.m_aObjectStack
.back();
659 aGrammar
.m_aObjectStack
.pop_back();
661 #if OSL_DEBUG_LEVEL > 1
662 else if( nEntries
> 1 )
664 SAL_WARN("sdext.pdfimport.pdfparse", "error got " << nEntries
<< " stack objects in parse");
665 for( unsigned int i
= 0; i
< nEntries
; i
++ )
667 SAL_WARN("sdext.pdfimport.pdfparse", typeid(*aGrammar
.m_aObjectStack
[i
]).name());
668 PDFObject
* pObj
= dynamic_cast<PDFObject
*>(aGrammar
.m_aObjectStack
[i
]);
670 SAL_WARN("sdext.pdfimport.pdfparse", " -> object " << pObj
->m_nNumber
<< " generation " << pObj
->m_nGeneration
);
672 SAL_WARN("sdext.pdfimport.pdfparse", "(type " << typeid(*aGrammar
.m_aObjectStack
[i
]).name() << ")");
685 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */